Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions extensions/vi-mode/commands.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -575,14 +575,14 @@
(back-to-indentation p))
(line-start p))))))
(line-end p)
(insert-character p #\newline)
(move-to-column p column t)
(change-state 'insert)))
(change-state 'insert)
(insert-character p #\Newline)
(move-to-column p column t)))

(define-command vi-open-above () ()
(line-start (current-point))
(open-line 1)
(change-state 'insert))
(change-state 'insert)
(open-line 1))

(define-command vi-jump-back (&optional (n 1)) ("p")
(dotimes (i n)
Expand All @@ -594,8 +594,8 @@

(define-command vi-repeat (n) ("P")
(when *last-repeat-keys*
(let ((lem:*pre-command-hook* nil)
(lem:*post-command-hook* nil))
(let ((*enable-repeat-recording* nil)
(prev-state (current-state)))
(let ((keyseq (if n
(append
(map 'list (lambda (char) (lem:make-key :sym (string char)))
Expand All @@ -604,7 +604,10 @@
*last-repeat-keys*))
;; Clear the universal argument for vi-repeat
(lem/universal-argument::*argument* (lem/universal-argument::make-arg-state)))
(execute-key-sequence keyseq)))))
(execute-key-sequence keyseq)
(unless (state= prev-state (current-state))
(change-state prev-state))
(fall-within-line (current-point))))))

(define-command vi-normal () ()
(change-state 'normal))
Expand Down
9 changes: 9 additions & 0 deletions extensions/vi-mode/core.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
(:export :*enable-hook*
:*disable-hook*
:*last-repeat-keys*
:*enable-repeat-recording*
:vi-state
:vi-mode
:define-vi-state
:current-state
:state=
:change-state
:with-state
:*command-keymap*
Expand All @@ -34,6 +36,8 @@
(defvar *enable-hook* '())
(defvar *disable-hook* '())

(defvar *enable-repeat-recording* t)

(defun enable-hook ()
(run-hooks *enable-hook*))

Expand Down Expand Up @@ -123,6 +127,11 @@

(defvar *current-state* nil)

(defun state= (state1 state2)
(and (typep state1 'vi-state)
(typep state2 'vi-state)
(eq (state-name state1) (state-name state2))))

;;; vi-state methods
(defmacro define-vi-state (name direct-super-classes direct-slot-specs &rest options)
(let ((cleaned-super-classes (if (null direct-super-classes) '(vi-state) direct-super-classes)))
Expand Down
11 changes: 9 additions & 2 deletions extensions/vi-mode/tests/commands.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@
(ok (buf= #?"[1]\n2\n3\n"))
(cmd "<C-r>")
(ok (buf= #?"1: Hello[!]\n2\n3\n"))
(cmd "o4: World!<Esc>")
(cmd "o4: World!<Esc>a<Esc>")
(ok (buf= #?"1: Hello!\n4: World[!]\n2\n3\n"))
(cmd "2u")
(ok (buf= #?"[1]\n2\n3\n")))))
(ok (buf= #?"[1]\n2\n3\n")))
(with-vi-buffer (#?"[1]\n2\n3\n")
(cmd "a: Hello!<Esc>")
(ok (buf= #?"1: Hello[!]\n2\n3\n"))
(cmd "ja: World!<Esc>")
(ok (buf= #?"1: Hello!\n2: World[!]\n3\n"))
(cmd "u")
(ok (buf= #?"1: Hello!\n[2]\n3\n")))))
7 changes: 6 additions & 1 deletion extensions/vi-mode/tests/operator.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@
(cmd "2d2d")
(ok (buf= #?"[5]:mno\n6:opq\n7:rst\n8:uvw"))
(cmd "2.")
(ok (buf= #?"[7]:rst\n8:uvw")))))
(ok (buf= #?"[7]:rst\n8:uvw")))
(with-vi-buffer (#?"[f]oo\nbar\nbaz\n")
(cmd "A-fighters<Esc>")
(ok (buf= #?"foo-fighter[s]\nbar\nbaz\n"))
(cmd "j^.")
(ok (buf= #?"foo-fighters\nbar-fighter[s]\nbaz\n")))))
3 changes: 1 addition & 2 deletions extensions/vi-mode/tests/utils.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,7 @@
(defun cmd (keys)
(check-type keys string)
(diag (format nil "[cmd] ~A~%" keys))
(let ((*this-command-keys* nil)
(*input-hook* (cons (cons (lambda (event)
(let ((*input-hook* (cons (cons (lambda (event)
(push event *this-command-keys*))
0)
*input-hook*)))
Expand Down
37 changes: 31 additions & 6 deletions extensions/vi-mode/vi-mode.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
:lem-vi-mode/ex)
(:import-from :lem-vi-mode/options
:vi-option-value)
(:import-from :lem-vi-mode/commands
:vi-open-below
:vi-open-above)
(:import-from :lem-vi-mode/commands/utils
:vi-command
:vi-command-repeat)
(:import-from :alexandria
:appendf)
(:export :vi-mode
:define-vi-state
:*command-keymap*
Expand All @@ -17,14 +22,34 @@
(in-package :lem-vi-mode)

(defmethod post-command-hook ((state normal))
(let ((command (this-command)))
(when (and (typep command 'vi-command)
(eq (vi-command-repeat command) t))
(setf *last-repeat-keys* (vi-this-command-keys)))))
(when *enable-repeat-recording*
(let ((command (this-command)))
(when (and (typep command 'vi-command)
(eq (vi-command-repeat command) t))
(setf *last-repeat-keys* (vi-this-command-keys))))))

(defmethod post-command-hook ((state insert))
(when (eq :separator (lem-base::last-edit-history (current-buffer)))
(vector-pop (lem-base::buffer-edit-history (current-buffer)))))
(let ((command (this-command)))
(when *enable-repeat-recording*
(unless (or (and (typep command 'vi-command)
(eq (vi-command-repeat command) nil))
(eq (command-name (this-command)) 'vi-end-insert))
(appendf *last-repeat-keys*
(vi-this-command-keys))))
(when (and (member (command-name command)
'(self-insert
;; XXX: lem:call-command always adds a undo boundary
;; Delete the last boundary after these commands executed.
vi-open-below
vi-open-above)
:test 'eq)
(eq :separator (lem-base::last-edit-history (current-buffer))))
(vector-pop (lem-base::buffer-edit-history (current-buffer))))))

(defmethod state-enabled-hook ((state insert))
(when *enable-repeat-recording*
(setf *last-repeat-keys* nil))
(buffer-undo-boundary))

(defmethod state-disabled-hook ((state insert))
(unless (eq :separator (lem-base::last-edit-history (current-buffer)))
Expand Down
3 changes: 2 additions & 1 deletion src/input.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@
(do-command-loop (:interactive nil)
(when (null *unread-keys*)
(return))
(call-command (read-command) nil))))
(let ((*this-command-keys* nil))
(call-command (read-command) nil)))))

(defun sit-for (seconds &optional (update-window-p t) (force-update-p nil))
(when update-window-p (redraw-display force-update-p))
Expand Down
3 changes: 1 addition & 2 deletions src/interp.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@
#'editor-abort-handler)
(editor-condition
#'editor-condition-handler))
(let ((*this-command-keys* '()))
(read-command-and-call)))
(read-command-and-call))
(editor-condition (c)
(restart-case (error c)
(lem-restart:message ()
Expand Down