VimConf 2023 Tiny を振り返る

先週の 2023 年 11 月 18 日、VimConf 2023 Tiny が開催されました。

開催からもう一週間も裁っていまいました。筆が遅い…。

久々の VimConf

VimConf は 2013 年から毎年 11 月に開催されていましたが、2020 年から 2022 年の 3 年間、COVID-19 の影響で休止していました。

そして今年、ついに復活を果たすことができました。ブランクもあり、また COVID-19 の影響が完全になくなったというわけでもないため、規模を縮小しての復活になります。

普段なかなか顔を合わせる機会がない面々と久しぶりに会えたことや、この 3 年で vim-jp 界隈に現れて今回初めて会えた方々もおり、大変嬉しいです。

VimConf と私との関わり

私は例年 VimConf にはスタッフとして関わらせてもらっています。今回も例に漏れずスタッフをやらせて頂きました。

今回は縮小開催だったこともあり、スタッフの仕事はそれほど多くなく、改めて振り返ると私がやってたのは懸念事項を洗い出したり関係者各位にリマインドを行ったり、くらいしかやってないような気がしてきました。

当日は受付でチケットの QR コードを読み込んだり、参加者と雑談したり、発表を最後部席から見守ったり、参加者と雑談したり、懇親会の会場の準備を見守ったり、参加者と雑談したりしていました。雑談楽しい。

今は参加レポートの記事がたくさん上がってきていて、見つけられた限りでは全て読ませて頂いています。やはり反響があるのは嬉しいです。

反省会

振り返りということで少し一人反省会をしてみます。

名札はやっぱりほしい

今回は労力を最小にするために名札の制作をカットしました。この判断は間違ってはいなかったと思いますが、それでもやはり名札はほしいな、と思いました。

休憩時間や懇親会で、「あのアイコン見覚えがある!」となるのとそうでないのとではやはり話しかけやすさが変わってきます。

もうちょっと仕事できた気がする

結構な部分を他のメンバーにやってもらってしまった結果、私自身はなんかほぼなんもしてないくらいの勢いでなんもしてなかった気がしてきています。 他のメンバーがやってくれていた仕事のうちいくつかは引き取れたんじゃないかと今になって思ったりしています。

受付の構築で少しもたついてしまった

現場で即座にビシッと決めるのが苦手なのもあり、受付での列形成をどうしようか、迷ってしまって決められずもたついてしまっていました。

開場前に入口で不安になられた方がいたら申し訳なかったです。

実は 10 周年

ところでお気付きでしょうか。最初の VimConf は 2013 年でした。 今年は 2023、つまり 10 周年です!めでたい。あまり触れられていませんでしたが、実は節目の年でもありました。

来年以降については現時点では何も決まっていませんが、少なくとも私はやりたいと思っています。微力ながら支えていければと思います。

11 年目以降も VimConf をよろしくお願いします!

Vim 駅伝 100 回記念

この記事は Vim 駅伝 の 100 本目の記事です。

というわけでついに 100 本目です!

私は言い出しっぺにも関わらず、記事はほとんど書けていません。申し訳ない…。

にも関わらず、ここまで続いたのは賛同してくれた皆さんの尽力によるものです。 おかげで新鮮な Vim の記事が定期的に届けられています。本当にありがとうございます。

さて、今回は 100 回ということで、普段書いてないくせにこういう時だけしゃしゃり出てきました。ずるいですね。 ここまでの Vim 駅伝の歩みをざっくり振り返ってみたいと思います。

投稿回数ランキング

投稿回数ランキングを集計してみました。対象はこの投稿も含む 100 回分です。

順位 投稿回数 走者
1 8 staticWagomU
2 7 ryoppippi
2 7 monaqa
2 7 kyoh86
5 6 uga-rosa
6 5 tani
6 5 kawarimidoll
6 5 atusy
9 4 kuuote
10 3 thinca
10 3 ArcCosine
12 2 slin
12 2 utubo
12 2 ゴリラ
12 2 ryota2357
12 2 mityu
12 2 matoruru
12 2 K Ikeda
12 2 kamecha
12 2 eihigh
12 2 NI57721
22 1 yuucu
22 1 yukimemi
22 1 uhooi
22 1 tomato3713
22 1 tadashi-aikawa
22 1 swnakamura
22 1 sontixyou
22 1 ぺりー
22 1 raa0121
22 1 koralle
22 1 浅倉有人
22 1 ikorihn
22 1 igrep
22 1 hokorobi
22 1 IK
22 1 fuzmare
22 1 futsuuu
22 1 Fohte
22 1 Liquid_system
22 1 4513ECHO

参加ユニークユーザー数は 41 人でした。 何度も参加してくれている人もいる一方、「まずは参加する」を達成した 1 回投稿の人が 20 人と約半分でした。 少人数で同じ人が何度も投稿して回しているとどうしても無理が出てきますし、これは結構バランス良く分布したなと感じました。

記事の種類

記事をざっくり分類して、それぞれの記事がいくつあったのかを集計してみました。

なお、分類は私の独断と偏見によるものであり、イベント運営の公式見解とかではありません。 分類に迷った記事も多く、ノリと勢いだけで分類したのであまり一貫性がないかもしれません。明らかにおかしい!とかありましたらコッソリ教えてください。コッソリ直します。

