Skip to content

Instantly share code, notes, and snippets.

@alphapapa
Last active September 7, 2023 00:03
Show Gist options
  • Save alphapapa/54761d6d507553f5a399 to your computer and use it in GitHub Desktop.
Save alphapapa/54761d6d507553f5a399 to your computer and use it in GitHub Desktop.
Emacs: Python: outline-minor-mode headings for both Python keywords and standard commented-starred headings
(defun python-mode-outline-hook ()
(setq outline-level 'python-outline-level)
(setq outline-regexp
(rx (or
;; Commented outline heading
(group
(* space) ; 0 or more spaces
(one-or-more (syntax comment-start))
(one-or-more space)
;; Heading level
(group (repeat 1 8 "\*")) ; Outline stars
(one-or-more space))
;; Python keyword heading
(group
;; Heading level
(group (* space)) ; 0 or more spaces
bow
;; Keywords
(or "class" "def" "else" "elif" "except" "for" "if" "try" "while")
eow)))))
(defun python-outline-level ()
(or
;; Commented outline heading
(and (string-match (rx
(* space)
(one-or-more (syntax comment-start))
(one-or-more space)
(group (one-or-more "\*"))
(one-or-more space))
(match-string 0))
(- (match-end 0) (match-beginning 0)))
;; Python keyword heading, set by number of indentions
;; Add 8 (the highest standard outline level) to every Python keyword heading
(+ 8 (- (match-end 0) (match-beginning 0)))))
(add-hook 'python-mode-hook 'python-mode-outline-hook)
@vv111y
Copy link

vv111y commented Feb 18, 2020

This is the best implementation I have come across, thanks @alphapapa.

Now I am trying to do the docstrings, so far I can't get the right regex's. I want to include the raw and unicode options, so all possible are:

""" """
r""" """
u""" """
(rx (or 
....
             (group
              (group (* space))
              (group
               (or "r" "u" "")
               (one-or-more (syntax string-quote))))
))

If you have any ideas I'd greatly appreciate it
EDIT: no I don't think this will work. Some other code will be needed to hide docstrings

@alphapapa
Copy link
Author

alphapapa commented Feb 19, 2020

Yeah, I don't know about that, sorry. Can Python docstrings even be matched correctly in all cases with a regexp?

BTW, I'm curious, how did you find this gist? I forgot that I had even posted it.

@vv111y
Copy link

vv111y commented Feb 20, 2020

I got this to work, not sure how proper it is. I'm using outlines folding function https://gist.github.com/db91372b34b99d317228a78082d49625

@alphapapa
Copy link
Author

Looks like that regexp might work for docstrings that have the closing quotes on a line by themselves, but not ones that don't.

@vv111y
Copy link

vv111y commented Feb 21, 2020

Good point, here' my attempt this morning. Seems to work

(setq py-docstring-regexp (rx
                           (group
                            (*? anything)
                            (group-n 3 (syntax string-quote))
                            not-newline
                            )))

ADD: okay, it has problems when quotes are used in certain ways elsewhere in the buffer, continuing ...

@vv111y
Copy link

vv111y commented Feb 21, 2020

Simple seems best, this works in all test cases

(setq py-docstring-regexp "\"\"\"")

ADD: almost, not exact. it matches 3 or more contiguous " . I am happy with this already but I'll try and get it exact.

ADD2: oh, finding the gist was just googling around. It was really frustrating, there were no good solutions anywhere and I'm surprised since docstrings can get quite large and are a real annoyance for code readability.
I think your 2 gists for python folding and my docstring one should be posted somewhere; I will bring it up for spacemacs as well.

@alphapapa
Copy link
Author

alphapapa commented Feb 22, 2020

Thanks. I'm not that interested in this kind of language-specific folding anymore, because it can be somewhat brittle and confusing at times, so I think I'll let you take this from here. :)

@vv111y
Copy link

vv111y commented Sep 15, 2020

Update, it works but it is not the best abstraction. Python code is not an outline in the sense of emacs outlines.
I'm trying @tarsius bicycle that combines outline-minor-mode with hideshow.
Also trying selective-display from suggestions here
fwiw
Update 2: wait, yafolding seems best yet. But I tried it earlier and rejected it??? oh well.

@TimotheeMathieu
Copy link

Thanks, this works well with outline-minor-mode.
Would it be possible to do something similar with outshine ? I tried without success.

@alphapapa
Copy link
Author

Thanks, this works well with outline-minor-mode. Would it be possible to do something similar with outshine ? I tried without success.

Generally, Outshine isn't designed to be terribly extensible or customizeable, but you might be able to customize the corresponding outshine variables to achieve a similar effect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment