Humanity

Edit the world by your favorite way

Vim のレジスタに :terminal のシェル上からアクセスする

Vim その2 Advent Calendar 2018 の記事です。

Advent Calendar 4日目で mattn さんが紹介してくれていた Tapi について、 ちょうど Tapi を使ったプラグインを作っていたので紹介したいと思います。 実際にこんな事ができるという例としてもシンプルで分かりやすいと思います。

概要

github.com

tapi-reg.vimVimレジスタと端末の標準入力/出力を繋げるものです。 :terminal で動かしているシェル上に Vimレジスタの内容を出力したり、 逆にシェル上から Vimレジスタの内容を書き換えたりできます。

セットアップ

動作には jq コマンドが必要です。 インストールはほぼ全ての OS でパッケージが用意されています

jq コマンドをインストールしたら

source <this repo>/macros/vimreg.sh

を .bashrc に書いてください。 vimreg というコマンドが使えるようになります。

どんなことができるのか

以下は README をほぼそのまま英訳したものです。 詳しくは README を見て下さい。

:terminalVim:terminal から Vimレジスタの内容を書き換える

Vim:terminal のバッファから vimreg コマンド経由で Vimレジスタの内容を書き換えることができます。

$ echo 'send this text to vim register!' | vimreg

これで無名レジスタsend this text to vim register! の内容がセットされます。

もちろんレジスタ名を指定する事もできます。

$ echo 'send this text to register a!' | vimreg a

vimreg は標準入力から文字列を取得するため、もちろんこのようにもできます。

$ vimreg
This
is
sent
to
vim
register.
^D
$

:terminalVimVimレジスタの内容を標準出力に出力する

vimreg--get (-g) オプションをサポートしています。 これは Vimレジスタの内容を標準出力に出力するものです。 もしレジスタ名が指定されなかったら、無名レジスタの内容が出力されます。

$ vimreg -g
Hello this is vim unnamed register content.
$ vimreg -g a
this is "a" register content.

また Vim レジスタの一覧とその内容を出力する事もできます (:registers の出力と同じ)。

$ vimreg -l
--- Registers ---
""   --- Registers ---^J""   ^J^J"0       if a:args[1] ==# '--list'^J^J"1   ^J^J"2       if a:args[1] =~# '\v^(-l|--list)$'^J^J"3     local reg='"'^J^J"4     set +x^J^J"5     set -x^J^J"6     set -x^J^J"7  
"0   --- Registers ---^J""   ^J^J"0       if a:args[1] ==# '--list'^J^J"1   ^J^J"2       if a:args[1] =~# '\v^(-l|--list)$'^J^J"3     local reg='"'^J^J"4     set +x^J^J"5     set -x^J^J"6     set -x^J^J"7  
"1   ^J
"2       if a:args[1] =~# '\v^(-l|--list)$'^J
"3     local reg='"'^J
"4     set +x^J
"5     set -x^J
"6     set -x^J
"7       content=^J
"8       printf '\e]51;["call","Tapi_reg",["set",%s,%s]]\x07' \^J        "$(to_json_string "$reg")" "$(to_json_string "$content")"^J
"9   $(to_json_string "$3")
"a   degure
"s   "
"-   $list || 
".   --list
":   call system('clip.exe', execute('registers'))
"%   macros/vimreg.sh
"#   plugin/tapi_reg.vim
"/   --list

疑似クリップボードサポート (Windows Subsystem Linux (以下 WSL) のみ)

もちろん vimreg では has('clipboard') == 1 の場合にクリップボードの内容も扱えます (つまりシェル上から Vim 経由でクリップボードの取得・設定もできます)。 しかしWSL では has('clipboard') == 0 にもかかわらずクリップボードを扱えるようになっています。

$ vimreg +
Send
this
text
to
clipboard
^D
$

CDDB に初めて登録したけどジャンル欄が文字化けてしまうので助けてほしい

CDDB は CD 入れると取得できるアレ。 自分はここのを使わせてもらってる。

https://freedbtest.dyndns.org/

設定はこの通りにしてある。

cdex の設定

そして送る時はここを参考にした。

TIPS集みたいな

登録したやつはこれ。

DIVERSE DIRECT | La Kasketia

DIVERSE DIRECT | nishi-ogikubo Landscape

2018/10/03

まだ表示されてない。 「更新: 2018-10-03 03:21:59」と書いてあるから明日にでもなったら表示されるはず。

Namazu: a Full-Text Search Engine: <La Kasketia>

2018/10/04

検索結果に表示された。

「更新: 2018-10-04 03:21:22」らしいので大体一日間隔でその時間に終わるっぽい。 ただバッチがいつ始まるか分からないので、いつ送れば登録されるかはわからない。

肝心のデータの方はというと、ジャンルが文字化けしてた。 同時に買った ∀rkadia のデータ を参考にして「ジャンル:同人」で送った。

f:id:tyru:20181004152809p:plain

おそらく UTF-8 で送らなければいけない所に CP932 で送って「<0x93><0xaf><0x90>l」のようになってしまっていると思われる。

これに対して2通りの方法を試した。

dbread4.php

こっちは以下の手順。

  1. CDPlayer.ini に書き出し
  2. CDPlayer.ini を UTF-8 にする
  3. CDPlayer.ini から読み直す
  4. CDDB に送る

dbread4.php

こっちは以下の手順。

  1. (CDex のパス)\LocalCDDB\CDexGenres.txt を UTF-8 にする
  2. CDex を再起動する
  3. CDDB に送る

とりあえず明日両方見てどっちの方法が正しかったのかを見るつもり。

ただ後者がまた文字化けしたデータを送ってしまった可能性が高いと思っていて、 CDexGenres.txt 送ったあとに末尾に cp932 のデータが追加されていた。

255  Animation   misc
255 Anime(J)    misc
255 同人  misc

おそらくどこからか読み取った「255 同人 misc」の行がなかったから末尾に追加されたと思うんだけど、読み取った場所が CDDB からなのか他にも「同人」のデータが残ってしまった。

255  Animation   misc
255 Anime(J)    misc
255 同人  misc
(cp932 の "255 同人  misc")

検索してみたらいくつか「同人」のデータはあった。

# jvgrep は日本語の複数エンコードで書かれた文字列を探せるやつです https://github.com/mattn/jvgrep
$ jvgrep -R '同人' /mnt/c/app/cdex_151/
/mnt/c/app/cdex_151/LocalCDDB/CDexGenres.txt:4:255      同人    misc
/mnt/c/app/cdex_151/LocalCDDB/SUBMIT.TXT:23:DGENRE=同人
/mnt/c/app/cdex_151/LocalCDDB/misc/6dto6d:24:DGENRE=同人
/mnt/c/app/cdex_151/LocalCDDB/misc/79to79:23:DGENRE=同人
/mnt/c/app/cdex_151/LocalCDDB/misc/7dto7d:25:DGENRE=同人

そもそも CDex 1.51 とかいう古いバージョンを使ってるのが悪くて、最新だと普通に UTF-8 で送るようになっているのかもしれない…


というわけで CDex 1.77 (Portable, Unicode 版) で再度送ってみた。


そういえばコンピレーションアルバムの場合は V.A.Various Artists どちらがいいのかについてもちょっと迷ったことを思い出した。 項目検索できることをふと思い出して、再度試してみる。

Namazu: a Full-Text Search Engine: <+Artist:"Various Artists">

Namazu: a Full-Text Search Engine: <+Artist:"V.A.">

V.A. が 4069 件、 Various Artists が 56500 件だった。 長いものにはぐるぐる巻かれていくタイプなので、今後 "Various Artists" で統一する。

2018/10/05

送りすぎて制限されたかな… 追記(2018/10/25): メールで問い合わせた結果、回数等に制限はないとのこと。

f:id:tyru:20181006105334p:plain

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Content-Length: 3
#
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
サーバーからの応答がありませんHTTP/1.1 400 Bad Request

Date: Sat, 06 Oct 2018 01:49:38 GMT
Server: Apache/2.2.31 (FreeBSD) mod_fcgid/2.3.9 mod_ssl/2.2.31 OpenSSL/1.0.1u-freebsd
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1
サーバーからの応答がありません<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

CDex 1.77 で送ったはずなのに Submit via : CDex 1.51 となっているのでもしかして昨日あたりから制限されてたんだろうか(エラーは出なかったけど)。 それとも送るのが遅かっただけだろうか。

結果的に制限されてしまった?のでちょっともうよくわからない。 誰か直せる人直して…

追記: 2018/10/25

管理人の方からメールの返信が来て、 文字化けはジャンルに日本語が入ることを想定していなかったことが原因とのことで、 現在は対応してもらって Web 上でも表示できるようになっていた。

ちなみに書いてなかったけど、Web の表示は文字化けてたけど、CDDB に問い合わせて取得したデータは文字化けていなかった。

400エラーについては

  • 回数等に制限は設けておらず
  • 「必ず発生するということであればなにか送信してくるデータが想定外の形でこちらが受け取れていないのかもしれません」とのこと

端末アプリで Ctrl-[ が Esc になる理由

理由

SHIFT キーはキーコードを -0x20、CTRL キーはキーコードを -0x40 する機能

全文

vim-jp.slack.com の #random から。

heavenshell [10:08 AM]
TouchBar MBP にしたら強制的に C-[ になるので、オススメです!ようやく矯正できた。

mattn [10:09 AM]
人間の方が最適化されている

yoshitia [10:12 AM]
Escが物理的にない状況用にデフォルトでCtrl-[ 用意してるのすごい

mattn [10:14 AM]
いや、用意した訳ではないです。
SHIFT キーはキーコードを -0x20、CTRL キーはキーコードを -0x40 する機能なのです。
なので `[` つまり 0x5b は 0x1b になる。
0x1b = ESC
同様に CTRL-H は H が 0x48 なので 0x08、つまり BS になる。

yoshitia [10:17 AM]
元からある仕組み上、代用ができちゃうだけなんですね

mattn [10:17 AM]
ですです。
逆に言うと
`;` は 0x3b なので CTRL を使うと 0 以下になる、つまり使えないという事です。
端末の場合はマッピング出来る事もありますが、gvim で出来ないのはそれが理由です。

yoshitia [10:19 AM]
符号付UNICODEの機運(ない

KoRoN [10:26 AM]
僕は ENTER の代わりに CTRL+M 使うことが多い。 (0x4D - 0x40 = 0x0D)
あれ? あれ?
M=0x4D, m=0x6D だな。
小文字基準で CTRL は -0x60 とすべきなのかな。 (edited)

mattn [10:30 AM]
あ、ですです
これちなみに Unicode も受け継いでてくれてて

KoRoN [10:30 AM]
でもそうすると 5b が説明つかん?

mattn [10:30 AM]
`a` と `A` は -0x60 なんすよね
CTRL は 0x40

KoRoN [10:31 AM]
やっぱ大文字基準で、 SHIFT=+0x20 CTRL=-0x40 のほうが合致しそう。

KoRoN [10:32 AM]
そういや昔のプログラム、全部大文字だったりしたな。

mattn [10:32 AM]
これ、0 割れした場合の処理が端末毎に異なってるのがイヤらしいんすよ。
* 受け付けない
* 300 から引く
みたいな色々流儀がある