From crying 16yo to grieving 18yo

Xubuntu を 16.04 から 18.04.1 に上げたので諸々をメモ。

  • ターミナルで bdf/pcf フォントを使えなくなった。これはアップグレードの際はいつものことで、[cci]/etc/fonts/conf.d/[/cci] から no-bitmap.conf 的なものを削除し、yes-bitmap.conf だけを残す(なければ [cci]../conf.avail/[/cci] からシンボリックリンクを貼る)
  • ログインできない。正確にはパスワードをキーボードから打ち込んでも正しいパスワードと認識されない。スクリーンキーボードを使用すると通る。まだ原因は調べてない
  • ログイン直後、マウスの右ボタンを連続して押している状態になっているらしく、右クリックからのメニューがまともに使用できない。数分で勝手に治る。まだ原因は調べてない
  • xfce のパネルを縦置きしている。従来はテキストが縦方向に描写されていたのが横方向になってしまう。これは単に見た目の問題なので気にしないことにする。多分きっとおそらくそのうち修正される
  • xkb の設定がリセットされた。うちの機械では過去の記事の通りに [cci]/usr/share/X11/xkb/[/cci] 以下のファイルへ直接必要な設定を埋め込んでいるという若干行儀の悪いことをしているので当然だ。ホームディレクトリに設定を置くようにしてもいいのだが、そうするとたまにやらかしてリカバリーモードで起動せざるを得なかったときにぎょえーとなる。そういうわけで再び [cci]/usr/share/X11/xkb/[/cci] 以下のファイルを弄る
  • cifs のマウントの際 smb のプロトコル ver3 がデフォルトになったそうなのだが、そうすると Windows10 機との接続に失敗するようなので fstab で vers=1 を追記。対 Win10 なのになんで ver1 じゃないとだめなの? 暇があったらあとで調べる

それから、これはもしかしたら 16.04 の頃からだったのかもしれないのだが、Thinkpad USB Keyboard with trackpoint …のトラックポイントの加速度の設定が、どうも標準の設定画面からはできてない気がする。この辺を参考に設定。


$ xinput list
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint id=10 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Power Button id=7 [slave keyboard (3)]
↳ Integrated Camera: Integrated C id=8 [slave keyboard (3)]
↳ Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint id=9 [slave keyboard (3)]
↳ C-Media Electronics Inc. USB PnP Sound Device id=11 [slave keyboard (3)]
↳ Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint id=12 [slave keyboard (3)]

製品名は “Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint” とのことだ。

$ xinput list-props "pointer:Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint"
Device 'Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint':
Device Enabled (140): 1
Coordinate Transformation Matrix (142): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
libinput Natural Scrolling Enabled (276): 0
libinput Natural Scrolling Enabled Default (277): 0
libinput Scroll Methods Available (278): 0, 0, 1
libinput Scroll Method Enabled (279): 0, 0, 1
libinput Scroll Method Enabled Default (280): 0, 0, 1
libinput Button Scrolling Button (281): 2
libinput Button Scrolling Button Default (282): 2
libinput Middle Emulation Enabled (283): 0
libinput Middle Emulation Enabled Default (284): 0
libinput Accel Speed (285): 0.500000
libinput Accel Speed Default (286): 0.000000
libinput Accel Profiles Available (287): 1, 1
libinput Accel Profile Enabled (288): 1, 0
libinput Accel Profile Enabled Default (289): 1, 0
libinput Left Handed Enabled (290): 0
libinput Left Handed Enabled Default (291): 0
libinput Send Events Modes Available (261): 1, 0
libinput Send Events Mode Enabled (262): 0, 0
libinput Send Events Mode Enabled Default (263): 0, 0
Device Node (264): "/dev/input/event3"
Device Product ID (265): 6127, 24585
libinput Drag Lock Buttons (292):
libinput Horizontal Scroll Enabled (293): 1

このデバイスに設定できるプロパティ群。個別の詳細は [cci]man xinput[/cci] で知るべし。で、[cci]/usr/share/X11/xorg.conf.d/[/cci] あたりに適当にファイルを作って中身を

Section "InputClass"
Identifier "Trackpoint tweaks"
MatchProduct "Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint"
MatchDevicePath "/dev/input/event*"

# The default driver now, so optional to put in this line.
# But does not hurt mentioning where the options will go.
Driver "libinput"

Option "Accel Speed" "0.5"
EndSection

こんな感じにする。

