zsh-workers
 help / color / mirror / code / Atom feed
From: Oliver Kiddle <okiddle@yahoo.co.uk>
To: Zsh workers <zsh-workers@zsh.org>
Subject: PATCH: vi-mode case-manipulation
Date: Tue, 28 Jun 2016 16:46:51 +0200	[thread overview]
Message-ID: <2679.1467125211@thecus.kiddle.eu> (raw)

This adds vi upper/lowercase widgets (gU / gu) in C form. There isn't
much difference to the shell widgets but it is possible to have the keys
bound by default and they aren't afflicted by KEYTIMEOUT problems. That
means guu and gUU work as aliases for gugu and gUgU. For consistency
with the naming of the emacs widgets, they are named
vi-up-case and vi-down-case.

Perhaps select-bracketed and quoted would also be better in C form with
something simpler and less likely to be missed by a vim user serving as
a shell widget example.

I think there is some value in providing a shell widget example of how
to read a vi movement. This includes vi-pipe which is like ! in vi. It
uses vi-delete instead of vi-change followed by vi-cmd-mode. Perhaps
there was a reason for using vi-change in my original case change
widgets but if so, I've forgotten what it was.

Oliver

diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 53ae96d..f1208e8 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 80d3f39..1bae0cc 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 0000000..a28f211
--- /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 2b2654c..58310cd 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 f547dbf..3db4207 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 953af24..baa2064 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 */


             reply	other threads:[~2016-06-28 14:53 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-28 14:46 Oliver Kiddle [this message]
2016-06-29 16:33 ` Bart Schaefer
2016-07-24  6:34   ` PATCH: vi-pipe (Re: PATCH: vi-mode case-manipulation) Oliver Kiddle
2016-07-24 21:30     ` Daniel Shahaf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2679.1467125211@thecus.kiddle.eu \
    --to=okiddle@yahoo.co.uk \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).