novel-writer 3.3.2

novel-writer 3.3.2を公開しました。今回はデバッグリリースです。原稿ツリーでファイルを追加したり、ファイル名を修正したりするときに不正な結果になっていたのを修正しています。

ドラッグ&ドロップを有効にしているときにファイルを追加すると、ファイルに連番が付与されなかったり、拡張子が付与されなかったりしました。また、ドラッグ&ドロップが無効のときにファイル名を変更すると、連番や拡張子が二重に付与されてしまったりすることがありました。しかも時々、結果が変わります。

「なんかおかしい」「なんだか結果が毎回違う」という気持ちの悪いバグですが、実はこの問題、近年のプログラムでは必ず注意しなければならない非同期関数を無視してしまっていたために発生したものです。

novel-writerはVS Codeの「設定」に状態を記録しています。ドラッグ&ドロップの有効・無効はNovel.DraftTree.renumberを書き換えて原稿ツリーに渡したり、処理の分岐に利用していたりします。vscode.workspace.getConfiguration("Novel.DraftTree")のように呼び出すこの設定は、処理が終わったときに初めて結果がわかる関数なのですが、それを忘れて、

  if (vscode.workspace.getConfiguration("Novel.DraftTree.renumber")) {
    // ドラッグ&ドロップ時の処理
    newFileName = oldFileName.replace(
    /^(\d+[-_\s]*)*(.+?)(\.(txt|md))?$/,
    `$1${newName}$3`
  }

のようにしていたのです。この関数、デフォルトはfalseを返すので、よほどのことがないとtrueにならない処理になってしまっていました。また悪いことに、処理を止めながら行うデバッグ中は、正しく設定を返すことが多かったりもするのです。

今回、3.3.2では、設定を読み込む部分を明示的な非同期関数にして、処理が終わるまで待ってから続きを実行するように修正しています。

// Configの読み込み
async function waitForConfiguration(): Promise<vscode.WorkspaceConfiguration> {
  // ここでは、たとえば設定が特定の値になっているかを監視する例です
  return new Promise((resolve) => {
      const configuration = vscode.workspace.getConfiguration("Novel.DraftTree");
      resolve(configuration);
  });
}


  const ifRenumber = (await waitForConfiguration()).get("renumber");
  if (ifRenumber) {
    newFileName = oldFileName.replace(
      /^(\d+[-_\s]*)*(.+?)(\.(txt|md))?$/,
      `$1${newName}$3`
    );
  }

非同期処理は現代のプログラミングの基本中の基本なのですが、見落としてしまいがちですね。

コメントを残す