zsh-workers
 help / color / mirror / code / Atom feed
* New widget "transpose-segments"
@ 2016-01-09 11:03 Sebastian Gniazdowski
  2016-01-09 12:19 ` Jérémie Roquet
                   ` (2 more replies)
  0 siblings, 3 replies; 23+ messages in thread
From: Sebastian Gniazdowski @ 2016-01-09 11:03 UTC (permalink / raw)
  To: Zsh hackers list

[-- Attachment #1: Type: text/plain, Size: 364 bytes --]

Hello
I've attached a new widget "transpose-segments". Works like
"transpose-words", but the "words" are what I call "segments" – parts
of a command obtained by (z) flag. This allows to comfortably swap
arbitrarily quoted things at prompt,

http://asciinema.org/a/5tkda9lr7dju4lh3vt5sj35wi

Can this be commited?

Best regards,
Sebastian Gniazdowski

[-- Attachment #2: transpose-segments.diff --]
[-- Type: text/plain, Size: 2481 bytes --]

diff --git a/Functions/Zle/transpose-segments b/Functions/Zle/transpose-segments
new file mode 100644
index 0000000..313febf
--- /dev/null
+++ b/Functions/Zle/transpose-segments
@@ -0,0 +1,82 @@
+# Transpose segments, i.e. parts of line obtained by (z) flag, i.e.
+# as if zsh parsed the line.
+#
+# Code to activate the functionality with Alt-t:
+# autoload transpose-segments
+# zle -N transpose-segments
+# bindkey "^[t" transpose-segments
+
+local curcontext=":zle:$WIDGET" skip
+local MATCH MBEGIN MEND
+
+# Will remember white spaces before each segment
+typeset -a spaces
+spaces=()
+
+# Working variable for $BUFFER
+local buf="$BUFFER"
+
+# Split the buffer
+typeset -a bufarr
+bufarr=( "${(z)buf}" )
+
+# (z) handles spaces nicely, but we need them for the user
+integer size="$#bufarr"
+integer char_count=0
+integer selected_segment=0
+
+for (( i=1; i<=size; i++ )); do
+    local segment="$bufarr[i]"
+
+    # In general, $buf can start with white spaces
+    # We will not search for them, but instead
+    # search for any char that's current segment's
+    # leading character. So this is an approach that
+    # doesn't trust [::space::]
+
+    local leadchar="$segment[1]"
+    buf="${buf##(#m)[^$leadchar]#}"
+
+    # Remember the spaces
+    spaces[$i]="$MATCH"
+
+    # Count all characters being processed, remove the spaces, then remove segment
+    char_count=char_count+"$#MATCH"+"$#segment"
+    buf="${buf#$MATCH}"
+    MATCH=""
+    buf="${buf#(#m)$segment}"
+
+    # If segment not found, return from the function doing nothing
+    # This of course shoudln't happen
+    [ -z "$MATCH" ] && return 0
+
+    # Detect which segment is active
+    [[ "$selected_segment" -eq 0 && "$char_count" -ge "$CURSOR" ]] && selected_segment=i
+done
+
+
+# What's left in $buf can be only white spaces
+spaces[i]="$buf"
+char_count=char_count+"$#buf"
+
+[[ "$selected_segment" -eq 0 && "$char_count" -ge "$CURSOR" ]] && selected_segment=i-1
+# No active segment found, or it's a first segment? Return. (this shouldn't happen)
+[[ "$selected_segment" -eq "0" || "$selected_segment" -eq "1" ]] && return 0
+
+# Swap segments
+local tmp="$bufarr[selected_segment]"
+bufarr[selected_segment]="$bufarr[selected_segment-1]"
+bufarr[selected_segment-1]="$tmp"
+
+# Build BUFFER
+integer curbkp="$CURSOR"
+BUFFER=""
+for (( i=1; i<=size; i++ )); do
+    BUFFER+="$spaces[i]$bufarr[i]"
+done
+CURSOR="$curbkp"
+
+# Append final white spaces
+BUFFER+="$spaces[i]"
+
+return 0

[-- Attachment #3: transpose-segments --]
[-- Type: application/octet-stream, Size: 2204 bytes --]

# Transpose segments, i.e. parts of line obtained by (z) flag, i.e.
# as if zsh parsed the line.
#
# Code to activate the functionality with Alt-t:
# autoload transpose-segments
# zle -N transpose-segments
# bindkey "^[t" transpose-segments

local curcontext=":zle:$WIDGET" skip
local MATCH MBEGIN MEND

# Will remember white spaces before each segment
typeset -a spaces
spaces=()

# Working variable for $BUFFER
local buf="$BUFFER"

# Split the buffer
typeset -a bufarr
bufarr=( "${(z)buf}" )

# (z) handles spaces nicely, but we need them for the user
integer size="$#bufarr"
integer char_count=0
integer selected_segment=0

for (( i=1; i<=size; i++ )); do
    local segment="$bufarr[i]"

    # In general, $buf can start with white spaces
    # We will not search for them, but instead
    # search for any char that's current segment's
    # leading character. So this is an approach that
    # doesn't trust [::space::]

    local leadchar="$segment[1]"
    buf="${buf##(#m)[^$leadchar]#}"

    # Remember the spaces
    spaces[$i]="$MATCH"

    # Count all characters being processed, remove the spaces, then remove segment
    char_count=char_count+"$#MATCH"+"$#segment"
    buf="${buf#$MATCH}"
    MATCH=""
    buf="${buf#(#m)$segment}"

    # If segment not found, return from the function doing nothing
    # This of course shoudln't happen
    [ -z "$MATCH" ] && return 0

    # Detect which segment is active
    [[ "$selected_segment" -eq 0 && "$char_count" -ge "$CURSOR" ]] && selected_segment=i
done


# What's left in $buf can be only white spaces
spaces[i]="$buf"
char_count=char_count+"$#buf"

[[ "$selected_segment" -eq 0 && "$char_count" -ge "$CURSOR" ]] && selected_segment=i-1
# No active segment found, or it's a first segment? Return. (this shouldn't happen)
[[ "$selected_segment" -eq "0" || "$selected_segment" -eq "1" ]] && return 0

# Swap segments
local tmp="$bufarr[selected_segment]"
bufarr[selected_segment]="$bufarr[selected_segment-1]"
bufarr[selected_segment-1]="$tmp"

# Build BUFFER
integer curbkp="$CURSOR"
BUFFER=""
for (( i=1; i<=size; i++ )); do
    BUFFER+="$spaces[i]$bufarr[i]"
done
CURSOR="$curbkp"

# Append final white spaces
BUFFER+="$spaces[i]"

return 0

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

end of thread, other threads:[~2016-01-12 19:12 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-09 11:03 New widget "transpose-segments" Sebastian Gniazdowski
2016-01-09 12:19 ` Jérémie Roquet
2016-01-09 15:56   ` Sebastian Gniazdowski
2016-01-09 15:55 ` Sebastian Gniazdowski
2016-01-09 15:57   ` Sebastian Gniazdowski
2016-01-09 17:22 ` Bart Schaefer
2016-01-09 17:48   ` transpose-words-match (Re: New widget "transpose-segments") Bart Schaefer
2016-01-09 18:03     ` Sebastian Gniazdowski
2016-01-09 18:18       ` Bart Schaefer
2016-01-11 13:13         ` Sebastian Gniazdowski
2016-01-12  6:26           ` Bart Schaefer
2016-01-12  6:46             ` Bart Schaefer
2016-01-12  9:09               ` Sebastian Gniazdowski
2016-01-12  9:39                 ` Sebastian Gniazdowski
2016-01-12  9:23             ` Sebastian Gniazdowski
2016-01-12  9:38               ` Sebastian Gniazdowski
2016-01-12  9:46               ` Peter Stephenson
2016-01-12 19:12               ` Bart Schaefer
2016-01-09 17:59   ` New widget "transpose-segments" Sebastian Gniazdowski
2016-01-09 19:06     ` Sebastian Gniazdowski
2016-01-12  8:13       ` Bart Schaefer
2016-01-12  8:09     ` Bart Schaefer
2016-01-12  9:50       ` Sebastian Gniazdowski

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