Installing Digital TV into Linux

ふだん家では Linux マシンがメインで、サブの Windows マシンはたまにテレビを見るときにつけるという感じだったのだが。ここに来てそれに接続していた15年選手のディスプレイがついに壊れてしまった。なんということでしょう。ブラタモリと鉄腕 DASH が見れなくなってしまうじゃないか。

Windows マシンへは Chrome Remote Desktop を通してリモートで操作する選択肢もあり、10fps くらいになるが一応メインマシンからテレビを見ることはできる…のだが、これが恐ろしく負荷が高い。大体30分もすると熱のために勝手に電源が落とされてしまう。

さてどうするか。ディスプレイが壊れたのだからディスプレイを新調すればいいのだが、実際のところ Windows マシンはほとんど使っていないのであった。ほとんど使ってないマシンに素敵なナウいディスプレイくっつけて何が楽しいのか。何も楽しくない。

それよりも、メインマシンで直接テレビが見られれば遥かに楽なのだが。でも Linux で地デジなんてできるの…? と思いつつググってみたら、なんと今では録画サーバーなるものを Linux マシンで組むことはごくごくあったりまえの行為らしい。そ、そうなんだ…。すごい。

ということでこのあたりを参考にチューナーとカードリーダーを入手してみたところ、実に簡単に VLC でテレビを視聴するところまでいけた。すごい。

このままでも視聴自体はできるのだが、チャンネルを変えたりするのが若干面倒なのでここから Chinachu の諸々を入れるといいようだ。これはまあ、そのうちにやりたい(やらないフラグ)。

CPU 負荷はだいたい10%くらい。すごい。ところでサブチャンネルを選択したい場合とかはどうするのかな。

Pikoyan

再放送中のけものフレンズには字幕が付いているのだが:

  • サーバルがジャパリバスの運転席を持ってジャンプする最後のシーン、「ぴこやん!」としか聞こえない。たぶん「とりゃー!」と言ってるのだと思うのだがぴこやんとしか聞こえない。自信がないので書き起こしでは地の文でごまかしてある。どうしよう
  • タイトルで○○ちほーとよくあるが、字幕ではカタカナのチホーである。これはアプリ版でもそうなので、そうなのかなと迷ったのだが、とりあえず書き起こしではひらがなで統一してある。しかしカタカナが正しいとなると、じゃあ「へいげんちほー」はセリフとしては(ライオンが 1 度セリフとして発音している)へいげんチホー? 平原チホー? ヘイゲンチホー? 判断する材料がない。どうしよう
  • 再放送のソースは最初に放送されたそれに比べて若干の修正が施してある。これは intro や outro のテロップも含まれる。甚だしいところでは、声優名が全然違うものになってたりする。これはどれを底とすべきだろうか
  • 再放送とはあまり関係ないが、サウンドトラックによって各 BGM の題名が明らかになったので、書き起こしにおいて BGM が奏でられるタイミングでその題名を追加したい。が、困ったことにサウンドトラックに収録されているのはサウンドトラック用に編集されたものであって、放送されたものに含まれるものとは若干違うのであった。また、常に BGM の最初から奏でられるわけではなく特徴的な最後の締めが多用されたりするパターンもある。どうしよう

Integration #2

そういうわけで、設定のうち例外リストとなっていたものを site overrides とした。こんな感じで記述する:

http://example.org/* * block
http://example.net/*.html * writeas=p

ディレクティブとして有効な行は、3つの要素からなる。左から順に URL パターン、CSS セレクタ、アクション。まず URL パターンと CSS セレクタで要素を特定する。例外リストの段階では CSS セレクタは省略可能で、省略した場合ユニバーサルセレクタを指定したことになっていたが、省略不可能になった。サイトすべての編集可能要素を対象にしたい場合はユニバーサルセレクタを明示的に記述する必要がある。

最後の要素がアクションで、これが [cci]block[/cci] であった場合は、そのパターンに合致する要素上では wasavi の起動が抑制される。それ以外であった場合、set コマンドの引数として wasavi 起動時に評価される。つまり、exrc の最後に付加される。

 * * *

これとは直接は関係ないのだけど、バックグラウンド側での設定の持ち方を変えた。従来は各ブラウザの差異を吸収するような抽象的なクラスを経由していたが、単に chrome の API を直接呼ぶようにした。

Integration

