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

发布于 2024-07-26 18:53:51 字数 572 浏览 8 评论 0原文

实现代码折叠或组织模式使用的循环类型等功能的最佳方法是什么? elisp 中创建此类行为的最佳解决方案是什么?

编辑: 抱歉我没说清楚。 我想在 elisp 中编写一些东西,它的功能与代码折叠非常相似,或者实际上最像具有可扩展层次结构的 org-mode。 我想知道实现这种效果的最佳方法。 我想我听说 emacs 覆盖是一个很好的解决方案,但我不知道。

至于折叠,我只使用内置的设置选择性显示

编辑编号2:

感谢您的回答,但我认为我问了错误的问题,所以让我尝试更清楚地了解我想要做什么。 我想创建以下内容

当您将您的观点放在函数上并调用此 elisp 函数时,它将把函数定义从任何位置放置(我正在考虑为此使用 find-tag )并将其展开在当前缓冲区中。 这个想法是,如果您必须跳转到不同的缓冲区来读取函数定义,我觉得它是到另一个文件的上下文切换。 所以我希望它的行为就像代码折叠一样,只是它从缓冲区外部提取代码。 这会带来一些问题,因为它实际上无法将代码粘贴到缓冲区中,或者如果有人保存,它将保存拉入的代码。 所以我想知道是否有一种方法可以在缓冲区内创建一个不属于缓冲区的区域。 我认为这是有道理的。

What's the best way to achieve something like code folding, or the type of cycling that org-mode uses. What would be the best solution in elisp to create this type of behavior?

EDIT:
I'm sorry I was not clear. I want to program something in elisp that does things very similar to code folding, or actually most like org-mode with the hierarchy that can be expanded. I am wondering the best way to achieve this effect. I think I have heard emacs overlays are a good solution, but I don't know.

As far as folding I just use the builtin set-selective-display

EDIT NUMBER 2:

Thanks for the answers but I think I am asking the wrong question so let me try to be more clear on what I am trying to do. I would like to create the following

When you put your point on a function and call this elisp function it will put the function definition from wherever it is (I am thinking of just using find-tag for this) and unfold it in the current buffer. The idea is if you have to jump to a different buffer to read the function definition I feel like it's a context switch to another file. So I would like it to behave like code folding only it pulls in code external from the buffer. This presents some problems as it can not actually paste the code into the buffer or if someone saves it will save the pulled in code. So I am wondering if there is a way to create an area inside a buffer that is also not part of the buffer. I think that makes sense.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

柳若烟 2024-08-02 18:53:51

您可以使用隐藏-显示模式(hs-minor-mode)。 要仅针对当前缓冲区动态激活此模式,请输入 Mx hs-minor-mode RET

假设您有默认的键绑定:

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

You can use the hide-show mode (hs-minor-mode). To activate this mode on the fly for the current buffer only, type M-x hs-minor-mode RET

Assuming you have the default keybinding:

  • C-c @ C-M-h To fold it all (hs-hide-all).
  • C-c @ C-h Hides the current block (hs-hide-block). The point (cursor) has to be inside the block.
  • C-c @ C-s Show current block (hs-show-block). The point has to be in the {...} marker that is hiding the code.
深陷 2024-08-02 18:53:51

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

大多数人通过简单的增量搜索就取得了巨大的成功。 看到某处提到的“foo”了吗? 输入Csfoo,找到定义,按回车键,阅读它,然后按Cx Cx返回到你所在的地方。 简单而且非常有用。

大多数模式都支持 imenuMximenu 将让您按名称跳转到函数定义(等)。 您还可以将其绑定到鼠标单击以获取功能菜单(或将其添加到菜单栏;有关更多详细信息,请参阅信息页面)。 它提供了哪个函数模式的数据,这将让您看到当前在模型行中的哪个函数。 (为什么你的函数这么长?)

还有speedbar,它以图形方式显示 imenu 信息(和其他内容)。

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

所以无论如何,想想您真正想要实现的目标,Emacs 可能会实现它。不要与那些让你不断折叠和展开东西的不完美的工具作斗争。

Folding is generally unnecessary with emacs, as it has tools that explicitly implement the actions people do manually when folding code.

Most people have good success with simple incremental searches. See "foo" mentioned somewhere? Type C-sfoo, find the definition, press enter, read it, and then press C-x C-x to go back to where you were. Simple and very useful.

Most modes support imenu. M-ximenu will let you jump to a function definition (etc.) by name. You can also bind it to a mouse click to get a menu of functions (or add it to the menubar; see the Info page for more detail). It provides data for which-function-mode, which will let you see which function you are currently inside in the modeline. (Why are your functions this long, though?)

