0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Windows + NeovimでMarp CLIのwatchが途中から効かなくなる問題を解決した

0
Posted at

Windows + NeovimでMarp CLIのwatchが途中から効かなくなる問題を解決した

現象について

Windows 11 上で Marp CLI の watch モード(-w)を使い、Neovim で保存するたびに HTML を自動生成しようとしたところ、最初の1回は変換されるものの、その後は保存しても HTML が更新されなくなってしまいました。その解消法を記録しておきます。なお、環境は以下の通りです。

  • Windows 11 Pro 64bit
  • WezTerm
  • Nushell 0.116.0
  • Neovim
  • Node.js
  • Marp CLI 4.5.1(@marp-team/marp-core 4.4.0)

Marp CLI は npm のグローバル環境にインストールしています。

marp --version
@marp-team/marp-cli v4.5.1 (w/ @marp-team/marp-core v4.4.0)

調査の経緯を書いているので、解決方法だけ知りたい方はこちらまで飛んでください。

本来の動作

次のように watch モードを起動します。

marp -w test.md

起動時に変換が行われ、

[ INFO ] Converting 1 markdown...
[ INFO ] test.md => test.html
[ INFO ] [Watch mode] Start watching...

となります。あとは Neovim で :w するたびに

[ INFO ] test.md => test.html

と表示されて test.html が更新されるはずです。

ところが、私の環境では1回目の保存以降、test.html が更新されなくなりました。

原因の切り分け

PowerShell では動く

調査中、PowerShell から同じコマンドを実行すると、保存のたびに正常に更新されることが分かりました。WezTerm 上でも、

  • WezTerm + PowerShell → 正常
  • WezTerm + Nushell → 問題発生

という結果です。「Nushell が原因か?」と疑いました。

marp.cmd を疑う

marp の解決先が Nushell と PowerShell で違っていました。

Nushell:

which marp
C:\Users\ユーザー名\AppData\Roaming\npm\marp.cmd

PowerShell:

Get-Command marp | Format-List Source,Path,CommandType

こちらでは npm が生成した marp.ps1 が使われていました。そこで marp.cmd を経由しないよう、Node.js から直接起動してみました。

node C:\Users\ユーザー名\AppData\Roaming\npm\node_modules\@marp-team\marp-cli\marp-cli.js -w test.md

しかし、これでも症状は変わらず、.cmd だけが原因とは言えないことが分かりました。

Chokidar 単体で確認する

Marp CLI はファイル監視に Chokidar を使っています。Nushell 上で Node.js のファイル監視自体が動いていないのでは、と考え、Chokidar だけでテストしました。

npm install chokidar

watch-test.mjs

import chokidar from "chokidar";

console.log("watch start");

chokidar.watch("test.md").on("all", (event, path) => {
  console.log(new Date().toISOString(), event, path);
});
node watch-test.mjs

Neovim で test.md を保存すると、Nushell でも PowerShell でも change が検出されました。これで「Nushell 上で Node.js のファイル監視が動かない」という仮説は否定されました。

Marp CLI のデバッグログを見る

Marp CLI が実際にどんなイベントを受け取っているのかを確認するため、デバッグログを出します。Nushell では次のように環境変数を設定します。

$env.DEBUG = "marp-cli:*"
marp -w test.md

すると、Chokidar で監視を始めていることが確認できます。

marp-cli:watcher Start watching with chokidar:
[
  [
    'test.md',
    '...themes\\tech-network.css'
  ],
  { ignoreInitial: true }
]

1回目の保存は正常でした。

marp-cli:watcher Chokidar event: [change] test.md
[ INFO ] test.md => test.html

ところが、2回目の保存では、

marp-cli:watcher Chokidar event: [unlink] test.md

となり、その後は何度保存してもイベント自体が発生しなくなりました。「change ではなく unlink が来ている」。これが大きな手掛かりでした。

原因

問題が起きていたときの Neovim のオプションを確認すると、次の状態でした。

nobackup
writebackup
backupcopy=auto

nobackup なのでバックアップは無効だと思い込んでいたのですが、backup と writebackup は別のオプションです。writebackup が有効だと、保存時にバックアップを伴う書き込み処理が行われます。

今回の環境では、この保存処理によって、Chokidar から test.md が change ではなく unlink として観測されることがあり、その後は変更を検出しなくなっていました。流れとしては次のとおりです。

Neovim :w(1回目)
    ↓
Chokidar: change test.md
    ↓
Marp が HTML を再生成
    ↓
Neovim :w(2回目)
    ↓
Chokidar: unlink test.md
    ↓
以降、test.md の変更を検出しない

解決方法

Neovim の設定を次のように変更します。

init.lua

vim.opt.backup = false
vim.opt.writebackup = false
vim.opt.backupcopy = "yes"

Vimscript の場合はこちらです。

set nobackup
set nowritebackup
set backupcopy=yes

Marp CLI を再起動して、何度か :w してみます。

marp -w test.md
[ INFO ] [Watch mode] Start watching...

marp-cli:watcher Chokidar event: [change] test.md
[ INFO ] test.md => test.html

marp-cli:watcher Chokidar event: [change] test.md
[ INFO ] test.md => test.html

(以下、5回連続で change として検出)

5回連続ですべて change として検出され、HTML も毎回更新されました。Marp CLI 側に wrapper などを用意する必要はなく、marp -w test.md のままで動作しています。

なお、私の環境では backupcopy=yes だけでは直らず、nowritebackup まで設定して初めて安定しました。

補足

設定の確認方法

Neovim 側の現在値は次のコマンドで確認できます。

:set backup?
:set writebackup?
:set backupcopy?

同じ症状が出たときの調査方法

Marp CLI の watch が途中で止まるときは、デバッグログを見ると原因を絞り込みやすいです。

Nushell:

$env.DEBUG = "marp-cli:*"
marp -w test.md

PowerShell:

$env:DEBUG = "marp-cli:*"
marp -w test.md

正常なら保存のたびに [change] test.md が出ます。[unlink] test.md が出たあとに反応しなくなる場合は、エディタの保存方式を疑ってみてください。

調査が終わったら、Nushell の DEBUG は次のコマンドで解除できます。

hide-env DEBUG

今回の教訓

見た目は「Nushell だと Marp CLI の watch が動かない」という症状でしたが、実際はシェルでも監視ツールでもなく、エディタが保存時にファイルをどう書き換えるかが原因でした。ファイル監視系のツールが保存後に反応しなくなったら、エディタ側の保存方式も確認してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?