『Hello, World!』で吉川英治文学新人賞を受賞したSF作家 

藤井:お時間いただきまして、ありがとうございます。本日、「Visual Studio Codeで小説を書く」というセッションを持たせていただく、SF作家の藤井太洋です。それでは、プレゼンテーションを進めます。

まず簡単な自己紹介から。私は、2012年に『Gene Mapper』というサイバーパンク小説をセルフパブリッシングしてデビューしました。その後、『オービタル・クラウド』で日本SF大賞を取りました。

そのあと、SwiftとかJavaScriptとか、プログラミング用語がそのまま出てくる『Hello, World!』を書いて、吉川英治文学新人賞を受賞しています。テック系の作家として活躍している次第です。

デビューから今まで使っていた執筆エディタも一時的なソリューションだと考えていた

デビューしてから2021年4月まで、私は「Scrivener」という執筆エディタを使って小説を書いていました。これは「Word」とか「一太郎」のような、1つのファイルに書いていくスタイルのツールではなくて、小さなRTFファイルをたくさん積み上げていって、最終的に1つのテキストにコンパイルして小説の原稿を作るソフトウェアで、大変便利ではあります。

私は、小説のファイルを1シーンごとに、だいたい2、3,000文字ぐらいの単位で区切って書くことが多いので、この仕組みは大変都合がよかったです。

自分で縦書きの確認もしたかったので、このScrivenerから出力されるテキストファイルをAdobeの組版ツールの「InDesign」でレイアウトタグを付けて、テキストで出力して、これをInDesignに取り込んで縦書きで組版して、推敲したり、編集者に読んでもらったりしていました。

ただ、これは正直怖かったですね。やはり、InDesignがAdobe製品でプロプライエイトなので、自分自身でバージョンのコントロールがまるでできない。ソフトウェアのバージョンが上がると、今まで動いた機能が動かなくなることもありました。

また、iPadでは動きませんでした。これはけっこう致命的で、モバイルで持ち出せないと、出張している時や海外で講演をしている時には、原稿の縦組みができないわけです。ライセンスもけっこう安くはないですね。

仕事に使うツールなので後方互換性はよかったのですが、いつまでも使えるソリューションではないなと考えていました。

もう1つ、「Scrivener」というソフトウェアも悪くはなかったのですが、バージョン管理がスナップショットを取っていくだけだったんですね。なので、差分を見ることはできなくもないのですが、「Git」でのバージョン管理に慣れていた私にとっては、ブランチが作れなかったり、「GitHub」の管理に任せられなかったりするのは、ちょっとつらかった部分がありました。

物書きとして必要となる機能

そこで、開発系のテキストエディタに引っ越そうと考えたのですが、Macで動くという要件がありました。次に、UTF-8のテキストファイルを開いて編集して、保存できる必要がありました。

これが日本語のテキストエディタはけっこう難しくて、内部的にShift JISでしか動いていなかったり、Unicodeには対応していても、UTF-16でしか保存できなかったりするエディタがけっこう多かったんですね。

私の作品は小説なので、漢字の中でも正字体を保存できる必要もありましたし、また、ベトナム語とか中国語とか、キリル文字とか、そういうものも直接ファイルの中に埋め込みたかったわけです。

そうなるとUTF-8で取り込んで、中がUnicodeで動くソフトでないとなかなか実用に耐えられないのですが、なかなかそういうエディタも開発系を外れると少ないですね。

ほかにも、複数のファイルが一覧できる必要がありました。開発系のエディタでは当然ですが、そうではない物書き用のエディタにはなかなかない機能でした。

あとは、正規表現で複数のファイルを検索置換できること、Gitに対応していること。GitHubインテグレーションがあるとすごくうれしいなと思っていました。あと拡張が書けること。自分しか使わないツールになる可能性があるので、こういう拡張があると大変うれしかったわけです。

候補に挙がった「Visual Studio Code」もそのままの使用は難しかった

そこで候補に挙がってきたのが「VSCode(Visual Studio Code)」でした。VSCodeは、たぶん今日聞いているみなさんも、日本語を書いたことがあると思うのですが、そのまま使おうとするとけっこう厳しいんですね。

まず、私にとって厳しかったのは日本語のテキストが形態素解析されていなかったことです。MacやWindowsの標準テキストフィールドは、テキストが形態素解析されていて、Macだとオプション、矢印キー。

あと「Emacs」のキーバインドだと、Ctrl、Alt、B、F、とかで、単語ごとにキャレットを飛ばせるのですが、VSCodeは開発用のエディタなので、ワードの単位が、プログラミング言語のワードの単位でしか分割されていないわけですね。なので、普通に使うと、日本語は1行が1単語になってしまう。これはけっこう厳しかったですね。

また、ちょっと書いているとすぐに自動インデントが発生してしまったり、標準が折り返しではないので、そういうところもけっこう調整をしなければいけなかったり。あと、標準では文字数を表示する機能がなかったので、行数もわかりにくかった。

ほかにも、補完が強過ぎた。かぎ括弧を1個入れると、ファイルにあるすべての会話の中から拾ってきて、会話の補完をしようとするわけですね。こういうところがけっこう厳しかったので、これを一つひとつ直していけば使えるかなと、Visual Studio Codeに手をつけたのが2021年4月でした。

単語区切り、テキストファイルの結合、textlintを追加・設定した

ソフトウェアの機能で簡単に調整できるのは折り返しの設定ですね。Word WrapとColumnを設定して文字数を指定すると、そこそこ見た目もいけます。

