100行でvim-startifyもどきを作る

## 他の100行シリーズもよろしくお願いします

https://qiita.com/neras_1215/items/5f58e10d3ba3b846b51b

https://qiita.com/neras_1215/items/1b79d3773a755e366f25

## [mhinz/vim-startify](https://github.com/mhinz/vim-startify)
リポジトリREADME内のスクショです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/91414a77-4fbd-d000-54b3-b7069faa2a22.png)

`vi ファイル名`でなく
`vi`のみで
vimを起動した直後の画面をカスタムできるもの。
さらに。セッション機能がある。
前回開いたファイルトップ10とかを表示し、カーソル移動で開けるというもの。

私個人としてはセッション機能いらないので
とにかく起動時の画面を作ってみる。

## できたもの

https://github.com/serna37/vim

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/3dd67238-5830-15c7-ace2-2b124bf9b8f5.png)

アスキーアート以外に、自分用にカスタムしたキーマップのチートシートを書いてみました。

私はLSPとかを除きプラグインは自作しているので
vim-airlineに見えるやつもvimrcに書いてます。真似しました。

## 仕組み
まず起動直後の画面をこんな大胆に変える方法は何かというと
これが全てです。
```vim
sil! exe 'e _cheat_cheet_'
```
起動後にautocmdで、新規バッファを開いているだけです。
ただしこのロゴ用のバッファは修正したくないし、勝手にファイルとして保存してほしくもないので
```vim
setl buftype=nofile bufhidden=wipe nobuflisted modifiable
```
とし、装飾をとっぱらいつつ、右下のファイルタイプを好きな文字にする。
```vim
setl nonumber norelativenumber nocursorline nocursorcolumn signcolumn=no
let &filetype = 'Bocchi_The_Rock'
```
また、INSERTモードなどの編集できるキーを無効にする
```vim
    nmap <buffer>i \<Esc>
    nmap <buffer>I \<Esc>
    nmap <buffer>a \<Esc>
    nmap <buffer>A \<Esc>
    nmap <buffer>s \<Esc>
```
あとはこのロゴ専用にできたバッファに文字を入れて
```vim
    cal append('$', self.btr_logo) " アスキーアートを1行ごとに分けた2次元配列文字
    cal append('$', ['',''])
    cal append('$', self.cheat_sheet_win) " チートシートを1行ごとに分けた2次元配列文字
```
色や装飾をする
```vim
    hi BTR ctermfg=218 cterm=bold
    cal matchaddpos('BTR', range(2,9)->map({_,v->[v]}), 999)
    cal matchaddpos('BTR', range(10,17)->map({_,v->[v]}), 999)
    cal matchaddpos('BTR', range(18,21)->map({_,v->[v]}), 999)
    cal matchadd('User_greenfg_blackbg', '[─│╰╯╭╮]', 20)
    cal matchadd('DarkOrange', '\(Window\|Search\|Motion\|Command\)')
    cal matchadd('DarkBlue', '│.\{-,25}|', 19)
    cal matchadd('DarkRed', '(.*)', 18)
```
最後に、appendした時点で編集されたと見なされるので
以下をつけて、あたかも最初からロゴやチートシートが書いてあったかのような顔をする
```vim
    setl nomodifiable nomodified
```

これらを`VimEnter`で呼ばれるようにしてやれば良いが
このままでは別のバッファを開いたときなどに、色やboldなどが残ってしまうので
`BufReadPre`のautocmdで`clearmatches`しつつ
そのautocmdが1度のみ呼ばれるようにしたい（バッファ開くたびにclearmatchesでは通常作業に支障）

なので
```vim
fu! s:start.move() abort " 一度のみ呼びたいクリア処理
    cal clearmatches()
    cal s:fmode.activate()

    " deactivate
    aug start_vim " 呼ばれたらautocmdを消すので1度しかここに来ない
        au!
    aug END
endf

" only first call
aug start_vim
    au!
    au VimEnter * cal s:start.exe()
    au BufReadPre * cal s:start.move() " スタート画面から変わった時に呼ばれるが
aug END

```
とする。

