Better Lisp Editing with major-mode-hydra
This commit is contained in:
		
							parent
							
								
									8857e1f6ef
								
							
						
					
					
						commit
						815f86fd87
					
				
					 3 changed files with 70 additions and 58 deletions
				
			
		| 
						 | 
					@ -42,11 +42,11 @@ I'm not trying an experiment where specially-placed function keys on my fancy er
 | 
				
			||||||
      :keymaps 'override
 | 
					      :keymaps 'override
 | 
				
			||||||
      :prefix "SPC"
 | 
					      :prefix "SPC"
 | 
				
			||||||
      :non-normal-prefix "M-SPC"
 | 
					      :non-normal-prefix "M-SPC"
 | 
				
			||||||
      :prefix "<f13>")
 | 
					      :global-prefix "<f13>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (general-create-definer ha-local-leader
 | 
					    (general-create-definer ha-local-leader
 | 
				
			||||||
      :states '(normal visual motion)
 | 
					      :states '(normal visual motion)
 | 
				
			||||||
      :global-prefix "<f17>")
 | 
					      :prefix "<f17>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (general-nmap "SPC m" (general-simulate-key "," :which-key "major mode")))
 | 
					    (general-nmap "SPC m" (general-simulate-key "," :which-key "major mode")))
 | 
				
			||||||
#+end_src
 | 
					#+end_src
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,23 +132,26 @@ My primary use-case is for its refactoring and other unique features. For instan
 | 
				
			||||||
          "gF" '("ace symbol" . lispy-ace-symbol)
 | 
					          "gF" '("ace symbol" . lispy-ace-symbol)
 | 
				
			||||||
          (kbd "M-v") '("mark s-exp" . lispy-mark)))   ; Mark entire s-expression
 | 
					          (kbd "M-v") '("mark s-exp" . lispy-mark)))   ; Mark entire s-expression
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (ha-local-leader :keymaps '(emacs-lisp-mode-map lisp-mode-map)
 | 
					      (pretty-hydra-define lispy-debug nil
 | 
				
			||||||
      "r"  '(:ignore t :which-key "refactor")
 | 
					        ("Debug"
 | 
				
			||||||
      "r i" '("cond→if" . lispy-to-ifs)
 | 
					         (("d" lispy-edebug "Start")
 | 
				
			||||||
      "r c" '("if→cond" . lispy-to-cond)
 | 
					          ("j" lispy-debug-step-in "Jump in")
 | 
				
			||||||
      "r d" '("λ→𝑓" . lispy-to-defun)
 | 
					          ("r" lispy-eval-and-replace "Eval/Replace"))
 | 
				
			||||||
      "r l" '("𝑓→λ" . lispy-to-lambda)
 | 
					         "Instrument"
 | 
				
			||||||
      "r f" '("flatten" . lispy-flatten)
 | 
					         (("f" (eval-defun t) "Function"))
 | 
				
			||||||
      "r b" '("bind var" . lispy-bind-variable)
 | 
					         ))
 | 
				
			||||||
      "r u" '("unbind var" . lispy-unbind-variable)
 | 
					 | 
				
			||||||
      "r >" '("to thread last" . lispy-toggle-thread-last)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      "e d" '("edebug" . lispy-edebug)
 | 
					      (pretty-hydra-define lisp-refactor nil
 | 
				
			||||||
      "e j" '("debug-step-in" . lispy-debug-step-in)
 | 
					        ("To"
 | 
				
			||||||
      "e R" '("eval-and-replace" . lispy-eval-and-replace)
 | 
					         (("i" lispy-to-ifs "cond→if")
 | 
				
			||||||
 | 
					          ("c" lispy-to-cond "if→cond")
 | 
				
			||||||
      "d d" '("describe" . lispy-describe)
 | 
					          ("t" lispy-toggle-thread-last "to thread")
 | 
				
			||||||
      "t t" '("ert" . lispy-ert)))
 | 
					          ("d" lispy-to-defun "λ→𝑓")
 | 
				
			||||||
 | 
					          ("l" lispy-to-lambda "𝑓→λ"))
 | 
				
			||||||
 | 
					         "Convert"
 | 
				
			||||||
 | 
					         (("F" lispy-flatten "flatten")
 | 
				
			||||||
 | 
					          ("b" lispy-bind-variable "bind var")
 | 
				
			||||||
 | 
					          ("B" lispy-unbind-variable "unbind var")))))
 | 
				
			||||||
#+end_src
 | 
					#+end_src
 | 
				
			||||||
** Lispyville
 | 
					** Lispyville
 | 
				
			||||||
