お前らはまだMacのメニューバーを使いこなせていない
ごきげんよう。
本日はMacのメニューバーについてのお話です。
お前らはメニューバーの奴隷
メニューバーとは
メニューバーとは、macOSにおけるディスプレイ上部にあるバーのことです。
おそらく多くの人が、このメニューバーに対して
「アプリをインストールしたらたまにアイコンが増えてるやつ」
みたいな印象しかないと思います。
また、メニューバーに何かを表示させることを主目的にしているアプリも存在しているため、そういったアプリをインストールしてメニューバーを有効活用しようとしている方もいるかもしれません。
しかし皆さんはこのメニューバーに、本当に自分の欲しい情報を表示できていますか?
なんとなくMacのシステムモニターやカレンダーを表示させるものをインストールしてみたけどそこまで使用してなかったり、バックグラウンドで動いているアプリを開くためであったりとか、メニューバーを「とりあえず使ってる」だけではないでしょうか。
つまりあなたはメニューバーの奴隷なのです。
じゃあ何に使うんだと思われるでしょうが、確かにニッチな需要に対応するものを探し始めると、なかなか既存のアプリでは見つかりません。
その解決策として真っ先に思い浮かぶのは「なければ自分で作る」ですが、
正攻法だとXcodeでSwiftUIなどを用いて制作することになります。とはいえ、リッチなデザインを必要とするならともかく、ちょっとした情報の表示を目的とするメニューバーアプリをわざわざXcodeで開発するのはコストが高いですよね。
そんなときにピッタリなユーティリティが『xbar』です。
『xbar』とは
『xbar』はスクリプト言語を用いてメニューバーアプリを作成できるユーティリティです。
『xbar』の利点は
シェルスクリプトやRuby、Pythonなどでメニューバー項目を作れる
項目は標準出力するだけで作れる
標準出力する内容に「"--"」を付けるだけでサブ項目を作れる
つまり、「かなり簡単!」というわけです。
作例として、僕がxbarで制作したものの中から2つ紹介します。
作例
最終目的:ゴミ出しカレンダー表示
1.『xbar』のインストール
まずはなにはともあれ『xbar』をインストールしなければ始まりません。
上記の公式リポジトリのReleaseからdmgをダウンロードし、アプリをインストールしてください。
2.『xbar』のプラグインフォルダーにプラグインを作成する
『xbar』を起動するとメニューバーに新たなアイコンが表示されると思います。そちらの「Open plugin folder」という項目をクリックするとプラグインフォルダー('/Users/name/Library/Application Support/xbar/plugins')がFinderで表示されます。
ちなみに自分で作らなくても「Plugin browser…」から他の人が作ったxbarプラグインを探してインストールすることも可能です。
プラグインフォルダー内に作るスクリプトファイルですが、ファイル名で更新間隔を指定できます。
詳しくは公式ドキュメントに記載されています。
また、サポートされている言語は以下のとおりです。
Ruby
Python2
Python3
JavaScript (node)
JavaScript/Typescript (deno)
CoffeeScript (coffee)
Swift (Interpreted)
Swift (Compiled)
Go (Interpreted)
Go (Compiled)
Lisp
Perl5
PHP
この中から自分の好きな言語を選べます。
いつも僕のプログラミング系の作例ではPythonを用いることが多いので、
たまにはRubyを使って作例を記述してみましょう。
今回はとりあえず
「garbage_collection_calendar.1d.rb」
というファイル名で作成します。
3.ゴミ出しカレンダーのデータを用意する
pluginフォルダ内に「data」フォルダを新規作成し、その中にゴミ出しカレンダーのデータを「calendar.json」として作成します。
方法としてはいろいろ考えられますが、
手っ取り早いのはお手持ちのカレンダーを目視して手入力することですね。
{
"2025" {
"2": {
"1": ["普通ごみ"],
"4": ["容器包装プラスチック"],
"5": ["普通ごみ"],
"6": ["古紙・衣類"]
//以下省略
}
}
}
もしくはカレンダーをカメラで撮影して、そのデータをChatGPTに投げてJSONで出力してもらう方法もありです。
僕は自治体が出しているスマホ向けのアプリのリクエストをキャプチャしてそのレスポンスを保存して読み込んでいます。
{
"result": {
"calendar_array": [
{
"year": "2025",
"month": "02",
"day": "01",
"trash_kind_id": 2549
},
{
"year": "2025",
"month": "02",
"day": "04",
"trash_kind_id": 2573
},
{
"year": "2025",
"month": "02",
"day": "05",
"trash_kind_id": 2549
},
{
"year": "2025",
"month": "02",
"day": "06",
"trash_kind_id": 2591
}
]
}
}
4.実際にコードを書く
「garbage_collection_calendar.1d.rb」を編集していきます。
もしプラグインを公開する場合は、『xbar』のドキュメントにあるように、Metadataを書いておきましょう。
また、1行目にシバンも書いておきます。
#!/usr/bin/env ruby
# <xbar.title>Garbage collection calendar</xbar.title>
# <xbar.version>v1.0</xbar.version>
# <xbar.author>Your name</xbar.author>
# <xbar.author.github>Your github name</xbar.author.github>
# <xbar.desc>Displays today's and tomorrow's garbage disposal schedules.</xbar.desc>
# <xbar.dependencies>ruby</xbar.dependencies>
require 'json'
Struct.new("Trash_kind", :name, :id)
class TrashCalendar
@@trash_kinds = [
Struct::Trash_kind.new("🔥普通ごみ", 2549),
Struct::Trash_kind.new("♻️容器包装プラスチック", 2573),
Struct::Trash_kind.new("👚古紙・衣類", 2591),
]
def initialize
file_content = File.read("data/calendar.json")
hash = JSON.load(file_content)
@calendar = hash["result"]["calendar_array"]
end
def get_trash_kind(day)
trash_kind_array = @calendar.select { |a_data| a_data["day"] == format("%02d", day)}
if trash_kind_array.empty? then
return ["なし"]
end
trash_kind_array.map do |a_data|
name = convert_trash_kind_id_to_name(a_data["trash_kind_id"])
if name.empty? then
"不明"
else
name[0].name
end
end
end
def convert_trash_kind_id_to_name(trash_kind_id)
@@trash_kinds.select { |kind| kind.id == trash_kind_id }
end
end
tc = TrashCalendar.new
today = Time.now
tomorrow = today + 1 * 60 * 60 * 24
puts "♻️" # 一番始めの標準出力。メニューバーに表示される
puts "---" # 区切り線
puts "本日(" + today.strftime("%Y年%m月%d日") + ")"
puts tc.get_trash_kind(today.day).map { |name| puts name + " | refresh=true" } # refreshパラメータをtrue
puts "---" # 区切り線
puts "明日(" + tomorrow.strftime("%Y年%m月%d日") + ")"
puts tc.get_trash_kind(tomorrow.day).map { |name| puts name + " | refresh=true" } # refreshパラメータをtrue
こちらを保存したら、『xbar』のRefresh allを押すことでロードされると思います。
『xbar』では一番最初の標準出力の内容がメニューバーに表示されます。
今回でいうと
puts "♻️"
の部分ですね。
例えばここを文字に変更すると以下のようになります。
puts "ゴミ出し"
また、この部分を画像にしたい場合があると思います。
『xbar』ではいろいろなパラメータが用意されていて、出力する内容の後ろにパイプラインを付けることで追加できます。
Open website | href=https://xbarapp.com | color=red | key=CmdOrCtrl+o
Open home folder | shell=open | param1="~/"
App version: v1.0 | disabled=true | size=10
画像を表示する場合は「image=..」というパラメータを用いるのですが、注意点として、36x36 ピクセルで144DPIの画像をbase64エンコードする必要があります。
例として、icon-rainbow様のごみ箱のイラストを上記のサイズに変換して、base64にエンコードしたものを設定してみました。
icon_b64 = "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"
puts " | image=" + icon_b64
また、環境変数でシステムがダークモードを使用しているか判定できるため、それに合わせて表示する画像を変更することも可能です。
XBARDarkMode=true|false
以上
スクリプト言語のライブラリを用いることで、スクレイピングした結果を表示したり、APIのレスポンスを表示できるのは非常に便利ですね!
皆さんもぜひメニューバーを活用してみてください。
この記事が気に入ったらサポートをしてみませんか?