From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19025 invoked from network); 24 Jul 2003 01:21:50 -0000 Received: from sunsite.dk (130.225.247.90) by ns1.primenet.com.au with SMTP; 24 Jul 2003 01:21:50 -0000 Received: (qmail 4041 invoked by alias); 24 Jul 2003 01:21:45 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 18897 Received: (qmail 4032 invoked from network); 24 Jul 2003 01:21:44 -0000 Received: from localhost (HELO sunsite.dk) (127.0.0.1) by localhost with SMTP; 24 Jul 2003 01:21:44 -0000 X-MessageWall-Score: 0 (sunsite.dk) Received: from [194.73.73.176] by sunsite.dk (MessageWall 1.0.8) with SMTP; 24 Jul 2003 1:21:44 -0000 Received: from dial81-131-90-95.in-addr.btopenworld.com ([81.131.90.95] helo=btopenworld.com) by protactinium.btinternet.com with esmtp (Exim 3.22 #23) id 19fUnX-0002C1-00; Thu, 24 Jul 2003 02:21:36 +0100 Message-ID: <3F1F3685.5040005@btopenworld.com> Date: Thu, 24 Jul 2003 02:29:41 +0100 From: Julian Foad User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 X-Accept-Language: en, en-us MIME-Version: 1.0 To: Philip Martin CC: dev@subversion.tigris.org, Sebastien Cevey , Clint Adams , zsh-workers@sunsite.dk Subject: Re: [PATCH] bash_completion: improvement, fixes and tests [was: Re: subversion and programmable completion] References: <20030720162723.GA26506@acolyte.scowler.net> <20030721183359.GA11160@cine7.net> <3F1EE28F.50500@btopenworld.com> <87u19dorwe.fsf@codematters.co.uk> In-Reply-To: <87u19dorwe.fsf@codematters.co.uk> Content-Type: multipart/mixed; boundary="------------000106090109000300090909" --------------000106090109000300090909 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Philip Martin wrote: > Julian Foad writes: > >> # Find the relevant lines; >> # remove brackets and commas; put each word on its own line. >> sed -n -e '1,/^Available subcommands:$/d;/^$/q' \ >> -e 's/[ )]//g;s/[(,]/\n/g;p' | > > $ sed -V | head -1 > GNU sed version 3.02 > $ echo 'x(y' | sed 's/[(,]/\n/g' > xny Oh dear. I don't know why you get that. ~> bash --version GNU bash, version 2.05b.0(1)-release (i586-suse-linux) ~> sed --version | head -1 GNU sed version 3.02.80 ~> echo 'x(y' | sed 's/[(,]/\n/g' x y I get the same under bash, ash-0.2, tcsh-6.12 and zsh-4.0.6 so I don't suppose it's she shell stripping the backslash. But just to check, try ~> echo 's/[(,]/\n/g' | hexdump -C 00000000 73 2f 5b 28 2c 5d 2f 5c 6e 2f 67 0a |s/[(,]/\n/g.| Work-arounds: these all work for me; I'd be interested to know which work for you and which don't. 1. Use "tr" instead of "sed"; unlike sed, its escape sequences are explicitly listed in its man page: ~> tr --version | head -1 tr (textutils) 2.1 ~> echo 'x(y' | tr '(,' '\n' 2. insert a literal newline character after the backslash, instead of 'n'; this is explicitly listed in the manual page: ~> echo 'x(y' | sed 's/[(,]/\ /g' 3. Use numeric escape sequences; these are not mentioned in the manual but work for me: ~> echo 'x(y' | sed 's/[(,]/\o012/g' ~> echo 'x(y' | sed 's/[(,]/\d010/g' ~> echo 'x(y' | sed 's/[(,]/\x0A/g' Attached is a version of bash_completion_test using "tr", which I think is the safest solution. And to keep the patch together, the original bash_completion.diff is also attached and the log message is repeated here: Log message: [[[ Improve and fix bash_completion. Add a script that tests bash_completion, including checking the completion results against the output of "svn help [...]". * tools/client-side/bash_completion (_svn) Recognise "--arg=value" as an alternative to "--arg value" (when excluding options or synonyms that are already present). Fix the list of subcommands and options accepted as a first argument. Fix the lists of options accepted by various subcommands. * tools/client-side/bash_completion_test New file: a shell script that tests bash_completion. ]]] Let me know if there are further problems. - Julian --------------000106090109000300090909 Content-Type: text/plain; name="bash_completion.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="bash_completion.diff" Index: tools/client-side/bash_completion =================================================================== --- tools/client-side/bash_completion (revision 6521) +++ tools/client-side/bash_completion (working copy) @@ -9,26 +9,26 @@ _svn() { - local cur cmds cmdOpts pOpts mOpts rOpts qOpts nOpts optsParam opt + local cur cmds cmdOpts pOpts mOpts rOpts qOpts nOpts optsParam opt optBase COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]} cmds='add cat checkout co cleanup commit ci copy cp delete del \ - remove rm diff di export import info h help list ls log merge \ + remove rm diff di export import info ? h help list ls log merge \ mkdir move mv rename ren propdel pdel propedit pedit pe propget \ pget pg proplist plist pl propset pset ps revert resolve status \ - stat st switch sw update up --version' + stat st switch sw update up' if [[ $COMP_CWORD -eq 1 ]] ; then - COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + COMPREPLY=( $( compgen -W "$cmds -h --help --version" -- $cur ) ) return 0 else # if we're completing for 'svn help' or 'svn h', then just # complete on any valid svn command case ${COMP_WORDS[1]} in help|h|\?) - COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) + COMPREPLY=( $( compgen -W "$cmds -q --quiet" -- $cur ) ) return 0 ;; *) @@ -62,7 +62,7 @@ cmdOpts="$qOpts" ;; add) - cmdOpts="--targets -$nOpts $qOpts" + cmdOpts="--targets $nOpts $qOpts" ;; cat) cmdOpts="$rOpts $pOpts" @@ -89,7 +89,7 @@ cmdOpts="$rOpts $qOpts $pOpts --force" ;; import) - cmdOpts="$mOpts $qOpts $nOpts --targets --editor-cmd $pOpts" + cmdOpts="$mOpts $qOpts $nOpts --editor-cmd $pOpts" ;; info) cmdOpts="--targets -R --recursive" @@ -99,7 +99,7 @@ ;; log) cmdOpts="$rOpts -v --verbose --targets $pOpts --strict \ - --incremental --xml" + --incremental --xml $qOpts" ;; merge) cmdOpts="$rOpts $nOpts $qOpts --force --dry-run --diff3-cmd \ @@ -115,7 +115,8 @@ cmdOpts="$qOpts -R --recursive $rOpts --revprop $pOpts" ;; propedit|pedit|pe) - cmdOpts="$rOpts --revprop --encoding --editor-cmd $pOpts" + cmdOpts="$rOpts --revprop --encoding --editor-cmd $pOpts \ + --force" ;; propget|pget|pg) cmdOpts="-R --recursive $rOpts --revprop --strict $pOpts" @@ -126,7 +127,7 @@ ;; propset|pset|ps) cmdOpts="-F --file $qOpts --targets -R --recursive --revprop \ - --encoding $pOpts" + --encoding $pOpts $rOpts --force" ;; revert) cmdOpts="--targets -R --recursive $qOpts" @@ -139,10 +140,10 @@ --no-ignore" ;; switch|sw) - cmdOpts="--relocate $rOpts $nOpts $qOpts $pOpts" + cmdOpts="--relocate $rOpts $nOpts $qOpts $pOpts --diff3-cmd" ;; update|up) - cmdOpts="$rOpts $nOpts $qOpts $pOpts" + cmdOpts="$rOpts $nOpts $qOpts $pOpts --diff3-cmd" ;; *) ;; @@ -151,11 +152,17 @@ # take out options already given for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do opt=${COMP_WORDS[$i]} + + case $opt in + --*) optBase=${opt/=*/} ;; + -*) optBase=${opt} ;; + esac + cmdOpts=" $cmdOpts " - cmdOpts=${cmdOpts/ ${opt} / } + cmdOpts=${cmdOpts/ ${optBase} / } # take out alternatives - case $opt in + case $optBase in -v) cmdOpts=${cmdOpts/ --verbose / } ;; --verbose) cmdOpts=${cmdOpts/ -v / } ;; -N) cmdOpts=${cmdOpts/ --non-recursive / } ;; --------------000106090109000300090909 Content-Type: text/plain; name="bash_completion_test" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="bash_completion_test" #!/bin/bash # Checks that the "_svn" function defined in the specified "bash_completion" # script produces appropriate lists of completions for various incomplete svn # command lines. if [ ! -f "$1" ] || [ "$2" ]; then echo "Usage: bash_completion_test BASH_COMPLETION_PATHNAME" echo "Tests the specified \"bash_completion\" script," echo "including checking it against the \"svn\" program found in the current PATH." exit 1 fi set -e # Exit on error shopt -s extglob # Execute the script which is to be tested. . "$1" # From the given incomplete svn command, print a space-separated list of # possible completions of the last argument (or of an empty first argument # if no subcommand is given). # Usage: get_svn_completions [SVN-SUBCOMMAND [SVN-OPTION...]] get_svn_completions() { COMP_WORDS=(svn "$@") if [ $# == 0 ]; then COMP_CWORD=1 else COMP_CWORD=$# fi _svn echo -n "${COMPREPLY[*]}" } # Print a failure message, record the failure, and return "false". # Usage: fail MESSAGE fail() { PREFIX="FAIL: " for LINE in "$@"; do echo "$PREFIX$LINE" PREFIX=" " done TESTS_FAILED=1 false } # Check that EXPECTED-WORD is among the completions of the last word in # SVN-COMMAND. SVN-COMMAND is a single argument to this function, split # into multiple arguments when passed to "get_svn_completions()". # Usage: includes SVN-COMMAND EXPECTED-WORD includes() { COMPLETIONS=`get_svn_completions $1` if [[ "$2" != @(${COMPLETIONS// /|}) ]]; then fail "completions of \"svn $1\" should include \"$2\"" \ "(completions: $COMPLETIONS)" fi } excludes() { COMPLETIONS=`get_svn_completions $1` if [[ "$2" == @(${COMPLETIONS// /|}) ]]; then fail "completions of \"svn $1\" should exclude \"$2\"" \ "(completions: $COMPLETIONS)" fi } # Print the valid subcommands for "svn", one per line, sorted. # Usage: get_svn_subcommands get_svn_subcommands() { svn help | # Find the relevant lines. sed -n -e '1,/^Available subcommands:$/d;/^$/q;p' | # Remove brackets and commas; put each word on its own line. tr -d ' )' | tr '(,' '\n' | sort } # Print the valid option switches for "svn SUBCMD", one per line, sorted. # Usage: get_svn_options SUBCMD get_svn_options() { { svn help "$1" | # Find the relevant lines; remove "arg" and description. sed -n -e '1,/^Valid options:$/d;/^ -/!d' \ -e 's/\( arg\)* * : .*//;p' | # Remove brackets; put each word on its own line. tr -d '] ' | tr '[' '\n' # The following options are always accepted but not listed in the help, # nor currently offered as completions. #echo "-h" #echo "--help" } | sort } # The tests. set +e # Do not exit on error TESTS_FAILED= echo "Checking general completion" includes "he" "help" includes "" "?" includes "" "h" includes "" "help" includes "" "-h" includes "" "--help" includes "" "--version" echo "Checking list of subcommands" HELP_SUBCMDS=`get_svn_subcommands | tr "\n" " "` COMPLETION_SUBCMDS=`get_svn_completions | tr " " "\n" | grep -v "^-" | sort | tr "\n" " "` if [ "$HELP_SUBCMDS" != "$COMPLETION_SUBCMDS" ]; then fail "non-option completions for \"svn \" != subcommands accepted" \ " (non-o. cmpl.: $COMPLETION_SUBCMDS)" \ " (svn accepts: $HELP_SUBCMDS)" fi echo "Checking list of options for each subcommand" for SUBCMD in $HELP_SUBCMDS; do HELP_OPTIONS=`get_svn_options $SUBCMD | tr "\n" " "` COMPLETION_OPTIONS=`get_svn_completions $SUBCMD - | tr " " "\n" | sort | tr "\n" " "` if [ "$HELP_OPTIONS" != "$COMPLETION_OPTIONS" ]; then fail "completions for \"svn $SUBCMD -\" != options accepted" \ " (completions: $COMPLETION_OPTIONS)" \ " (svn accepts: $HELP_OPTIONS)" fi done echo "Checking rejection of synonyms" excludes "diff -x -u -" "-x" excludes "diff -x -u --e" "--extensions" excludes "diff --extensions -u -" "--extensions" excludes "diff --extensions -u -" "-x" excludes "diff --extensions=-u -" "-x" if [ $TESTS_FAILED ]; then echo "FAILURE: at least one bash_completion test failed." else echo "All bash_completion tests passed." fi --------------000106090109000300090909--