wasavi のオプションに、writeas というものがあり、こういう仕様になっている。つまり、contentEditable な要素に対して wasavi のバッファを書き戻す際、どのような DOM の構造にするかを指定する。たとえば [cci]p[/cci] なら、各行を [cci]p[/cci] 要素として書き戻す。

しかし、当然ながら contentEditable な要素の内部構造をどのように保持しているかはサイトごとにまちまちであり、ひとつに決められるものではない。そこで、writeas には 連想配列を表す json 文字列を代入することも許している。こんな感じで:

set writeas='{ \
"http://example.com/*": "div", \
"http://example.net/*": [ \
{ \
"selector": "#any-css-selector", \
"writeas": "textAndBreak" \
} \
] \
}'

連想配列のキーが URL パターンで、値が writeas という形式だ。または、さらに連想配列の配列を入れ子にして、CSS セレクタを指定することもできる。これにより、つまりサイトごとに writeas の定義を分けることができる。

ただ……見てのとおり exrc 中に改行のエスケープしまくりで書かないといけないので、とても面倒くさい。また [cci]set all[/cci] した時の見栄えもとてもよくない。もっと洗練された形式で保持する必要がある。

ところで、サイトごとに定義を振り分けているものは wasavi はもうひとつ持っている。サイト自身が提供するスクリプトとコンフリクトするか何かでうまく動かない場合に、wasavi の起動をしないという例外リストである。これは普通のプレインテキストで

http://example.com/
http://exmaple.org/ #some-id

のように行ごとに URL を書き連ねる。URL のあとに任意の個数の空白を挟んで CSS セレクタを記述することもできる。これと writeas の定義を統合できないだろうか。つまり例外リストではなく per-site overrides という扱いにしたい。

override := URL-pattern (CSS-selector)? action
action := allow-actions
"block"
allow-actions := allow-action ("," allow-action)*
allow-action := "writeas" "=" writeas-value
writeas-value: "div" | "p" | "textAndBreak" | "plaintext" | "html"

という感じだ。

Mapping more modes #2

そういうわけでいろいろ変更している。

  • 特定のキー入力を別の入力に置き換えるために、最新の wasavi は以下の 3 種のマップを保持している:
    1. normal マップ: normal モード時に参照される
    2. bound マップ: bound/bound_line モード時に参照される
    3. input マップ: insert/overwrite モード時に参照される

    これ以外のモードにおいてはリマップはできない。これは技術的にできないのではなく、単に現状ではそういうふうにしていないというだけだ。

  • マップに対するルールの操作は、ex コマンド [cci]map[/cci]、および [cci]map![/cci] で行う。既定では、前者は normal と bound マップの両方を、後者は input マップを対象にする。どのマップを対象にするかは、後述のアトリビュートで変更できる。
  • [cci]map[/cci] [cci]map![/cci] は、最小で 0、最大で 2 つの引数を取ることができる。さらに、引数の前にアトリビュートを置くことができる。
  • アトリビュートは、先頭が [cci][[/cci]、末尾が [cci]][/cci] であるカンマ区切りの文字列である。アトリビュートのコンポーネントとして有効なものは、上記のマップ名か、もしくは [cci]clear[/cci] [cci]final[/cci] [cci]noremap[/cci] のいずれかである。
  • アトリビュートにマップ名が含まれる場合、デフォルトマップの代わりにそのマップが選択される。
  • アトリビュートに [cci]clear[/cci] が含まれる場合、選択されたマップに定義されたルールをすべて削除する。引数は使用されない。
  • 引数が 0 個の場合、選択されたマップに定義されたルールをすべて表示する。
  • 引数が 1 個の場合、lhs に引数 1 が部分的にマッチするルールをすべて表示する。
  • 引数が 2 個の場合、引数 1 を lhs、引数 2 を rhs として、選択されたマップ全てに対してルールを登録する。この際、アトリビュートに
    [cci]final[/cci] または [cci]noremap[/cci] が含まれる場合は、再帰展開しないマップとして登録される。

 * * *

ところでここまで修正したのを Selenium でテストしようと思ったら、何やらおかしい。wasavi を起動させたあと、キー入力が行われない。つまり textarea に対する sendKeys() は動くのだが、wasavi 本体の iframe への sendKeys() が動作しないようだ。

以下の chromium の issue が関係しているかもしれない:
https://bugs.chromium.org/p/chromedriver/issues/detail?id=1777
https://bugs.chromium.org/p/chromedriver/issues/detail?id=1819

