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:
parent
04a3db3d2b
commit
6cb5efc929
5 changed files with 88 additions and 84 deletions
|
@ -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
|
||||||
|
|
|
@ -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)))
|
||||||
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue