I have function that processes text and returns it in altered state. Result of the processing is a property list with following properties of interest:

  • :success - t if processing finished correctly
  • :text - complete changed text
  • :changedLines: list of changed lines as 2 element vectors [number-of-line line-text] (numbers are zero-based)
  • :cursorX - position of cursor on the current line
  • :error - description of the problem in case processing failed to succeed

This is a final version of the code:

(defun parinfer-mode--insert-result (result)
  "Put results of running parinfer in current buffer
If cursor is right after a newline and next character is a closing curly brace, result is ignored
All lines that were changed are replaced, then cursor is set toa new position"
  (let ((inhibit-modification-hooks t))
    (cl-macrolet ((-char-before (point) `(or (char-before ,point) -1))
                  (-char-after (point) `(or (char-after ,point) -1))
                  (sv (arg) `(symbol-value ,arg)))
      (cl-labels ((replace-line (index new-line posvar)
                                (forward-line (- index (sv posvar)))
                                (let ((beg (point))
                                      (end (progn (move-end-of-line 1) (point))))
                                  (insert new-line)
                                  (delete-region beg end))
                                (set posvar index)))
        (if (plist-get result :success)
            (if (not (and (= (-char-before (point)) 10)
                          (= (-char-after (point)) 41)))
                (let* ((old-line (line-number-at-pos))
                       (new-lines (plist-get result :changedLines))
                       (new-line-point (plist-get result :cursorX))
                       (cur-line old-line))
                  (mapc (lambda (elem)
                          (replace-line (1+ (aref elem 0))
                                        (aref elem 1)
                  (forward-line (- old-line cur-line))
                  (forward-char new-line-point)))
        (message "Parinfer did not succeed: %s" (plist-get result :error)))))))

This is previous version of the code:

(defun parinfer-mode--insert-result (result)
  (let ((inhibit-modification-hooks t))
    (cl-macrolet ((-char-before (point) `(or (char-before ,point) -1))
                  (-char-after (point) `(or (char-after ,point) -1)))
      (if (plist-get result :success)
          (if (not (and (= (-char-before (point)) 10)
                        (= (-char-after (point)) 41)))
              (let ((old-buffer (current-buffer))
                    (old-point (point)))
                  (insert (plist-get result :text))
                  (copy-to-buffer old-buffer (point-min) (point-max)))
                (goto-char old-point)))
        (message "Parinfer did not succeed: %s" (plist-get result :error))))))

I am having doubts first approach is better then second, because it has longer and harder-to-understand code. Also, i am not clear on whether replacing code line-by-line is actually faster then switching buffer contents.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.