2012-03-05 10 views
10

我已經測試optcompleteoptparse模塊一起使用。它的例子是一個簡單的文件,所以我可以得到這個工作。我還使用​​模塊對其進行了測試,因爲之前的模塊已棄用。但我真的不明白python程序如何以及由誰在tab鍵上調用。我懷疑bash連同shebang行和​​(或optparse)模塊以某種方式參與。我一直在想這個(現在要讀取源代碼)。在bash中,argparse(和不贊成使用的optparse)如何在python程序名後迴應'tab'keypress?

我有一個更復雜的程序結構,它包含一個處理參數的代碼片段的包裝。它的argparse.ArgumentParser()實例化和調用add_argument() - 它們被超級調入另一箇中間模塊以避免重複代碼,並且正在調用它的包裝 - 都在函數內部。

我想了解在bash和python(或者其他任何解釋器如perl)之間使用此選項卡完成的方式。

注意:我對bash完成(我剛纔瞭解到)有一個公正的理解,並且我認爲我理解bash(僅)自定義完成。

注:我看過其他類似的SO問題,並沒有真正回答這個問題:

編輯:Here是bash的功能。
我已經瞭解了Python模塊如何獲得去了解在命令行中輸入的單詞,通過讀取變量

$COMP_WORDS 
$COMP_CWORD 
$COMP_LINE 
$COMP_POINT 
$COMPREPLY 

這些變量os.environ值僅在標籤印刷機具有值。 我的問題是如何觸發python模塊?

+0

'optcomplet'文檔說:「您還需要獲取Bash函數,然後告訴Bash觸發使用它的特定程序的optcomplete完成:」。如果你確實這樣做了,爲什麼你仍然在問它是如何工作的?應該很明顯,你只需要告訴bash在完成請求時要調用哪個程序。 – 2012-03-05 15:17:40

+0

對不起,我誤解了我讀的內容。我會爲此添加一個答案。 – 2012-03-05 17:30:17

回答

14

要了解這裏發生了什麼,讓我們檢查是什麼bash函數實際上做:

COMPREPLY=($(\ 
    COMP_LINE=$COMP_LINE COMP_POINT=$COMP_POINT \ 
    COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ 
    OPTPARSE_AUTO_COMPLETE=1 $1)) 

$1在結束了嗎?這意味着它實際上調用了我們想用特殊環境變量設置執行的Python文件!要跟蹤發生了什麼,讓我們準備一個小腳本攔截什麼optcomplete.autocomplete做:

#!/usr/bin/env python2 
import os, sys 
import optparse, optcomplete 
from cStringIO import StringIO 

if __name__ == '__main__':  
    parser = optparse.OptionParser() 

    parser.add_option('-s', '--simple', action='store_true', 
         help="Simple really simple option without argument.") 

    parser.add_option('-o', '--output', action='store', 
         help="Option that requires an argument.") 

    opt = parser.add_option('-p', '--script', action='store', 
          help="Option that takes python scripts args only.") 
    opt.completer = optcomplete.RegexCompleter('.*\.py') 

    # debug env variables 
    sys.stderr.write("\ncalled with args: %s\n" % repr(sys.argv)) 
    for k, v in sorted(os.environ.iteritems()): 
     sys.stderr.write(" %s: %s\n" % (k, v)) 

    # setup capturing the actions of `optcomplete.autocomplete` 
    def fake_exit(i): 
     sys.stderr.write("autocomplete tried to exit with status %d\n" % i) 
    sys.stdout = StringIO() 
    sys.exit = fake_exit 

    # Support completion for the command-line of this script. 
    optcomplete.autocomplete(parser, ['.*\.tar.*']) 

    sys.stderr.write("autocomplete tried to write to STDOUT:\n") 
    sys.stderr.write(sys.stdout.getvalue()) 
    sys.stderr.write("\n") 

    opts, args = parser.parse_args() 

這給了我們以下的,當我們試圖自動完成它:

$ ./test.py [tab] 
called with args: ['./test.py'] 
    ... 
    COMP_CWORD: 1 
    COMP_LINE: ./test.py 
    COMP_POINT: 10 
    COMP_WORDS: ./test.py 
    ... 
    OPTPARSE_AUTO_COMPLETE: 1 
    ... 
autocomplete tried to exit with status 1 
autocomplete tried to write to STDOUT: 
-o -h -s -p --script --simple --help --output 

所以optcomplete.autocomplete只是讀取環境,準備匹配,將它們寫入STDOUT並退出。然後將結果-o -h -s -p --script --simple --help --output放入bash數組(COMPREPLY=(...))並返回給bash以向用戶顯示選項。沒有魔術參與:)

+0

嘿,非常感謝,事實上,當我閱讀你的評論,並在頁面上獲得鏈接時,我注意到1美元。然後我受到了我已經知道但從未使用過的東西,因爲我從未寫過任何bash腳本 - $ 1是第一個arg.-:S。我之前沒有得到過這一點,真是愚蠢。 – 0xc0de 2012-03-05 18:14:04

+0

對於一個不錯而清晰的例子:) – 0xc0de 2012-03-05 18:16:16

相關問題