cmd --- Hỗ trợ trình thông dịch lệnh hướng dòng

Source code: Lib/cmd.py


Lớp Cmd cung cấp một khung đơn giản để viết trình thông dịch lệnh hướng dòng. Chúng thường hữu ích cho việc khai thác thử nghiệm, công cụ quản trị và nguyên mẫu mà sau này sẽ được gói gọn trong một giao diện phức tạp hơn.

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

Một phiên bản Cmd hoặc phiên bản lớp con là một khung trình thông dịch hướng dòng. Không có lý do chính đáng nào để tự khởi tạo Cmd; đúng hơn, nó hữu ích như một siêu lớp của lớp trình thông dịch mà bạn tự xác định để kế thừa các phương thức của Cmd và đóng gói các phương thức hành động.

Đối số tùy chọn completekey là tên readline của khóa hoàn thành; nó mặc định là Tab. Nếu completekey không phải là Nonereadline có sẵn, việc hoàn thành lệnh sẽ được thực hiện tự động.

Mặc định, 'tab', được xử lý đặc biệt để nó đề cập đến khóa Tab trên mỗi readline.backend. Cụ thể, nếu readline.backendeditline thì Cmd sẽ sử dụng '^I' thay vì 'tab'. Lưu ý rằng các giá trị khác không được xử lý theo cách này và có thể chỉ hoạt động với một chương trình phụ trợ cụ thể.

Các đối số tùy chọn stdinstdout chỉ định các đối tượng tệp đầu vào và đầu ra mà cá thể Cmd hoặc cá thể lớp con sẽ sử dụng cho đầu vào và đầu ra. Nếu không được chỉ định, chúng sẽ mặc định là sys.stdinsys.stdout.

Nếu bạn muốn sử dụng một stdin nhất định, hãy đảm bảo đặt thuộc tính use_rawinput của phiên bản thành False, nếu không stdin sẽ bị bỏ qua.

Thay đổi trong phiên bản 3.13: completekey='tab' được thay thế bằng '^I' cho editline.

Đối tượng Cmd

Một phiên bản Cmd có các phương thức sau:

Cmd.cmdloop(intro=None)

Liên tục đưa ra lời nhắc, chấp nhận đầu vào, phân tích tiền tố ban đầu khỏi đầu vào nhận được và gửi đến các phương thức hành động, chuyển cho chúng phần còn lại của dòng làm đối số.

Đối số tùy chọn là một biểu ngữ hoặc chuỗi giới thiệu sẽ được đưa ra trước lời nhắc đầu tiên (điều này sẽ ghi đè thuộc tính lớp intro).

Nếu mô-đun readline được tải, đầu vào sẽ tự động kế thừa tính năng chỉnh sửa danh sách lịch sử giống như bash- (ví dụ: Control-P cuộn trở lại lệnh cuối cùng, Control-N chuyển tiếp sang lệnh tiếp theo, Control-F di chuyển con trỏ sang phải không phá hủy, Control-B di chuyển con trỏ sang trái không phá hủy, v.v.).

Phần cuối của tệp ở đầu vào được trả về dưới dạng chuỗi 'EOF'.

Một phiên bản trình thông dịch sẽ nhận ra tên lệnh foo khi và chỉ khi nó có phương thức do_foo(). Trong trường hợp đặc biệt, một dòng bắt đầu bằng ký tự '?' được gửi đến phương thức do_help(). Trong một trường hợp đặc biệt khác, một dòng bắt đầu bằng ký tự '!' được gửi đến phương thức do_shell() (nếu phương thức đó được xác định).

Phương thức này sẽ trả về khi phương thức postcmd() trả về giá trị true. Đối số stop cho postcmd() là giá trị trả về từ phương thức do_*() tương ứng của lệnh.

Nếu tính năng hoàn thành được bật, việc hoàn thành các lệnh sẽ được thực hiện tự động và việc hoàn thành các lệnh đối số được thực hiện bằng cách gọi complete_foo() với các đối số text, line, begidxendidx. text là tiền tố chuỗi mà chúng tôi đang cố gắng so khớp: tất cả các kết quả khớp được trả về phải bắt đầu bằng nó. line là dòng đầu vào hiện tại đã loại bỏ khoảng trắng ở đầu, begidxendidx là chỉ mục bắt đầu và kết thúc của văn bản tiền tố, có thể được sử dụng để cung cấp cách hoàn thành khác nhau tùy thuộc vào vị trí của đối số.

