かな入力を断念してAZIK + SKKになりました

気がついたら2月でした。書き出しがほとんど前回と一緒なので、そのへんなんとかしたいところです。 さて、実は今回結構大きめの決断をしたので、なんでそれに至ったのかを書いていきます。まぁそこまで強い理由がある、というわけでもないのですが。 <!–more–> かな入力、やめました 今まで、 https://github.com/derui/oif こういうものまで作って色々かな入力を試してきました。実際に使っていたと思しきコミット履歴を見てみると、2013年とかになっているので、都合7年くらい前からですね・・・。 実際、ほとんどはマイナー配列に属するようなものばかりでしたが、それなりの数を使ってきました。 月配列 新下駄配列 蜂蜜小梅配列 薙刀式 この中で一番長続きして、かつ速度が実用に至ったのは、月配列と蜂蜜小梅配列です。どっちも秒間3〜4カナとかは普通にいけてました。ちなみに、上二つが中指シフト、下二つが親指でのシフトです。 しかし、これを書いている現在は、AZIK + SKKという組み合わせになっています。SKKは多分8年振りくらいに戻ってきました。AZIKはなにげに初めてですね。 なんでかな入力をやめたのか これはいくつかの理由が複合しています。決してその配列に問題があるわけではない、ということは強調しておく必要があります。 親指の負荷が馬鹿にならないレベルになってしまった SKKとの相性が悪すぎた どうしても運指がローマ字入力の速度になってしまう 一つずつ少し深掘りしてみます。 親指の負荷 まず、私が使っているキーボードは、 Crkbd である、ということが前提にあります。このキーボードでは、一般的なキーボードよりも親指に色々機能を割り振ることを前提としたキー配置になっています。 詳しくは、私のキー配列を見てもらうとわかりやすいのですが、かなりの量の機能を割り振っています。 https://github.com/derui/qmk_firmware/blob/master/keyboards/crkbd/keymaps/derui/keymap.c 簡単に挙げると、 LOWER/RAISEでの数字・記号の入力 SandS/SandEnterによる、小指でのシフト全廃 かな・英数のトグル ADJUSTに矢印やsway/i3用の定義が満載 という感じで、普通のUS/JISキーボードとは比較にならないレベルで機能を割り振っています。親指でのシフトを行うかな入力は、これに加えてシフトをしないといけないため、親指の負荷が半端じゃありません。 親指は強い指ではありますが、それは筋力が強い(元々は支持するための指なので)ということであり、ほかの4指に比べたら遥かに鈍いということもあります。実際、親指に機能を割り振りすぎたゆえに、親指に変な痛みが生じたのは一度や二度ではありません。 SKKとの相性 これは一言です。 親指シフト系統とSKKの相性は最悪 です。少なくとも私にとっては。SKK自体では、一応NICOLA/旧JISかなをサポートしてはいますが、それを参考にしてみた限りでは、とてもではないですがQWERTYでの書き味とは全く異なる、と言わざるを得ません。 SKKとの相性自体は、そもそもSKKを使わなければいいじゃん、という話もありますが。SKKは一回使うとクセになってしまうところがあるので、相性が悪いということが許せなくなってしまった、というのもあります。 大分四苦八苦してみましたが、最終的な結論としてはこうなりました。多分、親指の負荷が低い月配列や新下駄配列であれば、そこまでの問題にはならないんじゃないかとは思いますが。 運指速度の問題 これは、特に親指でのシフトをする配列で顕著でした。今迄20年以上使いつづけており、かつプログラムを書く際にもずーっと使いつづけているのがQWERTY、そしてローマ字入力です。このときの運指速度がデフォルトになってしまっており、これとかな入力時の運指速度がバッティングしてしまう、ということが度々発生していました。 同時打鍵を要求する配列は、仕組み上どうあがいてもローマ字入力に匹敵する運指速度になることはありません。名目の打鍵数が低いから問題ない、とする向きが強いですが、同時打鍵という仕組み上、実際には少なくない数の打鍵は2打鍵必要です。 このあたりで折り合いを付けられなくなった、という形です。 かな入力はダメだったのか ある程度の速度にまでは到達できていましたし、実際には打っていて楽であった、ということもあります。なので、ダメだった、という二元的な評価ではありません。 単純に、合うか合わないかを実験してみた結果として、合わなかった、ということです。ブログでもなければ、プログラムを書く量の方が多い日もある、という事実もあるので、どちらにせよQWERTYの配列を変える方が余程効果がありそうですし。 AZIK + SKK さて、AZIKですが、これはこれでSKKで使われる上で、いくつか問題がありました。 q が潰される ; が「っ」になるので、switcky keyが使えない X が「sy*」の接頭になるので、辞書の削除が使えない これらをとりあえず解決してみました。こんな感じになります。 ;; azikを利用するように (setq skk-use-azik t) (setq skk-azik-keyboard-type 'us101) (require 'skk-azik) ;;; azikから追加された各種拡張を、SKK寄りに戻すための追加設定 ;; 「ん」をqに割り当てるのは、ただでさえ負荷の高い左小指を酷使することになるので、元に戻す (skk-delete-rule skk-rule-tree "q") ;; qの役割を元に戻したので、「も元に戻す (skk-delete-rule skk-rule-tree "[") ;; Xで辞書登録する場合があるので、この場合でもちゃんと破棄できるようにする (skk-add-rule skk-rule-tree '("!" nil skk-purge-from-jisyo)) (skk-add-rule skk-rule-tree '("q" nil skk-toggle-characters)) (skk-add-rule skk-rule-tree '("[" nil "「")) SKKは、 skk-add-rule とか skk-delete-rule といった便利関数を提供しているので、こういうのが簡単にできます。注意としては、 skk-azik は、何か関数を呼びだして変換ルールを設定しているわけではなく、requireされた瞬間に変換ルールを設定しているので、事後に追加したり削除したりしないといけない・・・ということです。 ...

