core-lib: rename helper fns; move doom-resolve-vim-path

+ doom--resolve-paths => doom--resolve-path-forms
+ doom--resolve-hooks => doom--resolve-hook-forms
+ +evil*ex-replace-special-filenames => doom-resolve-vim-path
This commit is contained in:
Henrik Lissner 2017-09-27 01:21:48 +02:00
parent 04a3db3d2b
commit 6cb5efc929
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
5 changed files with 88 additions and 84 deletions

View file

@ -29,7 +29,7 @@
;; Helpers ;; Helpers
;; ;;
(defun doom--resolve-paths (paths &optional root) (defun doom--resolve-path-forms (paths &optional root)
(cond ((stringp paths) (cond ((stringp paths)
`(file-exists-p `(file-exists-p
(expand-file-name (expand-file-name
@ -39,10 +39,10 @@
(or root `(doom-project-root)))))) (or root `(doom-project-root))))))
((listp paths) ((listp paths)
(cl-loop for i in paths (cl-loop for i in paths
collect (doom--resolve-paths i root))) collect (doom--resolve-path-forms i root)))
(t paths))) (t paths)))
(defun doom--resolve-hooks (hooks) (defun doom--resolve-hook-forms (hooks)
(cl-loop with quoted-p = (eq (car-safe hooks) 'quote) (cl-loop with quoted-p = (eq (car-safe hooks) 'quote)
for hook in (doom-enlist (doom-unquote hooks)) for hook in (doom-enlist (doom-unquote hooks))
if (eq (car-safe hook) 'quote) if (eq (car-safe hook) 'quote)
@ -61,6 +61,81 @@
"Return EXP wrapped in a list, or as-is if already a list." "Return EXP wrapped in a list, or as-is if already a list."
(if (listp exp) exp (list exp))) (if (listp exp) exp (list exp)))
(defun doom-resolve-vim-path (file-name)
"Take a path and resolve any vim-like filename modifiers in it. This adds
support for these special modifiers:
%:P Resolves to `doom-project-root'.
See http://vimdoc.sourceforge.net/htmldoc/cmdline.html#filename-modifiers."
(let* (case-fold-search
(regexp (concat "\\(?:^\\|[^\\\\]\\)"
"\\([#%]\\)"
"\\(\\(?::\\(?:[PphtreS~.]\\|g?s[^:\t\n ]+\\)\\)*\\)"))
(matches
(cl-loop with i = 0
while (and (< i (length file-name))
(string-match regexp file-name i))
do (setq i (1+ (match-beginning 0)))
and collect
(cl-loop for j to (/ (length (match-data)) 2)
collect (match-string j file-name)))))
(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"
(if (featurep 'evil)
(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))))
path))
("P"
(let ((default-directory (file-name-directory (expand-file-name path))))
(abbreviate-file-name (doom-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))))
(replace-regexp-in-string regexp "\\1" file-name t)))
;; ;;
;; Library ;; Library
@ -153,7 +228,7 @@ Body forms can access the hook's arguments through the let-bound variable
(:append (setq append-p t)) (:append (setq append-p t))
(:local (setq local-p t)) (:local (setq local-p t))
(:remove (setq hook-fn 'remove-hook)))) (:remove (setq hook-fn 'remove-hook))))
(let ((hooks (doom--resolve-hooks (pop args))) (let ((hooks (doom--resolve-hook-forms (pop args)))
(funcs (funcs
(let ((val (car args))) (let ((val (car args)))
(if (memq (car-safe val) '(quote function)) (if (memq (car-safe val) '(quote function))
@ -199,11 +274,11 @@ Body forms can access the hook's arguments through the let-bound variable
(not ,mode) (not ,mode)
(and buffer-file-name (not (file-remote-p buffer-file-name))) (and buffer-file-name (not (file-remote-p buffer-file-name)))
,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t) ,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t)
,(if files (doom--resolve-paths files) t) ,(if files (doom--resolve-path-forms files) t)
,(or pred-form t)) ,(or pred-form t))
(,mode 1))) (,mode 1)))
,@(if (and modes (listp modes)) ,@(if (and modes (listp modes))
(cl-loop for hook in (doom--resolve-hooks modes) (cl-loop for hook in (doom--resolve-hook-forms modes)
collect `(add-hook ',hook ',hook-name)) collect `(add-hook ',hook ',hook-name))
`((add-hook 'after-change-major-mode-hook ',hook-name)))))) `((add-hook 'after-change-major-mode-hook ',hook-name))))))
(match (match

View file

@ -72,7 +72,7 @@ If STRICT-P, return nil if no project was found, otherwise return
Paths are relative to the project root, unless they start with ./ or ../ (in Paths are relative to the project root, unless they start with ./ or ../ (in
which case they're relative to `default-directory'). If they start with a slash, which case they're relative to `default-directory'). If they start with a slash,
they are absolute." they are absolute."
(doom--resolve-paths files (doom-project-root))) (doom--resolve-path-forms files (doom-project-root)))
;; ;;

View file

@ -3,18 +3,18 @@
;; --- Helpers ---------------------------- ;; --- Helpers ----------------------------
;; `doom--resolve-paths' ;; `doom--resolve-path-forms'
(def-test! resolve-paths (def-test! resolve-paths
(should (should
(equal (doom--resolve-paths '(and "fileA" "fileB")) (equal (doom--resolve-path-forms '(and "fileA" "fileB"))
'(and (file-exists-p (expand-file-name "fileA" (doom-project-root))) '(and (file-exists-p (expand-file-name "fileA" (doom-project-root)))
(file-exists-p (expand-file-name "fileB" (doom-project-root))))))) (file-exists-p (expand-file-name "fileB" (doom-project-root)))))))
;; `doom--resolve-hooks' ;; `doom--resolve-hook-forms'
(def-test! resolve-hooks (def-test! resolve-hooks
(should (equal (doom--resolve-hooks '(js2-mode haskell-mode)) (should (equal (doom--resolve-hook-forms '(js2-mode haskell-mode))
'(js2-mode-hook haskell-mode-hook))) '(js2-mode-hook haskell-mode-hook)))
(should (equal (doom--resolve-hooks '(quote (js2-mode-hook haskell-mode-hook))) (should (equal (doom--resolve-hook-forms '(quote (js2-mode-hook haskell-mode-hook)))
'(js2-mode-hook haskell-mode-hook)))) '(js2-mode-hook haskell-mode-hook))))
;; `doom-unquote' ;; `doom-unquote'

View file

@ -26,76 +26,6 @@
(save-excursion (goto-char beg) (point-marker)) (save-excursion (goto-char beg) (point-marker))
end))) end)))
;;;###autoload
(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
(cl-loop with i = 0
while (and (< i (length file-name))
(string-match regexp file-name i))
do (setq i (1+ (match-beginning 0)))
and collect
(cl-loop for j to (/ (length (match-data)) 2)
collect (match-string j file-name)))))
(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 (doom-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))))
(defun +evil--window-swap (direction) (defun +evil--window-swap (direction)
"Move current window to the next window in DIRECTION. If there are no windows "Move current window to the next window in DIRECTION. If there are no windows
there and there is only one window, split in that direction and place this there and there is only one window, split in that direction and place this

View file

@ -124,8 +124,7 @@ across windows."
;; monkey patch `evil-ex-replace-special-filenames' to add more ex ;; monkey patch `evil-ex-replace-special-filenames' to add more ex
;; substitution flags to evil-mode ;; substitution flags to evil-mode
(advice-add #'evil-ex-replace-special-filenames (advice-add #'evil-ex-replace-special-filenames :override #'doom-resolve-vim-path)
:override #'+evil*ex-replace-special-filenames)
;; These arg types will highlight matches in the current buffer ;; These arg types will highlight matches in the current buffer
(evil-ex-define-argument-type buffer-match :runner +evil-ex-buffer-match) (evil-ex-define-argument-type buffer-match :runner +evil-ex-buffer-match)