drym-org / symex.el

An intuitive way to edit Lisp symbolic expressions ("symexes") structurally in Emacs
Other
271 stars 22 forks source link

Decompose symex.el into modular packages #26

Open countvajhula opened 3 years ago

countvajhula commented 3 years ago

For instance:

At the moment all of the above functionality is present in the current package.

Possible benefits of decomposing it:

[Extracted from #20 ]

devcarbon-com commented 1 year ago

I'm interested in using symex with meow.

Ideally, there would be no evil dependancy at all - (and I'd be happy to help with that as I'm able) but for now I'm curious: do you have to "use" evil to have symex?

devcarbon-com commented 1 year ago

Ah - found this in the readme:

is available to both evil and vanilla emacs users.

countvajhula commented 1 year ago

Yeah, it would be great to eliminate the evil dependency in the core symex package after decomposition (and as you found, even currently you don't need to be an Evil user to use Symex). Regarding helping with this, it would amount to finding every instance of use of an evil API in symex-transformations.el and symex-misc.el (since those are part of the core code and not specific to the modal interface like symex-evil.el) and replacing it with vanilla emacs code that does the same thing. As I recall, the only reason we use Evil in these modules is because it was convenient to use evil interfaces to do things I already knew how to do in evil/Vim (e.g. deleting lines, moving the cursor, etc.), so it was expedient to use them.

jdtsmith commented 1 year ago

Given the exciting work going on with tree-sitter integration, I think it's key to separate out evil as "one of many usage scenarios" rather than leading with it.

When I was evaluating sexp editors, I skipped right over symex after reading the first few words (since I'm not an evil user). I settled on lispy, and really like its idea of "one-key modality at the boundaries of an sexp". Maybe that style could be implemented in another interface "sub-package". Ideally you can mix and match: boundary modality for these edits/motions, modal prefix for these others, regular Emacs keybindings for some, and a hydra/transient pop-up as backup.

countvajhula commented 1 year ago

FWIW even today, I bet it wouldn't be too hard to use Symex and Lispy together though it would be a hacked-together integration.

But I definitely agree with you that the UI (e.g. modal interface vs boundary modality vs no modality) should be separated from the functionality (e.g. the DSL/traversal language, the primitive structural operations, etc.) so that they can be mixed and matched as desired in a clean way.

devcarbon-com commented 1 year ago

So I have a (very rough) draft of this I was working on as a pull request, but something got really messed up in git somehow. I'm including it here in case it is useful to you, as it may be a long time before I could polish this up myself. So far all the evil refs are replaced, except for evil-surround in symex-transformations.el

Most of what still needs to be done is namespacing and testing. draft.txt

countvajhula commented 1 year ago

I appreciate your efforts! At this point, it would be most useful to make a pull request against the 2.0-integration branch rather than starting from master, as there is a lot of work in progress there that has changed much of this code (e.g. Lispy is no longer a dependency, and the evil footprint has been reduced, too).

Still, if you are not able to get to a PR, if you wouldn't mind summarizing your changes in bullet points, that would help me to know if there is something in your changes that I should use and avoid redoing any work.

devcarbon-com commented 1 year ago

Glancing at the new symext-transformations.el I think these functions are the remaining relevant ones:

(defun --surround-change (delimiter)
  "Change current delimeters to match DELIMITER."
  (let ((bounds (bounds-of-thing-at-point 'sexp)))
    (--surround (car bounds) (cdr bounds) delimiter)))

(defun --join (beg end)
  "Join the selected lines."
  (let ((count (count-lines beg end)))
    (when (> count 1)
      (setq count (1- count)))
    (goto-char beg)
    (dotimes (_ count)
      (join-line 1))))

(defun --delete-pair ()
  "Delete a pair of characters enclosing sexps that follow point."
  (save-excursion
    (skip-chars-forward " \t")
    (save-excursion
      (let ((open-char (char-after)))
        (forward-sexp arg)
        (unless (member (list open-char (char-before))
                        (mapcar (lambda (p)
                                  (if (= (length p) 3) (cdr p) p))
                                insert-pair-alist))
          (error "Not before matching pair"))
        (delete-char -1)))
    (delete-char 1)))
countvajhula commented 1 year ago

Nice, these look like they will be useful in shedding the evil-surround dependency 👍 . If you are interested, I can assign #106 to you. Otherwise, I'll aim to get to it and will plan to use this code.

devcarbon-com commented 1 year ago

@countvajhula Apologies for the delay. Sure, feel free to assign it. :)

countvajhula commented 1 year ago

@devcarbon-com Done!