实现代码折叠或 org-mode 使用的循环类型的最佳方法是什么。 elisp 中创建这种行为的最佳解决方案是什么?
编辑:对不起,我不清楚。我想在 elisp 中编写一些与代码折叠非常相似的东西,或者实际上最像 org-mode 具有可以扩展的层次结构。我想知道实现这种效果的最佳方法。我想我听说 emacs 覆盖是一个很好的解决方案,但我不知道。
至于折叠,我只使用内置的 set-selective-display
编辑编号 2:
感谢您的回答,但我认为我问错了问题,所以让我试着更清楚地了解我想要做什么。我想创建以下
当你把你的观点放在一个函数上并调用这个 elisp 函数时,它将把函数定义放在它所在的任何地方(我正在考虑只使用 find-tag )并在当前缓冲区中展开它。这个想法是,如果您必须跳转到不同的缓冲区来读取函数定义,我觉得这是到另一个文件的上下文切换。所以我希望它表现得像代码折叠一样,只是它从缓冲区外部提取代码。这会带来一些问题,因为它实际上无法将代码粘贴到缓冲区中,或者如果有人保存它将保存拉入的代码。所以我想知道是否有一种方法可以在缓冲区内创建一个也不属于缓冲区的区域。我认为这是有道理的。
EDIT NB 2
并为它提出一个新问题。
emacs 通常不需要折叠,因为它具有明确实现人们在折叠代码时手动执行的操作的工具。
大多数人通过简单的增量搜索取得了很好的成功。看到某处提到的“foo”吗?键入 Csfoo
,找到定义,按 Enter 键,阅读它,然后按 Cx Cx 回到原来的位置。简单而且非常有用。
大多数模式都支持 imenu。 Mximenu
将让您按名称跳转到函数定义(等)。您还可以将其绑定到鼠标单击以获取功能菜单(或将其添加到菜单栏;有关详细信息,请参阅信息页面)。它提供了 which-function-mode 的数据,这将让你看到你当前在模式行中的哪个函数。 (不过,为什么你的函数这么长?)
还有速度条,它以图形方式显示 imenu 信息(和其他内容)。
如果您想获得文件的概览,请尝试 Mxoccur
"。给定一个正则表达式,它将为当前缓冲区中的每个匹配项创建一个新缓冲区。您可以搜索“(defun " 以获得当前文件实现的功能的概述。单击结果会将您移动到文件中的该位置。
所以无论如何,想想你真正想要实现的目标,Emacs 可能会实现它。不要与不完美的工具作斗争,这些工具会让你不断地折叠和展开事物。
您可以使用 hide-show 模式 (hs-minor-mode
)。要仅为当前缓冲区动态激活此模式,请键入 M-x hs-minor-mode RET
假设您有默认的键绑定:
抄送@CMh 全部折叠(hs-hide-all)。
Cc @Ch 隐藏当前块(hs-hide-block)。点(光标)必须在块内。
Cc @Cs 显示当前块(hs-show-block)。该点必须位于隐藏代码的 {...} 标记中。
zR
、zM
、zo
、zc
。
另一种给猫剥皮的方法:
碰巧的是,您不需要任何软件包或额外的配置。只需转到任何源文件,键入
M-1 Cx $ 奇迹发生了!
像往常一样,这是白魔法:Cx $ 将带回您的代码。
我们可以使用 Emacs 的帮助系统来发现发生了什么: Ch k Cx $ 告诉我们上面的组合键正在调用 set-selective-display,这是一个接受一个数字参数的函数(M-1 前缀传递 1 作为值该参数的值),并且不出所料地将变量选择性显示设置为该参数的值。
只是为了完整性: M-3 Cx $ 会显示更深的嵌套代码等等。
FWIW 我今天基于 smth 做了一个小帮手。找到 here 以便 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))))))
我使用大纲次要模式来折叠我的 python 代码。它不需要像折叠模式那样放置 {{{ 和 }}},而是使用定义块的位置。
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)
)
outline-mode
在 emacs 24 中支持 python 开箱即用 - 不需要自定义 outline-level
函数。这就是我需要添加到我的 user.el
的全部内容:(add-hook 'python-mode-hook 'outline-minor-mode)
outline-minor-mode-prefix
- 默认键绑定很糟糕 - 我使用 (setq outline-minor-mode-prefix (kbd "C-;"))
您还可以通过在初始化文件中使用带有以下代码的 CEDET 来获得代码折叠:
(global-semantic-folding-mode t)
评估此代码后,小三角形将出现在边缘区域,因此您可以使用它折叠和展开代码。这种方法更精确,因为它使用从源代码中提取的句法信息
hs-minor-mode 效果很好。
与 fold-dwim 搭配使用时效果更佳(按我的意思做)。然后是 fold-dwim-org,它为代码折叠提供了类似 org-mode 的键绑定!两者都可以通过果酱安装(我认为是 elpa)。
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))
我很惊讶没有人提到收窄。它非常棒,它还与 emacs 捆绑在一起。只需选择您要关注的代码并按 C-x n n
,只需执行 C-x n w
即可返回全视图模式。我总是更喜欢使用内置的 emacs 功能,而不是用另一个包来混乱我的用户空间。如果 emacs 可以使用内置功能做到这一点,那么我会更喜欢它而不是一些第三方包,但这只是我,并不意味着或暗示任何其他东西,除了我喜欢简单的东西而不是复杂的长配置。
我相信您将“项目”与折叠的比较不是很好,因为折叠是关于在保持缓冲区内容(文本)完整的同时改变外观。您的项目将涉及在保持缓冲区内容完整的同时显示额外的文本,AFAIU。所以。它不能作为文本插入和折叠的组合来实现(然后,缓冲区内容将被更改)。
但也许,确实有可能使用与折叠相同的机制——“覆盖”......考虑“前字符串”和“后字符串”overlay properties;也许,您可以将您的函数定义放入这些属于零长度覆盖的字符串中。查看 outline-flag-region 函数以了解在大纲模式中如何使用叠加层。
如果您使用 hs-minor-mode
,最好设置一个更方便的快捷方式,例如:
(eval-after-load 'hideshow
'(progn
(global-set-key (kbd "C-+") 'hs-toggle-hiding)))
来自 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)))
瞧,即使没有任何 C-u
或 M-4
业务,C-x $
也会突然变得有用。
如果您正在执行一些 JavaScript 并使用 js2-mode.el
,您可以:
C-c C-f
:切换隐藏/全部显示
C-c C-e
:隐藏元素
C-c C-s
:显示元素
不定期副业成功案例分享