Fix #2832: filename modifiers replaced with empty strings

This commit is contained in:
Henrik Lissner 2020-04-26 04:12:33 -04:00
parent 077b6f00d4
commit 50ff934ff2
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
5 changed files with 65 additions and 66 deletions

View file

@ -7,7 +7,7 @@
(call-interactively #'doom/escape))) (call-interactively #'doom/escape)))
;;;###autoload ;;;###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 "Take a path and resolve any vim-like filename modifiers in it. This adds
support for most vim file modifiers, as well as: 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 See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers for
more information on modifiers." more information on modifiers."
(let (case-fold-search) (let ((origin-buffer (current-buffer))
case-fold-search)
(with-temp-buffer (with-temp-buffer
(save-excursion (insert file-name)) (let ((buffer-file-name (buffer-file-name origin-buffer)))
(while (re-search-forward "\\(^\\|[^\\\\]\\)\\(\\([%#]\\)\\(:\\([PphtreS~.]\\|g?s\\)\\)*\\)" nil t) (save-excursion (insert file-name))
(catch 'continue (while (re-search-forward "\\(^\\|[^\\\\]\\)\\(\\([%#]\\)\\(:\\([PphtreS~.]\\|g?s\\)\\)*\\)" nil t)
(unless buffer-file-name (if (null buffer-file-name)
(replace-match (match-string 1) t t nil 2) (replace-match (match-string 1) t t nil 2)
(throw 'continue t)) (let ((beg (match-beginning 2))
(let ((beg (match-beginning 2)) (end (match-end 3))
(end (match-end 3)) (path (pcase (match-string 3)
(path (pcase (match-string 3) ("%" (file-relative-name buffer-file-name default-directory))
("%" (file-relative-name buffer-file-name)) ("#" (and (other-buffer origin-buffer)
("#" (and (other-buffer) (buffer-file-name (other-buffer origin-buffer)))))))
(buffer-file-name (other-buffer))))))) (save-match-data
(save-match-data (goto-char beg)
(goto-char beg) (while (re-search-forward ":\\([PphtreS~.]\\|g?s\\)" (+ (point) 3) t)
(while (re-search-forward ":\\([PphtreS~.]\\|g?s\\)" (+ (point) 3) t) (let* ((modifier (match-string 1))
(let* ((modifier (match-string 1)) (global (string-prefix-p "gs" modifier)))
(global (string-prefix-p "gs" modifier))) (when global
(when global (setq modifier (substring modifier 1)))
(setq modifier (substring modifier 1))) (setq end (match-end 1)
(setq end (match-end 1) path
path (pcase (and path (substring modifier 0 1))
(or (when path (`nil "")
(pcase (substring modifier 0 1) ("p" (expand-file-name path))
("p" (expand-file-name path)) ("~" (concat "~/" (file-relative-name path "~")))
("~" (concat "~/" (file-relative-name path "~"))) ("." (file-relative-name path))
("." (file-relative-name path default-directory)) ("t" (file-name-nondirectory (directory-file-name path)))
("t" (file-name-nondirectory (directory-file-name path))) ("r" (file-name-sans-extension path))
("r" (file-name-sans-extension path)) ("e" (file-name-extension path))
("e" (file-name-extension path)) ("S" (shell-quote-argument path))
("S" (shell-quote-argument path)) ("h"
("h" (let ((parent (file-name-directory (expand-file-name path))))
(let ((parent (file-name-directory (expand-file-name path)))) (unless (file-equal-p path parent)
(unless (file-equal-p path parent) (if (file-name-absolute-p path)
(if (file-name-absolute-p path) (directory-file-name parent)
(directory-file-name parent) (file-relative-name parent)))))
(file-relative-name parent))))) ("s"
("s" (if (featurep 'evil)
(if (featurep 'evil) (when-let (args (evil-delimited-arguments (substring modifier 1) 2))
(when-let (args (evil-delimited-arguments (substring modifier 1) 2)) (let ((pattern (evil-transform-vim-style-regexp (car args)))
(let ((pattern (evil-transform-vim-style-regexp (car args))) (replace (cadr args)))
(replace (cadr args))) (replace-regexp-in-string
(replace-regexp-in-string (if global pattern (concat "\\(" pattern "\\).*\\'"))
(if global pattern (concat "\\(" pattern "\\).*\\'")) (evil-transform-vim-style-regexp replace) path t t
(evil-transform-vim-style-regexp replace) path t t (unless global 1))))
(unless global 1)))) path))
path)) ("P"
("P" (let ((project-root (doom-project-root (file-name-directory (expand-file-name path)))))
(let ((project-root (doom-project-root (file-name-directory (expand-file-name path))))) (unless project-root
(unless project-root (user-error "Not in a project"))
(user-error "Not in a project")) (abbreviate-file-name project-root)))))
(abbreviate-file-name project-root))))) ;; strip trailing slash, if applicable
"")) (or (string-empty-p path)
;; strip trailing slash, if applicable (not (equal (substring path -1) "/"))
(or (string-empty-p path) (setq path (substring path 0 -1))))))
(not (equal (substring path -1) "/")) (replace-match path t t nil 2))))
(setq path (substring path 0 -1)))))) (replace-regexp-in-string "\\\\\\([#%]\\)" "\\1" (buffer-string) t)))))
(replace-match path t t nil 2))))
(replace-regexp-in-string "\\\\\\([#%]\\)" "\\1" (buffer-string) t))))
(defun +evil--insert-newline (&optional above _noextranewline) (defun +evil--insert-newline (&optional above _noextranewline)
(let ((pos (save-excursion (beginning-of-line-text) (point))) (let ((pos (save-excursion (beginning-of-line-text) (point)))

View file

@ -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 is non-nil, open compilation output in a comint buffer.
If BANG, then run ARGUMENTS as a full command. This command understands vim file 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 "<sh><!>") (interactive "<sh><!>")
(let ((compile-command "make")) (let ((compile-command "make"))
(+evil:compile (if (stringp arguments) (+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. If BANG is non-nil, open compilation output in a comint buffer.
This command understands vim file modifiers (like %:p:h). See 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 "<sh><!>") (interactive "<sh><!>")
(compile (evil-ex-replace-special-filenames (compile (evil-ex-replace-special-filenames
(format "%s %s" (format "%s %s"

View file

@ -159,7 +159,7 @@ directives. By default, this only recognizes C directives.")
;; monkey patch `evil-ex-replace-special-filenames' to improve support for ;; 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, ;; file modifiers like %:p:h. This adds support for most of vim's modifiers,
;; and one custom one: %:P (expand to the project root). ;; 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 ;; make `try-expand-dabbrev' (from `hippie-expand') work in minibuffer
(add-hook 'minibuffer-inactive-mode-hook #'+evil--fix-dabbrev-in-minibuffer-h) (add-hook 'minibuffer-inactive-mode-hook #'+evil--fix-dabbrev-in-minibuffer-h)

View file

@ -9,10 +9,10 @@
(load! "../autoload/evil") (load! "../autoload/evil")
(before-each (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))) (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" (describe "file modifiers"
(it "supports basic vim file modifiers" (it "supports basic vim file modifiers"
(let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el") (let ((buffer-file-name "~/.emacs.d/test/modules/feature/test-evil.el")

View file

@ -6,7 +6,7 @@
"TODO" "TODO"
(interactive "<fsh><!>") (interactive "<fsh><!>")
(let ((buffer (+eshell-last-buffer)) (let ((buffer (+eshell-last-buffer))
(command (+evil-resolve-vim-path-a command))) (command (+evil-replace-filename-modifiers-a command)))
(cond (buffer (cond (buffer
(select-window (get-buffer-window buffer)) (select-window (get-buffer-window buffer))
(+eshell-run-command command buffer)) (+eshell-run-command command buffer))