Remove def-menu!; use :localleader keys instead

def-menu was clumsy. We could use a better UI for refactoring commands,
but they should be available via localleader keybinds in any case.
This commit is contained in:
Henrik Lissner 2018-09-04 03:04:00 +02:00
parent d2f9d28577
commit 84abac6b69
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
7 changed files with 77 additions and 280 deletions

View file

@ -1,122 +0,0 @@
;;; ../core/autoload/menu.el -*- lexical-binding: t; -*-
;; Command dispatchers: basically M-x, but context sensitive, customizable and
;; persistent across Emacs sessions.
(defvar doom-menu-display-fn #'doom-menu-read-default
"The method to use to prompt the user with the menu. This takes two arguments:
PROMPT (a string) and COMMAND (a list of command plists; see `def-menu!').")
(defvar-local doom-menu-last-command nil
"TODO")
(defun doom-menu-read-default (prompt commands)
"Default method for displaying a completion-select prompt."
(completing-read prompt (mapcar #'car commands) nil nil nil nil (car doom-menu-last-command)))
;;;###autoload
(defun doom--menu-read (prompt commands)
(if-let* ((choice (funcall doom-menu-display-fn prompt commands)))
(assoc choice commands)
(user-error "Aborted")))
;;;###autoload
(defun doom--menu-exec (plist)
(save-selected-window
(let ((command (plist-get plist :exec))
(cwd (plist-get plist :cwd)))
(let ((default-directory
(cond ((eq cwd t) (doom-project-root))
((stringp cwd) cwd)
((functionp cwd) (funcall cwd))
(t default-directory))))
(cond ((stringp command)
(let (buf)
(compile command)
(setq buf next-error-last-buffer)
(unless buf
(error "Couldn't create compilation buffer"))
(with-current-buffer buf
(setq header-line-format
(concat (propertize "$ " 'face 'font-lock-doc-face)
(propertize command 'face 'font-lock-preprocessor-face))))))
((or (symbolp command)
(functionp command))
(call-interactively command))
((and command (listp command))
(eval command t))
(t
(error "Not a valid command: %s" command)))))))
;;;###autoload
(defmacro def-menu! (name desc commands &rest plist)
"Defines a menu and returns a function symbol for invoking it.
A dispatcher is an interactive command named NAME (a symbol). When called, this
dispatcher prompts you to select a command to run. This list is filtered
depending on its properties. Each command is takes the form of:
(DESCRIPTION :exec COMMAND &rest PROPERTIES)
PROPERTIES accepts the following properties:
:when FORM
:unless FORM
:region BOOL
:cwd BOOL|PATH|FUNCTION
:project BOOL|PATH|FUNCTION
COMMAND can be a string (a shell command), a symbol (an elisp function) or a
lisp form.
`def-menu!'s PLIST supports the following properties:
:prompt STRING"
(declare (indent defun) (doc-string 2))
(let ((commands-var (intern (format "%s-commands" name)))
(prop-prompt (or (plist-get plist :prompt) "> "))
(prop-sort (plist-get plist :sort)))
`(progn
(defconst ,commands-var
,(if prop-sort
`(cl-sort ,commands #'string-lessp :key #'car)
commands)
,(format "Menu for %s" name))
(defun ,name (arg command)
,(concat
(if (stringp desc) (concat desc "\n\n"))
"This is a command dispatcher. It will rerun the last command on\n"
"consecutive executions. If ARG (universal argument) is non-nil\n"
"then it always prompt you.")
(declare (interactive-only t))
(interactive
(list current-prefix-arg
(progn
(unless ,commands-var
(user-error "The '%s' menu is empty" ',name))
(doom--menu-read
,prop-prompt
(or (cl-remove-if-not
(let ((project-root (doom-project-root)))
(lambda (cmd)
(let ((plist (cdr cmd)))
(and (cond ((not (plist-member plist :region)) t)
((plist-get plist :region) (use-region-p))
(t (not (use-region-p))))
(let ((when (plist-get plist :when))
(unless (plist-get plist :unless))
(project (plist-get plist :project)))
(when (functionp project)
(setq project (funcall project)))
(or (or (not when) (eval when))
(or (not unless) (not (eval unless)))
(and (stringp project)
(file-in-directory-p (or buffer-file-name default-directory)
project-root))))))))
,commands-var)
(user-error "No commands available here"))))))
(doom--menu-exec
(cdr (or (when arg doom-menu-last-command)
(setq doom-menu-last-command command)
(user-error "No command selected"))))))))

View file

@ -21,51 +21,35 @@
(add-hook 'go-mode-hook #'go-eldoc-setup)
(def-menu! +go/refactor-menu
"Refactoring commands for `go-mode' buffers."
'(("Add import" :exec go-import-add :region nil)
("Remove unused imports" :exec go-remove-unused-imports :region nil)
("Format buffer (gofmt)" :exec go-gofmt))
:prompt "Refactor: ")
(def-menu! +go/build-menu
"Build/compilation commands for `go-mode' buffers."
'(("Build project" :exec "go build")
("Build & run project" :exec "go run")
("Clean files" :exec "go clean"))
:prompt "Run test: ")
(def-menu! +go/test-menu
"Test commands for `go-mode' buffers."
'(("Last test" :exec +go/test-rerun)
("All tests" :exec +go/test-all)
("Single test" :exec +go/test-single)
("Nested test" :exec +go/test-nested))
:prompt "Run test: ")
(def-menu! +go/help-menu
"Help and information commands for `go-mode' buffers."
'(("Go to imports" :exec go-goto-imports)
("Lookup in godoc" :exec godoc-at-point)
("Describe this" :exec go-guru-describe)
("List free variables" :exec go-guru-freevars)
("What does this point to" :exec go-guru-pointsto)
("Implements relations for package types" :exec go-guru-implements :region nil)
("List peers for channel" :exec go-guru-peers)
("List references to object" :exec go-guru-referrers)
("Which errors" :exec go-guru-whicerrs)
("What query" :exec go-guru-what)
("Show callers of this function" :exec go-guru-callers :region nil)
("Show callees of this function" :exec go-guru-callees :region nil)))
(map! :map go-mode-map
:localleader
:nr "r" #'+go/refactor-menu
:n "b" #'+go/build-menu
:n "h" #'+go/help-menu
:n "t" #'+go/test-menu
:n "r" #'go-play-buffer
:v "r" #'go-play-region))
:v "r" #'go-play-region
:n "i" #'go-goto-imports ; Go to imports
(:prefix "h"
:n "." #'godoc-at-point ; Lookup in godoc
:n "d" #'go-guru-describe ; Describe this
:n "v" #'go-guru-freevars ; List free variables
:n "i" #'go-guru-implements ; Implements relations for package types
:n "p" #'go-guru-peers ; List peers for channel
:n "P" #'go-guru-pointsto ; What does this point to
:n "r" #'go-guru-referrers ; List references to object
:n "e" #'go-guru-whicherrs ; Which errors
:n "w" #'go-guru-what ; What query
:n "c" #'go-guru-callers ; Show callers of this function
:n "C" #'go-guru-callees) ; Show callees of this function
(:prefix "r"
:n "ia" #'go-import-add
:n "ir" #'go-remove-unused-imports)
(:prefix "b"
:n "r" (λ! (compile "go run"))
:n "b" (λ! (compile "go build"))
:n "c" (λ! (compile "go clean")))
(:prefix "t"
:n "t" #'+go/test-rerun
:n "a" #'+go/test-all
:n "s" #'+go/test-single
:n "n" #'+go/test-nested)))
(def-package! gorepl-mode

View file

@ -16,39 +16,31 @@
help-at-pt-timer-delay 0.1)
(help-at-pt-set-timer)
;;
(def-menu! +java/refactor-menu
"Refactoring commands for `java-mode' buffers."
'(("Generate constructor" :exec eclim-java-constructor)
("Generate getter & setter" :exec eclim-java-generate-getter-and-setter)
("Organize imports" :exec eclim-java-import-organize)
("Reformat" :exec eclim-java-format)
("Rename symbol at point" :exec eclim-java-refactor-rename-symbol-at-point :region nil)))
(def-menu! +java/help-menu
"Help and information commands for `java-mode' buffers."
'(("Find documentation for current element" :exec eclim-java-show-documentation-for-current-element)
("Find references" :exec eclim-java-find-references)
("View call hierarchy" :exec eclim-java-call-hierarchy)
("View hierarchy" :exec eclim-java-hierarchy)
("View problems" :exec eclim-problems)))
(def-menu! +java/project-menu
"Building/compilation commands for `java-mode' buffers."
'(("Build project" :exec eclim-project-build)
("Create project" :exec eclim-project-create)
("Delete project" :exec eclim-project-delete)
("Go to project" :exec eclim-project-goto)
("Import project" :exec eclim-project-import)
("Close project" :exec eclim-project-close)
("Open project" :exec eclim-project-open)
("Update project" :exec eclim-project-update)))
(map! :map java-mode-map
:localleader
"r" #'+java/refactor-menu
"c" #'+java/compile-menu
"p" #'+java/project-menu))
(:prefix "r"
:n "gc" #'eclim-java-constructor
:n "gg" #'eclim-java-generate-getter-and-setter
:n "oi" #'eclim-java-import-organize
:n "f" #'eclim-java-format
:n "r" #'eclim-java-refactor-rename-symbol-at-point)
(:prefix "h"
:n "." #'eclim-java-show-documentation-for-current-element
:n "r" #'eclim-java-find-references
:n "c" #'eclim-java-call-hierarchy
:n "h" #'eclim-java-hierarchy
:n "p" #'eclim-problems
:n "r" #'meghanada-reference
:n "t" #'meghanada-typeinfo)
(:prefix "b"
:n "b" #'eclim-project-build
:n "c" #'eclim-project-create
:n "d" #'eclim-project-delete
:n "g" #'eclim-project-goto
:n "i" #'eclim-project-import
:n "k" #'eclim-project-close
:n "o" #'eclim-project-open
:n "u" #'eclim-project-update)))
(def-package! company-emacs-eclim

View file

@ -14,26 +14,16 @@
:definition #'meghanada-jump-declaration
:references #'meghanada-reference)
;;
(def-menu! +java/refactor-menu
"Refactoring commands for `java-mode' buffers."
'(("Add imports for unqualified classes" :exec meghanada-import-all)
("Optimize and clean up imports" :exec meghanada-optimize-import)
("Introduce local variable" :exec meghanada-local-variable)
("Format buffer code" :exec meghanada-code-beautify)))
(def-menu! +java/help-menu
"Help and information commands for `java-mode' buffers."
'(("Find usages" :exec meghanada-reference)
("Show type hierarchives and implemented interfaces" :exec meghanada-typeinfo)))
(def-menu! +java/project-menu
"Project commands for `java-mode' buffers."
'(("Compile current file" :exec meghanada-compile-file)
("Compile project" :exec meghanada-compile-project)))
(map! :map java-mode-map
:localleader
:nv "r" #'+java/refactor-menu
:nv "c" #'+java/compile-menu
:nv "p" #'+java/project-menu))
(:prefix "r"
:n "ia" #'meghanada-import-all
:n "io" #'meghanada-optimize-import
:n "l" #'meghanada-local-variable
:n "f" #'meghanada-code-beautify)
(:prefix "h"
:n "r" #'meghanada-reference
:n "t" #'meghanada-typeinfo)
(:prefix "b"
:n "f" #'meghanada-compile-file
:n "p" #'meghanada-compile-project)))

View file

@ -163,42 +163,12 @@
(add-hook! 'tide-mode-hook
(add-hook 'kill-buffer-hook #'+javascript|cleanup-tide-processes nil t))
(def-menu! +javascript/refactor-menu
"Refactoring commands for `js2-mode' buffers."
'(("Restart tsserver" :exec tide-restart-server :when (bound-and-true-p tide-mode))
("Reformat buffer/region (tide)" :exec tide-reformat :when (bound-and-true-p tide-mode))
("Organize imports" :exec tide-organize-imports :when (bound-and-true-p tide-mode))
("Rename symbol" :exec tide-rename-symbol :when (bound-and-true-p tide-mode) :region nil)
("Reformat buffer (eslint_d)" :exec eslintd-fix :when (bound-and-true-p eslintd-fix-mode) :region nil)
("Extract into function" :exec js2r-extract-function :region t)
("Extract into method" :exec js2r-extract-method :region t)
("Introduce parameter to function" :exec js2r-introduce-parameter :region t)
("Localize parameter" :exec js2r-localize-parameter :region nil)
("Expand object" :exec js2r-expand-object :region nil)
("Expand function" :exec js2r-expand-function :region nil)
("Expand array" :exec js2r-expand-array :region nil)
("Contract object" :exec js2r-contract-object :region nil)
("Contract function" :exec js2r-contract-function :region nil)
("Contract array" :exec js2r-contract-array :region nil)
("Wrap buffer in IIFE" :exec js2r-wrap-buffer-in-iife :region nil)
("Inject global into IIFE" :exec js2r-inject-global-in-iife :region t)
("Add to globals annotation" :exec js2r-add-to-globals-annotation :region nil)
("Extract variable" :exec js2r-extract-var :region t)
("Inline variable" :exec js2r-inline-var :region t)
("Rename variable" :exec js2r-rename-var :region nil)
("Replace var with this" :exec js2r-var-to-this :region nil)
("Arguments to object" :exec js2r-arguments-to-object :region nil)
("Ternary to if" :exec js2r-ternary-to-if :region nil)
("Split var declaration" :exec js2r-split-var-declaration :region nil)
("Split string" :exec js2r-split-string :region nil)
("Unwrap" :exec js2r-unwrap :region t)
("Log this" :exec js2r-log-this)
("Debug this" :exec js2r-debug-this))
:prompt "Refactor: ")
(map! :map tide-mode-map
:localleader
:n "r" #'+javascript/refactor-menu))
:n "R" #'tide-restart-server
:n "f" #'tide-reformat
:n "rs" #'tide-rename-symbol
:n "roi" #'tide-organize-imports))
(def-package! xref-js2
@ -208,15 +178,8 @@
(def-package! js2-refactor
:commands
(js2r-extract-function js2r-extract-method js2r-introduce-parameter
js2r-localize-parameter js2r-expand-object js2r-contract-object
js2r-expand-function js2r-contract-function js2r-expand-array
js2r-contract-array js2r-wrap-buffer-in-iife js2r-inject-global-in-iife
js2r-add-to-globals-annotation js2r-extract-var js2r-inline-var
js2r-rename-var js2r-var-to-this js2r-arguments-to-object js2r-ternary-to-if
js2r-split-var-declaration js2r-split-string js2r-unwrap js2r-log-this
js2r-debug-this js2r-forward-slurp js2r-forward-barf))
:hook ((js2-mode rjsx-mode) . js2-refactor-mode)
:config (js2r-add-keybindings-with-prefix (format "%s r" doom-localleader-key)))
(def-package! eslintd-fix

View file

@ -7,16 +7,7 @@
(set-lookup-handlers! 'lua-mode :documentation 'lua-search-documentation)
(set-electric! 'lua-mode :words '("else" "end"))
(set-repl-handler! 'lua-mode #'+lua/repl)
(set-company-backend! 'lua-mode '(company-lua company-yasnippet))
(def-menu! +lua/build-menu
"Build/compilation commands for `lua-mode' buffers."
'(("Run Love app" :exec +lua/run-love-game :when +lua-love-mode))
:prompt "Build tasks: ")
(map! :map lua-mode-map
:localleader
:n "b" #'+lua/build-menu))
(set-company-backend! 'lua-mode '(company-lua company-yasnippet)))
(after! moonscript
@ -29,5 +20,8 @@
(def-project-mode! +lua-love-mode
:modes (lua-mode markdown-mode json-mode)
:files (and "main.lua" "conf.lua"))
:files (and "main.lua" "conf.lua")
:on-load
(map! :map +lua-love-mode-map
:localleader
:n "b" #'+lua/run-love-game))

View file

@ -7,14 +7,10 @@
(map! :map rust-mode-map
:localleader
:n "b" #'+rust/build-menu)
(def-menu! +rust/build-menu
"TODO"
'(("cargo run" :exec "cargo run --color always")
("cargo build" :exec "cargo build --color always")
("cargo test" :exec "cargo test --color always"))
:prompt "Cargo: "))
:prefix "b"
:n "b" (λ! (compile "cargo build --color always"))
:n "r" (λ! (compile "cargo run --color always"))
:n "t" (λ! (compile "cargo test --color always"))))
(def-package! racer