あんパン

こしあん派

Kensington SlimBlade Proの全てのボタンをbt2usbhid&Linuxデスクトップ環境下で利用する

bt2usbhidとはこれのこと。

github.com

端的に書くと、Bluetooth接続のキーボードやマウスをRaspberry Pi経由でPCに有線接続できるようにするソフトウェア。USB切替器を挟むことで複数PC間でBluetooth接続のキーボードやマウスを共有するのに役立つ。このブログではたびたび言及している(それだけ便利に使っている)。

そしてKensington SlimBlade Proはこちら。

かなり前から販売されていたSlimBladeのBluetooth版。長らく待っていたけれどようやく発売された。さきほど届いたので早速セットアップした。といっても接続自体は難しくなくて、bt2usbhidのREADMEにあるとおりにRaspberry Piに接続するだけ。

このトラックボールにはボタンが4つついていて、全てのボタンを認識させるためにはXorgの設定でButtonMappingを変更する必要がある。bt2usbhidは単純に入力のイベントをそのまま再送しているだけなので、USBで接続した場合と同じマッピングを設定すれば良い。ただし、bt2usbhidはキーボードとマウスを接続していてもひとつのUSBデバイスとして振る舞っており、別個のデバイスとして認識されるわけではない。lsusbしてみると分かる。

$ lsusb
...
Bus 001 Device 009: ID 1d6b:0104 Linux Foundation Multifunction Composite Gadget
...

USBIDが1d6b:0104のデバイスがそれ。1d6bはLinux FoundationのVendor IDであり、0104はMultifunction Composite Gadgetであることをあらわす。これはbt2usbhid上で定義した値なので、どの環境でもこのUSBIDのデバイスが登場する*1。このデバイスが接続された場合にButtonMappingを書き換えてあげれば良い。具体的には以下のようなファイルを /etc/X11/xorg.conf.d に放りこんであげれば良い。

Section "InputClass"
  Identifier      "Bluetooth to USB HID Converter"
  MatchUSBID      "1d6b:0104"
  Driver          "libinput"
  MatchDevicePath "/dev/input/event*"
  Option          "ButtonMapping" "1 8 3 4 5 6 7 9 2"
EndSection

ちなみにどのボタンを押したときにどのボタンが反応するかは xev コマンドを見れば分かる。

ButtonPress event, serial 34, synthetic NO, window 0x3c00001,
    root 0x75d, subw 0x0, time 23937374, (231,956), root:(4075,1003),
    state 0x0, button 1, same_screen YES

ButtonRelease event, serial 34, synthetic NO, window 0x3c00001,
    root 0x75d, subw 0x0, time 23937444, (231,956), root:(4075,1003),
    state 0x100, button 1, same_screen YES

ButtonPress event, serial 34, synthetic NO, window 0x3c00001,
    root 0x75d, subw 0x0, time 23937584, (231,956), root:(4075,1003),
    state 0x0, button 3, same_screen YES

ButtonRelease event, serial 34, synthetic NO, window 0x3c00001,
    root 0x75d, subw 0x0, time 23937855, (231,956), root:(4075,1003),
    state 0x400, button 3, same_screen YES

うまく動かない場合はこれを頼りに調整することができる。とはいえ、これまで有線のSlimBladeとExpert Mouse Wireless Trackballを利用していたがいずれも同じButtonMappingを流用できたので、全ての製品が同じ配列なのかもしれない。

なおSlimBlade Proにはdpiを変更するスイッチが筐体の右側面にあり、これはハードウェア側で調整されるようで何も設定しなくても押せばカーソルの移動速度が切り替わる仕組みになっていた。ただ切り替えると素早すぎてコントロールを失うのでデフォルトのまま使おうと思っている。

SlimBladeは高さが低めに作られていて手首に負担がかかりづらいし、ボールの受け軸を掃除しやすくメンテナンス性も高いのでトラックボールを使うのに抵抗がない人にはぜひオススメしたい。

GitHub ActionsでstをビルドしてArch Linuxにインストールする

Linuxデスクトップを利用しはじめてからこれまでターミナルエミュレータとしてurxvtを利用してきた。のだが、どうもサロゲートペアに対応していない?ようで絵文字を表示できないのがやや気になるポイントであった。

普段から絵文字を入力することはないのでずっと放置していたのだけれど、最近「突撃! 隣のLinuxデスクトップ」という記事を書く中でstという軽量ターミナルエミュレータの存在を知り、絵文字もうまく表示されそうだったので利用してみることにした。

st.suckless.org

stは各種設定をconfig.hに書き込んでビルドするという硬派な設計になっている。つまり設定を変更するたびにビルドする必要がある。ArchWikiを眺めると