There is also speedbar, which displays the imenu information (and other things) graphically.

If you want to get an overview of your file, try M-xoccur". Given a regex, it will create a new buffer with each match in the current buffer. You can search for "(defun" to get an overview of the functions the current file implements. Clicking on the result will move you to that position in the file.

So anyway, think about what you really want to achieve, and Emacs probably implements that. Don't fight with imperfect tools that make you fold and unfold things constantly.

无言温柔 2024-08-02 18:53:51

另一种给猫剥皮的方法:

事实上,您不需要任何软件包或额外的配置
那。 只需转到任何源文件,输入

M-1 Cx $,奇迹就发生了!

和往常一样,这是白魔法:Cx $ 将带回您的代码。

我们可以使用 Emacs 的帮助系统来发现发生了什么:Ch k Cx $
告诉我们上面的组合键正在调用
set-selective-display,一种采用一个数字参数的函数
(M-1 前缀传递 1 作为该参数的值)并且,
毫不奇怪,将变量选择显示设置为值
那个论点。

来自 小型 emacs 魔法博客

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

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))))))

Another way to skin the cat:

As it happens, you don’t need any package or extra configuration for
that. Just go to any source file, type

M-1 C-x $ and magic happens!

As usual, it’s white magic: C-x $ will bring your code back.

We can use Emacs’ help system to discover what’s going on: C-h k C-x $
tells us that the above key combination is calling
set-selective-display, a function that takes one numerical argument
(the M-1 prefix passes 1 as the value of that argument) and,
unsurprisingly, sets the variable selective-display to the value of
that argument.

from minor emacs wizardry blog

Just for completeness: M-3 C-x $ would show deeper nested code and so on.

FWIW I made a tiny helper today based on smth. found here so that F5 toggles code folding based on the current cursor position:

(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))))))
递刀给你 2024-08-02 18:53:51

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

http://www.gnu.org/software/emacs/manual/html_node/emacs/Outline-模式.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)
)

I use the outline minor mode to fold my python code. Instead of needing to place {{{ and }}} as in folding mode, it uses where the block is defined.

http://www.gnu.org/software/emacs/manual/html_node/emacs/Outline-Mode.html
http://www.emacswiki.org/emacs/OutlineMinorMode

I am pretty sure that it comes with emacs. I then add this to my .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)
)
月光色 2024-08-02 18:53:51

您还可以通过使用 CEDET 在 init 文件中使用以下代码来获得代码折叠:

(global-semantic-folding-mode t)

执行此代码后,小三角形将出现在边缘区域,因此您将能够折叠和折叠 使用它展开代码。 这种方法更精确,因为它使用从源代码中提取的语法信息

You can also get code folding by using CEDET with following code in init file:

(global-semantic-folding-mode t)

After evaluation of this code, the small triangle will appear in fringle area, so you will able to fold & unfold code using it. This method is more precise, as it uses syntactic information, extracted from source code

乱了心跳 2024-08-02 18:53:51

hs-minor-mode 工作得很好。

与 Fold-dwim 配合使用时,它的工作效果会更加出色(按照我的意思做)。 然后是fold-dwim-org,它为代码折叠提供类似组织模式的键绑定! 两者都可以通过 marmalade 安装(我认为是 elpa)。

hs-minor-mode works beautifully.

It works even more beautifully when paired with fold-dwim (do what I mean). Then there's fold-dwim-org, which provides org-mode like key-bindings for code folding! Both can be installed via marmalade (and I think elpa).

孤独陪着我 2024-08-02 18:53:51

我很惊讶没有人提到缩小-扩大。 它超级棒,它还与 emacs 捆绑在一起。 只需选择您想要关注的代码并按 Cx n n,即可返回完整视图模式,只需执行 Cx n w。 我总是更喜欢使用内置的 emacs 功能,而不是用另一个包扰乱我的用户空间。 如果 emacs 可以使用内置功能来做到这一点,那么我会更喜欢它而不是某些第三方包,但这只是我,并不意味着或暗示任何其他东西,除了我喜欢简单的东西而不是复杂的长配置。

I am surprised that noone mentioned narrowing-widening. It's super awesome, it comes bundled with emacs as well. Simply select code you want to focus on and press C-x n n, to go back to full view mode just do C-x n w. I always prefer to use built-in emacs functionality than clutter my user space with another package. If emacs can do it with built-in functionality then I'll prefer that over some third party package, but that's just me, doesn't mean or imply anything else besides that I like simple stuff over complex long configs.

会傲 2024-08-02 18:53:51

vimish-fold 也是一个很好且简单的解决方案。

