summary refs log tree commit diff stats
path: root/lisp/+lisp.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/+lisp.el')
-rw-r--r--lisp/+lisp.el71
1 files changed, 71 insertions, 0 deletions
diff --git a/lisp/+lisp.el b/lisp/+lisp.el new file mode 100644 index 0000000..3267fd9 --- /dev/null +++ b/lisp/+lisp.el
@@ -0,0 +1,71 @@
1;;; +lisp.el --- extra lisp functionality -*- lexical-binding: t -*-
2
3;;; Code:
4
5;;; Sort sexps in a region.
6;; https://github.com/alphapapa/unpackaged.el
7
8(defun +lisp-skip-whitespace ()
9 (while (looking-at (rx (1+ (or space "\n"))))
10 (goto-char (match-end 0))))
11
12(defun +lisp-skip-both ()
13 (while (cond ((or (nth 4 (syntax-ppss))
14 (ignore-errors
15 (save-excursion
16 (forward-char 1)
17 (nth 4 (syntax-ppss)))))
18 (forward-line 1))
19 ((looking-at (rx (1+ (or space "\n"))))
20 (goto-char (match-end 0))))))
21
22(defun +lisp-sort-sexps (beg end &optional key-fn sort-fn)
23 "Sort sexps between BEG and END.
24Comments stay with the code below.
25
26Optional argument KEY-FN will determine where in each sexp to
27start sorting. e.g. (lambda (sexp) (symbol-name (car sexp)))
28
29Optional argument SORT-FN will determine how to sort two sexps'
30strings. It's passed to `sort'. By default, it sorts the sexps
31with `string<' starting with the key determined by KEY-FN."
32 (interactive "r")
33 (save-excursion
34 (save-restriction
35 (narrow-to-region beg end)
36 (goto-char beg)
37 (+lisp-skip-both)
38 (cl-destructuring-bind (sexps markers)
39 (cl-loop do (+lisp-skip-whitespace)
40 for start = (point-marker)
41 for sexp = (ignore-errors
42 (read (current-buffer)))
43 for end = (point-marker)
44 while sexp
45 ;; Collect the real string, then one used for sorting.
46 collect (cons (buffer-substring (marker-position start)
47 (marker-position end))
48 (save-excursion
49 (goto-char (marker-position start))
50 (+lisp-skip-both)
51 (if key-fn
52 (funcall key-fn sexp)
53 (buffer-substring
54 (point)
55 (marker-position end)))))
56 into sexps
57 collect (cons start end)
58 into markers
59 finally return (list sexps markers))
60 (setq sexps (sort sexps (if sort-fn sort-fn
61 (lambda (a b)
62 (string< (cdr a) (cdr b))))))
63 (cl-loop for (real . sort) in sexps
64 for (start . end) in markers
65 do (progn
66 (goto-char (marker-position start))
67 (insert-before-markers real)
68 (delete-region (point) (marker-position end))))))))
69
70(provide '+lisp)
71;;; +lisp.el ends here