前回、前々回に引き続き、今回は tmux のステータスラインにセグメントを追加してみます。
全ては例によって .config/powerline に上げておりますので、完全なものはそちらを参照してください。
前々回挙げたものと同じですが、こんな感じに作りました。
セグメント | 標準添付? | 説明 |
---|---|---|
– | tmux のセッション番号です。 | |
標準 | 日付。 | |
標準 | メールの未読数。 | |
自作 | Last.fm の再生履歴を表示しています。 | |
– | tmux のウィンドウが表示されています。 |
セグメント | 標準添付? | 説明 |
---|---|---|
標準 | グローバル IP アドレス | |
自作 | ローカル IP アドレス | |
標準 | ネットワーク帯域使用量 | |
標準 | CPU 使用率 | |
自作 | メモリ使用率 | |
自作 | バッテリー状況 |
セグメントの作り方は 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 の再生履歴を表示する
これは結構厄介です。標準でも common.py
に NowPlayingSegment
というクラスが定義されているのですが、これはデスクトップの音楽再生アプリに対応したものなので、そのまま使うことは出来ません。
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 だったので別の苦労がありました。それはまた次回にて。