Function: analyze-text-conversion

analyze-text-conversion is an interactive and byte-compiled function defined in simple.el.gz.

Signature

(analyze-text-conversion)

Documentation

Analyze the results of the previous text conversion event.

For each insertion:

  - Look for the insertion of a string starting or ending with a
    character inside auto-fill-chars, and fill the text around
    it if auto-fill-mode is enabled.

  - Look for the insertion of a new line, and cause automatic
    line breaking of the previous line when auto-fill-mode is
    enabled.

  - Look for the deletion of a single electric pair character,
    and delete the adjacent pair if
    electric-pair-delete-adjacent-pairs.

  - Run post-self-insert-hook for the last character of
    any inserted text so that modes such as electric-pair-mode(var)/electric-pair-mode(fun)
    can work.

  - Run post-text-conversion-hook with last-command-event set
    to the last character of any inserted text to finish up.

Finally, amalgamate recent changes to the undo list with previous ones, unless a new line has been inserted or auto-fill has taken place. If undo information is being recorded, make sure undo-auto-current-boundary-timer will run within the next 5 seconds.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/simple.el.gz
(defun analyze-text-conversion ()
  "Analyze the results of the previous text conversion event.

For each insertion:

  - Look for the insertion of a string starting or ending with a
    character inside `auto-fill-chars', and fill the text around
    it if `auto-fill-mode' is enabled.

  - Look for the insertion of a new line, and cause automatic
    line breaking of the previous line when `auto-fill-mode' is
    enabled.

  - Look for the deletion of a single electric pair character,
    and delete the adjacent pair if
    `electric-pair-delete-adjacent-pairs'.

  - Run `post-self-insert-hook' for the last character of
    any inserted text so that modes such as `electric-pair-mode'
    can work.

  - Run `post-text-conversion-hook' with `last-command-event' set
    to the last character of any inserted text to finish up.

Finally, amalgamate recent changes to the undo list with previous
ones, unless a new line has been inserted or auto-fill has taken
place.  If undo information is being recorded, make sure
`undo-auto-current-boundary-timer' will run within the next 5
seconds."
  (interactive)
  ;; One important consideration to bear in mind when adjusting this
  ;; code is to _never_ move point in reaction to an edit so long as
  ;; the additional processing undertaken by this function does not
  ;; also edit the buffer text.
  (let ((any-nonephemeral nil)
        point-moved)
    ;; The list must be processed in reverse.
    (dolist (edit (reverse text-conversion-edits))
      ;; Filter out ephemeral edits and deletions after point.  Here, we
      ;; are only interested in insertions or deletions whose contents
      ;; can be identified.
      (when (stringp (nth 3 edit))
        (with-current-buffer (car edit)
          ;; Record that the point hasn't been moved by the execution
          ;; of a post command or text conversion hook.
          (setq point-moved nil)
          (if (not (eq (nth 1 edit) (nth 2 edit)))
              ;; Process this insertion.  (nth 3 edit) is the text which
              ;; was inserted.
              (let* ((inserted (nth 3 edit))
                     ;; Get the first and last characters.
                     (start (aref inserted 0))
                     (end (aref inserted (1- (length inserted))))
                     ;; Figure out whether or not to auto-fill.
                     (auto-fill-p (or (aref auto-fill-chars start)
                                      (aref auto-fill-chars end)))
                     ;; Figure out whether or not a newline was inserted.
                     (newline-p (string-search "\n" inserted))
                     ;; Save the current undo list to figure out
                     ;; whether or not auto-fill has actually taken
                     ;; place.
                     (old-undo-list buffer-undo-list)
                     ;; Save the point position to return it there
                     ;; later.
                     (old-point (point)))
                (save-excursion
                  (if (and auto-fill-function newline-p)
                      (progn (goto-char (nth 2 edit))
                             (previous-logical-line)
                             (funcall auto-fill-function)
                             (setq old-point (point)))
                    (when (and auto-fill-function auto-fill-p)
                      (goto-char (nth 2 edit))
                      (funcall auto-fill-function)
                      (setq old-point (point))))
                  ;; Record whether or not this edit should result in
                  ;; an undo boundary being added.
                  (setq any-nonephemeral
                        (or any-nonephemeral newline-p
                            ;; See if auto-fill has taken place by
                            ;; comparing the current undo list with
                            ;; the saved head.
                            (not (eq old-undo-list
                                     buffer-undo-list)))))
                (goto-char (nth 2 edit))
                (let ((last-command-event end)
                      (point (point)))
                  (unless (run-hook-with-args-until-success
                           'post-text-conversion-hook)
                    (run-hooks 'post-self-insert-hook))
                  (when (not (eq (point) point))
                    (setq point-moved t)))
                ;; If post-self-insert-hook doesn't move the point,
                ;; restore it to its previous location.  Generally,
                ;; the call to goto-char upon processing the last edit
                ;; recorded text-conversion-edit will see to this, but
                ;; if the input method sets point expressly, no edit
                ;; will be recorded, and point will wind up away from
                ;; where the input method believes it is.
                (unless point-moved
                  (goto-char old-point)))
            ;; Process this deletion before point.  (nth 2 edit) is the
            ;; text which was deleted.  Input methods typically prefer
            ;; to edit words instead of deleting characters off their
            ;; ends, but they seem to always send proper requests for
            ;; deletion for punctuation.
            (when (and (boundp 'electric-pair-delete-adjacent-pairs)
                       (symbol-value 'electric-pair-delete-adjacent-pairs)
                       ;; Make sure elec-pair is loaded.
                       (fboundp 'electric-pair-analyze-conversion)
                       ;; Only do this if only a single edit happened.
                       text-conversion-edits)
              (save-excursion
                (goto-char (nth 2 edit))
                (electric-pair-analyze-conversion (nth 3 edit))))))))
    ;; If all edits were ephemeral, make this an amalgamating command.
    ;; Then, make sure that an undo boundary is placed within the next
    ;; five seconds.
    (unless any-nonephemeral
      (undo-auto-amalgamate)
      (let ((timer undo-auto-current-boundary-timer))
        (if timer
            ;; The timer is already running.  See if it's due to expire
            ;; within the next five seconds.
            (let ((time (timer--time timer)))
              (unless (<= (time-convert (time-subtract time nil)
                                        'integer)
                          5)
                ;; It's not, so make it run in 5 seconds.
                (timer-set-time undo-auto-current-boundary-timer
                                (time-add nil 5))))
          ;; Otherwise, start it for five seconds from now.
          (setq undo-auto-current-boundary-timer
                (run-at-time 5 nil #'undo-auto--boundary-timer)))))))