summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--Doc/Zsh/contrib.yo11
-rw-r--r--Doc/Zsh/zle.yo14
-rw-r--r--Functions/Zle/vi-pipe31
-rw-r--r--Src/Zle/iwidgets.list2
-rw-r--r--Src/Zle/zle_keymap.c5
-rw-r--r--Src/Zle/zle_vi.c46
7 files changed, 112 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 4f0a49397..831ea4e69 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
2016-06-29 Oliver Kiddle <opk@zsh.org>
+ * 38770: Src/Zle/zle_keymap.c, Src/Zle/zle_vi.c, Doc/Zsh/zle.yo,
+ Doc/Zsh/contrib.yo, Functions/Zle/vi-pipe: vi upper/lowercase
+ widgets and shell widget example that reads a vi movement
+
* 38752: Src/builtin.c: add comments to explain use of stdout
instead of stderr for the which builtin
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 53ae96dad..f1208e843 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -2968,6 +2968,17 @@ and aliases `tt(globurl)' to `tt(noglob urlglobber)'. This function takes
a local URL apart, attempts to pattern-match the local file portion of the
URL path, and then puts the results back into URL format again.
)
+tindex(vi-pipe)
+item(tt(vi-pipe))(
+This function reads a movement command from the keyboard and then
+prompts for an external command. The part of the buffer covered by
+the movement is piped to the external command and then replaced by
+the command's output. If the movement command is bound to vi-pipe,
+the current line is used.
+
+The function serves as an example for reading a vi movement command
+from within a user-defined widget.
+)
tindex(which-command)
item(tt(which-command))(
This function is a drop-in replacement for the builtin widget
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 80d3f39d8..1bae0ccf7 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -1781,6 +1781,13 @@ tindex(down-case-word)
item(tt(down-case-word) (tt(ESC-L ESC-l)) (unbound) (unbound))(
Convert the current word to all lowercase and move past it.
)
+tindex(vi-down-case)
+item(tt(vi-down-case)) ((unbound) (tt(gu)) (unbound))(
+Read a movement command from the keyboard, and convert all characters
+from the cursor position to the endpoint of the movement to lowercase.
+If the movement command is tt(vi-down-case), swap the case of all
+characters on the current line.
+)
tindex(kill-word)
item(tt(kill-word) (tt(ESC-D ESC-d)) (unbound) (unbound))(
Kill the current word.
@@ -1946,6 +1953,13 @@ tindex(vi-unindent)
item(tt(vi-unindent) (unbound) (tt(<)) (unbound))(
Unindent a number of lines.
)
+tindex(vi-up-case)
+item(tt(vi-up-case)) ((unbound) (tt(gU)) (unbound))(
+Read a movement command from the keyboard, and convert all characters
+from the cursor position to the endpoint of the movement to lowercase.
+If the movement command is tt(vi-up-case), swap the case of all
+characters on the current line.
+)
tindex(up-case-word)
item(tt(up-case-word) (tt(ESC-U ESC-u)) (unbound) (unbound))(
Convert the current word to all caps and move past it.
diff --git a/Functions/Zle/vi-pipe b/Functions/Zle/vi-pipe
new file mode 100644
index 000000000..2d2e29587
--- /dev/null
+++ b/Functions/Zle/vi-pipe
@@ -0,0 +1,31 @@
+# Example of a widget that takes a vi motion
+
+# Filter part of buffer corresponding to a vi motion through an external
+# program.
+
+# To enable with vi compatible bindings use:
+# autoload -Uz vi-pipe
+# bindkey -a '!' vi-pipe
+
+autoload -Uz read-from-minibuffer
+local _save_cut="$CUTBUFFER" REPLY
+
+# Use the standard vi-delete to accept a vi motion.
+zle .vi-delete || return
+read-from-minibuffer "!"
+local _save_cur=$CURSOR
+
+# cut buffer contains the deleted text and can be modified
+CUTBUFFER="$(eval $REPLY <<<$CUTBUFFER)"
+
+# put the modified text back in position.
+if [[ CURSOR -eq 0 || $BUFFER[CURSOR] = $'\n' ]]; then
+ # at the beginning of a line, vi-delete won't have moved the cursor
+ # back to a previous line
+ zle .vi-put-before -n 1
+else
+ zle .vi-put-after -n 1
+fi
+
+# restore cut buffer and cursor to the start of the range
+CUTBUFFER="$_save_cut" CURSOR="$_save_cur"
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index 2b2654c5d..58310cd74 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -143,6 +143,7 @@
"vi-delete", videlete, ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_VIOPER
"vi-delete-char", videletechar, ZLE_KEEPSUFFIX
"vi-digit-or-beginning-of-line", vidigitorbeginningofline, 0
+"vi-down-case", vidowncase, ZLE_LASTCOL | ZLE_VIOPER
"vi-down-line-or-history", vidownlineorhistory, ZLE_LINEMOVE
"vi-end-of-line", viendofline, ZLE_LASTCOL
"vi-fetch-history", vifetchhistory, ZLE_LINEMOVE
@@ -188,6 +189,7 @@
"vi-swap-case", viswapcase, ZLE_LASTCOL
"vi-undo-change", viundochange, ZLE_KEEPSUFFIX
"vi-unindent", viunindent, ZLE_LASTCOL | ZLE_VIOPER
+"vi-up-case", viupcase, ZLE_LASTCOL | ZLE_VIOPER
"vi-up-line-or-history", viuplineorhistory, ZLE_LINEMOVE
"vi-yank", viyank, ZLE_LASTCOL | ZLE_VIOPER
"vi-yank-eol", viyankeol, 0
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index f547dbf17..3db4207d9 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -1374,8 +1374,11 @@ default_bindings(void)
bindkey(amap, "ge", refthingy(t_vibackwardwordend), NULL);
bindkey(amap, "gE", refthingy(t_vibackwardblankwordend), NULL);
bindkey(amap, "gg", refthingy(t_beginningofbufferorhistory), NULL);
- bindkey(amap, "g~", refthingy(t_vioperswapcase), NULL);
+ bindkey(amap, "gu", refthingy(t_vidowncase), NULL);
+ bindkey(amap, "gU", refthingy(t_viupcase), NULL);
bindkey(amap, "g~~", NULL, "g~g~");
+ bindkey(amap, "guu", NULL, "gugu");
+ bindkey(amap, "gUU", NULL, "gUgU");
/* emacs mode: arrow keys */
add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A');
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 953af2401..baa2064e9 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -731,6 +731,52 @@ vioperswapcase(UNUSED(char **args))
/**/
int
+viupcase(UNUSED(char **args))
+{
+ int oldcs, c2, ret = 1;
+
+ /* get the range */
+ startvichange(1);
+ if ((c2 = getvirange(0)) != -1) {
+ oldcs = zlecs;
+ /* covert the case of all letters within range */
+ while (zlecs < c2) {
+ zleline[zlecs] = ZC_toupper(zleline[zlecs]);
+ INCCS();
+ }
+ /* go back to the first line of the range */
+ zlecs = oldcs;
+ ret = 0;
+ }
+ vichgflag = 0;
+ return ret;
+}
+
+/**/
+int
+vidowncase(UNUSED(char **args))
+{
+ int oldcs, c2, ret = 1;
+
+ /* get the range */
+ startvichange(1);
+ if ((c2 = getvirange(0)) != -1) {
+ oldcs = zlecs;
+ /* convert the case of all letters within range */
+ while (zlecs < c2) {
+ zleline[zlecs] = ZC_tolower(zleline[zlecs]);
+ INCCS();
+ }
+ /* go back to the first line of the range */
+ zlecs = oldcs;
+ ret = 0;
+ }
+ vichgflag = 0;
+ return ret;
+}
+
+/**/
+int
virepeatchange(UNUSED(char **args))
{
/* make sure we have a change to repeat */