次にやったのは単語区切りの追加です。形態素解析をする言語サーバーを作ればいいというのは調べてわかったのですが、とても作れないなと思ったので、まずは簡単に、句読点、かぎ括弧、あと「を」と「が」あたりを単語区切りに指定しました。これでかなり使いやすくなりました。

また、ばらけているテキストファイルを結合するために「Gulp」を使いました。Web開発をやっていたことがあるので、Gulpを使えばいいかなと思って書いてみたらけっこううまくいったという感じです。

実際、友人がGulpを使ってWeb開発しているのを見せてくれたので、それを見よう見まねでやってみたらすぐにできました。あとはtextlintを設定して、誤字脱字や日本語のスタイルを調整するようにして使っていました。

ただ、これでも足りないところがあったのでエクステンションを足して使っていました。4月の段階で使っていたのは、「縦書きプレビュー」ですね。「CharacterCount」「zenkaku」「vscode-textlint」、あとはEmacsのキーバインドが必要でした。あとは「Git Graph」など、このあたりを使って書いていました。

実際、こんな感じで小説を書いていたわけです。小説を書いている画面ですよと言うと、けっこう驚いちゃうかもしれませんが、実際こんな感じで書いていました。

小回りが利かないところは、自分でエクステンションを作成

ここまで、だいたい2、3日ぐらいで環境を組み上げて書いていたのですが、やはり小回りが利かないところがあるなと思いましたので、自分でエクステンションを書くことにしました。

それが今画面に出ているVisual Studio Codeの「novel-writer」です。先ほどの画面とかなり似ているんですが、いろいろと調整をしています。

まずはこれですね。言語モードでかぎ括弧の中のハイライトを実装しました。会話とそうでない部分。また、数字とそうでない部分。あとは、数字と数詞。私は青空文庫の注記法を使うので、青空文庫の注記がどこにあるかというものを作っています。

あともう1つは、縦書きです。原稿用紙のように1行の文字数を指定して、グリッドを引いたモードを作りました。青空文庫の注記法に対応しているので、字下げも作れます。

この縦書きのプレビューモードですが、これはhttpdのサーバーを立ち上げているので、VSCodeの画面の中だけではなくて、VSCodeの画面の外から、つまりタブレットやほかのブラウザから開くこともできます。

あとは、文字数ですね。テキストファイルを分割しているので、このフォルダーの中に入ってるテキストファイルのすべての文字数が必要でした。なので自分でテキストファイルを足し合わせるコードを書いています。このエクステンションで読めます。

あともう1つ、編集距離の表示も付けました。編集距離というのは、あるテキストファイルとあるテキストファイルの間にどれだけの文字数の変更があったかという数です。

小説を書いていると改稿という作業があります。例えば、連載で使った原稿を単行本用に書き直す作業をやっていると、ほとんど文字数が変わらないわけですよ。下手すると減るんですね。

文字数が変わらなかったり減ったりすると、モチベーションがだだ下がりになるわけです。「1日やったはずなのに、なぜ200文字減った?」みたいな感じになるわけです。

これを解消というか、自分を上げるために付けたのがこの編集距離です。この編集距離で見ると、「ああ、きちんと原稿用紙20枚分書き換えたな」ということがすぐにわかるわけですね。

または、原稿を増やさなければいけないのに、ずっと中をいじっていたりというような、無駄な作業もわかります。

「Visual Studio Code」の実際の挙動

こうやって使っているわけですが、実際に動いているところをお見せしたいと思います。アプリに移ります。

これがサンプルのプロジェクトですね。小説を書いていると言っても、実際の原稿が入っているのはこのDraftのフォルダーの中で、このDraftのフォルダーの中に入っていると、普通にエディタを立ち上げることができます。縦書きを起動すると、このように文字を縦書きで見ることができます。

カーソルを入れている場所にスクロールできますし、ほぼリアルタイムで入力できます。20万文字とかになってくると、どんどんレスポンスが悪くなってくるのですが、文字数が増えてくると、更新までの間隔を空けて、0.2秒置きとかにテキストを送信するようにしているので、タイピングをしている時のテキストエディタのレスポンスには影響しないように作っています。いろいろと工夫はしております。

これが編集距離ですね。編集距離は、Gitの昨日の最後のコミットから何文字変わったかという表示にしています。なので今、13文字分編集距離が広がりました。また0に戻ります。思い切り消すと、1,900……1,195文字離れたみたいな、こんな感じで編集した状態を見られるので、私はがんばったんだということがわかるわけですね。すごく上がります。

ほかにもtextlintがあって、書きながらその場で文字の直しができるので、手放せないツールになりつつあります。

このnovel-writerは、MITライセンスでGitHubに上げているので、おもしろいなと思ったら使ってみたり、いろいろとPRを投げてもらえると助かります。

中身はTypeScriptですが、中を見ていただくとおわかりのとおり、いろいろな世代のいろいろな書き方のTypeScriptが混在しています。それは私自身の本職がエンジニアリングではなくて、自分の設計で書いていない部分が多いためです。

参考にしたソフトウェアやコードに引きずられるかたちで、このファイルはTypeScriptのいつ頃のやつとか、このファイルはとてもオブジェクト指向的に書いてあるとか、このファイルは元にしたものがとてもエレガント過ぎたのでよくわからないままに丸ごと使っています、みたいなものがあったりします。

なので、見たり、リファクタリングするのもなかなか楽しかろうとは思います。私自身も、けっこうリファクタリングを楽しんでおりますし、どんどんPRを投げてもらえると助かります。

長々と話してしまいましたが、楽しんでいただけたなら幸いです。ありがとうございました。「Visual Studio Code」で小説を書くでした。それではまた。