Fix scrolling preferences in Evil

As well as address a bug when selecting an _inclusive_ function as a
text object. Now `d a d` will delete a function and the surround
whitespace and comments.
This commit is contained in:
Howard Abrams 2024-07-02 21:53:59 -07:00
parent 8eaf1d5600
commit c047eaa18b
2 changed files with 62 additions and 32 deletions

View file

@ -44,6 +44,13 @@ Changes and settings I like introduced that were introduced in Emacs 28:
completions-detailed t)
#+end_src
Ive got preferences for how I like scrolling, and with my org files, I need a little more of the of the context, so this increases from =2= to =3=, but I really like to keep the cursor in place when I can:
#+begin_src emacs-lisp
(setq next-screen-context-lines 3
scroll-error-top-bottom t
scroll-preserve-screen-position t)
#+end_src
Emacs has some new code to display line-numbers, and the =visual= value works well with my Org files, allowing a jump to a line via ~6 j~:
#+begin_src emacs-lisp
(setq display-line-numbers-type 'visual)

View file

@ -37,18 +37,6 @@ Some advice that I followed:
- [[https://github.com/noctuid/evil-guide][Evil Guide]]
- [[https://nathantypanski.com/blog/2014-08-03-a-vim-like-emacs-config.html][A Vim-like Emacs Configuration from Nathan Typanski]]
- [[https://stackoverflow.com/questions/25542097/emacs-evil-mode-how-to-change-insert-state-to-emacs-state-automatically][Evil insert state is really Emacs?]] Real answer to that is to set [[help:evil-disable-insert-state-bindings][evil-disable-insert-state-bindings]]
My Evil configuration should be /optionally/ included, so I define this variable:
#+begin_src emacs-lisp
(defvar ha-evil-on t
"If non-nil, it means that Evil configuration has been turned on.")
#+end_src
Then code through over files (but not this one), would have something like:
#+begin_src emacs-lisp :tangle no
(when (and (boundp 'ha-evil-on) ha-evil-one)
;; ...access evil...
)
#+end_src
* Evil-Specific Keybindings
I split the configuration of Evil mode into sections. First, global settings:
#+begin_src emacs-lisp
@ -118,18 +106,10 @@ Im not a long term VI user, and I generally like /easy keys/, e.g. ~w~, have
(evil-define-key '(normal visual motion operator) 'global
"b" 'evil-backward-WORD-begin)
(evil-define-key '(normal visual motion operator) 'global
"B" 'evil-backward-word-begin)
"B" 'evil-backward-word-begin))
;; Note that evil-backward-word-end is on the `g e':
;; Not a long-term VI user, so let's Emacsify some other keybindings:
(evil-define-key '(normal visual motion operator) 'global
(kbd "C-b") 'scroll-up-command
(kbd "C-f") 'scroll-down-command
(kbd "C-p") 'previous-line
(kbd "C-n") 'next-line
;; I have better window control:
(kbd "C-w") 'sp-kill-region))
#+end_src
Testing:
- =word-subword-subword=
- =word_subword_subword=
@ -174,6 +154,33 @@ What text objects are known?
- ~c~ :: for comments
- ~u~ :: for URLs, really? Useful much?
- ~a~ :: function arguments (probably a lot like symbol, ~o~), but the ~a~ can include commas. This comes from [[https://github.com/wcsmith/evil-args][evil-args]] extension (see below).
I am not a long term VI user, and dont have much need for any of its control sequences (well, not all), so I made the following more Emacsy. Ill admit, I like ~C-v~ (and use that all the time), so I need to futz around with the scrolling:
#+begin_src emacs-lisp
(use-package evil
:config
(evil-define-key '(normal visual motion operator) 'global
(kbd "C-a") 'move-beginning-of-line
(kbd "C-e") 'move-end-of-line
;; Since C-y scrolls the window down, Shifted Y goes up:
(kbd "C-y") 'evil-scroll-line-down
(kbd "C-b") 'evil-scroll-line-up
(kbd "C-S-y") 'evil-scroll-line-up
(kbd "C-d") 'scroll-down-command
(kbd "C-S-d") 'scroll-other-window-down
(kbd "C-f") 'scroll-up-command
(kbd "C-S-f") 'scroll-other-window
(kbd "C-o") 'open-line ; matches evil's o
(kbd "C-p") 'previous-line
(kbd "C-n") 'next-line
;; I have better window control:
(kbd "C-w") 'sp-kill-region))
#+end_src
** Evil Text Object Line
Delete a line, ~d d~ is in basic VI. Since some commands use text objects, and the basic text object doesnt include lines, the [[https://github.com/emacsorphanage/evil-textobj-line][evil-textobj-line]] project adds that:
#+begin_src emacs-lisp
@ -264,6 +271,7 @@ And the keybindings:
#+end_src
** Text Object for Functions
While Emacs has the ability to recognize functions, the Evil text object does not. But text objects have both an /inner/ and /outer/ form, and what does that mean for a function? The /inner/ will be the /function itself/ and the /outer/ (like words) would be the surrounding /non-function/ stuff … in other words, the distance between the next functions.
#+begin_src emacs-lisp
(defun ha-evil-defun-range (count beg end type inclusive)
"Get minimum range of `defun` as a text object.
@ -272,16 +280,30 @@ While Emacs has the ability to recognize functions, the Evil text object does no
inclusive acquiring the areas between the surrounding defuns."
(let ((start (save-excursion
(beginning-of-defun)
(when inclusive
(beginning-of-defun)
(end-of-defun))
(point)))
(end (save-excursion
(end-of-defun count)
(when inclusive
(end-of-defun)
(beginning-of-defun))
(point))))
(when inclusive
;; Let's see if we can grab more text ...
(save-excursion
;; Don't bother if we are at the start of buffer:
(when (> start (point-min))
(goto-char start)
;; go to the end of the previous function:
(beginning-of-defun)
(end-of-defun count)
;; if we found some more text to grab, reset start:
(if (< (point) start)
(setq start (point))))
;; Same approach with the end:
(when (< end (point-max))
(goto-char end)
(end-of-defun)
(beginning-of-defun)
(if (> (point) end)
(setq end (point))))))
(list start end)))
#+end_src
@ -303,6 +325,7 @@ And the keybindings:
(define-key evil-inner-text-objects-map "d" #'ha-evil-inner-defun)
(define-key evil-outer-text-objects-map "d" #'ha-evil-a-defun)
#+end_src
Why not use ~f~? Im reserving the ~f~ for a tree-sitter version that is not always available for all modes… yet.
* Evil Extensions
** Evil Exchange
@ -414,10 +437,10 @@ Not sure what is in a register? Have it show you when you hit ~”~ or ~@~ with
:after posframe
:config
(setq evil-owl-display-method 'posframe
evil-owl-extra-posframe-args '(:width 50 :height 20 :background-color "#444")
evil-owl-extra-posframe-args
'(:width 50 :height 20 :background-color "#444")
evil-owl-max-string-length 50)
(evil-owl-mode))
#+end_src
** Evil Surround
I like both [[https://github.com/emacs-evil/evil-surround][evil-surround]] and Henrik's [[https://github.com/hlissner/evil-snipe][evil-snipe]], but they both start with ~s~, and conflict, and getting them to work together means I have to remember when does ~s~ call sniper and when it calls surround. As an original Emacs person, I am not bound by that key history, but I do need them consistent, so Im choosing the ~s~ to be /surround/.
@ -460,8 +483,8 @@ The [[https//github.com/gilbertw1/better-jumper][better-jumper project]] replace
(better-jumper-mode +1)
(with-eval-after-load 'evil-maps
(define-key evil-motion-state-map (kbd "C-o") 'better-jumper-jump-backward)
(define-key evil-motion-state-map (kbd "C-i") 'better-jumper-jump-forward)))
(define-key evil-motion-state-map (kbd "M-[") 'better-jumper-jump-backward)
(define-key evil-motion-state-map (kbd "M-]") 'better-jumper-jump-forward)))
#+end_src
* Technical Artifacts :noexport: