diff options
| -rw-r--r-- | evil-commands.el | 64 | ||||
| -rw-r--r-- | evil-integration.el | 32 | ||||
| -rw-r--r-- | evil-macros.el | 2 | ||||
| -rw-r--r-- | evil-states.el | 4 | ||||
| -rw-r--r-- | evil-types.el | 30 | ||||
| -rw-r--r-- | evil-vars.el | 17 |
6 files changed, 115 insertions, 34 deletions
diff --git a/evil-commands.el b/evil-commands.el index 7d87d6b..6efa2cd 100644 --- a/evil-commands.el +++ b/evil-commands.el @@ -162,6 +162,18 @@ of the line or the buffer; just return nil." (evil-line-move (1- (or count 1))) ((beginning-of-buffer end-of-buffer))))) +(evil-define-motion evil-line-or-visual-line (count) + "Move COUNT - 1 lines down." + :type screen-line + (let ((line-move-visual (and evil-respect-visual-line-mode + visual-line-mode))) + ;; Catch bob and eob errors. These are caused when not moving + ;; point starting in the first or last line, respectively. In this + ;; case the current line should be selected. + (condition-case err + (evil-line-move (1- (or count 1))) + ((beginning-of-buffer end-of-buffer))))) + (evil-define-motion evil-beginning-of-line () "Move the cursor to the beginning of the current line." :type exclusive @@ -196,6 +208,18 @@ If COUNT is given, move COUNT - 1 screen lines downward first." (end-of-visual-line count) (end-of-line count))) +(evil-define-motion evil-end-of-line-or-visual-line (count) + "Move the cursor to the last character of the current screen +line if `visual-line-mode' is active and +`evil-respect-visual-line-mode' is non-nil. If COUNT is given, +move COUNT - 1 screen lines downward first." + :type inclusive + (if (and (fboundp 'end-of-visual-line) + evil-respect-visual-line-mode + visual-line-mode) + (end-of-visual-line count) + (evil-end-of-line count))) + (evil-define-motion evil-middle-of-visual-line () "Move the cursor to the middle of the current visual line." :type exclusive @@ -1344,12 +1368,16 @@ or line COUNT to the top of the window." (evil-define-operator evil-yank-line (beg end type register) "Saves whole lines into the kill-ring." - :motion evil-line + :motion evil-line-or-visual-line :move-point nil (interactive "<R><x>") (when (evil-visual-state-p) - (unless (memq type '(line block)) - (let ((range (evil-expand beg end 'line))) + (unless (memq type '(line block screen-line)) + (let ((range (evil-expand beg end + (if (and evil-respect-visual-line-mode + visual-line-mode) + 'screen-line + 'line)))) (setq beg (evil-range-beginning range) end (evil-range-end range) type (evil-type range)))) @@ -1391,10 +1419,20 @@ Save in REGISTER or in the kill-ring with YANK-HANDLER." (interactive "<R><x>") ;; act linewise in Visual state (let* ((beg (or beg (point))) - (end (or end beg))) + (end (or end beg)) + (visual-line-mode (and evil-respect-visual-line-mode + visual-line-mode)) + (line-end (if visual-line-mode + (save-excursion + (end-of-visual-line) + (point)) + (line-end-position)))) (when (evil-visual-state-p) - (unless (memq type '(line block)) - (let ((range (evil-expand beg end 'line))) + (unless (memq type '(line screen-line block)) + (let ((range (evil-expand beg end + (if visual-line-mode + 'screen-line + 'line)))) (setq beg (evil-range-beginning range) end (evil-range-end range) type (evil-type range)))) @@ -1408,15 +1446,15 @@ Save in REGISTER or in the kill-ring with YANK-HANDLER." (let ((temporary-goal-column most-positive-fixnum) (last-command 'next-line)) (evil-delete beg end 'block register yank-handler))) - ((eq type 'line) + ((memq type '(line screen-line)) (evil-delete beg end type register yank-handler)) (t - (evil-delete beg (line-end-position) type register yank-handler))))) + (evil-delete beg line-end type register yank-handler))))) (evil-define-operator evil-delete-whole-line (beg end type register yank-handler) "Delete whole line." - :motion evil-line + :motion evil-line-or-visual-line (interactive "<R><x>") (evil-delete beg end type register yank-handler)) @@ -1515,20 +1553,20 @@ of the block." (evil-define-operator evil-change-line (beg end type register yank-handler) "Change to end of line." - :motion evil-end-of-line + :motion evil-end-of-line-or-visual-line (interactive "<R><x><y>") (evil-change beg end type register yank-handler #'evil-delete-line)) (evil-define-operator evil-change-whole-line (beg end type register yank-handler) "Change whole line." - :motion evil-line + :motion evil-line-or-visual-line (interactive "<R><x>") (evil-change beg end type register yank-handler #'evil-delete-whole-line)) (evil-define-command evil-copy (beg end address) "Copy lines in BEG END below line given by ADDRESS." - :motion evil-line + :motion evil-line-or-visual-line (interactive "<r><addr>") (goto-char (point-min)) (forward-line address) @@ -1543,7 +1581,7 @@ of the block." (evil-define-command evil-move (beg end address) "Move lines in BEG END below line given by ADDRESS." - :motion evil-line + :motion evil-line-or-visual-line (interactive "<r><addr>") (goto-char (point-min)) (forward-line address) diff --git a/evil-integration.el b/evil-integration.el index bab8bde..50eff30 100644 --- a/evil-integration.el +++ b/evil-integration.el @@ -490,13 +490,31 @@ Based on `evil-enclose-ace-jump-for-motion'." ;; visual-line-mode integration (when evil-respect-visual-line-mode - (let ((swaps '((evil-next-line . evil-next-visual-line) - (evil-previous-line . evil-previous-visual-line) - (evil-beginning-of-line . evil-beginning-of-visual-line) - (evil-end-of-line . evil-end-of-visual-line)))) - (dolist (swap swaps) - (define-key visual-line-mode-map (vector 'remap (car swap)) (cdr swap)) - (define-key visual-line-mode-map (vector 'remap (cdr swap)) (car swap))))) + (evil-define-command evil-digit-argument-or-beginning-of-visual-line () + :digit-argument-redirection evil-beginning-of-visual-line + :keep-visual t + :repeat nil + (interactive) + (cond + (current-prefix-arg + (setq this-command #'digit-argument) + (call-interactively #'digit-argument)) + (t + (let ((target (or (command-remapping #'evil-beginning-of-visual-line) + #'evil-beginning-of-visual-line))) + (setq this-command 'evil-beginning-of-visual-line) + (call-interactively 'evil-beginning-of-visual-line))))) + + (evil-define-minor-mode-key 'motion 'visual-line-mode + "j" 'evil-next-visual-line + "gj" 'evil-next-line + "k" 'evil-previous-visual-line + "gk" 'evil-previous-line + "0" 'evil-digit-argument-or-evil-beginning-of-visual-line + "g0" 'evil-beginning-of-line + "$" 'evil-end-of-visual-line + "g$" 'evil-end-of-line + "V" 'evil-visual-screen-line)) ;;; abbrev.el (when evil-want-abbrev-expand-on-insert-exit diff --git a/evil-macros.el b/evil-macros.el index b820545..3af95d4 100644 --- a/evil-macros.el +++ b/evil-macros.el @@ -557,7 +557,7 @@ RETURN-TYPE is non-nil." (setq keys (listify-key-sequence keys)) (dotimes (var (length keys)) (define-key evil-operator-shortcut-map - (vconcat (nthcdr var keys)) 'evil-line))) + (vconcat (nthcdr var keys)) 'evil-line-or-visual-line))) ;; read motion from keyboard (setq command (evil-read-motion motion) motion (nth 0 command) diff --git a/evil-states.el b/evil-states.el index 8ffc1d6..7d029b3 100644 --- a/evil-states.el +++ b/evil-states.el @@ -258,6 +258,10 @@ the selection is enabled. "Linewise selection." :message "-- VISUAL LINE --") +(evil-define-visual-selection screen-line + "Linewise selection in `visual-line-mode'." + :message "-- SCREEN LINE --") + (evil-define-visual-selection block "Blockwise selection." :message "-- VISUAL BLOCK --" diff --git a/evil-types.el b/evil-types.el index 2c6b4f2..1e257ef 100644 --- a/evil-types.el +++ b/evil-types.el @@ -141,6 +141,36 @@ line and `evil-want-visual-char-semi-exclusive', then: (format "%s line%s" height (if (= height 1) "" "s"))))) +(evil-define-type screen-line + "Include whole lines, being aware of `visual-line-mode' +when `evil-respect-visual-line-mode' is non-nil." + :one-to-one nil + :expand (lambda (beg end) + (if (or (not evil-respect-visual-line-mode) + (not visual-line-mode)) + (evil-line-expand beg end) + (evil-range + (progn + (goto-char beg) + (save-excursion + (beginning-of-visual-line))) + (progn + (goto-char end) + (save-excursion + ;; `beginning-of-visual-line' reverts to the beginning of the + ;; last visual line if the end of the last line is the end of + ;; the buffer. This would prevent selecting the last screen + ;; line. + (if (= (line-beginning-position 2) (point-max)) + (point-max) + (beginning-of-visual-line 2))))))) + :contract (lambda (beg end) + (evil-range beg (max beg (1- end)))) + :string (lambda (beg end) + (let ((height (count-screen-lines beg end))) + (format "%s screen line%s" height + (if (= height 1) "" "s"))))) + (evil-define-type block "Like `inclusive', but for rectangles: the last column is included." diff --git a/evil-vars.el b/evil-vars.el index d95450c..d10a4a8 100644 --- a/evil-vars.el +++ b/evil-vars.el @@ -218,18 +218,7 @@ a line." (defcustom evil-respect-visual-line-mode nil "Whether movement commands respect `visual-line-mode'. -This variable must be set before Evil is loaded. When -`visual-line-mode' is active, the following commands are swapped - -`evil-next-line' <-> `evil-next-visual-line' -`evil-previous-line' <-> `evil-previous-visual-line' -`evil-beginning-of-line' <-> `evil-beginning-of-visual-line' -`evil-end-of-line' <-> `evil-end-of-visual-line' - -The commands `evil-insert-line', `evil-append-line', -`evil-find-char', `evil-find-char-backward', `evil-find-char-to' -and `evil-find-char-to-backward' are also made aware of visual -lines." +This variable must be set before Evil is loaded." :type 'boolean :group 'evil) @@ -506,7 +495,9 @@ The default behavior is to yank the whole line." :set #'(lambda (sym value) (evil-add-command-properties 'evil-yank-line - :motion (if value 'evil-end-of-line 'evil-line)))) + :motion (if value + 'evil-end-of-line-or-visual-line + 'evil-line-or-visual-line)))) (defcustom evil-disable-insert-state-bindings nil "Whether insert state bindings should be used. Excludes |