順位 記事数 種類 種類の説明
1 38 プラグイン紹介 特定のプラグインや、その設定、使い方やテクニックについて紹介する記事です。
2 29 設定 特定のプラグインには依存しない設定、vimrc/init.vim(lua) などに関する記事です。
3 8 スクリプトテクニック プラグインの開発における Tips やノウハウを紹介する記事です。
4 6 Vim 駅伝 Vim 駅伝自体に関する記事や、企画です。
5 5 エピソード Vim との関わりや、Vim にまつわるお話の記事です。
5 5 スタイル Vim を使う上での考え方や流儀についての記事です。
7 3 本体 Vim 本体のビルドやパッチ作成に関する記事です。
7 3 使い方 基本的な使い方や機能を紹介する記事です。
7 3 Vim ライク Vim 自体ではない Vim ライクなものを紹介する記事です。

プラグインの紹介や、使っている設定の紹介が多い印象でした。身近な分記事にしやすい、などの理由がありそうです。

Appendix. ここまでの記事一覧

最後に記事一覧を載せておきます。Vim 駅伝のアーカイブページでも見られますが、せっかくなのでここに並べておきます。 どの記事をどこに分類したかも載せておきます。

皆さん本当にありがとうございます。今後もよろしくお願いします!新しい執筆者も増えるといいですね。

