Windows上でOCamlアプリケーションを動かす デバッグ編

ようやく涼しくなってきたと思った瞬間に晩秋になってしまい、秋がなかったなぁ、としみじみと感じてしまいました。 第三回は、Cross Compileできたものの、上手く動かない、というときに役立つデバッグについて書きます。 <!–more–> Cross Compileしたバイナリの難しさ Linux上でクロスコンパイルしたバイナリですが、実際にこのバイナリを動かしてみると、問題が発生(Segfaultとか)することがあります。 特に最初はWineで動かすと思いますが、エラーの内容がメモリアドレスくらいしか無く、結構色々と辛いです。Windows上で実行してみるのも中々にしんどいです。普通にそのまま実行時エラーで落ちるので。 Visual Studioとかで動かしてみる、というのも手段だと思いますが、ここではあくまでLinux上で解決してみます。 gdbserverとgdb gdbには、remoteのgdbと繋げてローカルで実行できる gdbserver というツールが存在しています。 Debianであれば、まず以下でmingw向けのgdbserverと、mingwでコンパイルされたtargetをデバッグできるgdbをインストールします。 apt install mingw32-w64-gdbserver mingw32-w64-gdb-target これを使うと、以下のようにしてdebugを行えます。 wine /usr/share/win64/gdbserver :3000 sample.exe x86_64-w64-mingw32-gdb sample.exe # ここからGDB内 > remote target localhost:3000 # つながると普通の(若干コマンドが成約されていますが)gdbとして使えます。 > continue Program received signal SIGSEGV, Segmentation fault. 0x0000000000a19d1c in lwt_unix_not_available (feature=<optimized out>) at lwt_unix_stubs.c:107 107 lwt_unix_stubs.c: No such file or directory. (gdb) bt #0 0x0000000000a19d1c in lwt_unix_not_available (feature=<optimized out>) at lwt_unix_stubs.c:107 #1 0x0000000000a1b400 in lwt_unix_iov_max (a1=<optimized out>) at windows_not_available.c:16 #2 0x00000000008611ed in camlLwt_unix__entry () #3 0x0000000000000001 in ?? () 上記のように、Windows向けにビルドしたバイナリを、Linux上でデバッグできます。OCamlでビルドしたものであれば、上記のようにcaml系統のデバッグシンボルも見えるので、デバッグがはかどります。 ...

November 11, 2019 · derui

Windows上でOCamlアプリケーションを動かす ビルド環境編

