diff --git a/core/autoload/debug.el b/core/autoload/debug.el index 38e23ad29..38a38900a 100644 --- a/core/autoload/debug.el +++ b/core/autoload/debug.el @@ -341,10 +341,10 @@ Some items are not supported by the `nsm.el' module." (delete-file file) (signal (car e) (cdr e))))))) -(fset 'doom--run-vanilla-emacs (lambda! (doom--run-sandbox 'vanilla))) -(fset 'doom--run-vanilla-doom (lambda! (doom--run-sandbox 'vanilla-doom))) -(fset 'doom--run-vanilla-doom+ (lambda! (doom--run-sandbox 'vanilla-doom+))) -(fset 'doom--run-full-doom (lambda! (doom--run-sandbox 'doom))) +(fset 'doom--run-vanilla-emacs (cmd! (doom--run-sandbox 'vanilla))) +(fset 'doom--run-vanilla-doom (cmd! (doom--run-sandbox 'vanilla-doom))) +(fset 'doom--run-vanilla-doom+ (cmd! (doom--run-sandbox 'vanilla-doom+))) +(fset 'doom--run-full-doom (cmd! (doom--run-sandbox 'doom))) (defvar doom-sandbox-emacs-lisp-mode-map (let ((map (make-sparse-keymap))) diff --git a/core/core-lib.el b/core/core-lib.el index b505a9070..6f2811aeb 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -139,24 +139,6 @@ at the values with which this function was called." ;; ;;; Sugars -(defmacro λ! (&rest body) - "Expands to (lambda () (interactive) ,@body). -A factory for quickly producing interaction commands, particularly for keybinds -or aliases." - (declare (doc-string 1) (pure t) (side-effect-free t)) - `(lambda (&rest _) (interactive) ,@body)) -(defalias 'lambda! 'λ!) - -(defun λ!! (command &optional arg) - "Expands to a command that interactively calls COMMAND with prefix ARG. -A factory for quickly producing interactive, prefixed commands for keybinds or -aliases." - (declare (doc-string 1) (pure t) (side-effect-free t)) - (lambda (&rest _) (interactive) - (let ((current-prefix-arg arg)) - (call-interactively command)))) -(defalias 'lambda!! 'λ!!) - (defun dir! () "Returns the directory of the emacs lisp file this macro is called from." (when-let (path (file!)) @@ -256,6 +238,40 @@ See `if!' for details on this macro's purpose." (declare (indent defun) (doc-string 1) (pure t) (side-effect-free t)) `(cl-function (lambda ,arglist ,@body))) +(defmacro cmd! (&rest body) + "Expands to (lambda () (interactive) ,@body). +A factory for quickly producing interaction commands, particularly for keybinds +or aliases." + (declare (doc-string 1) (pure t) (side-effect-free t)) + `(lambda (&rest _) (interactive) ,@body)) + +(defmacro cmd!! (command &rest args) + "Expands to a closure that interactively calls COMMAND with ARGS. +A factory for quickly producing interactive, prefixed commands for keybinds or +aliases." + (declare (doc-string 1) (pure t) (side-effect-free t)) + `(lambda (&rest _) (interactive) + (funcall-interactively ,command ,@args))) + +(defmacro cmds! (&rest branches) + "Expands to a `menu-item' dispatcher for keybinds." + (declare (doc-string 1)) + (let ((docstring (if (stringp (car branches)) (pop branches) "")) + fallback) + (when (cl-oddp (length branches)) + (setq fallback (car (last branches)) + branches (butlast branches))) + `(general-predicate-dispatch ,fallback + :docstring ,docstring + ,@branches))) + +;; For backwards compatibility +(defalias 'λ! 'cmd!) +(defalias 'λ!! 'cmd!!) +;; DEPRECATED These have been superseded by `cmd!' and `cmd!!' +(define-obsolete-function-alias 'lambda! 'cmd! "3.0.0") +(define-obsolete-function-alias 'lambda!! 'cmd!! "3.0.0") + ;;; Mutation (defmacro appendq! (sym &rest lists) diff --git a/docs/api.org b/docs/api.org index 350249303..583841b11 100644 --- a/docs/api.org +++ b/docs/api.org @@ -18,8 +18,8 @@ It is integrated into Helpful, in Doom. - [[#disable-packages][disable-packages!]] - [[#doom][doom!]] - [[#file-exists-p][file-exists-p!]] - - [[#lambda][lambda!]] - - [[#lambda-1][lambda!!]] + - [[#cmd][cmd!]] + - [[#cmd-1][cmd!!]] - [[#letenv][letenv!]] - [[#load][load!]] - [[#map][map!]] @@ -238,38 +238,30 @@ It is integrated into Helpful, in Doom. #+RESULTS: : /home/hlissner/.emacs.d/LICENSE -*** lambda! +*** cmd! #+BEGIN_SRC elisp :eval no -(map! "C-j" (lambda! (newline) (indent-according-to-mode))) - -;; The `λ!' short-form alias exists. If you have the snippets module enabled and -;; Doom's default snippets, the 'lam' snippet will expand into 'λ!'. Otherwise, -;; you can use `lambda!'. -(map! "C-j" (λ! (newline) (indent-according-to-mode))) +(map! "C-j" (cmd! (newline) (indent-according-to-mode))) #+END_SRC -*** lambda!! + +*** cmd!! When ~newline~ is passed a numerical prefix argument (=C-u 5 M-x newline=), it -inserts N newlines. We can use ~lambda!!~ to easily create a keybinds that bakes -in the prefix arg into the command call: +inserts N newlines. We can use ~cmd!!~ to easily create a keybinds that bakes in +the prefix arg into the command call: #+BEGIN_SRC elisp :eval no -(map! "C-j" (lambda!! #'newline 5)) - -;; The `λ!!' short-form alias exists. If you have the snippets module enabled -;; and Doom's default snippets, a 'lam' snippet is available to expand into -;; 'λ!'. Otherwise, you can use `lambda!!'. -(map! "C-j" (λ!! #'newline 5)) +(map! "C-j" (cmd!! #'newline 5)) #+END_SRC Or to create aliases for functions that behave differently: #+BEGIN_SRC elisp :eval no -(fset 'insert-5-newlines (lambda!! #'newline 5)) +(fset 'insert-5-newlines (cmd!! #'newline 5)) ;; The equivalent of C-u M-x org-global-cycle, which resets the org document to ;; its startup visibility settings. -(fset 'org-reset-global-visibility (lambda!! #'org-global-cycle '(4)) +(fset 'org-reset-global-visibility (cmd!! #'org-global-cycle '(4)) #+END_SRC + *** letenv! #+BEGIN_SRC elisp (letenv! (("SHELL" "/bin/sh")) diff --git a/modules/config/default/+emacs-bindings.el b/modules/config/default/+emacs-bindings.el index f8e9ec800..05a5f526c 100644 --- a/modules/config/default/+emacs-bindings.el +++ b/modules/config/default/+emacs-bindings.el @@ -120,7 +120,7 @@ ;;; i --- insert (:prefix-map ("i" . "insert") :desc "Current file name" "f" #'+default/insert-file-path - :desc "Current file path" "F" (λ!! #'+default/insert-file-path t) + :desc "Current file path" "F" (cmd!! #'+default/insert-file-path t) :desc "Snippet" "s" #'yas-insert-snippet :desc "Unicode" "u" #'unicode-chars-list-chars :desc "From clipboard" "y" #'+default/yank-pop) @@ -412,7 +412,7 @@ ;;; Text scaling [C-mouse-4] #'text-scale-increase [C-mouse-5] #'text-scale-decrease - [C-down-mouse-2] (λ! (text-scale-set 0)) + [C-down-mouse-2] (cmd! (text-scale-set 0)) "M-+" #'doom/reset-font-size "M-=" #'doom/increase-font-size "M--" #'doom/decrease-font-size @@ -463,7 +463,7 @@ :map company-search-map "C-n" #'company-search-repeat-forward "C-p" #'company-search-repeat-backward - "C-s" (λ! (company-search-abort) (company-filter-candidates))) + "C-s" (cmd! (company-search-abort) (company-filter-candidates))) ;;; ein notebooks (:after ein:notebook-multilang diff --git a/modules/config/default/+evil-bindings.el b/modules/config/default/+evil-bindings.el index 351e89b50..74b90c0a0 100644 --- a/modules/config/default/+evil-bindings.el +++ b/modules/config/default/+evil-bindings.el @@ -18,7 +18,7 @@ "C-u" #'evil-delete-back-to-indentation "C-v" #'yank "C-w" #'doom/delete-backward-word - "C-z" (λ! (ignore-errors (call-interactively #'undo)))) + "C-z" (cmd! (ignore-errors (call-interactively #'undo)))) (when (featurep! :editor evil +everywhere) (define-key! :keymaps +default-minibuffer-maps @@ -39,19 +39,17 @@ ;;; Global keybindings ;; Smart tab, these will only work in GUI Emacs -(map! :i [tab] (general-predicate-dispatch nil ; fall back to nearest keymap - (and (featurep! :editor snippets) - (bound-and-true-p yas-minor-mode) - (yas-maybe-expand-abbrev-key-filter 'yas-expand)) - #'yas-expand - (and (featurep! :completion company +tng) - (+company-has-completion-p)) - #'+company/complete) - :v [tab] (general-predicate-dispatch nil - (and (bound-and-true-p yas-minor-mode) - (or (eq evil-visual-selection 'line) - (not (memq (char-after) (list ?\( ?\[ ?\{ ?\} ?\] ?\)))))) - #'yas-insert-snippet) +(map! :i [tab] (cmds! (and (featurep! :editor snippets) + (bound-and-true-p yas-minor-mode) + (yas-maybe-expand-abbrev-key-filter 'yas-expand)) + #'yas-expand + (and (featurep! :completion company +tng) + (+company-has-completion-p)) + #'+company/complete) + :v [tab] (cmds! (and (bound-and-true-p yas-minor-mode) + (or (eq evil-visual-selection 'line) + (not (memq (char-after) (list ?\( ?\[ ?\{ ?\} ?\] ?\)))))) + #'yas-insert-snippet) ;; Smarter newlines :i [remap newline] #'newline-and-indent ; auto-indent on newline @@ -136,7 +134,7 @@ "C-p" #'company-select-previous-or-abort "C-j" #'company-select-next-or-abort "C-k" #'company-select-previous-or-abort - "C-s" (λ! (company-search-abort) (company-filter-candidates)) + "C-s" (cmd! (company-search-abort) (company-filter-candidates)) [escape] #'company-search-abort)) ;; TAB auto-completion in term buffers (:after comint :map comint-mode-map @@ -456,8 +454,8 @@ ;;; i --- insert (:prefix-map ("i" . "insert") :desc "Current file name" "f" #'+default/insert-file-path - :desc "Current file path" "F" (λ!! #'+default/insert-file-path t) - :desc "Evil ex path" "p" (λ! (evil-ex "R!echo ")) + :desc "Current file path" "F" (cmd!! #'+default/insert-file-path t) + :desc "Evil ex path" "p" (cmd! (evil-ex "R!echo ")) :desc "From evil register" "r" #'evil-ex-registers :desc "Snippet" "s" #'yas-insert-snippet :desc "Unicode" "u" #'unicode-chars-list-chars