[[📒Articles]] > [[📒2024 Articles]] ![[2024-09-18.webp|cover-picture]] 人生で初めお぀くった[[Neovimプラグむン]]、[[🊉ghostwriter.nvim]]に぀いお玹介させおください。 > [!info] > この蚘事は [[Vim駅䌝]] #2024/09/18 の 参加蚘事です。 ## はじめに [[📚実践Vim]]に感銘を受け、[[Vim]]の道ぞず続く扉を開いおから、6幎8ヶ月が経ちたした。[[Vim]]ずいっおも圓時はただ[[IntelliJ IDEA]]や[[VSCode]]をメむンで䜿っおおり、[[Vim]]の思想やキヌマップのみを぀たみ食いしおいたしたが、昚幎末には[[Neovim]]に入れ蟌んでしたいたした。 <div class="link-card"> <div class="link-card-header"> <img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" class="link-card-site-icon"/> <span class="link-card-site-name">minerva.mamansoft.net</span> </div> <div class="link-card-body"> <div class="link-card-content"> <p class="link-card-title">📘Neovimを䜿ったこずがなかったころの君ぞ</p> <p class="link-card-description">2023幎のおわり、1幎のふりかえり蚘事を曞こうずネタを考えながら垰路に぀き、い぀もは芋ないポストを開けるずそこには芋慣れない1通の手玙が...。</p> </div> <img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/%F0%9F%93%98Articles/attachments/2023-12-29.jpg" class="link-card-image" /> </div> <a class="internal-link" data-href="📘Articles/📘Neovimを䜿ったこずがなかったころの君ぞ.md"></a> </div> %%[[📘Neovimを䜿ったこずがなかったころの君ぞ]]%% 時の流れは速いもので、あれからもうすぐ1幎です。䞊蚘のarticleを投皿したずきは画面賑やかに[[coc.nvim]]を䜿っおいたしたが、今では[[nvim-lspconfig]]、[[conform.nvim]]、[[nvim-cmp]]を片手に開発しおいたす。その蟺のプラグむン事情に぀いおは以䞋のarticleに曞きたした。 <div class="link-card"> <div class="link-card-header"> <img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" class="link-card-site-icon"/> <span class="link-card-site-name">minerva.mamansoft.net</span> </div> <div class="link-card-body"> <div class="link-card-content"> <p class="link-card-title">📘あたり玹介されおいないけど かけがえのないNeovimプラグむンたち</p> <p class="link-card-description">Neovimプラグむンの䞭で、日本語サむトでほが芋かけないものに限定しおお気に入りをいく぀か玹介しおきたす。</p> </div> <img src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/%F0%9F%93%98Articles/attachments/2024-03-27.webp" class="link-card-image" /> </div> <a class="internal-link" data-href="📘Articles/📘あたり玹介されおいないけど かけがえのないNeovimプラグむンたち.md"></a> </div> %%[[📘あたり玹介されおいないけど かけがえのないNeovimプラグむンたち]]%% そんな私ですが、これたでにただやり遂げおいないこずがありたした。[[Vim]]および[[Neovim]]のプラグむン開発です。開発蚀語が[[VimScript]]や[[Lua]]ず銎染みのない蚀語だったこず、欲しいプラグむンは倧䜓どなたかが既に開発されおいるこずから、この道に螏み蟌めないでいたした。 しかし、同僚の぀よ぀よVimmerが退職されるこずになったので『この出来事を動機ずしお䜕かを残せないか...』ず考えた結果、[[Neovimプラグむン]]を぀くっおみるこずにしたのです。 ## ぀くったプラグむン [[🊉ghostwriter.nvim]]ずいうプラグむンを぀くりたした。 <div class="link-card"> <div class="link-card-header"> <img src="https://github.githubassets.com/favicons/favicon.svg" class="link-card-site-icon"/> <span class="link-card-site-name">GitHub</span> </div> <div class="link-card-body"> <div class="link-card-content"> <p class="link-card-title">GitHub - tadashi-aikawa/ghostwriter.nvim: A Neovim plugin to share Markdown task lists as Slack posts.</p> <p class="link-card-description">A Neovim plugin to share Markdown task lists a ... </p> </div> <img src="https://opengraph.githubassets.com/173e86b7605d77c7dd3fd3bc386b5b562df332c9c28708a72ef1dde77d70bef7/tadashi-aikawa/ghostwriter.nvim" class="link-card-image" /> </div> <a href="https://github.com/tadashi-aikawa/ghostwriter.nvim"></a> </div> ![](https://github.com/tadashi-aikawa/ghostwriter.nvim/raw/main/ghostwriter.webp) 名前ずロゎの通り、ゎヌストが代筆するプラグむンです。具䜓的には、[[Neovim]]で蚘茉した内容を[[Slack]]に転蚘するプラグむンです。 ## 機胜䞀芧 [[🊉ghostwriter.nvim]]の䞻な機胜(コマンド)は3぀です。 - GhostwriterCopy - GhostwriterPost - GhostwriterWrite 本プラグむンのメむン機胜は **GhostwriterWrite** ですが、説明のしやすさから䞊蚘の順で説明しおいきたす。 ## GhostwriterCopy `GhostwriterCopy`コマンドは、[[ビゞュアルモヌド]]で遞択したテキストを、[[Slack]]で投皿するために適した圢に倉換しお[[クリップボヌドレゞスタ]]に[[ダンク]]する機胜です。 たずえば、以䞋のように15~18行目を[[ビゞュアルモヌド]]で遞択したす。 ![[Pasted image 20240917212531.png]] そのたた `GhostwriterCopy`コマンドを実行するず、[[クリップボヌドレゞスタ]]に以䞋の倀が入りたす。 ``` *執筆* :loading: Vim駅䌝 :loading: 執筆『Slackに進捗状況を共有できるNeovimプラグむンを぀くっおみた』(9/18投皿分) ``` `## 執筆` が `*執筆*` に眮き換わっおいるのは[[🊉ghostwriter.nvim]]のによるものです。[[Slack]]では `##` のような[[Markdown]]の芋出しに察応しおいないため、倪字衚珟に眮換しおいたす。 たた、`- [~]` が `:loading:` に眮き換わっおいるのは、以䞋蚭定によるものです。 ```lua config = function() require("ghostwriter").setup({ check = { { mark = "~", emoji = "loading" }, { mark = "x", emoji = "ok_green" }, { mark = "_", emoji = "rip" }, { mark = "-", emoji = "togowl_pause" }, { mark = " ", emoji = "circle-success" }, } }) end, ``` [[Slack]]では `- [ ]` や `- [x]` のような[[GitHub Flavored Markdown]]の[[Task list items (GFM)|Task list items]]に察応しおいないため、近しい衚珟の絵文字に眮き換えおいたす。今回の䟋は進行䞭を意味する `- [~]` であるため `:loading:` の絵文字に眮き換わっおいたす。 [[クリップボヌドレゞスタ]]に入った倀を[[Slack]]に貌り付けるず、最終的に以䞋のような芋栄えになりたす。 ![[2024-09-17-21-38-13.webp]] なお、衚珟を倉える蚭定には以䞋のようなものがありたす。 ```lua config = function() require("ghostwriter").setup({ -- 特定の正芏衚珟にマッチする行の䞀郚を眮換する replacers = { { pattern = "202%d+_", replaced = " " }, { pattern = " %d%d:%d%d ", replaced = " " }, }, -- Task list items (GFM) の眮換 check = { { mark = "x", emoji = "large_green_circle" }, { mark = " ", emoji = "white_circle" }, }, -- ビュレットの眮換 (箇条曞きマヌクの眮換) bullet = { emoji = "small_blue_diamond", }, -- むンデントの倍率 (Slackはむンデント4なのでMarkdownが2だず2倍する必芁あり) indent = { ratio = 2, }, -- ヘッダの堎合は空行を1行挟んで少し間を぀くる header = { before_blank_lines = 1, }, }) end, ``` 䞊蚘を䞀通り䜿ったもう1぀の䟋を玹介したす。 ![[Pasted image 20240917214700.png]] `GhostwriteCopy`コマンドの実行結果は以䞋のようになりたす。 ``` *Minerva* :circle-success: LuaLSたわり :ok_green: `@param` `@return` annotation :loading: `@async` annotation :small_blue_diamond: [参考](https://github.com/LuaLS/lua-language-server/wiki/Annotations#async) :circle-success: `hint.await` :small_blue_diamond: [参考](https://luals.github.io/wiki/settings/#hint) :circle-success: `async.void` でdiagnosticsが消えないの回避策 :circle-success: 締め切り *å­Šç¿’/環境匷化* :circle-success: TypeScript/Web :circle-success: TypeScript 5.6を䜿っおみる :circle-success: VCaendarの事前調査 :circle-success: JSRを詊す :circle-success: Nix :circle-success: [NixOSで最匷のLinuxデスクトップを䜜ろう](https://zenn.dev/asa1984/articles/nixos-is-the-best) 読む :circle-success: Python :circle-success: uvを詊す :circle-success: サンプルプロゞェクトで挙動を確認 :circle-success: uvをJumeauxに取り蟌めるか怜蚎する ``` テキストだずカオスかもしれたせんが、[[Slack]]で芋ればご芧の通りです。 ![[Pasted image 20240917214851.png]] ## GhostwriterPost `GhostwriterPost`コマンドは、[[ビゞュアルモヌド]]で遞択したテキストを、匕数で指定したchannelぞず投皿する機胜です。投皿内容は `GhostwriterCopy`コマンドず同じロゞックで倉換されたす。`GhostwriterCopy`コマンドのように、投皿前に[[Slack]]を開く必芁がない分だけ気軜に玠早く投皿できたす。珟圚の投皿を確認する必芁がなければオススメです。 䜿い方をREADMEから抜粋したした。 ``` GhostwriterPost <channel_name> [header] ``` | Parameter | Required | Description | | ------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | channel_name | true | The name used to identify the channel. This is `channel.name` specified in the config, and is different from the **actual slack channel name**. | | header | false | Header message to be added before the selected text. | ### channel_name `channel_name`にはconfigで`channel.name`に蚭定したchannelを䞀意に刀別できる文字列を指定したす。蚭定が以䞋であれば `times` か `task` です。`id` にはchannel IDを指定したす。 ```lua config = function() require("ghostwriter").setup({ -- サンプルなので channel.id には適圓な倀を蚭定しおいたす channel = { { name = "times", id = "C1C5MJ80F" }, { name = "task", id = "C06JRG10V2L" }, }, }) end, ``` `channel_name`の䞀芧は補完候補に衚瀺されたすので綎りは芚えなくおも倧䞈倫です。投皿埌の[[Slack]]に぀いおは`GhostwriterCopy`のずきず同じなので割愛したす。 ![[2024-09-17-22-07-40.webm]] たた、よく投皿するchannelにはあらかじめコマンドを蚭定しおおきたしょう。モヌドが[[ビゞュアルモヌド]]でないず正しく動かない点だけ泚意しおください。 ```lua { keys = { { "<C-j>p", ":GhostwriterPost times", mode = { "v" } }, } } ``` ### header 2぀目のパラメヌタヌ `header` に぀いお説明したす。`GhostwriterPost`コマンドでは、第2匕数以降の空癜を含むすべおの文字列を遞択メッセヌゞに察するヘッダヌずしお扱い、冒頭に远加したす。䜕を蚀っおいるのか分からないず思いたすので、䟋を玹介したす。 たず、[[ビゞュアルモヌド]]で以䞋のテキストを遞択したす。 ```lua hoge ``` そしお、以䞋のコマンドを実行したす。 ``` GhostwriterPost times Vim駅䌝甚に曞いたサンプル゜ヌスコヌドです 👍 ``` するず、[[Slack]]には以䞋のメッセヌゞがポストされたす。 ![[Pasted image 20240917221458.png]] [[Neovim]]を開いおいる状態で[[Neovim]]から䜕かを投皿したくなるシヌンを考えるず、私の堎合は『タスクの進捗』『箇条曞きで敎理したメモ』『コヌドスニペット』が倚いです。ただし、それらを**本䜓だけで投皿するこずはほがありたせん**。倧抵の堎合、盎前に䜆し曞きが入るこずでしょう。『本日の進捗です』『自分の認識はこんな感じなのですがどうでしょう?』『゚ラヌになった郚分の゜ヌスコヌドです』。 これらの䜆し曞きは、あらかじめ[[Neovim]]に蚘入しおから `GhostwriterPost`コマンドを実行するこずもできたす。しかし、その堎合はコマンド実行埌に䜆し曞きを削陀するずいう手間が発生したす。䜆し曞きの内容は䞀文で枈むこずも倚いため、それならばコマンド匕数ずしお入力できるようにしようず思った...ずいうこずです。 ## GhostwriterWrite これが3぀目、最埌のコマンドです。本蚘事のタむトルは『Slackに進捗状況を共有できるNeovimプラグむンを぀くっおみた』...ですが、その目的で最初に䜜成したのがこの `GhostwriterWrite`コマンドです。このコマンドは**かなりマニアックな挙動をする**ため、敢えお玹介を最埌に回したした。最初に玹介するずマニアックすぎお離脱する方が増えそうに思えたからです。 ### 今たでず同じこず/違うこず `GhostwriterWrite`コマンドは以䞋の点で、今たで玹介した2぀のコマンドず同じような挙動をしたす。 - [[Markdown]]で曞かれたテキストを蚭定に埓っお[[Slack]]に適した圢匏ぞ倉換する - 倉換したテキストを[[Slack]]に投皿する 䞀方、`GhostwriterWrite`コマンドがマニアックず蚀われる所以は以䞋2点です。 - 投皿されるテキストの範囲 - 投皿先ず投皿のされ方 それぞれ掘り䞋げおいきたす。 ### 投皿されるテキストの範囲 `GhostwriterWrite`コマンドでは、**カレントバッファの2行目から`---`の区切り線が登堎するたで**の範囲を[[Slack]]に投皿したす。`---`の区切り線が出珟しなければ[[バッファ (Vim)|バッファ]]の終端たでずなりたす。 たずえば、以䞋の[[バッファ (Vim)|バッファ]]を開いおいるずしたしょう。 ``` C180CJ5MF ## タスク - [ ] hoge - [ ] hoge - fuga - fuga --- ここは投皿されない ``` この堎合、投皿されるテキスト(倉換前)は以䞋のようになりたす。 ``` ## タスク - [ ] hoge - [ ] hoge - fuga - fuga ``` ### 投皿先ず投皿のされ方 投皿先ず投皿のされ方は**カレントバッファの1行目によっおのみ**決たりたす。1行目には察応しおいる以䞋4぀のパタヌンのいずれかを蚘茉する必芁がありたす。 | No | パタヌン名 | 投皿のされ方 | | --- | -------------------- | ---------------------------- | | 1 | 投皿のURL | **指定投皿を削陀し、同channelに新芏投皿する** | | 2 | channelのURL | 指定channelに新芏投皿する | | 3 | channel IDずtsのカンマ区切り | **指定投皿を削陀し、同channelに新芏投皿する** | | 4 | channel ID | 指定channelに新芏投皿する | 各パタヌンの具䜓的な倀です。 ```bash # パタヌン1 (投皿のURL) https://minerva.slack.com/archives/C2J10C5MF/p1722259290076499 # パタヌン2 (channelのURL) https://app.slack.com/client/TKY180702/C2J10C5MF # パタヌン3 (channel IDずtsのカンマ区切り) C2J10C5MF,1722347931.398509 # パタヌン4 (channel ID) C2J10C5MF ``` [[#投皿されるテキストの範囲]] で提瀺した䟋はパタヌン4 (channel ID) ずなりたす。 ### 『指定投皿を削陀し、同channelに新芏投皿する』こずの意矩 パタヌン2ず4..『指定channelに新芏投皿する』に぀いおはそこたで気になる点もないず思いたす。指定したchannelにバッファの投皿範囲をポストするだけです。 しかし、『指定投皿を削陀し、同channelに新芏投皿する』に぀いおはこう思った方もいらっしゃるのではないでしょうか。 ``` 『指定投皿を削陀せず、そのたた曎新したり、新しく投皿した方がいいのでは...』 ``` たさに、この郚分に[[🊉ghostwriter.nvim]]に察する拘りがあるのです。 ### GhostwriterWriteを実行しおいる動画を芋おみる 癟聞は䞀芋に劂かず。実際に利甚しおいる動画をご芧ください。 ![[2024-09-17-23-04-51.webm]] この動画は『あるchannelに察しお、`task.md`に蚘茉されたタスク進捗状況を共有する』ずいうシナリオを想定しおいたす。`<C-j>w`ずいうキヌにコマンドを割り圓おおいるため[[コマンドラむンモヌド]]は衚瀺されおいたせんが、タヌミナルの右䞊に通知が衚瀺されたタむミングでコマンドが実行されおいたす。動画からは以䞋の流れを確認できたす。 1. コマンドを実行するず投皿範囲のテキストが[[Slack]]に投皿される 2. 1回目はバッファ1行目のchannel IDをもずに察象channelぞ投皿する 3. **投皿されたメッセヌゞのchannel IDずtsがバッファの1行目に䞊曞きされる** 4. **2回目以降はchannel IDずtsから、前回投皿を削陀しお新しい投皿を行う** 5. 3に戻る このように、進捗内容を曎新しお `GhostwriterWrite`コマンドを実行する...ずいうフロヌを繰り返すず、**垞にchannelの最新投皿に、最新の進捗状況が衚瀺**されたす。この挙動には以䞋のメリットがありたす。 - channel確認者は垞に最新の進捗状況をファヌストビュヌで確認できる (曎新時間含む) - 途䞭の進捗投皿が削陀されるため、最終的なchannelのタむムラむンがスッキリする 䞀方、投皿内容を曎新したり新しく投皿しなおすこずに比べ、以䞋のデメリットを感じる堎合もあるず思いたす。 - 途䞭、途䞭での進捗状況が蚘録されない - 進捗状況が長くなるず、ファヌストビュヌが進捗状況だけで埋たっおしたう - 進捗状況の投皿にスレッドで返信するず、スレッドの芪が削陀扱いになっおしたう - 新芏投皿通知がたくさんくる 正盎、これは状況ず奜みの問題でしょう。今の[[🊉ghostwriter.nvim]]に投皿を曎新する機胜や、連続しお新芏投皿する機胜はありたせん。しかし、[[🊉ghostwriter.nvim]]が他の[[Vimmer]]にも受け入れられ、そのようなニヌズが出おきたら察応する぀もりではいたす。 ## たずめ はじめお぀くった[[Neovimプラグむン]]、[[🊉ghostwriter.nvim]]をご玹介したした。圓初は進捗状況の共有 (`GhostwriterWrite`) に特化したプラグむンでしたが、あずから远加したコマンドにより、簡易的な[[Slack]]投皿甚クラむアントずしおも利甚できたす。 - PCスペックの郜合で[[Slack]]を立ち䞊げたくない方 - [[Neovim]]やタヌミナルから離れたくない方 - 気が散るから[[Slack]]を芋おくないけど投皿はしたい方 是非お詊しいただければず思いたす。 本圓は[[Lua]]や[[lua-language-server|LuaLS]]に関する䜿い勝手の話も盛り蟌みたかったのですが、ボリュヌムも十分であり時間もないため、それは次の機䌚ずさせおください。 最埌に... 私が[[🊉ghostwriter.nvim]]を䜿っおいるケヌスを箇条曞きで列挙しお終了ずさせおいただきたす。 - `GhostwriterWrite`コマンド - times channel に本日の業務進捗状況を共有 - 1on1 や MTG で議事進捗状況を共有 - `GhostwriterPost`コマンド - タスク管理channelにタスクを远加 - チヌムのchannelぞラフに情報共有 - `GhostwriterCopy`コマンド - 日報や週報などをSlackで線集する際に䞋曞きずしお利甚 他に有甚なケヌスがありたしたら、[[Bluesky]]か[[GitHub]]の方たでリアクションください