Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

This question already has an answer here:

I wrote two functions push and pull to copy files to and from a directory ($FILE_EXCHANGE_DIR). I want bash to autocomplete names from that directory when I use the pull function. I want the autocompletion to only take names from the said directory. In the current form, my autocompletion also finds names of the files in the current directory, regardless of whether there was a match in the source dir ($FILE_EXCHANGE_DIR) or not.

Here are two versions of the function I passed to complete. Neither of them worked.

_pull () {
    local cmd="${1##*/}";
    local word=${COMP_WORDS[COMP_CWORD]};
    local line=${COMP_LINE};
    filelist=( $(ls ${FILE_EXCHANGE_DIR} ) )

    local TEMP_COMPREPLY=( $(compgen -W "${filelist[@]}" -- ${word} ) )

    COMPREPLY=( "${TEMP_COMPREPLY[@]}" )
    return 0;
}

_pull () 
{
    local word=${COMP_WORDS[COMP_CWORD]};
    local line=${COMP_LINE};
    local pat="$FILE_EXCHANGE_DIR/*"

    COMPREPLY=($(compgen -f -G "$pat" -- "$FILE_EXCHANGE_DIR/${word}"));

    i=0
    for item in "${COMPREPLY[@]}"; do
        COMPREPLY[$i]="${item##*/}"
        i+=1
    done;
    return 0;
}

In the end, I do

complete -f -F _pull pull

Is there a good way of completing names only from one directory (that is not the current one) and not from current? Even in the case when there was no match in the source (which should default to readline default completion?

share|improve this question

marked as duplicate by Anthon, slm, jasonwryan, Gilles, terdon Jan 13 at 0:59

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

add comment

1 Answer

up vote 3 down vote accepted

If I understand correctly, this should be what you're looking for:

_pull () {
    # Set
    IFS=$'\n' tmp=( $(compgen -W "$(ls "$FILE_EXCHANGE_DIR")" -- "${COMP_WORDS[$COMP_CWORD]}" ))
    COMPREPLY=( "${tmp[@]// /\ }" )
}
complete -o default -F _pull pull

It even escapes spaces in file names.

Note that -o default completes with readline's default, but that doesn't seem to actually be anything unless you set it explicitly somewhere (.initrc?). If you want file names, use -o filenames or stick with -f.

share|improve this answer
    
More or less. You need to include the -1 option to ls so that the newline works as a separator. In this form, there is still completion from the current directory if there is a match (say, I type a<tab><tab> and it completes the names from the directory I want but also from the current dir if there are files that match the pattern) and it does the same thing that my previous version did (although this is a briefer version). Is there any way to switch that off or do I just have to live with it? –  Wojtek Rzepala Mar 17 '12 at 14:08
    
@WojtekRzepala You don't need -1, it's automatic when it's not writing straight to the screen. And I swear it was working properly on my work machine, but it's not at home, I'm looking into it. –  Kevin Mar 17 '12 at 15:56
    
Never mind about it not working at home, retyped it wrong. It's working fine for me. I put "in_right" in the correct directory, "in_wrong" in my current directory, and when I type "in<tab>", it completes "in_right"; when I remove "in_right" it completes "in_wrong". Double check you sourced the function and set the completion properly. Otherwise, what system and bash version are you using? –  Kevin Mar 17 '12 at 16:07
    
turns out my main problem was sticking in the -f option everywhere. That one completed filenames from the current directory as well, which wasn't clear from the manuals and which I didn't want. –  Wojtek Rzepala Mar 19 '12 at 20:45
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.