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) completions-detailed t)
#+end_src #+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~: 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 #+begin_src emacs-lisp
(setq display-line-numbers-type 'visual) (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://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://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]] - [[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 * Evil-Specific Keybindings
I split the configuration of Evil mode into sections. First, global settings: I split the configuration of Evil mode into sections. First, global settings:
#+begin_src emacs-lisp #+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 (evil-define-key '(normal visual motion operator) 'global
"b" 'evil-backward-WORD-begin) "b" 'evil-backward-WORD-begin)
(evil-define-key '(normal visual motion operator) 'global (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': ;; 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 #+end_src
Testing: Testing:
- =word-subword-subword= - =word-subword-subword=
- =word_subword_subword= - =word_subword_subword=
@ -174,6 +154,33 @@ What text objects are known?
- ~c~ :: for comments - ~c~ :: for comments
- ~u~ :: for URLs, really? Useful much? - ~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). - ~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 ** 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: 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 #+begin_src emacs-lisp
@ -264,6 +271,7 @@ And the keybindings:
#+end_src #+end_src
** Text Object for Functions ** 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. 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 #+begin_src emacs-lisp
(defun ha-evil-defun-range (count beg end type inclusive) (defun ha-evil-defun-range (count beg end type inclusive)
"Get minimum range of `defun` as a text object. "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." inclusive acquiring the areas between the surrounding defuns."
(let ((start (save-excursion (let ((start (save-excursion
(beginning-of-defun) (beginning-of-defun)
(when inclusive
(beginning-of-defun)
(end-of-defun))
(point))) (point)))
(end (save-excursion (end (save-excursion
(end-of-defun count) (end-of-defun count)
(when inclusive
(end-of-defun)
(beginning-of-defun))
(point)))) (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))) (list start end)))
#+end_src #+end_src
@ -303,6 +325,7 @@ And the keybindings:
(define-key evil-inner-text-objects-map "d" #'ha-evil-inner-defun) (define-key evil-inner-text-objects-map "d" #'ha-evil-inner-defun)
(define-key evil-outer-text-objects-map "d" #'ha-evil-a-defun) (define-key evil-outer-text-objects-map "d" #'ha-evil-a-defun)
#+end_src #+end_src
Why not use ~f~? Im reserving the ~f~ for a tree-sitter version that is not always available for all modes… yet. 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 Extensions
** Evil Exchange ** Evil Exchange
@ -414,10 +437,10 @@ Not sure what is in a register? Have it show you when you hit ~”~ or ~@~ with
:after posframe :after posframe
:config :config
(setq evil-owl-display-method 'posframe (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-max-string-length 50)
(evil-owl-mode)) (evil-owl-mode))
#+end_src #+end_src
** Evil Surround ** 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/. 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) (better-jumper-mode +1)
(with-eval-after-load 'evil-maps (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 "M-[") '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-forward)))
#+end_src #+end_src
* Technical Artifacts :noexport: * Technical Artifacts :noexport: