"C-c C-b" #'elisp-byte-compile-buffer
"C-M-q" #'indent-pp-sexp
"C-c M-e" #'macrostep-expand
+ "C-c C-l" #'elisp-extract-to-local-variable
"C-c C-n" #'elisp-next-occurrence
"C-c C-p" #'elisp-prev-occurrence)
"C-n" #'elisp-next-occurrence
"C-p" #'elisp-prev-occurrence)
+(defvar avy-action)
+
+(defvar elisp-extract-local-variable-name-history nil)
+
+(defun elisp-extract-to-local-variable (beg end target var)
+ "Extract BEG to END region to local VAR bound at TARGET."
+ (interactive
+ (let ((beg (region-beginning))
+ (end (region-end))
+ (max 0)
+ (targets nil))
+ (save-excursion
+ (goto-char beg)
+ (beginning-of-defun-raw)
+ (scope (lambda (type sbeg len bin)
+ (and (<= sbeg beg)
+ (memq type '(function macro special-form top-level))
+ (push (save-excursion (nth 1 (syntax-ppss sbeg))) targets))
+ (let ((send (+ sbeg len)))
+ (and (<= beg sbeg send end) (numberp bin) (< bin beg)
+ (setq max (max max bin)))))))
+ (let* ((target
+ (if-let ((avy-action #'ignore)
+ (targets (seq-drop-while
+ (apply-partially #'> max)
+ (sort (seq-intersection
+ (nth 9 (syntax-ppss)) targets #'=)))))
+ (or (avy-process targets) (keyboard-quit))
+ (user-error "No valid targets")))
+ (tarend (save-excursion (goto-char target) (scan-sexps (point) 1)))
+ (ovbeg (make-overlay target (1+ target)))
+ (ovend (make-overlay tarend (1+ tarend))))
+ (overlay-put ovbeg 'face 'show-paren-match)
+ (overlay-put ovend 'face 'show-paren-match)
+ (list beg end target
+ (unwind-protect
+ (read-string (format-prompt "Extract region to local var called" "v")
+ nil 'elisp-extract-local-variable-name-history "v")
+ (delete-overlay ovbeg)
+ (delete-overlay ovend)))))
+ emacs-lisp-mode)
+ (let ((reg (delete-and-extract-region beg end)))
+ (goto-char beg)
+ (insert var)
+ (let ((pos (copy-marker (point))))
+ (goto-char target)
+ (pcase (save-excursion (read (current-buffer)))
+ (`(,(or 'let 'let* 'if-let* 'when-let* 'while-let*) . ,_)
+ (down-list 2)
+ (insert "(" var " " reg ")\n"))
+ (_
+ (insert "(let ((" var " " reg "))\n")
+ (goto-char (scan-sexps (point) 1))
+ (insert ")")))
+ (prog-indent-sexp 'defun)
+ (goto-char pos))))
+
\f
(put 'read-symbol-shorthands 'safe-local-variable #'consp)