diff options
Diffstat (limited to 'lisp/+lisp.el')
-rw-r--r-- | lisp/+lisp.el | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/lisp/+lisp.el b/lisp/+lisp.el new file mode 100644 index 0000000..22450f7 --- /dev/null +++ b/lisp/+lisp.el | |||
@@ -0,0 +1,93 @@ | |||
1 | ;;; +lisp.el -*- lexical-binding: t -*- | ||
2 | |||
3 | ;;; Comment-or-uncomment-sexp | ||
4 | ;; from https://endlessparentheses.com/a-comment-or-uncomment-sexp-command.html | ||
5 | |||
6 | (defun +lisp-uncomment-sexp (&optional n) | ||
7 | "Uncomment N sexps around point." | ||
8 | (interactive "P") | ||
9 | (let* ((initial-point (point-marker)) | ||
10 | (inhibit-field-text-motion t) | ||
11 | (p) | ||
12 | (end (save-excursion | ||
13 | (when (elt (syntax-ppss) 4) | ||
14 | (re-search-backward comment-start-skip | ||
15 | (line-beginning-position) | ||
16 | t)) | ||
17 | (setq p (point-marker)) | ||
18 | (comment-forward (point-max)) | ||
19 | (point-marker))) | ||
20 | (beg (save-excursion | ||
21 | (forward-line 0) | ||
22 | (while (and (not (bobp)) | ||
23 | (= end (save-excursion | ||
24 | (comment-forward (point-max)) | ||
25 | (point)))) | ||
26 | (forward-line -1)) | ||
27 | (goto-char (line-end-position)) | ||
28 | (re-search-backward comment-start-skip | ||
29 | (line-beginning-position) | ||
30 | t) | ||
31 | (ignore-errors | ||
32 | (while (looking-at-p comment-start-skip) | ||
33 | (forward-char -1))) | ||
34 | (point-marker)))) | ||
35 | (unless (= beg end) | ||
36 | (uncomment-region beg end) | ||
37 | (goto-char p) | ||
38 | ;; Indentify the "top-level" sexp inside the comment. | ||
39 | (while (and (ignore-errors (backward-up-list) t) | ||
40 | (>= (point) beg)) | ||
41 | (skip-chars-backward (rx (syntax expression-prefix))) | ||
42 | (setq p (point-marker))) | ||
43 | ;; Re-comment everything before it. | ||
44 | (ignore-errors | ||
45 | (comment-region beg p)) | ||
46 | ;; And everything after it. | ||
47 | (goto-char p) | ||
48 | (forward-sexp (or n 1)) | ||
49 | (skip-chars-forward "\r\n[:blank:]") | ||
50 | (if (< (point) end) | ||
51 | (ignore-errors | ||
52 | (comment-region (point) end)) | ||
53 | ;; If this is a closing delimiter, pull it up. | ||
54 | (goto-char end) | ||
55 | (skip-chars-forward "\r\n[:blank:]") | ||
56 | (when (eq 5 (car (syntax-after (point)))) | ||
57 | (delete-indentation)))) | ||
58 | ;; Without a prefix, it's more useful to leave point where | ||
59 | ;; it was. | ||
60 | (unless n | ||
61 | (goto-char initial-point)))) | ||
62 | |||
63 | (defun +lisp-comment-sexp--raw () | ||
64 | "Comment the sexp at point or ahead of point." | ||
65 | (pcase (or (bounds-of-thing-at-point 'sexp) | ||
66 | (save-excursion | ||
67 | (skip-chars-forward "\r\n[:blank:]") | ||
68 | (bounds-of-thing-at-point 'sexp))) | ||
69 | (`(,l . ,r) | ||
70 | (goto-char r) | ||
71 | (skip-chars-forward "\r\n[:blank:]") | ||
72 | (save-excursion | ||
73 | (comment-region l r)) | ||
74 | (skip-chars-forward "\r\n[:blank:]")))) | ||
75 | |||
76 | (defun +lisp-comment-or-uncomment-sexp (&optional n) | ||
77 | "Comment the sexp at point and move past it. | ||
78 | If already inside (or before) a comment, uncomment instead. | ||
79 | With a prefix argument N, (un)comment that many sexps." | ||
80 | (interactive "P") | ||
81 | (if (or (elt (syntax-ppss) 4) | ||
82 | (< (save-excursion | ||
83 | (skip-chars-forward "\r\n[:blank:]") | ||
84 | (point)) | ||
85 | (save-excursion | ||
86 | (comment-forward 1) | ||
87 | (point)))) | ||
88 | (+lisp-uncomment-sexp n) | ||
89 | (dotimes (_ (or n 1)) | ||
90 | (+lisp-comment-sexp--raw)))) | ||
91 | |||
92 | (provide '+lisp) | ||
93 | ;;; +lisp.el ends here | ||