create-link

概要

create-linkは簡単にリンクを各形式に変換する、自作Emacs package。Emacs Lispで書かれている。元ネタはChromeアドオンのCreate Link

Memo

アクセスを待つ必要がある

ブラウザでのテストは、(sit-for) で待つ必要がある。 ewwでは待たなくてもOK、w3mでは待つ必要がある、というのは同期、非同期が違うからか。

letで抜けられない

(let (result)
  (request
    :success (function*
      (progn
        (setq result "aaaa"))))
result) ; nil

みたいなとき、返り値resultがnilになる。 ほかの普通の関数だとOKだが、requestの特殊な形で、ちょっと違う。

CI

依存パッケージを読みこむ必要がある。 Emacs package以外にも、たとえばw3mは外部プログラムが必要なのでapt-getするなど。

CIやバッチテストでcl-libが読み込まれない

caskに書いてもインストールされない。 最初から入っているようだ。ただし、(require ’cl-lib)しないといけない。 また、function* はcl-functionのaliasだと書かれているが、CIやEmacsバッチモードだと認識しなかった。何か別のパッケージな可能性。

依存パッケージ

elisp-checkでの依存パッケージの読み込み方がわからない。 テストだけはcaskで別にやっている。

冗長なcustom

冗長なcustomをうまく指定するように。 customを設定するときにbm.elが参考になった。

helmソースの定義

最小構成ぽいhelm-miscが参考になった。

completion

デフォルトのcompletionもすぐできた。 要するにリストを渡せば選択肢になる。で、出てきた値は文字列なのでinternすれば良い。

mapcarを使って書き直せないか

あとクロージャとかも。

(defun test1 (default)
  `(lambda (optional) (if optional optional ,default)))

(funcall (test1 create-link-default-format) "aaa")
(setq test2 (test1 "aaa"))
test2
(funcall test2 create-link-default-format)

(defun make-adder (n)
  `(lambda (x) (+ x ,n)))
(setq add2 (make-adder 2))
(funcall add2 5)

(funcall (lambda (a b c) (+ a b c))
         1 2 3)

(funcall (lambda (n) (1+ n))        ; One required:
         1)

モード別に分岐する関数の参考になる

ace-link.el は参考になるな。 buffer-nameで判別してたが、modeのほうがよさそう。

(cond ((eq major-mode 'Info-mode)
       (ace-link-info))
      ((member major-mode '(help-mode
                            package-menu-mode geiser-doc-mode elbank-report-mode
                            elbank-overview-mode slime-trace-dialog-mode helpful-mode))
       (ace-link-help))
      ((eq major-mode 'Man-mode)
       (ace-link-man))
      ((eq major-mode 'woman-mode)
       (ace-link-woman))

ace-linkを参考に

info用とか、custom用のリンク抽出も考えられる。 ファイルでなくて、関数の集合体を生成できないか。

たとえばinfoの特定のページを開くのを実行するリストを生成する。 (info “ivy”)する。みたいな。 ファイルだと依存するからな。Emacsで実行するのが前提のを生成するというわけだ。

npm install date-fns @types/date-fns

Tasks

TODO シェルだったらカレントディレクトリを取る

ブラウザみたく、変数が用意されてはない模様。まあこれについてはあまりいらないか。 パスを取得したいときはあるけど、それをhtmlリンクにしたいってあまりないしな。

パスはdefault-directoryで取れる。

TODO タイトルはないときバージョンを作るか

つまりパスだけ。 主題とはずれる気がする。シェルとかだとタイトルの取りようがないのでこれを追加するのが必要。

TODO Gitリポジトリのときは、相対ディレクトリを取得するオプション

リポジトリからリンクを辿れるようになる。でもEmacs上でどうなんだろう。 辿れないけど、人にディレクトリを示すときには使える。今は絶対パスで取って前のを削除している。めんど い。 うむむ。リモートリポジトリのURLがわかるなら意味はありそう。git-linkとあまり変わらないけどな。 git-linkのコードを見てるけど、まだあまりよくわからない。

TODO ホームディレクトリを~で出すようにする

今は /home/kijima... で出てるからな。汎用性があまりよくない。あとで絶対変わるし、ほかで使えない。

TODO 実行関数を出力

たとえばivyのinfoページにいたとする。(info “ivy”) を出力する。 これを実行するとivyに飛べるので、リンクといえそう。環境も関係ない。

infoバッファからの検索キーワードの割り出し方… 実行ディレクトリをdefault-directoryか何かで取る。(.*).infoというファイルがあるはずなのでそのファイル名をinfoの引数に渡す。

Archives

DONE フックを追加…たとえばリンク生成 → {フック} → コピー前としておく。

フックでは式が使えるのでなんでもできる。動的にタイムスタンプを加えたり、連番を振ったりとか。単なる文字列フィルターよりはるかに強力。誰かがもっと便利な使い方を編み出してくれる。

make-formatと、message+killの前にフックを差し込むか。 でも、文字列を受け取れないからあまり意味ない気がしてきた。 フックはその処理に追加するというより、別の処理を差し込むためのものだ(ある関数を実行すると、別の全く関係ない)モードをオンにするとか。その意味でいうと、フックする処理はまったく思いつかない。

DONE リンク変換

別のフォーマットに変換するのもあっていいな。 すでに書式があるから、そこからURL, Titleを取り出せればいい。

  • 判定関数

thing-at-pointの拡張だな。フォーマットリンク上にカーソルがある場合、タイトルとURLを取得して変換…。 どのフォーマットか判定できれば、タイトルとURLを取れる。 markdown-mode.elの(markdown-kill-thing-at-point)が参考になりそう。

別に独自実装しなくても、各modeのregexpを使えばいいかな。いや、フル装備でめちゃくちゃ複雑だし、いろんな依存(5つも増えるのはさすがに…)があるので独自でやろう。 https://ayatakesi.github.io/emacs/25.1/Regexps.html

DONE フォーマットごとの特殊ルールを追加する

たとえばlatexの場合、ファイルリンクにはプレフィクスrun:がつくらしい。 今のコードだとファイルリンクだという検知はget-informationでしかできないのでそこに書くしかない。 一般的関数に特定のファイルフォーマットの処理が挟まれると非常に醜い。 なので、最終的な個別変換を分離する。そうするとhtmlがついてないときはrunをつけるとか、好きに追加できるだろう。

DONE 手動で形式選択できるように

helmから選べたらベスト。選択をどうやってやればいいのかよくわからない org-roamのファイル選択で出てくるhelmなど参考になりそう。

DONE checkdocをCIで走らせるようにする

elisp-checkはcask環境のためうまくできない。 なので、elisp-check.elを直に読み込んで実行するようにすればよさそう。

elisp-lintというパッケージに同梱されてたのでそれで一気にできるようになった。

DONE Magit(Gitクライアント)の場合。

git-link の整形バージョン。 そこまではちょっとやりすぎ感。依存が増えすぎるのも微妙な感じか。でも欲しいよな…。 各PRまではいいけど、少なくともリポジトリのホームページくらいならいいかな。

これができるとメモるとき便利なんだよな。