🌌

開発チームの一体感を出すために専用のバーチャル背景を作ろうとしたら、いつの間にかシェルスクリプトを触っていた話

2023/12/17に公開

この記事は、Magic Moment Advent Calendar 2023 17日目の記事です。

どうもこんにちは、Magic Moment の @morishin です。

お前は一体何を言っているんだ?

タイトルだけでは何を言っているか分からないと思うので説明します。
弊社のアドベントカレンダーページにも載っているコレ。

mmbg

コレは見ての通りコマンドの実行結果 (標準出力) で、元々は開発チーム専用のバーチャル背景画像として作り始めたものでした。
「バーチャル背景画像からなんでシェルスクリプト?」とお思いでしょうから順番にご説明します。

そもそもバーチャル背景画像を作ることになった経緯

時は遡ること今年の1月。開発チーム [1] を盛り上げるための企画を考えることになりました。
人も増えてきたことだし、今まで以上にチームの一体感を出していこう。もっともっとチームを盛り上げていこう。というのが狙い。
色々な案が挙がりましたが、取り敢えず専用パーカーと専用バーチャル背景画像 [2] を作ることにしました。

事の起こり パーカーとバーチャル背景決定
plan idea

どんな背景画像にするかをチーム内で公募し、集まったデザイン案にみんなで投票しました。

design

最終的に最も多くの票を集めたのは、大塚さんが応募してくれた「neofetch」でした。
こうして neofetch 風の画像を作ることになりました。

シェルスクリプトォ!?

かくして決まったデザイン。さっそく開発チームの有志メンバーで作っていくことにしました。
最初は普通に画像として作ろうとしていたのですが... ふと、思ったのです。本当にそれでアガるのかと。
せっかく作るなら、開発チームが「おぉ!」と唸るものにしたい。

逆に何故 neofetch は「おぉ!」となるのか。それはおそらくコマンドだからです。
コマンドでリッチなものが出力されると謎の感動を覚えませんか?

そして我々はエンジニアです。ならば自分たちで作ってしまおうというのがエンジニアの性。
したがってバーチャル背景画像もコマンドにするというのは当然の帰結。
そう、当然の帰結なのです。

元ネタの neofetch をもじり、mmfetch というコマンドを作ることになりました。
(弊社 Magic Moment はよく「MM」と略されるので、MM + neofetch というネーミングです)

そうしてできた mmfetch

まずは完成品をご覧ください。

初回実行時、自身のプロフィールについて色々聞かれます。頑張って答えます。
全て答えるとバーチャル背景画像用に、ロゴと自分のプロフィールが標準出力されます。

run

出力後、勝手にスクリーンショットを撮影するモードになります。便利。

capture

2回目以降は $ mmfetch だけですぐさま出力が見られます。

rerun

作り直す際は -i オプションをつけるだけ。

input

(一応) ヘルプ機能も搭載。

help

「おぉ...!」ってなりましたか?なりましたよね?
少なくとも社内で LT をしたときには、みんな「おぉ...!」ってなってくれました。
作って良かった。

mmfetch を支える技術

開発秘話的なことを書こうか迷ったのですが、単なる内輪の苦労話になりそうなので多分興味ないですよね。
なので技術的なことを書きます。ようやくテックブログっぽい話題になりましたね。

環境

あくまで私の環境というだけですので、Linux でも Bash でも動くと思います。

  • OS: macOS Sonoma 14.1.1
  • Shell: zsh
  • ターミナル: Warp

標準出力の装飾

