如何使Emacs解开代码块?

时间:2020-03-05 18:55:02  来源:igfitidea点击:

假设我在emacs缓冲区中有一行如下所示:

foo -option1 value1 -option2 value2 -option3 value3 \
    -option4 value4 ...

我希望它看起来像这样:

foo -option1 value1 \
    -option2 value2 \
    -option3 value3 \
    -option4 value4 \
    ...

我希望每个选项/值对在单独的行上。我还希望根据模式适当缩进那些后续行,而不是添加固定量的空格。我希望代码在当前块上运行,在第一条非空白行或者不包含选项/值对的行上停止,尽管我可以选择在选定区域上运行。

有人知道elisp函数可以做到这一点吗?

解决方案

回答

在这种情况下,我将使用宏。我们可以开始使用C-x录制宏,然后停止使用C-x录制宏。当我们想重播宏时,请键入C-x e。

在这种情况下,我将键入C-a C-x(C-s v alue C-f C-f \ RET SPC SPC SPC SPC C-x)

这将记录一个宏,该宏搜索"值",前进2,插入斜杠和换行符,最后将新行排成一行。然后,我们可以重复此宏几次。

编辑:我刚刚意识到,文字文本可能不像" value1"那样容易搜索。我们也可以搜索空格并在命中之间循环。例如,在第一个比赛后击中C-几次,以跳过某些比赛。

注意:由于示例是"临时"的,因此此解决方案也是。当我们需要临时解决方案时,通常会使用宏。使宏更一致地应用的一种方法是将原始语句全部放在一行上(也可以通过宏或者手动完成)。

编辑:感谢我们对(与C-()的评论,我们是对的,我的错!

回答

就我个人而言,我一直都在做这样的事情。

但是除非我会写一个函数,否则我不会写
每天一年。

我们可以使用query-replace轻松完成此操作,如下所示:

m-x(查询替换" -option"" ^ Q ^ J -option")

我说^ Q ^ J是因为我们要输入这行以引用换行符并将其放入
字符串。

然后只需按" y"替换字符串,然后按" n"跳过奇怪的字符串
我们会发现的极端情况。

另一个主要功能是可以执行的query-replace-regexp
正则表达式的替换。

还有grep-query-replace,它将通过解析执行查询替换
grep命令的输出。这很有用,因为我们可以搜索
100个文件中的" foo",然后在每次出现时进行查询替换
从一个文件跳到另一个文件。

回答

模式可能已经支持此功能。在C模式和Makefile模式下,至少M-q(填充段)将在填充列中插入行延续并换行。

我们以什么模式编辑它?

回答

没有人得到我想要的东西,所以我决定除掉自己的elisp手册,自己动手做。尽管输出结果与我要求的不完全相同,但这似乎效果很好。在此版本中,第一个选项本身排在一行上,而不是像我最初的问题那样停留在第一行上。

(defun tcl-multiline-options ()
  "spread option/value pairs across multiple lines with continuation characters"
  (interactive)
  (save-excursion
    (tcl-join-continuations)
    (beginning-of-line)
    (while (re-search-forward " -[^ ]+ +"  (line-end-position) t)
      (goto-char (match-beginning 0))
      (insert " \\n")
      (goto-char (+(match-end 0) 3))
      (indent-according-to-mode)
      (forward-sexp))))

(defun tcl-join-continuations ()
  "join multiple continuation lines into a single physical line"
  (interactive)
  (while (progn (end-of-line) (char-equal (char-before) ?\))
    (forward-line 1))
  (while (save-excursion (end-of-line 0) (char-equal (char-before) ?\))
    (end-of-line 0)
    (delete-char -1)
    (delete-char 1)
    (fixup-whitespace)))