February 23, 2021 · derui

OCamlでSchemeを実装してみている

気づいたら1月が終わりそうです。そしてPS5が当たりました。まだ特にやるものは決めてないんですが、総計抽選回数2回目で当たったので、日頃の行いが良かったんだと思います。 最近引っ越しにかこつけて、環境をいろいろ変更しています。その話でもう一回くらい書けるネタはあるんですが、今回はなんとなく始めたOCamlでのScheme実装について書いてみたいと思います。 <!–more–> とりあえずリポジトリ https://github.com/derui/scheme-ocaml-impl この記事の時点だと、 primitiveな関数は極々一部のみ 数値は整数のみ define/if/set!/let/lambda を実装済み defineでのlambda定義はまだやってません という、必要最小限すぎる実装となっています。いろいろ余裕があったら、r7rsに準拠できるように実装していく想定ですが、途中で飽きる可能性もめっちゃ高いです。 動機 さて、なんでOCamlでSchemeを実装しようと思ったのか?ですが、これはもうかなり簡単です。 もともと言語実装をやってみたかった 実はまともに実装したことがない・・・ 仕事でKotlinばっかり書いてるので、OCamlを書きたかった Schemeは昔から実装してみたかった という、やってみたかった駆動開発です。SchemeはSICPとかでもサブセットの実装を行ったりしているらしく、またscheme/lispでの実装例が結構多いです。これは、scheme/lispをそのまま使う場合、めんどくさいread/parserの部分が全部ないし一部をそのまま流用できるため、実装の総量が減り、また見通しが良くなりやすい、という理由っぽいです。 実装の参考にしている資料 昔探したとき、なんかいろいろあったよなー・・・と思いながら探していたら、こんなのを見つけました。 https://www.cs.utexas.edu/ftp/garbage/cs345/schintro-v13/schintro_toc.html 本当に最小限の実装から、lambdaやmacroの実装、compilerの実装とかまで進んでいくようで、結構分量が多いです。ちなみにこの資料だと、schemeでschemeするタイプなので、OCamlで実装する場合は前提になっているいろいろなものを事前に実装する必要があったりします。 OCamlで実装してみてよかったこと・悪かったこと JSONやES5のlexer/parserくらいは実装したことがありますが、実際にOCamlで言語を実装したのは初めてでした。とりあえず動く、というところまでやってみて、OCamlで書いた感想を挙げてみます。 Pros/Cons 内容 Pros lexer/parserの実装からASTを組み上げるのが楽 Pros パターンマッチがeval時にやはり強力 Cons schemeのcons listをパターンマッチだけでやるとこれはこれでめんどくさい。OCamlのlistに変換とかできるけど、それを毎回やるとそれはそれで重くなりそう Pros monadicな実装が簡単(まだちゃんとやっていないけど) Cons 引数のリストを組み上げるときとかがめんどくさい 概ね、schemeで超多用されるlistをOCaml内で扱うのがめんどくさい・・・、という感想です。どこかで見ましたが、最低限のspecial formとmacro/syntax-ruleなどを実装したら、後はschemeだけで実装していくのがやはり楽なのでは・・・?と思ってしまいます。もちろん、scheme自体では実装できないもの(比較とか)はprimitiveで実装しないとなりませんが。 ただ、OCamlで組み込み関数を実装するのは、Cとかで実装するより楽です。型のチェックでパターンマッチを使うだけで済むので、他の関数を呼び出す必要もありませんし。 これから実装していく方向 現在、schemeの式はすべて (data, string) result という型になるようにしています。ただ、例外とかを考えると、もうちょっとちゃんとしたmonadになるようにしてあげた方がいいかな?とは思っています。エラーの種類とかもほしいので。 まだmacro/syntax-ruleとかの実装が全くできていないので、ここを早めに実装していこうかなー、と思っています。 言語実装でOCamlはオススメです もともと関数型言語(Haskell/Lispとか)は、言語実装に向いている言語です。OCamlはReasonML(リブランドされてReScriptになるようですが)などの実装自体でも利用されていますし、以外なところで使われていたりします。 また、OCamlはMenhirという強力なパーサージェネレータがあったり、ocamllexというlexerジェネレータが組込だったり(ocamllexにもより強力な代替があったりします)と、手軽にlexer/parserを実装する環境があります。 OCamlに興味があるけどなー・・・、という方は、簡単な言語実装などしてみちゃーいかがでしょうか。楽しい?よ?

