Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible to make sort-sexps take a sorting function? #20

Open
duckwork opened this issue Sep 3, 2021 · 7 comments
Open

Possible to make sort-sexps take a sorting function? #20

duckwork opened this issue Sep 3, 2021 · 7 comments
Assignees
Labels
enhancement New feature or request

Comments

@duckwork
Copy link

duckwork commented Sep 3, 2021

My lisp-fu is not so advanced to do this, but I'd love ot pass something like, (sort-sexps beg end &optional accessor) to sort specifically on a certain element of a list (i.e., sort all defines by cadr).

Looks like the collect (cons (buffer-substring...) code needs to be modified, but I'm not sure how to define a searcher for a certain element of each read list and return its begin and end points in the buffer.

@alphapapa
Copy link
Owner

I guess you could do something like this:

(cl-defun unpackaged/sort-sexps (beg end &key key)
  "Sort sexps in region.
Comments stay with the code below."
  (interactive "r")
  (cl-flet ((skip-whitespace () (while (looking-at (rx (1+ (or space "\n"))))
                                  (goto-char (match-end 0))))
            (skip-both () (while (cond ((or (nth 4 (syntax-ppss))
                                            (ignore-errors
                                              (save-excursion
                                                (forward-char 1)
                                                (nth 4 (syntax-ppss)))))
                                        (forward-line 1))
                                       ((looking-at (rx (1+ (or space "\n"))))
                                        (goto-char (match-end 0)))))))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        (goto-char beg)
        (skip-both)
        (cl-destructuring-bind (sexps markers)
            (cl-loop do (skip-whitespace)
                     for start = (point-marker)
                     for sexp = (ignore-errors
                                  (read (current-buffer)))
                     for end = (point-marker)
                     while sexp
                     ;; Collect the real string, then one used for sorting.
                     collect (cons (buffer-substring (marker-position start) (marker-position end))
                                   (save-excursion
                                     (goto-char (marker-position start))
                                     (skip-both)
                                     (if key
                                         (funcall key sexp)
                                       (buffer-substring (point) (marker-position end)))))
                     into sexps
                     collect (cons start end)
                     into markers
                     finally return (list sexps markers))
          (setq sexps (sort sexps (lambda (a b)
                                    (string< (cdr a) (cdr b)))))
          (cl-loop for (real . sort) in sexps
                   for (start . end) in markers
                   do (progn
                        (goto-char (marker-position start))
                        (insert-before-markers real)
                        (delete-region (point) (marker-position end)))))))))

Then:

(sort-sexps (region-beginning) (region-end) :key (lambda (sexp) (symbol-name (car sexp))))

What do you think? Thanks.

@duckwork
Copy link
Author

duckwork commented Sep 4, 2021

Oh, that'll work! Thanks :)

@alphapapa
Copy link
Owner

Does it work? I didn't test it myself.

@duckwork
Copy link
Author

duckwork commented Sep 6, 2021

It does indeed. I've written my own function (viewable in all its awfulness here) that sorts my init file by setup forms. Exactly what I was looking for, thanks!

@alphapapa
Copy link
Owner

Oh, I didn't realize you are acdw. :)

@duckwork
Copy link
Author

duckwork commented Sep 7, 2021

Oh, right, haha :) ACDW was taken already on Github!

@duckwork duckwork closed this as completed Sep 7, 2021
@alphapapa alphapapa self-assigned this Sep 8, 2021
@alphapapa alphapapa added the enhancement New feature or request label Sep 8, 2021
@alphapapa
Copy link
Owner

Let's leave this open until I "merge" it...

@alphapapa alphapapa reopened this Sep 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants