在Emacs中重构

Dev*_*n M 7 emacs refactoring

我正在努力将代码分成更小的文件并重构一下.请考虑以下代码作为我要提取的部分:

(require 'package)
(add-to-list 'package-archives
             '("marmalade" . "http://marmalade-repo.org/packages/") t)
(package-initialize)
(when (not package-archive-contents)
  (package-refresh-contents))

(defvar my-packages '(org magit)
  "A list of packages to ensure are installed at launch.")

(dolist (p my-packages)
  (when (not (package-installed-p p))
    (package-install p)))
Run Code Online (Sandbox Code Playgroud)
  • 我想采取上面的部分,并用类似的东西替换它 (require `file-name)
  • 然后取出替换的文本并将其放在名为当前目录的新文件中 file-name.el
  • 然后在文件顶部添加一行 (provides `file-name)

如果我能敲击键盘然后输入一个名字就会发生这种情况会很棒.如果有一个简单的方法可以做到这一点,那么我很想听听可能的解决方案.

编辑: 我正在开始赏金,因为我认为这适用于比Lisp更多类型的代码,我想有一些更普遍的东西,我可以扩展.

我考虑过yasnippet,但我认为它不足以执行手头的任务.基本上理想的工作流程是标记要提取的行,用适当的require或include指令替换它,并将文本发送到它自己的文件.理想情况下,一个命令和一些知道正在编辑的文件类型或至少是主要模式以便行为可以自定义的东西,yasnippet再次擅长在不同主要模式下编辑时执行不同的任务但是我不知道如何使工作或评估使其工作的可能性.

如果您需要更多信息,请与我们联系.

Tho*_*mas 10

这类问题的一般解决方案是键盘宏(不要与(Emacs)LISP宏混淆).基本上,Emacs允许您记录一系列击键并在之后"回放".在编写自定义LISP代码似乎过度的情况下,这可以是一个非常方便的工具.

例如,您可以创建以下键盘宏(在左侧键入组合键,右侧显示每个键击的说明):

C-x (                            ; start recording a keyboard macro
C-x h                            ; mark whole buffer
C-w                              ; kill region
(require 'file-name)             ; insert a require statement into the buffer
C-x C-s                          ; save buffer
C-x C-f                          ; find file
file-name.el <RET>               ; specify the name of the file
M-<                              ; move to the beginning of the buffer
C-u C-y                          ; insert the previously killed text, leaving point where it is
(provide 'file-name) <RET> <RET> ; insert a provide statement into the buffer
C-x )                            ; stop recording the keyboard macro
Run Code Online (Sandbox Code Playgroud)

现在,您可以通过键入在其他缓冲区中重新播放该宏C-x e,或将其保存以供以后使用.您也可以像处理函数一样将宏绑定到快捷方式.

但是,这种方法存在一个缺点:您希望能够实际指定文件名,而不是每次都使用字符串"file-name".这是一个有点困难-默认情况下,键盘宏用于查询用户提供没有通常的设施(除了极少的C-x q,如记录在这里).

然而,Emacs Wiki有一些解决方法,而不是在迷你缓冲区中提示用户,有时通过终止当前行并将其文本保存到寄存器来启动宏是足够的.

C-x (
C-e C-<SPC> C-a    ; mark current line
C-x r s T          ; copy line to register T
C-k C-k            ; kill current line
...                ; actual macro
C-x )
Run Code Online (Sandbox Code Playgroud)

现在,当您想要使用宏时,首先在空行中写入所需的文件名,然后C-x e在该行中执行.只要宏中需要文件名的值,您就可以从寄存器T中检索它:

C-x r i T          ; insert file-name into buffer
Run Code Online (Sandbox Code Playgroud)

例如,对于provide上面宏中的语句,您可以写:(provide ' C-x r i T ).请注意,此技术(插入)也适用于迷你缓冲区,当然您可以将多行保存到不同的寄存器中.

可能听起来很复杂,但实际上很容易.


hua*_*uan 4

稍微测试了一下:

(defun extract-to-package (name start end)
  (interactive (list (read-string "Package name to create: ")
                     (region-beginning) (region-end)))
  (let ((snip (buffer-substring start end)))
    (delete-region start end)
    (insert (format "(require '%s)\n" name))
    (with-current-buffer (find-file-noselect (concat name ".el"))
      (insert snip)
      (insert (format "(provide '%s)\n" name))
      (save-buffer))))
Run Code Online (Sandbox Code Playgroud)