番号 公開日 走者 記事 種類
1 2023-03-01 thinca Vim 駅伝、始動します Vim 駅伝
2 2023-03-03 atusy Insertモードでも気軽に←・→したい 設定
3 2023-03-06 ryoppippi bunsetsu.vimとbunsetsu-wb.nvimを作ってます!!! プラグイン紹介
4 2023-03-08 tani Project V 「思考のスピードで編集せよ。32年の伝統をもつテキストエディタをビルドする。」 本体
5 2023-03-10 kyoh86 heirline.nvimでNeovimのStatusLineをカスタマイズしてみる プラグイン紹介
6 2023-03-13 staticWagomU Vim,Neovimのフォント変更方法について 使い方
7 2023-03-15 kuuote Vim Input Method Editor プラグイン紹介
8 2023-03-17 Liquid_system lualine.nvimでステータスラインをカスタマイズしよう! プラグイン紹介
9 2023-03-20 thinca Vim9 script の始め方 スクリプトテクニック
10 2023-03-22 matoruru 錆びついたinit.vimをLuaで書き換えてピカピカにする 設定
11 2023-03-24 fuzmare neovimターミナルモードエスケープと即座に確定するマッピング 設定
12 2023-03-27 tadashi-aikawa Vimを使わないVimmerであってもいい Vim ライク
13 2023-03-29 ArcCosine Vimのテキストオブジェクトとsurround.vimで効率よく入力 プラグイン紹介
14 2023-03-31 monaqa Vim 駅伝開始1ヶ月を振り返る Vim 駅伝
15 2023-04-03 IK Vim + npm install --save-dev textlint 設定
16 2023-04-05 eihigh ミニマリストに憧れて - 無彩色カラースキームを作った話 プラグイン紹介
17 2023-04-07 uga-rosa vusted & nvim-kitでユーザーの入力をテストする スクリプトテクニック
18 2023-04-10 ゴリラ denops-docker.vim のバグを直した話 プラグイン紹介
19 2023-04-12 monaqa dial.nvim の新機能紹介 プラグイン紹介
20 2023-04-14 ArcCosine HHKBとVimとの親和性について語る スタイル
21 2023-04-17 matoruru Vim(vi)との出逢いを振り返る エピソード
22 2023-04-19 atusy tsnode-marker.nvimでコードブロックとかの背景色を変える プラグイン紹介
23 2023-04-21 staticWagomU Eclipse 上で Vim ライクな操作を可能にする Vrapper を使ったはなし Vim ライク
24 2023-04-24 uga-rosa Neovim用のターミナルプラグインを作った話 プラグイン紹介
25 2023-04-26 ryoppippi Neovim 0.8以降のビルトインLSPについて 使い方
26 2023-04-28 ゴリラ My Vim philosophy 2 スタイル
27 2023-05-01 hokorobi dein.vim の hooks_file を使って vimrc を書き換えた話 プラグイン紹介
28 2023-05-03 slin DDSKKのチュートリアルをやりたい プラグイン紹介
29 2023-05-05 kamecha 部内SNSのVimクライアントもどきを作ってVim†完全に理解した†話 プラグイン紹介
30 2023-05-08 kyoh86 NeovimでScalaを使ってマインクラフトのプラグインを作ってみる 設定
31 2023-05-10 ryota2357 vim.ui.inputを自作floating windowにした 設定
32 2023-05-12 uga-rosa ccc.nvimのcolor highlighter機能について プラグイン紹介
33 2023-05-15 ikorihn NeovimとVSCode Neovimで使用するプラグインや設定を使い分ける 設定
34 2023-05-17 staticWagomU Neovim+LSPをなるべく簡単な設定で構築する ~ Lazy.nvim編 ~ プラグイン紹介
35 2023-05-19 monaqa Vim キーバインドをカスタマイズするとき考えていること スタイル
36 2023-05-22 ryoppippi NeovimでのSvelte/SvelteKitの開発環境 プラグイン紹介
37 2023-05-24 atusy leap.nvimを拡張して検索対象にラベルをつけて飛べるleap-search.nvimを作った プラグイン紹介
38 2023-05-26 kyoh86 Neovimの設定すべてをまるっと切り替えられるマルチプロファイル運用 設定
39 2023-05-29 uga-rosa ddu.vimにちゃんと入門した話 プラグイン紹介
40 2023-05-31 mityu zsh on :terminal on Vim で zsh のカレントディレクトリを Vim と同期する 設定
41 2023-06-02 staticWagomU キーマッピングを設定しないVimmerが居たっていい スタイル
42 2023-06-05 eihigh 2023年版VimでGoを書く プラグイン紹介
43 2023-06-07 sontixyou Neovimで今開いているファイルのパスをコピーするスクリプトを作った話 設定
44 2023-06-09 yukimemi Typescript で Vim / Neovim の設定を書く! 設定
45 2023-06-12 uhooi NeovimのHEADをビルドする方法 本体
46 2023-06-14 kawarimidoll Vim scriptで1回しか使えないコマンド・関数を定義する スクリプトテクニック
47 2023-06-16 staticWagomU vim.defer_fn でコマンドを直列実行する スクリプトテクニック
48 2023-06-19 uga-rosa LSP完全に理解した(ddu-source-lspの紹介) プラグイン紹介
49 2023-06-21 monaqa 【企画】これだけは外せない!あなたにとっての「いぶし銀」なプラグインを教えてください Vim 駅伝
50 2023-06-23 futsuuu Neovim の LSP 関係のプラグインの役割 プラグイン紹介
51 2023-06-26 4513ECHO Denopsでプラグインを作るときのTips スクリプトテクニック
52 2023-06-28 ryoppippi とあるコーディングチョットワカル勢のエディタ遍歴 エピソード
53 2023-06-30 monaqa Vim の一括置換を楽に行う裏技 設定
54 2023-07-03 staticWagomU 初めて参加したもくもく会の感想 エピソード
55 2023-07-05 tani タイポ修正を支える技術 プラグイン紹介
56 2023-07-07 kawarimidoll Vimでやべー名前のファイルが保存されるのを防止する 設定
57 2023-07-10 tani Vimmerのレベル10 スタイル
58 2023-07-12 NI57721 Vim を IME として使いこなす 設定
59 2023-07-14 tomato3713 Neovimでディレクトリを開いた時に任意のファイラープラグインを起動する設定を楽にするプラグインを作った プラグイン紹介
60 2023-07-17 K Ikeda vim-jp-westのオフ会幹事をしました エピソード
61 2023-07-19 ぺりー Vimカラースキーム自作のすすめ スクリプトテクニック
62 2023-07-21 monaqa 「いぶし銀プラグイン」企画集計結果発表(前編) Vim 駅伝
63 2023-07-24 atusy Vimでコマンドライン履歴を遡りやすくする 設定
64 2023-07-26 kyoh86 配下のファイルを一覧するときはディレクトリに色を付けると見やすい! プラグイン紹介
65 2023-07-28 ArcCosine denops.vim を使って初めてvim-pluginを作った。MarkdownをHTMLに変換してクリップボードにコピーする。 スクリプトテクニック
66 2023-07-31 yuucu lazy.nvimを使った起動時間チューニング入門! ~起動速度10倍を目指して~ プラグイン紹介
67 2023-08-02 浅倉有人 Vimっぽいな feat.初音zenn Vim ライク
68 2023-08-04 uga-rosa ddc-source-nvim-lspを大幅に強化した プラグイン紹介
69 2023-08-07 igrep Vimの検索で、都合がいいときだけ大文字小文字を区別する 使い方
70 2023-08-09 kawarimidoll Vimでspaceなしで展開できるabbrevっぽいものを作る 設定
71 2023-08-11 staticWagomU sandwichを使ったら案の定便利だったはなし プラグイン紹介
72 2023-08-14 kuuote フルパスをいい感じに入力する 設定
73 2023-08-16 ryoppippi 「commit messageを考えてる間によしなに git hooks を実行しておいてね!」を実現するneovimの設定をかいた 設定
74 2023-08-18 kyoh86 ddu.vimの使い方を俯瞰してみる プラグイン紹介
75 2023-08-21 monaqa 「いぶし銀プラグイン」企画集計結果発表(後編) Vim 駅伝
76 2023-08-23 tani Quickfix is all you need スクリプトテクニック
77 2023-08-25 kuuote cmdwinっぽい物を数行で作る 設定
78 2023-08-28 utubo mecabを使って漢字をよみがなに変換するプラグインetc. プラグイン紹介
79 2023-08-30 tani Artemis: Bridging gap between Vim and Neovim プラグイン紹介
80 2023-09-01 atusy mini.surroundによるHTMLタグ編集のemmet対応 プラグイン紹介
81 2023-09-04 K Ikeda vim-jp-west 歓迎&懇親会を開催しました エピソード
82 2023-09-06 swnakamura VimとIMEの仲を取り持つ 設定
83 2023-09-08 koralle null-ls.nvimがアーカイブされちゃったので移行先としてefm-langserver(+nvim-lsp)を検討してみる) プラグイン紹介
84 2023-09-11 kuuote 素早く安全にプラグインにパッチを打つ 設定
85 2023-09-13 raa0121 Ubuntu でも最新のVimを使いたいなら、Dockerから拾えばいいでしょ 本体
86 2023-09-15 NI57721 俺のAZIKが火を噴くぜ! 設定
87 2023-09-18 Fohte GhostText: Vim でブラウザのテキストエリアを入力する プラグイン紹介
88 2023-09-20 kawarimidoll Vimでインデント幅の単位で左右移動する 設定
89 2023-09-22 staticWagomU 闇の力への入門 ddc.vim編 プラグイン紹介
90 2023-09-25 kyoh86 Quickfixの中身を表として書き出せると地味に便利 設定
91 2023-09-27 ryoppippi BunとNeovim 設定
92 2023-09-29 ryota2357 textlintをefm-langserverとnvim-lspで導入してみた プラグイン紹介
93 2023-10-02 slin skkeletonのTips プラグイン紹介
94 2023-10-04 kamecha ddu.vimのアクション周りを便利にしよう プラグイン紹介
95 2023-10-06 utubo vimでgit addする前に--dry-runして確認する 設定
96 2023-10-09 kyoh86 denols/typescript-lsのLSPスイッチングは意外と気を遣うよという話 プラグイン紹介
97 2023-10-11 mityu :terminal から親の Vim でファイルを開く(bash/zsh 編) 設定
98 2023-10-13 kawarimidoll Vimで直前の検索結果をQuickFixに格納する 設定
99 2023-10-16 ryoppippi Vim/Neovimのプラグインマネージャーを悪用してCLIの管理ツールとして使う 設定
100 2023-10-18 thinca 100 回記念 Vim 駅伝

