-
Notifications
You must be signed in to change notification settings - Fork 275
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
Lispy Key Theme #116
Comments
Timing couldn't be better! Let me drop my current config for now, I'll discuss this more in-depth later:
|
Some comments:
Here is some of my configuration. Ideally as few commands as possible (or none) should be lost by using the key theme. (general-def lispy-mode-map
:definer 'lispy
"y" #'lispy-new-copy ; lose lispy-occur -> /
;; swap p and P
"p" #'lispy-paste
"P" #'lispy-eval-other-window
"d" #'noct:lispy-delete ; lose lispy-different -> o
;; like in visual state
"o" #'lispy-different ; lose lispy-other-mode (don't use)
"/" #'lispy-occur ; lose lispy-splice -> x
"x" #'lispy-splice ; lose lispy-x -> c
;; "change" works as a mnemonic for some of these actions (e.g. change to
;; cond, change to if, change to defun, and change to lambda; there's not
;; really a common theme for the other actions)
"c" #'lispy-x ; lose lispy-clone -> q
"f" #'lispy-ace-paren ; lose lispy-flow -> n
;; maybe
"F" #'lispy-ace-char ; lose lispy-follow -> ???
;; or this
"t" #'lispy-ace-char ; lose lispy-teleport -> ???
;; kind of like repeating a search
"n" #'lispy-flow
;; I don't have a good mnemonic for this other than that q sounds vaguely
;; similar to c
"q" #'lispy-clone
;; swap m and v
"v" #'lispy-mark-list
"m" #'lispy-view
;; extra not-vimmy personal configuration
;; swap H and A; makes more sense given default h and a
"H" #'lispy-beginning-of-defun
"A" #'lispy-ace-symbol-replace)
;; alternative that removes only convolute
"t" #'lispy-ace-char
"C" #'lispy-clone
"q" #'lispy-teleport
"Q" #'lispy-other-mode I think most of the above is fairly reasonable, but feedback would be appreciated. For example, I think it makes sense to bind As for (defun noct:lispy-delete (arg)
"Copy and delete current sexp.
Passes ARG to `lispy-delete' or `lispy-delete-back'."
(interactive "p")
(cond ((or (lispy-left-p)
(region-active-p))
(lispy-new-copy)
(lispy-delete arg))
((lispy-right-p)
(lispy-new-copy)
(lispy-delete-backward arg)))) @jojojames After using the above for a while, I feel like it should stay in special like your I'm splitting this comment because the rest of it isn't as relevant/important. |
Some reasons why losing
That said, I think the movement commands may make it worth putting on one of the freed keys (e.g.
;; TODO PR
(defun noct:lispy-tab (arg)
(interactive "p")
(if (looking-at lispy-outline)
(outline-toggle-children)
(lispy-indent-adjust-parens arg)))
(general-def lispy-mode-map-lispy
"TAB" #'noct:lispy-tab
"<backtab>" #'lispy-dedent-adjust-parens) The above functionality is basically the same as ;; | is point
;; TAB still works for indentation if the current line needs to be indented
(foo
|bar)
;; after TAB
(foo
|bar)
;; if current like is correctly indented
(let ((a 1)))
|(b 2)
;; after TAB (like k / `lispy-up-slurp' )
(let ((a 1))
|(b 2))
;; another TAB (or using count originally)
(let ((a 1)
|(b 2)))
;; reversible with S-TAB (like `lispy-move-right' for this specific case)
(let ((a 1))
|(b 2))
;; then
(let ((a 1)))
|(b 2) That's about all I have wrt a vim key theme. The rest of my lispy config is mostly commands that I've been meaning to add to lispy. If you're curious, here is some of it: ;; used for writing tests
(defun noct:lispy-stringify-oneline ()
"Combination of `lispy-stingify' and `lispy-string-oneline'."
(interactive)
(lispy-stringify nil)
(lispy-string-oneline))
(defun noct:flatten (arg)
"`lispy-flatten' but use macrostep when possible."
(interactive "P")
(if (and (eq major-mode 'emacs-lisp-mode)
(macrop (intern (lispy--current-function))))
(macrostep-expand)
(lispy-flatten arg)))
;; this is in the README, but it might be nice if it was directly in lispy
(defun abo-enable-lispy-for-M-: ()
"Enable lispy in minibuffer for `eval-expression'."
(when (eq this-command #'eval-expression)
(lispy-mode)))
(add-hook 'minibuffer-setup-hook #'abo-enable-lispy-for-M-:)
;; this is also from the parinfer key theme; examples below
(general-def lispy-mode-map-lispy
"(" #'lispy-parens-auto-wrap
;; "{" #'lispy-braces-auto-wrap
;; ...
)
(defun noct:paren-advice (&rest _)
(cond ((lispy--in-string-or-comment-p)
;; temporary workaround for lispy's weird paren behavior in strings
(insert ")")
(backward-char))
(t
(let ((map (make-sparse-keymap)))
;; easy way to undo unwanted wrap on reaction
;; instead of planning with a prefix arg
(define-key map ")"
(lambda ()
(interactive)
(call-interactively #'lispy-barf-to-point)
(backward-char)))
(set-transient-map map)))))
(general-add-advice 'lispy-parens-auto-wrap :after #'noct:paren-advice)
;; On line by itself, `lispy-parens-auto-wrap' acts like the default "(":
|
;; to
(|)
;; wraps when before sexp
|1 2 3
;; type (foo
(foo 1 2 3)
;; wrapping can be prevent with C--/negative argument or by pressing ")"
;; afterwards with above advice:
(|) 1 2 3 |
This function looks interesting though I've never used it. If there was something like that in lispy, = would be the best place for it for sure. Revising after looking at above^:
We probably don't want this:
Maybe T for lispy-teleport. That way we can have t and f for the ace-* functions while keeping F at follow. Then Q can probably go to other-mode?
|
What I'm currently using is: ;; I base myself on paredit,because I don't like [ and ] to jump
;; Also, I like " and ' better in paredit-style
(lispy-set-key-theme '(special paredit c-digits))
;; This makes the < and > behave similar to evil-cleverparens
;; Also I think it's more intuitive
(lispy-define-key lispy-mode-map "<" #'lispy-slurp-or-barf-left)
(lispy-define-key lispy-mode-map ">" #'lispy-slurp-or-barf-right)
;; Makes backspace splice sexp
(define-key lispy-mode-map (kbd "DEL") 'lispy-delete-backward-or-splice-or-slurp) I'll give my thoughts about @jojojames' bindings.
Is this the same as
Although
I prefer keeping
I agree. Personally I use readline keybinding (
I think
I think so too, especially because there is already an evil keytheme in lispy. It's not well-designed in my opinion, so it would be nice if it were replaced by something better. |
Not sure, my intention was to do a deletion and then move point to the next sexp. That way you can press 'd' over and over again to delete.
Yup. I changed it to o in my more recent post.
Noted. The i was just a placeholder for now.
Sounds good, removed.
I'm open to w/s or M-j/M-k either way. Maybe adding both will be fine.
;; Makes backspace splice sexp
These look really interesting. Any thoughts on using these as defaults instead (instead of the default slurp/barf)? |
Yeah, I think it'd be good to eventually PR lispy directly though I want to avoid too much noise while we're still thinking of a nice set of defaults. |
Revised:
|
I think the outline commands are worth keeping in some form; I guess it would be okay if they were bound with a modifer outside of special since they don't really depend on special, and once on an outline
My main issue with this is that Why is splice bound twice? While
Since it's still unbound, this seems like a good idea. |
I don't think that |
Revised:
w/s still up in the air as well as M-j/M-k Tangential: Anyone know if lispy plays well with undo-tree?
I don't use them yet so I don't have a good idea where to place them.
I was mainly focused on the single-key bindings but this would be a good idea as well. |
Still playing around with this every so often. The keybinds are pretty similar. Only w and s for moving s-exps seem to be a little awkward for me still. I still need to look into the M-* type bindings. |
I've pushed a lot of my in progress lispy bindings to evil-collection-lispy. This is not in the default list of modes so if anyone wants to try it out, they'll have to add lispy to the init list themselves. It'd be good if others tried it and gave feedback. I tried to structure the code to look like what it would look like if it were a PR to lispy itself. The non-special mode map is a duplicate of evilcp for now. @Somelauw, it looks like you had opinions on that keymap judging from abo-abo/lispy#327 so it'd be good to get your opinions here. I'm planning (slowly) to revise both sets (the special one seems fairly solid at this point) of keymaps and then make a PR to lispy in the future (not sure when). |
@jojojames Now I think it would be best to:
Instead recommend new users to put something like:
in their config Maybe this should be discussed further on abo-abo/lispy#327 |
I gave it a shot and it seems pretty neat, although I personally find the combination of Evil states and Lispy special keys quite confusing to my taste. That said, I think this binding set deserves some extra explaination:
It seems that some bindings don't work in normal state but I'm not sure to get the logic there. |
You may have seen the functionality already, but lispyville has some features to potentially mitigate this (e.g. keybindings to more get into insert state/special from both normal and insert state). If you elaborate, I could potentially offer suggestions.
Lispyville doesn't touch any lispy keybindings, so there shouldn't be any compatibility issues.
Yes; I'd think it makes sense to keep it that way.
Special is for lispy's "special" keybindings (at parens or active visual selection) and the other map is for bindings that should work globally regardless of the point location. |
Indeed, I use Lispyville without enabling Lispy: this enables me with nifty
navigation / manipulation all round. I think it relieves some cognitive burden.
|
Yup, I plan to soon. The keymaps are a little rough at this moment for me so I don't want them to harden on @abo-abo's repo yet.
I think we need two themes. One to evilify the special keymap and the other to evilify the global lispy keymap. Doing it this way, the user should be able to still mix and match the key themes they want.
I'd like to in a new PR at some point, but want to avoid too much noise in the lispy repo.
I used to until @noctuid recommended the lispy keymap too. I'm still getting used to them but I think they're a net improvement to my workflow. These evil-collection lispy keymaps are used in combination with lispyville so I think they should be fairly compatible. @Ambrevar I think you'd have good insight on the lispy keymaps when not in special state though. |
Commentary on lispy-special state for evil: I think moving the knight keys (zj/zk) to gj/gk works more comfortably for an evil user.
Doing that kicks the 'g' key out (lispy-goto) but evil-collection already wants that at 'gd' anyways which is a good fit. Moving some other related keys along..
gg and G are open for navigation bindings. Something analogous to going to top/bottom would fit very well. I have something like this for that but it's not perfect.
Maybe there is another better function for g and gg that would make sense for an evil user. @noctuid ? Because A is now free (was lispy-beginning-of-defun), we can make it similar to insertion in evil. I found no function in lispy that did something like (lispy-insert-at-end-of-sexp) / (lispy-insert-at-beginning-of-sexp). I found something close in lispyville but still maybe not quite there in lispyville-insert-at-end-of-list and lispyville-insert-at-beginning-of-list. Maybe this is something that can be PR'd in lispy or there's already a function there that I missed. @noctuid ?
Assuming these keys can be moved, I think the I (shifttab and maybe tab) keys can then go to z (which is similar to evil-collection's rationale of folding?). I have these changes locally (in progress) for now since some functions just don't seem to exist in lispy. |
Hmnn.. I'm guessing prefix keys won't work with special state since it might interfere with normal typing. |
Your suggestion seems reasonable. I can't think of anything better.
These commands don't exist in lispy, but it would be very easy to add them as a separate PR or with the new theme.
Prefix keys should work fine in special. |
I'm not too familiar with lispy but trying to bind something like 'gg' to lispy map will work but then typing 'g' in insert state pauses because it's a prefix? Looking at lispy-define-key:
So it would just resolve to something like (define-key keymap (kbd "gg") 'some-func)) which will block 'g' from being pressed. |
My bad I thought you were talking about prefix arguments/counts. Binding prefix keys should work too. You just need to bind the base key to a prefix keymap/command, hydra, etc. instead of binding the entire sequence directly. |
Sounds good, I gave it a quick try and lispy-define-key doesn't seem to play nice with the prefix keymap. I'll give hydra a shot . |
Since it expects def to be a symbol/command, you can use the prefix command created with |
I think lispy eventually calls (call-interactively 'def) somewhere in the pipeline and that didn't work with the prefix command for me. |
Right, my bad again; I didn't actually test it. It would be possible to support a prefix command/keymap, but having to use a hydra isn't a big deal. |
np I pushed some more in progress changes. Dunno how to write a cleaner version of your lispyville functions @noctuid so I'm just forwarding to them for now. (Probably need to implement them for lispy though.)
There's a couple keys that don't seem to be getting bound right now. Looking at it... I have no idea.. Appreciate a look from anyone interested in lispy keybindings. |
Which keys? I can take a look when I get some free time. Also, I can make a PR to add the insert functions to lispy before the evil theme PR. |
AFAIK,
But there might be others I didn't remember to mark/comment. ~ I think it might be cool to mark the lispy-splice-sexp-killing-forward/backward functions. I kind of like ^ and $ for those. Not sure what others think about that though. |
++ |
As for
Do you mean in special with an active region? That might be a little confusing since they are just motions in evil. On a related note, I've locally written lispyville versions of these that kill around the current atom (i.e. they well kill or splice to the end/beginning of the list without deleting part of the current atom if the point is in the middle of it). I plan to add these directly to lispy (along with other missing commands from smartparens) once they are more stable (the current atom selection function is not perfect; I may use a more dumb/simple approach here, but if anyone wants to provide cases where the atom text object fails, that would be awesome). |
I was thinking just in 'special'. My rationale currently was that those keys might be confusing at first but users might adapt fairly quickly $ -> (kill forward to end)/etc but I can see it being confusing enough that it should just be a local customization.
Do you have an example? I'm guessing it's something like:
|
I've been using the lispy in evil-collection for a while (well more than a year since the last comment :D) and I've changed my mind on this. I think it's probably cleaner to have lispy's version (from a maintenance/fast interation point of view) in evil-collection and also pushed into its set of default modes. It's still not super polished but works well enough of day to day (I haven't changed any of its bindings for a year). I think I'll look into lispy's delta with the current bindings, try to fix any previous issues and move it in as a default mode in evil-collection soon. |
Sorry for being a little late to the party :p So why did you decide to make it part of the default modes? It seems quite disruptive in my opinion. Well, it's easy enough to disable it, but still, I wonder if it's a good default. A few issues I've noticed so far:
|
It's only there if you actually use lispy so I think it follows in the spirit of the rest of evil-collection. I don't think lispy even works that well without these types of bindings anyways. (Unless you memorize the somewhat-emacsy-somewhat-vimy bindings). I think putting it as a default is also a good forcing function for getting user's feedback on specific keys. (Case in point, what we have here. :D)
Which functionality are you talking about? If it's the shortkey version, maybe not, since that special mode should be "short keys". As for going into special mode with ]. Yeah, that might be a good idea, not sure without playing with it though.
Without this integration, what does normal lispy do?
There is, but I think lispy requires it. I think doing no byte compile is probably a little better than explicitly requiring hydra. |
OK, makes sense to include Lispy by default then!
> I miss my function navigation functions, usually bound to [[ and ]] (evil-forward-section-begin, etc.).
Without this integration, what does normal lispy do?
This is not a lispy binding, it's an Evil binding. `[[` and `]]`
navigate top-level forms.
I don't know how to do this once evil-collection-lispy is activated.
|
Yeah I meant, without evil-collection-lispy, does lispy interfere with ] and [. |
In special mode, yes, but in normal mode.
|
But *not* in normal mode.
|
Following from noctuid/lispyville#29
It might be nice to make the lispy-shortkey bindings for vim-y.
Here's just a quick copy-pasta of what I have so far (very rough and probably has some unnecessary changes).
Instead of % for lispy-different, could probably just use 'o', but 'o' already has something attached.
Also / could probably be lispy-occur.
The lispy-action-then-next-sexp was just so I can rapidly type 'd' 3 times to delete 3 sexps quickly.
@noctuid @Somelauw @Ambrevar
Would be good to see what you guys are doing and maybe we can synthesize something up and further cut down lispy's barrier to entry for vimmers.
The text was updated successfully, but these errors were encountered: