core-lib: add auto-minor-mode, revise def-project-mode!
- Adds the auto-minor-mode package to replace our in-house implementation. - Merges associate! into the def-project-mode! macro because associate! on its own is less useful than auto-minor-mode-alist, auto-minor-mode-magic-alist or hooks. - Changes the semantics of :modes and :add-hooks properties of def-project-mode!. Its arguments are evaluated as is; lists will need to be quoted. squash! core-lib: remove associate! macro
This commit is contained in:
parent
3404899ec3
commit
0a84d2f0a9
15 changed files with 88 additions and 137 deletions
|
@ -451,51 +451,6 @@ DOCSTRING and BODY are as in `defun'."
|
|||
(advice-remove target #',symbol)
|
||||
(advice-add target ,where #',symbol)))))
|
||||
|
||||
(cl-defmacro associate! (mode &key modes match files when)
|
||||
"Enables a minor mode if certain conditions are met.
|
||||
|
||||
The available conditions are:
|
||||
|
||||
:modes SYMBOL_LIST
|
||||
A list of major/minor modes in which this minor mode may apply.
|
||||
:match REGEXP
|
||||
A regexp to be tested against the current file path.
|
||||
:files SPEC
|
||||
Accepts what `project-file-exists-p!' accepts. Checks if certain files or
|
||||
directories exist relative to the project root.
|
||||
:when FORM
|
||||
Whenever FORM returns non-nil."
|
||||
(declare (indent 1))
|
||||
(unless noninteractive
|
||||
(cond ((or files modes when)
|
||||
(when (and files
|
||||
(not (or (listp files)
|
||||
(stringp files))))
|
||||
(user-error "associate! :files expects a string or list of strings"))
|
||||
(let ((hook-name (intern (format "doom--enable-mode-%s-h" mode))))
|
||||
`(progn
|
||||
(fset ',hook-name
|
||||
(lambda ()
|
||||
(and (fboundp ',mode)
|
||||
(not (bound-and-true-p ,mode))
|
||||
(and buffer-file-name (not (file-remote-p buffer-file-name)))
|
||||
,(or (not match)
|
||||
`(if buffer-file-name (string-match-p ,match buffer-file-name)))
|
||||
,(or (not files)
|
||||
(doom--resolve-path-forms
|
||||
(if (stringp (car files)) (cons 'and files) files)
|
||||
'(doom-project-root)))
|
||||
,(or when t)
|
||||
(,mode 1))))
|
||||
,@(if (and modes (listp modes))
|
||||
(cl-loop for hook in (doom--resolve-hook-forms modes)
|
||||
collect `(add-hook ',hook #',hook-name))
|
||||
`((add-hook 'after-change-major-mode-hook #',hook-name))))))
|
||||
(match
|
||||
`(add-to-list 'doom-auto-minor-mode-alist '(,match . ,mode)))
|
||||
((user-error "Invalid `associate!' rules for mode [%s] (:modes %s :match %s :files %s :when %s)"
|
||||
mode modes match files when)))))
|
||||
|
||||
(defmacro file-exists-p! (spec &optional directory)
|
||||
"Returns non-nil if the files in SPEC all exist.
|
||||
|
||||
|
|
|
@ -236,31 +236,39 @@ If ALL-P is non-nil, return paths of possible modules, activated or otherwise."
|
|||
use-package-minimum-reported-time (if doom-debug-mode 0 0.1)
|
||||
use-package-expand-minimally (not noninteractive)))
|
||||
|
||||
;; Adds two new keywords to `use-package' (and consequently, `def-package!') to
|
||||
;; Adds four new keywords to `use-package' (and consequently, `def-package!') to
|
||||
;; expand its lazy-loading capabilities. They are:
|
||||
;;
|
||||
;; Check out `def-package!'s documentation for more about these two.
|
||||
;; :after-call SYMBOL|LIST
|
||||
;; :defer-incrementally SYMBOL|LIST|t
|
||||
;;
|
||||
;; Check out `def-package!'s documentation for more about these two.
|
||||
;; Provided by `auto-minor-mode' package:
|
||||
;; :minor
|
||||
;; :magic-minor
|
||||
;;
|
||||
(defvar doom--deferred-packages-alist '(t))
|
||||
|
||||
(with-eval-after-load 'use-package-core
|
||||
;; Macros are already fontified, no need for this
|
||||
(font-lock-remove-keywords 'emacs-lisp-mode use-package-font-lock-keywords)
|
||||
|
||||
;; Disable :ensure and :pin, because they don't work with Doom because we do
|
||||
;; our own package management.
|
||||
(with-eval-after-load 'use-package-ensure
|
||||
(dolist (keyword '(:ensure :pin))
|
||||
(delq! keyword use-package-keywords)
|
||||
(delq! keyword use-package-defaults 'assq)))
|
||||
|
||||
;; Insert new deferring keywords
|
||||
;; Register all new keywords
|
||||
(dolist (keyword '(:defer-incrementally :after-call))
|
||||
(add-to-list 'use-package-deferring-keywords keyword nil #'eq)
|
||||
(push keyword use-package-deferring-keywords)
|
||||
(setq use-package-keywords
|
||||
(use-package-list-insert keyword use-package-keywords :after)))
|
||||
(dolist (keyword '(:minor :magic-minor))
|
||||
(setq use-package-keywords
|
||||
(use-package-list-insert keyword use-package-keywords :commands)))
|
||||
|
||||
(defalias 'use-package-normalize/:minor #'use-package-normalize-mode)
|
||||
(defun use-package-handler/:minor (name _ arg rest state)
|
||||
(use-package-handle-mode name 'auto-minor-mode-alist arg rest state))
|
||||
|
||||
(defalias 'use-package-normalize/:magic-minor #'use-package-normalize-mode)
|
||||
(defun use-package-handler/:magic-minor (name _ arg rest state)
|
||||
(use-package-handle-mode name 'auto-minor-mode-magic-alist arg rest state))
|
||||
|
||||
(defalias 'use-package-normalize/:defer-incrementally #'use-package-normalize-symlist)
|
||||
(defun use-package-handler/:defer-incrementally (name _keyword targets rest state)
|
||||
|
|
|
@ -200,9 +200,11 @@ should be activated. If they are *all* true, NAME is activated.
|
|||
Relevant: `doom-project-hook'."
|
||||
(declare (indent 1))
|
||||
(let ((init-var (intern (format "%s-init" name))))
|
||||
`(progn
|
||||
,(if on-load `(defvar ,init-var nil))
|
||||
(define-minor-mode ,name
|
||||
(macroexp-progn
|
||||
(append
|
||||
(when on-load
|
||||
`((defvar ,init-var nil)))
|
||||
`((define-minor-mode ,name
|
||||
"A project minor mode generated by `def-project-mode!'."
|
||||
:init-value nil
|
||||
:lighter ""
|
||||
|
@ -215,15 +217,30 @@ Relevant: `doom-project-hook'."
|
|||
,on-load
|
||||
(setq ,init-var t)))
|
||||
,on-enter))
|
||||
,@(cl-loop for hook in add-hooks
|
||||
collect `(add-hook ',(intern (format "%s-hook" name))
|
||||
#',hook))
|
||||
,(when (or modes match files when)
|
||||
`(associate! ,name
|
||||
:modes ,modes
|
||||
:match ,match
|
||||
:files ,files
|
||||
:when ,when)))))
|
||||
(dolist (hook ,add-hooks)
|
||||
(add-hook ',(intern (format "%s-hook" name)) hook)))
|
||||
(cond ((or files modes when)
|
||||
(cl-check-type files (or null list string))
|
||||
(let ((fn `(lambda ()
|
||||
(and (not (bound-and-true-p ,name))
|
||||
(and buffer-file-name (not (file-remote-p buffer-file-name nil t)))
|
||||
,(or (null match)
|
||||
`(if buffer-file-name (string-match-p ,match buffer-file-name)))
|
||||
,(or (null files)
|
||||
(doom--resolve-path-forms
|
||||
(if (stringp (car files)) (cons 'and files) files)
|
||||
'(doom-project-root)))
|
||||
,(or when t)
|
||||
(,name 1)))))
|
||||
`((dolist (mode ,modes)
|
||||
(let ((hook-name (intern (format "doom--enable-%s%s-h" ',name
|
||||
(if (eq mode t) "" (format "-in-" mode))))))
|
||||
(fset hook-name #',fn)
|
||||
(if (eq mode t)
|
||||
(add-to-list 'auto-minor-mode-magic-alist (cons hook-name #',name))
|
||||
(add-hook (intern (format "%s-hook" mode)) hook-name)))))))
|
||||
(match
|
||||
`((add-to-list 'auto-minor-mode-alist (cons ,match #',name)))))))))
|
||||
|
||||
(provide 'core-projects)
|
||||
;;; core-projects.el ends here
|
||||
|
|
27
core/core.el
27
core/core.el
|
@ -299,33 +299,6 @@ users).")
|
|||
(add-hook 'focus-out-hook #'garbage-collect)
|
||||
|
||||
|
||||
;;
|
||||
;;; Minor mode version of `auto-mode-alist'
|
||||
|
||||
(defvar doom-auto-minor-mode-alist '()
|
||||
"Alist mapping filename patterns to corresponding minor mode functions, like
|
||||
`auto-mode-alist'. All elements of this alist are checked, meaning you can
|
||||
enable multiple minor modes for the same regexp.")
|
||||
|
||||
(defun doom-enable-minor-mode-maybe-h ()
|
||||
"Check file name against `doom-auto-minor-mode-alist'."
|
||||
(when (and buffer-file-name doom-auto-minor-mode-alist)
|
||||
(let ((name buffer-file-name)
|
||||
(remote-id (file-remote-p buffer-file-name))
|
||||
(alist doom-auto-minor-mode-alist))
|
||||
;; Remove backup-suffixes from file name.
|
||||
(setq name (file-name-sans-versions name))
|
||||
;; Remove remote file name identification.
|
||||
(when (and (stringp remote-id)
|
||||
(string-match (regexp-quote remote-id) name))
|
||||
(setq name (substring name (match-end 0))))
|
||||
(while (and alist (caar alist) (cdar alist))
|
||||
(if (string-match-p (caar alist) name)
|
||||
(funcall (cdar alist) 1))
|
||||
(setq alist (cdr alist))))))
|
||||
(add-hook 'find-file-hook #'doom-enable-minor-mode-maybe-h)
|
||||
|
||||
|
||||
;;
|
||||
;;; MODE-local-vars-hook
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
;; core.el
|
||||
(package! dotenv-mode)
|
||||
(package! auto-minor-mode)
|
||||
|
||||
;; core-ui.el
|
||||
(package! all-the-icons)
|
||||
|
@ -44,6 +45,3 @@
|
|||
|
||||
;; autoload/debug.el
|
||||
(package! esup)
|
||||
|
||||
;; cli/test.el
|
||||
(package! buttercup)
|
||||
|
|
|
@ -62,5 +62,5 @@
|
|||
(add-to-list 'auto-mode-alist '("\\.shader$" . shader-mode))
|
||||
|
||||
(def-project-mode! +csharp-unity-mode
|
||||
:modes (csharp-mode shader-mode)
|
||||
:modes '(csharp-mode shader-mode)
|
||||
:files (and "Assets" "Library/MonoManager.asset" "Library/ScriptMapper")))
|
||||
|
|
|
@ -38,3 +38,4 @@
|
|||
(def-project-mode! +data-vagrant-mode
|
||||
:files ("Vagrantfile"))
|
||||
|
||||
|
||||
|
|
|
@ -125,18 +125,16 @@ This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
|
|||
(advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update))
|
||||
|
||||
|
||||
(def-package! buttercup
|
||||
:defer t
|
||||
:minor ("/test[/-].+\\.el$" . buttercup-minor-mode)
|
||||
:config (set-yas-minor-mode! 'buttercup-minor-mode))
|
||||
|
||||
|
||||
;;
|
||||
;;; Project modes
|
||||
|
||||
(def-project-mode! +emacs-lisp-ert-mode
|
||||
:modes (emacs-lisp-mode)
|
||||
:modes '(emacs-lisp-mode)
|
||||
:match "/test[/-].+\\.el$"
|
||||
:add-hooks (overseer-enable-mode))
|
||||
|
||||
(associate! buttercup-minor-mode
|
||||
:modes (emacs-lisp-mode)
|
||||
:match "/test[/-].+\\.el$")
|
||||
|
||||
(after! buttercup
|
||||
(set-yas-minor-mode! 'buttercup-minor-mode))
|
||||
|
||||
:add-hooks '(overseer-enable-mode))
|
||||
|
|
|
@ -11,3 +11,5 @@
|
|||
|
||||
(when (featurep! :tools flycheck)
|
||||
(package! flycheck-cask))
|
||||
|
||||
(package! buttercup)
|
||||
|
|
|
@ -250,9 +250,9 @@ to tide."
|
|||
;;; Projects
|
||||
|
||||
(def-project-mode! +javascript-npm-mode
|
||||
:modes (html-mode css-mode web-mode typescript-mode js2-mode rjsx-mode json-mode markdown-mode)
|
||||
:modes '(html-mode css-mode web-mode typescript-mode js2-mode rjsx-mode json-mode markdown-mode)
|
||||
:when (locate-dominating-file default-directory "package.json")
|
||||
:add-hooks (+javascript|add-node-modules-path npm-mode))
|
||||
:add-hooks '(+javascript|add-node-modules-path npm-mode))
|
||||
|
||||
(def-project-mode! +javascript-gulp-mode
|
||||
:when (locate-dominating-file default-directory "gulpfile.js"))
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
;;; Frameworks
|
||||
|
||||
(def-project-mode! +lua-love-mode
|
||||
:modes (moonscript-mode lua-mode markdown-mode json-mode)
|
||||
:modes '(moonscript-mode lua-mode markdown-mode json-mode)
|
||||
:when #'+lua-love-project-root
|
||||
:on-load
|
||||
(progn
|
||||
|
|
|
@ -96,10 +96,9 @@
|
|||
;; Projects
|
||||
|
||||
(def-project-mode! +php-laravel-mode
|
||||
:modes (php-mode yaml-mode web-mode nxml-mode js2-mode scss-mode)
|
||||
:modes '(php-mode yaml-mode web-mode nxml-mode js2-mode scss-mode)
|
||||
:files (and "artisan" "server.php"))
|
||||
|
||||
(def-project-mode! +php-composer-mode
|
||||
:modes (web-mode php-mode)
|
||||
:modes '(web-mode php-mode)
|
||||
:files ("composer.json"))
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ called.")
|
|||
(def-package! nose
|
||||
:commands nose-mode
|
||||
:preface (defvar nose-mode-map (make-sparse-keymap))
|
||||
:init (associate! nose-mode :match "/test_.+\\.py$" :modes (python-mode))
|
||||
:minor-mode ("/test_.+\\.py$" . nose-mode)
|
||||
:config
|
||||
(set-popup-rule! "^\\*nosetests" :size 0.4 :select nil)
|
||||
(set-yas-minor-mode! 'nose-mode)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
;; Framework-based minor-modes
|
||||
|
||||
(def-project-mode! +web-jekyll-mode
|
||||
:modes (web-mode js-mode coffee-mode css-mode haml-mode pug-mode)
|
||||
:modes '(web-mode js-mode coffee-mode css-mode haml-mode pug-mode)
|
||||
:files (and (or "_config.yml" "_config.toml")
|
||||
(or "_layouts/" "_posts/"))
|
||||
:on-enter
|
||||
|
@ -30,18 +30,18 @@
|
|||
(web-mode-set-engine "django")))
|
||||
|
||||
(def-project-mode! +web-wordpress-mode
|
||||
:modes (php-mode web-mode css-mode haml-mode pug-mode)
|
||||
:modes '(php-mode web-mode css-mode haml-mode pug-mode)
|
||||
:files (or "wp-config.php" "wp-config-sample.php"))
|
||||
|
||||
(when (featurep! :lang javascript)
|
||||
(def-project-mode! +web-angularjs-mode
|
||||
:modes (+javascript-npm-mode)
|
||||
:modes '(+javascript-npm-mode)
|
||||
:when (+javascript-npm-dep-p 'angular))
|
||||
|
||||
(def-project-mode! +web-react-mode
|
||||
:modes (+javascript-npm-mode)
|
||||
:modes '(+javascript-npm-mode)
|
||||
:when (+javascript-npm-dep-p 'react))
|
||||
|
||||
(def-project-mode! +web-phaser-mode
|
||||
:modes (+javascript-npm-mode)
|
||||
:modes '(+javascript-npm-mode)
|
||||
:when (+javascript-npm-dep-p '(or phaser phaser-ce))))
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
:mode "\\.j2$")
|
||||
|
||||
(def-project-mode! +ansible-yaml-mode
|
||||
:modes (yaml-mode)
|
||||
:add-hooks (ansible ansible-auto-decrypt-encrypt ansible-doc-mode)
|
||||
:modes '(yaml-mode)
|
||||
:add-hooks '(ansible ansible-auto-decrypt-encrypt ansible-doc-mode)
|
||||
:files ("roles/"))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue