Commit 7378b55deda3ce4704448474b3a383a738317de3

Authored by mj
1 parent f4c442e7d6
Exists in master and in 1 other branch 02-merge

Squashed 'repos/robbyrussell/oh-my-zsh/' changes from 22632aa..00344f7

00344f7 Merge branch 'ferenczy-cygwin'
63d7500 Added setting of the window title in Cygwin
b457ae2 Merge pull request #4651 from ionelmc/patch-1
f7ed724 Merge pull request #3321 from moul/pr-tmux-cssh
d55111f Support all kinds of putty-like terminal strings.
78af29e Merge branch 'marking-master'
584e0a6 Use shwordsplit in open_command()
afdfe23 Add empty string parameter to start command
0a79f1e make this work in the git-for-windows SDK
a19ec10 Merge pull request #4649 from psprint/master
39e4dfb Updated README.md
c885290 Renamed README.txt to README.md
711c1bc Add support for "putty" $TERM in termsupport.zsh
c2b4d9f znt: n-history supports multi-line cmds and starts with current buffer
afd28bf Merge pull request #4368 from psprint/master
fea74b4 Fix open_command nohup call
ef031df Merge pull request #4207 from mpscholten/master
46824b3 Merge pull request #4191 from apjanke/vi-mode-fix-smkx
d3b9520 Merge branch 'apjanke-z-allow-custom'
2205aa4 z plugin: fix loading from custom location
85d9495 Merge pull request #4181 from posva/z
96108e1 Merge branch 'apjanke-histsubstr-update-2015_04_26'
7e39839 history-substring-search: update to upstream version 2015-09-28
d7e6ba0 history-substring-search: add a script to automatically update OMZ from the upstream repo
befb5b6 Merge pull request #4634 from mfaerevaag/master
424800e Merge pull request #4539 from Gnouc/master
90e1630 Merge pull request #4443 from apjanke/github-update
dfe10af Merge branch 'apjanke-termsupport-protect-subshell'
f0981d5 termsupport: protect subshell with quotes
d2e1c71 Merge pull request #4534 from mcornella/fix-open_command-nohup-tmux
ebfba0e Drop the use of nohup on OSX for tmux compatibility
7d9648e [wd] update minor version (v0.4.2)
8ea7735 vi-mode: remove line-init/finish widgets that broken terminfo keybindings
24492a2 Update github plugin to work with current hub versions
d336396 Updated z version
c25002a Removing `source` command
4c292ea Initial commit of Zsh Navigation Tools
53a6335 Change coding style
45cd2df Update uninstall.sh
d351c76 Also accept any forms of yes as an answer to the "do you want to update?" prompt
b7fcdc7 [tmux-cssh plugin] Initial version

git-subtree-dir: repos/robbyrussell/oh-my-zsh
git-subtree-split: 00344f7628099ad614a9db1b4a4d71155dc932ef

Showing 47 changed files with 3165 additions and 592 deletions Inline Diff