歓迎会と送別会が連チャンになったらだいぶグロッキーになってしまい、睡眠を削って生活するのはもう無理だなぁと思いました。十分な睡眠によるパフォーマンス向上をなめてはいけない・・・。 さて、第二回は実際にCross Compileを行うための環境について書きたいと思います。 <!–more–> ビルド環境の選定 まずOCamlプログラムのクロスコンパイル・・・というかWindows向けのビルド環境をどうするか?です。Windows向けにビルドする場合、次のいずれかが主要な選択肢になります。 Linux上でMinGWをインストールし、Windows向けのバイナリをクロスコンパイルする Windows上でOCaml/OPAMをインストールし、Windows向けのバイナリをネイティブコンパイルする Windows上でコンパイルする場合、OCaml/OPAMそれぞれをビルドするか、もしくは配布されているバイナリを展開する方法があります。この内、自前でビルドする方法は後述するとおり結構厳しいです。一応チャレンジしてみましたが、敢え無く爆砕しました・・・。 と、いうことで、Linuxでのクロスコンパイルに一縷の望みを託してみます。 Windows上のOCamlについて OCaml本体は、実はWindows環境上でもちゃんとコンパイル・実行できるようになっています。(MSVC/Cygwinのいずれかが必要です)また、OPAMもWindows上でビルドできるようになっています・・・が。 OPAMをMinGWでビルドしてしまうと、 opam init が上手く動作しない、という問題が発生します・・・。これはOPAMでも認識されている問題です。このため、OPAMをWindows上で動かす場合、OCaml本体もCygwin向けにコンパイルする必要があります。 しかし、Cygwinでコンパイルしてしまうと、Cygwin1.dllというdllを同梱しないと動作しなくなります。Cygwin1.dllはライセンス的にも結構厳しいため、できれば付けたくありません・・・。 Linux上でのクロスコンパイル環境 OCamlプログラムを、Linux上でWindows向けにコンパイルする方法は、 MinGWでコンパイルされたOCamlコンパイラでコンパイル・リンクする という形になります。本来、Linux上でMinGWを利用してコンパイルされたバイナリは、Windows環境またはWineでしか動きません。 ここで前に紹介したocaml-cross-windowsが効いてきます。このリポジトリでは、Windowsバイナリを生成でき、Linux上で実行可能なOCamlコンパイラを提供してくれています。ただ、ocaml-cross-windowsでは、Debianとかを推奨?している雰囲気があります。しかし私の利用しているDistributionはGentoo・・・。 と、いうことで、こういうときはDockerに頼ります。Debianのベースイメージから、クロスコンパイル環境を整えます。 クロスコンパイル用のイメージを作成する FROM debian:bullseye RUN apt update \ && apt install -y --no-install-recommends opam gcc-mingw-w64-x86-64 gawk m4 git ca-certificates \ && rm -rf /var/cache/apt/archives \ && opam init -n --disable-sandboxing \ && opam switch install 4.08.0 \ && opam repository --all add windows git://github.com/derui/sxfiler-repo-windows \ && eval $(opam env) \ && opam install -y conf-flambda-windows \ && opam install -y ocaml-windows64 \ && opam install -y ocaml-windows COPY scripts/entrypoint.sh /entrypoint.sh RUN chmod a+x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] entrypoint.sh の内容は、opamを利用できるようにしているだけです。ここでのポイントは、aptでopamを入れることで色々楽していることと、64bit向けのMinGW環境を導入していることです。gawkを入れているのは、地味にこれがないとOCaml自体のコンパイルに失敗するためです。 ...

November 2, 2019 · derui

Windows上でOCamlアプリケーションを動かす パッケージ編

