summaryrefslogtreecommitdiffhomepage
path: root/vhosts/blog/content/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre.dj
blob: a97337d05c65c02e90bafefe0eecc0823bcbd32a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
---
[article]
uuid = "44171f75-c312-4c92-9927-3d260e162175"
title = "【Vim】 autocmd events の BufWrite/BufWritePre の違い"
description = "Vim の autocmd events における BufWrite/BufWritePre がどう違うのかを調べた結果、違いはないことがわかった。"
tags = [
  "vim",
]

[[article.revisions]]
date = "2021-10-02"
remark = "Qiita から移植"
---
::: note
この記事は Qiita から移植してきたものです。
元 URL: https://qiita.com/nsfisis/items/79ab4db8564032de0b25
:::

{#tl-dr}
# TL; DR

違いはない。ただのエイリアス。

{#code-reading}
# 調査記録

Vim の autocmd events には似通った名前のものがいくつかある。大抵は
`:help`
に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。

* `BufRead`/`BufReadPost`
* `BufWrite`/`BufWritePre`
* `BufAdd`/`BufCreate`

このうち、`BufAdd`/`BufCreate` に関しては、`:help BufCreate` に

> The BufCreate event is for historic reasons.

とあり、おそらくは `BufAdd`
のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため
vim と neovim のソースコードを調査した。

ソースコードへのリンク

* [vim (調査時点での master branch)](https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2)
* [neovim (上に同じ)](https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3)

{#vim}
## vim のソースコード

以下は、autocmd events
の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。

https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86

{filename="src/autocmd.c"}
```c
{"BufAdd",      EVENT_BUFADD},
{"BufCreate",   EVENT_BUFADD},
```

https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97

{filename="src/autocmd.c"}
```c
{"BufRead",     EVENT_BUFREADPOST},
{"BufReadCmd",  EVENT_BUFREADCMD},
{"BufReadPost", EVENT_BUFREADPOST},
```

https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105

{filename="src/autocmd.c"}
```c
{"BufWrite",    EVENT_BUFWRITEPRE},
{"BufWritePost",    EVENT_BUFWRITEPOST},
{"BufWritePre", EVENT_BUFWRITEPRE},
```

{#neovim}
## neovim のソースコード

neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua
で書かれている。以下にある通り、はっきり `aliases` と書かれている。

https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124

{filename="src/nvim/auevents.lua"}
```lua
aliases = {
  BufCreate = 'BufAdd',
  BufRead = 'BufReadPost',
  BufWrite = 'BufWritePre',
  FileEncoding = 'EncodingChanged',
},
```

ところで、上では取り上げなかった `FileEncoding` だが、これは
`:help FileEncoding` にしっかりと書いてある。

{filename=":help FileEncoding"}
```
                                                              *FileEncoding*
FileEncoding                    Obsolete.  It still works and is equivalent
                                to |EncodingChanged|.
```

{#outro}
# まとめ

記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。

* `BufAdd`/`BufCreate`

  * → `BufCreate` は歴史的な理由により ("for historic reasons") 存在しているため、新しい方 (`BufAdd`) を使う

* `BufRead`/`BufReadPost`

  * → `BufReadPre` との対称性のため、あるいは `BufWritePost` との対称性のため `BufReadPost` を使う

* `BufWrite`/`BufWritePre`

  * → `BufWritePost` との対称性のため、あるいは `BufReadPre` との対称性のため `BufWritePre` を使う

* `FileEncoding`/`EncodingChanged`

  * → `FileEncoding` は "Obsolete" と明言されているので、`EncodingChanged` を使う

ところでこの調査で知ったのだが、`BufRead` と `BufWrite`
は上にある通り発火するタイミングが「後」と「前」で対称性がない。可能なら
`Pre`/`Post` 付きのものを使った方が分かりやすいだろう。