Consider maintaining your own config.h and PKGBUILD.

https://wiki.archlinux.org/title/st

と書いてあり硬派だ…… と思う。

一応AURにはPKGBUILDがあるので、config.hを置いたディレクトリで BUILDDIR=$(pwd) yay -Sy st みたいな感じで設定入りのstをビルドすることはできる。しかしまっさらな環境でこれを自動化するのは面倒なので、ArchWikiに書かれている通りPKGBUILDを飼うことにした。

ArchWikiのPKGBUILDページを眺めてだいたい雰囲気を掴んで、 cp /usr/share/pacman/PKGBUILD.proto ./PKGBUILD してきて編集すればあまり詰まることはないかと思う。実際に書いたPKGBUILDは以下。

# Maintainer: Masayoshi Wada <developer@andantesoftware.com>

pkgname=st
pkgver=0.9
pkgrel=1
pkgdesc="A simple terminal implementation for X."
arch=("x86_64")
url="https://st.suckless.org"
license=("MIT")
depends=("libxft")
source=("${pkgname}-${pkgver}::https://dl.suckless.org/$pkgname/$pkgname-$pkgver.tar.gz"
        "config.h")
sha256sums=("f36359799734eae785becb374063f0be833cf22f88b4f169cd251b99324e08e7"
            "8c6e61cabdd083315863c77e72ef5f669496b24863c3f1420ce83af3927da53d")

prepare() {
  cp "config.h" "$pkgname-$pkgver/config.h"
}

build() {
  cd "$pkgname-$pkgver"
  make
}

package() {
  cd "$pkgname-$pkgver"
  make PREFIX=/usr DESTDIR="$pkgdir/" install
}

config.hを変更する度にsha256sumも変える必要があるのはややだるいが、ある程度カスタマイズしたら更新頻度は落ちるだろうからよしとする。

これでPKGBUILDファイルとconfig.hディレクトリを一緒に置いて makepkg -si するだけでインストールできる状態になった。しかしこれをGitHubに置いていちいちcloneしてきてビルドするのも自動化するにはやや手間に見える。せっかくならビルド済のデータをGitHub Releasesから配信すれば良いのではないかと考えて、GitHub ActionsのWorkflowを書くことにした。書いたYAMLはこちら。

on:
  workflow_dispatch:

permissions:
  contents: write

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    container: 
      image: archlinux:latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Initialize
        run: |
          pacman -Syu --needed --noconfirm base-devel
          useradd builder -m
          echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
          chmod -R a+rw .
      - name: makepkg
        run: |
          sudo -H -u builder makepkg -sC --noconfirm
      - name: Parse .SRCINFO
        id: srcinfo
        run: |
          sudo -H -u builder makepkg --printsrcinfo > .SRCINFO
          echo "version=$(grep pkgver .SRCINFO | awk '{print $3}')-$(grep pkgrel .SRCINFO | awk '{print $3}')" >> $GITHUB_OUTPUT
      - name: Create new release
        uses: softprops/action-gh-release@v1
        with:
          name: Release ${{ steps.srcinfo.outputs.version }}
          tag_name: ${{ steps.srcinfo.outputs.version }}
          files:
            st-${{ steps.srcinfo.outputs.version }}-x86_64.pkg.tar.zst

makepkgはrootで実行すると ERROR: Running makepkg as root is not allowed as it can cause permanent, catastrophic damage to your system. というエラーを吐いて落ちるのでビルド専用のユーザを用意して利用している。バージョンの文字列を作るところはやや強引だけどPKGBUILDと二重管理したくなかったので .SRCINFO を生成して読み取ってawkで抜き出す形にした。あたりが工夫ポイント。

最後にReleaseを新規に作成して成果物をアップロードしている。actions/upload-release-assetを使えばよいという記事を多く目にしたが、既にArchiveされていてsoftprops/action-gh-releaseを使えと書かれていたのでこれを利用した。tagを作ってpushするのでpermissionとして contents: write を足す必要がある。

ということで、stをビルドしてGitHub Releasesの成果物として置いておくことができるようになった。あとはこれをダウンロードして sudo pacman -U st-0.9-1-x86_64.pkg.tar.zst のような形でインストールすれば良い。

stでは絵文字を表示できる

絵文字も表示できるようになって大満足。まだ何もカスタマイズしていない状態なのでざっくり好みの状態に整えていきたい。

リポジトリは以下にあるのでforkするなりなんなりしてご自由にお使いください。

github.com

3Dプリンタを購入した

ここ2年くらいずっと買おうと思って後回しになっていた3Dプリンタを購入した。全く知識のない状態から使い始めたのでそのあたりの話を書いておく。

3Dプリンタの選択

購入したのはAdventurer3。誰に聞いても入門にはこれがいいと教えてもらえる。理由はよく分かっていない。

flashforge.jp

自室の空きスペース的には40cm*40cmの面積を確保するのが精一杯なのでこれよりも大きいものが置けず、自ずと選択肢が絞られていった。また、印刷するノズル等がむきだしのプリンターだと、結構丁寧にほこりをはらってあげないと使えないだろうなという予感がしており、外装のあるプリンタにしたかったというのもある。

最初はAdventurer3 Proを買おうかと考えていたけど、結局は無印の方を購入した。Adventurer3 Proはビルドプレートがガラスになっていて、そのかわり取り外しができない。また本体についているのとは別にノズルが1本ついてくる。ビルドプレートを外しやすい方がメンテナンスが容易なのでは、と考えてこちらにした。実際に使って比べたわけではないのでどちらがいいとかはよく分かっていないが、1万円安いのでそのぶん何種類かのフィラメントを購入できてお得だったと思う。ガラスプレートの方が造形物の取り外しはしやすいと聞いていたが、Adventurer3のビルドプレートも取り外して曲げればすぐに外れるので困ってはいない。

テストプリント

まずは電源を入れて、デフォルトで入っているモデルを印刷してみた。

マニュアルには船っぽいモデルが入っているように見えるけど実際には含まれおらず、この2cm角の箱しか存在しない。ひととおりの操作方法を覚えたら、今度は自分でモデリングしたものを印刷してみる。

自分でモデリングしたものを印刷する

リビングの壁にケーブルを這わせていてモールで隠しているのだけれど、曲がり角にフィットするジョイント部品が存在しないので勉強がてらこれを作ってみた。

Adventurer3でモデルを印刷するには、以下のステップを踏む。

  • CADソフト等で物体をモデリングしてstlファイルとして書き出す
  • スライサーソフトを利用してstlファイルを3Dプリンタ用のスライスデータに変換する
  • これをなんらかの手段で3Dプリンタに転送して印刷する

CADソフトはひとまずAutodeskのFusion 360を利用してみることにした。個人で非商用であれば無料で使うことができる。全く知識がなかったので、ひとまず公式のYouTubeの動画を見ながらなんとなく概念を獲得していく。見たのは以下の2本。2本目は前編なので当然後編があるけれど、やりたいことに対してはこれで十分なのでひとまずこれだけ見た。

www.youtube.com

www.youtube.com

基本的な考え方としては、一旦スケッチとよばれる平面図を描いてから押し出しによって厚みを出せば良いという理解をした。スケッチを描く際は線分に対して拘束と呼ばれる制約をかけていって目的の形状を作る。拘束が足りないと一部の角が直角になりきらずに線分が微妙に長かったり短かったりしてしまうので気をつける必要がある。

これをstlとして書き出してFlashPrintで読み込んでサポート材の設定を行なってからスライスする。3Dプリンタは最初に土台となるサポート材を印刷して、その上に造形物を印刷していく。

サポート材の設定を終えた状態

このスライスデータ(.gxファイル)をUSBメモリに入れてAdventurer3に差し込む。Adventurer3側でLANに接続している場合はFlashPrintからも転送することができるらしい。

出力して試した結果、狙いどおりモールにフィットすることが分かった。

テスト印刷

……のだが、左右逆に作ってしまった。というのも、スケッチの段階では上から見た図を描いたが、その後の押し出しで底面を天井にするように作ってしまったのだった。スケッチの段階では左右を反転させる必要があった。ということで、スケッチをやりなおして印刷して実際に設置した様子がこちら。

現地の様子

無事に曲がり角にフィットするジョイント部品を作ることができた。

モデリング自体にかけた時間はだいたい1時間くらい。印刷に2時間くらいなので、かなり高速に欲しいものを手にいれられる環境が整った。

今年はハードをやっていきたい、あわよくば売ってみたい(まだ確度は低そう)と考えており、もうすこしいろいろなものをモデリングできるように練習していこうと思う。その際にFusion360だと有償版を購入する必要があるが、これが結構お高く、Adobe製品くらいの価格感なので他のソフトの使用感なども確認しながらどのソフトを使っていくかを考えたい。

個人的なタスク・目標の管理方法

前の記事で軽く触れた通り、Todoistでタスクを管理している。そのあたりの話。

masawada.hatenablog.jp