Vim9 script の始め方

この記事は Vim 駅伝の 9 本目の記事です。

9 本目ということで、Vim9 script について書きます。

Vim では Vim script を使ってエディタの挙動を拡張できますが、Vim 9.0 では新たに Vim9 script が追加されました。本記事ではそのさわりとして、Vim9 script の実行方法について簡単に紹介します。

Vim9 script について

従来の Vim script にはいくらか問題がありました。特に実行するたびにパースを行う関係上、動作が非常に遅く、また互換性の観点からわかりづらい文法があったりします。

Vim9 script は Vim script との互換性を捨て、処理速度の向上とよりわかりやすい文法を提供する目的で導入されました。 と言っても、ベースとなる文法を大きく変えることはせず、いくつかのとっつきづらい文法の見直しが行われています。

その他の特徴として、型の導入による型チェックの機能があります。 開発中の機能ですが、将来的にもあまり複雑なチェックができるようになることはないのではないかと個人的には予想しています。

Vim9 script の実行方法

Vim9 script として実行されるコードを書く方法は大きく 4 種類あります。

ファイル

ファイルの先頭に :vim9script Ex コマンドを置くと、そのファイルは Vim9 script として実行されます。

vim9script

var name = 'Vim9 script'
echo $'Hello, {name}'

関数

Vim script では :function Ex コマンドで関数を作ります。 Vim9 script では、代わりに :def を使います。これは Vim script 中にも混在して書くことができ、関数の中身だけが Vim9 script になります。

" ここは Vim script
let g:hello = 'Hello'

def! Greeting(name: string)
  # ここは Vim9 script
  echo $'{g:hello}, {name}'
enddef

" ここは Vim script
call Greeting('Vim9 script')

Vim9 script で定義した関数も通常の Vim script から呼び出すことができます。

:vim9cmd Ex コマンド

:vim9cmd Ex コマンドを使うと、その場でだけ Vim9 script を実行できます。

vim9cmd var name = 'Vim9 script'
vim9cmd echo $'Hello, {name}'

:command:autocmd

:command Ex コマンドと :autocmd Ex コマンドでは、実行されるコマンドの部分にブロック記法による Vim9 script の記述ができます。

command! -nargs=1 Hello {
  var name = <q-args>
  echo $'Hello, {name}'
}

Hello Vim9 script
" サンプルなので augroup は省略
autocmd! User hello-vim9 {
  echo 'Hello, Vim9 script'
}

doautocmd User hello-vim9

この場合のブロックは } で始まる行を終了行とするため、入れ子にするなどして別の } が行頭に来てしまうと期待通りに動作しないことに注意が必要です。

autocmd は、Vim9 script 内で実行するとその内容も Vim9 script として解釈されます。

def! MyAutocmd()
  autocmd! User hello-vim9 g:str = 'Vim9 script'
enddef

call MyAutocmd()
doautocmd User hello-vim9
echo $'Hello, {g:str}'

まとめ

Vim9 script を実行する方法について紹介しました。

  • ファイル全体を Vim9 script として実行する方法
  • Vim9 script の関数を定義する方法
  • 一時的に Vim9 script を実行する方法
  • その他の特殊な箇所

と言っても、Vim9 script の書き方がわからないと中身が書けないかと思います。

Vim9 script 自体の書き方についてはいずれ(気が向いたら)書こうと思います。

Vim 駅伝、始動します

これは Vim 駅伝 の 1 本目の記事です。

Vim 駅伝は、駅伝でタスキを繋ぐように Vim に関する記事を参加者で順番に書いていくイベントです。

発端

2023 年 2 月 6 日、vim-jp 内で Advent Calendar が話題に上がりました。