January 24, 2021 · derui

Linux環境をいろいろ変えた話

ふと気づいたら年が終わりそうですね。今年はどこもかしこも大体コロナのせい、という感じになりましたが。 前回PCを新調した話をしましたが、中身も1x年ぶりに新調しました。いろいろ変えたので、その話を書いてみます。 ...

December 21, 2020 · derui

引っ越ししたのでPCを新調した話

私用でいろいろ忙しかった原因である引っ越しが終わりました。数えたら8年半くらい同じ場所に住んでました。 で、引っ越しを期に自作PCを新調したので、それについて書いてみようと思います。 <!–more–> なんで新調したのか? 心機一転、という話もありますが、一番は 使っていたPCがめっちゃでかい ってことでした。 ちなみに前のPCで使っていたケースはこれです。 Themaltake Urban T81 https://kakaku.com/item/K0000626152/?cid=shop_yahoo_dsa_00010032&yclid=YSS.1000163161.EAIaIQobChMI5MqMh6LH7QIVV3RgCh3HQAkMEAAYAyAAEgLUW_D_BwE フルタワーケースで、全高が 61cm あります。このサイズの何が問題というと、実際に問題として感じていたのは以下のような点です。 入るPCラックがほとんどない 入手できそうなもので唯一入りそうだったのがこれです。これも割とギリギリまで伸ばさないとならなかった・・・。 重い スチールラックなので当然ですが、重いです。全部部品が組み込んであると、だいたい20kgくらいになるので、ダンボールに入れるのも一苦労です(でした よく考えたらそこまででかくなくていい ディスクの拡張とかそんなにしないし、でかいGPUを積むわけでもないし・・・ また、途中で一回M/Bのメモリ部分が故障してM/BごとCPU/Memory/CPUクーラーを全部新調したことはありますが、都合6年ほどこのケースを使っていたというのもあり、全面新調に至りました。 とりあえず新しいPCの構成 構成はこんな感じです。大体アッパーミドルくらいかな・・・。 ケース:Fractal Design Define R6 評判のいい、ミドルタワーケースです CPU:Ryzen9 3900XT CPUクーラー:Nocture NH-U12A かなり高価なクーラー。しかし、Ryzen9シリーズを空冷で冷やそうとすると、これくらいは欲しかったので SSD システム:Crucial M.2 P5(500GB) ストレージ:Crucial MX500 1TB HDDを卒業して、full SSD構成にしました。NVMeも使ってみたかったので。 Memory:Corsair 16GBx2 電源:Corsair RM750 GPU:Radeon RX 5700XT マザーボード:ASRock Steel Legend B550 初めて全面的にAMD構成にしてみました。Ryzenの5xxxシリーズは全滅していたので、潔く3900を使っています。 ちなみにお値段は、しめて21万程度でした。ドスパラでまとめて購入しましたが、BTOでも大体同じくらいの値段になっていたので、まぁ相場通りかな、と。 組んだ 大体2時間くらい・・・。毎回組むたび思うのは、システムパネルのケーブルはもうちょっと楽にならんのか・・・。というところですね。 ASUSのM/Bを使ったときにあった、 Q-Connector はほんとに楽だったので、これが標準添付されてほしいです。 https://www.pc-master.jp/jisaku/fp-connector.html ここで紹介されてるみたいなやつです。システムパネルはたいてい最後の方に組み込むことが多いと思うので、割と無理のある姿勢で細かい作業をしないとならないことが・・・。 とりあえずは、ちゃんと動きました。相変わらず最初の起動は緊張しますね。幸い今まで初期不良にはあたったことが無いのですが、ここで動かないときの絶望たるや凄まじいことと思います。 OSをインストール・・・できない? さて、このPCにインストールするのは、かれこれ10年くらい使い続けているGentoo Linuxです。ただし、今回はCPUが切り替わるということもあったので、10年ぶりにclean installすることにしました。 いつもの通り、USBにminimal imageを書き込んで起動、さてstage3を持ってくるかー、というタイミングで気づきました。 ...