割と忘れっぽい性質なのと、いろんなイベントを同時並行でやることが結構あって、破綻しないようにTodoistを使ってタスクを管理している。加えて無為に過ごしたくないなあという思いからここ数年はゆるく目標みたいなものを持っていて、Scrapboxで管理している。これらは一度設定してそのままにしてしまうと見るのすら忘れてしまうので、ある程度定期的に見直すタイミングを作っている。以下はざっくりどういうことをやっているかの紹介。

タスク管理

Todoistではレイアウトにリストとボードの2種類があって、それぞれ利用シーンに応じて使い分けている。

リストとボード

リスト

進捗を考えなくていいものについてはリストを利用している。アイディア帳的な使い方が多い。例えば前の記事で挙げていた技術ブログネタについてはリストを利用している。

前の記事にも掲載したリスト(例)

リスト内でもセクション分けはできるので「まだ記事にできるか分からないけどネタとしては面白そうリスト」みたいなものをセクション分けして置いておくことが可能。あとは、定期的なタスクは専用のセクションに放り込んでおくなども可能。

ボード

進捗をトラッキングしたいものはボードを利用している。いわゆるカンバンとしての利用。

テンプレートを用意しておいて、複製して使う形。レーンはInbox、Todo、In Progress、Waiting、Doneの5種類。Todoist自体にはオートメーションがなく、かつ完了済タスクはレーン間を移動できないので、手動でDoneレーンに移してから完了にしないといけないのが難しい。また、完了済タスクは見えなくなってしまうので、見たい場合は都度表示するボタンを押す必要がある。なんとかしてくれ〜と要望を出してみたりはしたけど特に変わらず。

テンプレート

引っ越しやフォトウェディングなどのように、順番に細かなタスクを消化していく系はこのカンバンで乗り越えた。その他にも、日々のタスクを詰め込むカンバンなども用意している。基本は日々のタスク用カンバンにこまごまと入れていくのだけれど、サブタスクが多そうなときはテンプレートをコピーして個別のプロジェクトに切り出す運用にしている。

完了した日々のタスクたち

ちなみに日々のタスク用カンバンだけTodoを2レーンに分けている。これは後述。

目標管理

Scrapboxを利用している。半期ごとに目標ページを作っている。

目標は以下の項目に分けて書いている。

  • 通期目標
    • 定量
    • 定性
  • 半期目標
    • 生活
    • 趣味
    • キャリア

通期の目標については、この1年でどうしても達成したいことがそれぞれ1項目だけ書いてある。この目標は一年間変更しない。

半期の目標についてはそれぞれの項目に必達と努力の2つに分けて具体的な内容を書いている。それぞれそんなに堅いものではなくて、必達には「今半期中に生命保険に加入する」みたいな目標が書いてある。あまりかっちりやりすぎて達成できないとモチベーションが下がるだけなので、必ずできるだろう項目を入れている。努力目標はやりたいことを書いて忘れないようにするためのもので、あんまり達成できている感じはしない。

前半期は生活、趣味、技術の3軸で目標を持っていたけれど、技術も趣味として扱う方が楽しめるんじゃないかなあという思いから趣味に統合して、キャリアという軸を増やしてみた。技術のところには、これからどういうことをしていきたいか考えるみたいな目標やこれを作りたいみたいな目標が入っていてごちゃ混ぜになっていたので、前者をキャリア・後者を趣味に分類しなおした形。どう転ぶかは不明。半年後にはまた違う形にしているかもしれない。

ペライチなページなのでScrapboxである必要はあんまりなくて、単純にメモが書ければなんでも良い。箇条書きを作りやすい点は便利かもしれない。少なくともTodoistひとつでやりきるよりは便利。

目標とタスクを忘れないようにする

冒頭に書いた通り、これらは設定しているだけだと放置してそのまま忘れてしまう。なので二週間に一度見直すタイミングを作ることにした。これをスプリントデーと呼んでいる。もともとはおそらく昔の社内用語で、スプリントプランニングとかバックログリファインメントとかスプリントレトロスペクティブとかのうちいくつかが合体したものと考えると良さそう。定義は曖昧。いまではこの用語を聞くことはまずない。自分はあんまりスクラムに明るくないのでだいたいそれっぽいイベントを定義してこの名前をつけている。詳しいひとが見たらツッコミどころ満載だと思う。

自分のScrapboxにおけるスプリントデーの説明

これをTodoistで二週間おきの定期タスクとして登録して忘れないようにしている。ただ結構スキップすることも多くて、去年の開催実績は15回だった。年間およそ52週あるとすると26回実施するはずで、半数ちょっとはできました、くらい。間があいても継続することが偉いという気持ちで、忙しいときは遠慮なくスキップして余裕のあるときに開催した。本来は定期的にやっていろんな効能を得たいわけだけれども、私生活は突発的なことがらが多いのでそこまで詰めると死んでしまうと思う。忘れずに継続することが大切で、ゆるくやるのがコツ。多少ルールから逸脱するのは仕方ない。