https://github.com/mrkkrp/vimish-fold

从主页:

这是一个像 Vim 一样执行文本折叠的包。 它具有以下特点:

  • 折叠活动区域;
  • 良好的视觉反馈:文本的哪一部分被折叠一目了然;
  • 默认持久性:关闭文件时,折叠不会消失;
  • 持久性可以很好地扩展,您可以处理数百个具有大量折叠的文件,而不会产生不利影响;
  • 它不会破坏缩进或其他东西;
  • 折叠可以轻松地从折叠状态切换到展开状态,然后再返回;
  • 在现有折叠之间快速导航;
  • 您可以使用鼠标展开折叠(不仅适合初学者,而且适合初学者);
  • 对于 avy 软件包的粉丝:您可以使用 avy 以最少的击键次数折叠文本!

使用优秀的 use-package 我在配置中使用此代码片段安装并激活它:

(use-package vimish-fold
  :ensure t
  :config (vimish-fold-global-mode t))

vimish-fold is also a nice and easy solution.

https://github.com/mrkkrp/vimish-fold.

From the homepage:

This is a package to perform text folding like in Vim. It has the following features:

  • folding of active regions;
  • good visual feedback: it's obvious which part of text is folded;
  • persistence by default: when you close file your folds don't disappear;
  • persistence scales well, you can work on hundreds of files with lots of folds without adverse effects;
  • it doesn't break indentation or something;
  • folds can be toggled from folded state to unfolded and back very easily;
  • quick navigation between existing folds;
  • you can use mouse to unfold folds (good for beginners and not only for them);
  • for fans of avy package: you can use avy to fold text with minimal number of key strokes!

Using the excellent use-package I install and activate it using this snippet in my config:

(use-package vimish-fold
  :ensure t
  :config (vimish-fold-global-mode t))
女中豪杰 2024-08-02 18:53:51

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

http://www.emacswiki.org /emacs/FoldingMode

Apparently there is no perfect solution, but I think the best one is this:

http://www.emacswiki.org/emacs/FoldingMode

漫雪独思 2024-08-02 18:53:51

我相信您将“项目”与折叠进行比较不太好,因为折叠是在保持缓冲区内容完整(文本)的同时改变外观。 您的项目将涉及显示额外的文本,同时保持缓冲区内容完整,AFAIU。 所以。 它不能作为文本插入和折叠的组合来实现(然后,缓冲区内容将被更改)。

但也许,确实可以使用与折叠相同的机制——“覆盖”...考虑“前字符串”和“后字符串”叠加属性; 也许,您可以将函数定义放入属于此时零长度覆盖的这些字符串中。 看看 outline-flag-region 函数来查看如何在轮廓模式下使用叠加。

I believe that your comparison of your "project" to folding is not quite good, because folding is about changing the appearance while keeping the buffer contents intact (the text). Your project would involve showing extra text while keeping the buffer contents intact, AFAIU. So. it's not implementable as a composition of text-insertion and folding (then, the buffer contents would be changed).

But perhaps, it's indeed possible with the same mechanism as folding is done with -- "overlays"... Consider the "before-string" and "after-string" overlay properties; perhaps, you could put your function definitions into these strings belonging to a zero-length overlay at the point. Look at outline-flag-region function to see how overlays are used in the outline mode.

撧情箌佬 2024-08-02 18:53:51

emacs 带有 hs-minor-mode,它促进平衡表达式之间的代码折叠
http://www.emacswiki.org/emacs/HideShow

emacs comes with hs-minor-mode which fascilitates code folding between balanced expressions
http://www.emacswiki.org/emacs/HideShow

守不住的情 2024-08-02 18:53:51

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

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

If you use hs-minor-mode, it might be a good idea to also set a more convenient shortcut, e.g.:

(eval-after-load 'hideshow
 '(progn
   (global-set-key (kbd "C-+") 'hs-toggle-hiding)))
梦忆晨望 2024-08-02 18:53:51

受到 einSelbst 的回答的启发:

(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)))

瞧,即使没有任何 Cx $ 也突然变得有用Cu 也不是 M-4 业务。

With inspiration from einSelbst's answer:

(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)))

Voila, C-x $ suddenly became useful even without any C-u nor M-4 business.

余罪 2024-08-02 18:53:51

如果您正在执行一些 JavaScript 操作并使用 js2-mode.el,您可以:

Cc Cf:切换隐藏/显示全部

Cc Ce:隐藏element

Cc Cs:显示元素

If you are doing some JavaScript and using js2-mode.el, you can:

C-c C-f: toggle hide/show all

C-c C-e: hide element

C-c C-s: show element

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文