doomemacs/modules/editor/evil/autoload/advice.el
Henrik Lissner 06392a723f refactor: rename orig-fn arg in advice to fn
A minor tweak to our naming conventions for the first argument of an
:around advice.
2021-08-04 01:53:12 -04:00

214 lines
9.9 KiB
EmacsLisp

;;; editor/evil/autoload/advice.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +evil-escape-a (&rest _)
"Call `doom/escape' if `evil-force-normal-state' is called interactively."
(when (called-interactively-p 'any)
(call-interactively #'doom/escape)))
;;;###autoload
(defun +evil-replace-filename-modifiers-a (file-name)
"Take a path and resolve any vim-like filename modifiers in it. This adds
support for most vim file modifiers, as well as:
%:P Resolves to `doom-project-root'.
See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers for
more information on modifiers."
(let ((origin-buffer (current-buffer))
case-fold-search)
(with-temp-buffer
(let ((buffer-file-name (buffer-file-name origin-buffer)))
(save-excursion (insert file-name))
(while (re-search-forward "\\(^\\|[^\\\\]\\)\\(\\([%#]\\)\\(:\\([PphtreS~.]\\|g?s\\)\\)*\\)" nil t)
(if (null buffer-file-name)
(replace-match (match-string 1) t t nil 2)
(let ((beg (match-beginning 2))
(end (match-end 3))
(path (pcase (match-string 3)
("%" (file-relative-name buffer-file-name default-directory))
("#" (and (other-buffer origin-buffer)
(buffer-file-name (other-buffer origin-buffer)))))))
(save-match-data
(goto-char beg)
(while (re-search-forward ":\\([PphtreS~.]\\|g?s\\)" (+ (point) 3) t)
(let* ((modifier (match-string 1))
(global (string-prefix-p "gs" modifier)))
(when global
(setq modifier (substring modifier 1)))
(setq end (match-end 1)
path
(pcase (and path (substring modifier 0 1))
(`nil "")
("p" (expand-file-name path))
("~" (concat "~/" (file-relative-name path "~")))
("." (file-relative-name path))
("t" (file-name-nondirectory (directory-file-name path)))
("r" (file-name-sans-extension path))
("e" (file-name-extension path))
("S" (shell-quote-argument path))
("h"
(let ((parent (file-name-directory (expand-file-name path))))
(unless (file-equal-p path parent)
(if (file-name-absolute-p path)
(directory-file-name parent)
(file-relative-name parent)))))
("s"
(if (featurep 'evil)
(when-let (args (evil-delimited-arguments (substring modifier 1) 2))
(let ((pattern (evil-transform-vim-style-regexp (car args)))
(replace (cadr args)))
(replace-regexp-in-string
(if global pattern (concat "\\(" pattern "\\).*\\'"))
(evil-transform-vim-style-regexp replace) path t t
(unless global 1))))
path))
("P"
(let ((project-root (doom-project-root (file-name-directory (expand-file-name path)))))
(unless project-root
(user-error "Not in a project"))
(abbreviate-file-name project-root)))))
;; strip trailing slash, if applicable
(or (string-empty-p path)
(not (equal (substring path -1) "/"))
(setq path (substring path 0 -1))))))
(replace-match path t t nil 2))))
(replace-regexp-in-string "\\\\\\([#%]\\)" "\\1" (buffer-string) t)))))
(defun +evil--insert-newline (&optional above _noextranewline)
(let ((pos (save-excursion (beginning-of-line-text) (point)))
comment-auto-fill-only-comments)
(require 'smartparens)
(evil-narrow-to-field
(if above
(if (save-excursion (nth 4 (sp--syntax-ppss pos)))
(evil-save-goal-column
(setq evil-auto-indent nil)
(goto-char pos)
(let ((ws (abs (skip-chars-backward " \t"))))
;; FIXME oh god why
(save-excursion
(if comment-line-break-function
(funcall comment-line-break-function nil)
(comment-indent-new-line))
(when (and (derived-mode-p 'c-mode 'c++-mode 'objc-mode 'java-mode 'js2-mode)
(eq (char-after) ?/))
(insert "*"))
(insert
(make-string (max 0 (+ ws (skip-chars-backward " \t")))
32)))
(insert (make-string (max 1 ws) 32))))
(evil-move-beginning-of-line)
(insert (if use-hard-newlines hard-newline "\n"))
(forward-line -1)
(back-to-indentation))
(evil-move-end-of-line)
(cond ((sp-point-in-comment pos)
(setq evil-auto-indent nil)
(if comment-line-break-function
(funcall comment-line-break-function nil)
(comment-indent-new-line)))
;; TODO Find a better way to do this
((and (eq major-mode 'haskell-mode)
(fboundp 'haskell-indentation-newline-and-indent))
(setq evil-auto-indent nil)
(haskell-indentation-newline-and-indent))
(t
(insert (if use-hard-newlines hard-newline "\n"))
(back-to-indentation)))))))
;;;###autoload
(defun +evil--insert-newline-below-and-respect-comments-a (fn count)
(if (or (not +evil-want-o/O-to-continue-comments)
(not (eq this-command 'evil-open-below))
(evil-insert-state-p)
(evil-emacs-state-p))
(funcall fn count)
(letf! (defun evil-insert-newline-below () (+evil--insert-newline))
(let ((evil-auto-indent evil-auto-indent))
(funcall fn count)))))
;;;###autoload
(defun +evil--insert-newline-above-and-respect-comments-a (fn count)
(if (or (not +evil-want-o/O-to-continue-comments)
(not (eq this-command 'evil-open-above))
(evil-insert-state-p)
(evil-emacs-state-p))
(funcall fn count)
(letf! (defun evil-insert-newline-above () (+evil--insert-newline 'above))
(let ((evil-auto-indent evil-auto-indent))
(funcall fn count)))))
;;;###autoload (autoload '+evil-window-split-a "editor/evil/autoload/advice" nil t)
(evil-define-command +evil-window-split-a (&optional count file)
"Same as `evil-window-split', but correctly updates the window history."
:repeat nil
(interactive "P<f>")
;; HACK This ping-ponging between the destination and source windows is to
;; update the window focus history, so that, if you close either split
;; afterwards you won't be sent to some random window.
(let ((doom-inhibit-switch-window-hooks t)
(origwin (selected-window)))
(select-window (split-window origwin count 'below))
(unless evil-split-window-below
(select-window origwin))
(run-hooks 'doom-switch-window-hook))
(recenter)
(when (and (not count) evil-auto-balance-windows)
(balance-windows (window-parent)))
(if file (evil-edit file)))
;;;###autoload (autoload '+evil-window-vsplit-a "editor/evil/autoload/advice" nil t)
(evil-define-command +evil-window-vsplit-a (&optional count file)
"Same as `evil-window-split', but correctly updates the window history."
:repeat nil
(interactive "P<f>")
;; HACK This ping-ponging between the destination and source windows is to
;; update the window focus history, so that, if you close either split
;; afterwards you won't be sent to some random window.
(let ((doom-inhibit-switch-window-hooks t)
(origwin (selected-window)))
(select-window (split-window origwin count 'right))
(unless evil-vsplit-window-right
(select-window origwin))
(run-hooks 'doom-switch-window-hook))
(run-hooks)
(recenter)
(when (and (not count) evil-auto-balance-windows)
(balance-windows (window-parent)))
(if file (evil-edit file)))
;;;###autoload (autoload '+evil-join-a "editor/evil/autoload/advice" nil nil)
(defun +evil-join-a (fn beg end)
"Join the selected lines.
This advice improves on `evil-join' by removing comment delimiters when joining
commented lines, by using `fill-region-as-paragraph'.
From https://github.com/emacs-evil/evil/issues/606"
;; But revert to the default we're not in a comment, where
;; `fill-region-as-paragraph' is too greedy.
(if (not (doom-point-in-comment-p (min (max beg (1+ (point))) end)))
(funcall fn beg end)
(let* ((count (count-lines beg end))
(count (if (> count 1) (1- count) count))
(fixup-mark (make-marker)))
(unwind-protect
(dotimes (var count)
(if (and (bolp) (eolp))
(join-line 1)
(let* ((end (line-beginning-position 3))
(fill-column (1+ (- end beg))))
(set-marker fixup-mark (line-end-position))
(fill-region-as-paragraph beg end nil t)
(goto-char fixup-mark)
(fixup-whitespace))))
(set-marker fixup-mark nil)))))
;;;###autoload
(defun +evil--fix-dabbrev-in-minibuffer-h ()
"Make `try-expand-dabbrev' from `hippie-expand' work in minibuffer. See
`he-dabbrev-beg', so we need to redefine syntax for '/'."
(set-syntax-table (let* ((table (make-syntax-table)))
(modify-syntax-entry ?/ "." table)
table)))