年ごとにKPTを書くページを用意して、その中でふりかえりを行う。スプリントデーでは直近2週間のふりかえりをざっくり書き出して、出てきたTRYを日々のタスク用カンバンのTodoレーンに登録する。その後Todoレーンを棚卸しする。Todoレーンは優先度順に並べたレーンと向こう2週間でやるタスク専用のレーンの2つを置いていて、必要なものだけ向こう2週間でやるタスクのレーンに入れて期限を切っている。

あとはTodoistの日々のタスク用カンバンを見て気が向いたときに消化すれば良い。自分はこのカンバンをChromeが起動する際に表示するページとして設定している。これでほぼ毎日嫌でも目にすることになるので、忘れることはなくなる。目標のページも同時に開いて存在を忘れないようにしている。


めちゃくちゃいいツールが登場したら乗り換えたり運用をやや変えるかもしれないけれど、いまのところ大きく変わるイメージはあまりない。どちらかというと何をやったか・やるかに重きを置きたい。そんな気持ちで、ここ1年くらいはこの運用で暮らしている。

毎週ブログを書く習慣を意識的に作っている

数日前に公開されたPodcastに出演した。

anchor.fm

この中でも触れている通り、最近は毎週ブログを書く習慣をつけている。始まりはCTOの id:motemen さんが毎週ブログを書いているなということに気付いて、自分より忙しいはずなのに自分にできないわけがないと考えたからだった。

motemen.hatenablog.com

加えて、これまで半期に1,2記事書くくらいのペースが続いていてアウトプットの量に引きずられてインプットも減っていく危機感があり、まずは手を動かすところから始めようと考えた。これが7月末くらいの出来事で、8月から毎週何かしら書いている。

目標の管理

目標は忘れないようにScrapboxに書いてChromeの起動時に表示されるようにしている。こういうページは目にする機会を増やすことでようやく意識できるようになる。設定は chrome://settings/onStartupOpen a specific page or set of pages を選んで表示したいURLを入力するだけ。自分は目標ページに加えて、Todoistも表示している。個人のタスクはTodoistで管理しているのだけど、そのあたりの話はまた今度。

毎週書いているけど、実はそれを目標にはしていなくて、月2を必達・年内20を努力目標とした。高すぎるハードルを設定すると簡単に不達になってやる気をなくしてしまうため。

Scrapboxに書いた目標

本当はスパンも短くして月ごとに目標を持つ方が良いと思う。その月達成できなければハードルを調整しつつ翌月の目標を設定できるため。半年スパンだと最悪半年書かないということが起きうる。今回はたまたま起きなかったけど、次の半年はこれも取り入れるかもしれない。

ネタの管理

ネタはTodoistで管理している。TodoistはiPhoneとWebのクライアントの出来がしっかりしていて、どちらからでも操作しやすいのが良い。メモ帳のように自由に入力できると散らかりやすいので、基本これで管理してもっと細かく書きたいことができたらScrapboxにするなどの使い分けをしている。

ネタたち(これは例で、実際にはこういうのが20件くらい入っているプロジェクトがある)

目標とは違って毎日見ているわけではなくて、ときどき眺めて次に何を書こうか考えるために利用している。項目は思い付いたら追加している。基本的に土日で記事を書くor書けるネタを作って次の金曜で公開することにしている(今回は曜日感覚を失って遅れてしまった)。土日で作り切れなかったら月曜から木曜でなんとかする方式。なので毎週土曜くらいにこのリストを眺めることが多い。

時間の管理

これは実は何もしていない。結構忙しいときはパッと小ネタを掴んで1時間くらいで書くし、そうでもないときはゆっくり土日に書いたりもする。というか忙しすぎて小ネタしか書けなかった。結果的に終盤は大きなネタしか残らず苦労したので、作業時間をうまく取るのが向こう半年の課題になりそう。単純に書くための時間を作るのもそうだけど、各ネタにどれくらいかかるのかの目算も置いておけるとよさそう。などなど、いろいろな話題がありそう。


試しに半年やってみて継続的に記事を書く習慣はできたので、次は時間管理やネタの管理をもうすこし改善して中くらいのネタを安定的に書ける状態を作ろうとしている。趣味なのだからもっとゆるくやればいいじゃんという気持ちがどこかでありつつ、しかし自分の場合は低きに流れるのをよしとすると無限に低まってしまうのでこれくらいが丁度良いのだと思う。ついでに誰かの参考になれば幸い。