Emacsist RSS --- If never, make it ever: C-h C-h

Commands to thread and unwind code in Emacs-Lisp

7290

这里 查看更多 Emacs 相关推荐文章最新 Emacs 圈的动态. 欢迎关注微信公众账号: Emacsist

As you may remember, one of the commands I like the most from theclj-refactor package are the ones that thread and unwind Clojure code forms for you. Now that Emacs is also getting built-in threading macros, I figured the best way to give them a fair chance in life is to also make them pretty convenient to use.

The point here is that you can place point before a paren, invoke a command, and a regular code form gets transformed into a threading macro, or vice-versa. See the linked post for what that means. Instead of writing whole new commands for that, I had a fun time just hackingclj-refactor commands to work on thread-first/last.

It should go without saying, you need clj-refactor installed for this to work.

(define-key emacs-lisp-mode-map "\C-ctf"
  #'endless/elisp-thread-first)
(define-key emacs-lisp-mode-map "\C-ctl"
  #'endless/elisp-thread-last)
(define-key emacs-lisp-mode-map "\C-ctu"
  #'endless/elisp-unwind)
(define-key emacs-lisp-mode-map "\C-cta"
  #'endless/elisp-unwind-all)

(defun endless/elisp-thread-last ()
  "Turn the form at point into a `thread-last' form."
  (interactive)
  (cljr-thread-last-all nil)
  (save-excursion
    (when (search-backward "->>" nil 'noerror)
      (replace-match "thread-last"))))

(defun endless/elisp-thread-first ()
  "Turn the form at point into a `thread-first' form."
  (interactive)
  (cljr-thread-first-all nil)
  (save-excursion
    (when (search-backward "->" nil 'noerror)
      (replace-match "thread-first"))))

(defun endless/elisp-unwind ()
  "Unwind thread at point or above point by one level.
Return nil if there are no more levels to unwind."
  (interactive)
  (let ((p (point)))
    ;; Find a thread above.
    (when (save-excursion
            (forward-sexp 1)
            (and (search-backward-regexp "\\_<thread-\\(first\\|last\\)\\_>" nil 'noerror)
                 ;; Ensure that it contains the original point.
                 (save-match-data (forward-char -1)
                                  (forward-sexp 1)
                                  (> (point) p))))
      (replace-match (if (string= (match-string 1) "first")
                         "->" "->>"))
      (let ((thread-beginnig (match-beginning 0)))
        (prog1 (cljr-unwind)
          (save-excursion
            (goto-char thread-beginnig)
            (when (looking-at "\\_<->>?\\_>")
              (replace-match (if (string= (match-string 0) "->")
                                 "thread-first" "thread-last")))))))))

(defun endless/elisp-unwind-all ()
  "Fully unwind thread at point or above point."
  (interactive)
  (while (endless/elisp-unwind)))

Maybe just writing it from scratch would have made for shorter code (it would certainly be more robust). But such is life. I try not to dwell too much on quick hacks.

原文出处: EndlessParenthese
原文地址: http://endlessparentheses.com/commands-to-thread-and-unwind-code-in-emacs-lisp.html?source=rss
原文时间: 2016-03-01 08:00
本文地址: http://emacsist.com/10787
整理时间: 2016-03-03 02:03

本文由 Hick 整理,转载请保留以上信息;
COPYLEFTThe articles on this site come from Internet, thanks to all the original authors.
      If anything about COPYRIGHT, or LEFT, please contact Emacsist at gmail dot com .