From 50ff934ff2169866e2fb38b32ae015a7268bb85a Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Sun, 26 Apr 2020 04:12:33 -0400 Subject: [PATCH] Fix #2832: filename modifiers replaced with empty strings --- modules/editor/evil/autoload/advice.el | 119 ++++++++++++------------- modules/editor/evil/autoload/ex.el | 4 +- modules/editor/evil/config.el | 2 +- modules/editor/evil/test/test-evil.el | 4 +- modules/term/eshell/autoload/evil.el | 2 +- 5 files changed, 65 insertions(+), 66 deletions(-) diff --git a/modules/editor/evil/autoload/advice.el b/modules/editor/evil/autoload/advice.el index 834f40315..e54a1ab90 100644 --- a/modules/editor/evil/autoload/advice.el +++ b/modules/editor/evil/autoload/advice.el @@ -7,7 +7,7 @@ (call-interactively #'doom/escape))) ;;;###autoload -(defun +evil-resolve-vim-path-a (file-name) +(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: @@ -15,66 +15,65 @@ support for most vim file modifiers, as well as: See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers for more information on modifiers." - (let (case-fold-search) + (let ((origin-buffer (current-buffer)) + case-fold-search) (with-temp-buffer - (save-excursion (insert file-name)) - (while (re-search-forward "\\(^\\|[^\\\\]\\)\\(\\([%#]\\)\\(:\\([PphtreS~.]\\|g?s\\)\\)*\\)" nil t) - (catch 'continue - (unless buffer-file-name - (replace-match (match-string 1) t t nil 2) - (throw 'continue t)) - (let ((beg (match-beginning 2)) - (end (match-end 3)) - (path (pcase (match-string 3) - ("%" (file-relative-name buffer-file-name)) - ("#" (and (other-buffer) - (buffer-file-name (other-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 - (or (when path - (pcase (substring modifier 0 1) - ("p" (expand-file-name path)) - ("~" (concat "~/" (file-relative-name path "~"))) - ("." (file-relative-name path default-directory)) - ("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)))) + (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))) diff --git a/modules/editor/evil/autoload/ex.el b/modules/editor/evil/autoload/ex.el index 09b18ed70..bdcb5d6fa 100644 --- a/modules/editor/evil/autoload/ex.el +++ b/modules/editor/evil/autoload/ex.el @@ -108,7 +108,7 @@ g Repeat alignment on all matches in each line" If BANG is non-nil, open compilation output in a comint buffer. If BANG, then run ARGUMENTS as a full command. This command understands vim file -modifiers (like %:p:h). See `+evil-resolve-vim-path-a' for details." +modifiers (like %:p:h). See `+evil-replace-filename-modifiers-a' for details." (interactive "") (let ((compile-command "make")) (+evil:compile (if (stringp arguments) @@ -122,7 +122,7 @@ modifiers (like %:p:h). See `+evil-resolve-vim-path-a' for details." If BANG is non-nil, open compilation output in a comint buffer. This command understands vim file modifiers (like %:p:h). See -`+evil-resolve-vim-path-a' for details." +`+evil-replace-filename-modifiers-a' for details." (interactive "") (compile (evil-ex-replace-special-filenames (format "%s %s" diff --git a/modules/editor/evil/config.el b/modules/editor/evil/config.el index 3dfb39fd3..358e0cb1f 100644 --- a/modules/editor/evil/config.el +++ b/modules/editor/evil/config.el @@ -159,7 +159,7 @@ directives. By default, this only recognizes C directives.") ;; monkey patch `evil-ex-replace-special-filenames' to improve support for ;; file modifiers like %:p:h. This adds support for most of vim's modifiers, ;; and one custom one: %:P (expand to the project root). - (advice-add #'evil-ex-replace-special-filenames :override #'+evil-resolve-vim-path-a) + (advice-add #'evil-ex-replace-special-filenames :override #'+evil-replace-filename-modifiers-a) ;; make `try-expand-dabbrev' (from `hippie-expand') work in minibuffer (add-hook 'minibuffer-inactive-mode-hook #'+evil--fix-dabbrev-in-minibuffer-h) diff --git a/modules/editor/evil/test/test-evil.el b/modules/editor/evil/test/test-evil.el index dd77fd0f4..3b77c9cc3 100644 --- a/modules/editor/evil/test/test-evil.el +++ b/modules/editor/evil/test/test-evil.el @@ -9,10 +9,10 @@ (load! "../autoload/evil") (before-each - (fset 'resv #'+evil-resolve-vim-path-a) + (fset 'resv #'+evil-replace-filename-modifiers-a) (spy-on 'doom-project-root :and-call-fake (lambda () project-root))) - ;; `evil-ex-replace-special-filenames' / `+evil-resolve-vim-path-a' + ;; `evil-ex-replace-special-filenames' / `+evil-replace-filename-modifiers-a' (describe "file modifiers" (it "supports basic vim file modifiers" (let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el") diff --git a/modules/term/eshell/autoload/evil.el b/modules/term/eshell/autoload/evil.el index a3326e322..04e45d377 100644 --- a/modules/term/eshell/autoload/evil.el +++ b/modules/term/eshell/autoload/evil.el @@ -6,7 +6,7 @@ "TODO" (interactive "") (let ((buffer (+eshell-last-buffer)) - (command (+evil-resolve-vim-path-a command))) + (command (+evil-replace-filename-modifiers-a command))) (cond (buffer (select-window (get-buffer-window buffer)) (+eshell-run-command command buffer))