Cmd.do_help(arg)

Tất cả các lớp con của Cmd đều kế thừa do_help() được xác định trước. Phương thức này, được gọi với đối số 'bar', gọi phương thức tương ứng help_bar() và nếu phương thức đó không xuất hiện, hãy in chuỗi tài liệu của do_bar(), nếu có. Không có đối số, do_help() liệt kê tất cả các chủ đề trợ giúp có sẵn (nghĩa là tất cả các lệnh có phương thức help_*() tương ứng hoặc các lệnh có chuỗi tài liệu) và cũng liệt kê mọi lệnh không có tài liệu.

Cmd.onecmd(str)

Diễn giải đối số như thể nó được gõ để đáp lại lời nhắc. Điều này có thể được ghi đè, nhưng thông thường không cần phải như vậy; xem các phương thức precmd()postcmd() để biết các hook thực thi hữu ích. Giá trị trả về là một cờ cho biết liệu trình thông dịch có nên dừng việc giải thích các lệnh hay không. Nếu có một phương thức do_*() cho lệnh str, thì giá trị trả về của phương thức đó sẽ được trả về, nếu không thì giá trị trả về từ phương thức default() sẽ được trả về.

Cmd.emptyline()

Phương thức được gọi khi một dòng trống được nhập vào để phản hồi lời nhắc. Nếu phương thức này không bị ghi đè, nó sẽ lặp lại lệnh không trống cuối cùng được nhập.

Cmd.default(line)

Phương thức được gọi trên dòng đầu vào khi tiền tố lệnh không được nhận dạng. Nếu phương thức này không bị ghi đè, nó sẽ in thông báo lỗi và trả về.

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

Phương thức được gọi để hoàn thành một dòng đầu vào khi không có sẵn phương thức complete_*() dành riêng cho lệnh. Theo mặc định, nó trả về một danh sách trống.

Cmd.columnize(list, displaywidth=80)

Phương thức được gọi để hiển thị danh sách các chuỗi dưới dạng tập hợp các cột thu gọn. Mỗi cột chỉ rộng ở mức cần thiết. Các cột được phân tách bằng hai dấu cách để dễ đọc.

Cmd.precmd(line)

Phương thức hook được thực thi ngay trước khi dòng lệnh line được diễn giải, nhưng sau khi dấu nhắc đầu vào được tạo và đưa ra. Phương pháp này vẫn còn sơ khai trong Cmd; nó tồn tại để bị ghi đè bởi các lớp con. Giá trị trả về được sử dụng làm lệnh sẽ được thực thi bằng phương thức onecmd(); việc triển khai precmd() có thể viết lại lệnh hoặc đơn giản trả về line không thay đổi.

Cmd.postcmd(stop, line)

Phương thức hook được thực thi ngay sau khi gửi lệnh xong. Phương pháp này vẫn còn sơ khai trong Cmd; nó tồn tại để bị ghi đè bởi các lớp con. line là dòng lệnh đã được thực thi và stop là cờ cho biết liệu việc thực thi có bị chấm dứt sau lệnh gọi tới postcmd() hay không; đây sẽ là giá trị trả về của phương thức onecmd(). Giá trị trả về của phương thức này sẽ được sử dụng làm giá trị mới cho cờ nội bộ tương ứng với stop; trả về sai sẽ khiến việc giải thích tiếp tục.

Cmd.preloop()

Phương thức hook được thực thi một lần khi cmdloop() được gọi. Phương thức này vẫn còn sơ khai trong Cmd; nó tồn tại để bị ghi đè bởi các lớp con.

Cmd.postloop()

Phương thức hook được thực thi một lần khi cmdloop() sắp quay trở lại. Phương thức này vẫn còn sơ khai trong Cmd; nó tồn tại để bị ghi đè bởi các lớp con.

Các phiên bản của lớp con Cmd có một số biến phiên bản công khai:

Cmd.prompt

