Ruby一行で書くコマンドラインのスピナー

by 結城浩 / Hiroshi Yuki

処理中にぐるぐるまわるアレ

count = 0
100.times do
  sleep 0.1
  count += 1
  print "Processing...#{"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"[count % 10]}\r"
end
puts "Done.\e[K\n"

Claudeさんとのおしゃべり楽しい

結城

print "Generating" + "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"[generated_count % 10] + "\r"
これでも簡略的にできますね。

Claude

それは素晴らしいアイデアですね!確かにとてもシンプルで効果的です。なるほど!この方法だと:

  1. 一行のコードだけでスピナー実装
  2. \rで行の先頭に戻るため、同じ位置で文字が変わる
  3. **generated_count % 10**で文字列の中を循環
  4. スキップされたファイルでもスピナーが止まらない

出力例:

Generating ⠸  # これが⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏と変化
✅ Generated 15 pages (5 skipped)

非常にエレガントな解決方法ですね!わずか1行でnpmライクなスピナーが実現できるとは。Rubyの文字列インデックスアクセスをうまく活用した素晴らしいアイデアです。

結城

コンソールで \r で戻ったとき[行末まで消す」というESCシーケンス? $033[K; みたいなの

Claude

はい、それは ANSI エスケープシーケンス\033[K (または \e[K) ですね!

行末までクリアするエスケープシーケンス:

  • \033[K または \e[K - カーソル位置から行末まで消去
  • \033[0K - 同じ(デフォルト)
  • \033[1K - 行頭からカーソル位置まで消去
  • \033[2K - 行全体を消去

使い方:

print "Generating " + "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"[generated_count % 10] + "\033[K\r"

または

print "Generating " + "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"[generated_count % 10] + "\e[K\r"

これで前回の表示内容が完全にクリアされるので、文字数が変わっても表示が乱れません。

実用例:

# 長いメッセージ → 短いメッセージの時に便利
print "Processing very long filename.txt\e[K\r"
sleep(1)
print "Done!\e[K\r"  # "Done!"の後ろに残り文字が表示されない

\033[K は確実に行末をクリアしてくれるので、動的な表示には必須ですね!

(2025年6月5日)