今回から何回かに分けて、今取り組んでいるOCamlのcross compileについて書いていきたいと思います。おおよそ三回位を予定しています。 第一回は、OCamlのcross compile事情について書きたいと思います。 <!–more–> Cross compileとは Cross Compileの正式な定義はいまいち判然としませんが、ここでは あるプラットフォーム上で、別のプラットフォームの実行ファイルなどをコンパイルする という定義にします。つまり、Linux上でWindowsのバイナリをコンパイルする、という感じです。 OCamlのcross compile事情 2019/10の時点で、一定以上の普及率かつ、上記の定義におけるCross complieを最も簡単に行える言語は、間違いなく Golang であることは論を待たないと思います。これは、Golang自体がlibc aware(というか再実装していた気がする)、かつ、デフォルトで各architectureへのコンパイルが可能な環境が整っているためです。この点から、マルチプラットフォームなCLIとかを作る時にGolangがファーストチョイスになっているのでしょう。 同じような感じで、 Rust もCross compileは簡単な部類だと思われます。(ここでは、シングルバイナリかどうか?というのは主題ではないので無視しています) これらの言語の共通点は、どちらもシステムプログラミングを主眼に置いた言語、ということも設定に影響していると思います。 翻ってOCamlですが、これらと比較すると中々厳しいです。何故厳しいのか?を考えてみると、以下のような点が挙げられそうです。 OCaml自体、複数のプラットフォーム向けのバイナリを出力するようにできていない OCamlはすでにだいぶ歴史のある処理系であり、2010年代に生まれた言語と背景が異なるので如何ともしがたい点もあります OCamlのユーザー内でニーズがない 最近になってニーズが出てきた・・・というよりも、Golangのこのfeatureないの?みたいな声が上がって来た感じです ライブラリがWindows/Linux両対応していないケースが多い OCamlのユーザーベースはLinuxが多い(偏見)なので、Linuxのみ対応しているライブラリが多いです ただ、ネットワーク周りは、Mirageの成果もあって、Pure OCamlで大体なんとかなります OPAMをwindowsで動かすのが超難易度 ・・・というよりも、2.0.5現在対応していません このため、Windows上でネイティブコンパイルすること自体も難しいです(近い将来出来るようになりそうですが こういう実態から、 OCamlのみでCross compileは出来ない というのが結論です。では諦めるしか無いのか?OCamlでマルチプラットフォームなアプリケーションを作るというのは夢物語なのか? ocaml-cross-windows しかしここで救いの手が。OCamlが好きな人々や、OCamlをマルチプラットフォーム(ここではWindows)で使いたい人々によって、ocaml-cross-windows というリポジトリが運用されています。主にLinux上でMingwを利用して、Windows向けのバイナリをコンパイル出来るように工夫されています。 これが自動的にopam-repositoryからmirrorされて自動的にアップデートされていく・・・のであればいいんですが、そうは問屋がおろしません。 公式のopamから、ocaml-cross-windows向けにportingするのは、ドキュメントに従っていけば意外と簡単なんです。ただ、例えばppxを利用していたりすると、ocaml-cross-windows上のpackageとopam公式の両方を入れないと動かなかったり、その逆もあります。また、最近のstandardであるduneを利用していないpackageの場合、色々と対応しないといけなかったりと、中々自動では難しいです。 しかし、現時点では非常に有力な選択肢です。このシリーズでは、これを使っていくことにします。 アプリケーション用のrepositoryという選択肢 ocaml-cross-windowsは、コミュニティによって運営されているため、足りないpackageがあれば、Pull Requestを出すのが正道です。・・・ただ、今やりたいのは、自分のアプリケーションをコンパイルしたいのです。そのためには、dirty hackも辞さない感じです。 となると、アプリケーション用のopam repository、という選択肢も上がります。単純にocaml-cross-windowsをcloneしてremoteと名前を変えれば、一応形になります。 当然、本来であればコミュニティに還元するのが自分のためにもなります。私も後で行うつもりですが・・・。 実際にocaml-cross-windowsから作って、自分が必要なpackageを追加しているのが、下のリポジトリです。 https://github.com/derui/sxfiler-repo-windows packageは用意できた ので、次はOCamlとOPAMを使ってCross compileする環境について書きたいと思います。

October 21, 2019 · derui

OCamlでFFTを実装してみる

WAVから十二音技法に基づく音程を、gnuplot形式で抽出するCLIをほそぼそと作っています。 wav-pitch-extractor まだreadmeもない+完全に自分用の実装なので、仕事であればやらないような、車輪の再実装もやっています。その中で、 Fast Fourier Transform 、通称FFTも実装してみたので、その感想を書こうかと思います。 <!–more–> FFTとは? まずFFTが何か、簡単に説明します。もっと正確でもっと詳しい説明は色んなサイトに載っているので、そちらを見ていただくとして。 なお、単純にFFTだけで検索すると、 Final Fantasy Tactics の方も引っかかってきて、一定以上の年齢層にとって懐かしい気持ちになること請け合いです。 閑話休題。 FFTは上でも書いた通り、 Fast Fourier Transform のアナグラムです。日本語だと 高速フーリエ変換 という名前です。 高速 という修飾があるので、 フーリエ変換 を高速にやるアルゴリズム、ということです。 フーリエ変換とは 実際にはフーリエ変換と離散フーリエ変換で別々のものとして扱われているんですが、プログラムでは基本離散フーリエ変換しか扱えないので、以下でも離散フーリエ変換をフーリエ変換として扱います。 フーリエ変換は、端的に言うと ある複素関数からある複素関数への変換 というものを指します。現実的には、デジタル信号の周波数解析などで使われるのが一般的、とのことです。以下の式で表されます。 \begin{equation} F(t)=\sum_{x=0}^N f(x) \mathrm{e}^{-i \frac{2 \pi t x}{N}} \end{equation} ・・・とだけ書かれても、高卒程度の知識しか無いと、ファッ?ってなってしまいます(なりました)。特に右辺のネイピア数の辺りが鬼門です・・・が、実はここはオイラーの公式というものを使うと、三角関数だけで書けます。オイラーの公式は次のように定義されています。 \begin{equation} \mathrm{e}^{i\theta} = \cos{\theta} + i \sin{\theta} \end{equation} これに関連する特に有名なものとして、オイラーの等式があります。と オイラーの公式を最初の式に適用すると、ある時間の振幅に、オイラー公式で表される周期関数がかけられたものを、全時間分足したものが、ある周波数のスペクトルになる、ということになります。 私の説明は単に現時点での私の理解ですので、より正確な定義などを知りたい場合はより信頼できるサイト・文献をあたったほうがよろしいかと・・・。 素朴なフーリエ変換と問題点 上記の定義に従うと、次のように書けます。 let dft (data : float array) = let size = Array.length data in let radian = 2. *. Float.pi /. float_of_int size in Array.mapi (fun index _ -> let start = ref Complex.zero in Array.iteri (fun index' v -> let v = {Complex.re = v; im = 0.} in let times = float_of_int index *. float_of_int index' in let next = {Complex.re = cos (radian *. times); im = sin (radian *. times)} in let next = Complex.mul v next in start := Complex.add next !start) data ; !start) data (* dft [|1.0;2.0;3.0|] *) 素朴なので、メモリ使用量がー、とかは気にしていません。なお、数式をプログラムに起こすとき、 \( \sum \) はfor loopでの足し算に相当します。 ...

October 12, 2019 · derui

OCamlでMonadを使う時はppx_letを使おう

ちょっとしたCLI(ある程度出来たら記事にします)をOCamlで作っています。その際、初めてppx_letを使ってみたんですが、なかなか良かったので紹介します。 <!–more–> ppx_letは、OCaml界隈では知らない人のいないJane Street社が公開しているPPX拡張です。 OCamlでmonadを扱う時の課題 大抵、resultとかoption(特にresult)をmonadicにつなげていく時、大抵は下のような書き方になります。 let bind v ~f = match v with | Ok v -> f v | Error _ as v -> v let (>>=) v f = bind v ~f let foo = function | v when v > 10 -> Ok v | _ -> Error "error" let bar v = Ok (v * 10) let () = let v = foo 12 >>= bar in match v with | Ok v -> Printf.printf "result %d\n" v | Error e -> Printf.printf "error %s\n" e >>= とかのoperatorを使うのが一般的かと思います。これは非常にシンプルな例なので、operatorでも特に困りません。 しかし、ある程度の規模になってくると、ある時点で取得したデータを、後に使いたい、ということが非常によくあります。 foo v >>= fun v1 -> bar v1 >>= fun v2 -> foobar v1 v2 これが続くと、特にreadabilityの点で問題になってきます。 ...

September 14, 2019 · derui

手動で作るReact + TypeScript環境(2019/8版)

最近、React+TypeScriptの開発環境を作る場合、大抵はcreate-react-appを利用するケースが多いと思います。 実際、種々のベストプラクティスであったり、単純にアプリケーションを作る方にフォーカスする場合、create-react-appを利用するのがbetterです。ただ、色々な要因でejectせざるを得ない状況に追い込まれると、結構厳しいケースが多いです。実際公式でもejectは非推奨です。 そういうときに備えて(?)、0から環境を作ってみましょう。こういう経験をしておくと、ejectすること無くいろいろすることが出来ます。 <!–more–> 今回作っていって見る環境は、次のような環境です。 React + TypeScriptで書ける TypeScript内では、moduleは相対パスではなく、 @/hoge のようにしてアクセスできる TSXで書ける ESLintでlintできる prettierでformatting Jest+enzymeでユニットテスト webpack-dev-serverでhot reloading Componentのreloadは色々問題もあるのでやりません Reactの導入 まず新しいpackageを作りましょう。ここでは react-handmade-sample という名前で作ります。 $ mkdir react-handmade-sample $ cd react-handmade-sample $ npm init 次に、React関連のパッケージをインストールします。styled-componentsは趣味なので、無くてもいいです。 $ npm install react react-dom styled-components Webpackの導入 Webpackは、現時点でデファクトbundlerです。非常に設定量が多いと思われがちですが、必要最小限であれば、意外と量は少ないです。とりあえず必要なので入れます。webpack-dev-serverもついでにいれます。 $ npm install webpack webpack-dev-server $ npm install html-webpack-plugin tsconfig-paths-webpack-plugin Webpackは、developmentの場合に使う基本設定と、production時に利用する設定の二通りを用意しますが、とりあえずはdevelopmentの設定だけ記述します。 // webpack.config.js const path = require('path'); module.exports = function(isProduction) { return { mode: "development", entry: path.resolve(__dirname, "./src/index.tsx"), // ファイルの出力設定 output: { // 出力ファイルのディレクトリ名 path: path.resolve(__dirname, 'dist'), // 出力ファイル名 filename: "index.js" }, module: { rules: [ ] }, resolve: { extensions: [".ts", ".tsx", ".js", ".json"], plugins: [ ] }, plugins: [ ] }; }; 空っぽに近いですが、とりあえず最小限です。 ...

August 21, 2019 · derui

OpenAPI3 Generatorで使える値の調べ方

人事/総務の業務上の問題を解決するために、APIを作ろうということになりました。せっかくなのでOpenAPI3を使おうぜ、となったんですが、Swagger2と構成が違っていて、テンプレートをいじるときにどういう値を視ればいいのか・・・がわからんかったです。 <!–more–> それをどう見ればいいか、のメモ書きです。 まず見るリポジトリ https://github.com/OpenAPITools/openapi-generator.git OpenAPI3のSpecifiationから、Server/Clientの生成をするための公式ツールです。jarが提供されているので、Javaが動けばだいたい動きます。 Swaggerのときも同じものがありましたが、OpenAPIに分化してからorganizationも分離しています。このGeneratorは各種言語のClient/Serverを生成するため、各言語用のテンプレートが置かれています。 各言語のテンプレート https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources リポジトリ上のリソース内に、各言語/フレームワークごとに分かれています。ここにテンプレートがありますが、このテンプレートの中を見ても、使われてる変数はわかりますが、 どういう値を使えるか はわかんないです。 実際、ここはテンプレートだけなので、これを利用して生成している場所は別にあります。 各言語の生成箇所 各言語ごとのCLIはここで定義されています。ただ、これを見ても、どのテンプレートを使うんだ?ということしかわかりません。 https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages 実際にテンプレートに値を注入している場所はここです。 https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultGenerator.java この中の、 generateApis というメソッドの中で定義されています。基本的にOpenAPI3のYAMLから取得できる情報はここから取得できます。なので、ここを見ると、自分のテンプレートで使いたい値が見つかる・・・かもしれません。 メモ書きもしていく宣言 簡単に見つかるだろー、ってなったら見つからなかったのと、デフォルトの提供されているテンプレートだと思ったものと違う可能性もあるので、テンプレートを編集するための第一手として。私を含め誰かの参考になれば・・・。 OpenAPI3だとSpringFoxでSwagger2の形式で吐き出せない、みたいなのもありますので、Swagger2を使い続けるか、OpenAPI3を使うかは計画的に。 気づいたら7月が終わりそうです。ブログをもうちょっと書いていきたいので、お手軽にかけそうなものがあれば書いていきたい所存。

July 24, 2019 · derui

Excelのページ指定印刷をPowerShellでやる方法

最近人事/総務からのヒアリングした業務上の問題を解決していく、という社内プロジェクトに参加しています。 その中で、割と調べても出てこなかった事柄をメモしておきます。 <!–more–> 要望 今回解決したいのは、次のような問題でした。 色々な事情で、Excelから紙で印刷いないといけない 親会社の意向とかいろいろあるようで Excelの数が多い だいたい社員数くらいある(現状だと300↑) 印刷するのが手作業で辛い しかもそういう業務がけっこうある とにかく問題としては、 Excelを開く→最初のページだけ印刷する という業務が多く、かつ時間がかかる、と。電子承認とかそういう方向に行きたいらしいですが、まーいろいろ事情があるようで。 方針の検討 とりあえず抜本的ではないが、ある程度作る労力と、結果の省力化に貢献できるものとして、次のようなツールを作ることにしました。 Excelマクロの実行が必須 実行しないと正しい状態にならないので・・・ Excelの 1ページ目だけ 印刷できる フォルダ内のExcelを一気に印刷できる 任意のフォルダでやりたい 困ったこと 人事/総務の方々は、ITレベルが様々なので、Windows標準で入っているものを使う、ということで、 PowerShell を使うことにしました。 ところが、いろいろ調べて(ググって)みても、 ExcelからBookを印刷する というものはあっても、 指定したページだけ印刷する ということをやっている人がまずいないっぽいという・・・。 フォルダ内のExcelを印刷するという回答 色々試す 色々試した所、次のサイトが気づきになりました。 https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbook.printout このページ、Office VBAのヘルプですが、ここに引数が書いてあります。 名前 必須 / オプション データ型 説明 From 省略可能 Variant 印刷を開始するページの番号を指定します。 この引数を省略すると、最初のページから印刷します。 To 省略可能 Variant 印刷を終了するページの番号を指定します。 この引数を省略すると、最後のページまで印刷します。 Copies 省略可能 Variant 印刷部数を指定します。 この引数を省略すると、印刷部数は 1 部になります。 Preview 省略可能 Variant True の場合、印刷をする前に印刷プレビューを実行します。 False、または省略した場合、直ちに印刷を行います。 ActivePrinter 省略可能 Variant アクティブなプリンターの名前を指定します。 PrintToFile 省略可能 Variant True の場合、ファイルへ出力します。 引数 PrToFileName が省略された場合、出力先のファイル名を指定するためのダイアログ ボックスを表示します。 Collate 省略可能 Variant True の場合、部単位で印刷します。 PrToFileName 省略可能 Variant _PrintToFile_がTrueに設定されている場合、この引数は印刷先のファイル名を指定します。 IgnorePrintAreas 省略可能 Variant True の場合、印刷範囲を無視してオブジェクト全体を印刷します。 これをPrintOutに指定すればいいんじゃね!?ということで、こんな感じにしてみました。 ...

July 10, 2019 · derui

以前作ったtensorflowを使うprojectで2.0 betaを試してみた(動いてない)

だいぶ前ですが、Tensorflowのメジャーバージョンアップである2.0のbetaがリリースされました。丁度いいので、以前作ったまま放置していたツールを更新してみようと思います。 <!–more–> 以前作ったのはこれです。Qiitaで記事も書きました。 https://github.com/derui/painter-tensorflow https://qiita.com/derui/items/fe232c87d981d241ae07 https://qiita.com/derui/items/9719efa14f44a792362b 大雑把に言うと、着色済みの画像から線画を抽出するものと、その逆版です。現在ではこういう個人レベルのおもちゃではなく、実際にサービスとして運用されてるものもありますね。 1. まず公式サイトを確認する 2.0-betaをインストールする方法は、公式サイトに載っています。ちゃんと確認しておきます。 https://www.tensorflow.org/install また、今回対象にするものは、GPUが大前提なので、CUDAとかの条件も確認しておきます。このへんがしんどいので、普通はGoogle Colabとかを利用するのが良いかと。私は裏側の学習も兼ねてやっているので、頑張って整えていきます。 https://www.tensorflow.org/install/gpu 2. CUDAとかを色々用意する 他のツールは触ったことがないのでなんとも言えませんが、TensorflowはかなりアグレッシブにCUDAのバージョンアップを行っている印象です。実際、2.0-betaでは以下を要求してきました。 Hardware requirements The following GPU-enabled devices are supported: NVIDIA® GPU card with CUDA® Compute Capability 3.5 or higher. See the list of CUDA-enabled GPU cards. Software requirements The following NVIDIA® software must be installed on your system: NVIDIA® GPU drivers —CUDA 10.0 requires 410.x or higher. CUDA® Toolkit —TensorFlow supports CUDA 10.0 (TensorFlow >= 1.13.0) CUPTI ships with the CUDA Toolkit. cuDNN SDK (>= 7.4.1) (Optional) TensorRT 5.0 to improve latency and throughput for inference on some models. ...

June 30, 2019 · derui

mozcの候補をposframeで表示するEmacs拡張を作った

最近家に帰ってからめっきりプログラミングをしなくなってしまいました。いろいろやることがあると同時並行では難しいですね。 さて、今回はmozcの候補表示pluginを作ってみたというお話です。 <!–more–> https://github.com/derui/mozc-posframe mozcの候補表示は、標準で存在する Echo Areaへの表示、overlayでの表示のほか、 mozc-popup という拡張があり、大抵はこれを利用している方が多そうです。私もこれを利用していました。 (Emacs上での日本語入力にfcitxとかを利用している人は対象外です。そういう人のほうが多いんだろうか・・・) mozc-popupの利点 mozc-popupを利用していたのは、やはり利便性を重視してのことでしたが、特に以下の点がキーだったと思います。 変換位置と候補が近い overlayでもだいたい一緒ですが 実績あるpopup.elの利用 Spacemacsから入った人は知らないかもしれない、auto-completeで熟成したpopup表示に特化したlibraryです この結果、標準のoverlayよりも高速でした だんだんででくる問題点 mozc-popupを利用する前は、mozc + popupという組み合わせで長年使っていましたが、最近色々と問題が見えるようになってきました。 org-modeとpopup.elの相性が悪い 新しい拡張を作ることにした最大の契機 特に多数の折りたたみがあるときに顕著で、表示までの時間や、表示の崩れが非常に激しかった popup.elの更新頻度 一時代を築いたpopup.elですが、companyが台頭してからはだいぶ表舞台から消えてしまった感があります その仕組み上も複雑で、メンテナンスが困難だという話も child frameという潮流 Emacs 26から、frameに大きな拡張が入り、child frameと呼ばれる形態が可能になりました。端的に言うと、frameをfloating windowとして扱うことができる、というものです。 すでに様々なライブラリで利用されており、名実ともにEmacs26の目玉機能となっています。(個人の観測範囲では) https://github.com/sebastiencs/company-box https://github.com/emacs-lsp/lsp-ui しかし、あくまでframeを扱うものであるため、そのままだとpixel単位での操作が必要となり、非常に煩雑です。WIN32 APIでwindow作っていた時代になった気分です。それをラッピングしたlibraryが、 posframe です。 mozc + posframe 前述したmozc-popupの問題は、つまるところoverlayでの表現に限界があった、ということに尽きると思います。overlayはあくまでtextのpropertyでしかないので、複数のoverlayが設定された場合、その時時で異なる問題が出るであろうことは想像に難くありません PCで日本語を入力する場合、大抵はIMEを使うかと思います。Windows/macOS/Linux いずれも、候補表示そのものは 独立したWindow です。つまり、Child frameをこの用途に使うと丁度いいんじゃないか?というのは前々から考えていました。 すでにあるだろうと探してもなかったので自作することにしたわけですが。 mozc-popupとの比較 Pros org-modeやそれ以外でも、候補表示の時間がほぼ一定 調整の余地はありますが 表示崩れがない これがposframeを利用する最大の利点です 独立したframeを表示しているだけなので、複数のoverlayが設定されることに起因する問題から開放されています Cons install方法が煩雑 melpaとかに入っていないので、どうしてもstraight.elとかが必要です Emacs26以上 + GUIでないと動かない 個人的に、端末上で利用するのはもはや趣味の領域でしかないと思ってます 描画性能もほとんどの場合GUIツールキットの方が早いし、ChildFrameは性質上GUIでしか動きません 端末しかない?諦めてVimった方が幸せになれるかと・・・ ありがとう、mozc-popup mozc-posframeは、mozc-popupのソースを7割くらい流用しています。mozc-popupがなければ、そもそもmozc-posframeを作ろうと思ってなかったと思います。 まだmozc-posframeは若干のバグや性能向上の余地がありますが、すでに常用できるものになっている(というか常用してる)と思うので、よければ利用してみてください。

June 7, 2019 · derui