Last active
May 8, 2017 14:49
-
-
Save hlissner/6c3878c5389594349b48 to your computer and use it in GitHub Desktop.
A simple hack to add several substitutions to evil-mode's :ex mode, other than % and #...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; A hack to add vim file modifiers to evil-mode's ex commandline: | |
;; | |
;; Requires projectile (https://github.com/bbatsov/projectile) for | |
;; project-awareness, and f.el (https://github.com/rejeep/f.el) for file | |
;; functions. | |
(defun +evil*ex-replace-special-filenames (file-name) | |
"Replace special symbols in FILE-NAME. Modified to include other substitution | |
flags. See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers." | |
(let* (case-fold-search | |
(regexp (concat "\\(?:^\\|[^\\\\]\\)" | |
"\\([#%]\\)" | |
"\\(\\(?::\\(?:[PphtreS~.]\\|g?s[^:\t\n ]+\\)\\)*\\)")) | |
(matches | |
(let ((all-strings ()) | |
(i 0)) | |
(while (and (< i (length file-name)) | |
(string-match regexp file-name i)) | |
(setq i (1+ (match-beginning 0))) | |
(let (strings) | |
(push (dotimes (i (/ (length (match-data)) 2) (nreverse strings)) | |
(push (match-string i file-name) strings)) | |
all-strings))) | |
(nreverse all-strings)))) | |
(dolist (match matches) | |
(let ((flags (split-string (car (cdr (cdr match))) ":" t)) | |
(path (and buffer-file-name | |
(pcase (car (cdr match)) | |
("%" (file-relative-name buffer-file-name)) | |
("#" (save-excursion (other-window 1) (file-relative-name buffer-file-name)))))) | |
flag global) | |
(if (not path) | |
(setq path "") | |
(while flags | |
(setq flag (pop flags)) | |
(when (string-suffix-p "\\" flag) | |
(setq flag (concat flag (pop flags)))) | |
(when (string-prefix-p "gs" flag) | |
(setq global t | |
flag (substring flag 1))) | |
(setq path | |
(or (pcase (substring flag 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 (equal (file-truename path) | |
(file-truename parent)) | |
(if (file-name-absolute-p path) | |
(directory-file-name parent) | |
(file-relative-name parent))))) | |
("s" | |
(when-let (args (evil-delimited-arguments (substring flag 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))))) | |
("P" | |
(let ((default-directory (file-name-directory (expand-file-name path)))) | |
(abbreviate-file-name (projectile-project-root)))) | |
(_ path)) | |
""))) | |
;; strip trailing slash, if applicable | |
(when (and (not (string= path "")) (equal (substring path -1) "/")) | |
(setq path (substring path 0 -1)))) | |
(setq file-name | |
(replace-regexp-in-string (format "\\(?:^\\|[^\\\\]\\)\\(%s\\)" | |
(regexp-quote (string-trim-left (car match)))) | |
path file-name t t 1)))) | |
(setq file-name (replace-regexp-in-string regexp "\\1" file-name t)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment