B-Teck!

お仕事からゲームまで幅広く

はてなブログのコードブロックをコピーできるようにする

ブログにコードブロックを置いたときに、コピーボタンがほしいとずっと思ってた。
N番煎じすぎるけど一応メモしておく。

コード

CSS

管理画面 > デザイン > デザインCSSに以下を追記する。

:root {
  --btn-bg: #2d2d2d;
  --btn-bg-hover: #3d3d3d;
  --btn-bg-copied: #4a4a4a;
}

pre.code {
  position: relative;
}

.copy-button {
  position: absolute;
  top: 4px;
  right: 4px;
  padding: 8px 16px;
  border: none;
  border-radius: 4px;
  background: var(--btn-bg);
  color: #fff;
  font-size: 14px;
  font-weight: bold;
  cursor: pointer;
  opacity: 0;
  transition: all 0.3s;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}

pre.code:hover .copy-button {
  opacity: 1;
}

.copy-button:hover {
  background: var(--btn-bg-hover);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4);
}

.copy-button:active {
  transform: translateY(2px);
  box-shadow: none;
}

.copy-button.copied {
  background: var(--btn-bg-copied);
}

JavaScript

管理画面 > デザイン > フッタ のHTMLに以下を貼り付ける

<script>
  document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('pre.code').forEach(codeBlock => {
      const button = document.createElement('button');
      button.className = 'copy-button';
      button.textContent = 'Copy';

      button.addEventListener('click', async () => {
        const code = codeBlock.querySelector('code')?.textContent || codeBlock.textContent;
        const text = code.replace(/(Copy|✓ Copied)$/, '').trim();

        await navigator.clipboard.writeText(text);

        button.textContent = '✓ Copied';
        button.classList.add('copied');

        setTimeout(() => {
          button.textContent = 'Copy';
          button.classList.remove('copied');
        }, 2000);
      });

      codeBlock.appendChild(button);
    });
  });
</script>

macOSで音声入力の言語をキーボードショートカットで切り替える

macOSの音声入力を使っていると、日本語と英語を切り替えたくなることがある。
しかし、OS標準でのキーボードショートカットは用意されておらず、システム設定から「キーボード → 音声入力 → 言語」と辿って変更する必要がある。

何か良い方法はないかと調べてみたところ、シェルスクリプトで音声入力の言語を直接変更できることがわかった。 これをAutomatorでキーボードショートカットに割り当てることで簡略化する。

仕組み

Keyboard Maestro Forum - Switch Dictation Languages が参考になった。

macOSの音声入力の言語設定は defaults コマンドで変更できる。具体的には、以下の設定キーを操作する:

  • DictationIMNetworkBasedLocaleIdentifier: 現在の言語
  • DictationIMPreferredLanguageIdentifiers: 優先言語のリスト

設定変更後、DictationIM プロセスを再起動すれば即座に反映される。

実装

スクリプトの作成

まず、言語を切り替えるスクリプトを作成する。

mkdir -p ~/bin
cat > ~/bin/dictation-lang-toggle.sh << 'EOF'
#!/bin/bash

prefs="com.apple.speech.recognition.AppleSpeechRecognition.prefs"
key_locale="DictationIMNetworkBasedLocaleIdentifier"
key_order="DictationIMPreferredLanguageIdentifiers"

langA="ja_JP"
langB="en_US"

get_lang() {
    defaults read "$prefs" "$key_locale" 2>/dev/null || echo "$langA"
}

set_lang() {
    local lang1="$1"
    local lang2="$2"
    defaults write "$prefs" "$key_locale" "$lang1"
    defaults write "$prefs" "$key_order" "($lang1, $lang2)"
    killall -HUP DictationIM 2>/dev/null
}

toggle_lang() {
    local current=$(get_lang)
    if [ "$current" = "$langA" ]; then
        set_lang "$langB" "$langA"
    else
        set_lang "$langA" "$langB"
    fi
}

case "$1" in
    -g) get_lang ;;
    -t) toggle_lang ;;
    *) echo "Usage: $0 [-g|-t]" ;;
esac
EOF

chmod +x ~/bin/dictation-lang-toggle.sh

動作確認

スクリプトが正しく動作するか確認する。

# 現在の言語を確認
~/bin/dictation-lang-toggle.sh -g

# 切り替え
~/bin/dictation-lang-toggle.sh -t

# 再度確認
~/bin/dictation-lang-toggle.sh -g

初回は ja_JP、トグル後は en_US と表示されれば成功。

キーボードショートカットの設定

Automatorで、スクリプトをキーボードショートカットから実行できるようにする。

  1. Automator.app を起動
  2. 「クイックアクション」を選択
  3. 「シェルスクリプトを実行」アクションを追加
  4. スクリプト内容: ~/bin/dictation-lang-toggle.sh -t
  5. 名前を付けて保存(例: "Toggle Dictation Language")
  6. システム設定 → キーボード → キーボードショートカット → サービス
  7. "Toggle Dictation Language" にショートカットを割り当て

