トップ «前の日記(2021 年 9 月 12 日 (日)) 最新
編集 RSS

ワタタツの日記


2021 年 12 月 25 日 (土)

はてなブックマーク用のconsultコマンドを作っている

これはemacs Advent Calendar 2021の25日目の記事です。

minad氏による、Emacsの最近のパッケージの一つ、consultをすごく気に入ったので、自分のはてなブックマークを検索するパッケージを書いています。

https://github.com/Nyoho/consult-hatena-bookmark

です。

[description]

はてなブックマーク

はてなブックマークはソーシャルブックマーキングサービスです。

ソーシャルなので、ブックマークするときだけでも他の人のコメントを見て勉強になります。

そんな一期一会な使い方も面白いですが、ストックしていくものとしても便利です。そこで欲しくなるのが「自分のブックマークを全部検索する」機能です。実は、サイト上でもできます。これがEmacs上でもすばやくできたら楽だし楽しいなと思います。

counsel用のものは途中まで書いた

昨年 (consult ではなく) counsel 用のコマンド counsel-hatena-bookmark は書いていました。しかし、非同期的に読むところがまだうまく書けてなくてそのままになっていました。 そして放置しています。

それは置いといてconsult用で書いてみようと思って書き始めたところ、非同期的なところが割と簡単に書けました(気がします)。と言っても「結果が多いときに繰り返し読む」機能はまだ書けていません。

歴史と問題と全文検索API

実装に関係するので先行研究(事例)をご紹介します。

おそらく歴史的にはまず、anything用の anything-hatena-bookmark がありました。その後にhelm用の helm-hatena-bookmark がありました。わしもどちらも使っていました。

このどちらの実装も、はてなブックマークの自分のブックマークをダンプしたものを定期的に(または手動で) 全部 取得しておいて、それをローカルで串刺し検索するというものでした。

しばらくは楽しく、便利に使っていたのですが、

  • このダンプするURLがすごく重い
  • ブックマークが数万を超えてくると以前のものが取得されない

という問題がありました。

そんな中(わしが)見付けたのが、マイブックマーク全文検索APIです。

これはその都度クエリを投げて返答をもらうAPIで、定期的にローカルにダンプしておく必要がありません。そのため、今ブックマークしたばかりのブックマークもひっかかります。(anything/helm用の上の実装では、その前に重たい手動ダンプが必要です。)

また、このAPIは、そのページのタイトル、ブックマークコメントだけでなく、ページの本文にもヒットする仕様になっています。これが便利なときがあります。(便利ではないときもあります。)

そんなわけで、 dump v.s. API で、後者の全文検索APIを使う方法をとることにしました。(counsel用のものも同様の方針にしています。) これならブックマークが数万を超えていても安心ですし、いつでも最新のブックマークが検索できます。

実装

consultのいろいろなコマンドの実装のソースとにらめっこしながら少しずつ作っていきました。

基本的には consult--read 関数がメインです。これに絞り込みたい候補を突っ込みます。そうするとプロンプトの上で絞り込みが行えます。オプションが色々付いていて、ヒストリを作ったりできます。

ログインはw3mにまかせる

工夫したところの一つはw3mを使ったことです。

はてなブックマーク全文検索APIを使うのにログインが必要です。 ログインの認証コードやクッキー保持などを書くのは(わしには)大変そうなので、外部コマンドのCUIブラウザであるw3mにおまかせしました。

そうすると、consult--async-command で外部コマンドとして w3m でAPIにアクセスするものを呼び出して、結果をJSONテキストでゲットし、あとはEmacsで処理するだけにできます。

JSON解析は27.1の新機能を使ってみた

ゲットしたテキストのJSONデータを実際のJSONオブジェクトにするには、Emacs 27.1で導入された新関数 json-parse-string を使ってみました。ビルトインの関数なので高速に解析してくれると評判(?)です。

これでパースしてEmacsのリストにします。

リスト項目にpropertize

ブックマークは、タイトル、URL、ブックマークコメント、日付という様々な要素があります。これが結果のリストの項目です。

これをconsultでうまく受け取るために、文字列本体は format した文字列にしました。これで割と整頓して表示できました。(これでいいのかな)

これだと絞り込んだ後のURLが表示用のこの文字列になってしまうので、 propertize'consult--candidate というキーに URLを値として付与しました。

こうしておいて、 consult--read:lookup:lookup #'consult--lookup-candidate としておくと、 このキーの値を返してくれるようになりました。表示用と実際の値をこのように分けることができたのでした。(これでいいのかな)

未来。今後の課題

以上で一旦公開までこぎ着けましたが、まだまだ課題があります。

MELPAかどこかに登録したい

せっかくなのですぐに使ってもらえるように、MELPAかどこかに登録したいです。

「結果が多いときに繰り返し読む」機能

APIでは、ディフォルトでヒットした最初の20件が返ってきます。本当はもっと多いときは、オフセットを指定して何度も問い合わせることで全件を取得できます。まだその機能は付けていません。どう書けばいいかまだわかっていないからです。わかる方は、どうかお教え下さい。🙏

Embarkへの受け渡し

今は絞り込み中に Embark を起動して、URLなので例えば eww に渡すとかしても、表示用の文字列が渡ってしまいます。ちゃんとURLはURLとしてEmbarkに渡したいです。こうするにはどうすればいいかまだわからないので、後回しにしています。 これもわかる方、是非ともお教え下さい。🙏

marginalia対応した方がいいのか

というかそもそもformatで自分で整形するより、そういうのはmarginalia対応してうまいこと日付とか表にしてもらった方がいいのではないだろうか、などと思うけど、maginaliaのことがよくわかっていないのでまだわからない。理解したい。

結論: 楽しい

ともかくこれで楽しく自分のブックマークを全文検索できるようになりました。Happy social bookmarking!

追記

はてなへのログインがJavaScript必須になってしまって w3m でアクセスする方法ではできなくなりました。

他の方法を模索中です。→WSSE認証にしました (後で書く)

Tags: emacs

トップ «前の日記(2021 年 9 月 12 日 (日)) 最新
Copyright © 2022 KITADAI, Yukinori. All rights reserved.