Hello Ys world ?

技術的なことや何か役立つこと、日々の活動を記録する

CmdモジュールでPythonコマンドラインのコマンドとサブコマンドをタブで補完する

Pythonコマンドライン上でタブ補完機能が使いたいなと思い調べたら標準で備わっているらしい。結構簡単に作れたので紹介する。

Pythonには標準でコマンドラインインタプリタを作成できるCmdモジュールがある。また、タブ補完にサブコマンドも実装できるようなのでそれも行う。

docs.python.org

必要ライブラリのインストール

環境によってはPyReadlineをインストールしないと反応してくれないのでインストールする。IPytonが入っている場合は既に入っていると思う。

pip install pyreadline

プログラム

適当にサンプルとして作ったプログラムを載せておく。

# -*- coding: utf-8 -*-
from cmd import Cmd # 標準
import readline # PyReadline

class CommandlineCompletion(Cmd): # Cmd(cmd.py)より継承
    intro = '--- コマンドラインでタブ補完 ---\n' # 実行時表示
    prompt = '>> ' # 入力時のプロンプト

    langlist = ['C/C++', 'Go', 'Julia', 'Python'] # likeコマンドの2次候補(サブコマンド)

    def emptyline(self): # 空行であった場合
        print('なにか入力しろよ')
        pass

    def do_like(self, line): # likeコマンド "do_"
        if line and line in self.langlist: #likeコマンドに文字があり、langlistにもあった場合
            message = '%sはいいよな\n' %line
        elif line: #likeコマンドに文字があった場合
            message = '%sが好きなのか\n' %line
        else:
            message = 'Juliaはいいぞ\n'
        print(message)
        pass
    
    def complete_like(self, text, line, begidx, endidx): # likeコマンドの2次補完候補表示 "complete_"
        if not text: # textがなかった場合
            completions = self.langlist[:] # langlistをすべて表示 [:]
        else:
            completions = [ # langlistから該当するものを表示または補完
                n for n in self.langlist
                if n.startswith(text)
            ]
        return completions

    def help_like(self): # likeコマンドのヘルプ表示 "help like" または "? like" で呼び出し "help_"
        print('好きなプログラム言語は?なにかを聞いているぞ')

    def do_exit(self, line): # ループ抜け(ただreturnするだけpassするとループ継続)
        return True
        
    def help_exit(self):
        print('ループを抜けるん')

if __name__ == '__main__':
    try:
        CommandlineCompletion().cmdloop() # cmd.pyにある "cmdlopp" 実行でタブ補完ができるループに入る
    except KeyboardInterrupt: # キーボードによる割り込み
        print('\nKeyboard Interrupt (Ctrl+C)')
        pass
    except:
        pass

解説

以下の2つはCmdで規定値が指定されているがユーザが上書きできる。

  • intro 実行時に1回のみ表示される文字列
  • prompt 入力時に表示されるプロンプト

コマンドの実装

  • do_XYZ XYZをコマンドとして実装する。XYZ で実行することができる。

  • complete_XYZ コマンドXYZのTabキー補完時に動作を実装。

  • help_XYZ コマンド do_XYZ に対するヘルプ。コマンド help XYZ または ? XYZ でヘルプを呼び出す。

  • emptyline 空入力時に呼び出される。オーバーライドしない場合、最後に入力したコマンドを繰り返す。

その他

precmd をオーバーライドして入力されたコマンドをすべて小文字として処理するなどもできる。

def precmd(self, line):
    return line.lower()

まとめ

思いのほか簡単にコマンドラインインタプリタが実装できる。このタブによる補完機能を使って簡単なツールをより便利にできそうだなと作っていて思った。