Lời nhắc được đưa ra để thu hút đầu vào.

Cmd.identchars

Chuỗi ký tự được chấp nhận cho tiền tố lệnh.

Cmd.lastcmd

Tiền tố lệnh không trống cuối cùng được nhìn thấy.

Cmd.cmdqueue

Danh sách các dòng đầu vào được xếp hàng đợi. Danh sách cmdqueue được kiểm tra trong cmdloop() khi cần đầu vào mới; nếu nó không trống, các phần tử của nó sẽ được xử lý theo thứ tự, như thể được nhập tại dấu nhắc.

Cmd.intro

Một chuỗi để phát hành dưới dạng phần giới thiệu hoặc biểu ngữ. Có thể bị ghi đè bằng cách đưa ra một đối số cho phương thức cmdloop().

Cmd.doc_header

Tiêu đề sẽ xuất hiện nếu đầu ra trợ giúp có một phần dành cho các lệnh được ghi lại.

Cmd.misc_header

Tiêu đề sẽ phát hành nếu đầu ra trợ giúp có một phần dành cho các chủ đề trợ giúp linh tinh (nghĩa là có các phương thức help_*() không có các phương thức do_*() tương ứng).

Cmd.undoc_header

Tiêu đề sẽ phát hành nếu đầu ra trợ giúp có một phần dành cho các lệnh không có giấy tờ (nghĩa là có các phương thức do_*() không có phương thức help_*() tương ứng).

Cmd.ruler

Ký tự được sử dụng để vẽ các đường phân cách dưới tiêu đề thông báo trợ giúp. Nếu trống thì không có đường thước kẻ nào được vẽ. Nó mặc định là '='.

Cmd.use_rawinput

Một lá cờ, mặc định là đúng. Nếu đúng, cmdloop() sử dụng input() để hiển thị lời nhắc và đọc lệnh tiếp theo; nếu sai, sys.stdout.write()sys.stdin.readline() sẽ được sử dụng. (Điều này có nghĩa là bằng cách nhập readline, trên các hệ thống hỗ trợ nó, trình thông dịch sẽ tự động hỗ trợ chỉnh sửa dòng giống Emacs- và tổ hợp phím lịch sử lệnh.)

Ví dụ về lệnh

Mô-đun cmd chủ yếu hữu ích để xây dựng các shell tùy chỉnh cho phép người dùng làm việc với chương trình một cách tương tác.

Phần này trình bày một ví dụ đơn giản về cách xây dựng một shell xung quanh một số lệnh trong mô-đun turtle.

Các lệnh rùa cơ bản như forward() được thêm vào lớp con Cmd với phương thức có tên do_forward(). Đối số được chuyển đổi thành số và gửi đến mô-đun rùa. Chuỗi tài liệu được sử dụng trong tiện ích trợ giúp do shell cung cấp.

Ví dụ này cũng bao gồm một cơ sở ghi và phát lại cơ bản được triển khai bằng phương thức precmd(), phương thức này chịu trách nhiệm chuyển đổi đầu vào thành chữ thường và ghi các lệnh vào một tệp. Phương thức do_playback() đọc tệp và thêm các lệnh đã ghi vào cmdqueue để phát lại ngay lập tức

nhập cmd, sys
từ nhập khẩu rùa *

