diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Completion/Unix/Command/_darcs | 533 |
2 files changed, 39 insertions, 501 deletions
diff --git a/ChangeLog b/ChangeLog index e006e634d..565ba3543 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-07-02 Peter Stephenson <pws@csr.com> + + * Nicolas Pouillard: 27028: Completion/Unix/Command/_darcs: New + darcs completion; it's a lot shorter but apparently that's OK. + 2009-07-01 Peter Stephenson <pws@csr.com> * 27085: Doc/Zsh/mod_complist.yo, Src/Zle/complist.c: @@ -11890,5 +11895,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.4724 $ +* $Revision: 1.4725 $ ***************************************************** diff --git a/Completion/Unix/Command/_darcs b/Completion/Unix/Command/_darcs index 1d3414e45..d40ecda28 100644 --- a/Completion/Unix/Command/_darcs +++ b/Completion/Unix/Command/_darcs @@ -1,503 +1,36 @@ #compdef darcs - -# EXTENDED_GLOB is required fr pattern backreferences. -setopt EXTENDED_GLOB - -local DARCS=$words[1] - -# test whether to hide short options from completion -autoload -z is-at-least -local hide_short -if zstyle -s ":completion:${curcontext}" hide-shortopts hide_short; then - case $hide_short in - true|yes|on|1) hide_short='!' ;; - *) hide_short='' ;; - esac -else - is-at-least 4.1 || hide_short='!' -fi - - - -_darcs_main() { -# Based on section 6.8 of _A User's Guide to the Z-Shell_ by Peter Stephenson. -# Also based on the tla completion module by Jason McCarty. How do I credit -# this? -local DARCS=$words[1] -local arguments -local curcontext="$curcontext" - -if (( CURRENT > 2 )); then - local cmd=${words[2]} - local var_cmd=cmd_${cmd//-/_} - curcontext="${curcontext%:*:*}:darcs-${cmd}:" - (( CURRENT-- )) - shift words - - local short long arg desc action - short=() - long=() - arg=() - desc=() - action=() - arguments=() - - # Collect all help lines which have a leading space. - local input - input=(${(f)"$($DARCS $cmd -h)"}) - input=(${input:#[^\ ]*}) - local i - for (( i=1 ; i <= ${#input} ; i++ )); do - # Assumption: the the argument descriptions from `darcs cmd -h` - # have the following format: - # [spaces]<-f>[spaces][--flag]<=<spaces>argument>[spaces][description] - [[ "$input[i]" = (#b)' '#(-?|)' '#([^' ']#|)' '#(--[^=' ']#)(=([^' ']#)|)' '#(*) ]] \ - || _message -e messages "cannot parse command help output." || return 1 - - short[i]="$match[1]" - long[i]="$match[3]" - arg[i]="$match[5]" - desc[i]="$match[6]" - desc[i]="${${desc[i]//\[/\\[}//\]/\\]}" # escape brackets - - case $arg[i] in - DIRECTORY) - action[i]='_files -/' ;; - FILE|FILENAME|IDFILE|KEYS) - action[i]='_files' ;; - USERNAME) - action[i]='_users' ;; - EMAIL|FROM) - action[i]='_email_addresses' ;; - URL) - action[i]='_darcs_repository_or_tree' ;; - *) - action[i]='' ;; - esac - done - - # Compute the exludes for _arguments - - local excluded short_excluded long_excluded k - - for (( i=1 ; i <= ${#input} ; i++ )); do - excluded=() - for opt (${=excludes[$long[i]]}); do - k=$long[(i)$opt] - excluded=($excluded $short[k] $long[k]) - done - - # Generate arguments for _arguments. - # Make long and short options mutually exclusive. - short_excluded=($long[i] $excluded) - long_excluded=($short[i] $excluded) - [ $short[i] ] && arguments=("$arguments[@]" - "${hide_short}(${short_excluded})${short[i]}[${desc[i]}]${arg[i]:+:$arg[i]:$action[i]}") - [ $long[i] ] && arguments=("$arguments[@]" - "(${long_excluded})${long[i]}${arg[i]:+=}[${desc[i]}]${arg[i]:+:$arg[i]:$action[i]}") - done - - arguments=("$arguments[@]" "${(@P)var_cmd-*:FILE:_files}") +## Darcs completion snippet for zsh. +## +## Copyright (C) 2009 Nicolas Pouillard +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. + +if (($CURRENT == 2)); then + # We're completing the first word after "darcs" -- the command. + _wanted command expl 'darcs command' \ + compadd -- $( darcs --commands ) else - local hline - local -a cmdlist - _call_program help-commands darcs --help | while read -A hline; do - (( ${#hline} < 2 )) && continue - [[ $hline[1] == darcs ]] && continue - [[ $hline[1] == [A-Z]* ]] && continue - cmdlist=( $cmdlist "${hline[1]}:${hline[2,-1]/(#b)([A-Z])(*)./${match[1]:l}$match[2]}" ) - done - arguments=(':commands:(($cmdlist))') + case "${words[$CURRENT]}"; in + # If it looks like an URL... + ht*|ft*) + _arguments '*:URL:_urls' + ;; + # If it looks like an explicit path... + /*|./*|\~*|../*) + _arguments '*:file:_files' + ;; + # Otherwise, let's ask darcs for all possible options + *) + _wanted args expl 'arg for darcs command' \ + compadd -- $( darcs ${words[2]} --list-option ) + ;; + esac fi - -_arguments -S -A '-*' \ - "$arguments[@]" -} - - - -# -# Command argument definitions -# -local -a cmd_initialize cmd_get -cmd_initialize=() -cmd_get=(':repository:_files -/' ':new repository name:_files -/') - -local -a cmd_add cmd_remove cmd_move cmd_replace -cmd_add=('*:new files:_darcs_new_file_or_tree') -cmd_remove=('*:existing controlled files:_darcs_controlled_files -e') -cmd_move=('*:existing controlled files:_darcs_controlled_files -e') -cmd_replace=(':old token:' ':new token:' '*:existing controlled files:_darcs_controlled_files -e') - -local -a cmd_record cmd_pull cmd_push cmd_send cmd_apply -cmd_record=('*:controlled files:_darcs_controlled_files') -cmd_pull=(':repository:_darcs_repository_or_tree') -cmd_push=(':repository:_darcs_repository_or_tree') -cmd_send=(':repository:_darcs_repository_or_tree') -cmd_apply=(':patch file:_files') - -local -a cmd_whatsnew cmd_changes -cmd_whatsnew=('*:controlled files:_darcs_controlled_files') -cmd_changes=('*:controlled files:_darcs_controlled_files') - -local -a cmd_tag cmd_setpref cmd_check cmd_optimize -cmd_tag=() -cmd_setpref=(':preference key:(test predist boringfile binaries)' ':value:_files') -cmd_check=() -cmd_optimize=() - -local -a cmd_amend_record cmd_rollback cmd_unrecord cmd_unpull cmd_revert cmd_unrevert -cmd_amend_record=('*:controlled files:_darcs_controlled_files') -cmd_rollback=() -cmd_unrecord=() -cmd_unpull=() -cmd_revert=('*:controlled files:_darcs_controlled_files') -cmd_unrevert=() - -local -a cmd_diff cmd_annotate -cmd_diff=('*:controlled files:_darcs_controlled_files') -cmd_annotate=('*:controlled files:_darcs_controlled_files') - -local -a cmd_resolve cmd_dist cmd_trackdown cmd_repair -cmd_resolve=() -cmd_dist=() -cmd_trackdown=(':initialization:' ':command:') -cmd_repair=() - - -# -# Completion functions -# - -(( $+functions[_darcs_new_files] )) || -_darcs_new_files () { - local -a new_files - local -a local_files - local in_tree_head in_tree_tail - _darcs_make_tree_path in_tree_head in_tree_tail || return 1 - new_files=(${(f)"$(cd $(_darcs_absolute_tree_root)/$in_tree_head; $DARCS whatsnew -sl .)"}) - new_files=(${${new_files:#[^a]*}//a /}) - - local_files=() - for file ($new_files); do - [[ $file:h = $in_tree_head && $file:t = ${in_tree_tail}* ]] && local_files+=$file:t - done - - compset -P '*/' - _description new_files expl "new files" - compadd "$expl[@]" "$local_files[@]" -} - - - - -# _darcs_controlled_files [-e|r] [-f|d] -# -# Adds controlled files to the completion. Can take either -# -e or -r as flags which respectively only add the existing -# files or the deleted files. Can take either -f or -d which -# respectively add only the files or directories. -(( $+functions[_darcs_controlled_files] )) || -_darcs_controlled_files() { - local abs_root=$(_darcs_absolute_tree_root) - local only_removed only_existing only_files only_dirs - zparseopts -E \ - 'r=only_removed' 'e=only_existing' \ - 'f=only_files' 'd=only_dirs' - - local in_tree_head in_tree_tail - _darcs_make_tree_path in_tree_head in_tree_tail - local recorded_dir="$abs_root/_darcs/current/$in_tree_head" - local -a controlled_files controlled_dirs existing_files existing_dirs - local -a dir_display_strs removed_dir_display_strs - controlled_files=${(z)$(print $recorded_dir/$in_tree_tail*(.:t))} - controlled_dirs=${(z)$(print $recorded_dir/$in_tree_tail*(/:t))} - existing_files=() existing_dirs=() - removed_files=() removed_dirs=() - dir_display_strs=() removed_dir_display_strs=() - local dir file - for dir ($controlled_dirs); do - if [[ -e $abs_root/$in_tree_head/$dir ]]; then - existing_dirs+="$dir" - dir_display_strs+="$dir/" - else - removed_dirs+="$dir" - removed_dir_display_strs+="$dir/" - fi - done - for file ($controlled_files); do - if [[ -e $abs_root/$in_tree_head/$file ]]; then - existing_files+="$file" - else - removed_files+="$file" - fi - done - - compset -P '*/' - if (( ! ${#only_removed} )); then - _description controlled_files expl "existing revision controlled files" - (( ! ${#only_dirs} )) && compadd "$expl[@]" $existing_files - (( ! ${#only_files} )) \ - && compadd "$expl[@]" -q -S / -d dir_display_strs -a -- existing_dirs - fi - if (( ! ${#only_existing} )); then - _description removed_files expl "removed revision controlled files" - (( ! ${#only_dirs} )) && compadd "$expl[@]" $removed_files - (( ! ${#only_files} )) \ - && compadd "$expl[@]" -q -S / -d removed_dir_display_strs -a -- removed_dirs - fi -} - -(( $+functions[_darcs_repositories] )) || -_darcs_repositories() { - local local_repos_path="$(_darcs_absolute_tree_root)/_darcs/prefs/repos" - local global_repos_path="$HOME/.darcs/repos" - local -a local_repos global_repos - [[ -e $local_repos_path ]] && local_repos=( $(<$local_repos_path) ) - [[ -e $global_repos_path ]] && global_repos=( $(<$global_repos_path) ) - _description repositories expl "repositories" - (( ${#local_repos} )) && compadd "$expl[@]" -- "$local_repos[@]" - (( ${#global_repos} )) && compadd "$expl[@]" -- "$global_repos[@]" -} - - - -# Combination completion functions - -(( $+functions[_darcs_new_file_or_tree] )) || -_darcs_new_file_or_tree() { - local base_dir=$( cd ${$(_darcs_repodir):-.}; pwd -P) - [[ -z $(_darcs_absolute_tree_root $base_dir) ]] && return 1 - local -a ignored_files - ignored_files=(_darcs) - _alternative 'newfiles:new file:_darcs_new_files' \ - "directories:tree:_path_files -/ -W$base_dir -Fignored_files" -} - -(( $+functions[_darcs_repository_or_tree] )) || -_darcs_repository_or_tree() { - local -a ignored_files - ignored_files=(_darcs) - _alternative 'repository:repository:_darcs_repositories' \ - "directories:directories:_path_files -/ -Fignored_files" -} - - -# -# Mutually exclusive options -# - -typeset -A excludes -excludes=( -# Output - --summary '--no-summary' - --no-summary '--summary' - --context ' --xml-output --human-readable --unified' - --xml-output '--context --human-readable --unified' - --human-readable '--context --xml-output --unified' - --unified '--context --xml-output --human-readable ' - -# Verbosity - --verbose ' --quiet --standard-verbosity' - --quiet '--verbose --standard-verbosity' - --standard-verbosity '--verbose --quiet ' - -# Traversal - --recursive '--not-recursive' - --not-recursive '--recursive' - --look-for-adds '--dont-look-for-adds' - --dont-look-for-adds '--look-for-adds' - -# Pattern - --from-match ' --from-patch --from-tag' - --from-patch '--from-match --from-tag' - --from-tag '--from-patch --from-match ' - --to-match ' --to-patch -to-tag' - --to-patch '--to-match -to-tag' - --to-tag '--to-match --to-patch ' - -# Repository Properties - --plain-pristine-tree '--no-pristine-tree' - --no-pristine-tree '--plain-pristine-tree' - --parial '--complete' - --complete '--partial' - --compress '--dont-compress' - --dont-compress '--compress' - --set-default '--no-set-default' - --no-set-default '--set-default' - -# Logs - --edit-long-comment '--skip-long-comment --leave-test-directory' - --skip-long-comment '--edit-long-comment --leave-test-directory' - --prompt-long-comment '--edit-long-comment --skip-long-comment' - -# Security - --sign ' --sign-as --sign-ssl --dont-sign' - --sign-as '--sign --sign-ssl --dont-sign' - --sign-ssl '--sign --sign-as --dont-sign' - --dont-sign '--sign --sign-as --sign-ssl ' - --verify ' --verify-ssl --no-verify' - --verify-ssl '--verify --no-verify' - --no-verify '--verify --verify-ssl ' - --apply-as '--apply-as-myself' - --apply-as-myself '--apply-as' - -# Conflicts - --mark-conflicts '--allow-conflicts --no-resolve-conflicts --dont-allow-conflicts' - --allow-conflicts '--mark-conflicts --no-resolve-conflicts --dont-allow-conflicts' - --no-resolve-conflicts '--mark-conflicts --allow-conflicts --dont-allow-conflicts' - --dont-allow-conflicts '--mark-conflicts --allow-conflicts --no-resolve-conflicts ' - -# Test - --test '--no-test' - --no-test '--test' - --leave-test-directory '--remove-test-directory' - --remove-test-directory '--leave-test-directory' - -# Misc - --force '--no-force' - --no-force '--force' - --ask-deps '--no-ask-deps' - --no-ask-deps '--ask-deps' - --date-trick '--no-date-trick' - --no-date-trick '--date-trick' - --set-scripts-executable '--dont-set-scripts-executable' - --dont-set-scripts-executable '--set-scripts-executable' -) - - - -# -# Utility functions -# - -# _darcs_make_tree_path in_tree_head_name in_tree_tail_name path -# Set in_tree_head_name in_tree_tail_name to the corresponding path -# parts from inside the current darcs tree. -_darcs_make_tree_path () { - [[ -z $3 || $3 = '.' ]] && 3=${PREFIX:-./} - local _in_tree=$(_darcs_path_from_root ${$(_darcs_repodir):-.}/$3) - [[ -z $_in_tree ]] && return 1 - 4='' 5='' - if [[ ${3[-1]} = / ]]; then - 4=$_in_tree - else - 4=$_in_tree:h - [[ $_in_tree:t != . ]] && 5=$_in_tree:t - fi - set -A "$1" "$4" - set -A "$2" "$5" -} - -_darcs_repodir () { - local index=$words[(i)--repodir*] - if (( index < CURRENT )); then - if [[ $words[$index] = --repodir ]]; then - (( index++ )) - print $words[$index] - else - print ${words[$index]#*=} - fi - fi -} - -_darcs_absolute_tree_root () { - local root=$(_darcs_repodir) - [[ -z $root ]] && root=$(pwd -P) - while [[ ! $root -ef / ]]; do - [[ -d $root/_darcs ]] && break - root="$root/.." - done - [[ $root -ef / ]] || print $(cd $root; pwd -P) -} - -_darcs_tree_root () { - local abs=$(_darcs_absolute_tree_root) - local rel=$(_darcs_relative_path $abs $(pwd -P)) - [[ -n $abs ]] && print $rel -} - -# _darcs_paths_from_root name paths -# Sets name to the paths relative to the darcs tree root. -# If no argument is given then the current directory -# is assumed. -_darcs_paths_from_root () { - local name=$1 - abs=$(_darcs_absolute_tree_root) - [[ -z $abs ]] && set -A "$name" && return 1 - shift - 1=${1:=$PWD} - local -a subpaths - _darcs_filter_for_subpaths subpaths $abs $* - local i - for (( i=1; i<=${#subpaths}; i++ )); do - [[ $subpaths[$i] != '.' ]] && subpaths[$i]="./$subpaths[$i]" - done - set -A "$name" "$subpaths[@]" -} - -_darcs_path_from_root() { - local path - _darcs_paths_from_root path $1 - [[ -n $path ]] && print "$path" -} - -# _darcs_filter_for_in_dir name dir paths -# Sets name to the relative paths from dir to the given paths which -# traverse dir. It ignores paths which are not in dir. -_darcs_filter_for_subpaths () { - local name=$1 dir=$2 - shift 2 - local p rel - local -a accepted_paths - accepted_paths=() - for p; do - rel=$(_darcs_path_difference $p $dir) - [[ -n $rel ]] && accepted_paths+="$rel" - done - set -A "$name" "$accepted_paths[@]" -} - -# _darcs_path_difference p1 p2 -# Print the path from p2 to p1. If p2 is not an ancestor of p1 then it -# prints a blank string. If they point to the same directory then it returns -# a single period. p2 needs to be a directory path. -_darcs_path_difference () { - local diff=$(_darcs_relative_path $1 $2) - [[ ${diff%%/*} != .. ]] && print $diff || return 1 -} - - -# Print the a relative path from the second directory to the first, -# defaulting the second directory to $PWD if none is specified. -# Taken from the zsh mailing list. -_darcs_relative_path () { - 2=${2:=$PWD} - [[ -d $2 && -d $1:h ]] || return 1 - [[ ! -d $1 ]] && 3=$1:t 1=$1:h - 1=$(cd $1; pwd -P) - 2=$(cd $2; pwd -P) - [[ $1 -ef $2 ]] && print ${3:-.} && return - - local -a cur abs - cur=(${(s:/:)2}) # Split 'current' directory into cur - abs=(${(s:/:)1} $3) # Split target directory into abs - - # Compute the length of the common prefix, or discover a subdiretory: - integer i=1 - while [[ i -le $#abs && $abs[i] == $cur[i] ]] - do - ((++i > $#cur)) && print ${(j:/:)abs[i,-1]} && return - done - - 2=${(j:/:)cur[i,-1]/*/..} # Up to the common prefix directory and - 1=${(j:/:)abs[i,-1]} # down to the target directory or file - - print $2${1:+/$1} -} - -# Code to make sure _darcs is run when we load it -_darcs_main "$@" - - - |