ANSI エスケープシーケンスの1つである、SGR (Select Graphic Rendition) コマンドというものを用いることで、グラフィック要素部分の設定ができます。
具体的に書くと \e[太さ;色番号m\e[m で囲まれた部分が装飾されます。
例として、以下は「hello, zsh world」の zsh だけを太く赤くする出力です。

echo -e "hello, \e[1;31mzsh\e[m world"

ただ、太さを変えるとレイアウトが崩れたりして微調整が面倒になります。
mmfetch では文字の太さを変えず、色だけ変えています。

プロフィール情報の保管

入力した情報は全て ~/.mmfetch ディレクトリに格納しています。

  • ~/.mmfetch/profile.txt ... 入力したプロフィール情報
  • ~/.mmfetch/capture.jpg ... 撮影したスクリーンショット

~/.mmfetch/profile.txt があればその内容をそのまま表示。
なければ初回実行と見なし、プロフィールを入力するモードになります。(-i オプションをつけたときも同じ挙動)

選択肢の表示と番号による選択

あらかじめ用意された選択肢の中から選んだもらいたいとき、select コマンドを用いることで簡単に実現できます。
以下は、所属チームの選択肢 teams を用意しておき、その中から選択されたものを表示する実装例です。

teams=('Alpha' 'Bravo' 'Charlie' 'Delta' 'Echo')
is_valid_team() {
    local i
    for i in ${teams[@]}; do
        if [[ ${i} = ${1} ]]; then
            return 0
        fi
    done
    return 1
}

printf "所属チームを選択してください: \n"
select VAR in ${teams[@]};
do
    if is_valid_team $VAR; then
        echo "あなたの所属チームは ${VAR} です"
        break
    else
        echo "正しい番号を入力してください"
        continue
    fi
done

カラム表示

出力を複数の列に整形する (カラム表示させる) のには column コマンドを用いています。
通常はファイルを引数にとるものですが、パイプさせることで標準出力に対しても活用できます。
例えば -c オプションをつけて全体の幅を指定することで、その幅の中で可能な限りカラム表示してくれます。

echo "hello\nzsh\nworld" | column -c 20
hello	world
zsh

スクリーンショット

screencapture コマンドでスクリーンショットを撮ることができます。
これは Mac なら標準で入っていますが、Linux だとディストリビューションによっては入っていないと思います。
mmfetch では以下のようにしています。

CAPTURE_FILE='./mmfetch/capture.jpg'
# (中略)
screencapture -xW ${CAPTURE_FILE}

使用しているオプションの説明は以下の通り。

  • -x ... 撮影時に音を出さない
  • -W ... インタラクションモードで起動し、デフォルトでウィンドウ選択にする

インタラクションモードが結構便利で、ウィンドウ全体を撮るか特定範囲だけを撮るかを Space キーで選べたりできます。
他にも色々便利なオプションがあるので、気になる方は是非調べてみてください。

ロゴの AA 化

これはネットに転がっている適当なツールをいくつか試しました。
例えば Online Ascii Art Creator なんかは AA の幅が選べて便利でしたね。

ただ、そのままだと思い通りの見た目にはならなかったりもしたので、ツールに食わせる画像を事前に編集して、二値化したりネガポジ反転したりしています。
それでも細かいところで気になる部分が出てくるので、最後は結局人間が手直しを加えています。

Future work

まずは動くものを作って開発チームのみんなに共有する、フィードバックをもらって改善は後から入れる、という意識でやっていました。
したがって色々惜しいところ、もっと良くしていきたいところがまだあります。
今後、余力があればやりたいなぁということを書いておきます。

インストーラ

mmfetch の想定利用者が全員エンジニアなので、コマンド化くらい自分たちでできるよね?ね?
圧をかけて甘えて、インストーラのようなものは作っていません。
今は /usr/local/bin にシンボリックリンクを作ったり、alias 登録してもらうことで、各人にコマンド化してもらっている状態です。
インストーラ的なものを作れたら「シェルスクリプト、ナンモワカラン」という人でも気軽に使ってもらえそうです。

レイアウトの見直し

AA が大きすぎるのもあって、プロフィール情報が画面の下の方に追いやられて見えづらいです。
バーチャル背景画像で暗に自己紹介をする、というようなことは難しい状況です。(自分の顔でほとんど隠れてしまう)
neofetch のように、ロゴとプロフィールの2カラムデザインにできたら、より実用的になりそうです。

ロゴのコード化

ロゴがただの AA なので、クワインにできると最高にクールです。
実は少しだけトライしたことはあるのですが、難しすぎて挫折しました。
クワインとまではいかないまでも、何か意味のある実行可能なコードにできれば、よりテッキーな感じが出せそうです。

mmfetch の公開予定はあるか

せっかくなのでドヤ顔公開しようかと思っていたのですが、やっぱりやめることにしました。
元々 Magic Moment の開発チーム専用と銘打っていたものですから、せっかくなので Magic Moment 内で閉じておこうと思います。

ただ、そこまで難しいことはしていないので、前述の内容とシェルスクリプトの基本的なところを押さえておけば、多分誰でも作れます。
それでも、どうしても見たいという方は、是非とも弊社 Magic Moment にご入社ください。

まとめ

開発チーム専用のバーチャル背景をシェルスクリプトで作った話を紹介させていただきました。
さっそく開発チームのみんなが使ってくれて何よりです。一体感も爆上がりしました。

use1
use2

これを読まれた方も、是非シェルスクリプトでチーム専用のバーチャル背景をつくってみませんか。
「もっとこうするとラクに開発できるよ」といった tips がありましたら、コメントいただけると幸いです。

さて、明日のアドベントカレンダー渡辺さんM2 MacBook Air (M2, 2022) を DisplayLink を使用して2台の外部ディスプレイに接続するです。お楽しみに!

最後に

弊社 Magic Moment では、フロントエンド・バックエンドにかかわらず全方位的にエンジニアを募集中です!
シェルスクリプトは書けなくても大丈夫ですのでご安心ください。
Magic Moment に少しでも興味を持っていただけたら是非エントリーください!

脚注
  1. 作成期間中に組織変更があり、開発チームは開発ディビジョン (部) という呼び名に変わりましたが、本記事では便宜上「開発チーム」で統一します ↩︎

  2. オンラインミーティングなどで利用する、会社のロゴと自身の簡単なプロフィールが記載された画像のことです ↩︎

Discussion