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

源代碼: Lib/cmd.py


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

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

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

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

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

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

Cmd 對(duì)象?

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

Cmd.cmdloop(intro=None)?

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

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

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

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

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

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

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

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

Cmd.onecmd(str)?

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

Cmd.emptyline()?

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

Cmd.default(line)?

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

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

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

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ā)出后。這個(gè)方法是一個(gè)在 Cmd 中的存根;它的存在是為了被子類(lèi)覆蓋。返回值被用作 onecmd() 方法執(zhí)行的命令; precmd() 的實(shí)現(xiàn)或許會(huì)重寫(xiě)命令或者簡(jiǎn)單的返回 line 不變。

Cmd.postcmd(stop, line)?

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

Cmd.preloop()?

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

Cmd.postloop()?

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

Instances of Cmd subclasses have some public instance variables:

Cmd.prompt?

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

Cmd.identchars?

接受命令前綴的字符串。

Cmd.lastcmd?

看到最后一個(gè)非空命令前綴。

Cmd.cmdqueue?

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

Cmd.intro?

要作為簡(jiǎn)介或橫幅發(fā)出的字符串。 可以通過(guò)給 cmdloop() 方法一個(gè)參數(shù)來(lái)覆蓋它。

Cmd.doc_header?

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

Cmd.misc_header?

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

Cmd.undoc_header?

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

Cmd.ruler?

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

Cmd.use_rawinput?

這是一個(gè)標(biāo)志,默認(rèn)為 true 。如果為 true ,, cmdloop() 使用 input() 先是提示并且閱讀下一個(gè)命令;如果為 false , sys.stdout.write()sys.stdin.readline() 被使用。(這意味著解釋器將會(huì)自動(dòng)支持類(lèi)似于 Emacs的行編輯和命令歷史記錄按鍵操作,通過(guò)導(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.

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

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

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

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()

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

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