Chapter 04

汎用的な関数を定義

AWtnb
AWtnb
2021.12.30に更新
このチャプターの目次

自作関数

キー入力で特定の関数を呼び出すこともできます。事前に各所で使い回せるような処理を関数にまとめておきましょう。

config.py

    # 遅延させる関数
    def delay(sec=0.05):
        time.sleep(sec)

    # クリップボード内容をテキスト形式で取得する関数
    # - クリップボードに画像などテキスト以外が入っていると getClipboardText() が None を返すため
    def get_current_clipboard():
        s = getClipboardText() or ""
        return s

    # 空白を削除する関数
    def simple_trim(s):
        return s.replace(" ", "").replace(" ", "").replace("\t", "")

    # キーストロークの入力
    def send_keys(*keys):
        keymap.beginInput()
        for key in keys:
            keymap.setInput_FromString(str(key))
        keymap.endInput()
        keymap._fixFunnyModifierState()

    # 文字列の入力
    def send_string(s):
        keymap.beginInput()
        keymap.setInput_Modifier(0)
        for c in s:
            keymap.input_seq.append(pyauto.Char(c))
        keymap.endInput()

    # 上記2つを組み合わせる
    def send_input(sequence, sleep=0.01):
        for elem in sequence:
            delay(sleep)
            try:
                send_keys(elem)
            except:
                send_string(elem)

    # IME 状態を指定する(オンが1、オフが0)
    def set_ime(mode):
        if keymap.getWindow().getImeStatus() != mode:
            send_keys("(243)") # 半角全角キー
            delay(0.01)

    # 選択中の文字列をコピーする
    # - コンソール系のアプリで Ctrl-C が処理の中断に割り当てられていることがあるため
    def copy_string(sec=0.01):
        setClipboardText("")
        send_keys("C-Insert")
        delay(sec)
        return get_current_clipboard()

    # 文字を貼り付ける
    def paste_string(s):
        setClipboardText(s)
        send_keys("C-V")

    # 有効なパスのファイルもしくは URL の実行
    def execute_path(s, arg=None):
        if s:
            if s.startswith("http") or to_local_path(s):
                keymap.ShellExecuteCommand(None, s, arg, None)()


send_keys()send_string() は公式のソースを参考に作ってみました。前者は send_keys("A", "Enter") のように可変長引数を受け付けます。

send_input() はリストを第1引数に取り、リストの各要素をキー入力として解釈できる場合( "C-A" など)はキーストロークを送り、そうでなければ文字列を送ります。

関数を生成する関数

keyhac でのキーリマップは、keymap_global[(キー定義)] = (キー入力で呼び出す内容) のようにキーと値の辞書形式で割り当てます。

ここで、send_input() など関数をそのまま右辺に書くと 関数の実行結果 が割り当てられることになりエラーを起こします。
対策としてはキーに対して 関数 を割り当ててやればいいので、下記の「関数を生成する関数」を作ってやります。

config.py
    # キーや文字のリストを受け取り、「IME をオフにしてその内容を入力する関数」を返す
    def non_ime_typing(*sequence):
        def _input():
            set_ime(0)
            send_input(sequence)
        return _input

    # 関数を受け取り、「その内容を実行してからIME をオンにする関数」を返す
    # - non_ime_typing() と組み合わせて使う
    def recover_ime(func):
        def _recover():
            func()
            set_ime(1)
        return _recover

これらを使って keymap_global["A"] = non_ime_typing("B", "Enter") とすれば、Aを押したときにBとエンターキーが押されるようになります。

なお、クロージャは生成時の変数を覚えていてくれます(=束縛)。
たとえば上記の non_ime_typing() で定義したあとに別の箇所で sequence という変数に代入しても、当初の割り当て内容には影響しません。