あんパン

こしあん派

Linuxデスクトップで壁紙を接続する無線LANのSSIDによって変える

ということをやっている。

壁紙は feh で設定していて無線LAN APのSSIDは iw で取得しているのでそれぞれインストールしておく必要がある。以下のスクリプトをどこかに置いておいて、systemdでresume時に読むunitファイルを書いたら都度壁紙が変わる。

#!/bin/bash

# select wallpapers by ssid
if ! type feh > /dev/null 2>&1; then
  exit 1;
fi
if ! type iw > /dev/null 2>&1; then
  exit 1;
fi

SSID=$(iw wlp3s0 info | grep ssid | awk '{ print $2 }')
[[ $SSID = '' ]] && SSID='default';

if [ -e "${HOME}/.wallpapers/${SSID}" ]; then
  WALLPAPER_DIR="${HOME}/.wallpapers/${SSID}"
else
  WALLPAPER_DIR="${HOME}/.wallpapers/default"
fi
WALLPAPER_PATH="${WALLPAPER_DIR}/$(ls ${WALLPAPER_DIR} | shuf -n 1)"
[[ ! -f $WALLPAPER_PATH ]] && exit;

feh --image-bg white --randomize --bg-max ${WALLPAPER_DIR}/*

$HOME/.wallpapers 以下にSSIDのディレクトリを掘っておいてSSIDに対応する画像を置いておく。SSIDが既知のものでない場合は default ディレクトリにフォールバックされるのでこちらには富士山の写真を入れておく。富士山でなくても良い。こうしておくと、自宅では萌絵(萌絵って久しく聞かないね)を設定しておいて出先で開かないといけなくなったときは富士山の写真とかにできる。

もっとも、最近は外に出ることがなくなったので活躍の場がない。

SKK-JISYO.jawikiをibus-skkで利用する

Linuxデスクトップをメインの端末にしてからこれまで2年ほどibus-skkを利用しており、辞書はSKK-JISYO.Lとユーザ辞書のみという状態で固有名詞に弱いことを不便に思っていた。都度ユーザ辞書に登録すれば良いが、それも面倒なのでWikipediaからSKK辞書を生成して利用できると便利そう。どうせ同じようなことを考えているひとはいるだろうと思って探したところ、tokuhiromさんが作られていた。しかもGitHub Actionsで定期的にビルドされているのである程度最新版のWikipediaに追従されている。最高です、ありがとうございます。

github.com

ということで、これをibus-skkで利用することにした。最初は $HOME/.config/ibus-skk/SKK-JISYO.jawiki に置いて辞書として登録したのだが、どうも使われていない様子。調べたところUTF-8の辞書を置くだけだとibus-skkが読んでくれていないようだった。

対処方法は以下の2つのいずれか。

  • Coding Cookie (;; -*- coding: utf-8 -*-) をファイルの先頭に挿入する
  • dconfで辞書のencodingを設定する

実際に両方とも試したところ、それぞれ辞書が使われるようになった。

辞書の取得と登録を自動化したいのでCoding Cookieを都度入れるのは面倒そう。生成時に含めるようにPull Requestを送るかどうかでいうと、いずれにせよ辞書の場所を設定したりその他の調整も自動化したいのでシェルスクリプトでdconfを叩いたら良いかという気持ちになりそのようにした。

$ dconf write /desktop/ibus/engine/skk/dictionaries "[..., 'file=/path/to/SKK-JISYO.jawiki,mode=readonly,type=file,encoding=UTF-8', ...]"

といった具合。作業前後に dconf read /desktop/ibus/engine/skk/dictionaries で様子を見ておくと良い。

内田真礼を一発で変換できて助かる。

GitHubにcurlで公開鍵を登録する2021

masawada.hatenablog.jp

ここでcurlで公開鍵を登録する方法を紹介していたのだけど、GitHub全域でこれまでのユーザ名・パスワード・OTPによるBASIC認証が使えなくなったようだった。以下のようなエラーが返る。

{
  "message": "Requires authentication",
  "documentation_url": "https://docs.github.com/rest/reference/users#create-a-public-ssh-key-for-the-authenticated-user"
}

ではどうすれば良いかというと、Personal Access Tokenを利用する。

docs.github.com

まず Personal Access Tokens から Generate new token を選択してPersonal Access Tokenを発行する。この際にpublic keysに関する権限をつけておく。

f:id:masawada:20210310111118p:plain

あとは以下で公開鍵を登録できるようになる。

curl -XPOST \
  -H 'Content-Type: application/json' \
  --basic -u '<user>:<personal_access_token>' \
  -d '{"title": "user@hostname", "key": "<public_key>"}' \
  'https://api.github.com/user/keys'

または以下のようにAuthorizationヘッダをつける形でも登録できるようだった。こちらの方がシンプルだと思う。

curl -XPOST \
  -H "Content-Type: application/json" \
  -H "Authorization: token <personal_access_token>" \
  -d '{"title": "user@hostname", "key": "<public_key>"}' \
  "https://api.github.com/user/keys"

登録した公開鍵はPersonal Access Tokenをrevokeすると削除される。あくまで一時的なものとして扱われるらしい。

一見 X-GitHub-OTP ヘッダをつけた方がセキュアなのではと思ったが、Personal Access Tokenを利用することで権限を絞って認可できるし一般的な認証方法に乗っかることができるから良いという話なんだろうか。個人的にはOSインストールの自動化のために利用しているのでPersonal Access Tokenをrevokeすると鍵が削除される仕様を若干不便に感じるけどその方がセキュアそうなので諦めるしかない。

gitでコミットする前のファイルを選択して編集する

repoで作業していて変更を加えたファイルを開き直してさらに追記したいケースは少なくない。historyから絞り込んで選択するよりは、差分が発生したファイルのリストから絞り込む方が見通しが良いのではないか、ということで普段は差分が発生したファイルから絞り込んでいる。以下のようなファイルを git-edit-changed という名前で $PATH のいずれかのディレクトリの中に置いて実行権限をつけておくと git edit-changed コマンドとして呼び出せる。

#!/bin/bash

filepath=$({\
  git ls-files $(git rev-parse --show-toplevel) --exclude-standard --others --full-name; \
  git diff --name-only HEAD; \
} | sort -u | peco)
if [ ${#filepath} -ne 0 ]; then
  cd $(git rev-parse --show-toplevel) && ${EDITOR} ${filepath}
fi

git ls-files $(git rev-parse --show-top-level) --exclude-standard --others --full-name では、untrackedなファイルをrepo rootからのパスとして出力している。 --others はgit管理されていないファイル群を出力するためのオプション。これを指定するだけでは .gitignore 等でignoreしているファイル群も含まれてしまうため、これらのファイルを無視するのが --exclude-standard--full-name を指定することで自分がどのディレクトリにいてもrepo rootからの相対パスとして出力できる。

git diff --name-only HEAD では、HEADからの差分を出力している。git diff --name-only 単体では、indexと現在の差分が出力されてしまうので、 HEAD をつけることで最新コミットからの差分を出力する。untrackedなファイルはindexに追加すると上記のコマンドでは出力されなくなり、こちらのコマンドで出力されるようになる。

これらの出力を {} でひとつにまとめてパイプで sort -u | peco に渡して絞り込んでから $filepath に代入している。といった具合でHEADとの差分一覧(コミットする前のファイル一覧)を取得できる。

どうぞご利用ください。

git管理下のファイルのみをtree表示する

treeはみなさんご存知便利なコマンドで、cwd以下のファイルをツリー表示するもの。だいたいの環境にはデフォルトで入っていないので、 brew などで入れる必要がある。

$ tree
.
├── hello.txt
├── test
│   └── hoge.txt
└── world.txt

1 directory, 3 files

大抵のソフトウェアのプロジェクトでは node_modules のような依存ライブラリ群をプロジェクトのディレクトリに内包しているのが常で、gitで管理している場合は .gitignore で無視することがほとんどだと思う。このような環境下でtreeを使うとこれらのファイルが一気に出力されてノイズとなることがしばしば。初めて参加するプロジェクトのコードを読む際はどこから読むかあたりをつけるのにtreeコマンドが便利そうだが、正直このままでは使いづらい。

treeには --fromfile オプションがあり、パスのリストをファイルから読み取ってツリー表示することができる。更に --fromfile=. とすると、標準入力からパスのリストを受け取ることができる。git ls-files | tree --fromfile=. とすることで、git管理しているファイルのみ、つまり依存などが無視されて純粋にプロジェクトそのもののファイルリストのみがツリー表示されるようになる。例えば以下は以前書いたbt2usbhidのプロジェクトルートでの出力。.gitignore で指定されている bin/bt2usbhid はファイルとしては存在するが、ツリー表示には出力されていないことが分かる。

$ ls bin
bt2usbhid  init_bt2usbhid
$ git ls-files | tree --fromfile=.
.
├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── bin
│   └── init_bt2usbhid
├── config
│   ├── 99-bluetooth.rules.example
│   ├── bt2usbhid_keyboard.service
│   ├── bt2usbhid_mouse.service
│   └── init_bt2usbhid.service
└── src
    ├── keyboard.c
    ├── keyboard.h
    ├── main.c
    ├── mouse.c
    └── mouse.h

3 directories, 14 files

github.com

以下のシェルスクリプトを $PATH のいずれかのディレクトリの中に git-tree という名前で実行権限をつけて入れておくと、 git tree サブコマンドでこれを呼び出すことができる。

#!/bin/bash

set -e

if ! type tree > /dev/null 2>&1; then
  echo 'command not found: tree'
  exit 1;
fi

git ls-files | tree --fromfile=. "$@"

インターネットで探したところ、これと同等の機能をGoやPythonで実装したツールが出てきたが、tree自体に実現する機能があるのでtreeを使う方が柔軟性があって良い。treeにはまだ面白いオプションがいくつかある。例えば -J オプションでツリーをJSONに変換することができる。上記のスクリプトはそのままオプションを受け取れるようにしているので、以下のようにJSONを出力することができる。

$ git tree -J
[{"type":"directory","name": ".","contents":[
    {"type":"file","name":".gitignore"},
    {"type":"file","name":"LICENSE"},
    {"type":"file","name":"Makefile"},
    {"type":"file","name":"README.md"},
    {"type":"directory","name":"bin","contents":[
      {"type":"file","name":"init_bt2usbhid"}
    ]},
    {"type":"directory","name":"config","contents":[
      {"type":"file","name":"99-bluetooth.rules.example"},
      {"type":"file","name":"bt2usbhid_keyboard.service"},
      {"type":"file","name":"bt2usbhid_mouse.service"},
      {"type":"file","name":"init_bt2usbhid.service"}
    ]},
    {"type":"directory","name":"src","contents":[
      {"type":"file","name":"keyboard.c"},
      {"type":"file","name":"keyboard.h"},
      {"type":"file","name":"main.c"},
      {"type":"file","name":"mouse.c"},
      {"type":"file","name":"mouse.h"}
    ]}
  ]},
  {"type":"report","directories":3,"files":14}
]

これでファイルリストをプログラムやjqなどのコマンドに食わせやすくなる。同様に -X オプションでXMLを出力することもできるし、 -H . とすればHTMLを出力することもできる。もっともこれらが役立つ場面があるかというと滅多になさそうではあるが、覚えておくと役に立つことがあるかもしれない。


追記(2021-02-24): 指摘いただいて、 git-tree のスクリプトの $@"$@" に変更しました。引数にスペースが含まれている場合に分割されてしまうためです