cmd --- 支持面向行的命令解釋器?

源代碼: Lib/cmd.py


Cmd 類提供簡單框架用于編寫面向行的命令解釋器。 這些通常對測試工具,管理工具和原型有用,這些工具隨后將被包含在更復(fù)雜的接口中。

class cmd.Cmd(completekey='tab', stdin=None, stdout=None)?

一個 Cmd 實(shí)例或子類實(shí)例是面向行的解釋器框架結(jié)構(gòu)。 實(shí)例化 Cmd 本身是沒有充分理由的, 它作為自定義解釋器類的超類是非常有用的為了繼承 Cmd 的方法并且封裝動作方法。

可選參數(shù) completekey 是完成鍵的 readline 名稱;默認(rèn)是 Tab 。如果 completekey 不是 None 并且 readline 是可用的, 命令完成會自動完成。

可選參數(shù) stdinstdout 指定了Cmd實(shí)例或子類實(shí)例將用于輸入和輸出的輸入和輸出文件對象。如果沒有指定,他們將默認(rèn)為 sys.stdinsys.stdout 。

如果你想要使用一個給定的 stdin ,確保將實(shí)例的 use_rawinput 屬性設(shè)置為 False ,否則 stdin 將被忽略。

Cmd 對象?

Cmd 實(shí)例有下列方法:

Cmd.cmdloop(intro=None)?

反復(fù)發(fā)出提示,接受輸入,從收到的輸入中解析出一個初始前綴,并分派給操作方法,將其余的行作為參數(shù)傳遞給它們。

可選參數(shù)是在第一個提示之前發(fā)布的橫幅或介紹字符串(這將覆蓋 intro 類屬性)。

如果 readline 繼承模塊被加載,輸入將自動繼承類似 bash的歷史列表編輯(例如, Control-P 滾動回到最后一個命令, Control-N 轉(zhuǎn)到下一個命令,以 Control-F 非破壞性的方式向右 Control-B 移動光標(biāo),破壞性地等)。

輸入的文件結(jié)束符被作為字符串傳回 'EOF'

解釋器實(shí)例將會識別命令名稱 foo 當(dāng)且僅當(dāng)它有方法 do_foo() 。有一個特殊情況,分派始于字符 '?' 的行到方法 do_help() 。另一種特殊情況,分派始于字符 '!' 的行到方法 do_shell() (如果定義了這個方法)

這個方法將返回當(dāng) postcmd() 方法返回一個真值 。參數(shù) stoppostcmd() 是命令對應(yīng)的返回值 do_*() 的方法。

如果激活了完成,全部命令將會自動完成,并且通過調(diào)用 complete_foo() 參數(shù) text , line, begidx ,和 endidx 完成全部命令參數(shù)。 text 是我們試圖匹配的字符串前綴,所有返回的匹配項(xiàng)必須以它為開頭。 line 是刪除了前導(dǎo)空格的當(dāng)前的輸入行, begidxendidx 是前綴文本的開始和結(jié)束索引。,可以用于根據(jù)參數(shù)位置提供不同的完成。

所有 Cmd 的子類繼承一個預(yù)定義 do_help() 。 這個方法使用參數(shù) 'bar' 調(diào)用, 調(diào)用對應(yīng)的方法 help_bar() ,如果不存在,打印 do_bar() 的文檔字符串,如果可用。沒有參數(shù)的情況下, do_help() 方法會列出所有可用的幫助主題 (即所有具有相應(yīng)的 help_*() 方法或命令的 文檔字符串),也會列舉所有未被記錄的命令。

Cmd.onecmd(str)?

解釋該參數(shù),就好像它是為響應(yīng)提示而鍵入的一樣。 這可能會被覆蓋,但通常不應(yīng)該被覆蓋; 請參閱: precmd()postcmd() 方法,用于執(zhí)行有用的掛鉤。 返回值是一個標(biāo)志,指示解釋器對命令的解釋是否應(yīng)該停止。 如果命令 str 有一個 do_*() 方法,則返回該方法的返回值,否則返回 default() 方法的返回值。

Cmd.emptyline()?

在響應(yīng)提示輸入空行時調(diào)用的方法。如果此方法未被覆蓋,則重復(fù)輸入的最后一個非空命令。

Cmd.default(line)?

