diff --git a/core/core-lib.el b/core/core-lib.el index 5bbb7e5f3..2dc21ace7 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -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. diff --git a/core/core-modules.el b/core/core-modules.el index 83fa0d35d..2453f861e 100644 --- a/core/core-modules.el +++ b/core/core-modules.el @@ -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: ;; -;; :after-call SYMBOL|LIST -;; :defer-incrementally SYMBOL|LIST|t -;; ;; Check out `def-package!'s documentation for more about these two. +;; :after-call SYMBOL|LIST +;; :defer-incrementally SYMBOL|LIST|t +;; +;; 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) diff --git a/core/core-projects.el b/core/core-projects.el index 38f679161..3f09b9de9 100644 --- a/core/core-projects.el +++ b/core/core-projects.el @@ -200,30 +200,47 @@ 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 - "A project minor mode generated by `def-project-mode!'." - :init-value nil - :lighter "" - :keymap (make-sparse-keymap) - (if (not ,name) - ,on-exit - (run-hook-with-args 'doom-project-hook ',name ,name) - ,(when on-load - `(unless ,init-var - ,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))))) + (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 "" + :keymap (make-sparse-keymap) + (if (not ,name) + ,on-exit + (run-hook-with-args 'doom-project-hook ',name ,name) + ,(when on-load + `(unless ,init-var + ,on-load + (setq ,init-var t))) + ,on-enter)) + (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 diff --git a/core/core.el b/core/core.el index b5238d23b..80ed6d957 100644 --- a/core/core.el +++ b/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 diff --git a/core/packages.el b/core/packages.el index ff81b783a..a1c5c6d60 100644 --- a/core/packages.el +++ b/core/packages.el @@ -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) diff --git a/modules/lang/csharp/config.el b/modules/lang/csharp/config.el index cb8e40aae..50ec7bd0e 100644 --- a/modules/lang/csharp/config.el +++ b/modules/lang/csharp/config.el @@ -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"))) diff --git a/modules/lang/data/config.el b/modules/lang/data/config.el index c18fb15a9..38982b7cc 100644 --- a/modules/lang/data/config.el +++ b/modules/lang/data/config.el @@ -38,3 +38,4 @@ (def-project-mode! +data-vagrant-mode :files ("Vagrantfile")) + diff --git a/modules/lang/emacs-lisp/config.el b/modules/lang/emacs-lisp/config.el index e33ba9279..d65baa920 100644 --- a/modules/lang/emacs-lisp/config.el +++ b/modules/lang/emacs-lisp/config.el @@ -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)) diff --git a/modules/lang/emacs-lisp/packages.el b/modules/lang/emacs-lisp/packages.el index 52ca5e6c5..5f7405ac1 100644 --- a/modules/lang/emacs-lisp/packages.el +++ b/modules/lang/emacs-lisp/packages.el @@ -11,3 +11,5 @@ (when (featurep! :tools flycheck) (package! flycheck-cask)) + +(package! buttercup) diff --git a/modules/lang/javascript/config.el b/modules/lang/javascript/config.el index 29ecfd456..717cec403 100644 --- a/modules/lang/javascript/config.el +++ b/modules/lang/javascript/config.el @@ -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")) diff --git a/modules/lang/lua/config.el b/modules/lang/lua/config.el index e2c849787..629c7b443 100644 --- a/modules/lang/lua/config.el +++ b/modules/lang/lua/config.el @@ -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 diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index 55a01fe46..c2e25cc53 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -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")) - diff --git a/modules/lang/python/config.el b/modules/lang/python/config.el index beea30ecb..f76e3feb4 100644 --- a/modules/lang/python/config.el +++ b/modules/lang/python/config.el @@ -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) diff --git a/modules/lang/web/config.el b/modules/lang/web/config.el index 7a9b96f05..5941210b5 100644 --- a/modules/lang/web/config.el +++ b/modules/lang/web/config.el @@ -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)))) diff --git a/modules/tools/ansible/config.el b/modules/tools/ansible/config.el index 97ab196c7..276d377f0 100644 --- a/modules/tools/ansible/config.el +++ b/modules/tools/ansible/config.el @@ -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/"))