lớp TurtleShell(cmd.Cmd):
    intro = 'Chào mừng đến với mai rùa.   Nhập trợ giúp hoặc ? để liệt kê các lệnh.\n'
    nhắc = '(rùa)'
    tập tin = Không 

    # ----- lệnh rùa cơ bản -----
    def do_forward(self, arg):
        'Di chuyển rùa về phía trước một khoảng cách quy định: FORWARD 10'
        chuyển tiếp(*parse(arg))
    def do_right(self, arg):
        'Quay rùa sang phải theo số độ cho trước: RIGHT 20'
        đúng(*parse(arg))
    def do_left(self, arg):
        'Quay rùa sang trái theo số độ cho trước: LEFT 90'
        trái(*parse(arg))
    def do_goto(self, arg):
        'Di chuyển rùa đến một vị trí tuyệt đối với hướng thay đổi.  GOTO 100 200'
        goto(*parse(arg))
    def do_home(self, arg):
        'Đưa rùa về vị trí ban đầu: HOME'
        nhà()
    def do_circle(self, arg):
        'Vẽ hình tròn với bán kính cho trước, phạm vi tùy chọn và các bước: CIRCLE 50'
        vòng tròn(*parse(arg))
    def do_position(self, arg):
        'In vị trí rùa hiện tại: POSITION'
        print('Vị trí hiện tại là %d %d\n' % location())
    def do_heading(self, arg):
        'In tiêu đề rùa hiện tại theo độ: HEADING'
        print('Tiêu đề hiện tại là %d\n' % (heading(),))
    def do_color(self, arg):
        'Đặt màu: COLOR BLUE'
        màu(arg.low())
    def do_undo(self, arg):
        'Hoàn tác (liên tục) hành động cuối cùng của rùa: UNDO'
    def do_reset(self, arg):
        'Xóa màn hình và đưa rùa về giữa: RESET'
        đặt lại()
    def do_bye(self, arg):
        'Dừng ghi, đóng cửa sổ rùa và thoát: BYE'
        print('Cảm ơn bạn đã sử dụng Turtle')
        tự.đóng ()
        tạm biệt()
        trả về Đúng

    # ----- ghi và phát lại -----
    def do_record(self, arg):
        'Lưu các lệnh sau này vào tên file: RECORD rose.cmd'
        self.file = open(arg, 'w')
    def do_playback(self, arg):
        'Lệnh phát lại từ một tập tin: PLAYBACK rose.cmd'
        tự.đóng ()
        với open(arg)  f:
            self.cmdqueue.extend(f.read().splitlines())
    def precmd(tự, dòng):
        line = line.low()
        nếu self.file  'playback' không thẳng hàng:
            print(line, file=self.file)
        dòng trở về
    def đóng (tự):
        nếu self.file:
            self.file.close()
            self.file = Không

phân tích  pháp def (arg):
    'Chuyển đổi một chuỗi số 0 hoặc nhiều số thành một bộ đối số'
    trả về tuple(map(int, arg.split()))

nếu __name__ == '__main__':
    TurtleShell().cmdloop()

Đây là một phiên làm việc mẫu với mai rùa hiển thị các chức năng trợ giúp, sử dụng các dòng trống để lặp lại các lệnh cũng như tiện ích ghi và phát lại đơn giản:

Chào mừng đến với mai rùa.   Nhập trợ giúp hoặc ? để liệt kê các lệnh

(con rùa) ?

Các lệnh được ghi lại (gõ help <topic>):
============================================
tạm biệt màu sắc, bản ghi phát lại tại nhà phải không
vòng tròn tiến về phía trước vị trí bên trái thiết lập lại hoàn tác

(rùa) giúp về phía trước
Di chuyển rùa về phía trước một khoảng cách nhất định: FORWARD 10
(rùa) ghi lại xoắn ốc.cmd
(rùa) tư thế
Vị trí hiện tại là 0 0

(rùa) đề mục
Tiêu đề hiện tại là 0

(rùa) đặt lại
(rùa) vòng tròn 20
(rùa) đúng 30
(rùa) vòng tròn 40
(rùa) đúng 30
(rùa) vòng tròn 60
(rùa) đúng 30
(rùa) vòng tròn 80
(rùa) đúng 30
(rùa) vòng tròn 100
(rùa) đúng 30
(rùa) vòng tròn 120
(rùa) đúng 30
(rùa) vòng tròn 120
(rùa) đề mục
Tiêu đề hiện tại là 180

(rùa) tiến 100
(rùa)
(rùa) đúng 90
(rùa) tiến 100
(rùa)
(rùa) đúng 90
(rùa) tiến 400
(rùa) đúng 90
(rùa) tiến 500
(rùa) đúng 90
(rùa) tiến 400
(rùa) đúng 90
(rùa) tiến 300
(rùa) phát lại xoắn ốc.cmd
Vị trí hiện tại là 0 0

Tiêu đề hiện tại là 0

Tiêu đề hiện tại là 180

(rùa) tạm biệt
Cảm ơn bạn đã sử dụng Rùa