118
91

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iTerm2 にステータスバーが付いた

Last updated at Posted at 2018-09-12

α版の頃から追っかけてましたが、ついに 3.3.0 正式版がリリースされましたね! 合わせて以下の記事も続編として公開しております。


スクリーンショット 2019-05-11 20.18.04.png

左から順に今いるディレクトリのブランチ名、実行中のプロセス、バッテリー・CPU・メモリ・ネットワークの状態、現在時刻が表示されています。それぞれの配置や並べるコンポーネントは GUI で簡単に設定できるようになっています(Preferences > Profiles > Session > Status bar enabled > Configure Status Bar から設定できます)。

スクリーンショット 2019-04-14 17.55.18.png

テキストの字体や色は自由に変更できますが、Auto-Rainbow をクリックすると、いい感じに色をつけてくれます。

tmux Integration と組み合わせると吉

iTerm2 には tmux Integration という機能がありまして、これは tmux の Control Mode を使って tmux の各ウィンドウを iTerm2 のタブに統合できるのです。

便利な機能なのですが、tmux のステータスバーが消えちゃうのが難点でした。これを iTerm2 のステータスバーで代替できるようになったのです。

コンポーネントを自作する

もちろん、このコンポーネントは自作も可能です。実は、最初のスクリーンショットに挙げている機能のうち、バッテリーの状態は自作したコンポーネントで表示しています。


(2019/8/13 追記)

以下のコードは初めて自作コンポーネントに挑戦する人には複雑すぎるので、続編として簡単なコンポーネントの作り方をまとめました。Python 使わなくても自作が可能ですので参考にしてください。


(2019/5/11 追記)

バッテリー状態の表示は他の人にも便利そうだったので、提案したところ、作者によってネイティブのものが実装されました(20190511 nightly build)。とはいえ、コンポーネントの自作手法としては相変わらず有用だと思われますので、以下のソースは残しておきます。


iTerm2 には昔から AppleScript を使った API が用意されていたのですが、最近はこれが Python3 で書けるようになりました。

事前準備

Python Runtime はメニューからインストールする必要があります。Scripts > Manage > Install Python Runtime の順にクリックするとインストールされます。

  • インストールパスは ~/Library/ApplicationSupport/iTerm2 です。
  • すでにインストール済みの方は Check for Updated Runtime という表示になっているかもしれません。

ドキュメントやサンプルスクリプトはここにあります。

今回はこれを使ってバッテリー残量を表すコンポーネントを自作してみました。

実際には Objective-C のコードを叩いたりなど、いくらか複雑なことをしていますが、ここには簡略化したものを載せておきます。これを ~/Library/ApplicationSupport/iTerm2/Scripts/Autolaunch/battery.py というファイル名で保存すると GUI から選択できるようになります。

#!/usr/bin/env python3

from iterm2 import Connection, StatusBarComponent, StatusBarRPC, run_forever
from iterm2.statusbar import Knob
from math import floor
from subprocess import CalledProcessError, check_output
from typing import List
import re

chars = ["", "", "", "", "", "", "", ""]
thunder = "ϟ"
width = 5


async def main(connection: Connection) -> None:
    component: StatusBarComponent = StatusBarComponent(
        "Battery",
        "Show battery remaining",
        [],
        "|███▎  | 66% 2:34",
        30,
        "cx.remora.battery",
    )
    plugged = "🔌"

    @StatusBarRPC
    async def battery_status(knobs: List[Knob]) -> str:
        try:
            out: str = check_output(args=["/usr/bin/pmset", "-g", "batt"]).decode(
                "utf-8"
            )
        except CalledProcessError as err:
            return "`pmset` cannot be executed"

        matched1 = re.match(r".*; (.*);", out, flags=re.S)
        if matched1:
            status: str = matched1[1]
        else:
            return plugged

        matched2 = re.match(r".*?(\d+)%", out, flags=re.S)
        if matched2:
            percent: int = int(matched2[1])
        else:
            return plugged

        battery: str
        if status == "charged":
            battery = width * chars[-1]
        elif status == "charging":
            mid: int = floor(width / 2)
            battery = mid * " " + thunder + (width - mid - 1) * " "
        elif status == "discharging":
            unit: int = len(chars)
            total_char_len: int = len(chars) * width
            char_len: int = floor(total_char_len * percent / 100)
            full_len: int = floor(char_len / unit)
            remained: int = char_len % unit
            space_len: int = width - full_len - (0 if remained == 0 else 1)
            battery = chars[-1] * full_len
            if remained != 0:
                battery += chars[remained - 1]
            battery += " " * space_len
        else:
            battery = " " * width

        matched = re.match(r".*?(\d+:\d+)", out, flags=re.S)
        elapsed: str = matched[1] if matched and matched[1] != "0:00" else ""
        last_status: str = "{0} |{1}| {2:d}% {3}".format("🔋", battery, percent, elapsed)
        return last_status

    await component.async_register(connection, battery_status, timeout=None)


run_forever(main)

スクリプトの状況はメニューアイテム Scripts > Manage > Console から閲覧可能です。

スクリーンショット 2019-04-14 18.02.46.png

表示イメージは Code-Hex/battery を参考にしました。コンポーネントを作る際は async/await のような結構新し目の機能を使ってコーディングするようです。上記のサンプルスクリプトでは Type Annotation も頑張ってつけていますが必須ではありません。battery_status という、文字列を返す関数だけが肝で、あとはコピペでいけると思います。

最後に

最初はゴリゴリインターフェイスが変わって大変だったのですが、beta になってだいぶ仕様が固まってきたようです。公式の Issues を随時確認して利用してください。

118
91
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
118
91

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?