mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-11 00:51:05 +02:00
43078: add completion for the sed expression
This commit is contained in:
parent
afd008d96b
commit
c919fa7f69
2 changed files with 209 additions and 11 deletions
|
@ -1,5 +1,8 @@
|
||||||
2018-06-18 Oliver Kiddle <okiddle@yahoo.co.uk>
|
2018-06-18 Oliver Kiddle <okiddle@yahoo.co.uk>
|
||||||
|
|
||||||
|
* 43078: Completion/Unix/Command/_sed: add completion for the
|
||||||
|
sed expression
|
||||||
|
|
||||||
* 43073: Completion/Linux/Command/_cryptsetup,
|
* 43073: Completion/Linux/Command/_cryptsetup,
|
||||||
Completion/Linux/Command/_sysstat, Completion/Linux/Command/_ss,
|
Completion/Linux/Command/_sysstat, Completion/Linux/Command/_ss,
|
||||||
Completion/Linux/Command/_kpartx, Completion/Linux/Command/_tune2fs,
|
Completion/Linux/Command/_kpartx, Completion/Linux/Command/_tune2fs,
|
||||||
|
|
|
@ -1,16 +1,60 @@
|
||||||
#compdef sed gsed psed s2p
|
#compdef sed gsed psed s2p
|
||||||
|
|
||||||
local inplace extended
|
local variant inplace extended ign sep separator
|
||||||
local -a args aopts=( -A '-*' )
|
local -i nest=0
|
||||||
|
local -a args aopts sedexpr cmds_none cmds_slash cmds_end substflags expl bsnl nl labels excl dedup
|
||||||
|
local -a step range negate mods
|
||||||
|
aopts=( -A '-*' )
|
||||||
|
bsnl=( $'\\\n' )
|
||||||
|
nl=$'\n'
|
||||||
|
compquote nl
|
||||||
|
|
||||||
|
cmds_none=(
|
||||||
|
'{:start group'
|
||||||
|
'q:quit after printing pattern space'
|
||||||
|
'h:copy pattern space to hold space'
|
||||||
|
'\::place label'
|
||||||
|
'#:comment'
|
||||||
|
'=:print current line number'
|
||||||
|
'a:append text'
|
||||||
|
'i:insert text'
|
||||||
|
'r:append contents of file'
|
||||||
|
'b:branch'
|
||||||
|
't:branch if s command has been successful'
|
||||||
|
'c:replace line with text'
|
||||||
|
'l:list current line in visually unambiguous form'
|
||||||
|
'w:write pattern space to file'
|
||||||
|
)
|
||||||
|
cmds_slash=(
|
||||||
|
's:substitute regex'
|
||||||
|
'y:transliterate characters'
|
||||||
|
)
|
||||||
|
cmds_end=(
|
||||||
|
'd:delete pattern space'
|
||||||
|
'D:delete up to the first newline in the pattern space'
|
||||||
|
'g:copy hold space to pattern space'
|
||||||
|
'G:append hold space to pattern space'
|
||||||
|
'H:append pattern space to hold space'
|
||||||
|
'n:read the next line of input into pattern space'
|
||||||
|
'N:append the next line of input to the pattern space'
|
||||||
|
'p:print the current pattern space'
|
||||||
|
'P:print upto the first newline of the current pattern space'
|
||||||
|
'x:exchange hold and pattern spaces'
|
||||||
|
'}:end group'
|
||||||
|
)
|
||||||
|
substflags=(
|
||||||
|
'g:replace all matches to the regular expression'
|
||||||
|
'p:print new pattern space if substitution made'
|
||||||
|
'w:write result to named file if substitution made'
|
||||||
|
)
|
||||||
args=(
|
args=(
|
||||||
'(-n --quiet --silent)'{-n,--quiet,--silent}'[suppress automatic printing of pattern space]'
|
'(-n --quiet --silent)'{-n,--quiet,--silent}'[suppress automatic printing of pattern space]'
|
||||||
'(1)*'{-e+,--expression=}'[specify sed commands to run]:sed script'
|
'(1)*'{-e+,--expression=}'[specify sed commands to run]:sed script:_sed_expressions'
|
||||||
'(1)*'{-f+,--file=}'[add contents of file to commands to run]: :_files'
|
'(1)*'{-f+,--file=}'[add contents of file to commands to run]:file:_files'
|
||||||
'(-e)1: :_guard "^-*" sed script'
|
'(-e)1:sed script:_sed_expressions'
|
||||||
'*:input file:_files'
|
'*:input file:_files'
|
||||||
)
|
)
|
||||||
inplace='[edit files in-place, running scripts separately for each file]::suffix for backup'
|
inplace='[edit files in-place, running scripts separately for each file]:: :_guard "^(*[@/; ]*|?(#c6,)|-*)" "suffix for backup"'
|
||||||
extended='[use extended regular expressions]'
|
extended='[use extended regular expressions]'
|
||||||
|
|
||||||
if [[ $service = (psed|s2p) ]]; then
|
if [[ $service = (psed|s2p) ]]; then
|
||||||
|
@ -18,11 +62,12 @@ if [[ $service = (psed|s2p) ]]; then
|
||||||
"${(@)args:#(|\(*\))(|\*)--*}"
|
"${(@)args:#(|\(*\))(|\*)--*}"
|
||||||
'-a[delay opening files listed with w function]'
|
'-a[delay opening files listed with w function]'
|
||||||
)
|
)
|
||||||
elif _pick_variant gnu=GNU unix --version; then
|
elif _pick_variant -r variant gnu=GNU unix --version; then
|
||||||
aopts=( )
|
aopts=( )
|
||||||
|
(( $#words > 2 )) && ign='!'
|
||||||
args+=(
|
args+=(
|
||||||
'--follow-symlinks[follow symlinks when processing in place]'
|
'--follow-symlinks[follow symlinks when processing in place]'
|
||||||
'(-i --in-place)'{-i+,--in-place=}$inplace
|
'(-i --in-place -s --separate)'{-i-,--in-place=-}$inplace
|
||||||
'(-c --copy)'{-c,--copy}'[copy instead of rename when shuffling files in in-place mode]'
|
'(-c --copy)'{-c,--copy}'[copy instead of rename when shuffling files in in-place mode]'
|
||||||
'(-l --line-length)'{-l+,--line-length=}'[specify line-wrap length for the l command]'
|
'(-l --line-length)'{-l+,--line-length=}'[specify line-wrap length for the l command]'
|
||||||
'(-r)--posix[disable GNU extensions]'
|
'(-r)--posix[disable GNU extensions]'
|
||||||
|
@ -31,9 +76,28 @@ elif _pick_variant gnu=GNU unix --version; then
|
||||||
'--sandbox[block commands that can affect the system (r/w/W/e)]'
|
'--sandbox[block commands that can affect the system (r/w/W/e)]'
|
||||||
'(-u --unbuffered)'{-u,--unbuffered}'[disable data buffering]'
|
'(-u --unbuffered)'{-u,--unbuffered}'[disable data buffering]'
|
||||||
'(-z --null-data)'{-z,--null-data}'[separate lines by NUL characters]'
|
'(-z --null-data)'{-z,--null-data}'[separate lines by NUL characters]'
|
||||||
'(- 1 :)--help[print program usage]'
|
"${ign}(- 1 :)--help[print program usage]"
|
||||||
'(- 1 :)--version[print program version]'
|
"${ign}(- 1 :)--version[print program version]"
|
||||||
)
|
)
|
||||||
|
if [[ -z ${words[(r)--posix]} ]]; then
|
||||||
|
cmds_none+=(
|
||||||
|
'R:append a line from file'
|
||||||
|
'T:branch if no s command has been successful'
|
||||||
|
'W:write the first line of pattern space to file'
|
||||||
|
'v:fail if GNU extensions not supported or older than specified version'
|
||||||
|
)
|
||||||
|
cmds_end+=(
|
||||||
|
"e:execute a command and include it's output"
|
||||||
|
'F:print the filename of the current input file'
|
||||||
|
'Q:quit'
|
||||||
|
'z:empty the pattern space'
|
||||||
|
)
|
||||||
|
substflags+=(
|
||||||
|
'e:execute pattern space as a command and replace with result'
|
||||||
|
{i,I}':case-insensitive regular expression matching'
|
||||||
|
{m,M}':multi-line matching'
|
||||||
|
)
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
args=( "${(@)args:#(|\(*\))(|\*)--*}" )
|
args=( "${(@)args:#(|\(*\))(|\*)--*}" )
|
||||||
case $OSTYPE in
|
case $OSTYPE in
|
||||||
|
@ -49,11 +113,142 @@ else
|
||||||
freebsd*) args+=( '-u[disable data buffering]' ) ;|
|
freebsd*) args+=( '-u[disable data buffering]' ) ;|
|
||||||
freebsd*|netbsd*)
|
freebsd*|netbsd*)
|
||||||
args+=(
|
args+=(
|
||||||
'-I+[edit files in-place, treating all files as a single input stream]::suffix for backup'
|
'-I+[edit files in-place, treating all files as a single input stream]:: :_guard "^(*[@/; \\\]*|?(#c6,)|-*)" "suffix for backup"'
|
||||||
)
|
)
|
||||||
;;
|
;;
|
||||||
openbsd*) args+=( '-u[make output line buffered]' ) ;;
|
openbsd*) args+=( '-u[make output line buffered]' ) ;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
zstyle -s ":completion:${curcontext}:address-forms" list-separator separator || separator=--
|
||||||
|
step=( "~ $separator step" )
|
||||||
|
negate=( "! $separator negated" )
|
||||||
|
range=( ", $separator range" )
|
||||||
|
mods=( "I $separator case-insensitive" "M $separator multi-line" )
|
||||||
|
|
||||||
|
sedexpr=(
|
||||||
|
\( /$'*\0[ \t\n]#'/ \) # strip off any preceding arguments - handled by _arguments
|
||||||
|
\(
|
||||||
|
# Handle an optional address range
|
||||||
|
\(
|
||||||
|
\(
|
||||||
|
\(
|
||||||
|
'///' '/[^/]#//' ':regexes:regex:' # skip /pattern/
|
||||||
|
\|
|
||||||
|
'/\\(?)/' -'sep=${match#?}' # handle \xpatternx
|
||||||
|
\( '/\?/' \| '/?/' -'[[ $match != $sep ]]' \) \# '/?/' -'[[ $match = $sep ]]' ':regexes:regex:'
|
||||||
|
\)
|
||||||
|
$'/[ \t]#/'
|
||||||
|
\( \| '/[IM]##/' -'dedup=( ${(s..)match} )' ':address-forms:address form:compadd -S "" -d mods -F dedup I M' \) \#
|
||||||
|
\|
|
||||||
|
'/([0-9]##|$)[ \t]#/' # line number
|
||||||
|
\(
|
||||||
|
'/\~[ \t]#/' # addr1~N
|
||||||
|
'/[0-9]##[ \t]#/' ': _message -e steps "number - match where line number is a multiple"'
|
||||||
|
\| '//' ':address-forms:address form:compadd -S "" -d step \~' \)
|
||||||
|
\|
|
||||||
|
'/[]/' ': _guard "^([sy]|[^0-9$/\\\]*)" "address - line number or /pattern/"'
|
||||||
|
\)
|
||||||
|
\( # range end, also optional
|
||||||
|
'/[ \t]#,[ \t]#/' -'excl=( \\\# : )' # exclude comments and labels after ranges
|
||||||
|
\(
|
||||||
|
'///' '/[^/]#//' ':regexes:regex:' # handle /pattern/
|
||||||
|
\|
|
||||||
|
'/\\(?)/' -'sep=${match#?}' # handle \xpatternx
|
||||||
|
\( '/\?/' \| '/?/' -'[[ $match != $sep ]]' \) \# '/?/' -'[[ $match = $sep ]]' ':regexes:regex - 2:'
|
||||||
|
\|
|
||||||
|
'/+[ \t]#/' # addr1,+N
|
||||||
|
'/[0-9]##/' ': _message -e number "number of following lines"'
|
||||||
|
\|
|
||||||
|
'/\~[ \t]#/' # addr1,~N
|
||||||
|
'/[0-9]##/' ': _message -e number "following lines until line number is a multiple of specified number"'
|
||||||
|
\|
|
||||||
|
'/([0-9]##|$)/' # line number
|
||||||
|
\|
|
||||||
|
'/[]/' ': _message -e ranges "ending line - [+~]number, $ or /pattern/"'
|
||||||
|
\)
|
||||||
|
\|
|
||||||
|
'//' -'excl=( \\\# : )' ':address-forms:address form:compadd -S "" -d range ,'
|
||||||
|
\)
|
||||||
|
\(
|
||||||
|
'/!/' ':address-forms:address form:compadd -S "" -d negate !'
|
||||||
|
\| \)
|
||||||
|
\| // -'excl=( \{ )' \) # { ... } is only useful following a range so exclude {
|
||||||
|
|
||||||
|
$'/[ \t]#/' -'(( nest )) || excl+=( \} )' # whitespace + exclude } without preceding {
|
||||||
|
\( # First commands, for which the pattern fully terminates them
|
||||||
|
'/e[ \t]#/' $'/((\\\n|\\[^\n]|[^\\\n])##\n|[\n;])/' ':commands:command:_cmdstring' # GNU extension
|
||||||
|
\|
|
||||||
|
$'/{[ ;\t\n]#/' -'((++nest,1))' # opening brace
|
||||||
|
\|
|
||||||
|
'/\#/' # comments
|
||||||
|
$'/[^\n]##\n[\n; \t]#/' ':comments:comment:'
|
||||||
|
\|
|
||||||
|
$'/[aci]/' # a, c and i commands
|
||||||
|
\(
|
||||||
|
$'/[ \t]#/' -'[[ $variant = gnu && $+opt_args[--posix] = 0 ]]' # GNU allows, e.g. 'c string'
|
||||||
|
\|
|
||||||
|
$'/[ \t]#/' $'/\\\n/' ':newlines:newline:compadd -Q -S "" "$bsnl"'
|
||||||
|
\)
|
||||||
|
$'/(\\\n|\\[^\n]|[^\\\n])##\n[\n; \t]#/' ':strings:string:'
|
||||||
|
\|
|
||||||
|
$'/[RrwW][ \t]#/' $'/[^\n]##\n[\n; \t]#/' ':files:file:_files -S ""'
|
||||||
|
\| # Now commands with shared termination handling
|
||||||
|
\(
|
||||||
|
# branches/labels, GNU sed allows an empty label
|
||||||
|
$'/[:btT][ \t]#/' $'/[^ \t\n;]#/' $'%[ \t\n;]%' -'labels+=( $match )'
|
||||||
|
':labels:label: _wanted -x labels expl label compadd -S "" -a labels'
|
||||||
|
\|
|
||||||
|
'/l/' $'/[ \t]#<->/' ':width:width:'
|
||||||
|
\|
|
||||||
|
'/s(?)/' -'sep=${match#s}' # Substitutions
|
||||||
|
\( '/\\?/' \| '/?/' -'[[ $match != $sep ]]' \) \#
|
||||||
|
'/?/' -'[[ $match = $sep ]]' ':regexes:source regex:'
|
||||||
|
\( '/\\?/' \| '/?/' -'[[ $match != $sep ]]' \) \#
|
||||||
|
'/?/' -'[[ $match = $sep ]]' ':regexes:substitute string (back-references with & and \1 .. \9):'
|
||||||
|
\( # Substitution flags
|
||||||
|
$'/w[ \t]#/' $'/[^\n]##/' $'%\n%' ':files:file:_files -S ""'
|
||||||
|
\|
|
||||||
|
# pass existing flags, building exclusion list from them
|
||||||
|
$'/[gpiImM0-9]#/' -'excl=( ${(s..)${${${match/[iI]/iI}/[mM]/mM}}/e/ew} )'
|
||||||
|
\(
|
||||||
|
'//' -'[[ -z ${excl[(r)[0-9]]} ]]' # exclude if numbers already there
|
||||||
|
'//' '%[^egpiImM0-9]%' ': _message -e numbers "number - substitute nth match"'
|
||||||
|
\|
|
||||||
|
'//' '%[^egpiImM0-9]%' $':flags:flag: _describe -t flags flag substflags -S "" -F excl'
|
||||||
|
\)
|
||||||
|
\)
|
||||||
|
\|
|
||||||
|
'/y(?)/' -'sep=${match#y}' # Character transliterations
|
||||||
|
\( '/\?/' \| '/?/' -'[[ $match != $sep ]]' \) \# '/?/' -'[[ $match = $sep ]]' ':source:source:'
|
||||||
|
\( '/\?/' \| '/?/' -'[[ $match != $sep ]]' \) \# '/?/' -'[[ $match = $sep ]]' ':dest:dest:'
|
||||||
|
\|
|
||||||
|
'/[qQ]/' -'[[ $variant = gnu && $+opt_args[--posix] = 0 ]]'
|
||||||
|
$'/[\t ]#<->/' '%[^0-9]%' ':exit-codes:exit code:'
|
||||||
|
\|
|
||||||
|
'/[=dDFhHgGnNpPqQxz]/' # stand-alone commands that take no argument
|
||||||
|
\( $'/[ \t]#/' $'%[#\n;}]%' \| $'/[ \t]/' '/[]/' ': _message "no arguments"' \| \)
|
||||||
|
\|
|
||||||
|
$'/v[ \t]#/' $'/[^\n;}]#/' $'%[\n;}]%' ':versions:version:'
|
||||||
|
\|
|
||||||
|
$'/}[ \t]#/' -'((--nest,1))' # closing }
|
||||||
|
\|
|
||||||
|
/'[]'/ ':commands:command: _describe -t sed-commands "sed command" cmds_none -S "" -F excl -- cmds_slash -S / -- cmds_end -F excl -r \; -S $nl'
|
||||||
|
\)
|
||||||
|
$'/[ \t]#/'
|
||||||
|
\( $'/}[ \t]#/' -'((--nest,1))' \| \) # closing } is allowed by GNU sed without preceding ; or newline
|
||||||
|
\(
|
||||||
|
'/\#/' $'/[^\n]##\n[\n; \t]#/' ':comments:comment:' # line end comments
|
||||||
|
\|
|
||||||
|
# add in and auto-removable newline if command is terminated
|
||||||
|
$'/[;\n][ ;\t\n]#/' $':separators:separator:compadd -r ";" -S $nl ""'
|
||||||
|
\|
|
||||||
|
$'/{[ \t]#/' -'((++nest,1))' # opening {, keep count of nesting level
|
||||||
|
\)
|
||||||
|
\)
|
||||||
|
\) \#
|
||||||
|
)
|
||||||
|
|
||||||
|
_regex_arguments _sed_expressions "$sedexpr[@]"
|
||||||
|
|
||||||
_arguments -s -S $aopts : "$args[@]"
|
_arguments -s -S $aopts : "$args[@]"
|
||||||
|
|
Loading…
Reference in a new issue