Advent Calendar は 12 月の 1 日から 25 日まで毎日参加者がトピックに関する記事を書いていくイベントです。 この時期になると大量の Advent Calendar が立てられ、それぞれのトピックで毎日記事が公開されます。 12 月に集中して大量の記事が公開され、お祭りのようなイベントとして毎年盛り上がります。

同じテーマの Advent Calendar がいくつも併走していることに対して、私が以下のような発言をしました。

ぶっちゃけ 12/1 ~ 12/25 の間に何周分も大量に記事が投下されるよりも長い期間毎日投稿された方が私は嬉しい

見ての通り、「わかる」のリアクションがたくさん付きました。同じように感じている人は結構いたようなので、後日以下のようなアンケートを取ってみました。

リレー執筆企画についてのアンケート

結構興味ある人が多そう。鉄は熱いうちに打て。というわけで Slack 内に専用のチャンネル #event-vim-ekiden を作り、イベントのための Web サイトをみんなで協力して用意しました。 色々準備をしていた関係で 2 月の頭から少し時間が空いてしまいましたが、本日 2023 年 3 月 1 日から開始します。

Vim 駅伝の概要

細かい部分は走りながら決めていくことになると思います。

  • 誰でも参加 OK
  • 投稿は月、水、金の週 3 回
    • 参加人数的にも、毎日は恐らく持たない。できるペースでやっていく
  • 終わりについては今のところ考えていない
    • 執筆者がいなくなったら自然消滅になるのかなと想像している
  • 駅伝になぞらえて「区間」のような区切りを用意したい
    • という話をしているが、現時点では何も決まっていない
    • 1 ヶ月で 1 区間?
    • 区間の区切りには何をするのか?

参加方法

誰でも参加可能です。 まずは書きたい記事を考えます。Vim に関することなら何でも大丈夫です。

  • 今日、人に教えてもらった Vim の Tips
    • あなたが知らなかったということは他にも知らない人はたくさんいるはず
  • 作ったプラグインの紹介
  • VSCodeVim(Neovim) について
  • ブラウザで使える Vim 系の拡張
  • Vim の歌を作ったので聴いてほしい
  • 内容はこれから考える。まずは参加だ

記事を書く場所は、インターネット上で広く公開されている場所ならどこでも大丈夫です。 技術記事の投稿サービスでも、自前のブログでも、スニペットサービスでもどこでもよいです。

分量も自由です。140 文字以内でもよいし、1 万文字を越える大作でも大丈夫です。 ただし、長くなる場合はシリーズ化することも検討してみてください。その方が読む側も書く側もラクになるはずです。

参加を決めたら、以下の Vim 駅伝のサイトから、まだ誰も登録していない日を選んで「参加登録」のリンクに飛びます。

https://vim-jp.org/ekiden/

すると GitHub の Issue を作成するページに飛びます。

GitHub Issue 作成ページ

最低限記事のタイトルを入力してください。入力は必須ですが、公開日までに入っていれば大丈夫なので「なにか書く」などでも大丈夫です。 執筆者名は、空にすると GitHub のユーザー ID になります。それ以外がいい場合は入力してください。 記事の URL も後からで大丈夫です。公開予定の URL がすでに決まっている場合は入力します。

Issue を作ると CI が動作し、Web サイトに反映されます。しばらく待ったら確認してみてください。

あとからタイトルや記事の URL が決まった場合は、Issue の description を編集して直接入力してください。編集の際はフォームではなく Markdown を編集することになるので、必要な箇所だけを編集してください。フォーマットが崩れると CI がうまく処理できない場合があります。

当日になったら記事を公開してください。あとはやることは特にありません。

定期的に参加してもらってもよいですし、スポット参加も大歓迎です。誰かが書かないとタスキが途切れるので、積極的に参加して頂けると嬉しいです。

コントリビューター募集

一番のコントリビュートは記事を書くことなのですが、それ以外にもやることがあります。

見ての通り突発で始まったので、主に Web サイト周辺の整備や参加希望者への案内が不十分な状態です。 この辺りの相談は vim-jp Slack 内の #event-vim-ekiden でしています。

Slack に参加するのが難しい方は GitHubvim-jp/ekiden にて Issue を立ててもらっても大丈夫です。 参加登録の Issue ではなく、テンプレートを使わずに Issue を立ててください。

最後に

このイベントが継続できるかどうかは執筆者が集まるかどうかにかかっています。皆さんのご参加お待ちしております。

新宿もくもく会(仮)をやった

1 年ぶりくらいのブログ更新。まだ書く気あったんですねー。

新宿もくもく会(仮)開催までの流れ

きっかけは 12/26 に日付が変わった直後頃のこと。 Slack での何気ない発言に私が反応したことでした。

Slack での発言

結果的に元発言の「イベント」はリアルイベントを想定したものではなかったんですが、きっかけなんてなんでもいいのです。

呼応する Vimmer

呼応する Vimmer

鉄は熱いうちに打て。即座に調整さんを立てます。

調整さんによる参加者の募集

集結する Vimmer

入力された調整さん

同日 19 時過ぎ。新宿にあるレンタルスペースを予約。開催決定です。

予約完了

当日の様子

途中参加や、都合により早抜けする人もいましたが、計 8 名の Vimmer が集結。

私自身、Vim 関係のリアルイベントは 2020 年 3 月以降で初めてです。 非常に和気あいあいとした雰囲気で、もくもく会と言いつつ常に誰かが誰かと相談したり雑談したりしていて、全員が作業に没頭して静まり返っている時間はまったくなかったように思います。

途中、会場の様子を Discord のボイスチャンネル経由で中継したりもしました。会場の様子がどの程度伝わっていたのかはちょっとわからないですが…。

個人的な成果

進捗

action-setup-vim が一部環境で動かなくなっていたのをなんとかしました。

GitHub Actions の GitHub Hosted Runner の ubuntu-latest のバージョンが 22.04 になり、環境の条件が変わった影響で AppImage が動かなくなっていました。 これに対する対応を以前 k-takata さんが vimdoc-ja-working リポジトリにて行っていたので、このやり方を取り入れる形で対応しました。

この方法は apt-get で新しいパッケージが入ってしまったり、ちょっと危険な環境変数が設定されてしまったりと副作用も大きいのですが、動かないよりかはマシだろう、と言うことで一旦入れました。問題があったら誰かが報告してくれるだろう…。

ガジェットの譲渡

個人的に不要になって持ち腐れ状態になっていたモバイルディスプレイ 2 枚と、格安の HDMI キャプチャを他の参加者の方に譲ることに成功しました(※有償)。

ずっと使われていなくてもったいなかったので、活用してくれる人の手に渡ったのはよいですね。

感想など

突発的な集まりにも関わらず参加してくださった皆さん、ありがとうございました! やはり実際に集まってわいわいするのは楽しいですね。

このくらい緩い会ならまた開催することは可能だと思うので、希望者の声などを聞きつつ折を見てまた開催するのもいいかもしれません(※開催を保証するものではありません)。

Twitter bot を作った時のメモ

Twitter bot を作ってみているのでその時のメモ。 あくまで個人的なメモであり、網羅的な解説などをするものではないです。

方針

なるべく新しいものを使いたいと思ったので、Twitter API v2 + OAuth 2.0 を使うことにした。

Twitter API v2 は 2021-11-15 にプライマリ API に指定された。まだ一部 1.1 にあって 2.0 にはない API もあるようだが、基本的には 2.0 を使っていくのがよさそうだ。

OAuth はどうも、App レベルのアクセスは 2.0 でユーザーレベルのアクセスは 1.0a みたいに使い分けることもできるらしい。 が、調べながらやった結果、その辺りをちゃんと把握せずに進めてしまい、今回は 2.0 だけでやるようにしてしまったので一旦その方向で進めている。

bot 用のアカウントを作る

bot 用に新しく Twitter アカウントを作る。 未ログインの状態で Twitter トップページから通常の手順で作れば問題ない。

色々挙動を確認したりするのに便利なので、運用に使うアカウントとは別にデバッグ用のアカウントを用意すると便利だ。一度 bot の運用を開始すると下手なテストができなくなる。

アカウントに電話番号を登録する

Twitter API を使うためには Twitter アカウントを開発者アカウントに登録する必要があるが、そのためには Twitter アカウントに電話番号を登録する必要がある。同じ電話番号を複数のアカウントに登録しても問題ないようなので、複数の bot を作る場合でも電話番号は 1 つで問題なさそうである。

一般的な手順通り、Twitter のログイン時の画面の左メニューから「もっと見る」「設定とプライバシー」「アカウント」「アカウント情報」でパスワードの確認が入るのでパスワードを入力し、「電話」「電話番号を追加」で行う。 番号を入力すると SMS で認証コードが送られてくるので入力すると登録できる。

なお、下記手順で開発者アカウントを有効にした後に試しにデバッグ用のアカウントに登録した電話番号の登録を消してみたが、今のところは問題なく API は使えている。もしかしたら何かのタイミングで使えなくなる可能性はあるかもしれない。

開発者アカウントを有効にする

Twitter アカウントを開発者アカウントに登録する。

開発者アカウントに登録したい Twitter アカウントにログインした状態で https://developer.twitter.com/ にアクセスし、右上の Sign up ボタンを押す。

名前、国、利用目的(選択式)、政府が使うものかどうか(?)、更新情報をメールで受け取るかを選んで下部の Next を押し、次の画面で Developer agreement & policy に同意するチェックボックスにチェックを入れて Submit を押す。

最後にメールアドレスの検証があるので、登録したメールアドレスに届いた検証メールを探して Confirm your email を押せば API の利用を開始できる。

開発者アカウントにはアクセスレベルがあり、一番簡単な(制限が強い) Essential access であればこれだけで使える。以前は申請理由について英作文をする必要があったようだが、今はここまでなら必要はない。

App を登録する

検証メールから Confirm your email を押すと、App の名前を入力するページに飛ばされる。 アプリ名はグローバルでユニークである必要があるが、後から変更できるので適当な名前でもよい。日本語でも大丈夫。 名前は OAuth の認可画面やツイート時の source 情報に使われる模様。

アプリ名を入力すると「API Key」「API Key Secret」「Bearer Token」が得られる。なくさないように保管する。

API を呼び出してみる

Bearer Token を使うと、ユーザーに紐付かない API を呼び出すことができる。

❯ curl -s -H "Authorization: bearer ${TWITTER_APP_BEARER_TOKEN}" 'https://api.twitter.com/2/users/by?usernames=thinca'
{"data":[{"id":"15676452","name":"thinca","username":"thinca"}]}

OAuth 2.0 を有効にする

