From fec79106d2546c268849f86ae1f8d6d27c5e7f28 Mon Sep 17 00:00:00 2001 From: John Lorentzson Date: Thu, 31 Jul 2025 14:35:55 +0200 Subject: [PATCH] Rewrite forward and backward commands, they now behave like Emacs's --- editor/editor.lisp | 88 +++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/editor/editor.lisp b/editor/editor.lisp index 3625166..be53032 100644 --- a/editor/editor.lisp +++ b/editor/editor.lisp @@ -787,51 +787,59 @@ Additionally ensures correct line numbers on the way, as a bonus." (com-end-of-line)))) (update-buffer-cursor buffer))) +(defun word-boundary-p (char) + (not (alphanumericp char))) + (defun com-forward-word () (with-editor-accessors *editor* (:current-buffer buffer - :current-line line - :current-column column) - (loop :for char := (char (line-content line) column) - :do (incf column) - :when (>= column (line-length line)) - :do (if (null (next-line line)) - (progn - (feep) - (return)) - (setf column 0 - line (next-line line))) - :until (or (zerop column) - (null line) - (char= char #\Space))) - (update-buffer-cursor buffer))) + :current-line cursor-line + :current-column cursor-column) + (let ((found-word-p nil)) + (block :search + (do-buffer (line column char :start-line cursor-line + :start-column cursor-column) + buffer + (cond ((and found-word-p (word-boundary-p char)) + (setf cursor-line line + cursor-column column) + (update-buffer-cursor buffer) + (return-from :search)) + ((and (or found-word-p (alphanumericp char)) + (= column (1- (line-length line)))) + (setf cursor-line line + cursor-column (1+ column)) + (update-buffer-cursor buffer) + (return-from :search)) + ((alphanumericp char) + (setf found-word-p t)))) + ;; Failure case, nothing found + (feep))))) (defun com-backward-word () (with-editor-accessors *editor* (:current-buffer buffer - :current-line line - :current-column column) - (when (zerop column) - (if (null (prev-line line)) - (progn - (feep) - (return-from com-backward-word)) - (setf line (prev-line line) - column (line-length line)))) - (loop :with donep := nil - :do (decf column) - :when (minusp column) - :do (if (null (prev-line line)) - (progn - (feep) - (setf column 0) - (return)) - (setf column (1- (line-length line)) - line (prev-line line) - donep t)) - :until (or donep - (zerop column) - (null line) - (char= (char (line-content line) (1- column)) #\Space))) - (update-buffer-cursor buffer))) + :current-line cursor-line + :current-column cursor-column) + (let ((found-word-p nil)) + (block :search + (do-buffer (line column char :start-line cursor-line + :start-column (1- cursor-column) + :direction :backward) + buffer + (cond ((and found-word-p (word-boundary-p char)) + (setf cursor-line line + cursor-column (1+ column)) + (update-buffer-cursor buffer) + (return-from :search)) + ((and (or found-word-p (alphanumericp char)) + (zerop column)) + (setf cursor-line line + cursor-column column) + (update-buffer-cursor buffer) + (return-from :search)) + ((alphanumericp char) + (setf found-word-p t)))) + ;; Failure case, nothing found + (feep))))) (defun com-next-page () (with-editor-accessors *editor* (:current-line line