I want an Evil version of [[Lispy]]. The [[https://github.com/noctuid/lispyville][lispyville project]] builds on it to make it Evil. From the README:
 | 
					I want an Evil version of [[Lispy]]. The [[https://github.com/noctuid/lispyville][lispyville project]] builds on it to make it Evil. From the README:
 | 
				
			||||||
| 
						 | 
					@ -273,21 +276,22 @@ These are all good, but the primary keys I need to figure out, are the s-express
 | 
				
			||||||
** Refactoring
 | 
					** Refactoring
 | 
				
			||||||
Wilfred’s [[https://github.com/Wilfred/emacs-refactor/tree/master#elisp][emacs-refactor]] package can be helpful if you turn on =context-menu-mode= and …
 | 
					Wilfred’s [[https://github.com/Wilfred/emacs-refactor/tree/master#elisp][emacs-refactor]] package can be helpful if you turn on =context-menu-mode= and …
 | 
				
			||||||
#+begin_src emacs-lisp
 | 
					#+begin_src emacs-lisp
 | 
				
			||||||
  (use-package emacs-refactor
 | 
					  (use-package emr
 | 
				
			||||||
    :general
 | 
					    ;; :straight (:host github :repo "Wilfred/emacs-refactor")
 | 
				
			||||||
    (:states '(normal visual) :keymaps 'emacs-lisp-mode-map
 | 
					    :config
 | 
				
			||||||
             ;; Often know what functions are available:
 | 
					    (pretty-hydra-define+ lisp-refactor nil
 | 
				
			||||||
             ", r r" '("refactor menu" . emr-show-refactor-menu)
 | 
					      ("To 𝛌"
 | 
				
			||||||
             ;; These are my favorites ...
 | 
					       (;; Often know what functions are available:
 | 
				
			||||||
 | 
					        ("a" emr-show-refactor-menu "all")
 | 
				
			||||||
        ;; Extracts the current s-expression or region to function:
 | 
					        ;; Extracts the current s-expression or region to function:
 | 
				
			||||||
             ", r F" '("to function" . emr-el-extract-function)
 | 
					        ("f" emr-el-extract-function "to function")
 | 
				
			||||||
             ", r V" '("to variable" . emr-el-extract-variable)
 | 
					        ("v" emr-el-extract-variable "to variable")
 | 
				
			||||||
        ;; Converts the current let to a let*
 | 
					        ;; Converts the current let to a let*
 | 
				
			||||||
             ", r *" '("toggle let*" . emr-el-toggle-let*)
 | 
					        ("*" emr-el-toggle-let* "toggle let*")
 | 
				
			||||||
        ;; asks for a variable, and extracts the code in a region
 | 
					        ;; asks for a variable, and extracts the code in a region
 | 
				
			||||||
        ;; or the current s-expression, into the nearest let binding
 | 
					        ;; or the current s-expression, into the nearest let binding
 | 
				
			||||||
             ", r l" '("to let" . emr-el-extract-to-let)))
 | 
					        ("L" emr-el-extract-to-let "to let")))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#+end_src
 | 
					#+end_src
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The idea of stealing some of Clojure Mode’s refactoring is brilliant (see [[https://isamert.net/2023/08/14/elisp-editing-development-tips.html#clojure-thread-lastfirst-all-from-https-github-com-clojure-emacs-clojure-mode-clojure-mode][the original idea]]), however, I’m already using Lispy’s =toggle-thread-last=.
 | 
					The idea of stealing some of Clojure Mode’s refactoring is brilliant (see [[https://isamert.net/2023/08/14/elisp-editing-development-tips.html#clojure-thread-lastfirst-all-from-https-github-com-clojure-emacs-clojure-mode-clojure-mode][the original idea]]), however, I’m already using Lispy’s =toggle-thread-last=.
 | 
				
			||||||
| 
						 | 
					@ -332,14 +336,22 @@ And we just need to bind it.
 | 
				
			||||||
  (ha-local-leader :keymaps '(emacs-lisp-mode-map lisp-mode-map)
 | 
					  (ha-local-leader :keymaps '(emacs-lisp-mode-map lisp-mode-map)
 | 
				
			||||||
    "e e" '("current" . ha-eval-current-expression))
 | 
					    "e e" '("current" . ha-eval-current-expression))
 | 
				
			||||||
#+end_src
 | 
					#+end_src
 | 
				
			||||||
** Debugging
 | 
					* Minor Mode Hydra
 | 
				
			||||||
The =edebug= debugger is built into Emacs, so all I need is an easier way to instrument a function:
 | 
					put it all together
 | 
				
			||||||
#+begin_src emacs-lisp
 | 
					#+begin_src emacs-lisp
 | 
				
			||||||
  (ha-local-leader :keymaps '(emacs-lisp-mode-map lisp-mode-map)
 | 
					  (use-package major-mode-hydra
 | 
				
			||||||
    "e D" '("set edebug" . (lambda ()
 | 
					    :config
 | 
				
			||||||
                             (interactive)
 | 
					    (major-mode-hydra-define emacs-lisp-mode nil
 | 
				
			||||||
                             (setq current-prefix-arg '(4)) ; C-u
 | 
					      ("Evaluating"
 | 
				
			||||||
                             (call-interactively 'eval-defun))))
 | 
					       (("e" ha-eval-current-expression "Current")
 | 
				
			||||||
 | 
					        ("d" lispy-debug/body "Debugging")
 | 
				
			||||||
 | 
					        ("f" eval-defun "Function")
 | 
				
			||||||
 | 
					        ("b" eval-buffer "Buffer"))
 | 
				
			||||||
 | 
					       "Editing"
 | 
				
			||||||
 | 
					       (("r" lisp-refactor/body "Refactoring"))
 | 
				
			||||||
 | 
					       "Documentation"
 | 
				
			||||||
 | 
					       (("a" elisp-demos-add-demo "Add Demo")
 | 
				
			||||||
 | 
					        ("H" suggest "Suggestions")))))
 | 
				
			||||||
#+end_src
 | 
					#+end_src
 | 
				
			||||||
* Technical Artifacts                                :noexport:
 | 
					* Technical Artifacts                                :noexport:
 | 
				
			||||||
Let's =provide= a name so we can =require= this file:
 | 
					Let's =provide= a name so we can =require= this file:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,15 +106,15 @@ I’m interested in using [[https://devdocs.io/][devdocs]] instead, which is sim
 | 
				
			||||||
                      "gD" '("devdocs" . devdocs-lookup))
 | 
					                      "gD" '("devdocs" . devdocs-lookup))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    :config
 | 
					    :config
 | 
				
			||||||
    (ha-local-leader :keymaps 'prog-mode-map
 | 
					    (major-mode-hydra-define emacs-lisp-mode nil
 | 
				
			||||||
      "d"  '(:ignore t :which-key "docs")
 | 
					      ("Dev Docs"
 | 
				
			||||||
      "d e" '("eldoc" . eldoc)
 | 
					       (("e" eldoc "eldoc")
 | 
				
			||||||
      "d d" '("open" . devdocs-lookup)
 | 
					        ("d" devdocs-lookup "open")
 | 
				
			||||||
      "d p" '("peruse" . devdocs-peruse)
 | 
					        ("p" devdocs-peruse "peruse")
 | 
				
			||||||
      "d i" '("install" . devdocs-install)
 | 
					        ("i" devdocs-install "install")
 | 
				
			||||||
      "d u" '("update" . devdocs-update-all)
 | 
					        ("u" devdocs-update-all "update")
 | 
				
			||||||
      "d x" '("uninstall" . devdocs-delete)
 | 
					        ("x" devdocs-delete "uninstall")
 | 
				
			||||||
      "d s" '("search" . devdocs-search)))
 | 
					        ("s" devdocs-search "search")))))
 | 
				
			||||||
#+end_src
 | 
					#+end_src
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The [[https://github.com/blahgeek/emacs-devdocs-browser][devdocs-browser]] project acts similar, but with slightly different command names. Its advantage is that it allows for downloading docs and having it available offline, in fact, you can’t search for a function, until you download its pack. This is slightly faster because of this.
 | 
					The [[https://github.com/blahgeek/emacs-devdocs-browser][devdocs-browser]] project acts similar, but with slightly different command names. Its advantage is that it allows for downloading docs and having it available offline, in fact, you can’t search for a function, until you download its pack. This is slightly faster because of this.
 | 
				
			||||||
| 
						 | 
					@ -689,7 +689,7 @@ I like =comment-dwim= (~M-;~), and I like =comment-box=, but I have an odd perso
 | 
				
			||||||
      (widen)))
 | 
					      (widen)))
 | 
				
			||||||
#+end_src
 | 
					#+end_src
 | 
				
			||||||
And a keybinding:
 | 
					And a keybinding:
 | 
				
			||||||
#+begin_src emacs-lisp
 | 
					#+begin_src emacs-lisp :tangle no
 | 
				
			||||||
  (ha-local-leader :keymaps 'prog-mode-map
 | 
					  (ha-local-leader :keymaps 'prog-mode-map
 | 
				
			||||||
    "c"  '(:ignore t :which-key "comment")
 | 
					    "c"  '(:ignore t :which-key "comment")
 | 
				
			||||||
    "c l" '("comment line" . ha-comment-line))
 | 
					    "c l" '("comment line" . ha-comment-line))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue