Powerline に○○が表示されない? なら作ればいいじゃない(4日目 tmux 編)


前回前々回に引き続き、今回は tmux のステータスラインにセグメントを追加してみます。

全ては例によって .config/powerline に上げておりますので、完全なものはそちらを参照してください。

前々回挙げたものと同じですが、こんな感じに作りました。

iTerm2 + tmux + vim + Powerline

iTerm2 + tmux + vim + Powerline

セグメント 標準添付? 説明
130428-0005 tmux のセッション番号です。
130428-0006 標準 日付。
130428-0007 標準 メールの未読数。
130428-0001 自作 Last.fm の再生履歴を表示しています。
130428-0008 tmux のウィンドウが表示されています。
セグメント 標準添付? 説明
130428-0009 標準 グローバル IP アドレス
130428-0002 自作 ローカル IP アドレス
130428-0010 標準 ネットワーク帯域使用量
130428-0011 標準 CPU 使用率
130428-0003 自作 メモリ使用率
130428-0004 自作 バッテリー状況

セグメントの作り方は vim 編でも説明した、グラデーション表示を利用しています。

{
    "groups": {

        ...

        "used_memory_percent": { "fg": "gray8", "bg": "gray0" },
        "used_memory_percent_gradient": { "fg": "green_yellow_orange_red", "bg": "gray0" },

        ...

    }
}

green_yellow_orange_red は、例によって colors.json に定義されています。

ちなみに、標準添付のものを含め、ほとんどのセグメントでは format 引数が指定可能になっています。これを利用すると、スクリーンショットのような絵文字が表示できます。

{
    "segment_date": {

        ...

        "used_memory_percent_gradient": {
            "args": {
                "format": "🔲  {0:4.1f}%"
            }
        },

        ...

Mac なら標準で絵文字フォントが入っているので問題なく見えているはずですが、他の OS ではフリーの絵文字フォントを入れるといいと思います。

バッテリー状況の表示

import commands
import re

def battery_percent_gradient(pl, format='{percent}%', charging='charging',
        discharging='', charged='', remain='remain {0}'):
    pmset_output = commands.getoutput('pmset -g ps')
    r = re.compile(r"Currently drawing from '(.*)'" + ¥
            r'.*-InternalBattery-¥d+¥s+(¥d+)%;' + ¥
            r'¥s+((?:dis)?charging|charged);' + ¥
            r'¥s+((¥d+:¥d+)? remaining|¥(no estimate¥))', re.S)
    m = r.search(pmset_output)

    if m == None:
        return

    if m.lastindex == 3 : remain = ''
    else                : remain = remain.format(m.group(5))

    if m.group(3) == 'charging'      : status = charging
    elif m.group(3) == 'discharging' : status = discharging
    elif m.group(3) == 'charged'     : status = charged; remain = ''

    battery = {
            'percent': int(m.group(2)),
            'status': status,
            'remain': remain,
            }

    return [{
        'contents': format.format(**battery),
        'highlight_group': ['battery_percent_gradient', 'battery_percent'],
        'draw_divider': True,
        'divider_highlight_group': 'background:divider',
        'gradient_level': 100 - battery['percent'],
        }]
バッテリー状況

バッテリー状況

今回は Mac で作業しているので、pmset -g ps の出力をパースして表示しています。Windows の場合はまた違ってくるのでそれは次回。

これもメモリ使用率の場合と同じく、グラデーション表示を使っています。カラースキームにも同様な設定が必要です。

更に、これも同じく、表示には絵文字を使っています。

{
    "segment_date": {

        ...

        "battery_percent_gradient": {
            "args": {
                "format": "🔋  {percent:2d}% ({status}{remain})",
                "charging": "充電中",
                "charged": "充電完了",
                "remain": "残り {0}"
            }
        },

        ...

Last.fm の再生履歴を表示する

Last.fm の再生履歴

Last.fm の再生履歴

これは結構厄介です。標準でも common.pyNowPlayingSegment というクラスが定義されているのですが、これはデスクトップの音楽再生アプリに対応したものなので、そのまま使うことは出来ません。

Last.fm の再生履歴は Web から取ってくる必要がありますので、むしろ同じファイルに含まれている EmailIMAPSegment の実装が参考になりました。これはちょっと長いので一部省略して貼ってみます。

from powerline.lib.threaded import KwThreadedSegment, with_docstring
from powerline.lib.url import urllib_read, urllib_urlencode

from collections import namedtuple
import json
import re
import types

_NowPlayingKey = namedtuple(
    'Key', 'username api_key format shorten_artist shorten_title')

STATE_SYMBOLS = {
    'fallback': u'♫?',
    'play': u'▶',
    'pause': u'▫▫',
    'stop': u'■',
    }

class NowPlayingLastFM(KwThreadedSegment):
    interval = 30

    # 呼び出し時の引数を保存
    @staticmethod
    def key(username, api_key, format=u'{state_symbol} {artist} - {title}',
            shorten_artist=False, shorten_title=False, **kwargs):
        return _NowPlayingKey(
                username, api_key, format, shorten_artist, shorten_title)

    # 表示する文字列を作る
    def compute_state(self, key):
        if not key.username or not key.api_key:
            self.warn('Username and api_key are not configured')
            return None
        data = self.player(key)
        stats = {
                'state': None,
                'state_symbol': STATE_SYMBOLS['fallback'],
                'album': None,
                'artist': None,
                'title': None,
                'elapsed': None,
                'total': None,
                }
        stats.update(data)
        string = key.format.format(**stats)
        return string

    # ダミー
    @staticmethod
    def render_one(string, **kwargs):
        return string

    # 再生履歴を取ってくる本体
    def player(self, key):
        query_data = {
                'method': 'user.getrecenttracks',
                'format': 'json',
                'user': key.username,
                'api_key': key.api_key,
                'nowplaying': 'true',
                }
        url = 'http://ws.audioscrobbler.com/2.0/?' + ¥
                urllib_urlencode(query_data)

        raw_response = urllib_read(url)

        # URL から GET したものをなんやかんややって解析

        return {
                'artist': artist,
                'title': title,
                'playing': status,
                }

    # アーティストを短く表示する
    def shorten_artist(self, artist):

        ...

    # タイトルを短く表示する
    def shorten_title(self, title):

        ...

powerline/lib/threaded.py に定義されている KwThreadedSegment クラスを継承することで作業を非同期に実行し、実際には Interval 秒ごとに Last.fm にアクセスすることでネットワーク負荷を減らす……んだと思うのですが、正直、あんまり理解できていません。

まあこれも Python の勉強ってことで晒しときます。

今回は Macbook Air の狭い画面に合わせて、 “(Original Mix)” とか “featuring John Doe” みたいなのを除いて短くする処理も追加しています。

{
    "segment_date": {

        ...

        "now_playing": {
            "args": {
                "username": "delphinus_iddqd",
                "api_key": "7a77671178c4f4cff16222c46f72d193",
                "format": "{state_symbol} {artist} - {title}",
                "shorten_artist": true,
                "shorten_title": true,
                "interval": 30
            }
        },

        ...

設定ファイルには API key やその他のオプションを指定しています。API key の取得は以前記事を書いたのでそちらを参照してください。

jQuery 版 Last.FM ウィジェットを導入してみた | blog.delphinus.dev
https://blog.delphinus.dev/2010/11/lastfm-widget-for-jquery.html

終わりに

さて、これで欲しい情報はそろったはずですが、会社の PC は Windows + Linux だったので別の苦労がありました。それはまた次回にて。

コメントを残す