Skip to content

Instantly share code, notes, and snippets.

@alphapapa
Last active September 7, 2023 00:03
Show Gist options
  • Select an option

  • Save alphapapa/54761d6d507553f5a399 to your computer and use it in GitHub Desktop.

Select an option

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

vv111y commented Feb 18, 2020 •

Copy link
Copy Markdown

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

alphapapa commented Feb 19, 2020 •

Copy link
Copy Markdown
Author

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

vv111y commented Feb 20, 2020

Copy link
Copy Markdown

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
Copy Markdown
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

vv111y commented Feb 21, 2020 •

Copy link
Copy Markdown

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

vv111y commented Feb 21, 2020 •

Copy link
Copy Markdown

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

alphapapa commented Feb 22, 2020 •

Copy link
Copy Markdown
Author

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

vv111y commented Sep 15, 2020 •

Copy link
Copy Markdown

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
Copy Markdown

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
Copy Markdown
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