API 経由で bot アカウントでツイート等を行うには、OAuth を使ってアカウントから App に認可を与える。 Developer Portal の左のメニューの Projects & Apps からプロジェクト内の Apps を選び、「User authentication settings」から「Set up」を押す。

OAuth 2.0 を有効にして、アプリのタイプを選ぶ。今回は bot を作るので「Automated App or bot」を選ぶ。

「Callback URI / Redirect URL」と「Website URL」を設定する。 これは一般ユーザー向けに認可を行いたい場合はきちんと Web アプリを用意する必要があるが、今回は bot アカウントだけでよいので手動でがんばればなんとかなる。 Callback URI には適当に http://localhost/ を設定(この URL に token 等が渡るので外部の URL にしてはいけない)。Website URL には http://example.com/ などを適当に設定する。

すると「Client ID」と「Client Secret」が手に入るのでこれをなくさないように保管する。

OAuth 2.0 で bot に権限を与える

認可用の URL を作る。

  • type = code 固定
  • client_id = 先ほど生成した Client ID
  • redirect_uri = 先ほど Callback URI / Redirect URL に登録したもの
  • scope = 許可を与えるスコープのスペース(%20)区切りのリスト
    • API ごとに、その API を利用するのに必要なスコープが決められている
  • code_challenge = ちゃんとやる場合はランダムに生成する必要があるが、今回は固定で challenge
  • code_challenge_method = ちゃんとやる場合は S256 とかを指定するが、今回は plain
https://twitter.com/i/oauth2/authorize?response_type=code&client_id=${CLIENT_ID}&redirect_uri=http://localhost/&scope=tweet.read%20users.read%20tweet.write&state=state&code_challenge=challenge&code_challenge_method=plain

bot のアカウントでログインした状態で作った URL にアクセスすると、認可のための画面になる。 「アプリにアクセスを許可」を押すと、Redirect URI に指定した URI にパラメータ付きでリダイレクトされる。 本来はここで Web アプリがリクエストを受け取り、サーバで処理を行う。 が、今回はともかく bot の認可だけできればいいので、リダイレクトされた先(localhost だと当然サーバが動いていなければ接続エラーになるが、URL さえわかればよいので問題はない)の URL の code= の部分に現れたコードを使って以下のように HTTP リクエストを手動で発行する。

${CLIENT_ID}${CLIENT_SECRET} にはそれぞれ Client ID と Client Secret を、${CODE} にはリダイレクトされた URL から得たコードを入れる。code_verifier にはちゃんとやる場合は計算して出した verifier を入れる必要があるが、今回は plain で値を固定しているのでそのまま先ほどの challenge を入れる。 なお、この ${CODE} の寿命はとても短いので、今回のように手動で行う場合は急いで行う必要がある。ちゃんと計測していないが数分で切れているように思う。

curl --location --request POST 'https://api.twitter.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--basic -u "${CLIENT_ID}:${CLIENT_SECRET}" \
--data-urlencode "code=${CODE}" \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode "client_id=${CLIENT_ID}" \
--data-urlencode 'redirect_uri=http://localhost/' \
--data-urlencode 'code_verifier=challenge'

ちなみにここで Basic 認証をしているが、OAuth 2.0 を有効にした際に選んだアプリのタイプ(今回は Automated App or bot を選んでいる)によっては不要になるそうだが、今回は試していない。Confidential Client に分類されるタイプの場合は必要で、Public Client に分類されるタイプは不要らしい。

すると以下のように Access Token が得られる。Access Token は寿命が短く、7200 秒(2 時間)で切れる。

{"token_type":"bearer","expires_in":7200,"access_token":"dEVDdWkxQnVZT184RlhZM0RQdHp6SjA3S2ExQmVQWG5KOTNvWkdmdGdueTh5OjE2NDE4MjEwOTYwNDM6MTowOmF0OjE","scope":"tweet.write users.read tweet.read"}

この Access Token を以下のように Authorization ヘッダに渡すことでユーザーとして API を利用できる。 以下は認証しているユーザー自身の情報を返す API を利用する例。

curl -H 'Authorization: bearer dEVDdWkxQnVZT184RlhZM0RQdHp6SjA3S2ExQmVQWG5KOTNvWkdmdGdueTh5OjE2NDE4MjEwOTYwNDM6MTowOmF0OjE' https://api.twitter.com/2/users/me

Refresh Token を使って永続的にアカウントにアクセスする

認可用の URL を作る際に、scope に offline.access を入れておくと、Access Token 発行の際に同時に Refresh Token も発行される。 Refresh Token を使うと Access Token を再発行できる。これを使うことで再度ユーザーに認可画面を表示することなくアクセスが可能になる。

https://twitter.com/i/oauth2/authorize?response_type=code&client_id=${CLIENT_ID}&redirect_uri=http://localhost/&scope=tweet.read%20users.read%20tweet.write%20offline.access&state=state&code_challenge=challenge&code_challenge_method=plain

上記のように offline.access を足した画面から発行した code を先ほどと同様に https://api.twitter.com/2/oauth2/token に渡すと、以下のように Refresh Token も一緒に返ってくる。