Throw a query to twitter

Twitter で検索する際、いろいろ特殊な文法が使えるらしい。例えば url: を前置して URL を書くと、それにリンクしているツイートを検索できるそうなので喜び勇んで appsweets.net とか github.com/akahuku とかやってみたのだが。それによってわかったことは、日本人はけものフレンズのセリフ起こしとかグラディウスとかには食いついてくるのだが、wasavi にはほとんど興味を示していないということだった。なるほど。

Mapping more modes

wasavi の issue として、bound/bound_line に normal ではない個別のマッピングを行いたい、というものがある。

現状では、normal/bound/bound_line は MapManager 内部の command マップに収斂、insert/overwrite は edit マップに収斂、それ以外のモードはマップ不可、という形になっている。したがって、要件に応えるには、単に bound/bound_line 用の個別のマップを設けるだけでいい。

ただ、インターフェースの問題がある。ex コマンド [cci]map[/cci] は command マップを操作する。一方 [cci]map![/cci] は edit マップを操作する。[cci]![/cci] の有無の二者択一のため、第3のマップが入り込む余地がない。

vim では、これを nmap/vmap/xmap/smap/omap/imap/lmap/cmap… とむやみに ex コマンドを増やすことで対処している。さらに再帰的なマップ展開をしない版である nnoremap/vnoremap/xnoremap/snoremap/onoremap/inoremap/lnoremap/cnoremap… という群もあり、総数としてはかなりのものになっている。

これ、果たしてわかりやすい仕様なんだろうか。だいたいなんなの onoremap とか inoremap って。初見じゃあ己マップと祈れマップとしか読めないよ。何をするコマンドなのかさっぱりわからない。

どうもこんな感じに ex コマンドをホイホイ新設するのは良くない設計に思える。加えて自己記述性の低いコマンド名はもっと良くない。

そんなわけで、wasavi では noremap かどうかを指定するのは map コマンドに与えるアトリビュートという形式にしてある。アトリビュートとはつまり
:map [noremap] gh ^
などと LHS の前に角括弧つきで指定する部分のことだ。ちなみに noremap というアトリビュート名もなんかいまいちなので、例えば final にしようかと考えている。

で、定義先のマップもアトリビュートで指定するようにしてはどうだろうか。例えば
:map [bound,final]
みたいな感じ。map コマンドを投入してかつアトリビュートでマップを指定しなかった場合に選択されるデフォルトのマップは normal と bound の和集合になる。一方、map! コマンドの場合は対象は edit マップ。

また、引数なしで map/map! コマンドを投入した場合は現在定義されているマップを表示するが、その場合には対象となるマップも表示したほうがいいかもしれない。

Xmodmap alternatives?

Xubuntuで、Caps と Ctrl を交換するだとか、その他細々としたキーボードのリマップを、xmodmap でやっている。が、なんだか知らないが、xmodmap はとっくの昔に Obsolete らしいのであった。さらに困ったことに、数時間おきに xmodmap によるリマップが勝手にリセットされるのだ。いや正確に言うと数時間おきというのも違い、ランダムというしかないタイミングでリセットされる。わからん。どういう嫌がらせなんだ。

で、xmodmap の代替は xkb らしいのだけど。ちょっと調べてみてなんかめんどくさそうだなーまあ xmodmap でいいかな…というのをかれこれ年に3回位繰り返している。

しかしせっかくなので、いろいろ試行錯誤してみた。xkb は基本的に言えば、物理キーに対してどの論理キーとして振る舞わせるかを制御する。また Shift−Level なんかも制御する。それらの情報は /usr/share/X11/xkb 以下にテキストファイルとして保持されている。各ユーザのホームに個別の .xkbrc ファイルみたいなのを置いて上書きするような仕組みはない。やろうとするなら、.xinitrc なり .xsession なりで setxkbmap を呼ぶことになると思う。

さて実際にキーの割当を記述するのは、symbols/ サブディレクトリ以下のファイル群となる。
/usr/share/X11/xkb $ ls symbols
af by es hu kz mm pt terminate
al ca et ie la mn ro th
altwin capslock eu il latam mt rs tj
am cd eurosign in latin mv ru tm
apl ch fi inet level3 nbsp rupeesign tr
ara cm fo iq level5 nec_vndr se tw
at cn fr ir lk ng sgi_vndr typo
az compose fujitsu_vndr is lt nl sharp_vndr tz
ba ctrl gb it lv no shift ua
bd cz ge jp ma nokia_vndr si us
be de gh ke macintosh_vndr np sk uz
bg digital_vndr gn keypad mao olpc sn vn
br dk gr kg md pc sony_vndr xfree68_vndr
brai ee group kh me ph srvr_ctrl za
bt empty hp_vndr kpdl mk pk sun_vndr
bw epo hr kr ml pl sy

