systemd-networkd + wpa_supplicant でワイヤレスネットワーク接続
netctl で繋いでいたが、別のマシンで systemd-networkd での接続が比較的スムーズに行ったので、母艦の ArchLinux も systemd-networkd で管理することにした。netctl で接続したときはツールがいろいろ出てきて(wifi-menu, wpa_supplicant)、正直どうやって繋がっているのか分かっておらず、接続が切れたときにパニックに陥りすぐ復旧できなかったというのも systemd-networkd に揃える目的の一つ。
基本的に systemd-networkd - ArchWiki に従って進めることでうまくいった。
2010年くらいの Mac mini にパーティションを切って Arch Linux を入れている。Wi-Fi インターフェース(手元だと wlp2s0b1)は認識されているのが前提。
$ ip link ... 2: wlp2s0b1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DORMANT group default qlen 1000 ...
まず netctl 時代に作った設定ファイルを消す。systemd-networkd が netctl で作った設定ファイルを使うことも可能のようだが、前述の理由と、Arch Wiki にある方法が最小設定だろうということで、wpa_supplicant に置き換えていく。以下で全部だったと思うが確証はなく、実際は find /etc/systemd/
してネットワーク接続に関係しそうなサービスを全て消していった。
# rm /etc/netctl/wlp2s0* # systemctl disable netctl-auto@wlp2s0 # systemctl disable 'netctl@wlp2s0b1\x2dSSID.service'
再起動してネットに繋がらないことを確認。次に WPA supplicant - ArchWiki に沿って Wi-Fi 接続設定ファイルを作る。
# cat /etc/wpa_supplicant/wpa_supplicant-wlp2s0b1.conf ctrl_interface=/run/wpa_supplicant update_config=1
update_config=1 を追加すると wpa_cli による example.conf への変更が保存されるようになります。
とのこと。このあと wpa_supplicant-wlp2s0b1.conf に Wi-Fi SSID とパスコードが保存される。
# wpa_cli
ここでやることは Wiki にある内容とほぼ同じだったので割愛する。こちらを参照のこと。
しかし私の場合初めに list_networks
するとこれから繋ぐ SSID が登録されてあった。netctl も中で同じことをしていたのだろうか? 全て消し、 add_network
set_network 0 ssid "MYSSID"
set_network 0 psk "passphrase"
enable_network 0
しなおした。save_config
すると先ほどの wpa_supplicant-wlp2s0b1.conf に保存される。続いて起動時に接続を確立するようサービスを設定。
# systemctl start wpa_supplicant@wlp2s0b1.service # systemctl enable wpa_supplicant@wlp2s0b1.service
Wi-Fi が利用できる状態になったところで、systemd-networkd がそれを利用しネット接続するための設定をする。Match さえすればファイル名はなんでも良いよう。
$ cat /etc/systemd/network/wlp2s0b1.network [Match] Name=wlp2s0b1 [Network] DHCP=ipv4
全てのオプションは man systemd.network
で見られる。
私の場合は再起動が必要だった。ネットに繋がれば成功。
IndexedDB調査
IndexedDBの動きを見てみた。特徴とおぼしき点を列挙する。
- DBバージョンとマイグレーションのための機構を提供
- JSONで表現できる型しか保存できない
- functionが生えてるとこける
- 主キー、もしくはマイグレーション(onupgradeneeded)で予めindexを作っておいたフィールドでしか検索できない
- 検索は範囲(range)という形式でのみ行える
- getAll でレコードの配列を取得する方法と、openCursorで1件1件取得する方法がある
- offsetで取れない
- cursor.advance(n)で何とかするしかなさそう
以下は半年後全部忘れちゃった自分がすぐに思い出せる用gist:
`pointer-events:none;` で作る視覚効果
CSSで、視覚的には手前(z-indexが大きい)にあるんだけど、clickやmouseoverに反応しない(他の要素へのイベントを一切妨げない)要素、みたいの作れるんだろうか。画面の特定箇所をハイライトする目的で使いたい。
— piglovesyou (@takamura_so) March 21, 2016
知らなかった。こういうのがある。
pointer-events:none;
IE11+。全ブラウザが実装してる。使えそうだ。
Can I use... Support tables for HTML5, CSS3, etc
これとSVGを組み合わせると、ユーザーの操作を邪魔せずに、ユーザーの注意をコントロールする視覚効果を作れる。新規ユーザーへのチュートリアルや、入力補助、ヘルプなどに使えそう。
Result タブを選んでみてほしい。ユーザーを注目させるための視覚効果としてスポットを動かしている。
キーワードをハイライトできるテキストボックスをReactで作った
山場
ハイライト自体は、contenteditable
+keyup
+el.innerHTML.replace
ですぐに動く。問題はel.innerHTML = el.innerHTML.replace(...)
したあとカーソルが先頭に戻ってしまうこと。これによりユーザーが入力し続けることができず、入力装置として使い物にならない。
賢者がいた
師「この問題、好きなんだよね。けっこうやった。だいたい動いてると思うよ」。
カーソルの位置を特定するために、テキストノードまで潜って数を数える。最終的な位置セットやもろもろのユーティリティーにrangy
というライブラリを使っている。これがnpmにあってとても助かった。
npmモジュール
賢者からの返事を待ってreact-highlightable
という名前でnpm publishしようと思ってる。
インターフェース
とりあえずこんな風にした。
const Highlightable = require('../react-highlightable'); const validUsers = ["ariel", "belle", "jasmine"]; ReactDOM.render( <div> <Highlightable className="highlightable" onChange={onChange} pairs={[ [Highlightable.TokenPreset.URL, 'hilite hilite--link'], [Highlightable.TokenPreset.USER_MENTION, token => `hilite hilite--user hilite--user-${ validUsers.includes(token.slice('@'.length)) ? 'valid' : 'invalid'}`], ['yeah|ohh', 'hilite hilite--token'] ]} value='@jasmine and @belle are you still there? Visit www.google.com' ></Highlightable> </div> )
ハイライトする文字列のパターンとclassNameまたはclassNameを作る関数をペアで渡す形式にした。
よくありそうなURL、EMAIL、USER_MENTIONはプリセットとして正規表現を用意しておいた。
使いどころ
URLハイライトとかはコメント投稿のプレビューとかに使えるかも。全ユーザー一覧をローカルに持ってることは多くないはず。サーバーに問い合わせて&ハイライトの条件を変えて再び描画、という使い方になると思う。
既知の問題
ヒットしたキーワードにカーソルが接触した状態で改行されると、contenteditable
のデフォルトの動きがそうであるように、ハイライト用のスタイルを引き継いで新規行が作られてしまう。賢者のデモでも同じだった。スタイル次第では目立たないが、背景色があると結構めだつ。その後文字を入力すると問題は直る。
またハイライトしたキーワードにfontawesomeでアイコンをつけたところ、カーソル補正が壊れた。CSS擬似要素が文字カウントに影響しているようだ。こちらはなんとかなる気はする。
MutationObserver/Mutation Events は孫DOMへの操作も検知するのか
MutationObserver/Mutation Events は、孫DOMへの操作も検知するのだろうか。Chrome48.0.2564.103 とFirefox44.0.2で検証した。
※ざっくりした調査なのでご参考までに。
結論
MutationObserverは仕様にsubtree
オプションがあり、ChromeもFirefoxもこれを実装している。問題なく検知する。
Mutation Events (廃止された仕様) は、Chromeで一部検知しない。Firefoxでは検知できた。
Mutation Events
廃止された仕様。使ってはいけない。Mutation events - Web developer guides | MDN
とりあえず、この3つだけを調査の対象とする。全イベント一覧はこちら
- DOMAttrModified
- DOMNodeInserted
- DOMNodeRemoved
HTML
<body> <div> <div id="descendant"></div> </div> <script src="./main.js"></script> </body>
JavaScript
'use strict'; /* * Mutation Events を document.body に登録する */ [ 'DOMAttrModified', 'DOMNodeInserted', 'DOMNodeRemoved' ] .forEach(type => { document.body.addEventListener(type, e => { console.log('=======', e.type); }); }); /* * 孫DOMに対し、操作を加えてみる */ test(); function test() { let el = document.getElementById('descendant'); let textNode = document.createTextNode('boooom'); el.setAttribute('boom', 'boom'); el.appendChild(textNode); setTimeout(() => el.removeChild(textNode), 800); }
実行結果
Firefox
全てのイベントがdocument.body
まで伝播している。
======= DOMAttrModified a.js:10:5 ======= DOMNodeInserted a.js:10:5 ======= DOMNodeRemoved a.js:10:5
Chrome
DOMAttrModifiedだけdocument.body
に来ない。
======= DOMNodeInserted a.js:10 ======= DOMNodeRemoved a.js:10
MutationObserver
MutationObserver - Web API インターフェイス | MDN
結果として、FirefoxもChromeも仕様通り機能した。平和平和。
JavaScript
HTMLと、検証用test()
関数は上記と同じ。MutationObserverのコードをこうした。
/* * Mutation Observerを登録。 */ let mo = new MutationObserver(mutationRecords => { console.log('=======', mutationRecords.map(r => r.type)); }); mo.observe(document.body, { childList: true, attributes: true, characterData: true, subtree: true, /* ここポイント */ attributeOldValue: true, characterDataOldValue: true });
Firefox
======= Array [ "attributes", "childList" ] a.js:19:3 ======= Array [ "childList", "characterData", "characterData" ] a.js:19:3 ======= Array [ "childList" ] a.js:19:3
Chrome
======= ["attributes", "childList"] a.js:19 ======= ["childList", "characterData", "characterData"] a.js:19 ======= ["childList"] a.js:19
同じ結果を返していることが分かる。
参考にした記事
非推奨になった Mutation events を Mutation Observers に置き換えよう - ログろいど
urxvt が unicode 記号を見つけるのに失敗
軽量ターミナル urxvt (rxvt-unicode) でチェックマーク(✓)が出てくれなかった。
失敗したときのフォント設定はこちら。
! ~/.Xdefaults urxvt.font: xft:Ricty:Normal:size=14:antialias=true
✓ がでないと「ヨシッ」って気持ちになれないですよ。
rxvt FAQ によると、フォントは複数指定でき、見つかるまで順に探していくとのこと。
rxvt-unicode は最初にベースフォントから文字を探す。見つからなければ、次、次という感じ。持ってるフォントを予め宣言しておけば、探索も速いし rxvt-unicode と X-server のリソース消費も少なくて済む。
速そうで良い。他のターミナルがどうフォントを探すのかを知りたいところ。
チェックマークを求めて手持ちのフォントを試したのだが、この宣言で表示することができた。
! ~/.Xdefaults urxvt.font: xft:Ricty:Normal:size=14:antialias=true, \ xft:DejaVu Sans Mono:size=13
ヨシッ。
- rxvt FAQで説明のある
urxvt -fn basefont,font2,font3...
と、私の書いた .Xdefaults の設定が同等であるかどうかは未検証。 - DejaVu Sans Mono を size=14 にしたらまたダメになった。理由知っている方いたら教えてください。
- 参考