Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Emacs: outline-mode folding for Python, elisp, and shell
(defun my/python-mode-outline-hook ()
(setq outline-level 'my/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
;; TODO: Try setting this to python-indent-offset
;; instead of space. Might capture the indention levels
;; better.
(group (* space)) ; 0 or more spaces
bow
;; Keywords
(or "class" "def" "else" "elif" "except" "for" "if" "try" "while" "with")
eow)))))
(defun my/python-outline-level ()
;; Based on this code found at
;; http://blog.zenspider.com/blog/2013/07/my-emacs-setup-ruby-and-outline.html:
;; (or (and (match-string 1)
;; (or (cdr (assoc (match-string 1) outline-heading-alist))
;; (- (match-end 1) (match-beginning 1))))
;; (and (match-string 0)
;; (cdr (assoc (match-string 0) outline-heading-alist)))
(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)))))
;; my/programming-hook must run before the outline-hook, or else
;; (outline-minor-mode) is run after the outline-hook and it resets
;; outline-{level,regexp}
(add-hook 'sh-mode-hook 'my/sh-mode-outline-hook)
(defun my/sh-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 1) (match-beginning 1) 1))
;; Keyword/function heading
;; Add 8 (the highest standard outline level) to every keyword
;; heading
(+ 8 (- (match-end 3) (match-beginning 3)))))
(defun my/sh-mode-outline-hook ()
(setq outline-level 'my/sh-outline-level)
(setq outline-regexp
(rx
(group
(or
;; Outline headings
(and (* space)
(one-or-more (syntax comment-start))
(* space)
(group (one-or-more "\*"))
(* space))
;; Keywords and functions
(and (group (* space))
(or
;; e.g. "function foo"
(and (or "function" "if" "elif" "else" "for" "while")
(one-or-more space))
;; e.g. "foo()"
(and (one-or-more (or alnum "_-"))
(* space)
(syntax open-parenthesis)
(syntax close-parenthesis)))))))))
;;;;; elisp
(add-hook 'emacs-lisp-mode-hook 'my/el-mode-outline-hook)
(defun my/el-outline-level ()
(or
;; Commented outline heading
(and (string-match (rx
(* space)
(group (one-or-more (syntax comment-start)))
(one-or-more space))
(match-string 0))
(- (match-end 0) (match-beginning 0) 1))
;; Lisp def heading
;; Add 8 (the highest standard outline level) to every keyword
;; heading
(+ 8 (- (match-end 0) (match-beginning 0)))))
(defun my/el-mode-outline-hook ()
(setq outline-level 'my/el-outline-level)
(setq outline-regexp "\\(;;[;]\\{1,8\\} \\|\\((def\\)\\)"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.