2013-04-07 57 views
3

我添加了一個新的別名scp_using_rsync,它使用rsync通過SSH將文件複製到特定選項。我想把scp的bash完成連接到這個別名。bash完成 - 在第一次調用命令時定義的完成功能

它的工作原理,當我加入這一行:

complete -o bashdefault -o default -o nospace -F _scp scp_using_rsync 2>/dev/null || complete -o default -o nospace -F _scp scp_using_rsync 

唯一的問題是,我注意到,_scp獲取我的bash環境中定義,只有當我嘗試至少一次製表完成與SSH/SCP那個外殼。所以如果我直接在新shell中運行scp_using_rsync,我會得到_scp找不到的錯誤。

typeset -F在之前一個新的外殼,並試圖爲ssh或scp命令選項卡完成後,該輸出清楚地表明瞭以下功能在嘗試首次製表完成後定義:

$ diff ~/.scratch/file1 ~/.scratch/file2 
224a225,227 
> declare -f _scp 
> declare -f _scp_local_files 
> declare -f _scp_remote_files 
226a230 
> declare -f _sftp 
230a235,240 
> declare -f _ssh 
> declare -f _ssh_ciphers 
> declare -f _ssh_macs 
> declare -f _ssh_options 
> declare -f _ssh_suboption 
> declare -f _ssh_suboption_check 

這些功能似乎在我的系統中定義在/usr/share/bash-completion/completions/ssh

這是我的2間相關的問題:

  • 如何bash的身影從哪裏自動拾取的定義,並定義它們的時候完成的嘗試,第一次?
  • 我應該如何將scp_using_rsync的bash完成以類似的方式鏈接到scp的bash完成?

回答

5

Bash 4.1增加了一個新-D選項completecompgencompopt

新完整/ compgen/compopt -D選項來定義一個'默認」完成: 完成時要調用上沒有完成的命令 定義爲。如果這個函數返回,可編程完成是 再次嘗試,允許用戶動態地建立了一套完井 作爲完成由具有默認完成函數 安裝個別完成功能每次被調用時嘗試。

有從bash的手冊的例子:

_completion_loader() 
{ 
    . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124 
} 
complete -D -F _completion_loader 
+0

鏈接到bash的手冊:[Programmable Completion](http:// www。 gnu.org/software/bash/manual/bashref.html#Programmable-Completion) – pynexj 2013-04-07 05:14:30

+0

哇!不知道bash有一個選項可以即時加載新的完成。你是對的,我看到'/ usr/share/bash-completion/bash_completion'中定義了'_completion_loader()'函數,這似乎是源於'/ usr/share/bash-completion/bash_completion'中的所有文件,因此ssh/scp的完成會被加載。甜! :)我認爲對於我的用例,我會覆蓋並定義自己的完成加載器來定義預期的完成,然後在bash完成中調用它。 – Tuxdude 2013-04-07 05:16:45

2

我不得不申請whjm的答案的問題。正如Tuxdude注意到的那樣,在我的發行版(Ubuntu 14.04)中已經定義了一個函數​​。該函數的定義如下:

_completion_loader() 
{ 
    local compfile=./completions; 
    [[ $BASH_SOURCE == */* ]] && compfile="${BASH_SOURCE%/*}/completions"; 
    compfile+="/${1##*/}"; 
    [[ -f "$compfile" ]] && . "$compfile" &> /dev/null && return 124; 
    complete -F _minimal "$1" && return 124 
} 

我想讓保持完井所有的維護在一個地方,所以我加了一個文件/usr/share/bash-completion/completions/與我想添加完成的命令的名稱。對於你的情況,你可以添加一個名爲scp_using_rsync文件,其中包含此:

cfile="${compfile%/*}/scp" 
cmd="${1##*/}" 
. "$cfile" 
complete -F _scp $cmd 

這將來源,定義補全文件scp,包括_scp功能,然後添加完成你的命令。我覺得這是一個更直接和一致的方式(雖然當然要做到這一點,但您必須爲所有用戶更改此行爲。)