當(dāng)命令前綴不能被識別的時候在輸入行調(diào)用的方法。如果此方法未被覆蓋,它將輸出一個錯誤信息并返回。

Cmd.completedefault(text, line, begidx, endidx)?

當(dāng)沒有特定于命令的 complete_*() 方法可用時,調(diào)用此方法完成輸入行。默認(rèn)情況下,它返回一個空列表。

Cmd.columnize(list, displaywidth=80)?

Method called to display a list of strings as a compact set of columns. Each column is only as wide as necessary. Columns are separated by two spaces for readability.

Cmd.precmd(line)?

鉤方法在命令行 line 被解釋之前執(zhí)行,但是在輸入提示被生成和發(fā)出后。這個方法是一個在 Cmd 中的存根;它的存在是為了被子類覆蓋。返回值被用作 onecmd() 方法執(zhí)行的命令; precmd() 的實(shí)現(xiàn)或許會重寫命令或者簡單的返回 line 不變。

Cmd.postcmd(stop, line)?

鉤方法只在命令調(diào)度完成后執(zhí)行。這個方法是一個在 Cmd 中的存根;它的存在是為了子類被覆蓋。 line 是被執(zhí)行的命令行, stop 是一個表示在調(diào)用 postcmd() 之后是否終止執(zhí)行的標(biāo)志;這將作為 onecmd() 方法的返回值。這個方法的返回值被用作與 stop 相關(guān)聯(lián)的內(nèi)部標(biāo)志的新值;返回 false 將導(dǎo)致解釋繼續(xù)。

Cmd.preloop()?

鉤方法當(dāng) cmdloop() 被調(diào)用時執(zhí)行一次。方法是一個在 Cmd 中的存根;它的存在是為了被子類覆蓋。

Cmd.postloop()?

鉤方法在 cmdloop() 即將返回時執(zhí)行一次。這個方法是一個在 Cmd 中的存根;它的存在是為了被子類覆蓋。

Instances of Cmd subclasses have some public instance variables:

Cmd.prompt?

發(fā)出提示以請求輸入。

Cmd.identchars?

接受命令前綴的字符串。

Cmd.lastcmd?

看到最后一個非空命令前綴。

Cmd.cmdqueue?

排隊(duì)的輸入行列表。當(dāng)需要新的輸入時,在 cmdloop() 中檢查 cmdqueue 列表;如果它不是空的,它的元素將被按順序處理,就像在提示符處輸入一樣。

Cmd.intro?

要作為簡介或橫幅發(fā)出的字符串。 可以通過給 cmdloop() 方法一個參數(shù)來覆蓋它。

Cmd.doc_header?

如果幫助輸出具有記錄命令的段落,則發(fā)出頭文件。

Cmd.misc_header?

如果幫助輸出其他幫助主題的部分(即與 do_*() 方法沒有關(guān)聯(lián)的 help_*() 方法),則發(fā)出頭文件。

Cmd.undoc_header?

如果幫助輸出未被記錄命令的部分(即與 help_*() 方法沒有關(guān)聯(lián)的 do_*() 方法),則發(fā)出頭文件。

Cmd.ruler?

用于在幫助信息標(biāo)題的下方繪制分隔符的字符,如果為空,則不繪制標(biāo)尺線。這個字符默認(rèn)是 '=' 。

Cmd.use_rawinput?

這是一個標(biāo)志,默認(rèn)為 true 。如果為 true ,, cmdloop() 使用 input() 先是提示并且閱讀下一個命令;如果為 false , sys.stdout.write()sys.stdin.readline() 被使用。(這意味著解釋器將會自動支持類似于 Emacs的行編輯和命令歷史記錄按鍵操作,通過導(dǎo)入 readline 在支持它的系統(tǒng)上。)

Cmd 例子?

The cmd module is mainly useful for building custom shells that let a user work with a program interactively.

這部分提供了一個簡單的例子來介紹如何使用一部分在 turtle 模塊中的命令構(gòu)建一個 shell 。

基礎(chǔ)的 turtle 命令比如 forward() 被添加進(jìn)一個 Cmd 子類,方法名為 do_forward() 。參數(shù)被轉(zhuǎn)換成數(shù)字并且分發(fā)至 turtle 模塊中。 docstring 是 shell 提供的幫助實(shí)用程序。

