-
Notifications
You must be signed in to change notification settings - Fork 23
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
Replace evil -- first pass #118
base: 2.0-integration
Are you sure you want to change the base?
Replace evil -- first pass #118
Conversation
This is intended to encapsulate any setup and teardown actions that in general would need to be performed with any symex transformation, such as re-indenting, whitespace elimination, etc. It should also avoid the need to rely on advice for some of these actions, and also therefore make it easier for developers (including third parties) to define such transformations, as all such logistical concerns can be taken care of internally in the macro.
Similar to `symex-define-command`, this will take care of entering an insertion state at the end, so that the implementation of the command only needs to take care of the core operation and placing point at the right place (without entering an insertion state).
Handle additional cases of empty lists to help ensure that motion does not attempt to enter empty expressions.
This fixes some indentation bugs in pasting multiple yanked expressions and in pasting with a quantifier, and also simplifies the code by sharing functionality common to pasting before and after.
Eliminate special cases by using generic region indenting. Also add the abilty to specify a quantifier/count.
(evil-emacs-state)))) | ||
(evil-emacs-state)) | ||
((fboundp 'symex-user-defined-higher-mode) | ||
(symex-user-defined-higher-mode)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@countvajhula I'm not sure if there a is a better way or a standard way of exposing user functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can just use symex-meow
here rather than expose it to an arbitrary user customization.
Seems to be working pretty well so far. Here is my current (WIP) setup with meow in case anyone wants to try it out: (note that I started with the meow defaults for the dvorak layout) (use-package symex
:load-path "~/projects/symex.el"
:config
(setq symex-highlight-p nil)
(defun symex-user-defined-higher-mode ()
(interactive)
(if dc/return-to-symex
(prog2 (setq-local dc/return-to-symex nil)
(meow-enter-paren-mode))
(meow-enter-normal-mode)))
(defun symex-user-defined-lower-mode ()
(setq-local dc/return-to-symex t)
(meow-insert-mode))
(defun symex-user-defined-lowest-mode () (symex-user-defined-lower-mode)))
;;* Modal user interface
(use-package meow
:demand t
:config
(defvar dc/return-to-symex nil "local-var used to know if we've entered insert from paren mode, and if so, return there.")
(defun meow-enter-normal-mode () (interactive) (meow-normal-mode 1))
(defun meow-enter-paren-mode ()
(interactive)
(meow-paren-mode 1)
(symex-select-nearest-in-line)
(symex--adjust-point)
(symex-initialize))
(setq meow-paren-keymap (make-keymap))
(meow-define-state paren
"meow state for interacting with smartparens"
:lighter " [P]"
:keymap meow-paren-keymap)
;; meow-define-state creates the variable
(setq meow-cursor-type-normal 'hollow)
(setq meow-cursor-type-paren 'box)
(meow-define-keys 'paren
'("0" . digit-argument)
'("9" . digit-argument)
'("8" . digit-argument)
'("7" . digit-argument)
'("6" . digit-argument)
'("5" . digit-argument)
'("4" . digit-argument)
'("3" . digit-argument)
'("2" . digit-argument)
'("1" . digit-argument)
'("<backspace>" . dc/switch-to-previous-buffer)
'("q" . meow-quit)
'("Q" . kill-buffer-and-window)
'("h" . symex-go-backward)
'(")" . symex-wrap-round)
'("]" . symex-wrap-square)
'("C-'" . symex-cycle-quote)
'("C-," . symex-cycle-unquote)
'("`" . symex-add-quoting-level)
'("C-`" . symex-remove-quoting-level)
'("y" . symex-yank)
'("K" . symex-yank-remaining)
'("p" . symex-paste-after)
'("P" . symex-paste-before)
'("x" . symex-delete)
'("X" . symex-delete-backwards)
'("D" . symex-delete-remaining)
'("c" . symex-change)
'("C" . symex-change-remaining)
'("C--" . symex-clear)
'("M-h" . symex-change-delimiter)
'("H" . symex-shift-backward)
'("S" . symex-shift-forward)
'("M-H" . symex-shift-backward-most)
'("M-S" . symex-shift-forward-most)
; revisit kb
'("M-(" . symex-emit-backward)
'("(" . symex-capture-backward)
'(")" . symex-capture-forward)
'("M-)" . symex-emit-forward)
'("z" . symex-swallow)
'("Z" . symex-swallow-tail)
'("e" . symex-evaluate)
'("E" . symex-evaluate-remaining)
'("C-M-e" . symex-evaluate-pretty)
'("d" . symex-evaluate-definition)
'("M-e" . symex-eval-recursive)
'("|" . symex-split)
'("_" . symex-split)
'("&" . symex-join)
'("-" . symex-splice)
'("o" . symex-open-line-after)
'("O" . symex-open-line-before)
'(">" . symex-insert-newline)
'("<" . symex-join-lines-backwards)
'("C->" . symex-append-newline)
'("C-<" . symex-join-lines)
'("C-S-o" . symex-append-newline)
'("J" . symex-join-lines)
'("M-J" . symex-collapse)
'("M-<" . symex-collapse)
'("M->" . symex-unfurl)
'("C-M-<" . symex-collapse-remaining)
'("C-M->" . symex-unfurl-remaining)
'("0" . symex-goto-first)
'("M-h" . symex-goto-first)
'("$" . symex-goto-last)
'("M-l" . symex-goto-last)
'("M-j" . symex-goto-lowest)
'("M-k" . symex-goto-highest)
'("=" . symex-tidy)
'("<tab>" . symex-tidy)
'("C-=" . symex-tidy-remaining)
'("C-<tab>" . symex-tidy-remaining)
'("M-=" . symex-tidy-proper)
'("M-<tab>" . symex-tidy-proper)
'("A" . symex-append-after)
'("a" . symex-insert-at-end)
'("i" . meow-insert-mode)
'("I" . symex-insert-before)
'("w" . symex-wrap)
'("W" . symex-wrap-and-append)
'(";" . symex-comment)
'("M-;" . symex-comment-remaining)
'("C-;" . symex-eval-print) ; weird pre-offset (in both)
'("H-h" . symex--toggle-highlight) ; treats visual as distinct mode
'("C-?" . symex-describe)
'("<return>" . symex-enter-lower)
'("d" . symex-go-up) ; Symex is in terms of branches as going up as a tree, whereas I think of branches of a root system.
'("u" . symex-go-down) ; Therefore I want to visually go down a line, not up a limb to climb a "branch".
'("s" . symex-go-forward)
'("n" . symex-traverse-forward)
'("N" . symex-traverse-forward-skip)
'("C-w" . symex-wrap-square)
'("M-w" . symex-wrap-curly)
'("M-d" . symex-climb-branch)
'("M-u" . symex-descend-branch)
'("M-j" . symex-goto-highest)
'("M-k" . symex-goto-lowest)
'("." . symex-leap-forward)
'("," . symex-leap-backward)
'("r" . paredit-raise-sexp)
'("<escape>" . meow-enter-normal-mode))
(setq meow-cheatsheet-layout meow-cheatsheet-layout-dvorak)
(meow-leader-define-key
'("1" . meow-digit-argument)
'("2" . meow-digit-argument)
'("3" . meow-digit-argument)
'("4" . meow-digit-argument)
'("5" . meow-digit-argument)
'("6" . meow-digit-argument)
'("7" . meow-digit-argument)
'("8" . meow-digit-argument)
'("9" . meow-digit-argument)
'("0" . meow-digit-argument)
'("/" . meow-keypad-describe-key)
'("?" . meow-cheatsheet))
(meow-motion-overwrite-define-key
;; custom keybinding for motion state
'("<escape>" . meow-enter-normal-mode))
(meow-normal-define-key
'("<backspace>" . dc/switch-to-previous-buffer)
'("-" . negative-argument)
'(";" . meow-reverse)
'("," . meow-inner-of-thing)
'("." . meow-bounds-of-thing)
'("<" . meow-beginning-of-thing)
'(">" . meow-end-of-thing)
'("a" . meow-append)
'("A" . meow-open-below)
'("b" . meow-back-word)
'("B" . meow-back-symbol)
'("c" . meow-change)
'("d" . meow-delete)
'("D" . meow-backward-delete)
'("e" . meow-line)
'("E" . meow-goto-line)
'("f" . meow-find)
'("g" . meow-cancel-selection)
'("G" . meow-grab)
'("h" . meow-left)
'("H" . meow-left-expand)
'("i" . meow-insert)
'("I" . meow-open-above)
'("j" . meow-join)
'("k" . meow-kill)
'("K" . meow-enter-paren-mode)
'("l" . meow-till)
'("m" . meow-mark-word)
'("M" . meow-mark-symbol)
'("n" . meow-next)
'("N" . meow-next-expand)
'("o" . meow-block)
'("O" . meow-to-block)
'("p" . meow-prev)
'("P" . meow-prev-expand)
'("q" . meow-quit)
'("Q" . kill-buffer-and-window)
'("r" . meow-replace)
'("R" . meow-swap-grab)
'("s" . meow-search)
'("t" . meow-right)
'("T" . meow-right-expand)
'("u" . meow-undo)
'("U" . meow-undo-in-selection)
'("v" . meow-visit)
'("w" . meow-next-word)
'("W" . meow-next-symbol)
'("x" . meow-save)
'("X" . meow-sync-grab)
'("y" . meow-yank)
'("z" . meow-pop-selection)
'("'" . repeat)
'("<escape>" . meow-enter-paren-mode))
(meow-define-keys 'insert
'("<escape>" . symex-user-defined-higher-mode))
(meow-global-mode 1)) |
This is a good start! A few initial comments: This PR disables evil wholesale, but Evil plays two distinct roles in the code that call for distinct handling. The first role is in the core, as a shortcut to implement features that we would otherwise need custom implementations for. The second role is as a modal interface, providing users a way to access Symex features whose implementation is a black box. For the core, we'd like to eliminate evil entirely, by using built-in Emacs or custom implementations instead. For the most part, this is what you've done here, but there are places, like the "emacslike" and "normallike" states, where Evil functionality is simply conditionally disabled. I don't recall exactly what the purpose of these was, but without delving into that for the moment, I'm assuming that disabling it is likely to break something when the affected features are used in Meow. Looks like that's used in For the modal interface, disabling Evil functionality means that users who don't have Evil installed would be left without a modal interface. This is in contrast to today where even vanilla Emacs users get a modal interface out of the box (that happens to be implemented in Evil, but this is abstracted from them). I'd recommend creating a new With this in place, we could remove symex-evil, symex-meow (and maybe reintroduce symex-hydra), as part of the broader effort to decouple things in #26 (which is likely post-2.0 to keep this release's scope manageable). Alternatively, you could implement symex-meow as a separate package even today, if you think that would be easier. Lastly, for the purposes of this PR, I think we'd want to retain |
Not quite what I had in mind; just to make it a soft dependency instead of a hard dependency. If evil is available it is intended to be used. If not, I've messed something up in the PR. Let me check ........
If I understand correctly, This allows changes "under evil's radar" so that there are not unwanted side-effects. No evil, no added hooks to avoid, no problem. (That's the theory, at least :P. Anecdotally I haven't had any trouble with
Do you mean by this that long-term, symex is intended to have it's own modal interface independent of third-party modal interfaces?
Oh, I like this idea!
Sounds good, I'll see if I can't fix this PR so that it works with Evil again. |
Ah yes, sorry, I didn't mean to suggest that you had removed evil for evil users, just that you had disabled it for non-evil users, and that that may lose functionality in the core. But it sounds like that may not be the case. Btw, I should have asked earlier -- is all you're trying to do use Symex with Meow? If so, then just implementing |
Long term, it would look more like #26 , so no, a modal interface would not be bundled. It would be up to the user to install either symex-evil, or symex-meow/hydra/anything else if they want a modal UI. Meanwhile, library authors could just use the DSL without any of the UI stuff, or even just the tree-sitter component without any of the Lisp stuff, and could mix and match as needed (also related: #9 ). |
Nope, not all I'm after. Main thing is that I like having light dependencies, and evil just doesn't qualify. Really I'm not using Meow for much of anything, other than to replace evil as the modal backend for Symex :) |
Aha, found problem. Accidentally put Now this works in (require 'package)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(use-package evil :ensure t)
(use-package tsc :ensure t)
(use-package tree-sitter :ensure t)
(use-package symex
:load-path "~/projects/symex.el") ;; path to local mirror of this PR
(symex-initialize) |
@@ -99,7 +97,7 @@ | |||
;; don't leave an empty line where the symex was | |||
(delete-region (line-beginning-position) | |||
(1+ (line-end-position))))) | |||
((or (save-excursion (evil-last-non-blank) ; (<>$ | |||
((or (save-excursion (end-of-line) (skip-chars-backward " \t") ; (<>$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd put this in a helper in symex-utils.el as symex-last-non-blank
@@ -125,7 +123,8 @@ | |||
;; ensure that there isn't a comment on the | |||
;; preceding line before joining lines | |||
(unless (condition-case nil | |||
(progn (evil-find-char 1 ?\;) | |||
(progn (search-forward ";" (save-excursion | |||
(end-of-line) (point))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably just (line-end-position)
(t (evil-emacs-state)))) | ||
((symex--evil-installed-p) | ||
(evil-emacs-state)) | ||
((fboundp 'symex-user-defined-lower-mode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, we don't need these. When the symex-meow
module is added, we can add an extra case at each of these sites.
(t (evil-emacs-state)))) | ||
((symex--evil-installed-p) | ||
(evil-emacs-state)) | ||
((fboundp 'symex-user-defined-lowest-mode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as others.
@devcarbon-com To set expectations on the timelines on this work, I think eliminating the Evil dependency is premature at this stage and is going to require more structured handling. For now, I think it is safe to merge:
As far as the conditional checks for evil-installed-p and stubbed interfaces, although it solves the dependency issue in your specific case, it introduces unnecessary complexity at this stage that doesn't help us truly address the problem. At a high level, I'd love to understand why Evil is used in the core (i.e. non-UI parts) at all, and either eliminate it, or fully encapsulate it in some kind of "adapter" module / layer. But as eliminating Evil isn't in scope for the 2.0 release, I don't anticipate being able to consider these changes in the immediate future. If you're fine with that, we could continue working on this PR on a longer timeframe, as long as you realize it will probably be after 2.0! But a better option (which I would recommend) is if you could trim the PR to the enumerated safe changes specifically, we could merge them in now before tackling the other stuff so that they aren't held up by longer term discussions. We could then continue the discussion on Evil on a dedicated second PR. Wdyt? |
@countvajhula Sounds good! I've got deadline I'm racing against right now with a project at work. but I'll get to this as soon as I'm able. |
Hey @devcarbon-com ! Just a heads up I may be doing some refactoring in the near future that may cause some conflicts for this PR. Specifically, I'm planning on refiling a lot of things from |
@countvajhula Thanks for the heads up! I'm almost done with "marathon mode" that I've been in for my work project. I'll be back to wrap this up after that. (Tentative ETA next week). |
Needed a hook to delete the selection highlight from symex which would otherwise remain unchanged when switching back to normal mode. Insert modes do not work yet, since symex is coupled to Evil states and does not work with meow out of the box. This will eventually change, as there are decoupling efforts (drym-org/symex.el#118) being made, but for now, I may just stick to meow-insert/append or maybe overwrite the relevant commands. Otherwise, it seems to work fine. I just hope the developer removes some of the dependencies, especially evil, but also lispy and evil-cleverparens, which I don’t really need.
Hi @countvajhula, my apologies for the radio silence. I expect to have some time to work on this in the next month or two. |
That's great to hear @devcarbon-com . I have had other work take priority in these last few months, but I hope to have time to dedicate to Symex soon as well, perhaps around the same time as you. |
bab9c37
to
9c43278
Compare
@devcarbon-com Psst... check this out 😛 I'm migrating all Rigpa modes to Lithium (a persistent modal UI that's a thin wrapper around Emacs's minor modes and keymap lookup), and with just a little refactoring it should be easy to do it for Symex too. Then, removing Evil could be on the horizon at last (we'd still need to remove all the implementation stuff that relies on Evil and use native Emacs alternatives... maybe a few other things). |
Woohoo, this is awesome @countvajhula !!! I've been pining for just such a thing :D |
52f885b
to
95bf3a5
Compare
Summary of Changes
I got a little carried away while replacing evil-surround and replaced evil altogether :P
Draft.
Initial testing looks promising.
Still need to update the doc strings everywhere that refer to evil specifically where they could be modal in general.
When merged will resolve #106.
Public Domain Dedication
(Why: The freely released, copyright-free work in this repository represents an investment in a better way of doing things called attribution-based economics. Attribution-based economics is based on the simple idea that we gain more by giving more, not by holding on to things that, truly, we could only create because we, in our turn, received from others. As it turns out, an economic system based on attribution -- where those who give more are more empowered -- is significantly more efficient than capitalism while also being stable and fair (unlike capitalism, on both counts), giving it transformative power to elevate the human condition and address the problems that face us today along with a host of others that have been intractable since the beginning. You can help make this a reality by releasing your work in the same way -- freely into the public domain in the simple hope of providing value. Learn more about attribution-based economics at drym.org, tell your friends, do your part.)