Re-work org-dwim-char
This commit is contained in:
parent
f527fc83b7
commit
479fc1436d
@ -47,10 +47,13 @@
|
||||
(bury-buffer)
|
||||
(other-window 1))
|
||||
|
||||
(defvar org-vw-pre-hook nil
|
||||
"Hook to run before org-vw-mode has been loaded.")
|
||||
(define-minor-mode org-vw-mode
|
||||
"Org VimWiki mode."
|
||||
:lighter " VW"
|
||||
:keymap (make-sparse-keymap)
|
||||
(run-hooks org-vw-pre-hook)
|
||||
;; TODO: This is a hack, because hyperbole is scary. Ideal implementation
|
||||
;; would add a proper case rather than this weird fallback.
|
||||
(require 'hyperbole)
|
||||
@ -60,7 +63,12 @@
|
||||
(general-define-key
|
||||
:keymaps 'local
|
||||
:states 'normal
|
||||
"DEL" 'org-vw-back))
|
||||
"DEL" 'org-vw-back)
|
||||
(dolist (key mitch/org-dwim-char-chars)
|
||||
(general-define-key
|
||||
:keymaps 'local
|
||||
key 'mitch/org-dwim-char))
|
||||
)
|
||||
;; (add-to-list 'auto-mode-alist `(,org-wiki-regex . org-vw-mode))
|
||||
(add-hook 'org-mode-hook #'org-vw-mode)
|
||||
|
||||
@ -84,6 +92,7 @@ Start insert mode."
|
||||
|
||||
;; ------------------ ABANDON ALL SANITY, YE WHO ENTER HERE --------------------
|
||||
|
||||
(defvar mitch/org-dwim-char-chars '("_" "/" "*" "+" "~" "="))
|
||||
(defun mitch/org-dwim-char (&optional char)
|
||||
"If a region is active (visual mode), surround selection with CHAR.
|
||||
|
||||
@ -100,28 +109,49 @@ character CHAR.
|
||||
|
||||
Otherwise, insert two of CHAR and put point between them like `electric-pair'."
|
||||
(interactive) ; TODO: can we make CHAR an arg to `interactive'?
|
||||
(let ((char (or char (string-to-char (this-command-keys))))
|
||||
(word (thing-at-point 'word 'no-properties)))
|
||||
(let* ((char (or char (string-to-char (this-command-keys))))
|
||||
(word (thing-at-point 'word 'no-properties))
|
||||
;;; test conditions here to be eval'd, separating flow from data
|
||||
;; at beginning of word
|
||||
(beginning-of-word-test '(or (bolp) (eq (char-before (point)) ?\ )))
|
||||
;; word is surrounded by `char'
|
||||
(surrounded-by-char-test
|
||||
'(and (eq (char-before (beginning-of-thing 'word)) char)
|
||||
(eq (char-after (end-of-thing 'word)) char)))
|
||||
;; char before and char after are the same
|
||||
(double-char-test (eq char (char-after)))
|
||||
;; Weird Org exceptions because org
|
||||
(org-exceptions-test
|
||||
'(or (string-match-p (rx bol (or "#" "*"))
|
||||
(thing-at-point 'line 'no-properties))
|
||||
(org-in-block-p org-protecting-blocks)
|
||||
(org-at-property-p))
|
||||
)
|
||||
)
|
||||
(cond
|
||||
((eq evil-state 'visual)
|
||||
(let* ((beg (region-beginning))
|
||||
(end (region-end)))
|
||||
(evil-surround-region beg end evil-visual-selection char nil)))
|
||||
((eq evil-state 'normal)
|
||||
(if (or (bolp) (eq (char-before (point)) ?\ )) ; at beginning of word
|
||||
(if (eval beginning-of-word-test)
|
||||
;; run original function bound to key
|
||||
(let ((charstr (make-string 1 char)))
|
||||
(pcase charstr
|
||||
;; TODO: can we not hard-code this?
|
||||
("_" (call-interactively 'evil-next-line-1-first-non-blank))
|
||||
("/" (call-interactively 'evil-search-forward))
|
||||
("*" (call-interactively 'evil-search-word-forward))
|
||||
("+" (call-interactively 'evil-next-line-first-non-blank))
|
||||
("~" (call-interactively 'evil-invert-char))
|
||||
("=" (call-interactively 'evil-indent))))
|
||||
;; (pcase charstr
|
||||
;; ;; TODO: can we not hard-code this?
|
||||
;; ;; MAYBE: with Advice on each below function.
|
||||
;; ;; MAYBE: with `key-binding' fn
|
||||
;; ("_" (call-interactively 'evil-next-line-1-first-non-blank))
|
||||
;; ("/" (call-interactively 'evil-search-forward))
|
||||
;; ("*" (call-interactively 'evil-search-word-forward))
|
||||
;; ("+" (call-interactively 'evil-next-line-first-non-blank))
|
||||
;; ("~" (call-interactively 'evil-invert-char))
|
||||
;; ("=" (call-interactively 'evil-indent)))
|
||||
(call-interactively (alist-get charstr org-vw-old-binds-alist
|
||||
nil nil #'string=))
|
||||
)
|
||||
(save-excursion
|
||||
(if (and (eq (char-before (beginning-of-thing 'word)) char)
|
||||
(eq (char-after (end-of-thing 'word)) char))
|
||||
(if (eval surrounded-by-char-test)
|
||||
(progn
|
||||
(search-backward (char-to-string char)) (delete-char 1)
|
||||
(search-forward (char-to-string char)) (delete-char -1))
|
||||
@ -130,16 +160,21 @@ Otherwise, insert two of CHAR and put point between them like `electric-pair'."
|
||||
(insert char)
|
||||
(end-of-thing 'word)
|
||||
(insert char))))))
|
||||
((eq char (char-after))
|
||||
(right-char))
|
||||
((or (string-match-p (rx bol (or "#" "*" ""))
|
||||
(thing-at-point 'line 'no-properties))
|
||||
(org-in-block-p org-protecting-blocks)
|
||||
(org-at-property-p))
|
||||
(insert char))
|
||||
((eval double-char-test) (right-char))
|
||||
((eval org-exceptions-test) (insert char))
|
||||
(t (progn
|
||||
(insert (make-string 2 char))
|
||||
(left-char))))))
|
||||
(defun org-vw-snapshot-bindings ()
|
||||
"Make an alist of the functions formerly ran by keys to be bound to `mitch/org-dwim-char'.
|
||||
|
||||
Store it in the variable `org-vw-old-binds-alist'."
|
||||
(unless org-vw-old-binds-alist
|
||||
(defvar-local org-vw-old-binds-alist
|
||||
(mapcar (lambda (key)
|
||||
(cons key (key-binding key)))
|
||||
mitch/org-dwim-char-chars))))
|
||||
(add-hook 'org-vw-pre-hook #'org-vw-snapshot-bindings nil 'local)
|
||||
;; (setq debug-on-error t)
|
||||
;; --------- LET THY BRAIN NO LONGER TREMBLE, FOR I AM BECOME COMPLETE ---------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user