Skip to content

Commit

Permalink
Add more keybindings/commands
Browse files Browse the repository at this point in the history
- Add more commands to the additional key theme (addresses #5)
- Add the additional insert key theme
- Add initial keybindings for the arrows key theme (address #10)
  • Loading branch information
noctuid committed Apr 8, 2018
1 parent 059362b commit df64528
Show file tree
Hide file tree
Showing 3 changed files with 227 additions and 9 deletions.
41 changes: 35 additions & 6 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,44 @@ The =slurp/barf-lispy= key theme provides commands that act the same as the defa
For both =<= bindings, if =lispyville-barf-stay-with-closing= is non-nil and barfing would move the closing delimiter behind the point, the point will instead be put on the closing delimiter.

** Additional Key Theme
The corresponding symbol is =additional=. The default states are normal and visual. This key theme is the equivalent of cleverparen's "additional bindings" keys. It is currently incomplete. =M-j= is comparable to ~evil-cp-drag-forward~ and ~lispy-move-down~. =M-k= is comparable to ~evil-cp-drag-backward~ and ~lispy-move-up~.

| key | command |
|-------+----------------------------|
| =M-j= | ~lispyville-drag-forward~ |
| =M-k= | ~lispyville-drag-backward~ |
The corresponding symbol is =additional=. The default state is normal state. This key theme is the equivalent of cleverparens' "additional bindings" keys. It is currently incomplete. =M-j= is comparable to ~evil-cp-drag-forward~ and ~lispy-move-down~. =M-k= is comparable to ~evil-cp-drag-backward~ and ~lispy-move-up~.

| key | command |
|-------+------------------------------------------|
| =M-j= | ~lispyville-drag-forward~ |
| =M-k= | ~lispyville-drag-backward~ |
| =M-J= | ~lispy-join~ |
| =M-s= | ~lispy-splice~ |
| =M-S= | ~lispy-split~ |
| =M-r= | ~lispy-raise-sexp~ |
| =M-R= | ~lispyville-raise-list~ |
| =M-t= | ~transpose-sexps~ |
| =M-v= | ~lispy-convolute-sexp~ |

~lispyville-move-down~ is an alias for ~lispyville-drag-forward~, and ~lispyville-move-up~ is an alias for ~lispyville-drag-backward~.

*** Additional Insert Key Theme
The corresponding symbol is =additional-insert=. The default state is normal state. This key theme also corresponds to keybindings from cleverparens additional keybindings.

| key | command |
|-------+------------------------------------------|
| =M-i= | ~lispyville-insert-at-beginning-of-list~ |
| =M-a= | ~lispyville-insert-at-end-of-list~ |
| =M-o= | ~lispyville-open-below-list~ |
| =M-O= | ~lispyville-open-above-list~ |

Unlike cleverparens, these commands work only with lists. ~evil-cp-insert-at-beginning-of-form~, for example, will insert at the beginning of strings as well. To me, it is simpler and more consistent to only consider lists instead of specially handling string atoms. If you would prefer the original behavior, feel free to make an issue, and I can add alternative commands.

** Arrows Key Theme
The corresponding symbol is =arrows=. The default state is normal state. This key theme provides similar keybindings to those from [[https://github.com/tpope/vim-sexp-mappings-for-regular-people][vim-sexp-mappings-for-regular-people]]. It is currently incomplete.

| key | command |
|------+------------------------------------------|
| =<i= | ~lispyville-insert-at-beginning-of-list~ |
| =>i= | ~lispyville-insert-at-end-of-list~ |

Note that the original plugin uses =>I= and =<I= in order not to override the default =<= and =>= used with inner text objects. Since manual indentation is never necessary with lisp (e.g. use =aggressive-indent-mode= or ~lispyville-prettify~ / ~lispy-tab~ instead), this key theme does not attempt to leave the original keybindings intact.

** Escape Key Theme
The corresponding symbol is =escape=. The default states are insert and emacs. See [[#using-both-separately][here]] for more information.

Expand Down
99 changes: 99 additions & 0 deletions lispyville-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
additional-movement
slurp/barf-cp
additional
additional-insert
mark-toggle))
(lispyville-set-key-theme)

Expand Down Expand Up @@ -760,6 +761,104 @@ character after it is not considered as part of the region."
;; "((|b c d) a)"))
)

(ert-deftest lispyville-raise-list ()
;; should work in the basic case
(should (string= (lispyville-with "((|a))"
"M-R")
"(|a)"))
;; should work in a string
(should (string= (lispyville-with "((\"|a\"))"
"M-R")
"(\"|a\")"))
;; should work with a count
(should (string= (lispyville-with "(((|a)))"
"2 M-R")
"(|a)"))
;; should work with a count larger than the max possible count
(should (string= (lispyville-with "(((|a)))"
"3 M-R")
"(|a)")))

(ert-deftest lispyville-insert-at-beginning-of-list ()
;; should work in the basic case
(should (string= (lispyville-with "(a |b c)"
"M-i")
"(|a b c)"))
;; should work in a string
(should (string= (lispyville-with "(a \"|b\" c)"
"M-i")
"(|a \"b\" c)"))
;; should work with a count
(should (string= (lispyville-with "((a |b c))"
"2 M-i")
"(|(a b c))"))
;; should work with a count larger than the max possible count
(should (string= (lispyville-with "((a |b c))"
"3 M-i")
"(|(a b c))")))

(ert-deftest lispyville-insert-at-end-of-list ()
;; should work in the basic case
(should (string= (lispyville-with "(a |b c)"
"M-a")
"(a b c|)"))
;; should work in a string
(should (string= (lispyville-with "(a \"|b\" c)"
"M-a")
"(a \"b\" c|)"))
;; should work with a count
(should (string= (lispyville-with "((a |b c))"
"2 M-a")
"((a b c)|)"))
;; should work with a count larger than the max possible count
(should (string= (lispyville-with "((a |b c))"
"3 M-a")
"((a b c)|)")))

(ert-deftest lispyville-open-below-list ()
;; should work in the basic case
(should (string= (lispyville-with "((|a)\n b)"
"M-o")
"((a)\n |\n b)"))
;; should work with trailing sexps
(should (string= (lispyville-with "((|a) b)"
"M-o")
"((a)\n |b)"))
;; should insert an extra newline at the top-level
(should (string= (lispyville-with "(|a)"
"M-o")
"(a)\n\n|"))
;; should work with a count
(should (string= (lispyville-with "((|a))"
"2 M-o")
"((a))\n\n|"))
;; should work with a count larger than the max possible count
(should (string= (lispyville-with "((|a))"
"3 M-o")
"((a))\n\n|")))

(ert-deftest lispyville-open-above-list ()
;; should work in the basic case
(should (string= (lispyville-with "(a\n (|b))"
"M-O")
"(a\n |\n (b))"))
;; should work with leading sexps
(should (string= (lispyville-with "(a (|b))"
"M-O")
"(a |\n (b))"))
;; should insert an extra newline at the top-level
(should (string= (lispyville-with "(|a)"
"M-O")
"|\n\n(a)"))
;; should work with a count
(should (string= (lispyville-with "((|a))"
"2 M-O")
"|\n\n((a))"))
;; should work with a count larger than the max possible count
(should (string= (lispyville-with "((|a))"
"3 M-O")
"|\n\n((a))")))

;;; * Visual and Special Mark Integration
(ert-deftest lispyville-toggle-mark-type ()
(lispy-define-key lispy-mode-map "m" #'lispyville-toggle-mark-type)
Expand Down
96 changes: 93 additions & 3 deletions lispyville.el
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,16 @@ only has an effect if `lispyville-commands-put-into-special' is nil."
:type 'boolean)

(defcustom lispyville-preferred-lispy-state 'insert
"The preferred evil state for using lispy.
"The preferred evil state for insertion and using lispy.
This is used by any command that should enter special to determine the correct
state."
:group 'lispyville
:type '(choice
(const :tag "Use insert state to get into special." insert)
(const :tag "Use emacs state to get into special." emacs)))

(defvaralias 'lispyville-preferred-state 'lispyville-preferred-lispy-state)

(defcustom lispyville-motions-put-into-special nil
"Applicable motions will enter insert or emacs state.
This will only happen when they are not called with an operator or in visual
Expand Down Expand Up @@ -895,6 +897,75 @@ This is the lispyville equivalent of `lispy-move-up' and

(defalias 'lispyville-move-up 'lispyville-drag-backward)

(evil-define-command lispyville-raise-list (count)
"Raise the current list COUNT times.
This is the lispyville equivalent of `evil-cp-raise-form' except for lists
only."
(interactive "<c>")
(save-excursion
;; unlike `backward-up-list', works in string
(when (lispy--out-backward 1)
(lispy-raise (or count 1)))))

;; ** Additional Insert Key Theme
(evil-define-command lispyville-insert-at-beggining-of-list (count)
"Enter `lispyville-preferred-state' at the beginning of the current list.
With COUNT, move backward/out COUNT lists first. This is the lispyville
equivalent of `evil-cp-insert-at-beginning-of-form' except for lists only."
(interactive "<c>")
(when (lispy--out-backward (or count 1))
(forward-char)
(evil-change-state lispyville-preferred-state)))

(defun lispyville--out-forward (count)
"Like `lispyville--out-forward' but don't return nil if move at least once.
COUNT is passed to `lispy--out-forward'."
(let ((orig-pos (point)))
(lispy--out-forward count)
(not (= (point) orig-pos))))

(evil-define-command lispyville-insert-at-end-of-list (count)
"Enter `lispyville-preferred-state' at the end of the current list.
With COUNT, move forward/out COUNT lists first. This is the lispyville
equivalent of `evil-cp-insert-at-end-of-form' except for lists only."
(interactive "<c>")
(when (lispyville--out-forward (or count 1))
(backward-char)
(evil-change-state lispyville-preferred-state)))

(defun lispyville--top-level-p ()
"Return whether the point is at the top level."
(= (car (syntax-ppss)) 0))

(evil-define-command lispyville-open-below-list (count)
"Enter `lispyville-preferred-state' below the current list and indent.
With COUNT, move forward/out COUNT lists first. When exiting to the top-level,
insert in between two newlines. This is the lispyville equivalent of
`evil-cp-open-below-form' except for lists only. This is somewhat comparable to
`lispy-out-forward-newline' as well"
(interactive "<c>")
(when (lispyville--out-forward (or count 1))
(newline-and-indent)
(when (lispyville--top-level-p)
(insert "\n"))
(evil-change-state lispyville-preferred-state)))

(evil-define-command lispyville-open-above-list (count)
"Enter `lispyville-preferred-state' above the current list and indent.
With COUNT, move backward/out COUNT lists first. When exiting to the top-level,
insert in between two newlines. This is the lispyville equivalent of
`evil-cp-open-above-form' except for lists only."
(interactive "<c>")
(when (lispy--out-backward (or count 1))
(save-excursion
(insert "\n")
(lispy--indent-for-tab))
(lispy--indent-for-tab)
(when (lispyville--top-level-p)
(save-excursion
(insert "\n")))
(evil-change-state lispyville-preferred-state)))

;; * Integration Between Visual State and Lispy's Special Mark State
;; ** Using Both Separately
(defun lispyville-normal-state ()
Expand Down Expand Up @@ -1125,10 +1196,29 @@ When THEME is not given, `lispville-key-theme' will be used instead."
">" #'lispyville-slurp
"<" #'lispyville-barf))
(additional
(or states (setq states '(normal visual)))
(or states (setq states 'normal))
(lispyville--define-key states
(kbd "M-j") #'lispyville-drag-forward
(kbd "M-k") #'lispyville-drag-backward))
(kbd "M-k") #'lispyville-drag-backward
(kbd "M-J") #'lispy-join
(kbd "M-s") #'lispy-splice
(kbd "M-S") #'lispy-split
(kbd "M-r") #'lispy-raise-sexp
(kbd "M-R") #'lispyville-raise-list
(kbd "M-t") #'transpose-sexps
(kbd "M-v") #'lispy-convolute-sexp))
(additional-insert
(or states (setq states 'normal))
(lispyville--define-key states
(kbd "M-i") #'lispyville-insert-at-beggining-of-list
(kbd "M-a") #'lispyville-insert-at-end-of-list
(kbd "M-o") #'lispyville-open-below-list
(kbd "M-O") #'lispyville-open-above-list))
(arrows
(or states (setq states 'normal))
(lispyville--define-key states
"<i" #'lispyville-insert-at-beggining-of-list
">i" #'lispyville-insert-at-end-of-list))
(insert
(lispyville-space-after-insert))
(escape
Expand Down

0 comments on commit df64528

Please sign in to comment.