如何在 Emacs 中实现代码折叠效果?

实现代码折叠或 org-mode 使用的循环类型的最佳方法是什么。在 Elisp 中创建这种行为的最佳解决方案是什么?

编辑: 抱歉我没说清楚。我想用省略号编写一些程序,这些程序与代码折叠非常相似,或者实际上最像组织模式(org-mode) ,其层次结构可以扩展。我想知道达到这种效果的最佳方法。我想我听说过 emacs 覆盖是一个很好的解决方案,但我不知道。

至于折叠,我只是使用内置的集-选择-显示

编辑2:

谢谢你的回答,但我认为我问错了问题,所以让我试着更清楚我正在努力做什么。我想创建以下内容

当你把你的点放在一个函数上并调用这个 elisp 函数时,它会把函数定义放在它所在的地方(我想只用 find-tag 来做这个) ,并在当前缓冲区中展开它。这个想法是,如果你必须跳转到一个不同的缓冲区来阅读函数定义,我觉得这是一个上下文切换到另一个文件。所以我希望它的行为像代码折叠一样,只是它从缓冲区外部拉入代码。这就出现了一些问题,因为它实际上不能将代码粘贴到缓冲区中,或者如果有人保存它将保存提取的代码。所以我想知道是否有一种方法可以在缓冲区中创建一个区域,而这个区域也不是缓冲区的一部分。我觉得有道理。

57759 次浏览

显然没有完美的解决方案,但我认为最好的解决方案是这样的:

Http://www.emacswiki.org/emacs/foldingmode

我使用大纲次要模式折叠 Python 代码。它不需要像在折叠模式中那样放置\{\{ and }}} ,而是使用定义块的位置。

Http://www.gnu.org/software/emacs/manual/html_node/emacs/outline-mode.html Http://www.emacswiki.org/emacs/outlineminormode

我非常确定它是与 emacs 一起提供的。然后我将它添加到我的.emacs 中

;;======= Code folding =======
(add-hook 'python-mode-hook 'my-python-outline-hook)
; this gets called by outline to deteremine the level. Just use the length of the whitespace
(defun py-outline-level ()
(let (buffer-invisibility-spec)
(save-excursion
(skip-chars-forward "    ")
(current-column))))
; this get called after python mode is enabled
(defun my-python-outline-hook ()
; outline uses this regexp to find headers. I match lines with no indent and indented "class"
; and "def" lines.
(setq outline-regexp "[^ \t]\\|[ \t]*\\(def\\|class\\) ")
; enable our level computation
(setq outline-level 'py-outline-level)
; do not use their \C-c@ prefix, too hard to type. Note this overides some bindings.
(setq outline-minor-mode-prefix "\C-t")
; turn on outline mode
(outline-minor-mode t)
; initially hide all but the headers
;(hide-body)
; make paren matches visible
(show-paren-mode 1)
)

你也可以通过在 init 文件中使用以下代码来进行代码折叠:

(global-semantic-folding-mode t)

在评估这个代码后,小三角形将出现在边缘区域,所以你可以折叠和展开代码使用它。这种方法更加精确,因为它使用从源代码中提取的语法信息

您可以使用 躲猫猫模式(hs-minor-mode)。若要动态激活当前缓冲区的此模式,请键入 M-x hs-minor-mode RET

假设您有默认的密钥绑定:

  • 全部折叠(hs-hide-all)。
  • 隐藏当前块(hs-hide-block)。点(光标)必须在块内。
  • 显示当前块(hs-show-block)。该点必须位于隐藏代码的 {...}标记中。

对于 emacs,折叠通常是不必要的,因为它有一些工具可以显式实现人们在折叠代码时手动执行的操作。

大多数人通过简单的增量搜索获得了很好的成功。看到“ foo”这个词了吗?键入 C-sfoo,找到定义,按回车键,读取它,然后按 C-xC-x返回到您所在的位置。简单又有用。

大多数模式支持 菜单M-ximenu允许您通过名称跳转到函数定义(等)。您还可以将它绑定到鼠标单击来获得一个函数菜单(或者将它添加到菜单栏; 请参阅信息页面了解更多细节)。它为 which-function-mode 提供数据,这将让您看到当前在 model 中的哪个函数。(不过你的功能为什么这么长?)

还有 快捷键,它以图形方式显示菜单信息(和其他内容)。

如果您想获得文件的概述,请尝试 M-xoccur”。给定一个正则表达式,它将为当前缓冲区中的每个匹配项创建一个新缓冲区。您可以搜索“(defun)”以获得当前文件实现的函数的概述。单击结果会将您移动到文件中的该位置。

不管怎样,想想你真正想要实现的是什么,Emacs 可能会实现它。不要用那些不完美的工具去战斗,因为它们会让你不断地折叠和展开东西。

Emacs 带有 hs-small-mode,它使平衡表达式之间的代码折叠更加方便 Http://www.emacswiki.org/emacs/hideshow

我相信您的“项目”与折叠的比较不是很好,因为折叠是关于在保持缓冲区内容(文本)完整的同时改变外观。您的项目将涉及显示额外的文本,同时保持缓冲区内容完整,AFAIU。那么。它不能作为文本插入和折叠的组合来实现(那样,缓冲区内容就会发生变化)。

但是也许,这确实是可能的,就像折叠的机制一样——“叠加”... 考虑“ before-string”和“ after-string”覆盖属性; 也许,你可以把你的函数定义放到这些字符串中,这些字符串属于零长度的叠加。查看 轮廓-旗帜-区域函数,了解如何在轮廓模式中使用覆盖图。

Hs-小调模式工作得很好。

如果配上折叠机构,效果会更好(照我说的做)。然后还有 old-dwim-org,它提供了类似于 org 模式的密钥绑定,用于代码折叠!两者都可以通过果酱安装(我认为 elpa)。

另一种剥猫皮的方法:

碰巧,您不需要任何包或额外的配置 打开任何源文件,输入

M-1 C-x $ 然后奇迹发生了!

像往常一样,这是白色魔法: C-x $会把你的代码带回来。

我们可以使用 Emacs 的帮助系统来发现正在发生的事情: C-h k C-x $ 告诉我们上面的组合键正在调用 Set-select-display ,一个带有一个数值参数的函数 (M-1前缀传递1作为该参数的值) , 不出所料,将变量 select-display 的值设置为 那个论点。

小 Emacs 魔法博客

只是为了完整性: M-3 C-x $将显示更深的嵌套代码等等。

FWIW 我今天在 smth 的基础上做了一个小小的助手。找到 给你,以便 F5根据当前光标位置切换代码折叠:

(global-set-key (kbd "<f5>") 'set-selective-display-dlw)


(defun set-selective-display-dlw (&optional level)
"Fold text indented same of more than the cursor.
If level is set, set the indent level to LEVEL.
If 'selective-display' is already set to LEVEL, clicking
F5 again will unset 'selective-display' by setting it to 0."
(interactive "P")
(if (eq selective-display (1+ (current-column)))
(set-selective-display 0)
(set-selective-display (or level (1+ (current-column))))))

如果你使用 hs-minor-mode,最好也设置一个更方便的快捷方式,例如:

(eval-after-load 'hideshow
'(progn
(global-set-key (kbd "C-+") 'hs-toggle-hiding)))

来自 自己的回答的灵感:

(advice-add 'set-selective-display
:filter-args (lambda (args)
(if (or (car args) selective-display)
args
(list (1+ (current-column)))))
'((name . set-selective-display-from-cursor-column)))

瞧,即使没有 C-uM-4业务,C-x $突然变得有用了。

我很惊讶竟然没有人提到缩小-扩大。超级棒,还附带了 Emacs。简单地选择代码,你想集中和按 C-x n n,回到全视图模式只要做 C-x n w。我总是更喜欢使用内置的 emacs 功能,而不是用另一个软件包来打乱我的用户空间。如果 emacs 可以通过内置功能来实现,那么相对于某些第三方软件包,我更喜欢它,但这只是我个人的想法,并不意味着或暗示其他任何东西,除此之外,我喜欢简单的东西胜过复杂的长配置。

如果你正在使用一些 JavaScript 和 js2-mode.el,你可以:

C-c C-f: 切换隐藏/显示所有

隐藏元素

显示元素