怖くなかったVim script


advent calendarの8日目です

## これは
Vim scriptに触れたのでふんわり紹介
Vim scriptとか.vimがつくやつって[unite.vim](https://github.com/Shougo/unite.vim)とかみたいに遠い存在かと思っていたがそんなことはなかった

## 前提条件
- 環境
    - VIM - Vi IMproved 8.1 (2018 May 18, compiled Sep 18 2019 03:49:48)

## 書かないこと
- 基本文法の解説
- チュートリアル
- モチベーション
    - 「普段、言語は何を？」って聞かれて*「Vim scriptを少々」*とか言えるようになりたくない？？？

## 参考文献

自分が触れていなかっただけで楽しめる入門記事はたくさんあった

- [Vimスクリプト基礎文法最速マスター](https://thinca.hatenablog.com/entry/20100201/1265009821)
- [はじめてのvimscriptとvimプラグインの作成](https://qiita.com/Sa2Knight/items/6b26d35af571c239da31)
- [Vim script事始め](https://vim-jp.org/tips/start_vimscript.html)
- [Vimスクリプトリファレンス](http://nanasi.jp/code.html)
- [モテる男のVim script短期集中講座](https://mattn.kaoriya.net/software/vim/20111202085236.htm)
- [im script と vimrc の正しい書き方](https://www.slideshare.net/cohama/vim-script-vimrc-nagoyavim-1)
- [Vim日本語ドキュメント](https://vim-jp.org/vimdoc-ja/usr_41.html)


## 本編
### そもそも何

>Vim script は Vim に組み込まれたスクリプト言語である。
https://ja.wikipedia.org/wiki/Vim_script

Wikipediaだがなるほど

>Vim script 言語は vimrc ファイルや構文ファイルなど、さまざまな目的に使われま
す。この章では Vim script の書き方を説明します。説明することがたくさんあるので
大きな章になってます。
https://vim-jp.org/vimdoc-ja/usr_41.html

(コピペの結晶となっているvimrcを読み解けるようになる日が来るのか...という顔)

### Hello World
個人的には新しい言語・環境を学ぶ時はHello Worldが大きな境目だと思っていて、実行さえできれば先駆者の記事やリファレンスを読みながら進んでいける（はずな）のでHello Worldだけはやる

```sh:sh
vim hello_vimscript.vim
```
```vimscript:hello_vimscript.vim
echo "hello vim script"
```
ファイルを開いたまま

```vim:exコマンド
:source hello_vimscript.vim
```
```sh:出力
hello vim script
```
できた！
コマンドラインからの実行もできるが割愛

### 遊んでみた
構文解析してプラグイン開発！はまだ遠いので身近なところからやる
手前味噌（厳密には意味違う）だが[これ](https://qiita.com/sh05_sh05/items/90315cd98a1ea3cead29#%E5%AE%9F%E8%B7%B5%E4%BE%8B)を自動化する

#### できるもの
開始時間と終了時間と1単位(分)を入力するとToDoを管理できるフォーマットを出力する

#### コード
```vim:make_today_schedule.vim
command! -nargs=* MTS call MakeTodaySchedule(<f-args>)

let s:d_st = 10
let s:d_ft = 19
let s:d_uom = 30

function! s:help()
  echo "Usage:"
  echo "\tMTS <StarHour> <FinishHour> <UnitOfMinute>"
  echo "Default:"
  echo "\tStarHour: " . s:d_st
  echo "\tFinishHour: " . s:d_ft
  echo "\tUnitOfMinute: " . s:d_uom
  echo "Example:"
  echo "\tMTS 9 18 30"
  return 
endfunction

function! MakeTodaySchedule(...) abort
  " defaultを入力
  let st = exists("a:1") ? a:1 : s:d_st
  let ft = exists("a:2") ? a:2 : s:d_ft
  let uom = exists("a:3") ? a:3 : s:d_uom

  if st == "help"
    call s:help()
    return 
  endif
    
  if st < 0
    echo "Message:"
    echo "\tStartHour must be after 0:00"
    call s:help()
    return 
  endif

  " 時間以外のテンプレート
  let now = localtime()
  execute "normal a" . "# ToDo on " . strftime("%Y/%m/%d", now) . "\n\n"
  execute "normal a" . "## ToDos" . "\n"
  execute "normal a" . "- ToDoA" . "\n"
  execute "normal a" . "- ToDoB" . "\n\n"
  execute "normal a" . "## Schedule" . "\n"

  " 分に換算
  let minute_of_range = (ft - st) * 60
  " uom は区切りたい分の単位
  let num_of_line = minute_of_range / uom
  for i in range(0, num_of_line)
    let h = st + i * uom / 60
    let m = i * uom % 60
    " 0-9分の表記直し
    if m < 10
      execute "normal a" . "### " . h . ":0" . m . "\n"
    else
      execute "normal a" . "### " . h . ":" . m . "\n"
    endif
    " 記入例
    if i == 0
      execute "normal a" . "- ToDoA" . "\n"
    endif
  endfor
endfunction
```
`echo`とか`execute`を連打してるのは見かけ良くなさそうなので、他の人のコードを読んで勉強せねば

終了時間を24以下としていないのは、自分が締め切り3日前に0:00~72:00と考えるようなよくない人間だから

#### 実行
todoを管理するファイルを開く

```sh:sh
vim todo.md
```
todo.mdを開いた状態で

```ex:exコマンド
"読み込み
:source make_today_schedule.vim
"実行(デフォルト値)
:MTS
"実行（8時から20時、37分単位（半端な数でもとりあえずは動く））
:MTS 8 20 37
"実行(ヘルプ)
:MTS help
```
下記は`:MTS 8 20 37`の実行結果

```todo.md
# ToDo on 2019/12/08

## ToDos
- ToDoA
- ToDoB

## Schedule
### 8:00
- ToDoA
### 8:37
### 9:14
### 9:51
### 10:28
### 11:05
### 11:42
### 12:19
### 12:56
### 13:33
### 14:10
### 14:47
### 15:24
### 16:01
### 16:38
### 17:15
### 17:52
### 18:29
### 19:06
### 19:43
```
下記は`:MTS help`の実行結果

```
Usage:
        MTS <StarHour> <FinishHour> <UnitOfMinute>
Default:
        StarHour: 10
        FinishHour: 19
        UnitOfMinute: 30
Example:
        MTS 9 18 30
```

#### 使い方
タスクをToDosに列挙して`yy`と`p`を駆使して予定を立てる

## おわり
これまでは思考停止でVim scriptは強者の戯れだと恐れていたが楽しいことがたくさんできそうだと思った

プログレスバーとかめちゃくちゃ楽しそうなので次は[こちら](https://mattn.kaoriya.net/software/vim/20111202085236.htm)をやりたい