add the functions needed for some keybindings
[zsh.git] / .zsh / functions / define-pipe-widget
1 # -*- mode:sh -*-
2
3 # Widget from Max Mikhanosha posted to zsh-users list at
4 # http://www.zsh.org/mla/users/2008/msg00708.html
5
6 # define-pipe-widget <widget-name> "template1" "template2" ....
7 #
8 # Defines "pipe widget" templates. Its hard to describe the best way
9 # is through an example:
10 #
11 # define-pipe-widget insert_grep "grep \"@@@\"" "grep -i \"@@@\"" "grep @@@"
12 # define-pipe-widget insert_head "head" "head\n"
13 #
14 # bindkey "\M-g" insert_grep
15 # bindkey "\M-h" insert_head
16 #
17 # Now pressing Alt-G will insert (| represents cursor position)
18 #
19 # On empty command line: grep "|"
20 #
21 # On non-empty command line: <old cmdline> | grep "|"
22 #
23 # Pressing Alt-G one more time cycles through choices
24 # ie:
25 # ... | grep "|"
26 # ... | grep -i "|"
27 # ... | grep
28 #
29 # If template has \n in the end, then it will be auto-accepted:
30 #
31 # Alt-H does: ... | head <cursor here>
32 # 2nd Alt-H does ... | head<Enter>
33 #
34 declare -gA pipe_widgets
35 function define-pipe-widget () {
36 local var=$1
37 local templates=_${var}_templates
38 declare -ga $templates
39 shift
40 set -A $templates $@
41 zle -N $var insert-pipe-command
42 }
43
44 insert-pipe-command () {
45 emulate -L zsh
46 local var=$WIDGET
47 local templates=_${var}_templates
48 local before after auto_accept same patnum
49
50 set nomatch
51 # see if command line is same as in our last invocation
52 if [[ $CURSOR == ${pipe_widgets[cursor_$var]}
53 && $HISTNO == $pipe_widgets[histno_$var]
54 && $BUFFER == $pipe_widgets[buffer_$var] ]] ; then
55 (( patnum = ++pipe_widgets[patnum_$var] ))
56 # wrap around
57 if [[ $patnum -gt ${#${(P)templates}} ]] ; then
58 (( patnum = pipe_widgets[patnum_$var] = 1 ))
59 fi
60 BUFFER=$pipe_widgets[buffer_before_$var]
61 CURSOR=$pipe_widgets[cursor_before_$var]
62 else
63 # start from scratch
64 (( patnum = pipe_widgets[patnum_$var] = 1 ))
65 pipe_widgets[buffer_before_$var]=$BUFFER
66 pipe_widgets[cursor_before_$var]=$CURSOR
67 fi
68 local tmp=${${(P)templates}[$patnum]}
69 if [[ $tmp == *\\n ]] ; then
70 auto_accept=1
71 tmp=$tmp[1,-3]
72 fi
73 # cursor in the end if not specified
74 if [[ $tmp != *@@@* ]] ; then
75 tmp="${tmp}@@@"
76 fi
77 before=${tmp%@@@*}
78 after=${tmp#*@@@}
79 if [[ -n ${LBUFFER## *} ]] ; then
80 RBUFFER+=" | "
81 else
82 if [[ $after == '' && $before[-1] != " " ]] ; then
83 before+=" "
84 fi
85 auto_accept=
86 fi
87 RBUFFER+=$before$after
88 CURSOR=$(( $#BUFFER - $#after))
89 # incase we were in vi mode
90 builtin zle vi-insert
91 if [[ $auto_accept == 1 ]] ; then
92 builtin zle accept-line
93 fi
94 pipe_widgets[histno_$var]=$HISTNO
95 pipe_widgets[buffer_$var]=$BUFFER
96 pipe_widgets[cursor_$var]=$CURSOR
97 }
98
99 define-pipe-widget "$@"