ずんだもんがvimでパワポをするのだ🫛

# ずんだもんがvimでパワポをするのだ🫛
vimでパワポするようなプラグインを作りました。

https://github.com/uesseu/vimslide

ジョークソフトに見えるだろう？はい、普通にジョークソフトです。でも本気を出せばパワポ以上に色々できるのです。すでにこれでLT会で複数回発表しています。結構リッチなのが出来ます。
ここに例もあります。

https://github.com/uesseu/vimslide/blob/example/README.md


:::note alert
ちなみに、本記事の執筆者はエンジニアではないのでコードの品質についてはよろしく。「vimへの愛」だけならば強くあるつもりだけど、所詮素人だよ。
:::



# 動機
パワポが辛くてMarkdownスライドは素敵、そう思っていた時期が俺にもありました。しかし、どれも一長一短だなぁと思っていたのです。

- GUIで最初から最後までゴリゴリやる
    - フォントが揃わない、パワポが勝手に変えちゃう!
    - 画像の位置あわせがミリ単位のマウス捌きに依存!
- Markdownでサクッとやる
    - 結果の画面とソースが違う(previewで軽減可)
    - 位置合せがきつい
    - いつのまにかHTML/JSやってる、楽をしたかったのに…

どっちもきついと思ったので、中毒者として、いつものアレをキめたのです。

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139153/c821daa7-bd2d-bde7-77d0-d8848b902785.png width=40%>

# 使い方

僕のプラグインは三つの記法を持っています。その時の本気度によって使い分けます。

- スクリプト無し記法
- スクリプト有り記法
- vimスクリプト無矛盾記法

順に説明します。
ちなみに、現時点ではファイルの先頭に1行の空行がないと動きません。

## スクリプト無し

スライドのセパレータは「"""」です。もちろん、設定次第で「""""」にも「""""""""""」にもできます。こんな感じ。

```
"""

     スライドの内容

文章文章文章文章文章文章文章
文章文章文章文章文章文章文章
文章文章文章文章文章文章文章

"""

     スライドの内容2

文章文章文章文章文章文章文章
文章文章文章文章文章文章文章
文章文章文章文章文章文章文章

```

ただ、これだと画像を表示できません。

## スクリプト有り記法
```
""" Slide1
call slide#image('image.png', [0, 0, 0, 0])
Slide1

     スライドの内容

文章文章文章文章文章文章文章
文章文章文章文章文章文章文章
文章文章文章文章文章文章文章

```

こんなヒアドキュメント風の書き方でvim scriptを書いていきます。画像はslide#image関数で表示します。第二引数で場所とか大きさを指定します。詳細は後述。

## vim script無矛盾記法
上記の記法はvim scriptとしては文法上誤りです。そこで、記法自体をvim scriptとして文法的に正しくできるように書けます。こんな感じ。

```vim
""" @Slide1
call slide#image('image.png', [0, 0, 0, 0])
let Slide1 =<< EOF

     スライドの内容

文章文章文章文章文章文章文章
文章文章文章文章文章文章文章
文章文章文章文章文章文章文章

EOF

""" @Slide2
let Slide2 =<< EOF

     スライドの内容

文章文章文章文章文章文章文章
文章文章文章文章文章文章文章
文章文章文章文章文章文章文章

EOF
```

つまり、ヒアドキュメント風ではなくてヒアドキュメントとして書くのです。この場合は@を頭につけます。ちなみに、この場合は「"""」までのvim scriptを実行するので、EOFの後も実行されます。

当然、vimにはsourceコマンドがありますから、スクリプトを外部ファイルに丸投げすることもできます。
# 操作
slide#start関数を使います。

```vim
call slide#start(3, '<down>', '<up'>)
```
これで「"""」で区切ったスライドを上下キーで移動できます。
でもめんどいじゃん？だからコマンドを作りました。シェルでこうします。

```sh
vim slide.txt +SlideStart
```

# 画像関連
特定の環境ではこのプラグインのslide#image関数を使えば画像を表示できます。slide#image関数はsixelとかkittyプロトコルとかitermプロトコルとかで表示するための関数です。どのプロトコルを使うかは事前に決めておく必要があります。例えばこんな感じ。

```vim
let g:slide#terminal = 'kitty'
```

```vim
let g:slide#terminal = 'wezterm-iterm'
```

その上で

```vim
call slide#image('fname.png', [0, 0, 0, 0])
```

後半は座標や大きさです。いずれも文字の大きさに合わせる事になります。

# 声を出す
僕のvimは喋ります。つまり、僕のスライドは喋ります。もちろんvim scriptを書いてもいいのですが、僕は外部コマンドに投げます。僕はVOICEVOXを使います。VOICEVOX ENGINEをダウンロードして起動する必要があります。また、シェルからVOICEVOXを使うツールは自作のninvoicevoxです。

https://github.com/uesseu/ninvoicevox

vimはシェルにコマンドを投げられるので、これでスライドを読んでくれるのです。ええ、僕はLT会ではvimとずんだもんによる自動スライドをぶっぱしてます。vimなら当然system関数…といいたい所ですが、それを使うのはたいへんです。job_start関数も大変です。だから、下記のコマンドを書きました。

# 時間・非同期処理関連
ずんだもんが読んでくれるとしても、スライド内の動的要素と同期しないといけません。vimの場合は外部コマンドをjob_start、vimの関数をtimer_startを使ってケアするのですが…どちらもコールバック関数を定義してから動作させるものです。
たかだかスライドを作るのにコールバック地獄を導入するのは、もはや何をしているのかわかりません。そこで、記法を考えました。

```vim
Do [command1] Then [command2]
```

こんな感じでチェインしていけば、コールバック地獄にならないです。普通にvimscriptを動かす時、少し待って動かす時、外部シェルに投げる時で、全て同じようなインターフェイスで実行できるようにしてやればいいのです。三つのコマンドを作りました。Do, Sh, Timerです。こうなります。

```
Do [vim command]
    \Then Sh [shell command]
    \Then Timer [時間] [vim command]
```

以下、いかようにも組みあわせる事ができます。ただし、Thenというキーワードが都合がわるい事もあると思います。Thenに関しては変更可能にしています。

これによって、疑似的に非同期的なスライドが作れます。つまり、ずんだもんが喋りながら表情を変え、そうしつつも画像を提示し、同時に画面内の文字列も変る…。マジでリッチです。<font color=red>**フォントは変えられないけどな!**</font>

https://github.com/uesseu/dothen.vim


# 劣化パワポだね、効能効果あるの？
完全に劣化パワポではありますが、一応以下のような効能効果があります。

- フォントを弄れないのでフォントの不揃いで叱られない
- 宴会芸としては割と優秀
- 柔軟性に関しては強いので下記のような事ができる

例えばこんな事ができるかもしれません。

- if文を使える
    - 時間に応じて内容を省けるスライド
- テキストを動的に変更可能
    - レトロゲーム風に文字を徐々に出すスライド<font color='red'>←やった</font>
    - スライド内で生成AIを実演できるスライド
- シェル内で動く
    - シームレスにCUIの実演をするスライド<font color='red'>←やった</font>
- サブプロセスを動かせる
    - ずんだもんが喋るスライド<font color='red'>←やった</font>

# 君、もしかして、ふざけてるよね？
ほんの少ししかふざけていないのに、ものすごーくふざけていると勘違いされるのは心外です!というか、僕はエンジニアじゃないし、単なる趣味勢だからふざけてもいいんです🤪

以上です。
プログラミングは楽しいなぁ…