December 12, 2020 · derui

GitHub Actionsでrelease processを作ってみた

私用でいろいろ忙しく、部屋の中がとっ散らかってしまっています。いらないものを整理していくのは大事・・・。 さて、今回はちょっと前につくった、GitHub Actionsを使ったリリースプロセスについてちょこっと書いてみます。 <!–more–> GitHub Actionsとは https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions 内容については、公式が詳しいのでそっちで。すげー簡単に言うと、GitHubに統合されたCodeBuildみたいな感じです。 GitHubがMicrosoftに買収されたことが影響しているのか、GitHub Actionsの中身はAzureの仮想マシンを使っているようです。公式ドキュメントに書いていたかと。 GitHub上にあることの利点としては、リポジトリとかの認証がいらず、かつソース上の設定とめっちゃ近いので、コンテキストの切り替えコストが低くなります。 GitHub Actionsの基本 自分の理解を試すために、ちょっとだけ基本的な概念だけ書いておきます。 Actionsは、 Event 、 Runner というランタイム的なものと、 Job > Step > Action という階層構造の定義があります。 このEvent/Runner/Jobを合わせて、 Workflow と呼ばれます。Github Actionsは、このWorkflowという単位で定義を作ります。 また、 Job はデフォルトで並列で動作するようになっています。(なので、これを忘れて上から動くような感じで書いてしまうと、全部一気に動いて大体エラーになる、ということになります) 作ったrelease flow https://github.com/derui/sxfiler/tree/master/.github/workflows こういうのを作りました。tagをpushするといろいろビルドして、最終的にGitHub Releaseを作成するようなフローになっています。 詳細は中身を見てほしいんですが、いくつかハマりポイントがありました。 Jobごとに異なる環境で動く ちゃんとドキュメントを読めば書いているんですが、jobは各々 完全に独立した環境 で動作します。CodeBuildとかとは設定のレベルが違うので、割と混乱しました。 完全に独立した環境、なので、各々の環境でcloneしてこないとなりません。これもしばらくなんでやろ・・・?と思ってしまった感じでした。あんまりjobを複数使ったり、というのは、シンプルなOSSとかだと無いと思います。 Dockerは普通に使える 各環境は単独の仮想マシンなので、普通にDockerが使えます。性能も意外と悪くない(2vCPU/7GiB)です。 ただ、私の作ったDockerfileみたいに、めっちゃ重いDockerfileを使う場合は、セオリー通りDockerHubとかにbuild済みのイメージをpushしておくのが良いです。 job間のファイルやり取りはartifactで job間は特に関連がないので、個々のJobで出来たものをまとめたりする場合、artifactを使う必要があります。 Releaseを作って、アセットをアップロードする場合は、大抵1つのJobにまとめられると思います。こういう場合はartifactを使う必要があります。 cacheはjob毎 cacheを利用する場合、基本的にはGitHub公式のActionを使うと思います。このcache、 Job毎 の定義になったりするみたいでしたので、複数のJobでキャッシュを使いたい場合はこの辺を注意する必要がありそうです。 使える場面は使っていきたい 企業で使う場合は色々な事情があったり、一極集中を避けようとCircleCIとかを使ったり、というのはあると思います。が、OSSとか個人開発とかで、そういったこだわりがない場合は、GitHub Releaseとかの連携がスムーズ(当たり前)だったり、並列で動かしても特にペナルティが無かったりと、結構優遇されています。 使ったことがない場合は一度試してみると、色々発見があると思います。ぜひ。

