怎么用hideshow折叠python代码?

大家好~ 今天发现用hideshow只能折叠def跟class,if之类好像折不了

hs-special-modes-alist打出来看发现python是这样的

(python-mode "\\s-*\\_<\\(?:def\\|class\\)\\_>" "" "#" python-hideshow-forward-sexp-function nil)

试着魔改成这个正则

"\\s-*\\_<\\(?:def\\|class\\|if\\|elif\\|else\\|for\\|try\\|except\\)\\_>"

但是好像还是不work

本来想试试是怎么匹配的

(match-string "\\s-*\\_<\\(?:def\\|class\\)\\_>" "class")

然而会这么报错

eval: Wrong type argument: fixnump, "\\s-*\\_<\\(?:def\\|class\\)\\_>"

请教如何调教这个speical-modes-list以及这个是个什么正则?

是每个语言都有一个 hide show forward/backward 的规则吗?利用好这个可以做不少事耶!

关键在于 python-hideshow-forward-sexp-function。在 defif 前面各运行一次就知道为什么不 work 了。

用错了函数,正确应该是 string-match

是的,但是一个major mode只能有一个正则规则

我有段逻辑需要找当前代码块的范围。感觉这个正合适。

直接去看hideshow源码了。

貌似python.el会在auto-load的时候写这个alist 之后 prog-mode-hook会执行(hs-grok-mode-type),hs会缓存这个正则

单纯魔改add-to-list,是不行的。因为在打开buffer里的还是原来那个正则

(defvar my/py-hide-show-keywords '("class" "def" "elif" "else" "except"
                                   "for" "if" "while" "finally" "try" "with"))
(defun my/replace-hs-spectial ()
  (setq hs-special-modes-alist
        (remove-if #'(lambda (x) (equal 'python-mode (car x)))
                   hs-special-modes-alist))
  (push (list
         'python-mode
         (mapconcat #'(lambda (x) (concat "^\\s-*" x "\\>"))
                    my/py-hide-show-keywords "\\|")
         nil
         "#"
         #'(lambda (x) (python-nav-end-of-block))
         nil)
        hs-special-modes-alist))
(add-hook 'python-mode-hook 'my/replace-hs-spectial)

找到了一封 2009 年给 xemacs 提 PR 的邮件 [Python-mode] hide-show support enabled with python-mode.el,也是关于给 python mode 增加可折叠的关键词的,不过好像也不可行了。

看了下 hs-special-modes-alist 的值,第一个 python-mode 是 hideshow 自带的规则,第二个 python-mode 是来自那个 PR 的,难道是只会找第一个 python-mode 么 :thinking:

还有个日本人基于此写了个 blog:python-modeでhideshow.el, hideshowvis.elを使って関数やクラスとかを折りたたんで表示する - uhiaha888’s diary,不过也是好早前的了。

试试我这个?

1 个赞

谢谢,好使了,应该是缺了 (hs-grok-mode-type) 这个函数。