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)
'cur-line))
new-lines)
(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)))
(with-temp-buffer
(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.