;;; 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") ;; 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") ;; 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)))