全量はこうなる
```vim
" ===================================================================
" mhinz/vim-startify
" ===================================================================
" {{{
let s:start = #{}

" ぼっちざろっく{{{
let s:start.btr_logo = [
    \'                                                                                                                                              dN',
    \'                                                                                                              ..                             JMF',
    \'                                                                                                         ..gMMMM%                           JMF',
    \'                                                                                                       .MM9^ .MF                           (MF',
    \'                                                                                              .(,      ("   .M#                  .g,      .MF',
    \'                                        .,  dN                                             gg,,M@          .M#                  .M#!      (M>',
    \'                                        JM} M#             .MNgg.                     .g,  ?M[ 7B         .MMg+gg,.           .MM"        ."',
    \'                                ...gNMN,.Mb MN           .gMM9!                      .(MN,  .=           .MMM9=  ?MN,         (WN,      .MM ',
    \'                   jN-      ..gMMN#!     (Mp(M}       .+MMYMF                    ..kMMWM%               ,M#^       dN.          .WNJ,   JM',
    \'                   MM     .MM9^  dN,                 dNB^ (M%                   ?M"!  ,M\        .,               .M#   .&MMMN,    ?"   M#',
    \'                   MN            .MN#^                    dM:  ..(J-,                 ,B         .TM             .M#   ,M@  .MF',
    \'                   MN.       ..MMBMN_                     dN_.MM@"!?MN.   TMm     .a,                           (M@         MM^',
    \'                   MN.     .MM"  JMb....       ..        dMMM=     .Mb            ?HNgJ..,                   .MM^',
    \'                   dM{          -MMM#7"T""   .dN#TMo       ?      .MM^                 ?!                 +gM#=',
    \'                   (M]         .MN(N#       .M@  .MF              .MM^                                      ~',
    \'                   .MN          ?"""             MM!            .MMD',
    \'                    ?N[                                         7"',
    \'                     TMe',
    \'                      ?MN,',
    \'                        TMNg,'
    \]
"}}}

" cheat sheet {{{
let s:start.cheat_sheet_win = [
    \'       ╭── Window ──────────────────────────────────────────╮           ╭── Search ───────────────────────────────────────╮',
    \'       │ C-n / p    | (buffer tab)(next / prev)             │           │ Space e    | (explorer)                         │',
    \'       │ Space x    | (buffer tab)(close)                   │           │ Space f    | (fzf)(files / projectfiles auto)   │',
    \'       │ C-w v / s  | (window split)(vertical / horizontal) │           │ Space h    | (fzf)(histories)                   │',
    \'       │ ←↑↓→       | (window)(resize)                      │           │ Space b    | (fzf)(buffers)                     │',
    \'       │ C-hjkl     | (window)(forcus)                      │           │ Space m    | (marks)                            │',
    \'       │ Space t/g  | (terminal)/(lazygit)                  │           │ Space s    | (fuzzy search in file / quickfix)  │',
    \'       │ Space z    | (Zen Mode)                            │           │ Space*2 s  | (grep interactive)                 │',
    \'       ╰────────────────────────────────────────────────────╯           │ Space q    | (clear search highlight)           │',
    \'                                                                        ╰─────────────────────────────────────────────────╯',
    \'',
    \'       ╭── Motion ───────────────────────────────────────────╮          ╭── Command ──────────────────────────────────────────╮',
    \'       │ Space v       | (IDE Action Menu)                   │          │ :PlugInstall            | (plugins install)         │',
    \'       │ Space w       | (f-scope toggle)                    │          │ :PlugUnInstall          | (plugins uninstall)       │',
    \'       │ Tab S-Tab     | (jump 5rows)                        │          │ :RunCat [option]        | (running cat)             │',
    \'       │ s             | (easymotion)                        │          │ :RunCatStop             | (running cat stop)        │',
    \'       │ mm            | (mark toggle)                       │          │ :TrainingWheelsProtocol | [option] (training vim)   │',
    \'       │ mn / mp       | (mark next / prev)                  │          ╰─────────────────────────────────────────────────────╯',
    \'       │ mc / mx       | (mark clear file / delete all file) │',
    \'       │ INSERT C-hjkl | (cursor move)                       │',
    \'       │ VISUAL C-jk   | (blok up / down)                    │',
    \'       ╰─────────────────────────────────────────────────────╯',
    \]
" }}}

fu! s:start.exe() abort
    let fopen = execute('ls')->split('\n')->map({_,v -> split(v, '"')[1]})
            \ ->filter({_,v -> v != '[No Name]' && v != '[無名]'})->len()
    if fopen
        cal self.move()
        retu
    endif
    " preview window
    sil! exe 'e _cheat_cheet_'
    setl buftype=nofile bufhidden=wipe nobuflisted modifiable
    setl nonumber norelativenumber nocursorline nocursorcolumn signcolumn=no
    let &filetype = 'Bocchi_The_Rock'
    nmap <buffer>i \<Esc>
    nmap <buffer>I \<Esc>
    nmap <buffer>a \<Esc>
    nmap <buffer>A \<Esc>
    nmap <buffer>s \<Esc>

    " draw
    cal append('$', self.btr_logo)
    cal append('$', ['',''])
    cal append('$', self.cheat_sheet_win)
    hi BTR ctermfg=218 cterm=bold
    cal matchaddpos('BTR', range(2,9)->map({_,v->[v]}), 999)
    cal matchaddpos('BTR', range(10,17)->map({_,v->[v]}), 999)
    cal matchaddpos('BTR', range(18,21)->map({_,v->[v]}), 999)
    cal matchadd('User_greenfg_blackbg', '[─│╰╯╭╮]', 20)
    cal matchadd('DarkOrange', '\(Window\|Search\|Motion\|Command\)')
    cal matchadd('DarkBlue', '│.\{-,25}|', 19)
    cal matchadd('DarkRed', '(.*)', 18)

    " fix
    setl nomodifiable nomodified
endf

fu! s:start.move() abort
    cal clearmatches()
    cal s:fmode.activate()

    " deactivate
    aug start_vim
        au!
    aug END
endf

" only first call
aug start_vim
    au!
    au VimEnter * cal s:start.exe()
    au BufReadPre * cal s:start.move()
aug END
" }}}

```

ちょっと100行超えました。。