Changeset 886
- Timestamp:
- Jun 25, 2010, 7:38:12 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
dasscm/trunk/etc/bash_completion.d/bash_completion_dasscm.sh
r885 r886 1 # Programmable completion for the Subversion svn command under bash. Source 2 # this file (or on some systems add it to ~/.bash_completion and start a new 3 # shell) and bash's completion mechanism will know all about svn's options! 4 # Provides completion for the svnadmin, svndumpfilter, svnlook and svnsync 5 # commands as well. Who wants to read man pages/help text... 1 _dasscm() 2 { 3 COMPREPLY=( $(dasscm complete "${COMP_WORDS[@]:1}") ) 4 return 0 6 5 7 # Known to work with bash 3.* with programmable completion and extended8 # pattern matching enabled (use 'shopt -s extglob progcomp' to enable9 # these if they are not already enabled).10 11 shopt -s extglob12 13 # Tree helper functions which only use bash, to ease readability.14 15 # look for value associated to key from stdin in K/V hash file format16 # val=$(_svn_read_hashfile svn:realmstring < some/file)17 function _svn_read_hashfile()18 {19 local tkey=$1 key= val=20 while true; do21 read tag len22 [ $tag = 'END' ] && break23 [ $tag != 'K' ] && {24 #echo "unexpected tag '$tag' instead of 'K'" >&225 return26 }27 read -r -n $len key ; read28 read tag len29 [ $tag != 'V' ] && {30 #echo "unexpected tag '$tag' instead of 'V'" >&231 return32 }33 read -r -n $len val ; read34 if [[ $key = $tkey ]] ; then35 echo "$val"36 return37 fi38 done39 #echo "target key '$tkey' not found" >&240 6 } 41 42 # _svn_grcut shell-regular-expression 43 # extract filenames from 'svn status' output 44 function _svn_grcut() 45 { 46 local re=$1 line= old_IFS 47 # fix IFS, so that leading spaces are not ignored by next read. 48 # (there is a leading space in svn status output if only a prop is changed) 49 old_IFS="$IFS" 50 IFS=$'\n' 51 while read -r line ; do 52 [[ ! $re || $line == $re ]] && echo "${line/????????/}" 53 done 54 IFS="$old_IFS" 55 } 56 57 # extract stuff from svn info output 58 # _svn_info (URL|Repository Root) 59 function _svn_info() 60 { 61 local what=$1 line= 62 LANG=C LC_MESSAGES=C svn info --non-interactive 2> /dev/null | \ 63 while read line ; do 64 [[ $line == *"$what: "* ]] && echo ${line#*: } 65 done 66 } 67 68 # _svn_lls (dir|file|all) files... 69 # list svn-managed files from list 70 # some 'svn status --all-files' would be welcome here? 71 function _svn_lls() 72 { 73 local opt=$1 f= 74 shift 75 for f in "$@" ; do 76 # could try to check in .svn/entries? hmmm... 77 if [[ $opt == @(dir|all) && -d "$f" ]] ; then 78 echo "$f/" 79 elif [[ $opt == @(file|all) ]] ; then 80 # split f in directory/file names 81 local dn= fn="$f" 82 [[ "$f" == */* ]] && dn=${f%\/*}/ fn=${f##*\/} 83 # ??? this does not work for just added files, because they 84 # do not have a content reference yet... 85 [ -f "${dn}.svn/text-base/${fn}.svn-base" ] && echo "$f" 86 fi 87 done 88 } 89 90 # This completion guides the command/option order along the one suggested 91 # by "svn help", although other syntaxes are allowed. 92 # 93 # - there is a "real" parser to check for what is available and deduce what 94 # can be suggested further. 95 # - the syntax should be coherent with subversion/svn/{cl.h,main.c} 96 # - although it is not a good practice, mixed options and arguments 97 # is supported by the completion as it is by the svn command. 98 # - the completion works in the middle of a line, 99 # but not really in the middle of an argument or option. 100 # - property names are completed: see comments about issues related to handling 101 # ":" within property names although it is a word completion separator. 102 # - unknown properties are assumed to be simple file properties. 103 # - --revprop and --revision options are forced to revision properties 104 # as they are mandatory in this case. 105 # - argument values are suggested to some other options, eg directory names 106 # for --config-dir. 107 # - values for some options can be extended with environment variables: 108 # SVN_BASH_FILE_PROPS: other properties on files/directories 109 # SVN_BASH_REV_PROPS: other properties on revisions 110 # SVN_BASH_ENCODINGS: encodings to be suggested 111 # SVN_BASH_MIME_TYPE: mime types to be suggested 112 # SVN_BASH_KEYWORDS: "svn:keywords" substitutions to be suggested 113 # SVN_BASH_USERNAME: usernames suggested for --username 114 # SVN_BASH_COMPL_EXT: completion extensions for file arguments, based on the 115 # current subcommand, so that for instance only modified files are 116 # suggested for 'revert', only not svn-managed files for 'add', and so on. 117 # Possible values are: 118 # - username: guess usernames from ~/.subversion/auth/... 119 # - svnstatus: use 'svn status' for completion 120 # - recurse: allow recursion (expensive) 121 # - externals: recurse into externals (very expensive) 122 # Both former options are reasonable, but beware that both later options 123 # may be unadvisable if used on large working copies. 124 # None of these costly completions are activated by default. 125 # Argument completion outside a working copy results in an error message. 126 # Filenames with spaces are not completed properly. 127 # 128 # TODO 129 # - other options? 130 # - obsolete options could be removed from auto-comp? (e.g. -N) 131 # - obsolete commands could be removed? (e.g. resolved) 132 # - completion does not work properly when editing in the middle of the line 133 # status/previous are those at the end of the line, not at the entry position 134 _svn() 135 { 136 local cur cmds cmdOpts pOpts mOpts rOpts qOpts nOpts optsParam opt 137 138 COMPREPLY=() 139 cur=${COMP_WORDS[COMP_CWORD]} 140 141 # Possible expansions, without pure-prefix abbreviations such as "up". 142 cmds='add blame annotate praise cat changelist cl checkout co cleanup' 143 cmds="$cmds commit ci copy cp delete remove rm diff export help import" 144 cmds="$cmds info list ls lock log merge mergeinfo mkdir move mv rename" 145 cmds="$cmds propdel pdel propedit pedit propget pget proplist plist" 146 cmds="$cmds propset pset resolve resolved revert status switch unlock" 147 cmds="$cmds update" 148 149 # help options have a strange command status... 150 local helpOpts='--help -h' 151 # all special options that have a command status 152 local specOpts="--version $helpOpts" 153 154 # options that require a parameter 155 # note: continued lines must end '|' continuing lines must start '|' 156 optsParam="-r|--revision|--username|--password|--targets" 157 optsParam="$optsParam|-x|--extensions|-m|--message|-F|--file" 158 optsParam="$optsParam|--encoding|--diff-cmd|--diff3-cmd|--editor-cmd" 159 optsParam="$optsParam|--old|--new|--config-dir|--config-option" 160 optsParam="$optsParam|--native-eol|-l|--limit|-c|--change" 161 optsParam="$optsParam|--depth|--set-depth|--with-revprop" 162 optsParam="$optsParam|--changelist|--accept|--show-revs" 163 164 # svn:* and other (env SVN_BASH_*_PROPS) properties 165 local svnProps revProps allProps psCmds propCmds 166 167 # svn and user configured file properties 168 svnProps="svn:keywords svn:executable svn:needs-lock svn:externals 169 svn:ignore svn:eol-style svn:mime-type $SVN_BASH_FILE_PROPS" 170 171 # svn and user configured revision properties 172 revProps="svn:author svn:log svn:date $SVN_BASH_REV_PROPS" 173 174 # all properties as an array variable 175 allProps=( $svnProps $revProps ) 176 177 # subcommands that expect property names 178 psCmds='propset|pset|ps' 179 propCmds="$psCmds|propget|pget|pg|propedit|pedit|pe|propdel|pdel|pd" 180 181 # Parse arguments and set various variables about what was found. 182 # 183 # cmd: the current command if available 184 # isPropCmd: whether it expects a property name argument 185 # isPsCmd: whether it also expects a property value argument 186 # isHelpCmd: whether it is about help 187 # nExpectArgs: how many arguments are expected by the command 188 # help: help requested about this command (if cmd=='help') 189 # prop: property name (if appropriate) 190 # isRevProp: is it a special revision property 191 # val: property value (if appropriate, under pset) 192 # options: all options encountered 193 # hasRevPropOpt: is --revprop set 194 # hasRevisionOpt: is --revision set 195 # hasRelocateOpt: is --relocate set 196 # hasReintegrateOpt: is --reintegrate set 197 # acceptOpt: the value of --accept 198 # nargs: how many arguments were found 199 # stat: status of parsing at the 'current' word 200 # 201 # prev: previous command in the loop 202 # last: status of last parameter analyzed 203 # i: index 204 local cmd= isPropCmd= isPsCmd= isHelpCmd= nExpectArgs= isCur= i=0 205 local prev= help= prop= val= isRevProp= last='none' nargs=0 stat= 206 local options= hasRevPropOpt= hasRevisionOpt= hasRelocateOpt= 207 local acceptOpt= URL= hasReintegrateOpt= 208 209 for opt in "${COMP_WORDS[@]}" 210 do 211 # get status of current word (from previous iteration) 212 [[ $isCur ]] && stat=$last 213 214 # are we processing the current word 215 isCur= 216 [[ $i -eq $COMP_CWORD ]] && isCur=1 217 let i++ 218 219 # FIRST must be the "svn" command 220 [ $last = 'none' ] && { last='first'; continue ; } 221 222 # SKIP option arguments 223 if [[ $prev == @($optsParam) ]] ; then 224 225 # record accept value 226 [[ $prev = '--accept' ]] && acceptOpt=$opt 227 228 prev='' 229 last='skip' 230 continue ; 231 fi 232 233 # Argh... This looks like a bash bug... 234 # Redirections are passed to the completion function 235 # although it is managed by the shell directly... 236 # It matters because we want to tell the user when no more 237 # completion is available, so it does not necessary 238 # fallback to the default case. 239 if [[ $prev == @(<|>|>>|[12]>|[12]>>) ]] ; then 240 prev='' 241 last='skip' 242 continue ; 243 fi 244 prev=$opt 245 246 # get the subCoMmanD 247 if [[ ! $cmd && $opt \ 248 && ( $opt != -* || $opt == @(${specOpts// /|}) ) ]] 249 then 250 cmd=$opt 251 [[ $cmd == @($propCmds) ]] && isPropCmd=1 252 [[ $cmd == @($psCmds) ]] && isPsCmd=1 253 [[ $cmd == @(${helpOpts// /|}) ]] && cmd='help' 254 [[ $cmd = 'help' ]] && isHelpCmd=1 255 # HELP about a command asked with an option 256 if [[ $isHelpCmd && $cmd && $cmd != 'help' && ! $help ]] 257 then 258 help=$cmd 259 cmd='help' 260 fi 261 last='cmd' 262 continue 263 fi 264 265 # HELP about a command 266 if [[ $isHelpCmd && ! $help && $opt && $opt != -* ]] 267 then 268 help=$opt 269 last='help' 270 continue 271 fi 272 273 # PROPerty name 274 if [[ $isPropCmd && ! $prop && $opt && $opt != -* ]] 275 then 276 prop=$opt 277 [[ $prop == @(${revProps// /|}) ]] && isRevProp=1 278 last='prop' 279 continue 280 fi 281 282 # property VALue 283 if [[ $isPsCmd && $prop && ! $val && $opt != -* ]] ; 284 then 285 val=$opt 286 last='val' 287 continue 288 fi 289 290 if [[ $last != 'onlyarg' ]] 291 then 292 # more OPTions 293 case $opt in 294 -r|--revision|--revision=*) 295 hasRevisionOpt=1 296 ;; 297 --revprop) 298 hasRevPropOpt=1 299 # restrict to revision properties! 300 allProps=( $revProps ) 301 # on revprops, only one URL is expected 302 nExpectArgs=1 303 ;; 304 -h|--help) 305 isHelpCmd=1 306 ;; 307 -F|--file) 308 val='-F' 309 ;; 310 --relocate) 311 hasRelocateOpt=1 312 ;; 313 --reintegrate) 314 hasReintegrateOpt=1 315 ;; 316 esac 317 318 # no more options, only arguments, whatever they look like. 319 if [[ $opt = '--' && ! $isCur ]] ; then 320 last='onlyarg' 321 continue 322 fi 323 324 # options are recorded... 325 if [[ $opt == -* ]] ; then 326 # but not the current one! 327 [[ ! $isCur ]] && options="$options $opt " 328 last='opt' 329 continue 330 fi 331 else 332 # onlyarg 333 let nargs++ 334 continue 335 fi 336 337 # then we have an argument 338 if [[ $cmd = 'merge' && ! $URL ]] ; then 339 # fist argument is the source URL for the merge 340 URL=$opt 341 fi 342 343 last='arg' 344 let nargs++ 345 done 346 # end opt option processing... 347 [[ $stat ]] || stat=$last 348 349 # suggest all subcommands, including special help 350 if [[ ! $cmd || $stat = 'cmd' ]] 351 then 352 COMPREPLY=( $( compgen -W "$cmds $specOpts" -- $cur ) ) 353 return 0 354 fi 355 356 # suggest all subcommands 357 if [[ $stat = 'help' || ( $isHelpCmd && ! $help ) ]] 358 then 359 COMPREPLY=( $( compgen -W "$cmds" -- $cur ) ) 360 return 0 361 fi 362 363 if [[ $cmd = 'merge' || $cmd = 'mergeinfo' ]] 364 then 365 local here=$(_svn_info URL) 366 # suggest a possible URL for merging 367 if [[ ! $URL && $stat = 'arg' ]] ; then 368 # we assume a 'standard' repos with branches and trunk 369 if [[ "$here" == */branches/* ]] ; then 370 # we guess that it is a merge from the trunk 371 COMPREPLY=( $(compgen -W ${here/\/branches\/*/\/trunk} -- $cur ) ) 372 return 0 373 elif [[ "$here" == */trunk* ]] ; then 374 # we guess that it is a merge from a branch 375 COMPREPLY=( $(compgen -W ${here/\/trunk*/\/branches\/} -- $cur ) ) 376 return 0 377 else 378 # no se, let us suggest the repository root... 379 COMPREPLY=( $(compgen -W $(_svn_info Root) -- $cur ) ) 380 return 0 381 fi 382 elif [[ $URL == */branches/* && $here == */trunk* && \ 383 ! $hasReintegrateOpt && $cur = '' && $stat = 'arg' ]] ; then 384 # force --reintegrate only if the current word is empty 385 COMPREPLY=( $(compgen -W '--reintegrate' -- $cur ) ) 386 return 0 387 fi 388 fi 389 390 # help about option arguments 391 if [[ $stat = 'skip' ]] 392 then 393 local previous=${COMP_WORDS[COMP_CWORD-1]} 394 local values= dirs= beep= exes= 395 396 [[ $previous = '--config-dir' ]] && dirs=1 397 398 # external editor, diff, diff3... 399 [[ $previous = --*-cmd ]] && exes=1 400 401 [[ $previous = '--native-eol' ]] && values='LF CR CRLF' 402 403 # just to suggest that a number is expected. hummm. 404 [[ $previous = '--limit' ]] && values='0 1 2 3 4 5 6 7 8 9' 405 406 # some special partial help about --revision option. 407 [[ $previous = '--revision' || $previous = '-r' ]] && \ 408 values='HEAD BASE PREV COMMITTED 0 {' 409 410 [[ $previous = '--encoding' ]] && \ 411 values="latin1 utf8 $SVN_BASH_ENCODINGS" 412 413 [[ $previous = '--extensions' || $previous = '-x' ]] && \ 414 values="--unified --ignore-space-change \ 415 --ignore-all-space --ignore-eol-style" 416 417 [[ $previous = '--depth' ]] && \ 418 values='empty files immediates infinity' 419 420 [[ $previous = '--set-depth' ]] && \ 421 values='empty exclude files immediates infinity' 422 423 [[ $previous = '--accept' ]] && \ 424 { 425 # the list is different for 'resolve' 426 if [[ $cmd = 'resolve' ]] ; then 427 # from svn help resolve 428 values='base working mine-full theirs-full' 429 else # checkout merge switch update 430 # not implemented yet: mine-conflict theirs-conflict 431 values='postpone base mine-full theirs-full edit launch' 432 fi 433 } 434 435 [[ $previous = '--show-revs' ]] && values='merged eligible' 436 437 if [[ $previous = '--username' ]] ; then 438 values="$SVN_BASH_USERNAME" 439 if [[ $SVN_BASH_COMPL_EXT == *username* ]] ; then 440 local file= 441 # digest? others? 442 for file in ~/.subversion/auth/svn.simple/* ; do 443 if [ -r $file ] ; then 444 values="$values $(_svn_read_hashfile username < $file)" 445 fi 446 done 447 fi 448 [[ ! "$values" ]] && beep=1 449 fi 450 451 # could look at ~/.subversion/ ? 452 # hmmm... this option should not exist 453 [[ $previous = '--password' ]] && beep=1 454 455 # TODO: provide help about other options such as: 456 # --old --new --with-revprop 457 458 # if the previous option required a parameter, do something 459 # or fallback on ordinary filename expansion 460 [[ $values ]] && COMPREPLY=( $( compgen -W "$values" -- $cur ) ) 461 [[ $dirs ]] && COMPREPLY=( $( compgen -o dirnames -- $cur ) ) 462 [[ $exes ]] && COMPREPLY=( $( compgen -c -- $cur ) ) 463 [[ $beep ]] && 464 { 465 # 'no known completion'. hummm. 466 echo -en "\a" 467 COMPREPLY=( '' ) 468 } 469 return 0 470 fi 471 472 # provide allowed property names after property commands 473 if [[ $isPropCmd && ( ! $prop || $stat = 'prop' ) && $cur != -* ]] 474 then 475 # 476 # Ok, this part is pretty ugly. 477 # 478 # The issue is that ":" is a completion word separator, 479 # which is a good idea for file:// urls but not within 480 # property names... 481 # 482 # The first idea was to remove locally ":" from COMP_WORDBREAKS 483 # and then put it back in all cases but in property name 484 # completion. It does not always work. There is a strange bug 485 # where one may get "svn:svn:xxx" in some unclear cases. 486 # 487 # Thus the handling is reprogrammed here... 488 # The code assumes that property names look like *:*, 489 # but it also works reasonably well with simple names. 490 local choices= 491 492 if [[ $cur == *:* ]] 493 then 494 # only suggest/show possible suffixes 495 local prefix=${cur%:*} suffix=${cur#*:} c= 496 for c in ${allProps[@]} ; do 497 [[ $c == $prefix:* ]] && choices="$choices ${c#*:}" 498 done 499 # everything will be appended to the prefix because ':' is 500 # a separator, so cur is restricted to the suffix part. 501 cur=$suffix 502 else 503 # only one choice is fine 504 COMPREPLY=( $( compgen -W "${allProps[*]}" -- $cur ) ) 505 [ ${#COMPREPLY[@]} -eq 1 ] && return 0 506 507 # no ':' so only suggest prefixes? 508 local seen= n=0 last= c= 509 for c in ${allProps[@]%:*} ; do 510 # do not put the same prefix twice... 511 if [[ $c == $cur* && ( ! $seen || $c != @($seen) ) ]] 512 then 513 let n++ 514 last=$c 515 choices="$choices $c:" 516 if [[ $seen ]] 517 then 518 seen="$seen|$c*" 519 else 520 seen="$c*" 521 fi 522 fi 523 done 524 525 # supply two choices to force a partial completion and a beep 526 [[ $n -eq 1 ]] && choices="$last:1 $last:2" 527 fi 528 529 COMPREPLY=( $( compgen -W "$choices" -- $cur ) ) 530 return 0 531 fi 532 533 # force mandatory --revprop option on revision properties 534 if [[ $isRevProp && ! $hasRevPropOpt ]] 535 then 536 COMPREPLY=( $( compgen -W '--revprop' -- $cur ) ) 537 return 0 538 fi 539 540 # force mandatory --revision option on revision properties 541 if [[ $isRevProp && $hasRevPropOpt && ! $hasRevisionOpt ]] 542 then 543 COMPREPLY=( $( compgen -W '--revision' -- $cur ) ) 544 return 0 545 fi 546 547 # possible completion when setting property values 548 if [[ $isPsCmd && $prop && ( ! $val || $stat = 'val' ) ]] 549 then 550 # ' is a reminder for an arbitrary value 551 local values="\' --file" 552 case $prop in 553 svn:keywords) 554 # just a subset? 555 values="Id Rev URL Date Author Header \' $SVN_BASH_KEYWORDS" 556 ;; 557 svn:executable|svn:needs-lock) 558 # hmmm... canonical value * is special to the shell. 559 values='\\*' 560 ;; 561 svn:eol-style) 562 values='native LF CR CRLF' 563 ;; 564 svn:mime-type) 565 # could read /etc/mime.types if available. overkill. 566 values="text/ text/plain text/html text/xml text/rtf 567 image/ image/png image/gif image/jpeg image/tiff 568 audio/ audio/midi audio/mpeg 569 video/ video/mpeg video/mp4 570 application/ application/octet-stream 571 $SVN_BASH_MIME_TYPE" 572 ;; 573 esac 574 575 COMPREPLY=( $( compgen -W "$values" -- $cur ) ) 576 # special case for --file... return even if within an option 577 [[ ${COMPREPLY} ]] && return 0 578 fi 579 580 # force mandatory --accept option for 'resolve' command 581 if [[ $cmd = 'resolve' && ! $acceptOpt ]] 582 then 583 COMPREPLY=( $( compgen -W '--accept' -- $cur ) ) 584 # force option now! others will be available on later completions 585 return 0 586 fi 587 588 # maximum number of additional arguments expected in various forms 589 case $cmd in 590 merge) 591 nExpectArgs=3 592 ;; 593 mergeinfo) 594 nExpectArgs=1 595 ;; 596 copy|cp|move|mv|rename|ren|export|import) 597 nExpectArgs=2 598 ;; 599 switch|sw) 600 [[ ! $hasRelocateOpt ]] && nExpectArgs=2 601 ;; 602 help|h) 603 nExpectArgs=0 604 ;; 605 --version) 606 nExpectArgs=0 607 ;; 608 esac 609 610 # the maximum number of arguments is reached for a command 611 if [[ $nExpectArgs && $nargs -gt $nExpectArgs ]] 612 then 613 # some way to tell 'no completion at all'... is there a better one? 614 # Do not say 'file completion' here. 615 echo -en "\a" 616 COMPREPLY=( '' ) 617 return 0 618 fi 619 620 # if not typing an option, 621 # then fallback on filename expansion... 622 if [[ $cur != -* || $stat = 'onlyarg' ]] ; then 623 624 # do we allow possible expensive completion here? 625 if [[ $SVN_BASH_COMPL_EXT == *svnstatus* ]] ; then 626 627 # build status command and options 628 # "--quiet" removes 'unknown' files 629 local status='svn status --non-interactive' 630 631 [[ $SVN_BASH_COMPL_EXT == *recurse* ]] || \ 632 status="$status --non-recursive" 633 634 # I'm not sure that it can work with externals in call cases 635 # the output contains translatable sentences (even with quiet) 636 [[ $SVN_BASH_COMPL_EXT == *externals* ]] || \ 637 status="$status --ignore-externals" 638 639 local cs= files= 640 # subtlety: must not set $cur* if $cur is empty in some cases 641 [[ $cur ]] && cs=$cur* 642 643 # 'files' is set according to the current subcommand 644 case $cmd in 645 st*) # status completion must include all files 646 files=$cur* 647 ;; 648 ci|commit|revert|di*) # anything edited 649 files=$($status $cs| _svn_grcut '@([MADR!]*| M*|_M*)') 650 ;; 651 add) # unknown files 652 files=$($status $cs| _svn_grcut '\?*') 653 ;; 654 unlock) # unlock locked files 655 files=$($status $cs| _svn_grcut '@(??L*|?????[KOTB]*)') 656 ;; 657 resolve*) # files in conflict 658 files=$($status $cs| _svn_grcut '@(?C*|C*)') 659 ;; 660 praise|blame|ann*) # any svn file but added 661 files=$( _svn_lls all $cur* ) 662 ;; 663 p*) # prop commands 664 if [[ $cmd == @($propCmds) && \ 665 $prop == @(svn:ignore|svn:externals) ]] ; then 666 # directory specific props 667 files=$( _svn_lls dir . $cur* ) 668 else 669 # ??? added directories appear twice: foo foo/ 670 files="$( _svn_lls all $cur* ) 671 $($status $cs | _svn_grcut 'A*' )" 672 fi 673 ;; 674 info) # information on any file 675 files="$( _svn_lls all $cur* ) 676 $($status $cs | _svn_grcut 'A*' )" 677 ;; 678 remove|rm|del*|move|mv|rename) # changing existing files 679 files=$( _svn_lls all $cur* ) 680 ;; 681 mkdir) # completion in mkdir can only be for subdirs? 682 files=$( _svn_lls dir $cur* ) 683 ;; 684 log|lock|up*|cl*|switch) # misc, all but added files 685 files=$( _svn_lls all $cur* ) 686 ;; 687 merge) # may do a better job? URL/WCPATH 688 files=$( _svn_lls all $cur* ) 689 ;; 690 ls|list) # better job? what about URLs? 691 files=$( _svn_lls all $cur* ) 692 ;; 693 *) # other commands: changelist export import cat mergeinfo 694 local fallback=1 695 ;; 696 esac 697 698 # when not recursive, some relevant files may exist 699 # within subdirectories, so they are added here. 700 # should it be restricted to svn-managed subdirs? no?? 701 if [[ $SVN_BASH_COMPL_EXT != *recurse* ]] ; then 702 files="$files $( _svn_lls dir $cur* )" 703 fi 704 705 # set completion depending on computed 'files' 706 if [[ $files ]] ; then 707 COMPREPLY=( $( compgen -W "$files" -- $cur ) ) 708 # if empty, set to nope? 709 [[ "${COMPREPLY[*]}" ]] || COMPREPLY=( '' ) 710 elif [[ ! $fallback ]] ; then 711 # this suggests no completion... 712 echo -en "\a" 713 COMPREPLY=( '' ) 714 fi 715 fi 716 # else fallback to ordinary filename completion... 717 return 0 718 fi 719 720 # otherwise build possible options for the command 721 pOpts="--username --password --no-auth-cache --non-interactive" 722 mOpts="-m --message -F --file --encoding --force-log --with-revprop" 723 rOpts="-r --revision" 724 qOpts="-q --quiet" 725 nOpts="-N --non-recursive --depth" 726 gOpts="-g --use-merge-history" 727 728 cmdOpts= 729 case $cmd in 730 --version) 731 cmdOpts="$qOpts" 732 ;; 733 add) 734 cmdOpts="--auto-props --no-auto-props --force --targets \ 735 --no-ignore --parents $nOpts $qOpts $pOpts" 736 ;; 737 blame|annotate|ann|praise) 738 cmdOpts="$rOpts $pOpts -v --verbose --incremental --xml \ 739 -x --extensions --force $gOpts" 740 ;; 741 cat) 742 cmdOpts="$rOpts $pOpts" 743 ;; 744 changelist|cl) 745 cmdOpts="--targets $pOpts $qOpts --changelist \ 746 -R --recursive --depth --remove" 747 ;; 748 checkout|co) 749 cmdOpts="$rOpts $qOpts $nOpts $pOpts --ignore-externals \ 750 --force --accept" 751 ;; 752 cleanup) 753 cmdOpts="--diff3-cmd $pOpts" 754 ;; 755 commit|ci) 756 cmdOpts="$mOpts $qOpts $nOpts --targets --editor-cmd $pOpts \ 757 --no-unlock --changelist --keep-changelists" 758 ;; 759 copy|cp) 760 cmdOpts="$mOpts $rOpts $qOpts --editor-cmd $pOpts --parents" 761 ;; 762 delete|del|remove|rm) 763 cmdOpts="--force $mOpts $qOpts --targets --editor-cmd $pOpts \ 764 --keep-local" 765 ;; 766 diff|di) 767 cmdOpts="$rOpts -x --extensions --diff-cmd --no-diff-deleted \ 768 $nOpts $pOpts --force --old --new --notice-ancestry \ 769 -c --change --summarize --changelist --xml" 770 ;; 771 export) 772 cmdOpts="$rOpts $qOpts $pOpts $nOpts --force --native-eol \ 773 --ignore-externals" 774 ;; 775 help|h|\?) 776 cmdOpts= 777 ;; 778 import) 779 cmdOpts="--auto-props --no-auto-props $mOpts $qOpts $nOpts \ 780 --no-ignore --editor-cmd $pOpts --force" 781 ;; 782 info) 783 cmdOpts="$pOpts $rOpts --targets -R --recursive --depth \ 784 --incremental --xml --changelist" 785 ;; 786 list|ls) 787 cmdOpts="$rOpts -v --verbose -R --recursive $pOpts \ 788 --incremental --xml --depth" 789 ;; 790 lock) 791 cmdOpts="-m --message -F --file --encoding --force-log \ 792 --targets --force $pOpts" 793 ;; 794 log) 795 cmdOpts="$rOpts -v --verbose --targets $pOpts --stop-on-copy \ 796 --incremental --xml $qOpts -l --limit -c --change \ 797 $gOpts --with-all-revprops --with-revprop" 798 ;; 799 merge) 800 cmdOpts="$rOpts $nOpts $qOpts --force --dry-run --diff3-cmd \ 801 $pOpts --ignore-ancestry -c --change -x --extensions \ 802 --record-only --accept --reintegrate" 803 ;; 804 mergeinfo) 805 cmdOpts="$rOpts $pOpts --show-revs" 806 ;; 807 mkdir) 808 cmdOpts="$mOpts $qOpts --editor-cmd $pOpts --parents" 809 ;; 810 move|mv|rename|ren) 811 cmdOpts="$mOpts $rOpts $qOpts --force --editor-cmd $pOpts \ 812 --parents" 813 ;; 814 propdel|pdel|pd) 815 cmdOpts="$qOpts -R --recursive $rOpts $pOpts --changelist \ 816 --depth" 817 [[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop" 818 ;; 819 propedit|pedit|pe) 820 cmdOpts="--editor-cmd $pOpts $mOpts --force" 821 [[ $isRevProp || ! $prop ]] && \ 822 cmdOpts="$cmdOpts --revprop $rOpts" 823 ;; 824 propget|pget|pg) 825 cmdOpts="-v --verbose -R --recursive $rOpts --strict $pOpts --changelist \ 826 --depth --xml" 827 [[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop" 828 ;; 829 proplist|plist|pl) 830 cmdOpts="-v --verbose -R --recursive $rOpts --revprop $qOpts \ 831 $pOpts --changelist --depth --xml" 832 ;; 833 propset|pset|ps) 834 cmdOpts="$qOpts --targets -R --recursive \ 835 --encoding $pOpts --force --changelist --depth" 836 [[ $isRevProp || ! $prop ]] && \ 837 cmdOpts="$cmdOpts --revprop $rOpts" 838 [[ $val ]] || cmdOpts="$cmdOpts -F --file" 839 ;; 840 resolve) 841 cmdOpts="--targets -R --recursive $qOpts $pOpts --accept \ 842 --depth" 843 ;; 844 resolved) 845 cmdOpts="--targets -R --recursive $qOpts $pOpts --depth" 846 ;; 847 revert) 848 cmdOpts="--targets -R --recursive $qOpts --changelist \ 849 --depth $pOpts" 850 ;; 851 status|stat|st) 852 cmdOpts="-u --show-updates -v --verbose $nOpts $qOpts $pOpts \ 853 --no-ignore --ignore-externals --incremental --xml \ 854 --changelist" 855 ;; 856 switch|sw) 857 cmdOpts="--relocate $rOpts $nOpts $qOpts $pOpts --diff3-cmd \ 858 --force --accept --ignore-externals --set-depth" 859 ;; 860 unlock) 861 cmdOpts="--targets --force $pOpts" 862 ;; 863 update|up) 864 cmdOpts="$rOpts $nOpts $qOpts $pOpts --diff3-cmd \ 865 --ignore-externals --force --accept --changelist \ 866 --editor-cmd --set-depth" 867 ;; 868 *) 869 ;; 870 esac 871 872 # add options that are nearly always available 873 [[ "$cmd" != "--version" ]] && cmdOpts="$cmdOpts $helpOpts" 874 cmdOpts="$cmdOpts --config-dir --config-option" 875 876 # --accept (edit|launch) incompatible with --non-interactive 877 if [[ $acceptOpt == @(edit|launch) ]] ; 878 then 879 cmdOpts=${cmdOpts/ --non-interactive / } 880 fi 881 882 # take out options already given 883 for opt in $options 884 do 885 local optBase 886 887 # remove leading dashes and arguments 888 case $opt in 889 --*) optBase=${opt/=*/} ;; 890 -*) optBase=${opt:0:2} ;; 891 esac 892 893 cmdOpts=" $cmdOpts " 894 cmdOpts=${cmdOpts/ ${optBase} / } 895 896 # take out alternatives and mutually exclusives 897 case $optBase in 898 -v) cmdOpts=${cmdOpts/ --verbose / } ;; 899 --verbose) cmdOpts=${cmdOpts/ -v / } ;; 900 -N) cmdOpts=${cmdOpts/ --non-recursive / } ;; 901 --non-recursive) cmdOpts=${cmdOpts/ -N / } ;; 902 -R) cmdOpts=${cmdOpts/ --recursive / } ;; 903 --recursive) cmdOpts=${cmdOpts/ -R / } ;; 904 -x) cmdOpts=${cmdOpts/ --extensions / } ;; 905 --extensions) cmdOpts=${cmdOpts/ -x / } ;; 906 -q) cmdOpts=${cmdOpts/ --quiet / } ;; 907 --quiet) cmdOpts=${cmdOpts/ -q / } ;; 908 -h) cmdOpts=${cmdOpts/ --help / } ;; 909 --help) cmdOpts=${cmdOpts/ -h / } ;; 910 -l) cmdOpts=${cmdOpts/ --limit / } ;; 911 --limit) cmdOpts=${cmdOpts/ -l / } ;; 912 -r) cmdOpts=${cmdOpts/ --revision / } ;; 913 --revision) cmdOpts=${cmdOpts/ -r / } ;; 914 -c) cmdOpts=${cmdOpts/ --change / } ;; 915 --change) cmdOpts=${cmdOpts/ -c / } ;; 916 --auto-props) cmdOpts=${cmdOpts/ --no-auto-props / } ;; 917 --no-auto-props) cmdOpts=${cmdOpts/ --auto-props / } ;; 918 -g) cmdOpts=${cmdOpts/ --use-merge-history / } ;; 919 --use-merge-history) 920 cmdOpts=${cmdOpts/ -g / } ;; 921 -m|--message|-F|--file) 922 cmdOpts=${cmdOpts/ --message / } 923 cmdOpts=${cmdOpts/ -m / } 924 cmdOpts=${cmdOpts/ --file / } 925 cmdOpts=${cmdOpts/ -F / } 926 ;; 927 esac 928 929 # remove help options within help subcommand 930 if [ $isHelpCmd ] ; then 931 cmdOpts=${cmdOpts/ -h / } 932 cmdOpts=${cmdOpts/ --help / } 933 fi 934 done 935 936 # provide help about available options 937 COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) ) 938 return 0 939 } 940 complete -F _svn -o default -X '@(*/.svn|*/.svn/|.svn|.svn/)' dasscm 941 7 complete -F _dasscm dasscm
Note:
See TracChangeset
for help on using the changeset viewer.