Created
November 21, 2022 19:01
-
-
Save rougier/3657a24f25d6d64550281c32a39cde8d to your computer and use it in GitHub Desktop.
An emacs folding box function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defun folding-box (content &optional size title prefix type folded) | |
"Enclose TEXT with a box of given SIZE with an optional TITLE at | |
the top. | |
If a PREFIX is given, it is prepended to the box such that total | |
size is enforced, including prefix. If a title is given, the | |
content of the box can be shown/hidden by clicking on the title | |
and initial state is specified with FOLDED. The type of the box | |
can be either 'unicode or 'ascii." | |
(let* ((prefix (or prefix "")) | |
(size (or size -1)) | |
(size (cond ((and size (> size 0)) size) | |
((and size (< size 0)) (+ (window-width) size)) | |
(t (- (window-size) 1)))) | |
(type (or type 'unicode)) | |
(content (with-temp-buffer | |
(insert content) | |
(goto-char (point-min)) | |
;; 6 instead of 4 to have room for the "filler" | |
(let ((fill-column (- size 6)) | |
(sentence-end-double-space nil)) | |
(fill-region (point-min) (point-max))) | |
(buffer-substring (point-min) (point-max)))) | |
(fill-title (propertize " " | |
'display `(space :align-to ,(- size 2)))) | |
(fill-body (propertize " " | |
'display `(space :align-to ,(- size 2)))) | |
(keymap (let ((map (make-sparse-keymap))) | |
(define-key map [mouse-2] #'folding-box--toggle) | |
(define-key map (kbd "TAB") #'folding-box--toggle) | |
(define-key map (kbd "RET") #'folding-box--toggle) | |
map)) | |
(body-format (concat prefix "│ " | |
(propertize "%s" 'face 'default) | |
fill-body | |
" │\n")) | |
(header (concat prefix | |
"┌" | |
(make-string (- size (length prefix) 2) ?─) | |
"┐\n")) | |
(footer (concat prefix | |
"└" | |
(make-string (- size (length prefix) 2) ?─) | |
"┘")) | |
(body (mapconcat (lambda (line) | |
(format body-format line)) | |
(split-string content "[\n]") "")) | |
(title (when title (truncate-string-to-width title | |
(- size (length prefix) 4) nil nil "…"))) | |
(title (when title (concat prefix "│ " | |
(propertize (concat title fill-title) | |
'face 'nano-strong | |
'mouse-face 'highlight | |
'body-size (length body) | |
'follow-link t | |
'help-echo "Click to fold/unfold box content" | |
'keymap keymap) | |
" │\n"))) | |
(body (propertize body 'invisible folded))) | |
(concat header | |
(when title title) | |
body footer))) | |
(defun folding-box--toggle () | |
(interactive) | |
(let ((body-size (get-text-property (point) 'body-size))) | |
(when body-size | |
(save-excursion | |
(end-of-line) | |
(let ((invisible (not (get-text-property (+ (point) 1) 'invisible)))) | |
(add-text-properties (+ (point) 1) (+ (point) body-size 1) | |
`(invisible ,invisible))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment