qterminalでコマンドから複数タブ操作する

今回はLubuntu 22.04で標準のqterminalという端末ソフトでコマンドラインからタブの追加とコマンドの送信をやってみます。

背景

GUIログインしたときにいつも開くソフトがあるのですが、これを自動起動でやりたいのです。

しかし端末(qterminal)で複数タブを簡単に自動起動する方法がありません。代替案はいくつかあります。

  • タブを使わず複数のqterminalで起動する
    →順当な方法ですが、少しでもリソースをケチりたいしアプリの切り替えが面倒
  • どうせサービスなのでバックグラウンドで実行する
    →ログ代わりの標準出力をすぐ見たいのでイヤ
  • gnome-terminalを使用する
    →標準機能だけがいいし、せっかく軽い(?)Qtを使ってるのでイヤ
  • screen/tmuxなどを使う
    →標準機能だけがいい

とにかく今までどおりの作業感で軽く済ませたいわけです。多分この条件なら大抵の人はtmuxなどを使用すると思います。しかし、何が何でもqterminalで複数タブ使いたいときはどうすればいいんだ!と気になったらもう他の選択肢は目に入りません。

目的

qterminalで複数タブをコマンドラインから操作する

詳細

前提

qterminalにはgnome-terminalのようにコマンドラインからタブを開くようなオプションがありません。しかしプログラミングが出来る人ならdbusを使ったRPCでタブの操作やコマンドの流し込みが出来るのです。ただしドキュメントもなく、qterminalのソースコードを読み解かないと出てこない情報だそうです。

この情報を見つけたのはqterminalのgithubの以下のissueからです。
https://github.com/lxqt/qterminal/issues/812

dbusとは

https://en.wikipedia.org/wiki/D-Bus

Lubuntu 22.04でやってみる

issueのコードはpydbusを使っているので、標準の状態では使えません。しかしLubuntu 22.04ではpython-dbusパッケージが(多分)標準で入っています。これを使った起動コードが以下になります。

import subprocess
from dbus import SessionBus, Interface

def dbus_get(bus, bus_name, object_path, interface):
    proxy = bus.get_object(bus_name, object_path)
    return Interface(proxy, interface)

def start_qterminal(multitab_commands):
    proc = subprocess.Popen(['qterminal'])
    dest = 'org.lxqt.QTerminal-' + str(proc.pid)
    subprocess.check_call(['gdbus', 'wait', '--session', dest])
    bus = SessionBus()
    process = dbus_get(bus, dest, '/', 'org.lxqt.QTerminal.Process')
    window = dbus_get(bus, dest, process.getWindows()[0], 'org.lxqt.QTerminal.Window')
    first = True
    for command in multitab_commands:
        if first:
            first = False
            tab = dbus_get(bus, dest, window.getTabs()[0], 'org.lxqt.QTerminal.Tab')
        else:
            tab = dbus_get(bus, dest, window.newTab({'shell': '/bin/bash'}), 'org.lxqt.QTerminal.Tab')
        term = dbus_get(bus, dest, tab.getTerminals()[0], 'org.lxqt.QTerminal.Terminal')
        term.sendText(command)

start_qterminal([
    """\
echo hello
""",
    """\
echo world
""",
])

このコードを実行すると、新しいqterminalが開き、最初のタブにhello、次のタブにworldが出力されます。中で使うシェルが/bin/bash決め打ちになっているので注意してください。

まとめ

qterminalには複数タブをオプションから操作する方法はないが、dbusをスクリプトなどから使えばRPCで操作できる。