Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Fix 'dw' not to delete to the next line.
  • Loading branch information
fukamachi committed Aug 24, 2023
commit d45804ecd7ac6a986c69c572b96c79ec78352ebc
39 changes: 37 additions & 2 deletions extensions/vi-mode/commands.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,37 @@
(previous-line n)
(fall-within-line (current-point)))

(defun on-only-space-line-p (point)
(with-point ((p point))
(line-end p)
(skip-whitespace-backward p t)
(bolp p)))

(define-command vi-forward-word-begin (&optional (n 1)) ("p")
(dotimes (i n)
(forward-word-begin #'char-type)))
(let ((start-line (line-number-at-point (current-point))))
(dotimes (i n)
(forward-word-begin #'char-type))
;; In operator-pending mode, this motion behaves differently.
(when (operator-pending-mode-p)
(with-point ((p (current-point)))
;; Go back to the end of the previous line when the END point is in the next line.
;; For example, when the cursor is at [b],
;; foo [b]ar
;; baz
;; 'dw' deletes only the 'bar', instead of the beginning of the next word.
(skip-whitespace-backward p t)
(when (bolp p)
(line-offset p -1)
(line-end p)
(loop while (and (< start-line
(line-number-at-point p))
(on-only-space-line-p p))
do (line-offset p -1)
(line-end p))
;; Skip this line if the previous line is empty
(when (bolp p)
(character-offset p 1))
(move-point (current-point) p))))))

(define-command vi-backward-word-begin (&optional (n 1)) ("p")
(dotimes (i n)
Expand Down Expand Up @@ -229,6 +257,13 @@
(max 0
(min (1- (length (line-string (current-point)))) pos))))
(when (eq 'vi-delete (command-name (this-command)))
;; After 'dw' or 'dW', move to the first non-blank char
(when (and (this-motion-command)
(member (command-name (this-motion-command))
'(vi-forward-word-begin
vi-forward-word-begin-broad)
:test 'eq))
(skip-chars-forward (current-point) '(#\Space #\Tab)))
(fall-within-line (current-point)))))

(define-vi-operator vi-delete-line (start end type) ("<R>")
Expand Down
19 changes: 19 additions & 0 deletions extensions/vi-mode/commands/utils.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
:eolp
:goto-eol
:fall-within-line
:operator-pending-mode-p
:this-motion-command
:read-universal-argument
:*cursor-offset*
:vi-command
Expand All @@ -33,6 +35,8 @@
(in-package :lem-vi-mode/commands/utils)

(defvar *cursor-offset* -1)
(defvar *operator-pending-mode* nil)
(defvar *this-motion-command* nil)

(defun bolp (point)
"Return t if POINT is at the beginning of a line."
Expand All @@ -55,6 +59,12 @@
(when (eolp point)
(goto-eol point)))

(defun operator-pending-mode-p ()
*operator-pending-mode*)

(defun this-motion-command ()
*this-motion-command*)

(defun read-universal-argument ()
(loop :for key := (read-key)
:for char := (key-to-char key)
Expand Down Expand Up @@ -85,6 +95,14 @@

(defclass vi-operator (vi-command) ())

(defmethod execute :around (mode (command vi-operator) uarg)
(declare (ignore mode uarg))
;; XXX: This flag will be replaced by checking the current state
;; when operator-pending-state is implemented.
(let ((*operator-pending-mode* t)
(*this-motion-command* nil))
(call-next-method)))

(defvar *vi-origin-point*)

(defun parse-vi-motion-arg-list (arg-list)
Expand Down Expand Up @@ -130,6 +148,7 @@
(check-type motion (or null symbol))
(with-point ((start (current-point)))
(labels ((call-motion (command uarg)
(setf *this-motion-command* command)
(let ((*cursor-offset* 0))
(save-excursion
(ignore-errors
Expand Down
8 changes: 7 additions & 1 deletion extensions/vi-mode/tests/operator.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@
(ok (buf= #?"ghi\n[]")))
(with-vi-buffer (#?"[a]bc\ndef\nghi\njkl\n")
(cmd "1000dd")
(ok (buf= "[]")))))
(ok (buf= "[]")))
(testing "with vi-forward-word-begin"
(with-vi-buffer (#?"[a]bc\n def\n")
(cmd "dw")
(ok (buf= #?"[\n] def\n"))
(cmd "dw")
(ok (buf= #?" [d]ef\n"))))))

(deftest vi-join-line
(with-fake-interface ()
Expand Down