1 function zsh_stats() { 1 function zsh_stats() {
2 fc -l 1 | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n20 2 fc -l 1 | awk '{CMD[$2]++;count++;}END { for (a in CMD)print CMD[a] " " CMD[a]/count*100 "% " a;}' | grep -v "./" | column -c3 -s " " -t | sort -nr | nl | head -n20
3 } 3 }
4 4
5 function uninstall_oh_my_zsh() { 5 function uninstall_oh_my_zsh() {
6 env ZSH=$ZSH /bin/sh $ZSH/tools/uninstall.sh 6 env ZSH=$ZSH /bin/sh $ZSH/tools/uninstall.sh
7 } 7 }
8 8
9 function upgrade_oh_my_zsh() { 9 function upgrade_oh_my_zsh() {
10 env ZSH=$ZSH /bin/sh $ZSH/tools/upgrade.sh 10 env ZSH=$ZSH /bin/sh $ZSH/tools/upgrade.sh
11 } 11 }
12 12
13 function take() { 13 function take() {
14 mkdir -p $1 14 mkdir -p $1
15 cd $1 15 cd $1
16 } 16 }
17 17
18 function open_command() { 18 function open_command() {
19 emulate -L zsh
20 setopt shwordsplit
21
19 local open_cmd 22 local open_cmd
20 23
21 # define the open command 24 # define the open command
22 case "$OSTYPE" in 25 case "$OSTYPE" in
23 darwin*) open_cmd="open" ;; 26 darwin*) open_cmd='open' ;;
24 cygwin*) open_cmd="cygstart" ;; 27 cygwin*) open_cmd='cygstart' ;;
25 linux*) open_cmd="xdg-open" ;; 28 linux*) open_cmd='xdg-open' ;;
29 msys*) open_cmd='start ""' ;;
26 *) echo "Platform $OSTYPE not supported" 30 *) echo "Platform $OSTYPE not supported"
27 return 1 31 return 1
28 ;; 32 ;;
29 esac 33 esac
30 34
31 nohup $open_cmd "$@" &>/dev/null 35 # don't use nohup on OSX
36 if [[ "$OSTYPE" == darwin* ]]; then
37 $open_cmd "$@" &>/dev/null
38 else
39 nohup $open_cmd "$@" &>/dev/null
40 fi
32 } 41 }
33 42
34 # 43 #
35 # Get the value of an alias. 44 # Get the value of an alias.
36 # 45 #
37 # Arguments: 46 # Arguments:
38 # 1. alias - The alias to get its value from 47 # 1. alias - The alias to get its value from
39 # STDOUT: 48 # STDOUT:
40 # The value of alias $1 (if it has one). 49 # The value of alias $1 (if it has one).
41 # Return value: 50 # Return value:
42 # 0 if the alias was found, 51 # 0 if the alias was found,
43 # 1 if it does not exist 52 # 1 if it does not exist
44 # 53 #
45 function alias_value() { 54 function alias_value() {
46 alias "$1" | sed "s/^$1='\(.*\)'$/\1/" 55 alias "$1" | sed "s/^$1='\(.*\)'$/\1/"
47 test $(alias "$1") 56 test $(alias "$1")
48 } 57 }
49 58
50 # 59 #
51 # Try to get the value of an alias, 60 # Try to get the value of an alias,
52 # otherwise return the input. 61 # otherwise return the input.
53 # 62 #
54 # Arguments: 63 # Arguments:
55 # 1. alias - The alias to get its value from 64 # 1. alias - The alias to get its value from
56 # STDOUT: 65 # STDOUT:
57 # The value of alias $1, or $1 if there is no alias $1. 66 # The value of alias $1, or $1 if there is no alias $1.
58 # Return value: 67 # Return value:
59 # Always 0 68 # Always 0
60 # 69 #
61 function try_alias_value() { 70 function try_alias_value() {
62 alias_value "$1" || echo "$1" 71 alias_value "$1" || echo "$1"
63 } 72 }
64 73
65 # 74 #
66 # Set variable "$1" to default value "$2" if "$1" is not yet defined. 75 # Set variable "$1" to default value "$2" if "$1" is not yet defined.
67 # 76 #
68 # Arguments: 77 # Arguments:
69 # 1. name - The variable to set 78 # 1. name - The variable to set
70 # 2. val - The default value 79 # 2. val - The default value
71 # Return value: 80 # Return value:
72 # 0 if the variable exists, 3 if it was set 81 # 0 if the variable exists, 3 if it was set
73 # 82 #
74 function default() { 83 function default() {
75 test `typeset +m "$1"` && return 0 84 test `typeset +m "$1"` && return 0
76 typeset -g "$1"="$2" && return 3 85 typeset -g "$1"="$2" && return 3
77 } 86 }
78 87
79 # 88 #
80 # Set enviroment variable "$1" to default value "$2" if "$1" is not yet defined. 89 # Set enviroment variable "$1" to default value "$2" if "$1" is not yet defined.
81 # 90 #
82 # Arguments: 91 # Arguments:
83 # 1. name - The env variable to set 92 # 1. name - The env variable to set
84 # 2. val - The default value 93 # 2. val - The default value
85 # Return value: 94 # Return value:
86 # 0 if the env variable exists, 3 if it was set 95 # 0 if the env variable exists, 3 if it was set
87 # 96 #
88 function env_default() { 97 function env_default() {
89 env | grep -q "^$1=" && return 0 98 env | grep -q "^$1=" && return 0
90 export "$1=$2" && return 3 99 export "$1=$2" && return 3
91 } 100 }
92 101
93 102
94 # Required for $langinfo 103 # Required for $langinfo
95 zmodload zsh/langinfo 104 zmodload zsh/langinfo
96 105
97 # URL-encode a string 106 # URL-encode a string
98 # 107 #
99 # Encodes a string using RFC 2396 URL-encoding (%-escaped). 108 # Encodes a string using RFC 2396 URL-encoding (%-escaped).
100 # See: https://www.ietf.org/rfc/rfc2396.txt 109 # See: https://www.ietf.org/rfc/rfc2396.txt
101 # 110 #
102 # By default, reserved characters and unreserved "mark" characters are 111 # By default, reserved characters and unreserved "mark" characters are
103 # not escaped by this function. This allows the common usage of passing 112 # not escaped by this function. This allows the common usage of passing
104 # an entire URL in, and encoding just special characters in it, with 113 # an entire URL in, and encoding just special characters in it, with
105 # the expectation that reserved and mark characters are used appropriately. 114 # the expectation that reserved and mark characters are used appropriately.
106 # The -r and -m options turn on escaping of the reserved and mark characters, 115 # The -r and -m options turn on escaping of the reserved and mark characters,
107 # respectively, which allows arbitrary strings to be fully escaped for 116 # respectively, which allows arbitrary strings to be fully escaped for
108 # embedding inside URLs, where reserved characters might be misinterpreted. 117 # embedding inside URLs, where reserved characters might be misinterpreted.
109 # 118 #
110 # Prints the encoded string on stdout. 119 # Prints the encoded string on stdout.
111 # Returns nonzero if encoding failed. 120 # Returns nonzero if encoding failed.
112 # 121 #
113 # Usage: 122 # Usage:
114 # omz_urlencode [-r] [-m] <string> 123 # omz_urlencode [-r] [-m] [-P] <string>
115 # 124 #
116 # -r causes reserved characters (;/?:@&=+$,) to be escaped 125 # -r causes reserved characters (;/?:@&=+$,) to be escaped
117 # 126 #
118 # -m causes "mark" characters (_.!~*''()-) to be escaped 127 # -m causes "mark" characters (_.!~*''()-) to be escaped
119 # 128 #
120 # -P causes spaces to be encoded as '%20' instead of '+' 129 # -P causes spaces to be encoded as '%20' instead of '+'
121 function omz_urlencode() { 130 function omz_urlencode() {
122 emulate -L zsh 131 emulate -L zsh
123 zparseopts -D -E -a opts r m P 132 zparseopts -D -E -a opts r m P
124 133
125 local in_str=$1 134 local in_str=$1
126 local url_str="" 135 local url_str=""
127 local spaces_as_plus 136 local spaces_as_plus
128 if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi 137 if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi
129 local str="$in_str" 138 local str="$in_str"
130 139
131 # URLs must use UTF-8 encoding; convert str to UTF-8 if required 140 # URLs must use UTF-8 encoding; convert str to UTF-8 if required
132 local encoding=$langinfo[CODESET] 141 local encoding=$langinfo[CODESET]
133 local safe_encodings 142 local safe_encodings
134 safe_encodings=(UTF-8 utf8 US-ASCII) 143 safe_encodings=(UTF-8 utf8 US-ASCII)
135 if [[ -z ${safe_encodings[(r)$encoding]} ]]; then 144 if [[ -z ${safe_encodings[(r)$encoding]} ]]; then
136 str=$(echo -E "$str" | iconv -f $encoding -t UTF-8) 145 str=$(echo -E "$str" | iconv -f $encoding -t UTF-8)
137 if [[ $? != 0 ]]; then 146 if [[ $? != 0 ]]; then
138 echo "Error converting string from $encoding to UTF-8" >&2 147 echo "Error converting string from $encoding to UTF-8" >&2
139 return 1 148 return 1
140 fi 149 fi
141 fi 150 fi
142 151
143 # Use LC_CTYPE=C to process text byte-by-byte 152 # Use LC_CTYPE=C to process text byte-by-byte
144 local i byte ord LC_ALL=C 153 local i byte ord LC_ALL=C
145 export LC_ALL 154 export LC_ALL
146 local reserved=';/?:@&=+$,' 155 local reserved=';/?:@&=+$,'
147 local mark='_.!~*''()-' 156 local mark='_.!~*''()-'
148 local dont_escape="[A-Za-z0-9" 157 local dont_escape="[A-Za-z0-9"
149 if [[ -z $opts[(r)-r] ]]; then 158 if [[ -z $opts[(r)-r] ]]; then
150 dont_escape+=$reserved 159 dont_escape+=$reserved
151 fi 160 fi
152 # $mark must be last because of the "-" 161 # $mark must be last because of the "-"
153 if [[ -z $opts[(r)-m] ]]; then 162 if [[ -z $opts[(r)-m] ]]; then
154 dont_escape+=$mark 163 dont_escape+=$mark
155 fi 164 fi
156 dont_escape+="]" 165 dont_escape+="]"
157 166
158 # Implemented to use a single printf call and avoid subshells in the loop, 167 # Implemented to use a single printf call and avoid subshells in the loop,
159 # for performance (primarily on Windows). 168 # for performance (primarily on Windows).
160 local url_str="" 169 local url_str=""
161 for (( i = 1; i <= ${#str}; ++i )); do 170 for (( i = 1; i <= ${#str}; ++i )); do
162 byte="$str[i]" 171 byte="$str[i]"
163 if [[ "$byte" =~ "$dont_escape" ]]; then 172 if [[ "$byte" =~ "$dont_escape" ]]; then
164 url_str+="$byte" 173 url_str+="$byte"
165 else 174 else
166 if [[ "$byte" == " " && -n $spaces_as_plus ]]; then 175 if [[ "$byte" == " " && -n $spaces_as_plus ]]; then
167 url_str+="+" 176 url_str+="+"
168 else 177 else
169 ord=$(( [##16] #byte )) 178 ord=$(( [##16] #byte ))
170 url_str+="%$ord" 179 url_str+="%$ord"
171 fi 180 fi
172 fi 181 fi
173 done 182 done
174 echo -E "$url_str" 183 echo -E "$url_str"
175 } 184 }
176 185
177 # URL-decode a string 186 # URL-decode a string
178 # 187 #
179 # Decodes a RFC 2396 URL-encoded (%-escaped) string. 188 # Decodes a RFC 2396 URL-encoded (%-escaped) string.
180 # This decodes the '+' and '%' escapes in the input string, and leaves 189 # This decodes the '+' and '%' escapes in the input string, and leaves
181 # other characters unchanged. Does not enforce that the input is a 190 # other characters unchanged. Does not enforce that the input is a
182 # valid URL-encoded string. This is a convenience to allow callers to 191 # valid URL-encoded string. This is a convenience to allow callers to
183 # pass in a full URL or similar strings and decode them for human 192 # pass in a full URL or similar strings and decode them for human
184 # presentation. 193 # presentation.
185 # 194 #
186 # Outputs the encoded string on stdout. 195 # Outputs the encoded string on stdout.
187 # Returns nonzero if encoding failed. 196 # Returns nonzero if encoding failed.
188 # 197 #
189 # Usage: 198 # Usage:
190 # omz_urldecode <urlstring> - prints decoded string followed by a newline 199 # omz_urldecode <urlstring> - prints decoded string followed by a newline
191 function omz_urldecode { 200 function omz_urldecode {
192 emulate -L zsh 201 emulate -L zsh
193 local encoded_url=$1 202 local encoded_url=$1
194 203
195 # Work bytewise, since URLs escape UTF-8 octets 204 # Work bytewise, since URLs escape UTF-8 octets
196 local caller_encoding=$langinfo[CODESET] 205 local caller_encoding=$langinfo[CODESET]
197 local LC_ALL=C 206 local LC_ALL=C
198 export LC_ALL 207 export LC_ALL
199 208
200 # Change + back to ' ' 209 # Change + back to ' '
201 local tmp=${encoded_url:gs/+/ /} 210 local tmp=${encoded_url:gs/+/ /}
202 # Protect other escapes to pass through the printf unchanged 211 # Protect other escapes to pass through the printf unchanged
203 tmp=${tmp:gs/\\/\\\\/} 212 tmp=${tmp:gs/\\/\\\\/}
204 # Handle %-escapes by turning them into `\xXX` printf escapes 213 # Handle %-escapes by turning them into `\xXX` printf escapes
205 tmp=${tmp:gs/%/\\x/} 214 tmp=${tmp:gs/%/\\x/}
206 local decoded 215 local decoded
207 eval "decoded=\$'$tmp'" 216 eval "decoded=\$'$tmp'"
208 217
209 # Now we have a UTF-8 encoded string in the variable. We need to re-encode 218 # Now we have a UTF-8 encoded string in the variable. We need to re-encode
210 # it if caller is in a non-UTF-8 locale. 219 # it if caller is in a non-UTF-8 locale.
211 local safe_encodings 220 local safe_encodings
212 safe_encodings=(UTF-8 utf8 US-ASCII) 221 safe_encodings=(UTF-8 utf8 US-ASCII)
213 if [[ -z ${safe_encodings[(r)$caller_encoding]} ]]; then 222 if [[ -z ${safe_encodings[(r)$caller_encoding]} ]]; then
214 decoded=$(echo -E "$decoded" | iconv -f UTF-8 -t $caller_encoding) 223 decoded=$(echo -E "$decoded" | iconv -f UTF-8 -t $caller_encoding)
215 if [[ $? != 0 ]]; then 224 if [[ $? != 0 ]]; then
216 echo "Error converting string from UTF-8 to $caller_encoding" >&2 225 echo "Error converting string from UTF-8 to $caller_encoding" >&2
217 return 1 226 return 1
218 fi 227 fi
219 fi 228 fi
220 229
221 echo -E "$decoded" 230 echo -E "$decoded"
222 } 231 }
223
1 # Set terminal window and tab/icon title 1 # Set terminal window and tab/icon title
2 # 2 #
3 # usage: title short_tab_title [long_window_title] 3 # usage: title short_tab_title [long_window_title]
4 # 4 #
5 # See: http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#ss3.1 5 # See: http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#ss3.1
6 # Fully supports screen, iterm, and probably most modern xterm and rxvt 6 # Fully supports screen, iterm, and probably most modern xterm and rxvt
7 # (In screen, only short_tab_title is used) 7 # (In screen, only short_tab_title is used)
8 # Limited support for Apple Terminal (Terminal can't set window and tab separately) 8 # Limited support for Apple Terminal (Terminal can't set window and tab separately)
9 function title { 9 function title {
10 emulate -L zsh 10 emulate -L zsh
11 setopt prompt_subst 11 setopt prompt_subst
12 12
13 [[ "$EMACS" == *term* ]] && return 13 [[ "$EMACS" == *term* ]] && return
14 14
15 # if $2 is unset use $1 as default 15 # if $2 is unset use $1 as default
16 # if it is set and empty, leave it as is 16 # if it is set and empty, leave it as is
17 : ${2=$1} 17 : ${2=$1}
18 18
19 if [[ "$TERM" == screen* ]]; then 19 if [[ "$TERM" == screen* ]]; then
20 print -Pn "\ek$1:q\e\\" #set screen hardstatus, usually truncated at 20 chars 20 print -Pn "\ek$1:q\e\\" #set screen hardstatus, usually truncated at 20 chars
21 elif [[ "$TERM" == xterm* ]] || [[ "$TERM" == rxvt* ]] || [[ "$TERM" == ansi ]] || [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then 21 elif [[ "$TERM" == xterm* ]] || [[ "$TERM" == putty* ]] || [[ "$TERM" == rxvt* ]] || [[ "$TERM" == ansi ]] || [[ "$TERM" == cygwin ]] || [[ "$TERM_PROGRAM" == "iTerm.app" ]]; then
22 print -Pn "\e]2;$2:q\a" #set window name 22 print -Pn "\e]2;$2:q\a" #set window name
23 print -Pn "\e]1;$1:q\a" #set icon (=tab) name 23 print -Pn "\e]1;$1:q\a" #set icon (=tab) name
24 fi 24 fi
25 } 25 }
26 26
27 ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" #15 char left truncated PWD 27 ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" #15 char left truncated PWD
28 ZSH_THEME_TERM_TITLE_IDLE="%n@%m: %~" 28 ZSH_THEME_TERM_TITLE_IDLE="%n@%m: %~"
29 # Avoid duplication of directory in terminals with independent dir display 29 # Avoid duplication of directory in terminals with independent dir display
30 if [[ $TERM_PROGRAM == Apple_Terminal ]]; then 30 if [[ $TERM_PROGRAM == Apple_Terminal ]]; then
31 ZSH_THEME_TERM_TITLE_IDLE="%n@%m" 31 ZSH_THEME_TERM_TITLE_IDLE="%n@%m"
32 fi 32 fi
33 33
34 # Runs before showing the prompt 34 # Runs before showing the prompt
35 function omz_termsupport_precmd { 35 function omz_termsupport_precmd {
36 emulate -L zsh 36 emulate -L zsh
37 if [[ $DISABLE_AUTO_TITLE == true ]]; then 37 if [[ $DISABLE_AUTO_TITLE == true ]]; then
38 return 38 return
39 fi 39 fi
40 40
41 title $ZSH_THEME_TERM_TAB_TITLE_IDLE $ZSH_THEME_TERM_TITLE_IDLE 41 title $ZSH_THEME_TERM_TAB_TITLE_IDLE $ZSH_THEME_TERM_TITLE_IDLE
42 } 42 }
43 43
44 # Runs before executing the command 44 # Runs before executing the command
45 function omz_termsupport_preexec { 45 function omz_termsupport_preexec {
46 emulate -L zsh 46 emulate -L zsh
47 if [[ $DISABLE_AUTO_TITLE == true ]]; then 47 if [[ $DISABLE_AUTO_TITLE == true ]]; then
48 return 48 return
49 fi 49 fi
50 50
51 setopt extended_glob 51 setopt extended_glob
52 52
53 # cmd name only, or if this is sudo or ssh, the next cmd 53 # cmd name only, or if this is sudo or ssh, the next cmd
54 local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%} 54 local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}
55 local LINE="${2:gs/%/%%}" 55 local LINE="${2:gs/%/%%}"
56 56
57 title '$CMD' '%100>...>$LINE%<<' 57 title '$CMD' '%100>...>$LINE%<<'
58 } 58 }
59 59
60 precmd_functions+=(omz_termsupport_precmd) 60 precmd_functions+=(omz_termsupport_precmd)
61 preexec_functions+=(omz_termsupport_preexec) 61 preexec_functions+=(omz_termsupport_preexec)
62 62
63 63
64 # Keep Apple Terminal.app's current working directory updated 64 # Keep Apple Terminal.app's current working directory updated
65 # Based on this answer: http://superuser.com/a/315029 65 # Based on this answer: http://superuser.com/a/315029
66 # With extra fixes to handle multibyte chars and non-UTF-8 locales 66 # With extra fixes to handle multibyte chars and non-UTF-8 locales
67 67
68 if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]]; then 68 if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]]; then
69 69
70 # Emits the control sequence to notify Terminal.app of the cwd 70 # Emits the control sequence to notify Terminal.app of the cwd
71 function update_terminalapp_cwd() { 71 function update_terminalapp_cwd() {
72 emulate -L zsh 72 emulate -L zsh
73 # Identify the directory using a "file:" scheme URL, including 73 # Identify the directory using a "file:" scheme URL, including
74 # the host name to disambiguate local vs. remote paths. 74 # the host name to disambiguate local vs. remote paths.
75 75
76 # Percent-encode the pathname. 76 # Percent-encode the pathname.
77 local URL_PATH=$(omz_urlencode -P $PWD) 77 local URL_PATH="$(omz_urlencode -P $PWD)"
78 [[ $? != 0 ]] && return 1 78 [[ $? != 0 ]] && return 1
79 local PWD_URL="file://$HOST$URL_PATH" 79 local PWD_URL="file://$HOST$URL_PATH"
80 # Undocumented Terminal.app-specific control sequence 80 # Undocumented Terminal.app-specific control sequence
81 printf '\e]7;%s\a' $PWD_URL 81 printf '\e]7;%s\a' $PWD_URL
82 } 82 }
83 83
84 # Use a precmd hook instead of a chpwd hook to avoid contaminating output 84 # Use a precmd hook instead of a chpwd hook to avoid contaminating output
85 precmd_functions+=(update_terminalapp_cwd) 85 precmd_functions+=(update_terminalapp_cwd)
86 # Run once to get initial cwd set 86 # Run once to get initial cwd set
87 update_terminalapp_cwd 87 update_terminalapp_cwd
88 fi 88 fi
89 89
plugins/github/README.md
File was created 1 # github
2
3 This plugin supports working with GitHub the command line. It provides a few things:
4
5 * Sets up the `hub` wrapper and completions for the `git` command if you have `hub` installed.
6 * Completion for the `github` Ruby gem.
7 * Convenience functions for working with repos and URLs.
8
9 ### Functions
10
11 * `empty_gh` - Creates a new empty repo (with a `README.md`) and pushes it to GitHub
12 * `new_gh` - Initializes an existing directory as a repo and pushes it to GitHub
13 * `exist_gh` - Takes an existing repo and pushes it to GitHub
14 * `git.io` - Shortens a URL using [git.io](http://git.io)
15
16
17 ## Installation
18
19 [Hub](http://github.com/github/hub) needs to be installed if you want to use it. On OS X with Homebrew, this can be done with `brew install hub`. The `hub` completion definition needs to be added to your `$FPATH` before initializing OMZ.
20
21 The [`github` Ruby gem](http://github.com/defunkt/github-gem) needs to be installed if you want to use it.
22
23 ### Configuration
24
25 These settings affect `github`'s behavior.
26
27 #### Environment variables
28
29 * `$GITHUB_USER`
30 * `$GITHUB_PASSWORD`
31
32 #### Git configuration options
33
34 * `github.user` - GitHub username for repo operations
35
36 See `man hub` for more details.
37
38 ### Homebrew installation note
39
40 If you have installed `hub` using Homebrew, its completions may not be on your `$FPATH` if you are using the system `zsh`. Homebrew installs `zsh` completion definitions to `/usr/local/share/zsh/site-functions`, which on `$FPATH` for the Homebrew-installed `zsh`, but not for the system `zsh`. If you want it to work with the system `zsh`, add this to your `~/.zshrc` before it sources `oh-my-zsh.sh`.
41
42 ```zsh
43 if (( ! ${fpath[(I)/usr/local/share/zsh/site-functions]} )); then
44 FPATH=/usr/local/share/zsh/site-functions:$FPATH
45 fi
46 ```
47
plugins/github/_github
1 #compdef github File was deleted
2 #autoload
3
4 # in order to make this work, you will need to have the github gem installed
5 # http://github.com/defunkt/github-gem
6
7 # github zsh completion, based on homebrew completion
8
9 local -a _1st_arguments
10 _1st_arguments=(
11 'browse:Open this repo in a web browser'
12 'clone:Clone a repo'
13 'config:Automatically set configuration info, or pass args to specify'
14 'create-from-local:Create a new GitHub repository from the current local repository'
15 'create:Create a new empty GitHub repository'
16 'fetch:Fetch from a remote to a local branch'
17 'fetch_all:Fetch all refs from a user'
18 'fork:Forks a GitHub repository'
19 'home:Open this repos master branch in a web browser'
20 'ignore:Ignore a SHA from github network commits'
21 'info:Info about this project'
22 'issues:Project issues tools'
23 'network:Project network tools - sub-commands : web [user], list, fetch, commits'
24 'open:Open the given user/project in a web browser'
25 'pull-request:Generate the text for a pull request'
26 'pull:Pull from a remote'
27 'search:Search GitHub for the given repository name'
28 'track:Track another users repository'
29 )
30
31 local expl
32 local -a pkgs installed_pkgs
33
34 _arguments \
35 '*:: :->subcmds' && return 0
36
37 if (( CURRENT == 1 )); then
38 _describe -t commands "github subcommand" _1st_arguments
39 return
40 fi
41 1 #compdef github
plugins/github/github.plugin.zsh
1 # Setup hub function for git, if it is available; http://github.com/defunkt/hub 1 # Set up hub wrapper for git, if it is available; http://github.com/github/hub
2 if [ "$commands[(I)hub]" ] && [ "$commands[(I)ruby]" ]; then 2 if [ "$commands[(I)hub]" ]; then
3 # Autoload _git completion functions 3 if hub --version &>/dev/null; then
4 if declare -f _git > /dev/null; then 4 eval $(hub alias -s zsh)
5 _git 5 fi
6 fi
7
8 if declare -f _git_commands > /dev/null; then
9 _hub_commands=(
10 'alias:show shell instructions for wrapping git'
11 'pull-request:open a pull request on GitHub'
12 'fork:fork origin repo on GitHub'
13 'create:create new repo on GitHub for the current project'
14 'browse:browse the project on GitHub'
15 'compare:open GitHub compare view'
16 )
17 # Extend the '_git_commands' function with hub commands
18 eval "$(declare -f _git_commands | sed -e 's/base_commands=(/base_commands=(${_hub_commands} /')"
19 fi
20 # eval `hub alias -s zsh`
21 function git(){
22 if ! (( $+_has_working_hub )); then
23 hub --version &> /dev/null
24 _has_working_hub=$(($? == 0))
25 fi
26 if (( $_has_working_hub )) ; then
27 hub "$@"
28 else
29 command git "$@"
30 fi
31 }
32 fi 6 fi
33 7
34 # Functions ################################################################# 8 # Functions #################################################################
35 9
36 # https://github.com/dbb 10 # Based on https://github.com/dbb/githome/blob/master/.config/zsh/functions
37 11
38 12 # empty_gh <NAME_OF_REPO>
39 # empty_gh [NAME_OF_REPO]
40 # 13 #
41 # Use this when creating a new repo from scratch. 14 # Use this when creating a new repo from scratch.
15 # Creates a new repo with a blank README.md in it and pushes it up to GitHub.
42 empty_gh() { # [NAME_OF_REPO] 16 empty_gh() { # [NAME_OF_REPO]
43 repo=$1 17 emulate -L zsh
44 ghuser=$( git config github.user ) 18 local repo=$1
45 19
46 mkdir "$repo" 20 mkdir "$repo"
47 cd "$repo" 21 touch "$repo/README.md"
48 git init 22 new_gh "$repo"
49 touch README
50 git add README
51 git commit -m 'Initial commit.'
52 git remote add origin git@github.com:${ghuser}/${repo}.git
53 git push -u origin master
54 } 23 }
55 24
56 # new_gh [DIRECTORY] 25 # new_gh [DIRECTORY]
57 # 26 #
58 # Use this when you have a directory that is not yet set up for git. 27 # Use this when you have a directory that is not yet set up for git.
59 # This function will add all non-hidden files to git. 28 # This function will add all non-hidden files to git.
60 new_gh() { # [DIRECTORY] 29 new_gh() { # [DIRECTORY]
61 cd "$1" 30 emulate -L zsh
62 ghuser=$( git config github.user ) 31 local repo="$1"
32 cd "$repo" \
33 || return
63 34
64 git init 35 git init \
65 # add all non-dot files 36 || return
66 print '.*'"\n"'*~' >> .gitignore 37 # add all non-dot files
67 git add ^.* 38 print '.*'"\n"'*~' >> .gitignore
68 git commit -m 'Initial commit.' 39 git add [^.]* \
69 git remote add origin git@github.com:${ghuser}/${repo}.git 40 || return
70 git push -u origin master 41 git add .gitignore \
42 || return
43 git commit -m 'Initial commit.' \
44 || return
45 hub create \
46 || return
47 git push -u origin master \
48 || return
71 } 49 }
72 50
73 # exist_gh [DIRECTORY] 51 # exist_gh [DIRECTORY]
74 # 52 #
75 # Use this when you have a git repo that's ready to go and you want to add it 53 # Use this when you have a git repo that's ready to go and you want to add it
76 # to your GitHub. 54 # to your GitHub.
77 exist_gh() { # [DIRECTORY] 55 exist_gh() { # [DIRECTORY]
78 cd "$1" 56 emulate -L zsh
79 name=$( git config user.name ) 57 local repo=$1
80 ghuser=$( git config github.user ) 58 cd "$repo"
81 repo=$1
82 59
83 git remote add origin git@github.com:${ghuser}/${repo}.git 60 hub create \
84 git push -u origin master 61 || return
62 git push -u origin master
85 } 63 }
86 64
87 # git.io "GitHub URL" 65 # git.io "GitHub URL"
plugins/history-substring-search/README.markdown
1 To activate this script, please include it the `plugins` variable within `~/.zshrc` File was deleted
2
3 `plugins=(git history-substring-search)`
4
5 See the "history-substring-search.zsh" file for more information:
6
7 `sed -n '2,/^$/s/^#//p' history-substring-search.zsh | more`
8 1 To activate this script, please include it the `plugins` variable within `~/.zshrc`
plugins/history-substring-search/README.md
File was created 1 zsh-history-substring-search
2 ==============================================================================
3
4 This is a clean-room implementation of the [Fish shell][1]'s history search
5 feature, where you can type in any part of any previously entered command
6 and press the UP and DOWN arrow keys to cycle through the matching commands.
7 You can also use K and J in VI mode or ^P and ^N in EMACS mode for the same.
8
9 [1]: http://fishshell.com
10 [2]: http://www.zsh.org/mla/users/2009/msg00818.html
11 [3]: http://sourceforge.net/projects/fizsh/
12 [4]: https://github.com/robbyrussell/oh-my-zsh/pull/215
13 [5]: https://github.com/zsh-users/zsh-history-substring-search
14 [6]: https://github.com/zsh-users/zsh-syntax-highlighting
15
16 ------------------------------------------------------------------------------
17 Requirements
18 ------------------------------------------------------------------------------
19
20 * [ZSH](http://zsh.sourceforge.net) 4.3 or newer
21
22 ------------------------------------------------------------------------------
23 Usage
24 ------------------------------------------------------------------------------
25
26 1. Load this script into your interactive ZSH session:
27
28 % source zsh-history-substring-search.zsh
29
30 If you want to use [zsh-syntax-highlighting][6] along with this script,
31 then make sure that you load it *before* you load this script:
32
33 % source zsh-syntax-highlighting.zsh
34 % source zsh-history-substring-search.zsh
35
36 2. Bind keyboard shortcuts to this script's functions:
37
38 # bind UP and DOWN arrow keys
39 zmodload zsh/terminfo
40 bindkey "$terminfo[kcuu1]" history-substring-search-up
41 bindkey "$terminfo[kcud1]" history-substring-search-down
42
43 # bind UP and DOWN arrow keys (compatibility fallback
44 # for Ubuntu 12.04, Fedora 21, and MacOSX 10.9 users)
45 bindkey '^[[A' history-substring-search-up
46 bindkey '^[[B' history-substring-search-down
47
48 # bind P and N for EMACS mode
49 bindkey -M emacs '^P' history-substring-search-up
50 bindkey -M emacs '^N' history-substring-search-down
51
52 # bind k and j for VI mode
53 bindkey -M vicmd 'k' history-substring-search-up
54 bindkey -M vicmd 'j' history-substring-search-down
55
56 3. Type any part of any previous command and then:
57
58 * Press the UP arrow key to select the nearest command that (1) contains
59 your query and (2) is older than the current command in the command
60 history.
61
62 * Press the DOWN arrow key to select the nearest command that (1)
63 contains your query and (2) is newer than the current command in the
64 command history.
65
66 * Press ^U (the Control and U keys simultaneously) to abort the search.
67
68 4. If a matching command spans more than one line of text, press the LEFT
69 arrow key to move the cursor away from the end of the command, and then:
70
71 * Press the UP arrow key to move the cursor to the line above. When the
72 cursor reaches the first line of the command, pressing the UP arrow
73 key again will cause this script to perform another search.
74
75 * Press the DOWN arrow key to move the cursor to the line below. When
76 the cursor reaches the last line of the command, pressing the DOWN
77 arrow key again will cause this script to perform another search.
78
79 ------------------------------------------------------------------------------
80 Configuration
81 ------------------------------------------------------------------------------
82
83 This script defines the following global variables. You may override their
84 default values only after having loaded this script into your ZSH session.
85
86 * HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND is a global variable that defines
87 how the query should be highlighted inside a matching command. Its default
88 value causes this script to highlight using bold, white text on a magenta
89 background. See the "Character Highlighting" section in the zshzle(1) man
90 page to learn about the kinds of values you may assign to this variable.
91
92 * HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND is a global variable that
93 defines how the query should be highlighted when no commands in the
94 history match it. Its default value causes this script to highlight using
95 bold, white text on a red background. See the "Character Highlighting"
96 section in the zshzle(1) man page to learn about the kinds of values you
97 may assign to this variable.
98
99 * HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS is a global variable that defines
100 how the command history will be searched for your query. Its default value
101 causes this script to perform a case-insensitive search. See the "Globbing
102 Flags" section in the zshexpn(1) man page to learn about the kinds of
103 values you may assign to this variable.
104
105 To always receive _unique_ search results, use `setopt HIST_IGNORE_ALL_DUPS`.
106 Alternatively, use `setopt HIST_FIND_NO_DUPS` which makes this plugin skip
107 duplicate _adjacent_ search results as you cycle through them---however, this
108 does not guarantee that search results are unique: if your search results were
109 "Dog", "Dog", "HotDog", "Dog", then cycling them gives "Dog", "HotDog", "Dog".
110 Notice that the "Dog" search result appeared twice as you cycled through them!
111 If you wish to avoid this limitation, then use `setopt HIST_IGNORE_ALL_DUPS`.
112
113 ------------------------------------------------------------------------------
114 History
115 ------------------------------------------------------------------------------
116
117 This script was originally written by [Peter Stephenson][2], who published it
118 to the ZSH users mailing list (thereby making it public domain) in September
119 2009. It was later revised by Guido van Steen and released under the BSD
120 license (see below) as part of [the fizsh project][3] in January 2011.
121
122 It was later extracted from fizsh release 1.0.1, refactored heavily, and
123 repackaged as both an [oh-my-zsh plugin][4] and as an independently loadable
124 [ZSH script][5] by Suraj N. Kurapati in 2011.
125
126 It was [further developed][4] by Guido van Steen, Suraj N. Kurapati, Sorin
127 Ionescu, and Vincent Guerci in 2011.
128
129 ------------------------------------------------------------------------------
130 Oh My Zsh Distribution Notes
131 ------------------------------------------------------------------------------
132
133 What you are looking at now is Oh My Zsh's repackaging of zsh-history-substring-search
134 as an OMZ module inside the Oh My Zsh distribution.
135
136 The upstream repo, zsh-users/zsh-history-substring-search, can be found on GitHub at
137 https://github.com/zsh-users/zsh-history-substring-search.
138
139 This downstream copy was last updated from the following upstream commit:
140
141 SHA: 2c295432175990c1bb4e90bc13f609daa67a25d6
142 Commit date: 2015-09-28 10:47:34 -0700
143
144 Everything above this section is a copy of the original upstream's README, so things
145 may differ slightly when you're using this inside OMZ. In particular, you do not
146 need to set up key bindings for the up and down arrows yourself in `~/.zshrc`; the OMZ
147 plugin does that for you. You may still want to set up additional emacs- or vi-specific
148 bindings as mentioned above.
149
150
plugins/history-substring-search/history-substring-search.plugin.zsh
1 # This file integrates the history-substring-search script into oh-my-zsh. 1 # This file integrates the zsh-history-substring-search script into oh-my-zsh.
2 2
3 source "$ZSH/plugins/history-substring-search/history-substring-search.zsh" 3 source "${0:r:r}.zsh"
4 4
5 if test "$CASE_SENSITIVE" = true; then 5 if test "$CASE_SENSITIVE" = true; then
6 unset HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS 6 unset HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS
7 fi 7 fi
8 8
9 if test "$DISABLE_COLOR" = true; then 9 if test "$DISABLE_COLOR" = true; then
10 unset HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND 10 unset HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
11 unset HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND 11 unset HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND
12 fi 12 fi
13
14
15 # Bind terminal-specific up and down keys
16
17 if [[ -n "$terminfo[kcuu1]" ]]; then
18 bindkey "$terminfo[kcuu1]" history-substring-search-up
19 fi
20 if [[ -n "$terminfo[kcud1]" ]]; then
21 bindkey "$terminfo[kcud1]" history-substring-search-down
22 fi
23
13 24
plugins/history-substring-search/history-substring-search.zsh
1 #!/usr/bin/env zsh 1 #!/usr/bin/env zsh
2 #
3 # This is a clean-room implementation of the Fish[1] shell's history search
4 # feature, where you can type in any part of any previously entered command
5 # and press the UP and DOWN arrow keys to cycle through the matching commands.
6 #
7 #-----------------------------------------------------------------------------
8 # Usage
9 #-----------------------------------------------------------------------------
10 #
11 # 1. Load this script into your interactive ZSH session:
12 #
13 # % source history-substring-search.zsh
14 #
15 # If you want to use the zsh-syntax-highlighting[6] script along with this
16 # script, then make sure that you load it *before* you load this script:
17 #
18 # % source zsh-syntax-highlighting.zsh
19 # % source history-substring-search.zsh
20 #
21 # 2. Type any part of any previous command and then:
22 #
23 # * Press the UP arrow key to select the nearest command that (1) contains
24 # your query and (2) is older than the current command in the command
25 # history.
26 #
27 # * Press the DOWN arrow key to select the nearest command that (1)
28 # contains your query and (2) is newer than the current command in the
29 # command history.
30 #
31 # * Press ^U (the Control and U keys simultaneously) to abort the search.
32 #
33 # 3. If a matching command spans more than one line of text, press the LEFT
34 # arrow key to move the cursor away from the end of the command, and then:
35 #
36 # * Press the UP arrow key to move the cursor to the line above. When the
37 # cursor reaches the first line of the command, pressing the UP arrow
38 # key again will cause this script to perform another search.
39 #
40 # * Press the DOWN arrow key to move the cursor to the line below. When
41 # the cursor reaches the last line of the command, pressing the DOWN
42 # arrow key again will cause this script to perform another search.
43 #
44 #-----------------------------------------------------------------------------
45 # Configuration
46 #-----------------------------------------------------------------------------
47 #
48 # This script defines the following global variables. You may override their
49 # default values only after having loaded this script into your ZSH session.
50 #
51 # * HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND is a global variable that defines
52 # how the query should be highlighted inside a matching command. Its default
53 # value causes this script to highlight using bold, white text on a magenta
54 # background. See the "Character Highlighting" section in the zshzle(1) man
55 # page to learn about the kinds of values you may assign to this variable.
56 #
57 # * HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND is a global variable that
58 # defines how the query should be highlighted when no commands in the
59 # history match it. Its default value causes this script to highlight using
60 # bold, white text on a red background. See the "Character Highlighting"
61 # section in the zshzle(1) man page to learn about the kinds of values you
62 # may assign to this variable.
63 #
64 # * HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS is a global variable that defines
65 # how the command history will be searched for your query. Its default value
66 # causes this script to perform a case-insensitive search. See the "Globbing
67 # Flags" section in the zshexpn(1) man page to learn about the kinds of
68 # values you may assign to this variable.
69 #
70 #-----------------------------------------------------------------------------
71 # History
72 #-----------------------------------------------------------------------------
73 #
74 # This script was originally written by Peter Stephenson[2], who published it
75 # to the ZSH users mailing list (thereby making it public domain) in September
76 # 2009. It was later revised by Guido van Steen and released under the BSD
77 # license (see below) as part of the fizsh[3] project in January 2011.
78 #
79 # It was later extracted from fizsh[3] release 1.0.1, refactored heavily, and
80 # repackaged as both an oh-my-zsh plugin[4] and as an independently loadable
81 # ZSH script[5] by Suraj N. Kurapati in 2011.
82 #
83 # It was further developed[4] by Guido van Steen, Suraj N. Kurapati, Sorin
84 # Ionescu, and Vincent Guerci in 2011.
85 #
86 # [1]: http://fishshell.com
87 # [2]: http://www.zsh.org/mla/users/2009/msg00818.html
88 # [3]: http://sourceforge.net/projects/fizsh/
89 # [4]: https://github.com/robbyrussell/oh-my-zsh/pull/215
90 # [5]: https://github.com/sunaku/zsh-history-substring-search
91 # [6]: https://github.com/nicoulaj/zsh-syntax-highlighting
92 #
93 ############################################################################## 2 ##############################################################################
94 # 3 #
95 # Copyright (c) 2009 Peter Stephenson 4 # Copyright (c) 2009 Peter Stephenson
96 # Copyright (c) 2011 Guido van Steen 5 # Copyright (c) 2011 Guido van Steen
97 # Copyright (c) 2011 Suraj N. Kurapati 6 # Copyright (c) 2011 Suraj N. Kurapati
98 # Copyright (c) 2011 Sorin Ionescu 7 # Copyright (c) 2011 Sorin Ionescu
99 # Copyright (c) 2011 Vincent Guerci 8 # Copyright (c) 2011 Vincent Guerci
100 # All rights reserved. 9 # All rights reserved.
101 # 10 #
102 # Redistribution and use in source and binary forms, with or without 11 # Redistribution and use in source and binary forms, with or without
103 # modification, are permitted provided that the following conditions are met: 12 # modification, are permitted provided that the following conditions are met:
104 # 13 #
105 # * Redistributions of source code must retain the above copyright 14 # * Redistributions of source code must retain the above copyright
106 # notice, this list of conditions and the following disclaimer. 15 # notice, this list of conditions and the following disclaimer.
107 # 16 #
108 # * Redistributions in binary form must reproduce the above 17 # * Redistributions in binary form must reproduce the above
109 # copyright notice, this list of conditions and the following 18 # copyright notice, this list of conditions and the following
110 # disclaimer in the documentation and/or other materials provided 19 # disclaimer in the documentation and/or other materials provided
111 # with the distribution. 20 # with the distribution.
112 # 21 #
113 # * Neither the name of the FIZSH nor the names of its contributors 22 # * Neither the name of the FIZSH nor the names of its contributors
114 # may be used to endorse or promote products derived from this 23 # may be used to endorse or promote products derived from this
115 # software without specific prior written permission. 24 # software without specific prior written permission.
116 # 25 #
117 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
118 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
119 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
120 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 29 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
121 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
122 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
123 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
124 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
125 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
126 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
127 # POSSIBILITY OF SUCH DAMAGE. 36 # POSSIBILITY OF SUCH DAMAGE.
128 # 37 #
129 ############################################################################## 38 ##############################################################################
130 39
131 #----------------------------------------------------------------------------- 40 #-----------------------------------------------------------------------------
132 # configuration variables 41 # configuration variables
133 #----------------------------------------------------------------------------- 42 #-----------------------------------------------------------------------------
134 43
135 HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND='bg=magenta,fg=white,bold' 44 HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND='bg=magenta,fg=white,bold'
136 HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND='bg=red,fg=white,bold' 45 HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND='bg=red,fg=white,bold'
137 HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS='i' 46 HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS='i'
138 47
139 #----------------------------------------------------------------------------- 48 #-----------------------------------------------------------------------------
140 # the main ZLE widgets 49 # the main ZLE widgets
141 #----------------------------------------------------------------------------- 50 #-----------------------------------------------------------------------------
142 51
143 function history-substring-search-up() { 52 history-substring-search-up() {
144 _history-substring-search-begin 53 _history-substring-search-begin
145 54
146 _history-substring-search-up-history || 55 _history-substring-search-up-history ||
147 _history-substring-search-up-buffer || 56 _history-substring-search-up-buffer ||
148 _history-substring-search-up-search 57 _history-substring-search-up-search
149 58
150 _history-substring-search-end 59 _history-substring-search-end
151 } 60 }
152 61
153 function history-substring-search-down() { 62 history-substring-search-down() {
154 _history-substring-search-begin 63 _history-substring-search-begin
155 64
156 _history-substring-search-down-history || 65 _history-substring-search-down-history ||
157 _history-substring-search-down-buffer || 66 _history-substring-search-down-buffer ||
158 _history-substring-search-down-search 67 _history-substring-search-down-search
159 68
160 _history-substring-search-end 69 _history-substring-search-end
161 } 70 }
162 71
163 zle -N history-substring-search-up 72 zle -N history-substring-search-up
164 zle -N history-substring-search-down 73 zle -N history-substring-search-down
165 74
166 zmodload zsh/terminfo
167 if [[ -n "$terminfo[kcuu1]" ]]; then
168 bindkey "$terminfo[kcuu1]" history-substring-search-up
169 fi
170 if [[ -n "$terminfo[kcud1]" ]]; then
171 bindkey "$terminfo[kcud1]" history-substring-search-down
172 fi
173
174 #----------------------------------------------------------------------------- 75 #-----------------------------------------------------------------------------
175 # implementation details 76 # implementation details
176 #----------------------------------------------------------------------------- 77 #-----------------------------------------------------------------------------
177 78
178 zmodload -F zsh/parameter 79 zmodload -F zsh/parameter
179 80
180 # 81 #
181 # We have to "override" some keys and widgets if the 82 # We have to "override" some keys and widgets if the
182 # zsh-syntax-highlighting plugin has not been loaded: 83 # zsh-syntax-highlighting plugin has not been loaded:
183 # 84 #
184 # https://github.com/nicoulaj/zsh-syntax-highlighting 85 # https://github.com/nicoulaj/zsh-syntax-highlighting
185 # 86 #
186 if [[ $+functions[_zsh_highlight] -eq 0 ]]; then 87 if [[ $+functions[_zsh_highlight] -eq 0 ]]; then
187 # 88 #
188 # Dummy implementation of _zsh_highlight() 89 # Dummy implementation of _zsh_highlight() that
189 # that simply removes existing highlights 90 # simply removes any existing highlights when the
190 # 91 # user inserts printable characters into $BUFFER.
191 function _zsh_highlight() {
192 region_highlight=()
193 }
194
195 #
196 # Remove existing highlights when the user
197 # inserts printable characters into $BUFFER
198 # 92 #
199 function ordinary-key-press() { 93 _zsh_highlight() {
200 if [[ $KEYS == [[:print:]] ]]; then 94 if [[ $KEYS == [[:print:]] ]]; then
201 region_highlight=() 95 region_highlight=()
202 fi 96 fi
203 zle .self-insert
204 } 97 }
205 zle -N self-insert ordinary-key-press
206 98
207 # 99 #
208 # Override ZLE widgets to invoke _zsh_highlight() 100 # The following snippet was taken from the zsh-syntax-highlighting project:
209 # 101 #
210 # https://github.com/nicoulaj/zsh-syntax-highlighting/blob/ 102 # https://github.com/zsh-users/zsh-syntax-highlighting/blob/56b134f5d62ae3d4e66c7f52bd0cc2595f9b305b/zsh-syntax-highlighting.zsh#L126-161
211 # bb7fcb79fad797a40077bebaf6f4e4a93c9d8163/zsh-syntax-highlighting.zsh#L121
212 #
213 #--------------8<-------------------8<-------------------8<-----------------
214 # 103 #
215 # Copyright (c) 2010-2011 zsh-syntax-highlighting contributors 104 # Copyright (c) 2010-2011 zsh-syntax-highlighting contributors
216 # All rights reserved. 105 # All rights reserved.
217 # 106 #
218 # Redistribution and use in source and binary forms, with or without 107 # Redistribution and use in source and binary forms, with or without
219 # modification, are permitted provided that the following conditions are 108 # modification, are permitted provided that the following conditions are
220 # met: 109 # met:
221 # 110 #
222 # * Redistributions of source code must retain the above copyright 111 # * Redistributions of source code must retain the above copyright
223 # notice, this list of conditions and the following disclaimer. 112 # notice, this list of conditions and the following disclaimer.
224 # 113 #
225 # * Redistributions in binary form must reproduce the above copyright 114 # * Redistributions in binary form must reproduce the above copyright
226 # notice, this list of conditions and the following disclaimer in the 115 # notice, this list of conditions and the following disclaimer in the
227 # documentation and/or other materials provided with the distribution. 116 # documentation and/or other materials provided with the distribution.
228 # 117 #
229 # * Neither the name of the zsh-syntax-highlighting contributors nor the 118 # * Neither the name of the zsh-syntax-highlighting contributors nor the
230 # names of its contributors may be used to endorse or promote products 119 # names of its contributors may be used to endorse or promote products
231 # derived from this software without specific prior written permission. 120 # derived from this software without specific prior written permission.
232 # 121 #
233 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 122 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
234 # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 123 # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
235 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 124 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
236 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 125 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
237 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 126 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
238 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 127 # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
239 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 128 # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
240 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 129 # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
241 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 130 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
242 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 131 # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
243 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 132 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
244 133 #
245 # Load ZSH module zsh/zleparameter, needed to override user defined widgets. 134 #--------------8<-------------------8<-------------------8<-----------------
246 zmodload zsh/zleparameter 2>/dev/null || { 135 # Rebind all ZLE widgets to make them invoke _zsh_highlights.
247 echo 'zsh-syntax-highlighting: failed loading zsh/zleparameter, exiting.' >&2 136 _zsh_highlight_bind_widgets()
248 return -1 137 {
249 } 138 # Load ZSH module zsh/zleparameter, needed to override user defined widgets.
250 139 zmodload zsh/zleparameter 2>/dev/null || {
251 # Override ZLE widgets to make them invoke _zsh_highlight. 140 echo 'zsh-syntax-highlighting: failed loading zsh/zleparameter.' >&2
252 for event in ${${(f)"$(zle -la)"}:#(_*|orig-*|.run-help|.which-command)}; do 141 return 1
253 if [[ "$widgets[$event]" == completion:* ]]; then 142 }
254 eval "zle -C orig-$event ${${${widgets[$event]}#*:}/:/ } ; $event() { builtin zle orig-$event && _zsh_highlight } ; zle -N $event" 143
255 else 144 # Override ZLE widgets to make them invoke _zsh_highlight.
256 case $event in 145 local cur_widget
257 accept-and-menu-complete) 146 for cur_widget in ${${(f)"$(builtin zle -la)"}:#(.*|_*|orig-*|run-help|which-command|beep|yank*)}; do
258 eval "$event() { builtin zle .$event && _zsh_highlight } ; zle -N $event" 147 case $widgets[$cur_widget] in
259 ;; 148
260 149 # Already rebound event: do nothing.
261 # The following widgets should NOT remove any previously 150 user:$cur_widget|user:_zsh_highlight_widget_*);;
262 # applied highlighting. Therefore we do not remap them. 151
263 .forward-char|.backward-char|.up-line-or-history|.down-line-or-history) 152 # User defined widget: override and rebind old one with prefix "orig-".
264 ;; 153 user:*) eval "zle -N orig-$cur_widget ${widgets[$cur_widget]#*:}; \
265 154 _zsh_highlight_widget_$cur_widget() { builtin zle orig-$cur_widget -- \"\$@\" && _zsh_highlight }; \
266 .*) 155 zle -N $cur_widget _zsh_highlight_widget_$cur_widget";;
267 clean_event=$event[2,${#event}] # Remove the leading dot in the event name 156
268 case ${widgets[$clean_event]-} in 157 # Completion widget: override and rebind old one with prefix "orig-".
269 (completion|user):*) 158 completion:*) eval "zle -C orig-$cur_widget ${${widgets[$cur_widget]#*:}/:/ }; \
270 ;; 159 _zsh_highlight_widget_$cur_widget() { builtin zle orig-$cur_widget -- \"\$@\" && _zsh_highlight }; \
271 *) 160 zle -N $cur_widget _zsh_highlight_widget_$cur_widget";;
272 eval "$clean_event() { builtin zle $event && _zsh_highlight } ; zle -N $clean_event" 161
273 ;; 162 # Builtin widget: override and make it call the builtin ".widget".
274 esac 163 builtin) eval "_zsh_highlight_widget_$cur_widget() { builtin zle .$cur_widget -- \"\$@\" && _zsh_highlight }; \
275 ;; 164 zle -N $cur_widget _zsh_highlight_widget_$cur_widget";;
276 *) 165
277 ;; 166 # Default: unhandled case.
167 *) echo "zsh-syntax-highlighting: unhandled ZLE widget '$cur_widget'" >&2 ;;
278 esac 168 esac
279 fi 169 done
280 done 170 }
281 unset event clean_event
282 #-------------->8------------------->8------------------->8----------------- 171 #-------------->8------------------->8------------------->8-----------------
172
173 _zsh_highlight_bind_widgets
283 fi 174 fi
284 175
285 function _history-substring-search-begin() { 176 _history-substring-search-begin() {
286 setopt localoptions extendedglob 177 setopt localoptions extendedglob
287 _history_substring_search_move_cursor_eol=false 178
179 _history_substring_search_refresh_display=
288 _history_substring_search_query_highlight= 180 _history_substring_search_query_highlight=
289 181
290 # 182 #
291 # Continue using the previous $_history_substring_search_result by default, 183 # Continue using the previous $_history_substring_search_result by default,
292 # unless the current query was cleared or a new/different query was entered. 184 # unless the current query was cleared or a new/different query was entered.
293 # 185 #
294 if [[ -z $BUFFER || $BUFFER != $_history_substring_search_result ]]; then 186 if [[ -z $BUFFER || $BUFFER != $_history_substring_search_result ]]; then
295 # 187 #
296 # For the purpose of highlighting we will also keep 188 # For the purpose of highlighting we will also keep
297 # a version without doubly-escaped meta characters. 189 # a version without doubly-escaped meta characters.
298 # 190 #
299 _history_substring_search_query=$BUFFER 191 _history_substring_search_query=$BUFFER
300 192
301 # 193 #
302 # $BUFFER contains the text that is in the command-line currently. 194 # $BUFFER contains the text that is in the command-line currently.
303 # we put an extra "\\" before meta characters such as "\(" and "\)", 195 # we put an extra "\\" before meta characters such as "\(" and "\)",
304 # so that they become "\\\(" and "\\\)". 196 # so that they become "\\\(" and "\\\)".
305 # 197 #
306 _history_substring_search_query_escaped=${BUFFER//(#m)[\][()|\\*?#<>~^]/\\$MATCH} 198 _history_substring_search_query_escaped=${BUFFER//(#m)[\][()|\\*?#<>~^]/\\$MATCH}
307 199
308 # 200 #
309 # Find all occurrences of the search query in the history file. 201 # Find all occurrences of the search query in the history file.
310 # 202 #
311 # (k) turns it an array of line numbers. 203 # (k) returns the "keys" (history index numbers) instead of the values
312 # 204 # (Oa) reverses the order, because (R) returns results reversed.
313 # (on) seems to remove duplicates, which are default
314 # options. They can be turned off by (ON).
315 # 205 #
316 _history_substring_search_matches=(${(kon)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)*${_history_substring_search_query_escaped}*]}) 206 _history_substring_search_matches=(${(kOa)history[(R)(#$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)*${_history_substring_search_query_escaped}*]})
317 207
318 # 208 #
319 # Define the range of values that $_history_substring_search_match_index 209 # Define the range of values that $_history_substring_search_match_index
320 # can take: [0, $_history_substring_search_matches_count_plus]. 210 # can take: [0, $_history_substring_search_matches_count_plus].
321 # 211 #
322 _history_substring_search_matches_count=$#_history_substring_search_matches 212 _history_substring_search_matches_count=$#_history_substring_search_matches
323 _history_substring_search_matches_count_plus=$(( _history_substring_search_matches_count + 1 )) 213 _history_substring_search_matches_count_plus=$(( _history_substring_search_matches_count + 1 ))
324 _history_substring_search_matches_count_sans=$(( _history_substring_search_matches_count - 1 )) 214 _history_substring_search_matches_count_sans=$(( _history_substring_search_matches_count - 1 ))
325 215
326 # 216 #
327 # If $_history_substring_search_match_index is equal to 217 # If $_history_substring_search_match_index is equal to
328 # $_history_substring_search_matches_count_plus, this indicates that we 218 # $_history_substring_search_matches_count_plus, this indicates that we
329 # are beyond the beginning of $_history_substring_search_matches. 219 # are beyond the beginning of $_history_substring_search_matches.
330 # 220 #
331 # If $_history_substring_search_match_index is equal to 0, this indicates 221 # If $_history_substring_search_match_index is equal to 0, this indicates
332 # that we are beyond the end of $_history_substring_search_matches. 222 # that we are beyond the end of $_history_substring_search_matches.
333 # 223 #
334 # If we have initially pressed "up" we have to initialize 224 # If we have initially pressed "up" we have to initialize
335 # $_history_substring_search_match_index to 225 # $_history_substring_search_match_index to
336 # $_history_substring_search_matches_count_plus so that it will be 226 # $_history_substring_search_matches_count_plus so that it will be
337 # decreased to $_history_substring_search_matches_count. 227 # decreased to $_history_substring_search_matches_count.
338 # 228 #
339 # If we have initially pressed "down" we have to initialize 229 # If we have initially pressed "down" we have to initialize
340 # $_history_substring_search_match_index to 230 # $_history_substring_search_match_index to
341 # $_history_substring_search_matches_count so that it will be increased to 231 # $_history_substring_search_matches_count so that it will be increased to
342 # $_history_substring_search_matches_count_plus. 232 # $_history_substring_search_matches_count_plus.
343 # 233 #
344 if [[ $WIDGET == history-substring-search-down ]]; then 234 if [[ $WIDGET == history-substring-search-down ]]; then
345 _history_substring_search_match_index=$_history_substring_search_matches_count 235 _history_substring_search_match_index=$_history_substring_search_matches_count
346 else 236 else
347 _history_substring_search_match_index=$_history_substring_search_matches_count_plus 237 _history_substring_search_match_index=$_history_substring_search_matches_count_plus
348 fi 238 fi
349 fi 239 fi
350 } 240 }
351 241
352 function _history-substring-search-end() { 242 _history-substring-search-end() {
353 setopt localoptions extendedglob 243 setopt localoptions extendedglob
244
354 _history_substring_search_result=$BUFFER 245 _history_substring_search_result=$BUFFER
355 246
356 # move the cursor to the end of the command line 247 # the search was succesful so display the result properly by clearing away
357 if [[ $_history_substring_search_move_cursor_eol == true ]]; then 248 # existing highlights and moving the cursor to the end of the result buffer
249 if [[ $_history_substring_search_refresh_display -eq 1 ]]; then
250 region_highlight=()
358 CURSOR=${#BUFFER} 251 CURSOR=${#BUFFER}
359 fi 252 fi
360 253
361 # highlight command line using zsh-syntax-highlighting 254 # highlight command line using zsh-syntax-highlighting
362 _zsh_highlight 255 _zsh_highlight
363 256
364 # highlight the search query inside the command line 257 # highlight the search query inside the command line
365 if [[ -n $_history_substring_search_query_highlight && -n $_history_substring_search_query ]]; then 258 if [[ -n $_history_substring_search_query_highlight && -n $_history_substring_search_query ]]; then
366 # 259 #
367 # The following expression yields a variable $MBEGIN, which 260 # The following expression yields a variable $MBEGIN, which
368 # indicates the begin position + 1 of the first occurrence 261 # indicates the begin position + 1 of the first occurrence
369 # of _history_substring_search_query_escaped in $BUFFER. 262 # of _history_substring_search_query_escaped in $BUFFER.
370 # 263 #
371 : ${(S)BUFFER##(#m$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)($_history_substring_search_query##)} 264 : ${(S)BUFFER##(#m$HISTORY_SUBSTRING_SEARCH_GLOBBING_FLAGS)($_history_substring_search_query##)}
372 local begin=$(( MBEGIN - 1 )) 265 local begin=$(( MBEGIN - 1 ))
373 local end=$(( begin + $#_history_substring_search_query )) 266 local end=$(( begin + $#_history_substring_search_query ))
374 region_highlight+=("$begin $end $_history_substring_search_query_highlight") 267 region_highlight+=("$begin $end $_history_substring_search_query_highlight")
375 fi 268 fi
376 269
377 # For debugging purposes: 270 # For debugging purposes:
378 # zle -R "mn: "$_history_substring_search_match_index" m#: "${#_history_substring_search_matches} 271 # zle -R "mn: "$_history_substring_search_match_index" m#: "${#_history_substring_search_matches}
379 # read -k -t 200 && zle -U $REPLY 272 # read -k -t 200 && zle -U $REPLY
380 273
381 # Exit successfully from the history-substring-search-* widgets. 274 # Exit successfully from the history-substring-search-* widgets.
382 true 275 return 0
383 } 276 }
384 277
385 function _history-substring-search-up-buffer() { 278 _history-substring-search-up-buffer() {
386 # 279 #
387 # Check if the UP arrow was pressed to move the cursor within a multi-line 280 # Check if the UP arrow was pressed to move the cursor within a multi-line
388 # buffer. This amounts to three tests: 281 # buffer. This amounts to three tests:
389 # 282 #
390 # 1. $#buflines -gt 1. 283 # 1. $#buflines -gt 1.
391 # 284 #
392 # 2. $CURSOR -ne $#BUFFER. 285 # 2. $CURSOR -ne $#BUFFER.
393 # 286 #
394 # 3. Check if we are on the first line of the current multi-line buffer. 287 # 3. Check if we are on the first line of the current multi-line buffer.
395 # If so, pressing UP would amount to leaving the multi-line buffer. 288 # If so, pressing UP would amount to leaving the multi-line buffer.
396 # 289 #
397 # We check this by adding an extra "x" to $LBUFFER, which makes 290 # We check this by adding an extra "x" to $LBUFFER, which makes
398 # sure that xlbuflines is always equal to the number of lines 291 # sure that xlbuflines is always equal to the number of lines
399 # until $CURSOR (including the line with the cursor on it). 292 # until $CURSOR (including the line with the cursor on it).
400 # 293 #
401 local buflines XLBUFFER xlbuflines 294 local buflines XLBUFFER xlbuflines
402 buflines=(${(f)BUFFER}) 295 buflines=(${(f)BUFFER})
403 XLBUFFER=$LBUFFER"x" 296 XLBUFFER=$LBUFFER"x"
404 xlbuflines=(${(f)XLBUFFER}) 297 xlbuflines=(${(f)XLBUFFER})
405 298
406 if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xlbuflines -ne 1 ]]; then 299 if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xlbuflines -ne 1 ]]; then
407 zle up-line-or-history 300 zle up-line-or-history
408 return true 301 return 0
409 fi 302 fi
410 303
411 false 304 return 1
412 } 305 }
413 306
414 function _history-substring-search-down-buffer() { 307 _history-substring-search-down-buffer() {
415 # 308 #
416 # Check if the DOWN arrow was pressed to move the cursor within a multi-line 309 # Check if the DOWN arrow was pressed to move the cursor within a multi-line
417 # buffer. This amounts to three tests: 310 # buffer. This amounts to three tests:
418 # 311 #
419 # 1. $#buflines -gt 1. 312 # 1. $#buflines -gt 1.
420 # 313 #
421 # 2. $CURSOR -ne $#BUFFER. 314 # 2. $CURSOR -ne $#BUFFER.
422 # 315 #
423 # 3. Check if we are on the last line of the current multi-line buffer. 316 # 3. Check if we are on the last line of the current multi-line buffer.
424 # If so, pressing DOWN would amount to leaving the multi-line buffer. 317 # If so, pressing DOWN would amount to leaving the multi-line buffer.
425 # 318 #
426 # We check this by adding an extra "x" to $RBUFFER, which makes 319 # We check this by adding an extra "x" to $RBUFFER, which makes
427 # sure that xrbuflines is always equal to the number of lines 320 # sure that xrbuflines is always equal to the number of lines
428 # from $CURSOR (including the line with the cursor on it). 321 # from $CURSOR (including the line with the cursor on it).
429 # 322 #
430 local buflines XRBUFFER xrbuflines 323 local buflines XRBUFFER xrbuflines
431 buflines=(${(f)BUFFER}) 324 buflines=(${(f)BUFFER})
432 XRBUFFER="x"$RBUFFER 325 XRBUFFER="x"$RBUFFER
433 xrbuflines=(${(f)XRBUFFER}) 326 xrbuflines=(${(f)XRBUFFER})
434 327
435 if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xrbuflines -ne 1 ]]; then 328 if [[ $#buflines -gt 1 && $CURSOR -ne $#BUFFER && $#xrbuflines -ne 1 ]]; then
436 zle down-line-or-history 329 zle down-line-or-history
437 return true 330 return 0
438 fi 331 fi
439 332
440 false 333 return 1
441 } 334 }
442 335
443 function _history-substring-search-up-history() { 336 _history-substring-search-up-history() {
444 # 337 #
445 # Behave like up in ZSH, except clear the $BUFFER 338 # Behave like up in ZSH, except clear the $BUFFER
446 # when beginning of history is reached like in Fish. 339 # when beginning of history is reached like in Fish.
447 # 340 #
448 if [[ -z $_history_substring_search_query ]]; then 341 if [[ -z $_history_substring_search_query ]]; then
449 342
450 # we have reached the absolute top of history 343 # we have reached the absolute top of history
451 if [[ $HISTNO -eq 1 ]]; then 344 if [[ $HISTNO -eq 1 ]]; then
452 BUFFER= 345 BUFFER=
453 346
454 # going up from somewhere below the top of history 347 # going up from somewhere below the top of history
455 else 348 else
456 zle up-history 349 zle up-line-or-history
457 fi 350 fi
458 351
459 return true 352 return 0
460 fi 353 fi
461 354
462 false 355 return 1
463 } 356 }
464 357
465 function _history-substring-search-down-history() { 358 _history-substring-search-down-history() {
466 # 359 #
467 # Behave like down-history in ZSH, except clear the 360 # Behave like down-history in ZSH, except clear the
468 # $BUFFER when end of history is reached like in Fish. 361 # $BUFFER when end of history is reached like in Fish.
469 # 362 #
470 if [[ -z $_history_substring_search_query ]]; then 363 if [[ -z $_history_substring_search_query ]]; then
471 364
472 # going down from the absolute top of history 365 # going down from the absolute top of history
473 if [[ $HISTNO -eq 1 && -z $BUFFER ]]; then 366 if [[ $HISTNO -eq 1 && -z $BUFFER ]]; then
474 BUFFER=${history[1]} 367 BUFFER=${history[1]}
475 _history_substring_search_move_cursor_eol=true 368 _history_substring_search_refresh_display=1
476 369
477 # going down from somewhere above the bottom of history 370 # going down from somewhere above the bottom of history
478 else 371 else
479 zle down-history 372 zle down-line-or-history
480 fi 373 fi
481 374
482 return true 375 return 0
483 fi 376 fi
484 377
485 false 378 return 1
379 }
380
381 _history-substring-search-not-found() {
382 #
383 # Nothing matched the search query, so put it back into the $BUFFER while
384 # highlighting it accordingly so the user can revise it and search again.
385 #
386 _history_substring_search_old_buffer=$BUFFER
387 BUFFER=$_history_substring_search_query
388 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND
486 } 389 }
487 390
488 function _history-substring-search-up-search() { 391 _history-substring-search-up-search() {
489 _history_substring_search_move_cursor_eol=true 392 _history_substring_search_refresh_display=1
490 393
491 # 394 #
492 # Highlight matches during history-substring-up-search: 395 # Highlight matches during history-substring-up-search:
493 # 396 #
494 # The following constants have been initialized in 397 # The following constants have been initialized in
495 # _history-substring-search-up/down-search(): 398 # _history-substring-search-up/down-search():
496 # 399 #
497 # $_history_substring_search_matches is the current list of matches 400 # $_history_substring_search_matches is the current list of matches
498 # $_history_substring_search_matches_count is the current number of matches 401 # $_history_substring_search_matches_count is the current number of matches
499 # $_history_substring_search_matches_count_plus is the current number of matches + 1 402 # $_history_substring_search_matches_count_plus is the current number of matches + 1
500 # $_history_substring_search_matches_count_sans is the current number of matches - 1 403 # $_history_substring_search_matches_count_sans is the current number of matches - 1
501 # $_history_substring_search_match_index is the index of the current match 404 # $_history_substring_search_match_index is the index of the current match
502 # 405 #
503 # The range of values that $_history_substring_search_match_index can take 406 # The range of values that $_history_substring_search_match_index can take
504 # is: [0, $_history_substring_search_matches_count_plus]. A value of 0 407 # is: [0, $_history_substring_search_matches_count_plus]. A value of 0
505 # indicates that we are beyond the end of 408 # indicates that we are beyond the end of
506 # $_history_substring_search_matches. A value of 409 # $_history_substring_search_matches. A value of
507 # $_history_substring_search_matches_count_plus indicates that we are beyond 410 # $_history_substring_search_matches_count_plus indicates that we are beyond
508 # the beginning of $_history_substring_search_matches. 411 # the beginning of $_history_substring_search_matches.
509 # 412 #
510 # In _history-substring-search-up-search() the initial value of 413 # In _history-substring-search-up-search() the initial value of
511 # $_history_substring_search_match_index is 414 # $_history_substring_search_match_index is
512 # $_history_substring_search_matches_count_plus. This value is set in 415 # $_history_substring_search_matches_count_plus. This value is set in
513 # _history-substring-search-begin(). _history-substring-search-up-search() 416 # _history-substring-search-begin(). _history-substring-search-up-search()
514 # will initially decrease it to $_history_substring_search_matches_count. 417 # will initially decrease it to $_history_substring_search_matches_count.
515 # 418 #
516 if [[ $_history_substring_search_match_index -ge 2 ]]; then 419 if [[ $_history_substring_search_match_index -ge 2 ]]; then
517 # 420 #
518 # Highlight the next match: 421 # Highlight the next match:
519 # 422 #
520 # 1. Decrease the value of $_history_substring_search_match_index. 423 # 1. Decrease the value of $_history_substring_search_match_index.
521 # 424 #
522 # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND 425 # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
523 # to highlight the current buffer. 426 # to highlight the current buffer.
524 # 427 #
525 (( _history_substring_search_match_index-- )) 428 (( _history_substring_search_match_index-- ))
526 BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]] 429 BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]]
527 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND 430 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
528 431
529 elif [[ $_history_substring_search_match_index -eq 1 ]]; then 432 elif [[ $_history_substring_search_match_index -eq 1 ]]; then
530 # 433 #
531 # We will move beyond the end of $_history_substring_search_matches: 434 # We will move beyond the end of $_history_substring_search_matches:
532 # 435 #
533 # 1. Decrease the value of $_history_substring_search_match_index. 436 # 1. Decrease the value of $_history_substring_search_match_index.
534 # 437 #
535 # 2. Save the current buffer in $_history_substring_search_old_buffer, 438 # 2. Save the current buffer in $_history_substring_search_old_buffer,
536 # so that it can be retrieved by 439 # so that it can be retrieved by
537 # _history-substring-search-down-search() later. 440 # _history-substring-search-down-search() later.
538 # 441 #
539 # 3. Make $BUFFER equal to $_history_substring_search_query. 442 # 3. Make $BUFFER equal to $_history_substring_search_query.
540 # 443 #
541 # 4. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND 444 # 4. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND
542 # to highlight the current buffer. 445 # to highlight the current buffer.
543 # 446 #
544 (( _history_substring_search_match_index-- )) 447 (( _history_substring_search_match_index-- ))
545 _history_substring_search_old_buffer=$BUFFER 448 _history-substring-search-not-found
546 BUFFER=$_history_substring_search_query
547 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_NOT_FOUND
548 449
549 elif [[ $_history_substring_search_match_index -eq $_history_substring_search_matches_count_plus ]]; then 450 elif [[ $_history_substring_search_match_index -eq $_history_substring_search_matches_count_plus ]]; then
550 # 451 #
551 # We were beyond the beginning of $_history_substring_search_matches but 452 # We were beyond the beginning of $_history_substring_search_matches but
552 # UP makes us move back to $_history_substring_search_matches: 453 # UP makes us move back to $_history_substring_search_matches:
553 # 454 #
554 # 1. Decrease the value of $_history_substring_search_match_index. 455 # 1. Decrease the value of $_history_substring_search_match_index.
555 # 456 #
556 # 2. Restore $BUFFER from $_history_substring_search_old_buffer. 457 # 2. Restore $BUFFER from $_history_substring_search_old_buffer.
557 # 458 #
558 # 3. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND 459 # 3. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
559 # to highlight the current buffer. 460 # to highlight the current buffer.
560 # 461 #
561 (( _history_substring_search_match_index-- )) 462 (( _history_substring_search_match_index-- ))
562 BUFFER=$_history_substring_search_old_buffer 463 BUFFER=$_history_substring_search_old_buffer
563 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND 464 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
465
466 else
467 #
468 # We are at the beginning of history and there are no further matches.
469 #
470 _history-substring-search-not-found
471 return
472 fi
473
474 #
475 # When HIST_FIND_NO_DUPS is set, meaning that only unique command lines from
476 # history should be matched, make sure the new and old results are different.
477 # But when HIST_IGNORE_ALL_DUPS is set, ZSH already ensures a unique history.
478 #
479 if [[ ! -o HIST_IGNORE_ALL_DUPS && -o HIST_FIND_NO_DUPS && $BUFFER == $_history_substring_search_result ]]; then
480 #
481 # Repeat the current search so that a different (unique) match is found.
482 #
483 _history-substring-search-up-search
564 fi 484 fi
565 } 485 }
566 486
567 function _history-substring-search-down-search() { 487 _history-substring-search-down-search() {
568 _history_substring_search_move_cursor_eol=true 488 _history_substring_search_refresh_display=1
569 489
570 # 490 #
571 # Highlight matches during history-substring-up-search: 491 # Highlight matches during history-substring-up-search:
572 # 492 #
573 # The following constants have been initialized in 493 # The following constants have been initialized in
574 # _history-substring-search-up/down-search(): 494 # _history-substring-search-up/down-search():
575 # 495 #
576 # $_history_substring_search_matches is the current list of matches 496 # $_history_substring_search_matches is the current list of matches
577 # $_history_substring_search_matches_count is the current number of matches 497 # $_history_substring_search_matches_count is the current number of matches
578 # $_history_substring_search_matches_count_plus is the current number of matches + 1 498 # $_history_substring_search_matches_count_plus is the current number of matches + 1
579 # $_history_substring_search_matches_count_sans is the current number of matches - 1 499 # $_history_substring_search_matches_count_sans is the current number of matches - 1
580 # $_history_substring_search_match_index is the index of the current match 500 # $_history_substring_search_match_index is the index of the current match
581 # 501 #
582 # The range of values that $_history_substring_search_match_index can take 502 # The range of values that $_history_substring_search_match_index can take
583 # is: [0, $_history_substring_search_matches_count_plus]. A value of 0 503 # is: [0, $_history_substring_search_matches_count_plus]. A value of 0
584 # indicates that we are beyond the end of 504 # indicates that we are beyond the end of
585 # $_history_substring_search_matches. A value of 505 # $_history_substring_search_matches. A value of
586 # $_history_substring_search_matches_count_plus indicates that we are beyond 506 # $_history_substring_search_matches_count_plus indicates that we are beyond
587 # the beginning of $_history_substring_search_matches. 507 # the beginning of $_history_substring_search_matches.
588 # 508 #
589 # In _history-substring-search-down-search() the initial value of 509 # In _history-substring-search-down-search() the initial value of
590 # $_history_substring_search_match_index is 510 # $_history_substring_search_match_index is
591 # $_history_substring_search_matches_count. This value is set in 511 # $_history_substring_search_matches_count. This value is set in
592 # _history-substring-search-begin(). 512 # _history-substring-search-begin().
593 # _history-substring-search-down-search() will initially increase it to 513 # _history-substring-search-down-search() will initially increase it to
594 # $_history_substring_search_matches_count_plus. 514 # $_history_substring_search_matches_count_plus.
595 # 515 #
596 if [[ $_history_substring_search_match_index -le $_history_substring_search_matches_count_sans ]]; then 516 if [[ $_history_substring_search_match_index -le $_history_substring_search_matches_count_sans ]]; then
597 # 517 #
598 # Highlight the next match: 518 # Highlight the next match:
599 # 519 #
600 # 1. Increase $_history_substring_search_match_index by 1. 520 # 1. Increase $_history_substring_search_match_index by 1.
601 # 521 #
602 # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND 522 # 2. Use $HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
603 # to highlight the current buffer. 523 # to highlight the current buffer.
604 # 524 #
605 (( _history_substring_search_match_index++ )) 525 (( _history_substring_search_match_index++ ))
606 BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]] 526 BUFFER=$history[$_history_substring_search_matches[$_history_substring_search_match_index]]
607 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND 527 _history_substring_search_query_highlight=$HISTORY_SUBSTRING_SEARCH_HIGHLIGHT_FOUND
608 528
609 elif [[ $_history_substring_search_match_index -eq $_history_substring_search_matches_count ]]; then 529 elif [[ $_history_substring_search_match_index -eq $_history_substring_search_matches_count ]]; then
610 # 530 #
611 # We will move beyond the beginning of $_history_substring_search_matches: 531 # We will move beyond the beginning of $_history_substring_search_matches:
612 # 532 #
613 # 1. Increase $_history_substring_search_match_index by 1. 533 # 1. Increase $_history_substring_search_match_index by 1.
plugins/history-substring-search/update-from-upstream.zsh
File was created 1 #!/usr/bin/env zsh
2 #
3 # update-from-upstream.zsh
4 #
5 # This script updates the Oh My Zsh version of the zsh-history-substring-search
6 # plugin from the independent upstream repo. This is to be run by OMZ developers
7 # when they want to pull in new changes from upstream to OMZ. It is not run
8 # during normal use of the plugin.
9 #
10 # The official upstream repo is zsh-users/zsh-history-substring-search
11 # https://github.com/zsh-users/zsh-history-substring-search
12 #
13 # This is a zsh script, not a function. Call it with `zsh update-from-upstream.zsh`
14 # from the command line, running it from within the plugin directory.
15 #
16 # You can set the environment variable REPO_PATH to point it at an upstream
17 # repo you have already prepared. Otherwise, it will do a clean checkout of
18 # upstream's HEAD to a temporary local repo and use that.
19
20
21 # Just bail on any error so we don't have to do extra checking.
22 # This is a developer-use script, so terse output like that should
23 # be fine.
24 set -e
25
26
27 upstream_basename=zsh-history-substring-search
28 plugin_basename=history-substring-search
29 UPSTREAM_REPO=zsh-users/$upstream_basename
30 need_repo_cleanup=false
31 upstream_github_url="https://github.com/$UPSTREAM_REPO"
32
33 if [[ -z "$UPSTREAM_REPO_PATH" ]]; then
34 # Do a clean checkout
35 my_tempdir=$(mktemp -d -t omz-update-histsubstrsrch)
36 UPSTREAM_REPO_PATH="$my_tempdir/$upstream_basename"
37 git clone "$upstream_github_url" "$UPSTREAM_REPO_PATH"
38 need_repo_cleanup=true
39 print "Checked out upstream repo to $UPSTREAM_REPO_PATH"
40 else
41 print "Using existing $upstream_basename repo at $UPSTREAM_REPO_PATH"
42 fi
43
44 upstream="$UPSTREAM_REPO_PATH"
45
46 # Figure out what we're pulling in
47 upstream_sha=$(cd $upstream && git rev-parse HEAD)
48 upstream_commit_date=$(cd $upstream && git log -1 --pretty=format:%ci)
49 upstream_just_date=${${=upstream_commit_date}[1]}
50 print "upstream SHA: $upstream_sha"
51 print "upstream commit time: $upstream_commit_date"
52 print "upstream commit date: $upstream_just_date"
53 print
54
55 # Copy the files over, using the OMZ plugin's names where needed
56 cp -v "$upstream"/* .
57 mv -v zsh-history-substring-search.zsh $plugin_basename.zsh
58 mv -v zsh-history-substring-search.plugin.zsh $plugin_basename.plugin.zsh
59
60 if [[ $need_repo_cleanup == true ]]; then
61 print "Removing temporary repo at $my_tempdir"
62 rm -rf "$my_tempdir"
63 fi
64
65 # Do OMZ-specific edits
66
67 print
68 print "Updating files with OMZ-specific stuff"
69 print
70
71 # OMZ binds the keys as part of the plugin loading
72
73 cat >> $plugin_basename.plugin.zsh <<EOF
74
75
76 # Bind terminal-specific up and down keys
77
78 if [[ -n "\$terminfo[kcuu1]" ]]; then
79 bindkey "\$terminfo[kcuu1]" history-substring-search-up
80 fi
81 if [[ -n "\$terminfo[kcud1]" ]]; then
82 bindkey "\$terminfo[kcud1]" history-substring-search-down
83 fi
84
85 EOF
86
87 # Tack OMZ-specific notes on to readme
88
89 thin_line="------------------------------------------------------------------------------"
90 cat >> README.md <<EOF
91
92 $thin_line
93 Oh My Zsh Distribution Notes
94 $thin_line
95
96 What you are looking at now is Oh My Zsh's repackaging of zsh-history-substring-search
97 as an OMZ module inside the Oh My Zsh distribution.
98
99 The upstream repo, $UPSTREAM_REPO, can be found on GitHub at
100 $upstream_github_url.
101
102 This downstream copy was last updated from the following upstream commit:
103
104 SHA: $upstream_sha
105 Commit date: $upstream_commit_date
106
107 Everything above this section is a copy of the original upstream's README, so things
108 may differ slightly when you're using this inside OMZ. In particular, you do not
109 need to set up key bindings for the up and down arrows yourself in \`~/.zshrc\`; the OMZ
110 plugin does that for you. You may still want to set up additional emacs- or vi-specific
111 bindings as mentioned above.
112
113 EOF
114
115 # Announce success and generate git commit messages
116
117 cat <<EOF
118 Done OK
119
120 Now you can check the results and commit like this:
121
122 git add *
123 git commit -m "history-substring-search: update to upstream version $upstream_just_date" \\
124 -m "Updates OMZ's copy to commit $upstream_sha from $UPSTREAM_REPO"
125
126 EOF
127
128
plugins/tmux-cssh/_tmux-cssh
File was created 1 #compdef tmux-cssh
2
3 # tmux-cssh autocompletion for oh-my-zsh
4 # Requires: tmux-cssh installed
5 # Author: Manfred Touron (@moul)
6
7 _arguments \
8 '(-h --help)'{-h,--help}'[This help.]' \
9 '(-u --user)'{-u,--user}'[User to use.]' \
10 '(-c --certificate)'{-c,--certificate}'[Path to ssh-certificate to use.]' \
11 '(-sc --ssh)'{-sc,--ssh}'[SSH-connection-string, multiple.]' \
12 '(-sa --ssh)'{-sa,--ssh}'[SSH connection arguments, used on every session.]' \
13 '(-ts --tmux)'{-ts,--tmux}'[Alternative tmux-session-name, default: tmux-cssh]' \
14 '(-ns --new)'{-ns,--new}'[Initializes a new session, like -ts \[name\].]' \
15 '(-q --quiet)'{-q,--quiet}'[Quiet-mode.]' \
16 '(-f --filename)'{-f,--filename}'[Filename of textfile to get -sc connection-strings from, line separated.]' \
17 '(-cs --config)'{-cs,--config}'[Name of config-settings which should be get from config-file "$HOME/.tmux-cssh". Which can be a grep-regular expression to find the name(s).]' \
18 ':hosts:_hosts' \
19 '*:: :->subcmds' \
20 && return 0
21
22 if (( CURRENT == 1 )); then
23 _describe -t commands "tmux-cssh command"
24 return
25 fi
26
plugins/vi-mode/vi-mode.plugin.zsh
1 # Ensures that $terminfo values are valid and updates editor information when 1 # Updates editor information when the keymap changes.
2 # the keymap changes. 2 function zle-keymap-select() {
3 function zle-keymap-select zle-line-init zle-line-finish {
4 # The terminal must be in application mode when ZLE is active for $terminfo
5 # values to be valid.
6 if (( ${+terminfo[smkx]} )); then
7 printf '%s' ${terminfo[smkx]}
8 fi
9 if (( ${+terminfo[rmkx]} )); then
10 printf '%s' ${terminfo[rmkx]}
11 fi
12
13 zle reset-prompt 3 zle reset-prompt
14 zle -R 4 zle -R
15 } 5 }
16 6
17 # Ensure that the prompt is redrawn when the terminal size changes. 7 # Ensure that the prompt is redrawn when the terminal size changes.
18 TRAPWINCH() { 8 TRAPWINCH() {
19 zle && { zle reset-prompt; zle -R } 9 zle && { zle reset-prompt; zle -R }
20 } 10 }
21 11
22 zle -N zle-line-init
23 zle -N zle-line-finish
24 zle -N zle-keymap-select 12 zle -N zle-keymap-select
25 zle -N edit-command-line 13 zle -N edit-command-line
26 14
27 15
28 bindkey -v 16 bindkey -v
29 17
30 # allow v to edit the command line (standard behaviour) 18 # allow v to edit the command line (standard behaviour)
31 autoload -Uz edit-command-line 19 autoload -Uz edit-command-line
32 bindkey -M vicmd 'v' edit-command-line 20 bindkey -M vicmd 'v' edit-command-line
33 21
34 # allow ctrl-p, ctrl-n for navigate history (standard behaviour) 22 # allow ctrl-p, ctrl-n for navigate history (standard behaviour)
35 bindkey '^P' up-history 23 bindkey '^P' up-history
36 bindkey '^N' down-history 24 bindkey '^N' down-history
37 25
38 # allow ctrl-h, ctrl-w, ctrl-? for char and word deletion (standard behaviour) 26 # allow ctrl-h, ctrl-w, ctrl-? for char and word deletion (standard behaviour)
39 bindkey '^?' backward-delete-char 27 bindkey '^?' backward-delete-char
40 bindkey '^h' backward-delete-char 28 bindkey '^h' backward-delete-char
41 bindkey '^w' backward-kill-word 29 bindkey '^w' backward-kill-word
42 30
43 # if mode indicator wasn't setup by theme, define default 31 # if mode indicator wasn't setup by theme, define default
44 if [[ "$MODE_INDICATOR" == "" ]]; then 32 if [[ "$MODE_INDICATOR" == "" ]]; then
45 MODE_INDICATOR="%{$fg_bold[red]%}<%{$fg[red]%}<<%{$reset_color%}" 33 MODE_INDICATOR="%{$fg_bold[red]%}<%{$fg[red]%}<<%{$reset_color%}"
46 fi 34 fi
47 35
48 function vi_mode_prompt_info() { 36 function vi_mode_prompt_info() {
49 echo "${${KEYMAP/vicmd/$MODE_INDICATOR}/(main|viins)/}" 37 echo "${${KEYMAP/vicmd/$MODE_INDICATOR}/(main|viins)/}"
50 } 38 }
51 39
52 # define right prompt, if it wasn't defined by a theme 40 # define right prompt, if it wasn't defined by a theme
53 if [[ "$RPS1" == "" && "$RPROMPT" == "" ]]; then 41 if [[ "$RPS1" == "" && "$RPROMPT" == "" ]]; then
54 RPS1='$(vi_mode_prompt_info)' 42 RPS1='$(vi_mode_prompt_info)'
55 fi 43 fi
56 44
1 #!/bin/zsh 1 #!/bin/zsh
2 2
3 # WARP DIRECTORY 3 # WARP DIRECTORY
4 # ============== 4 # ==============
5 # Jump to custom directories in terminal 5 # Jump to custom directories in terminal
6 # because `cd` takes too long... 6 # because `cd` takes too long...
7 # 7 #
8 # @github.com/mfaerevaag/wd 8 # @github.com/mfaerevaag/wd
9 9
10 # version 10 # version
11 readonly WD_VERSION=0.4 11 readonly WD_VERSION=0.4.2
12 12
13 # colors 13 # colors
14 readonly WD_BLUE="\033[96m" 14 readonly WD_BLUE="\033[96m"
15 readonly WD_GREEN="\033[92m" 15 readonly WD_GREEN="\033[92m"
16 readonly WD_YELLOW="\033[93m" 16 readonly WD_YELLOW="\033[93m"
17 readonly WD_RED="\033[91m" 17 readonly WD_RED="\033[91m"
18 readonly WD_NOC="\033[m" 18 readonly WD_NOC="\033[m"
19 19
20 ## functions 20 ## functions
21 21
22 # helpers 22 # helpers
23 wd_yesorno() 23 wd_yesorno()
24 { 24 {
25 # variables 25 # variables
26 local question="${1}" 26 local question="${1}"
27 local prompt="${question} " 27 local prompt="${question} "
28 local yes_RETVAL="0" 28 local yes_RETVAL="0"
29 local no_RETVAL="3" 29 local no_RETVAL="3"
30 local RETVAL="" 30 local RETVAL=""
31 local answer="" 31 local answer=""
32 32
33 # read-eval loop 33 # read-eval loop
34 while true ; do 34 while true ; do
35 printf $prompt 35 printf $prompt
36 read -r answer 36 read -r answer
37 37
38 case ${answer:=${default}} in 38 case ${answer:=${default}} in
39 Y|y|YES|yes|Yes ) 39 Y|y|YES|yes|Yes )
40 RETVAL=${yes_RETVAL} && \ 40 RETVAL=${yes_RETVAL} && \
41 break 41 break
42 ;; 42 ;;
43 N|n|NO|no|No ) 43 N|n|NO|no|No )
44 RETVAL=${no_RETVAL} && \ 44 RETVAL=${no_RETVAL} && \
45 break 45 break
46 ;; 46 ;;
47 * ) 47 * )
48 echo "Please provide a valid answer (y or n)" 48 echo "Please provide a valid answer (y or n)"
49 ;; 49 ;;
50 esac 50 esac
51 done 51 done
52 52
53 return ${RETVAL} 53 return ${RETVAL}
54 } 54 }
55 55
56 wd_print_msg() 56 wd_print_msg()
57 { 57 {
58 if [[ -z $wd_quiet_mode ]] 58 if [[ -z $wd_quiet_mode ]]
59 then 59 then
60 local color=$1 60 local color=$1
61 local msg=$2 61 local msg=$2
62 62
63 if [[ $color == "" || $msg == "" ]] 63 if [[ $color == "" || $msg == "" ]]
64 then 64 then
65 print " ${WD_RED}*${WD_NOC} Could not print message. Sorry!" 65 print " ${WD_RED}*${WD_NOC} Could not print message. Sorry!"
66 else 66 else
67 print " ${color}*${WD_NOC} ${msg}" 67 print " ${color}*${WD_NOC} ${msg}"
68 fi 68 fi
69 fi 69 fi
70 } 70 }
71 71
72 wd_print_usage() 72 wd_print_usage()
73 { 73 {
74 cat <<- EOF 74 cat <<- EOF
75 Usage: wd [command] <point> 75 Usage: wd [command] <point>
76 76
77 Commands: 77 Commands:
78 add <point> Adds the current working directory to your warp points 78 add <point> Adds the current working directory to your warp points
79 add! <point> Overwrites existing warp point 79 add! <point> Overwrites existing warp point
80 rm <point> Removes the given warp point 80 rm <point> Removes the given warp point
81 show Print warp points to current directory 81 show Print warp points to current directory
82 show <point> Print path to given warp point 82 show <point> Print path to given warp point
83 list Print all stored warp points 83 list Print all stored warp points
84 ls <point> Show files from given warp point 84 ls <point> Show files from given warp point
85 path <point> Show the path to given warp point 85 path <point> Show the path to given warp point
86 clean! Remove points warping to nonexistent directories 86 clean! Remove points warping to nonexistent directories
87 87
88 -v | --version Print version 88 -v | --version Print version
89 -d | --debug Exit after execution with exit codes (for testing) 89 -d | --debug Exit after execution with exit codes (for testing)
90 -c | --config Specify config file (default ~/.warprc) 90 -c | --config Specify config file (default ~/.warprc)
91 -q | --quiet Suppress all output 91 -q | --quiet Suppress all output
92 92
93 help Show this extremely helpful text 93 help Show this extremely helpful text
94 EOF 94 EOF
95 } 95 }
96 96
97 wd_exit_fail() 97 wd_exit_fail()
98 { 98 {
99 local msg=$1 99 local msg=$1
100 100
101 wd_print_msg $WD_RED $msg 101 wd_print_msg $WD_RED $msg
102 WD_EXIT_CODE=1 102 WD_EXIT_CODE=1
103 } 103 }
104 104
105 wd_exit_warn() 105 wd_exit_warn()
106 { 106 {
107 local msg=$1 107 local msg=$1
108 108
109 wd_print_msg $WD_YELLOW $msg 109 wd_print_msg $WD_YELLOW $msg
110 WD_EXIT_CODE=1 110 WD_EXIT_CODE=1
111 } 111 }
112 112
113 wd_getdir() 113 wd_getdir()
114 { 114 {
115 local name_arg=$1 115 local name_arg=$1
116 116
117 point=$(wd_show $name_arg) 117 point=$(wd_show $name_arg)
118 dir=${point:28+$#name_arg+7} 118 dir=${point:28+$#name_arg+7}
119 119
120 if [[ -z $name_arg ]]; then 120 if [[ -z $name_arg ]]; then
121 wd_exit_fail "You must enter a warp point" 121 wd_exit_fail "You must enter a warp point"
122 break 122 break
123 elif [[ -z $dir ]]; then 123 elif [[ -z $dir ]]; then
124 wd_exit_fail "Unknown warp point '${name_arg}'" 124 wd_exit_fail "Unknown warp point '${name_arg}'"
125 break 125 break
126 fi 126 fi
127 } 127 }
128 128
129 # core 129 # core
130 130
131 wd_warp() 131 wd_warp()
132 { 132 {
133 local point=$1 133 local point=$1
134 134
135 if [[ $point =~ "^\.+$" ]] 135 if [[ $point =~ "^\.+$" ]]
136 then 136 then
137 if [ $#1 < 2 ] 137 if [ $#1 < 2 ]
138 then 138 then
139 wd_exit_warn "Warping to current directory?" 139 wd_exit_warn "Warping to current directory?"
140 else 140 else
141 (( n = $#1 - 1 )) 141 (( n = $#1 - 1 ))
142 cd -$n > /dev/null 142 cd -$n > /dev/null
143 fi 143 fi
144 elif [[ ${points[$point]} != "" ]] 144 elif [[ ${points[$point]} != "" ]]
145 then 145 then
146 cd ${points[$point]} 146 cd ${points[$point]/#\~/$HOME}
147 else 147 else
148 wd_exit_fail "Unknown warp point '${point}'" 148 wd_exit_fail "Unknown warp point '${point}'"
149 fi 149 fi
150 } 150 }
151 151
152 wd_add() 152 wd_add()
153 { 153 {
154 local force=$1 154 local force=$1
155 local point=$2 155 local point=$2
156 156
157 if [[ $point =~ "^[\.]+$" ]] 157 if [[ $point =~ "^[\.]+$" ]]
158 then 158 then
159 wd_exit_fail "Warp point cannot be just dots" 159 wd_exit_fail "Warp point cannot be just dots"
160 elif [[ $point =~ "[[:space:]]+" ]] 160 elif [[ $point =~ "[[:space:]]+" ]]
161 then 161 then
162 wd_exit_fail "Warp point should not contain whitespace" 162 wd_exit_fail "Warp point should not contain whitespace"
163 elif [[ $point == *:* ]] 163 elif [[ $point == *:* ]]
164 then 164 then
165 wd_exit_fail "Warp point cannot contain colons" 165 wd_exit_fail "Warp point cannot contain colons"
166 elif [[ $point == "" ]] 166 elif [[ $point == "" ]]
167 then 167 then
168 wd_exit_fail "Warp point cannot be empty" 168 wd_exit_fail "Warp point cannot be empty"
169 elif [[ ${points[$2]} == "" ]] || $force 169 elif [[ ${points[$2]} == "" ]] || $force
170 then 170 then
171 wd_remove $point > /dev/null 171 wd_remove $point > /dev/null
172 printf "%q:%s\n" "${point}" "${PWD}" >> $WD_CONFIG 172 printf "%q:%s\n" "${point}" "${PWD/#$HOME/~}" >> $WD_CONFIG
173 173
174 wd_print_msg $WD_GREEN "Warp point added" 174 wd_print_msg $WD_GREEN "Warp point added"
175 175
176 # override exit code in case wd_remove did not remove any points 176 # override exit code in case wd_remove did not remove any points
177 # TODO: we should handle this kind of logic better 177 # TODO: we should handle this kind of logic better
178 WD_EXIT_CODE=0 178 WD_EXIT_CODE=0
179 else 179 else
180 wd_exit_warn "Warp point '${point}' already exists. Use 'add!' to overwrite." 180 wd_exit_warn "Warp point '${point}' already exists. Use 'add!' to overwrite."
181 fi 181 fi
182 } 182 }
183 183
184 wd_remove() 184 wd_remove()
185 { 185 {
186 local point=$1 186 local point=$1
187 187
188 if [[ ${points[$point]} != "" ]] 188 if [[ ${points[$point]} != "" ]]
189 then 189 then
190 local config_tmp=$WD_CONFIG.tmp 190 local config_tmp=$WD_CONFIG.tmp
191 if sed -n "/^${point}:.*$/!p" $WD_CONFIG > $config_tmp && mv $config_tmp $WD_CONFIG 191 if sed -n "/^${point}:.*$/!p" $WD_CONFIG > $config_tmp && mv $config_tmp $WD_CONFIG
192 then 192 then
193 wd_print_msg $WD_GREEN "Warp point removed" 193 wd_print_msg $WD_GREEN "Warp point removed"
194 else 194 else
195 wd_exit_fail "Something bad happened! Sorry." 195 wd_exit_fail "Something bad happened! Sorry."
196 fi 196 fi
197 else 197 else
198 wd_exit_fail "Warp point was not found" 198 wd_exit_fail "Warp point was not found"
199 fi 199 fi
200 } 200 }
201 201
202 wd_list_all() 202 wd_list_all()
203 { 203 {
204 wd_print_msg $WD_BLUE "All warp points:" 204 wd_print_msg $WD_BLUE "All warp points:"
205 205
206 entries=$(sed "s:${HOME}:~:g" $WD_CONFIG)
207
208 max_warp_point_length=0
209 while IFS= read -r line
210 do
211 arr=(${(s,:,)line})
212 key=${arr[1]}
213
214 length=${#key}
215 if [[ length -gt max_warp_point_length ]]
216 then
217 max_warp_point_length=$length
218 fi
219 done <<< $entries
220
206 while IFS= read -r line 221 while IFS= read -r line
207 do 222 do
208 if [[ $line != "" ]] 223 if [[ $line != "" ]]
209 then 224 then
210 arr=(${(s,:,)line}) 225 arr=(${(s,:,)line})
211 key=${arr[1]} 226 key=${arr[1]}
212 val=${arr[2]} 227 val=${arr[2]}
213 228
214 if [[ -z $wd_quiet_mode ]] 229 if [[ -z $wd_quiet_mode ]]
215 then 230 then
216 printf "%20s -> %s\n" $key $val 231 printf "%${max_warp_point_length}s -> %s\n" $key $val
217 fi 232 fi
218 fi 233 fi
219 done <<< $(sed "s:${HOME}:~:g" $WD_CONFIG) 234 done <<< $entries
220 } 235 }
221 236
222 wd_ls() 237 wd_ls()
223 { 238 {
224 wd_getdir $1 239 wd_getdir $1
225 ls $dir 240 ls ${dir/#\~/$HOME}
226 } 241 }
227 242
228 wd_path() 243 wd_path()
229 { 244 {
230 wd_getdir $1 245 wd_getdir $1
231 echo $(echo $dir | sed "s:${HOME}:~:g") 246 echo $(echo $dir | sed "s:${HOME}:~:g")
232 } 247 }
233 248
234 wd_show() 249 wd_show()
235 { 250 {
236 local name_arg=$1 251 local name_arg=$1
237 # if there's an argument we look up the value 252 # if there's an argument we look up the value
238 if [[ ! -z $name_arg ]] 253 if [[ ! -z $name_arg ]]
239 then 254 then
240 if [[ -z $points[$name_arg] ]] 255 if [[ -z $points[$name_arg] ]]
241 then 256 then
242 wd_print_msg $WD_BLUE "No warp point named $name_arg" 257 wd_print_msg $WD_BLUE "No warp point named $name_arg"
243 else 258 else
244 wd_print_msg $WD_GREEN "Warp point: ${WD_GREEN}$name_arg${WD_NOC} -> $points[$name_arg]" 259 wd_print_msg $WD_GREEN "Warp point: ${WD_GREEN}$name_arg${WD_NOC} -> $points[$name_arg]"
245 fi 260 fi
246 else 261 else
247 # hax to create a local empty array 262 # hax to create a local empty array
248 local wd_matches 263 local wd_matches
249 wd_matches=() 264 wd_matches=()
250 # do a reverse lookup to check whether PWD is in $points 265 # do a reverse lookup to check whether PWD is in $points
266 PWD="${PWD/$HOME/~}"
251 if [[ ${points[(r)$PWD]} == $PWD ]] 267 if [[ ${points[(r)$PWD]} == $PWD ]]
252 then 268 then
253 for name in ${(k)points} 269 for name in ${(k)points}
254 do 270 do
255 if [[ $points[$name] == $PWD ]] 271 if [[ $points[$name] == $PWD ]]
256 then 272 then
257 wd_matches[$(($#wd_matches+1))]=$name 273 wd_matches[$(($#wd_matches+1))]=$name
258 fi 274 fi
259 done 275 done
260 276
261 wd_print_msg $WD_BLUE "$#wd_matches warp point(s) to current directory: ${WD_GREEN}$wd_matches${WD_NOC}" 277 wd_print_msg $WD_BLUE "$#wd_matches warp point(s) to current directory: ${WD_GREEN}$wd_matches${WD_NOC}"
262 else 278 else
263 wd_print_msg $WD_YELLOW "No warp point to $(echo $PWD | sed "s:$HOME:~:")" 279 wd_print_msg $WD_YELLOW "No warp point to $(echo $PWD | sed "s:$HOME:~:")"
264 fi 280 fi
265 fi 281 fi
266 } 282 }
267 283
268 wd_clean() { 284 wd_clean() {
269 local force=$1 285 local force=$1
270 local count=0 286 local count=0
271 local wd_tmp="" 287 local wd_tmp=""
272 288
273 while read line 289 while read line
274 do 290 do
275 if [[ $line != "" ]] 291 if [[ $line != "" ]]
276 then 292 then
277 arr=(${(s,:,)line}) 293 arr=(${(s,:,)line})
278 key=${arr[1]} 294 key=${arr[1]}
279 val=${arr[2]} 295 val=${arr[2]}
280 296
281 if [ -d "$val" ] 297 if [ -d "$val" ]
282 then 298 then
283 wd_tmp=$wd_tmp"\n"`echo $line` 299 wd_tmp=$wd_tmp"\n"`echo $line`
284 else 300 else
285 wd_print_msg $WD_YELLOW "Nonexistent directory: ${key} -> ${val}" 301 wd_print_msg $WD_YELLOW "Nonexistent directory: ${key} -> ${val}"
286 count=$((count+1)) 302 count=$((count+1))
287 fi 303 fi
288 fi 304 fi
289 done < $WD_CONFIG 305 done < $WD_CONFIG
290 306
291 if [[ $count -eq 0 ]] 307 if [[ $count -eq 0 ]]
292 then 308 then
293 wd_print_msg $WD_BLUE "No warp points to clean, carry on!" 309 wd_print_msg $WD_BLUE "No warp points to clean, carry on!"
294 else 310 else
295 if $force || wd_yesorno "Removing ${count} warp points. Continue? (Y/n)" 311 if $force || wd_yesorno "Removing ${count} warp points. Continue? (Y/n)"
296 then 312 then
297 echo $wd_tmp >! $WD_CONFIG 313 echo $wd_tmp >! $WD_CONFIG
298 wd_print_msg $WD_GREEN "Cleanup complete. ${count} warp point(s) removed" 314 wd_print_msg $WD_GREEN "Cleanup complete. ${count} warp point(s) removed"
299 else 315 else
300 wd_print_msg $WD_BLUE "Cleanup aborted" 316 wd_print_msg $WD_BLUE "Cleanup aborted"
301 fi 317 fi
302 fi 318 fi
303 } 319 }
304 320
305 local WD_CONFIG=$HOME/.warprc 321 local WD_CONFIG=$HOME/.warprc
306 local WD_QUIET=0 322 local WD_QUIET=0
307 local WD_EXIT_CODE=0 323 local WD_EXIT_CODE=0
308 local WD_DEBUG=0 324 local WD_DEBUG=0
309 325
310 # Parse 'meta' options first to avoid the need to have them before 326 # Parse 'meta' options first to avoid the need to have them before
311 # other commands. The `-D` flag consumes recognized options so that 327 # other commands. The `-D` flag consumes recognized options so that
312 # the actual command parsing won't be affected. 328 # the actual command parsing won't be affected.
313 329
314 zparseopts -D -E \ 330 zparseopts -D -E \
315 c:=wd_alt_config -config:=wd_alt_config \ 331 c:=wd_alt_config -config:=wd_alt_config \
316 q=wd_quiet_mode -quiet=wd_quiet_mode \ 332 q=wd_quiet_mode -quiet=wd_quiet_mode \
317 v=wd_print_version -version=wd_print_version \ 333 v=wd_print_version -version=wd_print_version \
318 d=wd_debug_mode -debug=wd_debug_mode 334 d=wd_debug_mode -debug=wd_debug_mode
319 335
320 if [[ ! -z $wd_print_version ]] 336 if [[ ! -z $wd_print_version ]]
321 then 337 then
322 echo "wd version $WD_VERSION" 338 echo "wd version $WD_VERSION"
323 fi 339 fi
324 340
325 if [[ ! -z $wd_alt_config ]] 341 if [[ ! -z $wd_alt_config ]]
326 then 342 then
327 WD_CONFIG=$wd_alt_config[2] 343 WD_CONFIG=$wd_alt_config[2]
328 fi 344 fi
329 345
330 # check if config file exists 346 # check if config file exists
331 if [ ! -e $WD_CONFIG ] 347 if [ ! -e $WD_CONFIG ]
332 then 348 then
333 # if not, create config file 349 # if not, create config file
334 touch $WD_CONFIG 350 touch $WD_CONFIG
335 fi 351 fi
336 352
337 # load warp points 353 # load warp points
338 typeset -A points 354 typeset -A points
339 while read -r line 355 while read -r line
340 do 356 do
341 arr=(${(s,:,)line}) 357 arr=(${(s,:,)line})
342 key=${arr[1]} 358 key=${arr[1]}
343 val=${arr[2]} 359 val=${arr[2]}
344 360
345 points[$key]=$val 361 points[$key]=$val
346 done < $WD_CONFIG 362 done < $WD_CONFIG
347 363
348 # get opts 364 # get opts
349 args=$(getopt -o a:r:c:lhs -l add:,rm:,clean\!,list,ls:,path:,help,show -- $*) 365 args=$(getopt -o a:r:c:lhs -l add:,rm:,clean\!,list,ls:,path:,help,show -- $*)
350 366
351 # check if no arguments were given, and that version is not set 367 # check if no arguments were given, and that version is not set
352 if [[ ($? -ne 0 || $#* -eq 0) && -z $wd_print_version ]] 368 if [[ ($? -ne 0 || $#* -eq 0) && -z $wd_print_version ]]
353 then 369 then
354 wd_print_usage 370 wd_print_usage
355 371
356 # check if config file is writeable 372 # check if config file is writeable
357 elif [ ! -w $WD_CONFIG ] 373 elif [ ! -w $WD_CONFIG ]
358 then 374 then
359 # do nothing 375 # do nothing
360 # can't run `exit`, as this would exit the executing shell 376 # can't run `exit`, as this would exit the executing shell
361 wd_exit_fail "\'$WD_CONFIG\' is not writeable." 377 wd_exit_fail "\'$WD_CONFIG\' is not writeable."
362 378
363 else 379 else
364 380
365 # parse rest of options 381 # parse rest of options
366 for o 382 for o
367 do 383 do
368 case "$o" 384 case "$o"
369 in 385 in
370 -a|--add|add) 386 -a|--add|add)
371 wd_add false $2 387 wd_add false $2
372 break 388 break
373 ;; 389 ;;
374 -a!|--add!|add!) 390 -a!|--add!|add!)
375 wd_add true $2 391 wd_add true $2
376 break 392 break
377 ;; 393 ;;
378 -r|--remove|rm) 394 -r|--remove|rm)
379 wd_remove $2 395 wd_remove $2
380 break 396 break
381 ;; 397 ;;
382 -l|list) 398 -l|list)
383 wd_list_all 399 wd_list_all
384 break 400 break
385 ;; 401 ;;
386 -ls|ls) 402 -ls|ls)
387 wd_ls $2 403 wd_ls $2
388 break 404 break
389 ;; 405 ;;
390 -p|--path|path) 406 -p|--path|path)
391 wd_path $2 407 wd_path $2
392 break 408 break
393 ;; 409 ;;
394 -h|--help|help) 410 -h|--help|help)
395 wd_print_usage 411 wd_print_usage
396 break 412 break
397 ;; 413 ;;
398 -s|--show|show) 414 -s|--show|show)
399 wd_show $2 415 wd_show $2
400 break 416 break
401 ;; 417 ;;
402 -c|--clean|clean) 418 -c|--clean|clean)
403 wd_clean false 419 wd_clean false
404 break 420 break
405 ;; 421 ;;
406 -c!|--clean!|clean!) 422 -c!|--clean!|clean!)
407 wd_clean true 423 wd_clean true
408 break 424 break
409 ;; 425 ;;
410 *) 426 *)
411 wd_warp $o 427 wd_warp $o
412 break 428 break
413 ;; 429 ;;
414 --) 430 --)
415 break 431 break
416 ;; 432 ;;
417 esac 433 esac
418 done 434 done
419 fi 435 fi
420 436
421 ## garbage collection 437 ## garbage collection
422 # if not, next time warp will pick up variables from this run 438 # if not, next time warp will pick up variables from this run
423 # remember, there's no sub shell 439 # remember, there's no sub shell
424 440
425 unset wd_warp 441 unset wd_warp
426 unset wd_add 442 unset wd_add
427 unset wd_remove 443 unset wd_remove
428 unset wd_show 444 unset wd_show
429 unset wd_list_all 445 unset wd_list_all
430 unset wd_print_msg 446 unset wd_print_msg
431 unset wd_yesorno 447 unset wd_yesorno
432 unset wd_print_usage 448 unset wd_print_usage
433 unset wd_alt_config 449 unset wd_alt_config
434 unset wd_quiet_mode 450 unset wd_quiet_mode
435 unset wd_print_version 451 unset wd_print_version
436 452
437 unset args 453 unset args
438 unset points 454 unset points
439 unset val &> /dev/null # fixes issue #1 455 unset val &> /dev/null # fixes issue #1
440 456
441 if [[ ! -z $wd_debug_mode ]] 457 if [[ ! -z $wd_debug_mode ]]
442 then 458 then
443 exit $WD_EXIT_CODE 459 exit $WD_EXIT_CODE
444 else 460 else
445 unset wd_debug_mode 461 unset wd_debug_mode
446 fi 462 fi
447 463
1 Z(1) User Commands Z(1) 1 Z(1) User Commands Z(1)
2 2
3 3
4 4
5 NAME 5 NAME
6 z - jump around 6 z - jump around
7 7
8 SYNOPSIS 8 SYNOPSIS
9 z [-chlrt] [regex1 regex2 ... regexn] 9 z [-chlrtx] [regex1 regex2 ... regexn]
10 10
11 AVAILABILITY 11 AVAILABILITY
12 bash, zsh 12 bash, zsh
13 13
14 DESCRIPTION 14 DESCRIPTION
15 Tracks your most used directories, based on 'frecency'. 15 Tracks your most used directories, based on 'frecency'.
16 16
17 After a short learning phase, z will take you to the most 'frecent' 17 After a short learning phase, z will take you to the most 'frecent'
18 directory that matches ALL of the regexes given on the command line. 18 directory that matches ALL of the regexes given on the command line, in
19 order.
20
21 For example, z foo bar would match /foo/bar but not /bar/foo.
19 22
20 OPTIONS 23 OPTIONS
21 -c restrict matches to subdirectories of the current directory. 24 -c restrict matches to subdirectories of the current directory
22 25
23 -h show a brief help message 26 -h show a brief help message
24 27
25 -l list only 28 -l list only
26 29
27 -r match by rank only 30 -r match by rank only
28 31
29 -t match by recent access only 32 -t match by recent access only
30 33
34 -x remove the current directory from the datafile
35
31 EXAMPLES 36 EXAMPLES
32 z foo cd to most frecent dir matching foo 37 z foo cd to most frecent dir matching foo
33 38
34 z foo bar cd to most frecent dir matching foo and bar 39 z foo bar cd to most frecent dir matching foo, then bar
35 40
36 z -r foo cd to highest ranked dir matching foo 41 z -r foo cd to highest ranked dir matching foo
37 42
38 z -t foo cd to most recently accessed dir matching foo 43 z -t foo cd to most recently accessed dir matching foo
39 44
40 z -l foo list all dirs matching foo (by frecency) 45 z -l foo list all dirs matching foo (by frecency)
41 46
42 NOTES 47 NOTES
43 Installation: 48 Installation:
44 Put something like this in your $HOME/.bashrc or $HOME/.zshrc: 49 Put something like this in your $HOME/.bashrc or $HOME/.zshrc:
45 50
46 . /path/to/z.sh 51 . /path/to/z.sh
47 52
48 cd around for a while to build up the db. 53 cd around for a while to build up the db.
49 54
50 PROFIT!! 55 PROFIT!!
51 56
52 Optionally: 57 Optionally:
53 Set $_Z_CMD to change the command name (default z). 58 Set $_Z_CMD to change the command name (default z).
54 Set $_Z_DATA to change the datafile (default $HOME/.z). 59 Set $_Z_DATA to change the datafile (default $HOME/.z).
55 Set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution. 60 Set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
56 Set $_Z_NO_PROMPT_COMMAND to handle PROMPT_COMMAND/precmd your- 61 Set $_Z_NO_PROMPT_COMMAND to handle PROMPT_COMMAND/precmd your-
57 self. 62 self.
58 Set $_Z_EXCLUDE_DIRS to an array of directories to exclude. 63 Set $_Z_EXCLUDE_DIRS to an array of directory trees to exclude.
59 (These settings should go in .bashrc/.zshrc before the lines 64 Set $_Z_OWNER to allow usage when in 'sudo -s' mode.
65 (These settings should go in .bashrc/.zshrc before the line
60 added above.) 66 added above.)
61 Install the provided man page z.1 somewhere like 67 Install the provided man page z.1 somewhere like
62 /usr/local/man/man1. 68 /usr/local/man/man1.
63 69
64 Aging: 70 Aging:
65 The rank of directories maintained by z undergoes aging based on a sim- 71 The rank of directories maintained by z undergoes aging based on a sim-
66 ple formula. The rank of each entry is incremented every time it is 72 ple formula. The rank of each entry is incremented every time it is
67 accessed. When the sum of ranks is greater than 6000, all ranks are 73 accessed. When the sum of ranks is over 9000, all ranks are multiplied
68 multiplied by 0.99. Entries with a rank lower than 1 are forgotten. 74 by 0.99. Entries with a rank lower than 1 are forgotten.
69 75
70 Frecency: 76 Frecency:
71 Frecency is a portmantaeu of 'recent' and 'frequency'. It is a weighted 77 Frecency is a portmanteau of 'recent' and 'frequency'. It is a weighted
72 rank that depends on how often and how recently something occured. As 78 rank that depends on how often and how recently something occurred. As
73 far as I know, Mozilla came up with the term. 79 far as I know, Mozilla came up with the term.
74 80
75 To z, a directory that has low ranking but has been accessed recently 81 To z, a directory that has low ranking but has been accessed recently
76 will quickly have higher rank than a directory accessed frequently a 82 will quickly have higher rank than a directory accessed frequently a
77 long time ago. 83 long time ago.
78 84
79 Frecency is determined at runtime. 85 Frecency is determined at runtime.
80 86
81 Common: 87 Common:
82 When multiple directories match all queries, and they all have a common 88 When multiple directories match all queries, and they all have a common
83 prefix, z will cd to the shortest matching directory, without regard to 89 prefix, z will cd to the shortest matching directory, without regard to
84 priority. This has been in effect, if undocumented, for quite some 90 priority. This has been in effect, if undocumented, for quite some
85 time, but should probably be configurable or reconsidered. 91 time, but should probably be configurable or reconsidered.
86 92
87 Tab Completion: 93 Tab Completion:
88 z supports tab completion. After any number of arguments, press TAB to 94 z supports tab completion. After any number of arguments, press TAB to
89 complete on directories that match each argument. Due to limitations of 95 complete on directories that match each argument. Due to limitations of
90 the completion implementations, only the last argument will be com- 96 the completion implementations, only the last argument will be com-
91 pleted in the shell. 97 pleted in the shell.
92 98
93 Internally, z decides you've requested a completion if the last argu- 99 Internally, z decides you've requested a completion if the last argu-
94 ment passed is an absolute path to an existing directory. This may 100 ment passed is an absolute path to an existing directory. This may
95 cause unexpected behavior if the last argument to z begins with /. 101 cause unexpected behavior if the last argument to z begins with /.
96 102
97 ENVIRONMENT 103 ENVIRONMENT
98 A function _z() is defined. 104 A function _z() is defined.
99 105
100 The contents of the variable $_Z_CMD is aliased to _z 2>&1. If not set, 106 The contents of the variable $_Z_CMD is aliased to _z 2>&1. If not set,
101 $_Z_CMD defaults to z. 107 $_Z_CMD defaults to z.
102 108
103 The environment variable $_Z_DATA can be used to control the datafile 109 The environment variable $_Z_DATA can be used to control the datafile
104 location. If it is not defined, the location defaults to $HOME/.z. 110 location. If it is not defined, the location defaults to $HOME/.z.
105 111
106 The environment variable $_Z_NO_RESOLVE_SYMLINKS can be set to prevent 112 The environment variable $_Z_NO_RESOLVE_SYMLINKS can be set to prevent
107 resolving of symlinks. If it is not set, symbolic links will be 113 resolving of symlinks. If it is not set, symbolic links will be
108 resolved when added to the datafile. 114 resolved when added to the datafile.
109 115
110 In bash, z prepends a command to the PROMPT_COMMAND environment vari- 116 In bash, z appends a command to the PROMPT_COMMAND environment variable
111 able to maintain its database. In zsh, z appends a function _z_precmd 117 to maintain its database. In zsh, z appends a function _z_precmd to the
112 to the precmd_functions array. 118 precmd_functions array.
113 119
114 The environment variable $_Z_NO_PROMPT_COMMAND can be set if you want 120 The environment variable $_Z_NO_PROMPT_COMMAND can be set if you want
115 to handle PROMPT_COMMAND or precmd yourself. 121 to handle PROMPT_COMMAND or precmd yourself.
116 122
117 The environment variable $_Z_EXCLUDE_DIRS can be set to an array of 123 The environment variable $_Z_EXCLUDE_DIRS can be set to an array of
118 directories to exclude from tracking. $HOME is always excluded. Direc- 124 directory trees to exclude from tracking. $HOME is always excluded.
119 tories must be full paths without trailing slashes. 125 Directories must be full paths without trailing slashes.
126
127 The environment variable $_Z_OWNER can be set to your username, to
128 allow usage of z when your sudo enviroment keeps $HOME set.
120 129
121 FILES 130 FILES
122 Data is stored in $HOME/.z. This can be overridden by setting the 131 Data is stored in $HOME/.z. This can be overridden by setting the
123 $_Z_DATA environment variable. When initialized, z will raise an error 132 $_Z_DATA environment variable. When initialized, z will raise an error
124 if this path is a directory, and not function correctly. 133 if this path is a directory, and not function correctly.
125 134
126 A man page (z.1) is provided. 135 A man page (z.1) is provided.
127 136
128 SEE ALSO 137 SEE ALSO
129 regex(7), pushd, popd, autojump, cdargs 138 regex(7), pushd, popd, autojump, cdargs
130 139
131 Please file bugs at https://github.com/rupa/z/ 140 Please file bugs at https://github.com/rupa/z/
132 141
133 142
134 143
135 z January 2013 Z(1) 144 z January 2013 Z(1)
136 145
1 .TH "Z" "1" "January 2013" "z" "User Commands" 1 .TH "Z" "1" "January 2013" "z" "User Commands"
2 .SH 2 .SH
3 NAME 3 NAME
4 z \- jump around 4 z \- jump around
5 .SH 5 .SH
6 SYNOPSIS 6 SYNOPSIS
7 z [\-chlrt] [regex1 regex2 ... regexn] 7 z [\-chlrtx] [regex1 regex2 ... regexn]
8 .SH 8 .SH
9 AVAILABILITY 9 AVAILABILITY
10 bash, zsh 10 bash, zsh
11 .SH 11 .SH
12 DESCRIPTION 12 DESCRIPTION
13 Tracks your most used directories, based on 'frecency'. 13 Tracks your most used directories, based on 'frecency'.
14 .P 14 .P
15 After a short learning phase, \fBz\fR will take you to the most 'frecent' 15 After a short learning phase, \fBz\fR will take you to the most 'frecent'
16 directory that matches ALL of the regexes given on the command line. 16 directory that matches ALL of the regexes given on the command line, in order.
17
18 For example, \fBz foo bar\fR would match \fB/foo/bar\fR but not \fB/bar/foo\fR.
17 .SH 19 .SH
18 OPTIONS 20 OPTIONS
19 .TP 21 .TP
20 \fB\-c\fR 22 \fB\-c\fR
21 restrict matches to subdirectories of the current directory. 23 restrict matches to subdirectories of the current directory
22 .TP 24 .TP
23 \fB\-h\fR 25 \fB\-h\fR
24 show a brief help message 26 show a brief help message
25 .TP 27 .TP
26 \fB\-l\fR 28 \fB\-l\fR
27 list only 29 list only
28 .TP 30 .TP
29 \fB\-r\fR 31 \fB\-r\fR
30 match by rank only 32 match by rank only
31 .TP 33 .TP
32 \fB\-t\fR 34 \fB\-t\fR
33 match by recent access only 35 match by recent access only
36 .TP
37 \fB\-x\fR
38 remove the current directory from the datafile
34 .SH EXAMPLES 39 .SH EXAMPLES
35 .TP 14 40 .TP 14
36 \fBz foo\fR 41 \fBz foo\fR
37 cd to most frecent dir matching foo 42 cd to most frecent dir matching foo
38 .TP 14 43 .TP 14
39 \fBz foo bar\fR 44 \fBz foo bar\fR
40 cd to most frecent dir matching foo and bar 45 cd to most frecent dir matching foo, then bar
41 .TP 14 46 .TP 14
42 \fBz -r foo\fR 47 \fBz -r foo\fR
43 cd to highest ranked dir matching foo 48 cd to highest ranked dir matching foo
44 .TP 14 49 .TP 14
45 \fBz -t foo\fR 50 \fBz -t foo\fR
46 cd to most recently accessed dir matching foo 51 cd to most recently accessed dir matching foo
47 .TP 14 52 .TP 14
48 \fBz -l foo\fR 53 \fBz -l foo\fR
49 list all dirs matching foo (by frecency) 54 list all dirs matching foo (by frecency)
50 .SH 55 .SH
51 NOTES 56 NOTES
52 .SS 57 .SS
53 Installation: 58 Installation:
54 .P 59 .P
55 Put something like this in your \fB$HOME/.bashrc\fR or \fB$HOME/.zshrc\fR: 60 Put something like this in your \fB$HOME/.bashrc\fR or \fB$HOME/.zshrc\fR:
56 .RS 61 .RS
57 .P 62 .P
58 \fB. /path/to/z.sh\fR 63 \fB. /path/to/z.sh\fR
59 .RE 64 .RE
60 .P 65 .P
61 \fBcd\fR around for a while to build up the db. 66 \fBcd\fR around for a while to build up the db.
62 .P 67 .P
63 PROFIT!! 68 PROFIT!!
64 .P 69 .P
65 Optionally: 70 Optionally:
66 .RS 71 .RS
67 Set \fB$_Z_CMD\fR to change the command name (default \fBz\fR). 72 Set \fB$_Z_CMD\fR to change the command name (default \fBz\fR).
68 .RE 73 .RE
69 .RS 74 .RS
70 Set \fB$_Z_DATA\fR to change the datafile (default \fB$HOME/.z\fR). 75 Set \fB$_Z_DATA\fR to change the datafile (default \fB$HOME/.z\fR).
71 .RE 76 .RE
72 .RS 77 .RS
73 Set \fB$_Z_NO_RESOLVE_SYMLINKS\fR to prevent symlink resolution. 78 Set \fB$_Z_NO_RESOLVE_SYMLINKS\fR to prevent symlink resolution.
74 .RE 79 .RE
75 .RS 80 .RS
76 Set \fB$_Z_NO_PROMPT_COMMAND\fR to handle \fBPROMPT_COMMAND/precmd\fR yourself. 81 Set \fB$_Z_NO_PROMPT_COMMAND\fR to handle \fBPROMPT_COMMAND/precmd\fR yourself.
77 .RE 82 .RE
78 .RS 83 .RS
79 Set \fB$_Z_EXCLUDE_DIRS\fR to an array of directories to exclude. 84 Set \fB$_Z_EXCLUDE_DIRS\fR to an array of directory trees to exclude.
85 .RE
86 .RS
87 Set \fB$_Z_OWNER\fR to allow usage when in 'sudo -s' mode.
80 .RE 88 .RE
81 .RS 89 .RS
82 (These settings should go in .bashrc/.zshrc before the lines added above.) 90 (These settings should go in .bashrc/.zshrc before the line added above.)
83 .RE 91 .RE
84 .RS 92 .RS
85 Install the provided man page \fBz.1\fR somewhere like \fB/usr/local/man/man1\fR. 93 Install the provided man page \fBz.1\fR somewhere like \fB/usr/local/man/man1\fR.
86 .RE 94 .RE
87 .SS 95 .SS
88 Aging: 96 Aging:
89 The rank of directories maintained by \fBz\fR undergoes aging based on a simple 97 The rank of directories maintained by \fBz\fR undergoes aging based on a simple
90 formula. The rank of each entry is incremented every time it is accessed. When 98 formula. The rank of each entry is incremented every time it is accessed. When
91 the sum of ranks is greater than 6000, all ranks are multiplied by 0.99. Entries 99 the sum of ranks is over 9000, all ranks are multiplied by 0.99. Entries with a
92 with a rank lower than 1 are forgotten. 100 rank lower than 1 are forgotten.
93 .SS 101 .SS
94 Frecency: 102 Frecency:
95 Frecency is a portmantaeu of 'recent' and 'frequency'. It is a weighted rank 103 Frecency is a portmanteau of 'recent' and 'frequency'. It is a weighted rank
96 that depends on how often and how recently something occured. As far as I 104 that depends on how often and how recently something occurred. As far as I
97 know, Mozilla came up with the term. 105 know, Mozilla came up with the term.
98 .P 106 .P
99 To \fBz\fR, a directory that has low ranking but has been accessed recently 107 To \fBz\fR, a directory that has low ranking but has been accessed recently
100 will quickly have higher rank than a directory accessed frequently a long time 108 will quickly have higher rank than a directory accessed frequently a long time
101 ago. 109 ago.
102 .P 110 .P
103 Frecency is determined at runtime. 111 Frecency is determined at runtime.
104 .SS 112 .SS
105 Common: 113 Common:
106 When multiple directories match all queries, and they all have a common prefix, 114 When multiple directories match all queries, and they all have a common prefix,
107 \fBz\fR will cd to the shortest matching directory, without regard to priority. 115 \fBz\fR will cd to the shortest matching directory, without regard to priority.
108 This has been in effect, if undocumented, for quite some time, but should 116 This has been in effect, if undocumented, for quite some time, but should
109 probably be configurable or reconsidered. 117 probably be configurable or reconsidered.
110 .SS 118 .SS
111 Tab Completion: 119 Tab Completion:
112 \fBz\fR supports tab completion. After any number of arguments, press TAB to 120 \fBz\fR supports tab completion. After any number of arguments, press TAB to
113 complete on directories that match each argument. Due to limitations of the 121 complete on directories that match each argument. Due to limitations of the
114 completion implementations, only the last argument will be completed in the 122 completion implementations, only the last argument will be completed in the
115 shell. 123 shell.
116 .P 124 .P
117 Internally, \fBz\fR decides you've requested a completion if the last argument 125 Internally, \fBz\fR decides you've requested a completion if the last argument
118 passed is an absolute path to an existing directory. This may cause unexpected 126 passed is an absolute path to an existing directory. This may cause unexpected
119 behavior if the last argument to \fBz\fR begins with \fB/\fR. 127 behavior if the last argument to \fBz\fR begins with \fB/\fR.
120 .SH 128 .SH
121 ENVIRONMENT 129 ENVIRONMENT
122 A function \fB_z()\fR is defined. 130 A function \fB_z()\fR is defined.
123 .P 131 .P
124 The contents of the variable \fB$_Z_CMD\fR is aliased to \fB_z 2>&1\fR. If not 132 The contents of the variable \fB$_Z_CMD\fR is aliased to \fB_z 2>&1\fR. If not
125 set, \fB$_Z_CMD\fR defaults to \fBz\fR. 133 set, \fB$_Z_CMD\fR defaults to \fBz\fR.
126 .P 134 .P
127 The environment variable \fB$_Z_DATA\fR can be used to control the datafile 135 The environment variable \fB$_Z_DATA\fR can be used to control the datafile
128 location. If it is not defined, the location defaults to \fB$HOME/.z\fR. 136 location. If it is not defined, the location defaults to \fB$HOME/.z\fR.
129 .P 137 .P
130 The environment variable \fB$_Z_NO_RESOLVE_SYMLINKS\fR can be set to prevent 138 The environment variable \fB$_Z_NO_RESOLVE_SYMLINKS\fR can be set to prevent
131 resolving of symlinks. If it is not set, symbolic links will be resolved when 139 resolving of symlinks. If it is not set, symbolic links will be resolved when
132 added to the datafile. 140 added to the datafile.
133 .P 141 .P
134 In bash, \fBz\fR prepends a command to the \fBPROMPT_COMMAND\fR environment 142 In bash, \fBz\fR appends a command to the \fBPROMPT_COMMAND\fR environment
135 variable to maintain its database. In zsh, \fBz\fR appends a function 143 variable to maintain its database. In zsh, \fBz\fR appends a function
136 \fB_z_precmd\fR to the \fBprecmd_functions\fR array. 144 \fB_z_precmd\fR to the \fBprecmd_functions\fR array.
137 .P 145 .P
138 The environment variable \fB$_Z_NO_PROMPT_COMMAND\fR can be set if you want to 146 The environment variable \fB$_Z_NO_PROMPT_COMMAND\fR can be set if you want to
139 handle \fBPROMPT_COMMAND\fR or \fBprecmd\fR yourself. 147 handle \fBPROMPT_COMMAND\fR or \fBprecmd\fR yourself.
140 .P 148 .P
141 The environment variable \fB$_Z_EXCLUDE_DIRS\fR can be set to an array of 149 The environment variable \fB$_Z_EXCLUDE_DIRS\fR can be set to an array of
142 directories to exclude from tracking. \fB$HOME\fR is always excluded. 150 directory trees to exclude from tracking. \fB$HOME\fR is always excluded.
143 Directories must be full paths without trailing slashes. 151 Directories must be full paths without trailing slashes.
152 .P
153 The environment variable \fB$_Z_OWNER\fR can be set to your username, to
154 allow usage of \fBz\fR when your sudo enviroment keeps \fB$HOME\fR set.
144 .SH 155 .SH
145 FILES 156 FILES
146 Data is stored in \fB$HOME/.z\fR. This can be overridden by setting the 157 Data is stored in \fB$HOME/.z\fR. This can be overridden by setting the
147 \fB$_Z_DATA\fR environment variable. When initialized, \fBz\fR will raise an 158 \fB$_Z_DATA\fR environment variable. When initialized, \fBz\fR will raise an
148 error if this path is a directory, and not function correctly. 159 error if this path is a directory, and not function correctly.
149 .P 160 .P
150 A man page (\fBz.1\fR) is provided. 161 A man page (\fBz.1\fR) is provided.
151 .SH 162 .SH
152 SEE ALSO 163 SEE ALSO
153 regex(7), pushd, popd, autojump, cdargs 164 regex(7), pushd, popd, autojump, cdargs
154 .P 165 .P
155 Please file bugs at https://github.com/rupa/z/ 166 Please file bugs at https://github.com/rupa/z/
156 167
plugins/z/z.plugin.zsh
1 _load_z() { 1 source "${0:h}/z.sh"
2 source $1/z.sh
3 }
4
5 [[ -f $ZSH_CUSTOM/plugins/z/z.plugin.zsh ]] && _load_z $ZSH_CUSTOM/plugins/z
6 [[ -f $ZSH/plugins/z/z.plugin.zsh ]] && _load_z $ZSH/plugins/z
7 2
1 # Copyright (c) 2009 rupa deadwyler under the WTFPL license 1 # Copyright (c) 2009 rupa deadwyler under the WTFPL license
2 2
3 # maintains a jump-list of the directories you actually use 3 # maintains a jump-list of the directories you actually use
4 # 4 #
5 # INSTALL: 5 # INSTALL:
6 # * put something like this in your .bashrc/.zshrc: 6 # * put something like this in your .bashrc/.zshrc:
7 # . /path/to/z.sh 7 # . /path/to/z.sh
8 # * cd around for a while to build up the db 8 # * cd around for a while to build up the db
9 # * PROFIT!! 9 # * PROFIT!!
10 # * optionally: 10 # * optionally:
11 # set $_Z_CMD in .bashrc/.zshrc to change the command (default z). 11 # set $_Z_CMD in .bashrc/.zshrc to change the command (default z).
12 # set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z). 12 # set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).
13 # set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution. 13 # set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
14 # set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself. 14 # set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
15 # set $_Z_EXCLUDE_DIRS to an array of directories to exclude. 15 # set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
16 # set $_Z_OWNER to your username if you want use z while sudo with $HOME kept
16 # 17 #
17 # USE: 18 # USE:
18 # * z foo # cd to most frecent dir matching foo 19 # * z foo # cd to most frecent dir matching foo
19 # * z foo bar # cd to most frecent dir matching foo and bar 20 # * z foo bar # cd to most frecent dir matching foo and bar
20 # * z -r foo # cd to highest ranked dir matching foo 21 # * z -r foo # cd to highest ranked dir matching foo
21 # * z -t foo # cd to most recently accessed dir matching foo 22 # * z -t foo # cd to most recently accessed dir matching foo
22 # * z -l foo # list matches instead of cd 23 # * z -l foo # list matches instead of cd
23 # * z -c foo # restrict matches to subdirs of $PWD 24 # * z -c foo # restrict matches to subdirs of $PWD
24
25 case $- in
26 *i*) ;;
27 *) echo 'ERROR: z.sh is meant to be sourced, not directly executed.'
28 esac
29 25
30 [ -d "${_Z_DATA:-$HOME/.z}" ] && { 26 [ -d "${_Z_DATA:-$HOME/.z}" ] && {
31 echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory." 27 echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
32 } 28 }
33 29
34 _z() { 30 _z() {
35 31
36 local datafile="${_Z_DATA:-$HOME/.z}" 32 local datafile="${_Z_DATA:-$HOME/.z}"
37 33
38 # bail out if we don't own ~/.z (we're another user but our ENV is still set) 34 # bail if we don't own ~/.z and $_Z_OWNER not set
39 [ -f "$datafile" -a ! -O "$datafile" ] && return 35 [ -z "$_Z_OWNER" -a -f "$datafile" -a ! -O "$datafile" ] && return
40 36
41 # add entries 37 # add entries
42 if [ "$1" = "--add" ]; then 38 if [ "$1" = "--add" ]; then
43 shift 39 shift
44 40
45 # $HOME isn't worth matching 41 # $HOME isn't worth matching
46 [ "$*" = "$HOME" ] && return 42 [ "$*" = "$HOME" ] && return
47 43
48 # don't track excluded dirs 44 # don't track excluded directory trees
49 local exclude 45 local exclude
50 for exclude in "${_Z_EXCLUDE_DIRS[@]}"; do 46 for exclude in "${_Z_EXCLUDE_DIRS[@]}"; do
51 [ "$*" = "$exclude" ] && return 47 case "$*" in "$exclude*") return;; esac
52 done 48 done
53 49
54 # maintain the file 50 # maintain the data file
55 local tempfile 51 local tempfile="$datafile.$RANDOM"
56 tempfile="$(mktemp "$datafile.XXXXXX")" || return 52 while read line; do
57 while read line; do 53 # only count directories
58 [ -d "${line%%\|*}" ] && echo $line 54 [ -d "${line%%\|*}" ] && echo $line
59 done < "$datafile" | awk -v path="$*" -v now="$(date +%s)" -F"|" ' 55 done < "$datafile" | awk -v path="$*" -v now="$(date +%s)" -F"|" '
60 BEGIN { 56 BEGIN {
61 rank[path] = 1 57 rank[path] = 1
62 time[path] = now 58 time[path] = now
63 } 59 }
64 $2 >= 1 { 60 $2 >= 1 {
65 if( $1 == path ) { 61 # drop ranks below 1
66 rank[$1] = $2 + 1 62 if( $1 == path ) {
67 time[$1] = now 63 rank[$1] = $2 + 1
68 } else { 64 time[$1] = now
69 rank[$1] = $2 65 } else {
70 time[$1] = $3 66 rank[$1] = $2
71 } 67 time[$1] = $3
72 count += $2 68 }
73 } 69 count += $2
74 END { 70 }
75 if( count > 6000 ) { 71 END {
76 for( i in rank ) print i "|" 0.99*rank[i] "|" time[i] # aging 72 if( count > 9000 ) {
77 } else for( i in rank ) print i "|" rank[i] "|" time[i] 73 # aging
78 } 74 for( x in rank ) print x "|" 0.99*rank[x] "|" time[x]
79 ' 2>/dev/null >| "$tempfile" 75 } else for( x in rank ) print x "|" rank[x] "|" time[x]
80 if [ $? -ne 0 -a -f "$datafile" ]; then 76 }
81 env rm -f "$tempfile" 77 ' 2>/dev/null >| "$tempfile"
82 else 78 # do our best to avoid clobbering the datafile in a race condition
83 env mv -f "$tempfile" "$datafile" 79 if [ $? -ne 0 -a -f "$datafile" ]; then
84 fi 80 env rm -f "$tempfile"
85 81 else
86 # tab completion 82 [ "$_Z_OWNER" ] && chown $_Z_OWNER:$(id -ng $_Z_OWNER) "$tempfile"
87 elif [ "$1" = "--complete" ]; then 83 env mv -f "$tempfile" "$datafile" || env rm -f "$tempfile"
88 while read line; do 84 fi
89 [ -d "${line%%\|*}" ] && echo $line 85
90 done < "$datafile" | awk -v q="$2" -F"|" ' 86 # tab completion
91 BEGIN { 87 elif [ "$1" = "--complete" -a -s "$datafile" ]; then
92 if( q == tolower(q) ) nocase = 1 88 while read line; do
93 split(substr(q,3),fnd," ") 89 [ -d "${line%%\|*}" ] && echo $line
94 } 90 done < "$datafile" | awk -v q="$2" -F"|" '
95 { 91 BEGIN {
96 if( nocase ) { 92 if( q == tolower(q) ) imatch = 1
97 for( i in fnd ) tolower($1) !~ tolower(fnd[i]) && $1 = "" 93 q = substr(q, 3)
98 } else { 94 gsub(" ", ".*", q)
99 for( i in fnd ) $1 !~ fnd[i] && $1 = "" 95 }
100 } 96 {
101 if( $1 ) print $1 97 if( imatch ) {
102 } 98 if( tolower($1) ~ tolower(q) ) print $1
103 ' 2>/dev/null 99 } else if( $1 ~ q ) print $1
104 100 }
105 else 101 ' 2>/dev/null
106 # list/go 102
107 while [ "$1" ]; do case "$1" in 103 else
108 --) while [ "$1" ]; do shift; local fnd="$fnd $1";done;; 104 # list/go
109 -*) local opt=${1:1}; while [ "$opt" ]; do case ${opt:0:1} in 105 while [ "$1" ]; do case "$1" in
110 c) local fnd="^$PWD $fnd";; 106 --) while [ "$1" ]; do shift; local fnd="$fnd${fnd:+ }$1";done;;
111 h) echo "${_Z_CMD:-z} [-chlrt] args" >&2; return;; 107 -*) local opt=${1:1}; while [ "$opt" ]; do case ${opt:0:1} in
112 l) local list=1;; 108 c) local fnd="^$PWD $fnd";;
113 r) local typ="rank";; 109 h) echo "${_Z_CMD:-z} [-chlrtx] args" >&2; return;;
114 t) local typ="recent";; 110 x) sed -i -e "\:^${PWD}|.*:d" "$datafile";;
115 esac; opt=${opt:1}; done;; 111 l) local list=1;;
116 *) local fnd="$fnd $1";; 112 r) local typ="rank";;
117 esac; local last=$1; shift; done 113 t) local typ="recent";;
118 [ "$fnd" -a "$fnd" != "^$PWD " ] || local list=1 114 esac; opt=${opt:1}; done;;
119 115 *) local fnd="$fnd${fnd:+ }$1";;
120 # if we hit enter on a completion just go there 116 esac; local last=$1; [ "$#" -gt 0 ] && shift; done
121 case "$last" in 117 [ "$fnd" -a "$fnd" != "^$PWD " ] || local list=1
122 # completions will always start with / 118
123 /*) [ -z "$list" -a -d "$last" ] && cd "$last" && return;; 119 # if we hit enter on a completion just go there
124 esac 120 case "$last" in
125 121 # completions will always start with /
126 # no file yet 122 /*) [ -z "$list" -a -d "$last" ] && cd "$last" && return;;
127 [ -f "$datafile" ] || return 123 esac
128 124
129 local cd 125 # no file yet
130 cd="$(while read line; do 126 [ -f "$datafile" ] || return
131 [ -d "${line%%\|*}" ] && echo $line 127
132 done < "$datafile" | awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -F"|" ' 128 local cd
133 function frecent(rank, time) { 129 cd="$(while read line; do
134 dx = t-time 130 [ -d "${line%%\|*}" ] && echo $line
135 if( dx < 3600 ) return rank*4 131 done < "$datafile" | awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -F"|" '
136 if( dx < 86400 ) return rank*2 132 function frecent(rank, time) {
137 if( dx < 604800 ) return rank/2 133 # relate frequency and time
138 return rank/4 134 dx = t - time
139 } 135 if( dx < 3600 ) return rank * 4
140 function output(files, toopen, override) { 136 if( dx < 86400 ) return rank * 2
141 if( list ) { 137 if( dx < 604800 ) return rank / 2
142 cmd = "sort -n >&2" 138 return rank / 4
143 for( i in files ) if( files[i] ) printf "%-10s %s\n", files[i], i | cmd 139 }
144 if( override ) printf "%-10s %s\n", "common:", override > "/dev/stderr" 140 function output(files, out, common) {
145 } else { 141 # list or return the desired directory
146 if( override ) toopen = override 142 if( list ) {
147 print toopen 143 cmd = "sort -n >&2"
148 } 144 for( x in files ) {
149 } 145 if( files[x] ) printf "%-10s %s\n", files[x], x | cmd
150 function common(matches) { 146 }
151 # shortest match 147 if( common ) {
152 for( i in matches ) { 148 printf "%-10s %s\n", "common:", common > "/dev/stderr"
153 if( matches[i] && (!short || length(i) < length(short)) ) short = i 149 }
154 } 150 } else {
155 if( short == "/" ) return 151 if( common ) out = common
156 # shortest match must be common to each match. escape special characters in 152 print out
157 # a copy when testing, so we can return the original. 153 }
158 clean_short = short 154 }
159 gsub(/[\(\)\[\]\|]/, "\\\\&", clean_short) 155 function common(matches) {
160 for( i in matches ) if( matches[i] && i !~ clean_short ) return 156 # find the common root of a list of matches, if it exists
161 return short 157 for( x in matches ) {
162 } 158 if( matches[x] && (!short || length(x) < length(short)) ) {
163 BEGIN { split(q, a, " "); oldf = noldf = -9999999999 } 159 short = x
164 { 160 }
165 if( typ == "rank" ) { 161 }
166 f = $2 162 if( short == "/" ) return
167 } else if( typ == "recent" ) { 163 # use a copy to escape special characters, as we want to return
168 f = $3-t 164 # the original. yeah, this escaping is awful.
169 } else f = frecent($2, $3) 165 clean_short = short
170 wcase[$1] = nocase[$1] = f 166 gsub(/\[\(\)\[\]\|\]/, "\\\\&", clean_short)
171 for( i in a ) { 167 for( x in matches ) if( matches[x] && x !~ clean_short ) return
172 if( $1 !~ a[i] ) delete wcase[$1] 168 return short
173 if( tolower($1) !~ tolower(a[i]) ) delete nocase[$1] 169 }
174 } 170 BEGIN {
175 if( wcase[$1] && wcase[$1] > oldf ) { 171 gsub(" ", ".*", q)
176 cx = $1 172 hi_rank = ihi_rank = -9999999999
177 oldf = wcase[$1] 173 }
178 } else if( nocase[$1] && nocase[$1] > noldf ) { 174 {
179 ncx = $1 175 if( typ == "rank" ) {
180 noldf = nocase[$1] 176 rank = $2
181 } 177 } else if( typ == "recent" ) {
182 } 178 rank = $3 - t
183 END { 179 } else rank = frecent($2, $3)
184 if( cx ) { 180 if( $1 ~ q ) {
185 output(wcase, cx, common(wcase)) 181 matches[$1] = rank
186 } else if( ncx ) output(nocase, ncx, common(nocase)) 182 } else if( tolower($1) ~ tolower(q) ) imatches[$1] = rank
187 } 183 if( matches[$1] && matches[$1] > hi_rank ) {
188 ')" 184 best_match = $1
189 [ $? -gt 0 ] && return 185 hi_rank = matches[$1]
190 [ "$cd" ] && cd "$cd" 186 } else if( imatches[$1] && imatches[$1] > ihi_rank ) {
191 fi 187 ibest_match = $1
188 ihi_rank = imatches[$1]
189 }
190 }
191 END {
192 # prefer case sensitive
193 if( best_match ) {
194 output(matches, best_match, common(matches))
195 } else if( ibest_match ) {
196 output(imatches, ibest_match, common(imatches))
197 }
198 }
199 ')"
200 [ $? -gt 0 ] && return
201 [ "$cd" ] && cd "$cd"
202 fi
192 } 203 }
193 204
194 alias ${_Z_CMD:-z}='_z 2>&1' 205 alias ${_Z_CMD:-z}='_z 2>&1'
195 206
196 [ "$_Z_NO_RESOLVE_SYMLINKS" ] || _Z_RESOLVE_SYMLINKS="-P" 207 [ "$_Z_NO_RESOLVE_SYMLINKS" ] || _Z_RESOLVE_SYMLINKS="-P"
197 208
198 if compctl &> /dev/null; then 209 if type compctl >/dev/null 2>&1; then
199 [ "$_Z_NO_PROMPT_COMMAND" ] || { 210 # zsh
200 # zsh populate directory list, avoid clobbering any other precmds 211 [ "$_Z_NO_PROMPT_COMMAND" ] || {
201 if [ "$_Z_NO_RESOLVE_SYMLINKS" ]; then 212 # populate directory list, avoid clobbering any other precmds.
202 _z_precmd() { 213 if [ "$_Z_NO_RESOLVE_SYMLINKS" ]; then
203 _z --add "${PWD:a}" 214 _z_precmd() {
215 _z --add "${PWD:a}"
216 }
217 else
218 _z_precmd() {
219 _z --add "${PWD:A}"
220 }
221 fi
222 [[ -n "${precmd_functions[(r)_z_precmd]}" ]] || {
223 precmd_functions[$(($#precmd_functions+1))]=_z_precmd
224 }
225 }
226 _z_zsh_tab_completion() {
227 # tab completion
228 local compl
229 read -l compl
230 reply=(${(f)"$(_z --complete "$compl")"})
204 } 231 }
205 else 232 compctl -U -K _z_zsh_tab_completion _z
206 _z_precmd() { 233 elif type complete >/dev/null 2>&1; then
207 _z --add "${PWD:A}" 234 # bash
235 # tab completion
236 complete -o filenames -C '_z --complete "$COMP_LINE"' ${_Z_CMD:-z}
237 [ "$_Z_NO_PROMPT_COMMAND" ] || {
238 # populate directory list. avoid clobbering other PROMPT_COMMANDs.
239 grep "_z --add" <<< "$PROMPT_COMMAND" >/dev/null || {
plugins/zsh-navigation-tools/.config/znt/README.txt
File was created 1 These are skeletons, configuration is read from ~/.config/znt/*
2
plugins/zsh-navigation-tools/.config/znt/n-aliases.conf
File was created 1 # How should be current element of the list drawn. Possible values: reverse,
2 # underline. Default (without option set) is reverse
3 # On Linux virtual terminal this will be enforced to reverse (because of poor
4 # underline support on that terminal)
5 # local active_text=underline
6
plugins/zsh-navigation-tools/.config/znt/n-cd.conf
File was created 1 # Hotlist
2 local hotlist
3 hotlist=(
4 ~/.config/znt
5 /usr/share/zsh/site-functions
6 /usr/share/zsh
7 /usr/local/share/zsh/site-functions
8 /usr/local/share/zsh
9 /usr/local/bin
10 /usr/lib
11 )
12
13 # Suppress adding (to directory stack) directories visited by n-cd
14 # Value 0 is the default (directories will be added to dirstack)
15 local NCD_DONT_PUSHD=0
16
17 # How should be current element of the list drawn. Possible values: reverse,
18 # underline. Default (without option set) is reverse
19 # On Linux virtual terminal this will be enforced to reverse (because of poor
20 # underline support on that terminal)
21 # local active_text=underline
22
23 # Colorize last segments of the paths
24 # (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
25 local NLIST_COLORING_PATTERN="[a-zA-Z0-9 ._-]##/#(#e)"
26 local NLIST_COLORING_COLOR=$'\x1b[00;33m'
27
plugins/zsh-navigation-tools/.config/znt/n-env.conf
File was created 1 # How should be current element of the list drawn. Possible values: reverse,
2 # underline. Default (without option set) is reverse
3 # On Linux virtual terminal this will be enforced to reverse (because of poor
4 # underline support on that terminal)
5 # local active_text=underline
6
7 # (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
8 local NLIST_COLORING_PATTERN="[a-zA-Z0-9_]##"
9 local NLIST_COLORING_MATCH_MULTIPLE=0
10
plugins/zsh-navigation-tools/.config/znt/n-functions.conf
File was created 1 # Which editor to use, zed or vared
2 # vared is the default
3 local feditor="zed"
4 # local feditor="vared"
5
6 # How should be current element of the list drawn. Possible values: reverse,
7 # underline. Default (without option set) is reverse
8 # On Linux virtual terminal this will be enforced to reverse (because of poor
9 # underline support on that terminal)
10 # local active_text=underline
11
plugins/zsh-navigation-tools/.config/znt/n-history.conf
File was created 1 # How should be current element of the list drawn. Possible values: reverse,
2 # underline. Default (without option set) is reverse
3 # On Linux virtual terminal this will be enforced to reverse (because of poor
4 # underline support on that terminal)
5 local active_text=underline
6
7 # Highlight a few keywords
8 local NLIST_COLORING_PATTERN="(while|for |sudo|make|(#s)git|vim(#e)|vim |emacs(#e)|emacs )"
9 local NLIST_COLORING_COLOR=$'\x1b[00;33m'
10 local NLIST_COLORING_MATCH_MULTIPLE=1
11
plugins/zsh-navigation-tools/.config/znt/n-kill.conf
File was created 1 # How should be current element of the list drawn. Possible values: reverse,
2 # underline. Default (without option set) is reverse
3 # On Linux virtual terminal this will be enforced to reverse (because of poor
4 # underline support on that terminal)
5 # local active_text=underline
6
7 # Colorize first number column and last path segment
8 # This doesn't cover scripts named "[0-9]## *", which should be very rare
9 # (#s) is ^, (#e) is $, # is *, ## is + (comparing to regex)
10 # | is alternative, but only in ()
11 local NLIST_COLORING_PATTERN="((#s) #[0-9]## |[[][^]]#](#e)|[^ 0-9/?\\\\][^/\\\\]#(#e)|[^ /\\\\]##[^0-9/\\\\ ]##[^/\\\\]#(#e))"
12 local NLIST_COLORING_COLOR=$'\x1b[00;33m'
13 local NLIST_COLORING_MATCH_MULTIPLE=1
14
plugins/zsh-navigation-tools/.config/znt/n-list.conf
File was created 1 # Should the list (text, borders) be drawn in bold
2 # Value 1 is the default
3 local bold=1
4
plugins/zsh-navigation-tools/.config/znt/n-options.conf
File was created 1 # How should be current element of the list drawn. Possible values: reverse,
2 # underline. Default (without option set) is reverse
3 # On Linux virtual terminal this will be enforced to reverse (because of poor
4 # underline support on that terminal)
5 # local active_text=underline
6
plugins/zsh-navigation-tools/.config/znt/n-panelize.conf
File was created 1 # How should be current element of the list drawn. Possible values: reverse,
2 # underline. Default (without option set) is reverse
3 # On Linux virtual terminal this will be enforced to reverse (because of poor
4 # underline support on that terminal)
5 # local active_text=underline
6
plugins/zsh-navigation-tools/LICENSE
File was created 1 This software is dual-licensed under MIT and GPLv3.
2
3 MIT License
4 -----------
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23
24 GPLv3 License
25 --------------
26
27 GNU GENERAL PUBLIC LICENSE
28 Version 3, 29 June 2007
29
30 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
31 Everyone is permitted to copy and distribute verbatim copies
32 of this license document, but changing it is not allowed.
33
34 Preamble
35
36 The GNU General Public License is a free, copyleft license for
37 software and other kinds of works.
38
39 The licenses for most software and other practical works are designed
40 to take away your freedom to share and change the works. By contrast,
41 the GNU General Public License is intended to guarantee your freedom to
42 share and change all versions of a program--to make sure it remains free
43 software for all its users. We, the Free Software Foundation, use the
44 GNU General Public License for most of our software; it applies also to
45 any other work released this way by its authors. You can apply it to
46 your programs, too.
47
48 When we speak of free software, we are referring to freedom, not
49 price. Our General Public Licenses are designed to make sure that you
50 have the freedom to distribute copies of free software (and charge for
51 them if you wish), that you receive source code or can get it if you
52 want it, that you can change the software or use pieces of it in new
53 free programs, and that you know you can do these things.
54
55 To protect your rights, we need to prevent others from denying you
56 these rights or asking you to surrender the rights. Therefore, you have
57 certain responsibilities if you distribute copies of the software, or if
58 you modify it: responsibilities to respect the freedom of others.
59
60 For example, if you distribute copies of such a program, whether
61 gratis or for a fee, you must pass on to the recipients the same
62 freedoms that you received. You must make sure that they, too, receive
63 or can get the source code. And you must show them these terms so they
64 know their rights.
65
66 Developers that use the GNU GPL protect your rights with two steps:
67 (1) assert copyright on the software, and (2) offer you this License
68 giving you legal permission to copy, distribute and/or modify it.
69
70 For the developers' and authors' protection, the GPL clearly explains
71 that there is no warranty for this free software. For both users' and
72 authors' sake, the GPL requires that modified versions be marked as
73 changed, so that their problems will not be attributed erroneously to
74 authors of previous versions.
75
76 Some devices are designed to deny users access to install or run
77 modified versions of the software inside them, although the manufacturer
78 can do so. This is fundamentally incompatible with the aim of
79 protecting users' freedom to change the software. The systematic
80 pattern of such abuse occurs in the area of products for individuals to
81 use, which is precisely where it is most unacceptable. Therefore, we
82 have designed this version of the GPL to prohibit the practice for those
83 products. If such problems arise substantially in other domains, we
84 stand ready to extend this provision to those domains in future versions
85 of the GPL, as needed to protect the freedom of users.
86
87 Finally, every program is threatened constantly by software patents.
88 States should not allow patents to restrict development and use of
89 software on general-purpose computers, but in those that do, we wish to
90 avoid the special danger that patents applied to a free program could
91 make it effectively proprietary. To prevent this, the GPL assures that
92 patents cannot be used to render the program non-free.
93
94 The precise terms and conditions for copying, distribution and
95 modification follow.
96
97 TERMS AND CONDITIONS
98
99 0. Definitions.
100
101 "This License" refers to version 3 of the GNU General Public License.
102
103 "Copyright" also means copyright-like laws that apply to other kinds of
104 works, such as semiconductor masks.
105
106 "The Program" refers to any copyrightable work licensed under this
107 License. Each licensee is addressed as "you". "Licensees" and
108 "recipients" may be individuals or organizations.
109
110 To "modify" a work means to copy from or adapt all or part of the work
111 in a fashion requiring copyright permission, other than the making of an
112 exact copy. The resulting work is called a "modified version" of the
113 earlier work or a work "based on" the earlier work.
114
115 A "covered work" means either the unmodified Program or a work based
116 on the Program.
117
118 To "propagate" a work means to do anything with it that, without
119 permission, would make you directly or secondarily liable for
120 infringement under applicable copyright law, except executing it on a
121 computer or modifying a private copy. Propagation includes copying,
122 distribution (with or without modification), making available to the
123 public, and in some countries other activities as well.
124
125 To "convey" a work means any kind of propagation that enables other
126 parties to make or receive copies. Mere interaction with a user through
127 a computer network, with no transfer of a copy, is not conveying.
128
129 An interactive user interface displays "Appropriate Legal Notices"
130 to the extent that it includes a convenient and prominently visible
131 feature that (1) displays an appropriate copyright notice, and (2)
132 tells the user that there is no warranty for the work (except to the
133 extent that warranties are provided), that licensees may convey the
134 work under this License, and how to view a copy of this License. If
135 the interface presents a list of user commands or options, such as a
136 menu, a prominent item in the list meets this criterion.
137
138 1. Source Code.
139
140 The "source code" for a work means the preferred form of the work
141 for making modifications to it. "Object code" means any non-source
142 form of a work.
143
144 A "Standard Interface" means an interface that either is an official
145 standard defined by a recognized standards body, or, in the case of
146 interfaces specified for a particular programming language, one that
147 is widely used among developers working in that language.
148
149 The "System Libraries" of an executable work include anything, other
150 than the work as a whole, that (a) is included in the normal form of
151 packaging a Major Component, but which is not part of that Major
152 Component, and (b) serves only to enable use of the work with that
153 Major Component, or to implement a Standard Interface for which an
154 implementation is available to the public in source code form. A
155 "Major Component", in this context, means a major essential component
156 (kernel, window system, and so on) of the specific operating system
157 (if any) on which the executable work runs, or a compiler used to
158 produce the work, or an object code interpreter used to run it.
159
160 The "Corresponding Source" for a work in object code form means all
161 the source code needed to generate, install, and (for an executable
162 work) run the object code and to modify the work, including scripts to
163 control those activities. However, it does not include the work's
164 System Libraries, or general-purpose tools or generally available free
165 programs which are used unmodified in performing those activities but
166 which are not part of the work. For example, Corresponding Source
167 includes interface definition files associated with source files for
168 the work, and the source code for shared libraries and dynamically
169 linked subprograms that the work is specifically designed to require,
170 such as by intimate data communication or control flow between those
171 subprograms and other parts of the work.
172
173 The Corresponding Source need not include anything that users
174 can regenerate automatically from other parts of the Corresponding
175 Source.
176
177 The Corresponding Source for a work in source code form is that
178 same work.
179
180 2. Basic Permissions.
181
182 All rights granted under this License are granted for the term of
183 copyright on the Program, and are irrevocable provided the stated
184 conditions are met. This License explicitly affirms your unlimited
185 permission to run the unmodified Program. The output from running a
186 covered work is covered by this License only if the output, given its
187 content, constitutes a covered work. This License acknowledges your
188 rights of fair use or other equivalent, as provided by copyright law.
189
190 You may make, run and propagate covered works that you do not
191 convey, without conditions so long as your license otherwise remains
192 in force. You may convey covered works to others for the sole purpose
193 of having them make modifications exclusively for you, or provide you
194 with facilities for running those works, provided that you comply with
195 the terms of this License in conveying all material for which you do
196 not control copyright. Those thus making or running the covered works
197 for you must do so exclusively on your behalf, under your direction
198 and control, on terms that prohibit them from making any copies of
199 your copyrighted material outside their relationship with you.
200
201 Conveying under any other circumstances is permitted solely under
202 the conditions stated below. Sublicensing is not allowed; section 10
203 makes it unnecessary.
204
205 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
206
207 No covered work shall be deemed part of an effective technological
208 measure under any applicable law fulfilling obligations under article
209 11 of the WIPO copyright treaty adopted on 20 December 1996, or
210 similar laws prohibiting or restricting circumvention of such
211 measures.
212
213 When you convey a covered work, you waive any legal power to forbid
214 circumvention of technological measures to the extent such circumvention
215 is effected by exercising rights under this License with respect to
216 the covered work, and you disclaim any intention to limit operation or
217 modification of the work as a means of enforcing, against the work's
218 users, your or third parties' legal rights to forbid circumvention of
219 technological measures.
220
221 4. Conveying Verbatim Copies.
222
223 You may convey verbatim copies of the Program's source code as you
224 receive it, in any medium, provided that you conspicuously and
225 appropriately publish on each copy an appropriate copyright notice;
226 keep intact all notices stating that this License and any
227 non-permissive terms added in accord with section 7 apply to the code;
228 keep intact all notices of the absence of any warranty; and give all
229 recipients a copy of this License along with the Program.
230
231 You may charge any price or no price for each copy that you convey,
232 and you may offer support or warranty protection for a fee.
233
234 5. Conveying Modified Source Versions.
235
236 You may convey a work based on the Program, or the modifications to
237 produce it from the Program, in the form of source code under the
238 terms of section 4, provided that you also meet all of these conditions:
239
240 a) The work must carry prominent notices stating that you modified
241 it, and giving a relevant date.
242
243 b) The work must carry prominent notices stating that it is
244 released under this License and any conditions added under section
245 7. This requirement modifies the requirement in section 4 to
246 "keep intact all notices".
247
248 c) You must license the entire work, as a whole, under this
249 License to anyone who comes into possession of a copy. This
250 License will therefore apply, along with any applicable section 7
251 additional terms, to the whole of the work, and all its parts,
252 regardless of how they are packaged. This License gives no
253 permission to license the work in any other way, but it does not
254 invalidate such permission if you have separately received it.
255
256 d) If the work has interactive user interfaces, each must display
257 Appropriate Legal Notices; however, if the Program has interactive
258 interfaces that do not display Appropriate Legal Notices, your
259 work need not make them do so.
260
261 A compilation of a covered work with other separate and independent
262 works, which are not by their nature extensions of the covered work,
263 and which are not combined with it such as to form a larger program,
264 in or on a volume of a storage or distribution medium, is called an
265 "aggregate" if the compilation and its resulting copyright are not
266 used to limit the access or legal rights of the compilation's users
267 beyond what the individual works permit. Inclusion of a covered work
268 in an aggregate does not cause this License to apply to the other
269 parts of the aggregate.
270
271 6. Conveying Non-Source Forms.
272
273 You may convey a covered work in object code form under the terms
274 of sections 4 and 5, provided that you also convey the
275 machine-readable Corresponding Source under the terms of this License,
276 in one of these ways:
277
278 a) Convey the object code in, or embodied in, a physical product
279 (including a physical distribution medium), accompanied by the
280 Corresponding Source fixed on a durable physical medium
281 customarily used for software interchange.
282
283 b) Convey the object code in, or embodied in, a physical product
284 (including a physical distribution medium), accompanied by a
285 written offer, valid for at least three years and valid for as
286 long as you offer spare parts or customer support for that product
287 model, to give anyone who possesses the object code either (1) a
288 copy of the Corresponding Source for all the software in the
289 product that is covered by this License, on a durable physical
290 medium customarily used for software interchange, for a price no
291 more than your reasonable cost of physically performing this
292 conveying of source, or (2) access to copy the
293 Corresponding Source from a network server at no charge.
294
295 c) Convey individual copies of the object code with a copy of the
296 written offer to provide the Corresponding Source. This
297 alternative is allowed only occasionally and noncommercially, and
298 only if you received the object code with such an offer, in accord
299 with subsection 6b.
300
301 d) Convey the object code by offering access from a designated
302 place (gratis or for a charge), and offer equivalent access to the
303 Corresponding Source in the same way through the same place at no
304 further charge. You need not require recipients to copy the
305 Corresponding Source along with the object code. If the place to
306 copy the object code is a network server, the Corresponding Source
307 may be on a different server (operated by you or a third party)
308 that supports equivalent copying facilities, provided you maintain
309 clear directions next to the object code saying where to find the
310 Corresponding Source. Regardless of what server hosts the
311 Corresponding Source, you remain obligated to ensure that it is
312 available for as long as needed to satisfy these requirements.
313
314 e) Convey the object code using peer-to-peer transmission, provided
315 you inform other peers where the object code and Corresponding
316 Source of the work are being offered to the general public at no
317 charge under subsection 6d.
318
319 A separable portion of the object code, whose source code is excluded
320 from the Corresponding Source as a System Library, need not be
321 included in conveying the object code work.
322
323 A "User Product" is either (1) a "consumer product", which means any
324 tangible personal property which is normally used for personal, family,
325 or household purposes, or (2) anything designed or sold for incorporation
326 into a dwelling. In determining whether a product is a consumer product,
327 doubtful cases shall be resolved in favor of coverage. For a particular
328 product received by a particular user, "normally used" refers to a
329 typical or common use of that class of product, regardless of the status
330 of the particular user or of the way in which the particular user
331 actually uses, or expects or is expected to use, the product. A product
332 is a consumer product regardless of whether the product has substantial
333 commercial, industrial or non-consumer uses, unless such uses represent
334 the only significant mode of use of the product.
335
336 "Installation Information" for a User Product means any methods,
337 procedures, authorization keys, or other information required to install
338 and execute modified versions of a covered work in that User Product from
339 a modified version of its Corresponding Source. The information must
340 suffice to ensure that the continued functioning of the modified object
341 code is in no case prevented or interfered with solely because
342 modification has been made.
343
344 If you convey an object code work under this section in, or with, or
345 specifically for use in, a User Product, and the conveying occurs as
346 part of a transaction in which the right of possession and use of the
347 User Product is transferred to the recipient in perpetuity or for a
348 fixed term (regardless of how the transaction is characterized), the
349 Corresponding Source conveyed under this section must be accompanied
350 by the Installation Information. But this requirement does not apply
351 if neither you nor any third party retains the ability to install
352 modified object code on the User Product (for example, the work has
353 been installed in ROM).
354
355 The requirement to provide Installation Information does not include a
356 requirement to continue to provide support service, warranty, or updates
357 for a work that has been modified or installed by the recipient, or for
358 the User Product in which it has been modified or installed. Access to a
359 network may be denied when the modification itself materially and
360 adversely affects the operation of the network or violates the rules and
361 protocols for communication across the network.
362
363 Corresponding Source conveyed, and Installation Information provided,
364 in accord with this section must be in a format that is publicly
365 documented (and with an implementation available to the public in
366 source code form), and must require no special password or key for
367 unpacking, reading or copying.
368
369 7. Additional Terms.
370
371 "Additional permissions" are terms that supplement the terms of this
372 License by making exceptions from one or more of its conditions.
373 Additional permissions that are applicable to the entire Program shall
374 be treated as though they were included in this License, to the extent
375 that they are valid under applicable law. If additional permissions
376 apply only to part of the Program, that part may be used separately
377 under those permissions, but the entire Program remains governed by
378 this License without regard to the additional permissions.
379
380 When you convey a copy of a covered work, you may at your option
381 remove any additional permissions from that copy, or from any part of
382 it. (Additional permissions may be written to require their own
383 removal in certain cases when you modify the work.) You may place
384 additional permissions on material, added by you to a covered work,
385 for which you have or can give appropriate copyright permission.
386
387 Notwithstanding any other provision of this License, for material you
388 add to a covered work, you may (if authorized by the copyright holders of
389 that material) supplement the terms of this License with terms:
390
391 a) Disclaiming warranty or limiting liability differently from the
392 terms of sections 15 and 16 of this License; or
393
394 b) Requiring preservation of specified reasonable legal notices or
395 author attributions in that material or in the Appropriate Legal
396 Notices displayed by works containing it; or
397
398 c) Prohibiting misrepresentation of the origin of that material, or
399 requiring that modified versions of such material be marked in
400 reasonable ways as different from the original version; or
401
402 d) Limiting the use for publicity purposes of names of licensors or
403 authors of the material; or
404
405 e) Declining to grant rights under trademark law for use of some
406 trade names, trademarks, or service marks; or
407
408 f) Requiring indemnification of licensors and authors of that
409 material by anyone who conveys the material (or modified versions of
410 it) with contractual assumptions of liability to the recipient, for
411 any liability that these contractual assumptions directly impose on
412 those licensors and authors.
413
414 All other non-permissive additional terms are considered "further
415 restrictions" within the meaning of section 10. If the Program as you
416 received it, or any part of it, contains a notice stating that it is
417 governed by this License along with a term that is a further
418 restriction, you may remove that term. If a license document contains
419 a further restriction but permits relicensing or conveying under this
420 License, you may add to a covered work material governed by the terms
421 of that license document, provided that the further restriction does
422 not survive such relicensing or conveying.
423
424 If you add terms to a covered work in accord with this section, you
425 must place, in the relevant source files, a statement of the
426 additional terms that apply to those files, or a notice indicating
427 where to find the applicable terms.
428
429 Additional terms, permissive or non-permissive, may be stated in the
430 form of a separately written license, or stated as exceptions;
431 the above requirements apply either way.
432
433 8. Termination.
434
435 You may not propagate or modify a covered work except as expressly
436 provided under this License. Any attempt otherwise to propagate or
437 modify it is void, and will automatically terminate your rights under
438 this License (including any patent licenses granted under the third
439 paragraph of section 11).
440
441 However, if you cease all violation of this License, then your
442 license from a particular copyright holder is reinstated (a)
443 provisionally, unless and until the copyright holder explicitly and
444 finally terminates your license, and (b) permanently, if the copyright
445 holder fails to notify you of the violation by some reasonable means
446 prior to 60 days after the cessation.
447
448 Moreover, your license from a particular copyright holder is
449 reinstated permanently if the copyright holder notifies you of the
450 violation by some reasonable means, this is the first time you have
451 received notice of violation of this License (for any work) from that
452 copyright holder, and you cure the violation prior to 30 days after
453 your receipt of the notice.
454
455 Termination of your rights under this section does not terminate the
456 licenses of parties who have received copies or rights from you under
457 this License. If your rights have been terminated and not permanently
458 reinstated, you do not qualify to receive new licenses for the same
459 material under section 10.
460
461 9. Acceptance Not Required for Having Copies.
462
463 You are not required to accept this License in order to receive or
464 run a copy of the Program. Ancillary propagation of a covered work
465 occurring solely as a consequence of using peer-to-peer transmission
466 to receive a copy likewise does not require acceptance. However,
467 nothing other than this License grants you permission to propagate or
468 modify any covered work. These actions infringe copyright if you do
469 not accept this License. Therefore, by modifying or propagating a
470 covered work, you indicate your acceptance of this License to do so.
471
472 10. Automatic Licensing of Downstream Recipients.
473
474 Each time you convey a covered work, the recipient automatically
475 receives a license from the original licensors, to run, modify and
476 propagate that work, subject to this License. You are not responsible
477 for enforcing compliance by third parties with this License.
478
479 An "entity transaction" is a transaction transferring control of an
480 organization, or substantially all assets of one, or subdividing an
481 organization, or merging organizations. If propagation of a covered
482 work results from an entity transaction, each party to that
483 transaction who receives a copy of the work also receives whatever
484 licenses to the work the party's predecessor in interest had or could
485 give under the previous paragraph, plus a right to possession of the
486 Corresponding Source of the work from the predecessor in interest, if
487 the predecessor has it or can get it with reasonable efforts.
488
489 You may not impose any further restrictions on the exercise of the
490 rights granted or affirmed under this License. For example, you may
491 not impose a license fee, royalty, or other charge for exercise of
492 rights granted under this License, and you may not initiate litigation
493 (including a cross-claim or counterclaim in a lawsuit) alleging that
494 any patent claim is infringed by making, using, selling, offering for
495 sale, or importing the Program or any portion of it.
496
497 11. Patents.
498
499 A "contributor" is a copyright holder who authorizes use under this
500 License of the Program or a work on which the Program is based. The
501 work thus licensed is called the contributor's "contributor version".
502
503 A contributor's "essential patent claims" are all patent claims
504 owned or controlled by the contributor, whether already acquired or
505 hereafter acquired, that would be infringed by some manner, permitted
506 by this License, of making, using, or selling its contributor version,
507 but do not include claims that would be infringed only as a
508 consequence of further modification of the contributor version. For
509 purposes of this definition, "control" includes the right to grant
510 patent sublicenses in a manner consistent with the requirements of
511 this License.
512
513 Each contributor grants you a non-exclusive, worldwide, royalty-free
514 patent license under the contributor's essential patent claims, to
515 make, use, sell, offer for sale, import and otherwise run, modify and
516 propagate the contents of its contributor version.
517
518 In the following three paragraphs, a "patent license" is any express
519 agreement or commitment, however denominated, not to enforce a patent
520 (such as an express permission to practice a patent or covenant not to
521 sue for patent infringement). To "grant" such a patent license to a
522 party means to make such an agreement or commitment not to enforce a
523 patent against the party.
524
525 If you convey a covered work, knowingly relying on a patent license,
526 and the Corresponding Source of the work is not available for anyone
527 to copy, free of charge and under the terms of this License, through a
528 publicly available network server or other readily accessible means,
529 then you must either (1) cause the Corresponding Source to be so
530 available, or (2) arrange to deprive yourself of the benefit of the
531 patent license for this particular work, or (3) arrange, in a manner
532 consistent with the requirements of this License, to extend the patent
533 license to downstream recipients. "Knowingly relying" means you have
534 actual knowledge that, but for the patent license, your conveying the
535 covered work in a country, or your recipient's use of the covered work
536 in a country, would infringe one or more identifiable patents in that
537 country that you have reason to believe are valid.
538
539 If, pursuant to or in connection with a single transaction or
540 arrangement, you convey, or propagate by procuring conveyance of, a
541 covered work, and grant a patent license to some of the parties
542 receiving the covered work authorizing them to use, propagate, modify
543 or convey a specific copy of the covered work, then the patent license
544 you grant is automatically extended to all recipients of the covered
545 work and works based on it.
546
547 A patent license is "discriminatory" if it does not include within
548 the scope of its coverage, prohibits the exercise of, or is
549 conditioned on the non-exercise of one or more of the rights that are
550 specifically granted under this License. You may not convey a covered
551 work if you are a party to an arrangement with a third party that is
552 in the business of distributing software, under which you make payment
553 to the third party based on the extent of your activity of conveying
554 the work, and under which the third party grants, to any of the
555 parties who would receive the covered work from you, a discriminatory
556 patent license (a) in connection with copies of the covered work
557 conveyed by you (or copies made from those copies), or (b) primarily
558 for and in connection with specific products or compilations that
559 contain the covered work, unless you entered into that arrangement,
560 or that patent license was granted, prior to 28 March 2007.
561
562 Nothing in this License shall be construed as excluding or limiting
563 any implied license or other defenses to infringement that may
564 otherwise be available to you under applicable patent law.
565
566 12. No Surrender of Others' Freedom.
567
568 If conditions are imposed on you (whether by court order, agreement or
569 otherwise) that contradict the conditions of this License, they do not
570 excuse you from the conditions of this License. If you cannot convey a
571 covered work so as to satisfy simultaneously your obligations under this
572 License and any other pertinent obligations, then as a consequence you may
573 not convey it at all. For example, if you agree to terms that obligate you
574 to collect a royalty for further conveying from those to whom you convey
575 the Program, the only way you could satisfy both those terms and this
576 License would be to refrain entirely from conveying the Program.
577
578 13. Use with the GNU Affero General Public License.
579
580 Notwithstanding any other provision of this License, you have
581 permission to link or combine any covered work with a work licensed
582 under version 3 of the GNU Affero General Public License into a single
583 combined work, and to convey the resulting work. The terms of this
584 License will continue to apply to the part which is the covered work,
585 but the special requirements of the GNU Affero General Public License,
586 section 13, concerning interaction through a network will apply to the
587 combination as such.
588
589 14. Revised Versions of this License.
590
591 The Free Software Foundation may publish revised and/or new versions of
592 the GNU General Public License from time to time. Such new versions will
593 be similar in spirit to the present version, but may differ in detail to
594 address new problems or concerns.
595
596 Each version is given a distinguishing version number. If the
597 Program specifies that a certain numbered version of the GNU General
598 Public License "or any later version" applies to it, you have the
599 option of following the terms and conditions either of that numbered
600 version or of any later version published by the Free Software
601 Foundation. If the Program does not specify a version number of the
602 GNU General Public License, you may choose any version ever published
603 by the Free Software Foundation.
604
605 If the Program specifies that a proxy can decide which future
606 versions of the GNU General Public License can be used, that proxy's
607 public statement of acceptance of a version permanently authorizes you
608 to choose that version for the Program.
609
610 Later license versions may give you additional or different
611 permissions. However, no additional obligations are imposed on any
612 author or copyright holder as a result of your choosing to follow a
613 later version.
614
615 15. Disclaimer of Warranty.
616
617 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
618 APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
619 HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
620 OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
621 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
622 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
623 IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
624 ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
625
626 16. Limitation of Liability.
627
628 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
629 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
630 THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
631 GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
632 USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
633 DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
634 PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
635 EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
636 SUCH DAMAGES.
637
638 17. Interpretation of Sections 15 and 16.
639
640 If the disclaimer of warranty and limitation of liability provided
641 above cannot be given local legal effect according to their terms,
642 reviewing courts shall apply local law that most closely approximates
643 an absolute waiver of all civil liability in connection with the
644 Program, unless a warranty or assumption of liability accompanies a
645 copy of the Program in return for a fee.
646
647 END OF TERMS AND CONDITIONS
648
649 How to Apply These Terms to Your New Programs
650
651 If you develop a new program, and you want it to be of the greatest
652 possible use to the public, the best way to achieve this is to make it
653 free software which everyone can redistribute and change under these terms.
654
655 To do so, attach the following notices to the program. It is safest
656 to attach them to the start of each source file to most effectively
657 state the exclusion of warranty; and each file should have at least
658 the "copyright" line and a pointer to where the full notice is found.
659
660 <one line to give the program's name and a brief idea of what it does.>
661 Copyright (C) <year> <name of author>
662
663 This program is free software: you can redistribute it and/or modify
664 it under the terms of the GNU General Public License as published by
665 the Free Software Foundation, either version 3 of the License, or
666 (at your option) any later version.
667
668 This program is distributed in the hope that it will be useful,
669 but WITHOUT ANY WARRANTY; without even the implied warranty of
670 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
671 GNU General Public License for more details.
672
673 You should have received a copy of the GNU General Public License
674 along with this program. If not, see <http://www.gnu.org/licenses/>.
675
676 Also add information on how to contact you by electronic and paper mail.
677
678 If the program does terminal interaction, make it output a short
679 notice like this when it starts in an interactive mode:
680
681 <program> Copyright (C) <year> <name of author>
682 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
683 This is free software, and you are welcome to redistribute it
684 under certain conditions; type `show c' for details.
685
686 The hypothetical commands `show w' and `show c' should show the appropriate
687 parts of the General Public License. Of course, your program's commands
688 might be different; for a GUI interface, you would use an "about box".
689
690 You should also get your employer (if you work as a programmer) or school,
691 if any, to sign a "copyright disclaimer" for the program, if necessary.
692 For more information on this, and how to apply and follow the GNU GPL, see
693 <http://www.gnu.org/licenses/>.
694
695 The GNU General Public License does not permit incorporating your program
696 into proprietary programs. If your program is a subroutine library, you
697 may consider it more useful to permit linking proprietary applications with
698 the library. If this is what you want to do, use the GNU Lesser General
699 Public License instead of this License. But first, please read
700 <http://www.gnu.org/philosophy/why-not-lgpl.html>.
701
plugins/zsh-navigation-tools/README.md
File was created 1 # Zsh Navigation Tools
2
3 http://imageshack.com/a/img633/7967/ps6rKR.png
4
5 Set of tools like n-history โ€“ย multi-word history searcher, n-cd โ€“ directory
6 bookmark manager, n-kill โ€“ย htop like kill utility, and more. Based on
7 n-list, a tool generating selectable curses-based list of elements that has
8 access to current Zsh session, i.e. has broad capabilities to work together
9 with it. Feature highlights include incremental multi-word searching, ANSI
10 coloring, unique mode, horizontal scroll, non-selectable elements, grepping and
11 various integrations with Zsh.
12
13 ## History Widget
14
15 To have n-history as multi-word incremental searcher bound to Ctrl-R copy znt-*
16 files into the */site-functions dir (unless you use Oh My Zsh) and
17 add:
18
19 autoload znt-history-widget
20 zle -N znt-history-widget
21 bindkey "^R" znt-history-widget
22
23 to .zshrc. This is done automatically when using Oh My Zsh. Two other
24 widgets exist, znt-cd-widget and znt-kill-widget, they can be too assigned
25 to key combinations (no need for autoload when using Oh My Zsh):
26
27 zle -N znt-cd-widget
28 bindkey "^T" znt-cd-widget
29 zle -N znt-kill-widget
30 bindkey "^Y" znt-kill-widget
31
32 Oh My Zsh stores history into ~/.zsh_history. When you switch to OMZ you could
33 want to copy your previous data (from e.g. ~/.zhistory) into the new location.
34
35 ## Introduction
36
37 The tools are:
38
39 - n-aliases - browses aliases, relegates editing to vared
40 - n-cd - browses dirstack and bookmarked directories, allows to enter selected directory
41 - n-functions - browses functions, relegates editing to zed or vared
42 - n-history - browses history, allows to edit and run commands from it
43 - n-kill - browses processes list, allows to send signal to selected process
44 - n-env - browses environment, relegates editing to vared
45 - n-options - browses options, allows to toggle their state
46 - n-panelize - loads output of given command into the list for browsing
47
48 All tools support horizontal scroll with <,>, {,}, h,l or left and right
49 cursors. Other keys are:
50
51 - [,] - jump directory bookmarks in n-cd and typical signals in n-kill
52 - Ctrl-d, Ctrl-u - half page up or down
53 - Ctrl-p, Ctrl-n - previous and next (also done with vim's j,k)
54 - Ctrl-l - redraw of whole display
55 - g, G - beginning and end of the list
56 - Ctrl-o, o - enter uniq mode (no duplicate lines)
57 - / - start incremental search
58 - Enter - finish incremental search, retaining filter
59 - Esc - exit incremental search, clearing filter
60 - Ctrl-w (in incremental search) - delete whole word
61 - Ctrl-k (in incremental search) - delete whole line
62
63 ## Programming
64
65 The function n-list is used as follows:
66
67 n-list {element1} [element2] ... [elementN]
68
69 This is all that is needed to be done to have the features like ANSI coloring,
70 incremental multi-word search, unique mode, horizontal scroll, non-selectable
71 elements (grepping is done outside n-list, see the tools for how it can be
72 done). To set up non-selectable entries add their indices into array
73 NLIST_NONSELECTABLE_ELEMENTS:
74
75 typeset -a NLIST_NONSELECTABLE_ELEMENTS
76 NLIST_NONSELECTABLE_ELEMENTS=( 1 )
77
78 Result is stored as $reply[REPLY] ($ isn't needed before REPLY because
79 of arithmetic context inside []). The returned array might be different from
80 input arguments as n-list can process them via incremental search or uniq
81 mode. $REPLY is the index in that possibly processed array. If $REPLY
82 equals -1 it means that no selection have been made (user quitted via q
83 key).
84
85 To set up entries that can be jumped to with [,] keys add their indices to
86 NLIST_HOP_INDEXES array:
87
88 typeset -a NLIST_HOP_INDEXES
89 NLIST_HOP_INDEXES=( 1 10 )
90
91 n-list can automatically colorize entries according to a Zsh pattern.
92 Following example will colorize all numbers with blue:
93
94 local NLIST_COLORING_PATTERN="[0-9]##"
95 local NLIST_COLORING_COLOR=$'\x1b[00;34m'
96 local NLIST_COLORING_END_COLOR=$'\x1b[0m'
97 local NLIST_COLORING_MATCH_MULTIPLE=1
98 n-list "This is a number 123" "This line too has a number: 456"
99
100 Blue is the default color, it doesn't have to be set. See zshexpn man page
101 for more information on Zsh patterns. Briefly, comparing to regular
102 expressions, (#s) is ^, (#e) is $, # is *, ## is +. Alternative
103 will work when in parenthesis, i.e. (a|b). BTW by using this method you can
104 colorize output of the tools, via their config files (check out e.g. n-cd.conf,
105 it uses this).
106
107 ## Performance
108 ZNT is fastest with Zsh before 5.0.8 and starting from 5.2 (the version yet to
109 be released).
110
111 # vim:filetype=conf
112
plugins/zsh-navigation-tools/n-aliases
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-aliases` to .zshrc
3 #
4 # This function allows to choose an alias for edition with vared
5 #
6 # Uses n-list
7
8 emulate -L zsh
9
10 setopt extendedglob
11 zmodload zsh/curses
12 zmodload zsh/parameter
13
14 local IFS="
15 "
16
17 unset NLIST_COLORING_PATTERN
18
19 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
20 [ -f ~/.config/znt/n-aliases.conf ] && . ~/.config/znt/n-aliases.conf
21
22 local list
23 local selected
24
25 NLIST_REMEMBER_STATE=0
26
27 list=( "${(@k)aliases}" )
28 list=( "${(@M)list:#(#i)*$1*}" )
29
30 local NLIST_GREP_STRING="$1"
31
32 if [ "$#list" -eq 0 ]; then
33 echo "No matching aliases"
34 return 1
35 fi
36
37 list=( "${(@i)list}" )
38 n-list "$list[@]"
39
40 if [ "$REPLY" -gt 0 ]; then
41 selected="$reply[REPLY]"
42 echo "Editing \`$selected':"
43 print -rs "vared aliases\\[$selected\\]"
44 vared aliases\[$selected\]
45 fi
46
47 # vim: set filetype=zsh:
48
plugins/zsh-navigation-tools/n-cd
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-cd` to .zshrc
3 #
4 # This function allows to choose a directory from pushd stack
5 #
6 # Uses n-list
7
8 emulate -L zsh
9
10 setopt extendedglob pushdignoredups
11
12 zmodload zsh/curses
13 local IFS="
14 "
15
16 # Unset before configuration is read
17 unset NLIST_COLORING_PATTERN
18
19 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
20 [ -f ~/.config/znt/n-cd.conf ] && . ~/.config/znt/n-cd.conf
21
22 local list
23 local selected
24
25 NLIST_REMEMBER_STATE=0
26
27 list=( `dirs -p` )
28 list=( "${(@M)list:#(#i)*$1*}" )
29
30 local NLIST_GREP_STRING="$1"
31
32 [ "$#list" -eq 0 ] && echo "No matching directories"
33
34 if [ "$#hotlist" -ge 1 ]; then
35 typeset -a NLIST_NONSELECTABLE_ELEMENTS NLIST_HOP_INDEXES
36 local tmp_list_size="$#list"
37 NLIST_NONSELECTABLE_ELEMENTS=( $(( tmp_list_size+1 )) $(( tmp_list_size+2 )) )
38 list=( "$list[@]" "" $'\x1b[00;31m'"Hotlist"$'\x1b[00;00m': "$hotlist[@]" )
39 (( tmp_list_size+=3 ))
40 local middle_hop=$(( (tmp_list_size+$#list) / 2 ))
41 [[ "$middle_hop" -eq $tmp_list_size || "$middle_hop" -eq $#list ]] && middle_hop=""
42 [ "$tmp_list_size" -eq $#list ] && tmp_list_size=""
43 NLIST_HOP_INDEXES=( 1 $tmp_list_size $middle_hop $#list )
44 else
45 [ "$#list" -eq 0 ] && return 1
46 fi
47
48 n-list "${list[@]}"
49
50 if [ "$REPLY" -gt 0 ]; then
51 selected="$reply[REPLY]"
52 selected="${selected/#\~/$HOME}"
53
54 (( NCD_DONT_PUSHD )) && setopt NO_AUTO_PUSHD
55 cd "$selected"
56 (( NCD_DONT_PUSHD )) && setopt AUTO_PUSHD
57
58 # ZLE?
59 if [ "${(t)CURSOR}" = "integer-local-special" ]; then
60 zle -M "You have selected $selected"
61 else
62 echo "You have selected $selected"
63 fi
64 else
65 [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
66 fi
67
68 # vim: set filetype=zsh:
69
plugins/zsh-navigation-tools/n-env
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-env` to .zshrc
3 #
4 # This function allows to choose an environment variable
5 # for edition with vared
6 #
7 # Uses n-list
8
9 emulate -L zsh
10
11 setopt extendedglob
12 unsetopt equals
13 zmodload zsh/curses
14
15 local IFS="
16 "
17
18 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
19 [ -f ~/.config/znt/n-env.conf ] && . ~/.config/znt/n-env.conf
20
21 local list
22 local selected
23
24 NLIST_REMEMBER_STATE=0
25
26 list=( `env` )
27 list=( "${(@M)list:#(#i)*$1*}" )
28
29 local NLIST_GREP_STRING="$1"
30
31 if [ "$#list" -eq 0 ]; then
32 echo "No matching variables"
33 return 1
34 fi
35
36 list=( "${(@i)list}" )
37 n-list "$list[@]"
38
39 if [ "$REPLY" -gt 0 ]; then
40 selected="$reply[REPLY]"
41 selected="${selected%%=*}"
42 echo "Editing \`$selected':"
43 print -rs "vared \"$selected\""
44 vared "$selected"
45 fi
46
47 # vim: set filetype=zsh:
48
plugins/zsh-navigation-tools/n-functions
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-functions` to .zshrc
3 #
4 # This function allows to choose a function for edition with vared
5 #
6 # Uses n-list
7
8 emulate -L zsh
9
10 setopt extendedglob
11 zmodload zsh/curses
12 zmodload zsh/parameter
13
14 local IFS="
15 "
16
17 unset NLIST_COLORING_PATTERN
18
19 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
20 [ -f ~/.config/znt/n-functions.conf ] && . ~/.config/znt/n-functions.conf
21
22 local list
23 local selected
24
25 NLIST_REMEMBER_STATE=0
26
27 list=( "${(@k)functions}" )
28 list=( "${(@M)list:#(#i)*$1*}" )
29
30 local NLIST_GREP_STRING="$1"
31
32 if [ "$#list" -eq 0 ]; then
33 echo "No matching functions"
34 return 1
35 fi
36
37 list=( "${(@i)list}" )
38 n-list "$list[@]"
39
40 if [ "$REPLY" -gt 0 ]; then
41 selected="$reply[REPLY]"
42 if [ "$feditor" = "zed" ]; then
43 echo "Editing \`$selected' (ESC ZZ or Ctrl-x-w to finish):"
44 autoload zed
45 print -rs "zed -f -- \"$selected\""
46 zed -f -- "$selected"
47 else
48 echo "Editing \`$selected':"
49 print -rs "vared functions\\[$selected\\]"
50 vared functions\[$selected\]
51 fi
52 fi
53
54 # vim: set filetype=zsh:
55
plugins/zsh-navigation-tools/n-history
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-history` to .zshrc
3 #
4 # This function allows to browse Z shell's history and use the
5 # entries
6 #
7 # Uses n-list
8
9 emulate -L zsh
10
11 setopt extendedglob
12 zmodload zsh/curses
13 zmodload zsh/parameter
14
15 local IFS="
16 "
17
18 unset NLIST_COLORING_PATTERN
19
20 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
21 [ -f ~/.config/znt/n-history.conf ] && . ~/.config/znt/n-history.conf
22
23 local list
24 local selected
25
26 NLIST_REMEMBER_STATE=0
27
28 list=( "$history[@]" )
29 list=( "${(@M)list:#(#i)*$1*}" )
30
31 if [ "$#list" -eq 0 ]; then
32 echo "No matching history entries"
33 return 1
34 fi
35
36 local NLIST_GREP_STRING="$1"
37 local NLIST_REPLACE_NEWLINES="1"
38 n-list "${list[@]}"
39
40 if [ "$REPLY" -gt 0 ]; then
41 selected="$reply[REPLY]"
42 # ZLE?
43 if [ "${(t)CURSOR}" = "integer-local-special" ]; then
44 zle redisplay
45 zle kill-whole-line
46 zle -U "$selected"
47 else
48 print -zr "$selected"
49 fi
50 else
51 [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
52 fi
53
54 # vim: set filetype=zsh:
55
plugins/zsh-navigation-tools/n-kill
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-kill` to .zshrc
3 #
4 # This function allows to choose a process and a signal to send to it
5 #
6 # Uses n-list
7
8 emulate -L zsh
9
10 setopt extendedglob
11 zmodload zsh/curses
12
13 local IFS="
14 "
15
16 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
17 [ -f ~/.config/znt/n-kill.conf ] && . ~/.config/znt/n-kill.conf
18
19 typeset -A signals
20 signals=(
21 1 "1 - HUP"
22 2 "2 - INT"
23 3 "3 - QUIT"
24 6 "6 - ABRT"
25 9 "9 - KILL"
26 14 "14 - ALRM"
27 15 "15 - TERM"
28 17 "17 - STOP"
29 19 "19 - CONT"
30 )
31
32 local list
33 local selected
34 local signal
35 local -a signal_names
36 local title
37
38 NLIST_REMEMBER_STATE=0
39
40 typeset -a NLIST_NONSELECTABLE_ELEMENTS
41 NLIST_NONSELECTABLE_ELEMENTS=( 1 )
42
43 type ps 2>/dev/null 1>&2 || { echo >&2 "Error: \`ps' not found"; return 1 }
44
45 case "$(uname)" in
46 CYGWIN*) list=( `command ps -Wa` ) ;;
47 *) list=( `command ps -o pid,uid,command -A` ) ;;
48 esac
49
50 # Ask of PID
51 title=$'\x1b[00;31m'"${list[1]}"$'\x1b[00;00m\0'
52 shift list
53 list=( "$title" "${(@M)list:#(#i)*$1*}" )
54
55 local NLIST_GREP_STRING="$1"
56
57 if [ "$#list" -eq 1 ]; then
58 echo "No matching processes"
59 return 1
60 fi
61
62 n-list "$list[@]"
63
64 # Got answer? (could be Ctrl-C or 'q')
65 if [ "$REPLY" -gt 0 ]; then
66 selected="$reply[REPLY]"
67 selected="${selected## #}"
68 pid="${selected%% *}"
69
70 # Now ask of signal
71 signal_names=( ${(vin)signals} )
72 typeset -a NLIST_HOP_INDEXES
73 NLIST_HOP_INDEXES=( 3 6 8 )
74 unset NLIST_COLORING_PATTERN
75 n-list $'\x1b[00;31mSelect signal:\x1b[00;00m' "$signal_names[@]"
76
77 if [ "$REPLY" -gt 0 ]; then
78 selected="$reply[REPLY]"
79 signal="${(k)signals[(r)$selected]}"
80
81 # ZLE?
82 if [ "${(t)CURSOR}" = "integer-local-special" ]; then
83 zle redisplay
84 zle kill-whole-line
85 zle -U "kill -$signal $pid"
86 else
87 print -zr "kill -$signal $pid"
88 fi
89 else
90 [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
91 fi
92 else
93 [ "${(t)CURSOR}" = "integer-local-special" ] && zle redisplay
94 fi
95
96 # vim: set filetype=zsh:
97
plugins/zsh-navigation-tools/n-list
File was created 1 # $1, $2, ... - elements of the list
2 # $NLIST_NONSELECTABLE_ELEMENTS - array of indexes (1-based) that cannot be selected
3 # $REPLY is the output variable - contains index (1-based) or -1 when no selection
4 #
5 # Copy this file into /usr/share/zsh/site-functions/
6 # and add 'autoload n-list` to .zshrc
7 #
8 # This function outputs a list of elements that can be
9 # navigated with keyboard. Uses curses library
10
11 emulate -LR zsh
12
13 setopt typesetsilent extendedglob noshortloops
14
15 _nlist_has_terminfo=0
16
17 zmodload zsh/curses
18 zmodload zsh/terminfo 2>/dev/null && _nlist_has_terminfo=1
19
20 trap "REPLY=-2; reply=(); return" TERM INT QUIT
21 trap "_nlist_exit" EXIT
22
23 # Drawing and input
24 autoload n-list-draw n-list-input
25
26 # Cleanup before any exit
27 _nlist_exit() {
28 setopt localoptions
29 setopt extendedglob
30
31 [[ "$REPLY" = -(#c0,1)[0-9]## ]] || REPLY="-1"
32 zcurses 2>/dev/null delwin inner
33 zcurses 2>/dev/null delwin main
34 zcurses 2>/dev/null refresh
35 zcurses end
36 _nlist_alternate_screen 0
37 _nlist_cursor_visibility 1
38 unset _nlist_has_terminfo
39 }
40
41 # Outputs a message in the bottom of the screen
42 _nlist_status_msg() {
43 # -1 for border, -1 for 0-based indexing
44 zcurses move main $(( term_height - 1 - 1 )) 2
45 zcurses clear main eol
46 zcurses string main "$1"
47 #status_msg_strlen is localized in caller
48 status_msg_strlen=$#1
49 }
50
51 # Prefer tput, then module terminfo
52 _nlist_cursor_visibility() {
53 if type tput 2>/dev/null 1>&2; then
54 [ "$1" = "1" ] && { tput cvvis; tput cnorm }
55 [ "$1" = "0" ] && tput civis
56 elif [ "$_nlist_has_terminfo" = "1" ]; then
57 [ "$1" = "1" ] && { [ -n $terminfo[cvvis] ] && echo -n $terminfo[cvvis];
58 [ -n $terminfo[cnorm] ] && echo -n $terminfo[cnorm] }
59 [ "$1" = "0" ] && [ -n $terminfo[civis] ] && echo -n $terminfo[civis]
60 fi
61 }
62
63 # Reason for this function is that on some systems
64 # smcup and rmcup are not knowing why left empty
65 _nlist_alternate_screen() {
66 [ "$_nlist_has_terminfo" -ne "1" ] && return
67 [[ "$1" = "1" && -n "$terminfo[smcup]" ]] && return
68 [[ "$1" = "0" && -n "$terminfo[rmcup]" ]] && return
69
70 case "$TERM" in
71 *rxvt*)
72 [ "$1" = "1" ] && echo -n $'\x1b7\x1b[?47h'
73 [ "$1" = "0" ] && echo -n $'\x1b[2J\x1b[?47l\x1b8'
74 ;;
75 *)
76 [ "$1" = "1" ] && echo -n $'\x1b[?1049h'
77 [ "$1" = "0" ] && echo -n $'\x1b[?1049l'
78 # just to remember two other that work: $'\x1b7\x1b[r\x1b[?47h', $'\x1b[?47l\x1b8'
79 ;;
80 esac
81 }
82
83 _nlist_compute_user_vars_difference() {
84 if [[ "${(t)NLIST_NONSELECTABLE_ELEMENTS}" != "array" &&
85 "${(t)NLIST_NONSELECTABLE_ELEMENTS}" != "array-local" ]]
86 then
87 last_element_difference=0
88 current_difference=0
89 else
90 last_element_difference=$#NLIST_NONSELECTABLE_ELEMENTS
91 current_difference=0
92 local idx
93 for idx in "${(n)NLIST_NONSELECTABLE_ELEMENTS[@]}"; do
94 [ "$idx" -le "$NLIST_CURRENT_IDX" ] && current_difference+=1 || break
95 done
96 fi
97 }
98
99 # List was processed, check if variables aren't off range
100 _nlist_verify_vars() {
101 [ "$NLIST_CURRENT_IDX" -gt "$last_element" ] && NLIST_CURRENT_IDX="$last_element"
102 [[ "$NLIST_CURRENT_IDX" -eq 0 && "$last_element" -ne 0 ]] && NLIST_CURRENT_IDX=1
103 (( NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=0+((NLIST_CURRENT_IDX-1)/page_height)*page_height+1 ))
104 }
105
106 # Compute the variables which are shown to the user
107 _nlist_setup_user_vars() {
108 if [ "$1" = "1" ]; then
109 # Basic values when there are no non-selectables
110 NLIST_USER_CURRENT_IDX="$NLIST_CURRENT_IDX"
111 NLIST_USER_LAST_ELEMENT="$last_element"
112 else
113 _nlist_compute_user_vars_difference
114 NLIST_USER_CURRENT_IDX=$(( NLIST_CURRENT_IDX - current_difference ))
115 NLIST_USER_LAST_ELEMENT=$(( last_element - last_element_difference ))
116 fi
117 }
118
119 _nlist_coloring_list_into_col_list() {
120 local col=$'\x1b[00;34m' reset=$'\x1b[0m'
121 [ -n "$NLIST_COLORING_COLOR" ] && col="$NLIST_COLORING_COLOR"
122 [ -n "$NLIST_COLORING_END_COLOR" ] && reset="$NLIST_COLORING_END_COLOR"
123
124 if [ "$NLIST_COLORING_MATCH_MULTIPLE" -eq 1 ]; then
125 col_list=( "${(@)list//(#mi)$~NLIST_COLORING_PATTERN/$col${MATCH}$reset}" )
126 else
127 col_list=( "${(@)list/(#mi)$~NLIST_COLORING_PATTERN/$col${MATCH}$reset}" )
128 fi
129 }
130
131 #
132 # Main code
133 #
134
135 # Check if there is proper input
136 if [ "$#" -lt 1 ]; then
137 echo "Usage: n-list element_1 ..."
138 return 1
139 fi
140
141 REPLY="-1"
142 typeset -ga reply
143 reply=()
144
145 integer term_height="$LINES"
146 integer term_width="$COLUMNS"
147 if [[ "$term_height" -lt 1 || "$term_width" -lt 1 ]]; then
148 local stty_out=$( stty size )
149 term_height="${stty_out% *}"
150 term_width="${stty_out#* }"
151 fi
152 integer inner_height=term_height-3
153 integer inner_width=term_width-3
154 integer page_height=inner_height
155 integer page_width=inner_width
156
157 typeset -a list col_list disp_list
158 integer last_element=$#
159 local action
160 local final_key
161 integer selection
162 integer last_element_difference=0
163 integer current_difference=0
164 local prev_search_buffer=""
165 integer prev_uniq_mode=0
166 integer prev_start_idx=-1
167
168 # Ability to remember the list between calls
169 if [[ -z "$NLIST_REMEMBER_STATE" || "$NLIST_REMEMBER_STATE" -eq 0 || "$NLIST_REMEMBER_STATE" -eq 2 ]]; then
170 NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN=1
171 NLIST_CURRENT_IDX=1
172 NLIST_IS_SEARCH_MODE=0
173 NLIST_SEARCH_BUFFER=""
174 NLIST_TEXT_OFFSET=0
175 NLIST_IS_UNIQ_MODE=0
176
177 # Zero - because it isn't known, unless we
178 # confirm that first element is selectable
179 NLIST_USER_CURRENT_IDX=0
180 [[ ${NLIST_NONSELECTABLE_ELEMENTS[(r)1]} != 1 ]] && NLIST_USER_CURRENT_IDX=1
181 NLIST_USER_LAST_ELEMENT=$(( last_element - $#NLIST_NONSELECTABLE_ELEMENTS ))
182
183 # 2 is init once, then remember
184 [ "$NLIST_REMEMBER_STATE" -eq 2 ] && NLIST_REMEMBER_STATE=1
185 fi
186
187 if [ "$NLIST_START_IN_SEARCH_MODE" -eq 1 ]; then
188 NLIST_START_IN_SEARCH_MODE=0
189 NLIST_IS_SEARCH_MODE=1
190 fi
191
192 if [ -n "$NLIST_SET_SEARCH_TO" ]; then
193 NLIST_SEARCH_BUFFER="$NLIST_SET_SEARCH_TO"
194 NLIST_SET_SEARCH_TO=""
195 fi
196
197 if [ "$NLIST_START_IN_UNIQ_MODE" -eq 1 ]; then
198 NLIST_START_IN_UNIQ_MODE=0
199 NLIST_IS_UNIQ_MODE=1
200 fi
201
202 _nlist_alternate_screen 1
203 zcurses init
204 zcurses delwin main 2>/dev/null
205 zcurses delwin inner 2>/dev/null
206 zcurses addwin main "$term_height" "$term_width" 0 0
207 zcurses addwin inner "$inner_height" "$inner_width" 1 2
208 zcurses bg main white/black
209 zcurses bg inner white/black
210 if [ "$NLIST_IS_SEARCH_MODE" -ne 1 ]; then
211 _nlist_cursor_visibility 0
212 fi
213
214 #
215 # Listening for input
216 #
217
218 local key keypad
219
220 # Clear input buffer
221 zcurses timeout main 0
222 zcurses input main key keypad
223 zcurses timeout main -1
224 key=""
225 keypad=""
226
227 list=( "$@" )
228 last_element="$#list"
229
230 integer is_colored=0
231 if [[ -z "$NLIST_SEARCH_BUFFER" && -n "$NLIST_COLORING_PATTERN" ]]; then
232 is_colored=1
233 _nlist_coloring_list_into_col_list
234 fi
235
236 while (( 1 )); do
237 # Do searching (filtering with string)
238 if [ -n "$NLIST_SEARCH_BUFFER" ]; then
239 # Compute new list, col_list ?
240 if [[ "$NLIST_SEARCH_BUFFER" != "$prev_search_buffer" || "$NLIST_IS_UNIQ_MODE" -ne "$prev_uniq_mode" ]]; then
241 prev_search_buffer="$NLIST_SEARCH_BUFFER"
242 prev_uniq_mode="$NLIST_IS_UNIQ_MODE"
243 # regenerating list -> regenerating disp_list
244 prev_start_idx=-1
245
246 # Take all elements, including duplicates and non-selectables
247 typeset +U list
248 list=( "$@" )
249
250 # Remove non-selectable elements
251 [ "$#NLIST_NONSELECTABLE_ELEMENTS" -gt 0 ] && for i in "${(nO)NLIST_NONSELECTABLE_ELEMENTS[@]}"; do
252 list[$i]=()
253 done
254
255 # Remove duplicates
256 [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && typeset -U list
257
258 last_element="$#list"
259
260 # Next do the filtering
261 local search_buffer="${NLIST_SEARCH_BUFFER%% ##}"
262 search_buffer="${search_buffer## ##}"
263 search_buffer="${search_buffer//(#m)[][*?|#~^()><\\]/\\$MATCH}"
264 if [ -n "$search_buffer" ]; then
265 # Patterns will be *foo*~^*bar* and foo|bar)
266 local search_pattern="${search_buffer// ##/*~^*}"
267 local colsearch_pattern="${search_buffer// ##/|}"
268
269 list=( "${(@M)list:#(#i)*$~search_pattern*}" )
270 last_element="$#list"
271
272 local red=$'\x1b[00;31m' reset=$'\x1b[00;00m'
273 col_list=( "${(@)list//(#mi)($~colsearch_pattern)/$red${MATCH}$reset}" )
274 else
275 col_list=( "$list[@]" )
276 fi
277
278 # Called after processing list
279 _nlist_verify_vars
280 fi
281
282 _nlist_setup_user_vars 1
283
284 integer end_idx=$(( NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN + page_height - 1 ))
285 [ "$end_idx" -gt "$last_element" ] && end_idx=last_element
286
287 if [ "$prev_start_idx" -ne "$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN" ]; then
288 prev_start_idx="$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN"
289 disp_list=( "${(@)col_list[NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN, end_idx]}" )
290
291 # We have display list, lets replace newlines with "\n" when needed (1/3)
292 [ "$NLIST_REPLACE_NEWLINES" -eq 1 ] && disp_list=( "${(@)disp_list//$'\n'/\\n}" )
293 fi
294
295 # Output colored list
296 n-list-draw "$(( (NLIST_CURRENT_IDX-1) % page_height + 1 ))" \
297 "$page_height" "$page_width" 0 0 "$NLIST_TEXT_OFFSET" inner \
298 "$disp_list[@]"
299 else
300 # There is no search, but there was in previous loop
301 # OR
302 # Uniq mode was entered or left out
303 # -> compute new list (maybe also col_list)
304 if [[ -n "$prev_search_buffer" || "$NLIST_IS_UNIQ_MODE" -ne "$prev_uniq_mode" ]]; then
305 prev_search_buffer=""
306 prev_uniq_mode="$NLIST_IS_UNIQ_MODE"
307 # regenerating list -> regenerating disp_list
308 prev_start_idx=-1
309
310 # Take all elements, including duplicates and non-selectables
311 typeset +U list
312 list=( "$@" )
313
314 # Remove non-selectable elements only when in uniq mode
315 [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && [ "$#NLIST_NONSELECTABLE_ELEMENTS" -gt 0 ] &&
316 for i in "${(nO)NLIST_NONSELECTABLE_ELEMENTS[@]}"; do
317 list[$i]=()
318 done
319
320 # Remove duplicates when in uniq mode
321 [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && typeset -U list
322
323 # Apply coloring pattern (when not with search query)
324 is_colored=0
325 if [ -n "$NLIST_COLORING_PATTERN" ]; then
326 is_colored=1
327 _nlist_coloring_list_into_col_list
328 fi
329
330 last_element="$#list"
331 # Called after processing list
332 _nlist_verify_vars
333 fi
334
335 # "1" - shouldn't bother with non-selectables
336 _nlist_setup_user_vars "$NLIST_IS_UNIQ_MODE"
337
338 integer end_idx=$(( NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN + page_height - 1 ))
339 [ "$end_idx" -gt "$last_element" ] && end_idx=last_element
340
341 if [ "$is_colored" -eq 0 ]; then
342 if [ "$prev_start_idx" -ne "$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN" ]; then
343 prev_start_idx="$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN"
344 disp_list=( "${(@)list[NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN, end_idx]}" )
345
346 # We have display list, lets replace newlines with "\n" when needed (2/3)
347 [ "$NLIST_REPLACE_NEWLINES" -eq 1 ] && disp_list=( "${(@)disp_list//$'\n'/\\n}" )
348 fi
349 else
350 if [ "$prev_start_idx" -ne "$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN" ]; then
351 prev_start_idx="$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN"
352 disp_list=( "${(@)col_list[NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN, end_idx]}" )
353
354 # We have display list, lets replace newlines with "\n" when needed (3/3)
355 [ "$NLIST_REPLACE_NEWLINES" -eq 1 ] && disp_list=( "${(@)disp_list//$'\n'/\\n}" )
356 fi
357 fi
358
359 # Output the list
360 n-list-draw "$(( (NLIST_CURRENT_IDX-1) % page_height + 1 ))" \
361 "$page_height" "$page_width" 0 0 "$NLIST_TEXT_OFFSET" inner \
362 "$disp_list[@]"
363 fi
364
365 local status_msg_strlen
366 if [ "$NLIST_IS_SEARCH_MODE" = "1" ]; then
367 local _txt2=""
368 [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && _txt2="[-UNIQ-] "
369 _nlist_status_msg "${_txt2}Filtering with: ${NLIST_SEARCH_BUFFER// /+}"
370 elif [[ ${NLIST_NONSELECTABLE_ELEMENTS[(r)$NLIST_CURRENT_IDX]} != $NLIST_CURRENT_IDX ||
371 -n "$NLIST_SEARCH_BUFFER" || "$NLIST_IS_UNIQ_MODE" -eq 1 ]]; then
372 local _txt="" _txt2=""
373 [ -n "$NLIST_GREP_STRING" ] && _txt=" [$NLIST_GREP_STRING]"
374 [ "$NLIST_IS_UNIQ_MODE" -eq 1 ] && _txt2="[-UNIQ-] "
375 _nlist_status_msg "${_txt2}Current #$NLIST_USER_CURRENT_IDX (of #$NLIST_USER_LAST_ELEMENT entries)$_txt"
376 else
377 _nlist_status_msg ""
378 fi
379
380 zcurses border main
381 zcurses refresh main inner
382 zcurses move main $(( term_height - 1 - 1 )) $(( status_msg_strlen + 2 ))
383
384 # Wait for input
385 zcurses input main key keypad
386
387 # Get the special (i.e. "keypad") key or regular key
388 if [ -n "$key" ]; then
389 final_key="$key"
390 elif [ -n "$keypad" ]; then
391 final_key="$keypad"
392 else
393 _nlist_status_msg "Inproper input detected"
394 zcurses refresh main inner
395 fi
396
397 n-list-input "$NLIST_CURRENT_IDX" "$NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN" \
398 "$page_height" "$page_width" "$last_element" "$NLIST_TEXT_OFFSET" \
399 "$final_key" "$NLIST_IS_SEARCH_MODE" "$NLIST_SEARCH_BUFFER" \
400 "$NLIST_IS_UNIQ_MODE"
401
402 selection="$reply[1]"
403 action="$reply[2]"
404 NLIST_CURRENT_IDX="$reply[3]"
405 NLIST_FROM_WHAT_IDX_LIST_IS_SHOWN="$reply[4]"
406 NLIST_TEXT_OFFSET="$reply[5]"
407 NLIST_IS_SEARCH_MODE="$reply[6]"
408 NLIST_SEARCH_BUFFER="$reply[7]"
409 NLIST_IS_UNIQ_MODE="$reply[8]"
410
411 if [ "$action" = "SELECT" ]; then
412 REPLY="$selection"
413 reply=( "$list[@]" )
414 break
415 elif [ "$action" = "QUIT" ]; then
416 REPLY=-1
417 reply=( "$list[@]" )
418 break
419 elif [ "$action" = "REDRAW" ]; then
420 zcurses clear main redraw
421 zcurses clear inner redraw
422 fi
423 done
424
425 # vim: set filetype=zsh:
426
plugins/zsh-navigation-tools/n-list-draw
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-list-draw` to .zshrc
3 #
4 # This is an internal function not for direct use
5
6 emulate -L zsh
7
8 zmodload zsh/curses
9
10 setopt typesetsilent extendedglob
11
12 _nlist_print_with_ansi() {
13 local win="$1" text="$2" out col chunk Xout
14 integer text_offset="$3" max_text_len="$4" text_len=0 no_match=0 nochunk_text_len to_skip_from_chunk to_chop_off_from_chunk before_len
15
16 # 1 - non-escaped text, 2 - first number in the escaped text, with ;
17 # 3 - second number, 4 - text after whole escape text
18
19 typeset -a c
20 c=( black red green yellow blue magenta cyan white )
21
22 while [[ -n "$text" && "$no_match" -eq 0 ]]; do
23 if [[ "$text" = (#b)([^$'\x1b']#)$'\x1b'\[([0-9](#c0,2))(#B)(\;|)(#b)([0-9](#c0,2))m(*) ]]; then
24 # Text for further processing
25 text="$match[4]"
26 # Text chunk to output now
27 out="$match[1]"
28 # Save color
29 col="$match[2]"
30 (( match[3] >= 30 && match[3] <= 37 )) && col="$match[3]"
31 else
32 out="$text"
33 no_match=1
34 fi
35
36 if [ -n "$out" ]; then
37 ################ Expand tabs ################
38 chunk="$out"
39 before_len="$text_len"
40 Xout=""
41
42 while [ -n "$chunk" ]; do
43 [[ "$chunk" = (#b)([^$'\t']#)$'\t'(*) ]] && {
44 (( all_text_len=((before_len+${#match[1]})/8+1)*8 ))
45
46 Xout+="${(r:all_text_len-before_len:: :)match[1]}"
47
48 before_len+=all_text_len-before_len
49 chunk="$match[2]"
50 } || {
51 Xout+="$chunk"
52 break
53 }
54 done
55 #############################################
56
57 # Input text length without the current chunk
58 nochunk_text_len=text_len
59 # Input text length up to current chunk
60 text_len+="$#Xout"
61
62 # Should start displaying with this chunk?
63 # I.e. stop skipping left part of the input text?
64 if (( text_len > text_offset )); then
65 to_skip_from_chunk=text_offset-nochunk_text_len
66
67 # LEFT - is chunk off the left skip boundary? +1 for 1-based index in string
68 (( to_skip_from_chunk > 0 )) && Xout="${Xout[to_skip_from_chunk+1,-1]}"
69
70 # RIGHT - is text off the screen?
71 if (( text_len-text_offset > max_text_len )); then
72 to_chop_off_from_chunk=0+(text_len-text_offset)-max_text_len
73 Xout="${Xout[1,-to_chop_off_from_chunk-1]}"
74 fi
75
76 [ -n "$Xout" ] && zcurses string "$win" "$Xout"
77 fi
78 fi
79
80 if (( no_match == 0 )); then
81 if (( col >= 30 && col <= 37 )); then
82 zcurses attr "$win" $c[col-29]/black
83 elif [[ "$col" -eq 0 ]]; then
84 zcurses attr "$win" white/black
85 fi
86 fi
87 done
88 }
89
90 integer highlight="$1"
91 integer page_height="$2"
92 integer page_width="$3"
93 local y_offset="$4"
94 local x_offset="$5"
95 local text_offset="$6"
96 local win="$7"
97 shift 7
98 integer max_text_len=page_width-x_offset
99
100 [ "$bold" = "0" ] && bold="" || bold="+bold"
101 [[ "$active_text" = "underline" || "$active_text" = "reverse" ]] || active_text="reverse"
102 # With Linux terminal underline won't work properly
103 [ "$TERM" = "linux" ] && active_text="reverse"
104
105 integer max_idx=page_height
106 integer end_idx=max_idx
107 [ "$end_idx" -gt "$#" ] && end_idx="$#"
108 integer y=y_offset
109
110 zcurses attr "$win" $bold white/black
111
112 integer i text_len
113 local text
114 for (( i=1; i<=end_idx; i++ )); do
115 zcurses move "$win" $y "$x_offset"
116
117 [ "$i" = "$highlight" ] && zcurses attr "$win" +"$active_text"
118 _nlist_print_with_ansi "$win" "$@[i]" "$text_offset" "$max_text_len"
119 zcurses clear "$win" eol
120 [ "$i" = "$highlight" ] && zcurses attr "$win" -"$active_text"
121
122 y+=1
123 done
124
125 if [ "$end_idx" -lt "$max_idx" ]; then
126 zcurses move "$win" $y "$x_offset"
127 zcurses clear "$win" eol
128 fi
129
130 zcurses attr "$win" white/black
131 # vim: set filetype=zsh:
132
plugins/zsh-navigation-tools/n-list-input
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-list-input` to .zshrc
3 #
4 # This is an internal function not for direct use
5
6 emulate -L zsh
7
8 zmodload zsh/curses
9
10 setopt typesetsilent
11
12 # Compute first to show index
13 _nlist_compute_first_to_show_idx() {
14 from_what_idx_list_is_shown=0+((current_idx-1)/page_height)*page_height+1
15 }
16
17 typeset -ga reply
18 reply=( -1 '' )
19 integer current_idx="$1"
20 integer from_what_idx_list_is_shown="$2"
21 integer page_height="$3"
22 integer page_width="$4"
23 integer last_element="$5"
24 integer hscroll="$6"
25 local key="$7"
26 integer search="$8"
27 local buffer="$9"
28 integer uniq_mode="$10"
29
30 #
31 # Listening for input
32 #
33
34 if [ "$search" = "0" ]; then
35
36 case "$key" in
37 (UP|k|$'\C-P')
38 # Are there any elements before the current one?
39 [ "$current_idx" -gt 1 ] && current_idx=current_idx-1;
40 _nlist_compute_first_to_show_idx
41 ;;
42 (DOWN|j|$'\C-N')
43 # Are there any elements after the current one?
44 [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1;
45 _nlist_compute_first_to_show_idx
46 ;;
47 (PPAGE)
48 current_idx=current_idx-page_height
49 [ "$current_idx" -lt 1 ] && current_idx=1;
50 _nlist_compute_first_to_show_idx
51 ;;
52 (NPAGE|" ")
53 current_idx=current_idx+page_height
54 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
55 _nlist_compute_first_to_show_idx
56 ;;
57 ($'\C-U')
58 current_idx=current_idx-page_height/2
59 [ "$current_idx" -lt 1 ] && current_idx=1;
60 _nlist_compute_first_to_show_idx
61 ;;
62 ($'\C-D')
63 current_idx=current_idx+page_height/2
64 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
65 _nlist_compute_first_to_show_idx
66 ;;
67 (HOME|g)
68 current_idx=1
69 _nlist_compute_first_to_show_idx
70 ;;
71 (END|G)
72 current_idx=last_element
73 _nlist_compute_first_to_show_idx
74 ;;
75 ($'\n')
76 # Is that element selectable?
77 # Check for this only when there is no search
78 if [[ "$NLIST_SEARCH_BUFFER" != "" || "$NLIST_IS_UNIQ_MODE" -eq 1 ||
79 ${NLIST_NONSELECTABLE_ELEMENTS[(r)$current_idx]} != $current_idx ]]
80 then
81 # Save current element in the result variable
82 reply=( $current_idx SELECT )
83 fi
84 ;;
85 (q)
86 reply=( -1 QUIT )
87 ;;
88 (/)
89 search=1
90 _nlist_cursor_visibility 1
91 ;;
92 ($'\t')
93 reply=( $current_idx LEAVE )
94 ;;
95 ($'\C-L')
96 reply=( -1 REDRAW )
97 ;;
98 (\])
99 [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
100 [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] &&
101 for idx in "${(n)NLIST_HOP_INDEXES[@]}"; do
102 if [ "$idx" -gt "$current_idx" ]; then
103 current_idx=$idx
104 _nlist_compute_first_to_show_idx
105 break
106 fi
107 done
108 ;;
109 (\[)
110 [[ "${(t)NLIST_HOP_INDEXES}" = "array" || "${(t)NLIST_HOP_INDEXES}" = "array-local" ]] &&
111 [ -z "$NLIST_SEARCH_BUFFER" ] && [ "$NLIST_IS_UNIQ_MODE" -eq 0 ] &&
112 for idx in "${(nO)NLIST_HOP_INDEXES[@]}"; do
113 if [ "$idx" -lt "$current_idx" ]; then
114 current_idx=$idx
115 _nlist_compute_first_to_show_idx
116 break
117 fi
118 done
119 ;;
120 ('<'|'{'|LEFT|'h')
121 hscroll=hscroll-7
122 [ "$hscroll" -lt 0 ] && hscroll=0
123 ;;
124 ('>'|'}'|RIGHT|'l')
125 hscroll+=7
126 ;;
127 ($'\E')
128 buffer=""
129 ;;
130 (o|$'\C-O')
131 uniq_mode=1-uniq_mode
132 ;;
133 (*)
134 ;;
135 esac
136
137 else
138
139 case "$key" in
140 ($'\n')
141 search=0
142 _nlist_cursor_visibility 0
143 ;;
144 ($'\C-L')
145 reply=( -1 REDRAW )
146 ;;
147
148 #
149 # Slightly limited navigation
150 #
151
152 (UP|$'\C-P')
153 [ "$current_idx" -gt 1 ] && current_idx=current_idx-1;
154 _nlist_compute_first_to_show_idx
155 ;;
156 (DOWN|$'\C-N')
157 [ "$current_idx" -lt "$last_element" ] && current_idx=current_idx+1;
158 _nlist_compute_first_to_show_idx
159 ;;
160 (PPAGE)
161 current_idx=current_idx-page_height
162 [ "$current_idx" -lt 1 ] && current_idx=1;
163 _nlist_compute_first_to_show_idx
164 ;;
165 (NPAGE)
166 current_idx=current_idx+page_height
167 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
168 _nlist_compute_first_to_show_idx
169 ;;
170 ($'\C-U')
171 current_idx=current_idx-page_height/2
172 [ "$current_idx" -lt 1 ] && current_idx=1;
173 _nlist_compute_first_to_show_idx
174 ;;
175 ($'\C-D')
176 current_idx=current_idx+page_height/2
177 [ "$current_idx" -gt "$last_element" ] && current_idx=last_element;
178 _nlist_compute_first_to_show_idx
179 ;;
180 (HOME)
181 current_idx=1
182 _nlist_compute_first_to_show_idx
183 ;;
184 (END)
185 current_idx=last_element
186 _nlist_compute_first_to_show_idx
187 ;;
188 (LEFT)
189 hscroll=hscroll-7
190 [ "$hscroll" -lt 0 ] && hscroll=0
191 ;;
192 (RIGHT)
193 hscroll+=7
194 ;;
195 (F1|F2|F3|F4|F5|F6|F7|F8|F9|F10)
196 # ignore
197 ;;
198
199 #
200 # The input
201 #
202
203 ($'\b'|$'\C-?'|BACKSPACE)
204 buffer="${buffer%?}"
205 ;;
206 ($'\C-W')
207 [ "$buffer" = "${buffer% *}" ] && buffer="" || buffer="${buffer% *}"
208 ;;
209 ($'\C-K')
210 buffer=""
211 ;;
212 ($'\E')
213 buffer=""
214 search=0
215 _nlist_cursor_visibility 0
216 ;;
217 ($'\C-O')
218 uniq_mode=1-uniq_mode
219 ;;
220 (*)
221 if [[ $#key == 1 && $((#key)) -lt 31 ]]; then
222 # ignore all other control keys
223 else
224 buffer+="$key"
225 fi
226 ;;
227 esac
228
229 fi
230
231 reply[3]="$current_idx"
232 reply[4]="$from_what_idx_list_is_shown"
233 reply[5]="$hscroll"
234 reply[6]="$search"
235 reply[7]="$buffer"
236 reply[8]="$uniq_mode"
237
238 # vim: set filetype=zsh:
239
plugins/zsh-navigation-tools/n-options
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-options` to .zshrc
3 #
4 # This function allows to browse and toggle shell's options
5 #
6 # Uses n-list
7
8 #emulate -L zsh
9
10 zmodload zsh/curses
11
12 local IFS="
13 "
14
15 unset NLIST_COLORING_PATTERN
16
17 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
18 [ -f ~/.config/znt/n-options.conf ] && . ~/.config/znt/n-options.conf
19
20 # TODO restore options
21 unsetopt localoptions
22
23 integer kshoptionprint=0
24 [[ -o kshoptionprint ]] && kshoptionprint=1
25 setopt kshoptionprint
26
27 local list
28 local selected
29 local option
30 local state
31
32 # 0 - don't remember, 1 - remember, 2 - init once, then remember
33 NLIST_REMEMBER_STATE=2
34
35 local NLIST_GREP_STRING="${1:=}"
36
37 while (( 1 )); do
38 list=( `setopt` )
39 list=( "${(M)list[@]:#*${1:=}*}" )
40 list=( "${list[@]:#kshoptionprint*}" )
41
42 if [ "$#list" -eq 0 ]; then
43 echo "No matching options"
44 break
45 fi
46
47 local red=$'\x1b[00;31m' green=$'\x1b[00;32m' reset=$'\x1b[00;00m'
48 list=( "${list[@]/ off/${red} off$reset}" )
49 #list=( "${list[@]/ on/${green} on$reset}" )
50 list=( "${(i)list[@]}" )
51
52 n-list "${list[@]}"
53
54 if [ "$REPLY" -gt 0 ]; then
55 [[ -o ksharrays ]] && selected="${reply[$(( REPLY - 1 ))]}" || selected="${reply[$REPLY]}"
56 option="${selected%% *}"
57 state="${selected##* }"
58
59 if [[ -o globsubst ]]; then
60 unsetopt globsubst
61 state="${state%$reset}"
62 setopt globsubst
63 else
64 state="${state%$reset}"
65 fi
66
67 # Toggle the option
68 if [ "$state" = "on" ]; then
69 echo "Setting |$option| to off"
70 unsetopt "$option"
71 else
72 echo "Setting |$option| to on"
73 setopt "$option"
74 fi
75 else
76 break
77 fi
78 done
79
80 NLIST_REMEMBER_STATE=0
81
82 [[ "$kshoptionprint" -eq 0 ]] && unsetopt kshoptionprint
83
84 # vim: set filetype=zsh:
85
plugins/zsh-navigation-tools/n-panelize
File was created 1 # Copy this file into /usr/share/zsh/site-functions/
2 # and add 'autoload n-panelize` to .zshrc
3 #
4 # This function somewhat reminds the panelize feature from Midnight Commander
5 # It allows browsing output of arbitrary command. Example usage:
6 # v-panelize ls /usr/local/bin
7 #
8 # Uses n-list
9
10 emulate -L zsh
11
12 setopt extendedglob
13 zmodload zsh/curses
14
15 local IFS="
16 "
17
18 unset NLIST_COLORING_PATTERN
19
20 [ -f ~/.config/znt/n-list.conf ] && . ~/.config/znt/n-list.conf
21 [ -f ~/.config/znt/n-panelize.conf ] && . ~/.config/znt/n-panelize.conf
22
23 local list
24 local selected
25
26 NLIST_REMEMBER_STATE=0
27
28 if [ -t 0 ]; then
29 # Check if there is proper input
30 if [ "$#" -lt 1 ]; then
31 echo "Usage: n-panelize {command} [option|argument] ... or command | n-panelize"
32 return 1
33 fi
34
35 list=( `"$@"` )
36 # TODO: $? doesn't reach user
37 [ "$?" -eq 127 ] && return $?
38 else
39 # Check if can reattach to terminal
40 if [[ ! -c /dev/tty && ! -t 2 ]]; then
41 echo "No terminal available (no /dev/tty)"
42 return 1
43 fi
44
45 list=( "${(@f)"$(<&0)"}" )
46
47 if [[ ! -c /dev/tty ]]; then
48 exec <&2
49 else
50 exec </dev/tty
51 fi
52 fi
53
54 n-list "${list[@]}"
55
56 if [ "$REPLY" -gt 0 ]; then
57 selected="$reply[REPLY]"
58 print -zr "# $selected"
59 fi
60
61 # vim: set filetype=zsh:
62
plugins/zsh-navigation-tools/znt-cd-widget
File was created 1 autoload znt-usetty-wrapper n-cd
2 local NLIST_START_IN_SEARCH_MODE=0
3 local NLIST_START_IN_UNIQ_MODE=0
4
5 znt-usetty-wrapper n-cd "$@"
6
7 unset NLIST_START_IN_SEARCH_MODE
8 unset NLIST_START_IN_UNIQ_MODE
9
plugins/zsh-navigation-tools/znt-history-widget
File was created 1 autoload znt-usetty-wrapper n-history
2 local NLIST_START_IN_SEARCH_MODE=1
3 local NLIST_START_IN_UNIQ_MODE=1
4 local NLIST_SET_SEARCH_TO="$BUFFER"
5
6 znt-usetty-wrapper n-history "$@"
7
8 unset NLIST_START_IN_SEARCH_MODE
9 unset NLIST_START_IN_UNIQ_MODE
10 unset NLIST_SET_SEARCH_TO
11
plugins/zsh-navigation-tools/znt-kill-widget
File was created 1 autoload znt-usetty-wrapper n-kill
2 local NLIST_START_IN_SEARCH_MODE=0
3 local NLIST_START_IN_UNIQ_MODE=0
4
5 znt-usetty-wrapper n-kill "$@"
6
7 unset NLIST_START_IN_SEARCH_MODE
8 unset NLIST_START_IN_UNIQ_MODE
9
plugins/zsh-navigation-tools/znt-usetty-wrapper
File was created 1 emulate -L zsh
2
3 zmodload zsh/curses
4
5 test_fd0() {
6 true <&0
7 }
8
9 local restore=0 FD
10
11 # Reattach to terminal
12 if [ ! -t 0 ]; then
13 # Check if can reattach to terminal in any way
14 if [[ ! -c /dev/tty && ! -t 2 ]]; then
15 echo "No terminal available (no /dev/tty and no terminal at stderr)"
16 return 1
17 fi
18
19 if test_fd0 2>/dev/null; then
20 exec {FD}<&0
21 restore=2
22 else
23 restore=1
24 fi
25
26 if [[ ! -c /dev/tty ]]; then
27 exec <&2
28 else
29 exec </dev/tty
30 fi
31 fi
32
33 # Run the command
34 "$@"
35
36 # Restore FD state
37 (( restore == 1 )) && exec <&-
38 (( restore == 2 )) && exec <&$FD && exec {FD}<&-
39
40 # vim: set filetype=zsh:
41
plugins/zsh-navigation-tools/zsh-navigation-tools.plugin.zsh
File was created 1 #!/usr/bin/env zsh
2
3 REPO_DIR="${0%/*}"
4 CONFIG_DIR="$HOME/.config/znt"
5
6 #
7 # Copy configs
8 #
9
10 if ! test -d "$HOME/.config"; then
11 mkdir "$HOME/.config"
12 fi
13
14 if ! test -d "$CONFIG_DIR"; then
15 mkdir "$CONFIG_DIR"
16 fi
17
18 set n-aliases.conf n-env.conf n-history.conf n-list.conf n-panelize.conf n-cd.conf n-functions.conf n-kill.conf n-options.conf
19
20 for i; do
21 if ! test -f "$CONFIG_DIR/$i"; then
22 cp "$REPO_DIR/.config/znt/$i" "$CONFIG_DIR"
23 fi
24 done
25
26 #
27 # Load functions
28 #
29
30 autoload n-aliases n-cd n-env n-functions n-history n-kill n-list n-list-draw n-list-input n-options n-panelize
31 autoload znt-usetty-wrapper znt-history-widget znt-cd-widget znt-kill-widget
32 alias naliases=n-aliases ncd=n-cd nenv=n-env nfunctions=n-functions nhistory=n-history
33 alias nkill=n-kill noptions=n-options npanelize=n-panelize
34
35 zle -N znt-history-widget
36 bindkey '^R' znt-history-widget
37 setopt AUTO_PUSHD HIST_IGNORE_DUPS PUSHD_IGNORE_DUPS
38
39
tools/check_for_upgrade.sh
1 #!/usr/bin/env zsh 1 #!/usr/bin/env zsh
2 2
3 zmodload zsh/datetime 3 zmodload zsh/datetime
4 4
5 function _current_epoch() { 5 function _current_epoch() {
6 echo $(( $EPOCHSECONDS / 60 / 60 / 24 )) 6 echo $(( $EPOCHSECONDS / 60 / 60 / 24 ))
7 } 7 }
8 8
9 function _update_zsh_update() { 9 function _update_zsh_update() {
10 echo "LAST_EPOCH=$(_current_epoch)" >! ~/.zsh-update 10 echo "LAST_EPOCH=$(_current_epoch)" >! ~/.zsh-update
11 } 11 }
12 12
13 function _upgrade_zsh() { 13 function _upgrade_zsh() {
14 env ZSH=$ZSH /bin/sh $ZSH/tools/upgrade.sh 14 env ZSH=$ZSH /bin/sh $ZSH/tools/upgrade.sh
15 # update the zsh file 15 # update the zsh file
16 _update_zsh_update 16 _update_zsh_update
17 } 17 }
18 18
19 epoch_target=$UPDATE_ZSH_DAYS 19 epoch_target=$UPDATE_ZSH_DAYS
20 if [[ -z "$epoch_target" ]]; then 20 if [[ -z "$epoch_target" ]]; then
21 # Default to old behavior 21 # Default to old behavior
22 epoch_target=13 22 epoch_target=13
23 fi 23 fi
24 24
25 # Cancel upgrade if the current user doesn't have write permissions for the 25 # Cancel upgrade if the current user doesn't have write permissions for the
26 # oh-my-zsh directory. 26 # oh-my-zsh directory.
27 [[ -w "$ZSH" ]] || return 0 27 [[ -w "$ZSH" ]] || return 0
28 28
29 # Cancel upgrade if git is unavailable on the system 29 # Cancel upgrade if git is unavailable on the system
30 whence git >/dev/null || return 0 30 whence git >/dev/null || return 0
31 31
32 if [ -f ~/.zsh-update ] 32 if [ -f ~/.zsh-update ]
33 then 33 then
34 . ~/.zsh-update 34 . ~/.zsh-update
35 35
36 if [[ -z "$LAST_EPOCH" ]]; then 36 if [[ -z "$LAST_EPOCH" ]]; then
37 _update_zsh_update && return 0; 37 _update_zsh_update && return 0;
38 fi 38 fi
39 39
40 epoch_diff=$(($(_current_epoch) - $LAST_EPOCH)) 40 epoch_diff=$(($(_current_epoch) - $LAST_EPOCH))
41 if [ $epoch_diff -gt $epoch_target ] 41 if [ $epoch_diff -gt $epoch_target ]
42 then 42 then
43 if [ "$DISABLE_UPDATE_PROMPT" = "true" ] 43 if [ "$DISABLE_UPDATE_PROMPT" = "true" ]
44 then 44 then
45 _upgrade_zsh 45 _upgrade_zsh
46 else 46 else
47 echo "[Oh My Zsh] Would you like to check for updates? [Y/n]: \c" 47 echo "[Oh My Zsh] Would you like to check for updates? [Y/n]: \c"
48 read line 48 read line
49 if [ "$line" = Y ] || [ "$line" = y ] || [ -z "$line" ]; then 49 if [[ "$line" == Y* ]] || [[ "$line" == y* ]] || [ -z "$line" ]; then
50 _upgrade_zsh 50 _upgrade_zsh
51 else 51 else
52 _update_zsh_update 52 _update_zsh_update
53 fi 53 fi
54 fi 54 fi
55 fi 55 fi
56 else 56 else
57 # create the zsh file 57 # create the zsh file
58 _update_zsh_update 58 _update_zsh_update
59 fi 59 fi
60 60
1 read -r -p "Are you sure you want to remove Oh My Zsh? [y/N] " confirmation 1 read -r -p "Are you sure you want to remove Oh My Zsh? [y/N] " confirmation
2 if [ "$confirmation" != y ] && [ "$confirmation" != Y ] 2 if [ "$confirmation" != y ] && [ "$confirmation" != Y ]; then
3 then
4 echo "Uninstall cancelled" 3 echo "Uninstall cancelled"
5 exit 4 exit
6 fi 5 fi
7 6
8 echo "Removing ~/.oh-my-zsh" 7 echo "Removing ~/.oh-my-zsh"
9 if [ -d ~/.oh-my-zsh ] 8 if [ -d ~/.oh-my-zsh ]; then
10 then
11 rm -rf ~/.oh-my-zsh 9 rm -rf ~/.oh-my-zsh
12 fi 10 fi
13 11
14 echo "Looking for original zsh config..." 12 echo "Looking for original zsh config..."
15 if [ -f ~/.zshrc.pre-oh-my-zsh ] || [ -h ~/.zshrc.pre-oh-my-zsh ] 13 if [ -f ~/.zshrc.pre-oh-my-zsh ] || [ -h ~/.zshrc.pre-oh-my-zsh ]; then
16 then
17 echo "Found ~/.zshrc.pre-oh-my-zsh -- Restoring to ~/.zshrc"; 14 echo "Found ~/.zshrc.pre-oh-my-zsh -- Restoring to ~/.zshrc";
18 15
19 if [ -f ~/.zshrc ] || [ -h ~/.zshrc ] 16 if [ -f ~/.zshrc ] || [ -h ~/.zshrc ]; then
20 then 17 ZSHRC_SAVE=".zshrc.omz-uninstalled-$(date +%Y%m%d%H%M%S)";
21 ZSHRC_SAVE=".zshrc.omz-uninstalled-`date +%Y%m%d%H%M%S`";
22 echo "Found ~/.zshrc -- Renaming to ~/${ZSHRC_SAVE}"; 18 echo "Found ~/.zshrc -- Renaming to ~/${ZSHRC_SAVE}";
23 mv ~/.zshrc ~/${ZSHRC_SAVE}; 19 mv ~/.zshrc ~/"${ZSHRC_SAVE}";
24 fi 20 fi
25 21
26 mv ~/.zshrc.pre-oh-my-zsh ~/.zshrc; 22 mv ~/.zshrc.pre-oh-my-zsh ~/.zshrc;
27 23
28 source ~/.zshrc; 24 echo "Your original zsh config was restored. Please restart your session."
29 else 25 else
30 if hash chsh >/dev/null 2>&1 26 if hash chsh >/dev/null 2>&1; then
31 then
32 echo "Switching back to bash" 27 echo "Switching back to bash"
33 chsh -s /bin/bash 28 chsh -s /bin/bash
34 else 29 else
35 echo "You can edit /etc/passwd to switch your default shell back to bash" 30 echo "You can edit /etc/passwd to switch your default shell back to bash"
36 fi 31 fi
37 fi 32 fi
38 33
39 echo "Thanks for trying out Oh My Zsh. It's been uninstalled." 34 echo "Thanks for trying out Oh My Zsh. It's been uninstalled."
40 35