diff --git a/contrib/mutt b/contrib/mutt index d532258f..3a1ddf77 100644 --- a/contrib/mutt +++ b/contrib/mutt @@ -4,17 +4,50 @@ # a "query" function to retrieve addresses, so that's what we use here. have mutt || have muttng && { + +# @param $1 (cur) Current word to complete _muttaddr() { - _muttaliases - _muttquery + _muttaliases "$1" + _muttquery "$1" - cur=`_get_cword` - COMPREPLY=( "${COMPREPLY[@]}" $( compgen -u -- "$cur" ) ) + COMPREPLY=( "${COMPREPLY[@]}" $( compgen -u -- "$1" ) ) return 0 -} +} # _muttaddr() + +# Find muttrc to use +# @output muttrc filename +_muttrc() +{ + # Search COMP_WORDS for '-F muttrc' or '-Fmuttrc' argument + set -- "${COMP_WORDS[@]}" + while [ $# -gt 0 ]; do + if [ "${1:0:2}" = -F ]; then + if [ ${#1} -gt 2 ]; then + muttrc="$(dequote "${1:2}")" + else + shift + [ "$1" ] && muttrc="$(dequote "$1")" + fi + break + fi + shift + done + + if [ -z "$muttrc" ]; then + [ -f ~/.${muttcmd}/${muttcmd}rc ] && muttrc="~/.${muttcmd}/${muttcmd}rc" + [ -f ~/.${muttcmd}rc ] && muttrc="~/.${muttcmd}rc" + fi + printf "%s" "$muttrc" +} # _muttrc() + + +# Recursively build list of sourced config files +# @param $1 List of config files found so far +# @param $2 Config file to process +# @output List of config files _muttconffiles() { local file sofar @@ -25,24 +58,24 @@ _muttconffiles() while [[ "$1" ]]; do newconffiles=( $(sed -rn 's|^source[[:space:]]+([^[:space:]]+).*$|\1|p' $(eval echo $1) ) ) for file in "${newconffiles[@]}"; do - [[ ! "$file" ]] || [[ "${sofar/ ${file} / }" != "$sofar" ]] && - continue - sofar="$sofar $file" - sofar=" $(eval _muttconffiles \"$sofar\" $file) " + [[ ! "$file" ]] || [[ "${sofar/ ${file} / }" != "$sofar" ]] && + continue + sofar="$sofar $file" + sofar=" $(eval _muttconffiles \"$sofar\" $file) " done shift done echo $sofar -} +} # _muttconffiles() + +# @param $1 (cur) Current word to complete _muttaliases() { - local cur muttrc muttcmd=${COMP_WORDS[0]} + local cur=$1 muttrc muttcmd=${COMP_WORDS[0]} local -a conffiles aliases - cur=`_get_cword =` - [ -f ~/.${muttcmd}/${muttcmd}rc ] && muttrc="~/.${muttcmd}/${muttcmd}rc" - [ -f ~/.${muttcmd}rc ] && muttrc="~/.${muttcmd}rc" + muttrc=$(_muttrc) [ -z "$muttrc" ] && return 0 conffiles=( $(eval _muttconffiles $muttrc $muttrc) ) @@ -53,11 +86,12 @@ _muttaliases() return 0 } + +# @param $1 (cur) Current word to complete _muttquery() { - local cur querycmd muttcmd=${COMP_WORDS[0]} + local cur=$1 querycmd muttcmd=${COMP_WORDS[0]} local -a queryresults - cur=`_get_cword` querycmd="$( $muttcmd -Q query_command | sed -r 's|^query_command=\"(.*)\"$|\1|; s|%s|'$cur'|' )" if [ -z "$cur" -o -z "$querycmd" ]; then @@ -72,15 +106,15 @@ _muttquery() return 0 } + +# @param $1 (cur) Current word to complete _muttfiledir() { - local cur folder spoolfile muttcmd=${COMP_WORDS[0]} - cur=`_get_cword` + local cur=$1 folder muttrc spoolfile muttcmd=${COMP_WORDS[0]} - # This is currently not working so well. Perhaps this function should - # just call _filedir() for the moment. + muttrc=$(_muttrc) if [[ $cur == [=+]* ]]; then - folder="$( $muttcmd -Q folder | sed -r 's|^folder=\"(.*)\"$|\1|' )" + folder="$( $muttcmd -F "$muttrc" -Q folder | sed -r 's|^folder=\"(.*)\"$|\1|' )" : folder:=~/Mail # Match any file in $folder beginning with $cur @@ -89,20 +123,21 @@ _muttfiledir() COMPREPLY=( ${COMPREPLY[@]#$folder/} ) return 0 elif [ "$cur" == !* ]; then - spoolfile="$( $muttcmd -Q spoolfile | \ + spoolfile="$( $muttcmd -F "$muttrc" -Q spoolfile | \ sed -r 's|^spoolfile=\"(.*)\"$|\1|' )" [ ! -z "$spoolfile" ] && eval cur="${cur/^!/$spoolfile}"; fi _filedir return 0 -} +} # _muttfiledir + _mutt() { local cur prev - cur=`_get_cword` - prev=${COMP_WORDS[COMP_CWORD-1]} + cur=`_get_cword =+!` + prev=`_get_pword =+!` COMPREPLY=() @@ -115,27 +150,26 @@ _mutt() *) case "$prev" in -@(a|f|F|H|i)) - _muttfiledir + _muttfiledir "$cur" return 0 ;; -A) - _muttaliases + _muttaliases "$cur" return 0 ;; -@(e|m|Q|s|h|p|R|v|y|z|Z)) return 0 ;; *) - _muttaddr + _muttaddr "$cur" return 0 ;; esac ;; esac - -} +} # _mutt() complete -F _mutt -o default -o filenames mutt muttng -} +} # have mutt # Local variables: # mode: shell-script diff --git a/test/fixtures/mutt/bar/.gitignore b/test/fixtures/mutt/bar/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/fixtures/mutt/foo/.gitignore b/test/fixtures/mutt/foo/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/fixtures/mutt/muttrc b/test/fixtures/mutt/muttrc new file mode 100644 index 00000000..58ad7f55 --- /dev/null +++ b/test/fixtures/mutt/muttrc @@ -0,0 +1,3 @@ +set folder=. +alias a1 a1@example.com +alias a2 a2@example.com diff --git a/test/lib/completions/mutt.exp b/test/lib/completions/mutt.exp index e683f471..6c727daf 100644 --- a/test/lib/completions/mutt.exp +++ b/test/lib/completions/mutt.exp @@ -4,7 +4,7 @@ proc setup {} { proc teardown {} { - assert_env_unmodified + assert_env_unmodified {/OLDPWD=/d} }; # teardown() @@ -17,4 +17,17 @@ assert_complete_any "mutt -" sync_after_int +set test "mutt should complete mailboxes" +set expected {foo/ bar/ muttrc} +assert_complete_dir $expected "mutt -F muttrc -f =" fixtures/mutt + + +set test "mutt should complete aliases" +set expected {a1 a2} +assert_complete_dir $expected "mutt -F muttrc -A " fixtures/mutt + + +sync_after_int + + teardown diff --git a/test/lib/library.exp b/test/lib/library.exp index 05259d30..a8438c97 100644 --- a/test/lib/library.exp +++ b/test/lib/library.exp @@ -128,7 +128,7 @@ proc assert_complete {expected cmd {test ""} {prompt /@} {size 20}} { } else { # Remove optional (partial) argument from `cmd'. # E.g. "finger test@" becomes "finger" - set cmd2 [lindex [split $cmd] 0] + set cmd2 [lrange [split $cmd] 0 end-1] # Determine common prefix of completions set common [::textutil::string::longestCommonPrefixList $expected] if {[string length $common] > 0} {set common " $common"}