November 8, 2020 · derui

ctypesをduneで使っていく方法

気づけば10月、今年ももう3ヶ月を切っていることにびっくりです。 今回は、OMakeをビルドシステムとして使っていたツールをdune対応した時に困ったことがあったので、それについて書こうと思います。 <!–more–> 発端 https://github.com/derui/okeyfum このリポジトリですが、6年くらい前にノリだけで作ったツールです。もともとは OMake というビルドシステムを使っていました。しかし、OMakeが事実上の開発休止になり、このリポジトリ以外ではocamlbuildを使っていたりしました。そして現代は、事実上dune一択状態になりました。 そこで、暇を見つけてdune対応しようとしたとき、ctypesを使っていたために、色々とビルドが通らないようになってしまいました。 ctypesとは ちょっと脱線して、OCamlにおけるctypesというライブラリについて紹介しておきます。 https://github.com/ocamllabs/ocaml-ctypes どういうライブラリかは、最初の一文を見れば大体わかります。 ctypes is a library for binding to C libraries using pure OCaml. The primary aim is to make writing C extensions as straightforward as possible. The core of ctypes is a set of combinators for describing the structure of C types – numeric types, arrays, pointers, structs, unions and functions. You can use these combinators to describe the types of the functions that you want to call, then bind directly to those functions – all without writing or generating any C! ...

October 7, 2020 · derui

OCaml製プログラムでperformance profileをする

OCamlで作ったソフトウェアをチューニングしようとprofilingしようとしたら、4.09.0で gprof 対応が削除されていました。 https://github.com/ocaml/ocaml/pull/2314 これはこれで困ったので、Linuxでのprofiling方法を調べたのでメモります。 ...

September 22, 2020 · derui

Migemoを使って絞り込みできるfzfっぽいものを作っています

残暑というかもう真夏じゃねーか、という気温でいやんな感じです。でも夕方の風邪は大分過ごしやすくなってきました。 そんな秋の声が聞こえはじめている季節とは関係なく、今作っているtoolについて書いてみます。 https://github.com/derui/oif ...

September 9, 2020 · derui

Windows10 + WSL2で環境を整えた

