zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: vi-mode case-manipulation
@ 2016-06-28 14:46 Oliver Kiddle
  2016-06-29 16:33 ` Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Oliver Kiddle @ 2016-06-28 14:46 UTC (permalink / raw)
  To: Zsh workers

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 */


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PATCH: vi-mode case-manipulation
  2016-06-28 14:46 PATCH: vi-mode case-manipulation Oliver Kiddle
@ 2016-06-29 16:33 ` Bart Schaefer
  2016-07-24  6:34   ` PATCH: vi-pipe (Re: PATCH: vi-mode case-manipulation) Oliver Kiddle
  0 siblings, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2016-06-29 16:33 UTC (permalink / raw)
  To: Zsh workers

On Jun 28,  4:46pm, Oliver Kiddle wrote:
}
} 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.

At the very least there should be contrib.yo items for select-bracketed
and select-quoted, which presently there are not.

} 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.

I think you've forgotten an "emulate zsh" or the like, since you're
referencing $REPLY and $CUTBUFFER un-quoted.  (Sorry I didn't get to
this before you'd committed.)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* PATCH: vi-pipe (Re: PATCH: vi-mode case-manipulation)
  2016-06-29 16:33 ` Bart Schaefer
@ 2016-07-24  6:34   ` Oliver Kiddle
  2016-07-24 21:30     ` Daniel Shahaf
  0 siblings, 1 reply; 4+ messages in thread
From: Oliver Kiddle @ 2016-07-24  6:34 UTC (permalink / raw)
  To: Zsh workers

On 29 Jun, Bart wrote:
> } 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.
>
> I think you've forgotten an "emulate zsh" or the like, since you're
> referencing $REPLY and $CUTBUFFER un-quoted.  (Sorry I didn't get to
> this before you'd committed.)

Is compatibility ok in the following? RHS of the CUTBUFFER assignment
now has no outer quotes but I think that's ok as it is the rhs of an
assignment.

I also discovered the reason for having used vi-change followed by
vi-cmd-mode in my original case conversion widgets instead of
vi-delete - it has a subtle effect on cursor positioning. Though
we've got a bug that vi-cmd-mode in the middle of a widget will act
like a split-undo.

Furthermore, ! in real vi forces the movement to act linewise. We can force
this by ungetting a V before calling vi-change.

I had thought ! a good example for a shell-based widget because I
couldn't imagine anyone wanting mappings that make it a prefix so
the lack if the VI_OPER flag wouldn't matter. It now occurs to me that
  noremap !o o<Esc>!!
and similarly for O is a useful shortcut. Zsh equivalent if you can
type faster than KEYTIMEOUT is:
  bindkey -as '!o' $'o\e!!'
Or maybe there's a better way to insert the output of a command in vim?

Oliver

diff --git a/Functions/Zle/vi-pipe b/Functions/Zle/vi-pipe
index 2d2e295..028f1e1 100644
--- a/Functions/Zle/vi-pipe
+++ b/Functions/Zle/vi-pipe
@@ -7,16 +7,21 @@
 #   autoload -Uz vi-pipe
 #   bindkey -a '!' vi-pipe
 
+setopt localoptions noksharrays
+
 autoload -Uz read-from-minibuffer
 local _save_cut="$CUTBUFFER" REPLY
 
-# Use the standard vi-delete to accept a vi motion.
-zle .vi-delete || return
+# force movement to default to line mode
+zle -U V
+# Use the standard vi-change to accept a vi motion.
+zle .vi-change || return
 read-from-minibuffer "!"
+zle .vi-cmd-mode
 local _save_cur=$CURSOR
 
 # cut buffer contains the deleted text and can be modified
-CUTBUFFER="$(eval $REPLY <<<$CUTBUFFER)"
+CUTBUFFER=$(eval "$REPLY" <<<"$CUTBUFFER")
 
 # put the modified text back in position.
 if [[ CURSOR -eq 0 || $BUFFER[CURSOR] = $'\n' ]]; then


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: PATCH: vi-pipe (Re: PATCH: vi-mode case-manipulation)
  2016-07-24  6:34   ` PATCH: vi-pipe (Re: PATCH: vi-mode case-manipulation) Oliver Kiddle
@ 2016-07-24 21:30     ` Daniel Shahaf
  0 siblings, 0 replies; 4+ messages in thread
From: Daniel Shahaf @ 2016-07-24 21:30 UTC (permalink / raw)
  To: Oliver Kiddle; +Cc: Zsh workers

Oliver Kiddle wrote on Sun, Jul 24, 2016 at 08:34:59 +0200:
> Furthermore, ! in real vi forces the movement to act linewise. We can force
> this by ungetting a V before calling vi-change.
> 
> I had thought ! a good example for a shell-based widget because I
> couldn't imagine anyone wanting mappings that make it a prefix so
> the lack if the VI_OPER flag wouldn't matter. It now occurs to me that
>   noremap !o o<Esc>!!
> and similarly for O is a useful shortcut. Zsh equivalent if you can
> type faster than KEYTIMEOUT is:
>   bindkey -as '!o' $'o\e!!'
> Or maybe there's a better way to insert the output of a command in vim?

There are «:r !<command>» and «:<range>!<filter>», for example

    :r !pwd
    :%!tr a-z A-Z

Another way is append('.') or i_CTRL-= with systemlist().

Cheers,

Daniel


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-07-24 21:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-28 14:46 PATCH: vi-mode case-manipulation Oliver Kiddle
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

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).