ここにたくさんのファイルがあるわけだが、個々のファイルはそれら自身が行うキー定義量によって実質的に階層化されている。例えば pc ファイルはほぼすべてのキーに対して割当を定義する。言語コードっぽいファイルは各言語に応じた部分だけを定義する。ctrl や altwin、shift といったファイルは、それぞれの個別のキーをどのように振る舞わせるかだけを定義する。このようにレイアウトや言語から独立して、ほんの一部の定義だけを行うものを option と呼ぶ。

言語による定義の場合、さらにその言語内でいくつかのバリエーションが必要になる場合がある。その場合は、例えば us ファイルであればそのファイル内で、基本の定義を継承し、必要な部分だけを変更したものを定義する。そのような定義を variant と呼ぶ。

これらのファイルから任意のものをピックアップし、定義量の大きいファイルから小さいファイルへ順々に定義を行うことで任意のキーレイアウトが完成する。

で、実際にキーボードの種別を指定するには /etc/default/keyboard ファイルを

XKBMODEL="pc105"
XKBLAYOUT="us"
XKBVARIANT=""
XKBOPTIONS=""

と言った感じに記述する。model -> layout -> variant -> option という並びがまさに前述の、定義量の大きい順から小さい順というトピックに対応している。

ということを踏まえた上で、行いたいリマップは:

  1. 左の Ctrl と、Capslock を交換する
  2. Menu キーを Compose キーにする
  3. 右の Alt キーを、F20 キーにする

1. と 2. については、標準でオプションが定義されているので、前述の keyboard ファイル中の XKBOPTIONS に “ctrl:swapcaps,compose:menu” という値を与えればいい。問題は 3. だ。3. を実現するには、us の variant を定義するか、あるいは新しい option を定義するか…が正道に思える。

しかし、実際に行うのはそのどちらでもない。というのは variant や option を新設するには、rules/ 以下のいろいろなファイルを併せていじる必要があり、とても面倒だからだ。しかもそれらの編集が間違っていると、X 上の文字入力が一切できない、つまりログインスクリーンから進めないというかなり困る状態になってしまう。実際にやらかして、アワワワワ…となった。

実際に行うのは、上記で参照している option の定義中に 3. の定義を忍び込ませるというものだ。かなりイケてないが、たぶんこれが xkb の定義ファイルを最小限いじるだけで済むベストな方法だ。us ファイルを使わないのは、それが定義順の左の方に位置するので、知らない定義で上書きされる可能性が高いからだ。option なら定義の最後なので上書きされる恐れはかなり小さい。

swapcaps の定義は ctrl ファイルの

// Swap the functions of the CapsLock key and the left Ctrl key.
partial modifier_keys
xkb_symbols "swapcaps" {
replace key { [ Control_L ] };
replace key { [ Caps_Lock ] };
};

というセクションなので、この中に

replace key { [ F20 ] };

という行を追加する。そして祈りながら再起動する。これで xmodmap でやっていたリマップを xkb で再現できた。

Screen Casting

wasavi の Readme の最初の画像2つは、素の textarea と、それに対して wasavi を起動した状態の対となるものにしてある。

ところで Twitter でたまに wasavi について tweet される際、それは最初の画像を添付してあったりする。前述の通り最初の画像は単に素の textarea の画像なので、wasavi についての説明になっていない。例えば:

これを解消するために、2つの画像をまとめ、スクリーンキャストによる gif アニメーションをこさえたい。素の textarea から wasavi を起動し、編集し、書き込んで終了するまでを録画すればいい。というわけで、gtk-recordmydesktop をインストールし、録画し、ogg theora 動画を生成した。それを適当なオンラインのコンバータで gif に落とした。

gif に落とす際のオプションとかはなかったのでディザが目立つが、まあこんなもんだろう!

* * *

適当なオンラインのコンバータに頼るのはやめ、ogv → gif 変換はローカルで ffmpeg により行うようにした。見苦しいディザは追放した、はず。