帰省のイベントである、自分のノートPC(Windows10)に開発環境を整備する時期になったので、今回はVagrantからWSL2を使ったものにしてみました。 見切り発車ですので出来るかどうかは不定です。ではいってみましょう。 <!–more–> 不安な点 いつもはVagrant上に構築したX11環境で開発していたわけですが、今回はWSL2になるということで、いろいろ考える必要がありそうでした。 WSL2ではUbuntu20.04/Debian/SUSEくらいしか使えない いつもはArchLinuxを使っているので、色々と不安な点が・・・ Xserverが必要 Windows上のX serverを入れる必要があります 自分のdotfileが使えるのか・・・? Gentoo/Archlinux用になっているようなものなので、色々厳しそう? 今回の要件 以下を目標にします。努力目標は OPT がついてます。 EmacsをGUIで使える 自分のdotfile/.emacs.dを使えている OCaml/opam/Node.jsが入っている (OPT) Emacsからmozc_emacs_helperを通してWindows上のGoogle日本語入力を使えている (OPT) EmacsからWindowsの方のブラウザとかを使える Emacsとterminalだけで大体生きてるOld typeなので、これくらい出来ればだいたい何とかなります。 WSL2のインストール いつものごとく画像はありませんがご容赦を。以下の手順でWSLを有効にします。なお、前提としてWindowsのOS versionがMay Update以降である必要があります。お気をつけて。 アップデートが必要なことを忘れていてだいぶ時間を食ったのは内緒です インストールと更新方法は、Microsoftの公式ドキュメントが詳しいのでそっちを見ましょう。 https://docs.microsoft.com/ja-jp/windows/wsl/install-win10 一応手順を書いておきます。 PowerShellを管理者権限で開く dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart 再起動する またPowerShellを管理者権限で開く wsl --set-default-version 2 なんかURLが表示されるので、アクセスしてWSLのkernel updateを入手してインストールする Windows StoreからWSLのディストリビューションをダウンロードする(今回はUbuntu 20.04を選択) Windows Storeからダウンロードしたディストリビューションを起動する しばらく待つ(数分程度) UNIX username/passwordを入れる。Windows usernameと同じにしとくのが無難な模様 これでいけるはずです。WSLにアクセスする時は、Windows TerminalとかcmdとかPowerShellとかお好きなもので wsl と打てば、デフォルトで設定されているディストリビューションに対してアクセスできます。 WSLにいろいろインストール WSL2は普通のLinuxなので、色々設定をしていきます。ただ、WSL2は若干特殊な環境なので、systemctlは使えないものと考えるのが良さそうです。 timezoneはだいたい初期状態で問題なさそうでした。 ...

August 8, 2020 · derui

lambda-termでmulti byteを一文字ずつ表示する

気づいたら8月になっていました。今年の梅雨はかなり長かったですね・・・。過ごしやすいのは結構なんですが、野菜が高くなるのでこれも困ります。 今回は、OCamlでTUI(Terminal-based User Interface)を作る際の鉄板ライブラリである lambda-term を使ったときに、multi byteを表示出来なかったのを解消したので、備忘録として書いておきます。 <!–more–> やりたかったことと起こっていたこと やりたかったこととしては、 一文字ずつ表示したい 各文字にstyleを当てたい lambda-termでは、 LTerm_draw.draw_string と LTerm_draw.draw_char という2つの関数があります。こいつらは字面の通り、stringやcharをレンダリングします。 使い方はこんな感じです。実際にはcontextが必要なので、widgetの中とかで行う感じです。 let str = Zed_string.of_utf8 "foo" in let style = LTerm_style.none in LTerm_draw.draw_string ~style ctx 0 0 str; LTerm_draw.draw_char ~style ctx 0 1 @@ Zed_string.get 0 str これで表示自体は出来るんですが、 LTerm_draw.draw_char を使っていった時に、色々と気になる問題がありました。それは、multi byte(ここでは日本語)を表示しようとした時に、なぜか表示されない、ということでした。 解決 備忘録なのでさっさと行きますが、原因は LTerm_draw.draw_char のcolumn指定の誤りでした。 LTerm_draw.draw_char のシグネチャは、以下のようになっています。 val draw_char: ?style:LTerm_style.style -> LTerm_draw.context -> int -> int -> Zed_char.t -> unit さて、Zed_charですが、こいつは zed というライブラリが提供しているmoduleです。こいつはunicodeを保持していて、保持している文字の幅も持っています。 Zed_char.width で取得できます。 LTerm_draw.draw_char の挙動ですが、基本的にはterminalのascii 1文字を1columnとして描画します。ただ、 Zed_char.width が1より大きい場合は、1より大きい分だけSizeHolderというダミー文字で埋めるようになっています。 この挙動がわかっていなかったので、multi byteを1columnずつずらして表示しようとすると、一つ前に表示したmulti byteを消したのと同じ状態になってしまっていました。 実際、multi byteを考慮した上で LTerm_draw.draw_char を使う場合、以下のようにする必要があります。 let str = Zed_string.of_utf8 "テストfoo" in let style = LTerm_style.none in Zed_string.fold (fun ch index -> LTerm_draw.draw_char ~style ctx 0 index ch; index + Zed_char.width ch ) 0 |> ignore わかってしまえば納得ですが、中々ドキュメントだけでは分かりづらいことなので、誰か(主に自分)の役に立てばと思います。 ...

August 1, 2020 · derui