{"token_type":"bearer","expires_in":7200,"access_token":"UEo2TDBIemlBUkdsVlRJNHpzMWxZekFkd24tcGFETGFmVXJOWEtKdXJJVUU0OjE2NDE4MjE3NTA4ODA6MToxOmF0OjE","scope":"tweet.write users.read tweet.read offline.access","refresh_token":"b0F1bXNtd0Q4QlpDSGg5dWVEeG82UHNIY3lGcC1RbVRUMzRZcVQ0bFpkSVhrOjE2NDE4MjE3NTA4ODA6MToxOnJ0OjE"}

Refresh Token を以下のように使えば、新しい Access Token と Refresh Token が手に入る。

curl --location --request POST 'https://api.twitter.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--basic -u "${CLIENT_ID}:${CLIENT_SECRET}" \
--data-urlencode 'refresh_token=b0F1bXNtd0Q4QlpDSGg5dWVEeG82UHNIY3lGcC1RbVRUMzRZcVQ0bFpkSVhrOjE2NDE4MjE3NTA4ODA6MToxOnJ0OjE \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'client_id=${CLIENT_ID}'
{"token_type":"bearer","expires_in":7200,"access_token":"aTl5MVNPMlhHSUltck5lOWFlM2lyQ3dLbGhMWnBEbUxEdl9Zdi1yWGdPMUtCOjE2NDE4MjgyMDg0ODU6MTowOmF0OjE","scope":"tweet.write users.read tweet.read offline.access","refresh_token":"TlZvNXNWT0wyMzhialRZdWloM0w5OENGc3JnZzVDYlphLTM3OXItMzVaUXgwOjE2NDE4MjgyMDg0ODU6MToxOnJ0OjE"}

新しい Access Token と Refresh Token が発行されると、古い Access Token と Refresh Token はどちらも無効になる。 実際の運用時には Access Token とその有効期限と Refresh Token を保存しておき、有効期限が切れていたら Access Token を再発行して使うことになる。

Optional: アクセスレベルを上げる

開発者アカウントに登録した直後は Essential Access になっている。申請を行うことで、Elevated Access にすることができる。 検索やユーザータイムライン取得などのいくつかの API は月当たりに取得できるツイート数の上限が決まっている。Essential は 50 万だが、Elevated は 200 万になる。また、作れるアプリの数や Filtered Stream に設定できるルールの数などいくつかの点で違いがある。

ログインした状態で以下にアクセスし、「Apply for Elevated」を押す。

https://developer.twitter.com/en/portal/products/elevated

Twitter アカウント、メールアドレス、個人開発者かどうか、名前、国、コーディングスキル(承認の可否には影響しない)、更新情報をメールで受け取るかを選んで下部の「Next」を押す。

次の画面で、申請したい理由を英語で書く必要がある。最低 200 文字。用途に応じて追加でいくつか理由を書く必要がある。ここは必要であれば機械翻訳等を駆使しつつ素直に書くのがよさそう。 私の場合は具体的に作りたい bot が決まっていたので、そのために制約の緩和があると助かる、みたいなことを書いたら 1 時間かかるかどうかの速度であっという間に承認された。

具体的な API の利用について

別記事で書くかもしれないし書かないかもしれない。とりあえず現状だと、API v2 ではできないけど v1.1 ではできること、v1.1 ではできないけど v2 ではできること、どちらもある。今後の v2 のアップデートに期待したい。

qfhl.vim を作った

quickfix は便利ですが、それがバッファ内のどの位置を指しているのか、視覚的には分かりづらいです。

これを解決するための vim-hier というプラグインがあります。このプラグインは、quickfix の位置をハイライトで視覚的に表示してくれます。 実用には十分ではあるのですが、長らくメンテされておらず、またプラグインの構造やハイライトの仕組みが古いことが気になっていました。

一方、現在の Vim には text property という仕組みがあります。これを使えば、いい感じのものが作れそうな気がしました。

というわけで作ってみました。

github.com

(作ってみましたと軽く言ってますが、放置期間も含めると数年越しのリリースです…。)

qfhl.vim は、quickfix および location list の場所をバッファ上でハイライトします。

ハイライトには text property を使用しています。text property はバッファの一部に埋め込まれ、バッファ編集に合わせて位置が移動します。 これにより、ハイライト後にバッファを編集して行がずれたりした場合でも、ハイライトの位置も適切に移動します。

quickfix には行と桁と言う位置情報があり、それを元にハイライトを行っていますが、これだけだとどこまでハイライトをすればいいのかが判断できません。

これは不便なので、Vim 本体に PR を出しました。

github.com

quickfix が持つ位置情報に、オプショナルな終了位置の行と桁の情報を持たせられるようにする変更です。この PR は無事 v8.2.3019 で取り込まれました。

と言うわけで、もし quickfix が終了位置を持っていた場合は qfhl.vim も適切な範囲をハイライトします。 とは言うものの、quickfix を設定する多くの grep 系のコマンドやプラグインは、まだ終了位置を設定してくれないでしょう。終了位置がない場合は、仕方ないので行末までハイライトをします。

現時点で手軽に試すには :vimgrep コマンドが使えます。:vimgrep は組み込みコマンドだったので、上記の PR で終了位置を設定するように対応しています。

f:id:thinca:20210731135546p:plain
qfhl でハイライトを行った様子

最後に注意点ですが、Vim script の新しめの機能を使って書いているため、恐らく Neovim では動きません…。

以上、もし需要が合う方はお試しください。