branch: elpa/aidermacs commit 5c77085c4bec41c56f2b4446b2b2b446db72b6f1 Author: Mingde (Matthew) Zeng (aider) <matthew...@posteo.net> Commit: Mingde (Matthew) Zeng <matthew...@posteo.net>
refactor: Move syntax highlighting code to aidermacs-backend-comint.el refactor: Rename syntax highlighting variables for clarity --- aidermacs-backend-comint.el | 108 ++++++++++++++++++++++++++++++-------------- aidermacs.el | 37 --------------- 2 files changed, 75 insertions(+), 70 deletions(-) diff --git a/aidermacs-backend-comint.el b/aidermacs-backend-comint.el index c03e298129..7aadc6f0bd 100644 --- a/aidermacs-backend-comint.el +++ b/aidermacs-backend-comint.el @@ -7,6 +7,13 @@ (require 'comint) +(defconst aidermacs-search-marker "<<<<<<< SEARCH") +(defconst aidermacs-diff-marker "=======") +(defconst aidermacs-replace-marker ">>>>>>> REPLACE") +(defconst aidermacs-fence-marker "```") +(defvar aidermacs-block-re + (format "^\\(?:\\(?1:%s\\|%s\\)\\|\\(?1:%s\\).+\\)$" aidermacs-search-marker aidermacs-diff-marker aidermacs-fence-marker)) + (defcustom aidermacs-comint-multiline-newline-key "S-<return>" "Key binding for `comint-accumulate' in Aidermacs buffers. This allows for multi-line input without sending the command." @@ -40,40 +47,51 @@ This allows for multi-line input without sending the command." ("^=======$" 0 'aidermacs-search-replace-block t)) "Font lock keywords for aidermacs buffer.") -(defvar-local aidermacs--font-lock-buffer nil - "Temporary buffer for fontification.") +;; Buffer-local variables for syntax highlighting state +(defvar-local aidermacs--syntax-block-delimiter nil + "The expected delimiter (diff/replace/fence) for the current syntax block.") -(defun aidermacs--comint-output-filter (output) - "Filter function for comint OUTPUT." - (when (not (string-empty-p output)) - (aidermacs--store-output output))) +(defvar-local aidermacs--syntax-block-start-pos nil + "The starting position of the current syntax block.") + +(defvar-local aidermacs--syntax-block-end-pos nil + "The end position of the current syntax block.") + +(defvar-local aidermacs--syntax-last-output-pos nil + "Position tracker for incremental syntax highlighting.") + +(defvar-local aidermacs--syntax-major-mode nil + "The major mode used for syntax highlighting the current block.") + +(defvar-local aidermacs--syntax-work-buffer nil + "Temporary buffer used for syntax highlighting operations.") (defun aidermacs-reset-font-lock-state () "Reset font lock state to default for processing another a new src block." - (unless (equal aidermacs--block-end-marker aidermacs-diff-marker) + (unless (equal aidermacs--syntax-block-delimiter aidermacs-diff-marker) ;; if we are processing the other half of a SEARCH/REPLACE block, we need to ;; keep the mode - (setq aidermacs--block-mode nil)) - (setq aidermacs--block-end-marker nil - aidermacs--last-output-start nil - aidermacs--block-start nil - aidermacs--block-end nil)) + (setq aidermacs--syntax-major-mode nil)) + (setq aidermacs--syntax-block-delimiter nil + aidermacs--syntax-last-output-pos nil + aidermacs--syntax-block-start-pos nil + aidermacs--syntax-block-end-pos nil)) (defun aidermacs-fontify-blocks (_output) "Fontify search/replace blocks in comint output." (save-excursion - (goto-char (or aidermacs--last-output-start + (goto-char (or aidermacs--syntax-last-output-pos comint-last-output-start)) (beginning-of-line) ;; Continue processing existing block if we're in one - (when aidermacs--block-start + (when aidermacs--syntax-block-start-pos (aidermacs--fontify-block)) - (setq aidermacs--last-output-start nil) + (setq aidermacs--syntax-last-output-pos nil) ;; Look for new blocks if we're not in one - (while (and (null aidermacs--block-start) - (null aidermacs--last-output-start) + (while (and (null aidermacs--syntax-block-start-pos) + (null aidermacs--syntax-last-output-pos) (re-search-forward aidermacs-block-re nil t)) ;; If it is code fence marker, we need to check if there is a SEARCH marker @@ -89,22 +107,22 @@ This allows for multi-line input without sending the command." ((string-prefix-p line-text aidermacs-search-marker) ;; Next line *might* be a SEARCH marker. Don't process more of ;; the buffer until we know for sure - (setq aidermacs--last-output-start comint-last-output-start))))) + (setq aidermacs--syntax-last-output-pos comint-last-output-start))))) - (unless aidermacs--last-output-start + (unless aidermacs--syntax-last-output-pos ;; Set up new block state - (setq aidermacs--block-end-marker + (setq aidermacs--syntax-block-delimiter (pcase (match-string 1) ((pred (equal aidermacs-search-marker)) aidermacs-diff-marker) ((pred (equal aidermacs-diff-marker)) aidermacs-replace-marker) ((pred (equal aidermacs-fence-marker)) aidermacs-fence-marker)) - aidermacs--block-start (line-end-position) - aidermacs--block-end (line-end-position) - aidermacs--block-mode (aidermacs--guess-major-mode)) + aidermacs--syntax-block-start-pos (line-end-position) + aidermacs--syntax-block-end-pos (line-end-position) + aidermacs--syntax-major-mode (aidermacs--guess-major-mode)) ;; Set the major-mode of the font lock buffer - (let ((mode aidermacs--block-mode)) - (with-current-buffer aidermacs--font-lock-buffer + (let ((mode aidermacs--syntax-major-mode)) + (with-current-buffer aidermacs--syntax-work-buffer (erase-buffer) (unless (eq mode major-mode) (condition-case e @@ -144,7 +162,7 @@ This allows for multi-line input without sending the command." fontified) ;; Insert the new text and get the fontified result - (with-current-buffer aidermacs--font-lock-buffer + (with-current-buffer aidermacs--syntax-work-buffer (goto-char (point-max)) (insert new-content) (with-demoted-errors "aidermacs block font lock error: %s" @@ -153,10 +171,10 @@ This allows for multi-line input without sending the command." (setq fontified (buffer-string))) ;; Apply the faces to the buffer - (remove-overlays aidermacs--block-start aidermacs--block-end) - (while (< pos aidermacs--block-end) + (remove-overlays aidermacs--syntax-block-start-pos aidermacs--syntax-block-end-pos) + (while (< pos aidermacs--syntax-block-end-pos) (let* ((next-font-pos (or (next-property-change font-pos fontified) (length fontified))) - (next-pos (+ aidermacs--block-start next-font-pos)) + (next-pos (+ aidermacs--syntax-block-start-pos next-font-pos)) (face (get-text-property font-pos 'face fontified))) (ansi-color-apply-overlay-face pos next-pos face) (setq pos next-pos @@ -164,7 +182,7 @@ This allows for multi-line input without sending the command." ;; If we found the end marker, finalize the block (when end-of-block-p - (when (equal aidermacs--block-end-marker aidermacs-diff-marker) + (when (equal aidermacs--syntax-block-delimiter aidermacs-diff-marker) ;; we will need to process the other half of the SEARCH/REPLACE block. ;; Backup so it will get matched (beginning-of-line)) @@ -189,9 +207,32 @@ This allows for multi-line input without sending the command." (when (re-search-backward "^\\([^[:space:]]+\\)" (line-beginning-position -3) t) (let ((file (match-string 1))) (cdr (cl-assoc-if (lambda (re) (string-match re file)) auto-mode-alist)))) - aidermacs--block-mode + aidermacs--syntax-major-mode 'fundamental-mode))) +(defun aidermacs-kill-buffer () + "Clean-up fontify buffer." + (when (bufferp aidermacs--syntax-work-buffer) + (kill-buffer aidermacs--syntax-work-buffer))) + +(defvar-local aidermacs--comint-output-temp "" + "Temporary output variable storing the output log.") + +(defun aidermacs-input-sender (proc string) + "Reset font-lock state before executing a command." + (aidermacs-reset-font-lock-state) + (comint-simple-send proc (aidermacs--process-message-if-multi-line string))) + +(defun aidermacs--comint-output-filter (output) + "Accumulate OUTPUT until a prompt is detected, then store it." + (unless (string-empty-p output) + (setq aidermacs--comint-output-temp + (concat aidermacs--comint-output-temp output)) + ;; Check if the output contains a prompt + (when (string-match-p "\n[^[:space:]]*>[[:space:]]$" aidermacs--comint-output-temp) + (aidermacs--store-output aidermacs--comint-output-temp) + (setq aidermacs--comint-output-temp "")))) + (defun aidermacs-run-aidermacs-comint (program args buffer-name) "Create a comint-based buffer and run aidermacs PROGRAM with ARGS in BUFFER-NAME." (let ((comint-terminfo-terminal "dumb")) @@ -200,8 +241,8 @@ This allows for multi-line input without sending the command." (with-current-buffer buffer-name (comint-mode) (setq-local comint-input-sender 'aidermacs-input-sender) - (setq aidermacs--font-lock-buffer - (get-buffer-create (concat " *aidermacs-fontify" buffer-name))) + (setq aidermacs--syntax-work-buffer + (get-buffer-create (concat " *aidermacs-syntax" buffer-name))) (add-hook 'kill-buffer-hook #'aidermacs-kill-buffer nil t) (add-hook 'comint-output-filter-functions #'aidermacs-fontify-blocks 100 t) (add-hook 'comint-output-filter-functions #'aidermacs--comint-output-filter) @@ -221,6 +262,7 @@ If SWITCH-TO-BUFFER is non-nil, switch to the buffer after sending." (setq aidermacs--last-command command aidermacs--current-output nil) (goto-char (process-mark process)) + (aidermacs-reset-font-lock-state) (insert (propertize command 'face 'aidermacs-command-text 'font-lock-face 'aidermacs-command-text diff --git a/aidermacs.el b/aidermacs.el index 240dfb2572..91f2461053 100644 --- a/aidermacs.el +++ b/aidermacs.el @@ -209,49 +209,12 @@ With the universal argument, prompt to edit aidermacs-args before running." Dispatches to the appropriate backend." (if-let ((aidermacs-buffer (get-buffer (aidermacs-buffer-name)))) (let ((processed-command (aidermacs--process-message-if-multi-line command))) - (aidermacs-reset-font-lock-state) (aidermacs--send-command-backend aidermacs-buffer processed-command switch-to-buffer) (when switch-to-buffer (aidermacs-switch-to-buffer)) (sleep-for 0.2)) (message "Buffer %s does not exist. Please start aidermacs with 'M-x aidermacs-run-aidermacs'." aidermacs-buffer-name))) -(defun aidermacs-kill-buffer () - "Clean-up fontify buffer." - (when (bufferp aidermacs--font-lock-buffer) - (kill-buffer aidermacs--font-lock-buffer))) - -(defun aidermacs-input-sender (proc string) - "Reset font-lock state before executing a command." - (aidermacs-reset-font-lock-state) - (comint-simple-send proc (aidermacs--process-message-if-multi-line string))) - -;; Buffer-local variables for block processing state -(defvar-local aidermacs--block-end-marker nil - "The end marker for the current block being processed.") - -(defvar-local aidermacs--block-start nil - "The starting position of the current block being processed.") - -(defvar-local aidermacs--block-end nil - "The end position of the current block being processed.") - -(defvar-local aidermacs--last-output-start nil - "an alternative to `comint-last-output-start' used in aidermacs.") - -(defvar-local aidermacs--block-mode nil - "The major mode for the current block being processed.") - -(defvar-local aidermacs--font-lock-buffer nil - "Temporary buffer for fontification.") - -(defconst aidermacs-search-marker "<<<<<<< SEARCH") -(defconst aidermacs-diff-marker "=======") -(defconst aidermacs-replace-marker ">>>>>>> REPLACE") -(defconst aidermacs-fence-marker "```") -(defvar aidermacs-block-re - (format "^\\(?:\\(?1:%s\\|%s\\)\\|\\(?1:%s\\).+\\)$" aidermacs-search-marker aidermacs-diff-marker aidermacs-fence-marker)) - ;; Function to switch to the aidermacs buffer ;;;###autoload