使い方

設定したキーボードショートカットを押すだけで、音声入力の言語が日本語⇔英語で切り替わる。再度音声入力を起動すれば、選択した言語で入力できる。

カスタマイズ

スクリプト内の langAlangB を変更すれば、他の言語ペアにも対応できる。

例: 韓国語⇔英語

langA="ko_KR"
langB="en_US"

制限事項: 音声入力の自動起動について

当初は、言語切り替え後に再度音声入力を起動することも試みた。 AppleScriptで 音声入力起動キーの押下をシミュレートすれば良いと考えたが、以下のエラーで動作しなかった:

osascript is not allowed to send keystrokes

これはmacOSのアクセシビリティ権限の制限によって、osascriptからのキーストローク送信が許可されていないことにより発生するものだった。
システム設定でアクセシビリティ権限を付与すれば解決する可能性もあるが、セキュリティ上の懸念もあり、今回は見送った。 ただし、言語切り替えだけでも十分に便利だったので、実用上は問題を感じていない。

2023年ふりかえり

blog.beatdjam.com

概況


転職以降、業務やドメインのキャッチアップに忙しくなってしまい、ブログや勉強会参加などがかなり減ってしまいました。
オンラインであれば参加可能な余裕は出てきたので、年明けから徐々に増やしていけたらなと思っています。

1,2,3月

  • 前職最後の大きめの機能開発
  • 転職活動

この時期は大きめの機能開発を2人で進めつつ、転職活動をしていたので割とバタバタしていました。
転職活動については以下の記事で書いています。
blog.beatdjam.com

4,5,6月

  • 教習所
  • 入社

有給消化期間で教習所に通い始め、6月頭に無事普通免許を取得しました。
人生でほぼ乗ること無いからせっかくだし、と思ってMTでしたが、難しかった…。
免許取得後、一度しか運転していないので公道を走るのはまだまだ怖い…。

5月中頃には新しい会社での業務がスタートしました。
5月いっぱいは研修やオンボーディングを受け、6月頃からチームに配属となっています。
これまで経験した組織よりも人数やフローの複雑度が高く、とにかくついていくので精一杯だった記憶があります。

7,8,9月

  • 業務のキャッチアップ
  • チームトポロジー読書会の参加

この時期になって、ようやくフローにもなれ、業務領域やドメイン知識に向き合うことができるようになってきました。
Java+JS、TSなので技術スタックとして未知のものはないものの、純粋なアプリケーションとしての難しさと戦っていたように思います。
(とはいえここ数年で主に触っていたのがKotlin、Scalaだったのでそれなりに思い出すコストはありました) リリースから年数が経っており、ユーザーの自由度が高いシステムはやっぱりそれなりに認知負荷が高いですね。

プライベートではチームトポロジーの勉強会に参加したりしていました。
社外でこういったものに参加するのは初めてだったのでいい経験でした。
細かい話は以下に書いています。 blog.beatdjam.com

10,11,12月

  • CSM研修受講

業務的に大きい出来事はあまりなく、半年経ってだいぶ慣れてきたこともあって粛々と進めるという感じでした。
チームが持っている複雑な機能の改修タスクが発生して、ちょうどよく知見を得られたのはよかったです。

また、チームでスクラムに対してどう向き合うかという話があり、CSM研修を受講しました。
blog.beatdjam.com

考えてること

技術

転職の結果、インフラから割と切り離された業務になりました。
Javaでの設計力やReactへの慣れが現状の課題かな〜と思っています。
Angularやったから割といけるだろ!と思っていたけど、やっぱり難しいものは難しい。

その他

どことなく余裕がなく、インプットもアウトプットも滞りがちな一年となってしまいました。
あんまり変化がなかったのもあり、途中で月次ふりかえりをやめてしまったり…。 こういうときはどうしても近視眼的になってしまって、俯瞰した目で見たり提案したりができないので、もうちょっと余裕を持って生きるを心がけたいなと思っています。
あとはしっかり気を抜くときは抜く。

読んだ本


今年は本もわりかし少なめだったな〜という感じです。
真面目に勉強する系の本をあまり読めませんでした。

小説

プロジェクト・ヘイル・メアリーは抜群に面白かったですね。

夏へのトンネル、さよならの出口も爽やかな青春SFとしてよかったです。

仕事系

チームトポロジーは今の組織で参考にされてる書籍なのもあって、非常に勉強になりました。

はじめて業務でSpring Bootを触るので、かなり重宝しました。
Spring特有の仕組み、挙動などが細かく解説されていて、この一冊ですごく解像度が上がったように思います。

おわりに

今年は変化が多く、新たな出会いが沢山あった一年でした。
引き続きやったことないこと、初めてのことにチャレンジしていきたいと思っています。
来年もどうぞよろしくお願いします。