summaryrefslogtreecommitdiff
path: root/emacs/inits/14-movement.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/inits/14-movement.el')
-rw-r--r--emacs/inits/14-movement.el92
1 files changed, 59 insertions, 33 deletions
diff --git a/emacs/inits/14-movement.el b/emacs/inits/14-movement.el
index b44778e..3950fef 100644
--- a/emacs/inits/14-movement.el
+++ b/emacs/inits/14-movement.el
@@ -1,16 +1,65 @@
-;; Time-stamp: <2024-02-29 11h24 CET (f62464ac)>
+;; Time-stamp: <2025-06-25 20h01 BST (anker)>
;; -------------------------------------------------------------------
-;; Repeated key presses for region
+;; We have expand region at home
-(use-package expand-region
- :ensure t
- :bind (("M-r" . er/expand-region))
- :config
- (setq expand-region-fast-keys-enabled t
- expand-region-contract-fast-key "c"
- expand-region-reset-fast-key "e"
- expand-region-autocopy-register "i"))
+(defvar treesit--region-stack '())
+
+(defun treesit-node-bounds-match-region-p (node beg end)
+ "Returns `t' if the bounds of the region marked `beg' and `end' match the bounds of `node'."
+ (and
+ (= beg (treesit-node-start node))
+ (= end (treesit-node-end node))))
+
+(defun treesit-mark-bigger-node ()
+ "Expand selection to the parent of the smallest node containing the region."
+ (interactive)
+ (unless mark-active
+ (set-mark-command nil))
+ (unless (or (eq last-command 'treesit-mark-bigger-node) (eq last-command 'treesit-contract-region))
+ (setq treesit--region-stack nil))
+ (let* ((cur-node (treesit-node-on (region-beginning) (region-end)))
+ (next-node (if
+ ;; check if the node containing the selection is already good
+ (not (treesit-node-bounds-match-region-p cur-node (region-beginning) (region-end)))
+ cur-node
+ (treesit-parent-until
+ cur-node
+ (lambda (n)
+ (not (treesit-node-bounds-match-region-p n (region-beginning) (region-end))))))))
+ (unless (null next-node)
+ (push (cons (region-beginning) (region-end)) treesit--region-stack)
+ (set-mark (treesit-node-end next-node))
+ (goto-char (treesit-node-start next-node)))))
+
+(defun treesit-contract-region ()
+ "Contract a region to the last expansion."
+ (interactive)
+ (unless (null treesit--region-stack)
+ (let ((last-region (pop treesit--region-stack)))
+ (set-mark (cdr last-region))
+ (goto-char (car last-region)))))
+
+(defun treesit-reset-region ()
+ "Reset region to before the first invocation of `treesit-mark-bigger-node'."
+ (interactive)
+ (unless (null treesit--region-stack)
+ (let ((last-region (car (last treesit--region-stack))))
+ (setq treesit--region-stack nil)
+ (set-mark (cdr last-region))
+ (goto-char (car last-region))
+ (when (= (car last-region) (cdr last-region))
+ (deactivate-mark)))))
+
+(defvar-keymap treesit-mark-bigger-node-repeat-map
+ :doc "Repeatedly expand selection up tree sitter nodes."
+ :repeat (:exit (treesit-reset-region))
+ "<return>" #'treesit-mark-bigger-node
+ "-" #'treesit-contract-region
+ "C-g" #'treesit-reset-region)
+
+(global-set-key (kbd "M-r") 'treesit-mark-bigger-node)
+(global-set-key (kbd "M-S-r") 'treesit-contract-region)
;; -------------------------------------------------------------------
;; Window switching
@@ -23,29 +72,6 @@
(setq aw-keys '(?a ?r ?s ?t ?c ?e ?n ?i)))
;; -------------------------------------------------------------------
-;; Character jumping
-
-(use-package avy
- :ensure t
- :demand
- :bind (("C->" . avy-goto-char-timer)
- ("C-." . avy-goto-char-in-line)
- ("M-g s" . avy-goto-word-or-subword-1)
- ("M-g w" . avy-goto-word-1)
- ("M-g a" . avy-goto-word-0)
- ("M-g C-g" . avy-goto-line))
- :config
- (setq avy-keys '(?a ?r ?s ?t ?g ?k ?n ?e ?i ?o ?q ?w ?f ?p)
- avy-dispatch-alist '((?w . avy-action-kill-move)
- (?W . avy-action-kill-stay)
- (?j . avy-action-teleport)
- (?m . avy-action-mark)
- (?c . avy-action-copy)
- (?y . avy-action-yank)
- (?i . avy-action-ispell)
- (?z . avy-action-zap-to-char))))
-
-;; -------------------------------------------------------------------
;; General stuff
;; (global-set-key (kbd "C-b") 'recenter-top-bottom)