例子也包含使用 precmd() 方法實(shí)現(xiàn)基礎(chǔ)的記錄和回放的功能,這個方法負(fù)責(zé)將輸入轉(zhuǎn)換為小寫并且將命令寫入文件。 do_playback() 方法讀取文件并添加記錄命令至 cmdqueue 用于即時回放:

import cmd, sys
from turtle import *

class TurtleShell(cmd.Cmd):
    intro = 'Welcome to the turtle shell.   Type help or ? to list commands.\n'
    prompt = '(turtle) '
    file = None

    # ----- basic turtle commands -----
    def do_forward(self, arg):
        'Move the turtle forward by the specified distance:  FORWARD 10'
        forward(*parse(arg))
    def do_right(self, arg):
        'Turn turtle right by given number of degrees:  RIGHT 20'
        right(*parse(arg))
    def do_left(self, arg):
        'Turn turtle left by given number of degrees:  LEFT 90'
        left(*parse(arg))
    def do_goto(self, arg):
        'Move turtle to an absolute position with changing orientation.  GOTO 100 200'
        goto(*parse(arg))
    def do_home(self, arg):
        'Return turtle to the home position:  HOME'
        home()
    def do_circle(self, arg):
        'Draw circle with given radius an options extent and steps:  CIRCLE 50'
        circle(*parse(arg))
    def do_position(self, arg):
        'Print the current turtle position:  POSITION'
        print('Current position is %d %d\n' % position())
    def do_heading(self, arg):
        'Print the current turtle heading in degrees:  HEADING'
        print('Current heading is %d\n' % (heading(),))
    def do_color(self, arg):
        'Set the color:  COLOR BLUE'
        color(arg.lower())
    def do_undo(self, arg):
        'Undo (repeatedly) the last turtle action(s):  UNDO'
    def do_reset(self, arg):
        'Clear the screen and return turtle to center:  RESET'
        reset()
    def do_bye(self, arg):
        'Stop recording, close the turtle window, and exit:  BYE'
        print('Thank you for using Turtle')
        self.close()
        bye()
        return True

    # ----- record and playback -----
    def do_record(self, arg):
        'Save future commands to filename:  RECORD rose.cmd'
        self.file = open(arg, 'w')
    def do_playback(self, arg):
        'Playback commands from a file:  PLAYBACK rose.cmd'
        self.close()
        with open(arg) as f:
            self.cmdqueue.extend(f.read().splitlines())
    def precmd(self, line):
        line = line.lower()
        if self.file and 'playback' not in line:
            print(line, file=self.file)
        return line
    def close(self):
        if self.file:
            self.file.close()
            self.file = None

def parse(arg):
    'Convert a series of zero or more numbers to an argument tuple'
    return tuple(map(int, arg.split()))

if __name__ == '__main__':
    TurtleShell().cmdloop()

這是一個示例會話,其中 turtle shell 顯示幫助功能,使用空行重復(fù)命令,以及簡單的記錄和回放功能:

Welcome to the turtle shell.   Type help or ? to list commands.

(turtle) ?

Documented commands (type help <topic>):
========================================
bye     color    goto     home  playback  record  right
circle  forward  heading  left  position  reset   undo

(turtle) help forward
Move the turtle forward by the specified distance:  FORWARD 10
(turtle) record spiral.cmd
(turtle) position
Current position is 0 0

(turtle) heading
Current heading is 0

(turtle) reset
(turtle) circle 20
(turtle) right 30
(turtle) circle 40
(turtle) right 30
(turtle) circle 60
(turtle) right 30
(turtle) circle 80
(turtle) right 30
(turtle) circle 100
(turtle) right 30
(turtle) circle 120
(turtle) right 30
(turtle) circle 120
(turtle) heading
Current heading is 180

(turtle) forward 100
(turtle)
(turtle) right 90
(turtle) forward 100
(turtle)
(turtle) right 90
(turtle) forward 400
(turtle) right 90
(turtle) forward 500
(turtle) right 90
(turtle) forward 400
(turtle) right 90
(turtle) forward 300
(turtle) playback spiral.cmd
Current position is 0 0

Current heading is 0

Current heading is 180

(turtle) bye
Thank you for using Turtle