autocmd_option_spec.lua 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. local helpers = require('test.functional.helpers')(after_each)
  2. local nvim = helpers.meths
  3. local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq
  4. local curbuf, buf = helpers.curbuf, helpers.bufmeths
  5. local curwin = helpers.curwin
  6. local redir_exec = helpers.redir_exec
  7. local source, command = helpers.source, helpers.command
  8. local function declare_hook_function()
  9. source([[
  10. fu! AutoCommand(match, bufnr, winnr)
  11. let l:acc = {
  12. \ 'option' : a:match,
  13. \ 'oldval' : v:option_old,
  14. \ 'newval' : v:option_new,
  15. \ 'scope' : v:option_type,
  16. \ 'attr' : {
  17. \ 'bufnr' : a:bufnr,
  18. \ 'winnr' : a:winnr,
  19. \ }
  20. \ }
  21. call add(g:ret, l:acc)
  22. endfu
  23. ]])
  24. end
  25. local function set_hook(pattern)
  26. command(
  27. 'au OptionSet '
  28. .. pattern ..
  29. ' :call AutoCommand(expand("<amatch>"), bufnr("%"), winnr())'
  30. )
  31. end
  32. local function init_var()
  33. command('let g:ret = []')
  34. end
  35. local function get_result()
  36. local ret = nvim.get_var('ret')
  37. init_var()
  38. return ret
  39. end
  40. local function expected_table(option, oldval, newval, scope, attr)
  41. return {
  42. option = option,
  43. oldval = tostring(oldval),
  44. newval = tostring(newval),
  45. scope = scope,
  46. attr = attr,
  47. }
  48. end
  49. local function expected_combination(...)
  50. local args = {...}
  51. local ret = get_result()
  52. if not (#args == #ret) then
  53. local expecteds = {}
  54. for _, v in pairs(args) do
  55. table.insert(expecteds, expected_table(unpack(v)))
  56. end
  57. eq(expecteds, ret)
  58. return
  59. end
  60. for i, v in ipairs(args) do
  61. local attr = v[5]
  62. if not attr then
  63. -- remove attr entries
  64. ret[i].attr = nil
  65. else
  66. -- remove attr entries which are not required
  67. for k in pairs(ret[i].attr) do
  68. if not attr[k] then
  69. ret[i].attr[k] = nil
  70. end
  71. end
  72. end
  73. eq(expected_table(unpack(v)), ret[i])
  74. end
  75. end
  76. local function expected_empty()
  77. eq({}, get_result())
  78. end
  79. local function make_buffer()
  80. local old_buf = curbuf()
  81. command('botright new')
  82. local new_buf = curbuf()
  83. command('wincmd p') -- move previous window
  84. neq(old_buf, new_buf)
  85. eq(old_buf, curbuf())
  86. return new_buf
  87. end
  88. local function get_new_window_number()
  89. local old_win = curwin()
  90. command('botright new')
  91. local new_win = curwin()
  92. local new_winnr = redir_exec('echo winnr()')
  93. command('wincmd p') -- move previous window
  94. neq(old_win, new_win)
  95. eq(old_win, curwin())
  96. return new_winnr:gsub('\n', '')
  97. end
  98. describe('au OptionSet', function()
  99. describe('with any opton (*)', function()
  100. before_each(function()
  101. clear()
  102. declare_hook_function()
  103. init_var()
  104. set_hook('*')
  105. end)
  106. it('should be called in setting number option', function()
  107. command('set nu')
  108. expected_combination({'number', 0, 1, 'global'})
  109. command('setlocal nonu')
  110. expected_combination({'number', 1, 0, 'local'})
  111. command('setglobal nonu')
  112. expected_combination({'number', 1, 0, 'global'})
  113. end)
  114. it('should be called in setting autoindent option',function()
  115. command('setlocal ai')
  116. expected_combination({'autoindent', 0, 1, 'local'})
  117. command('setglobal ai')
  118. expected_combination({'autoindent', 0, 1, 'global'})
  119. command('set noai')
  120. expected_combination({'autoindent', 1, 0, 'global'})
  121. end)
  122. it('should be called in inverting global autoindent option',function()
  123. command('set ai!')
  124. expected_combination({'autoindent', 0, 1, 'global'})
  125. end)
  126. it('should be called in being unset local autoindent option',function()
  127. command('setlocal ai')
  128. expected_combination({'autoindent', 0, 1, 'local'})
  129. command('setlocal ai<')
  130. expected_combination({'autoindent', 1, 0, 'local'})
  131. end)
  132. it('should be called in setting global list and number option at the same time',function()
  133. command('set list nu')
  134. expected_combination(
  135. {'list', 0, 1, 'global'},
  136. {'number', 0, 1, 'global'}
  137. )
  138. end)
  139. it('should not print anything, use :noa', function()
  140. command('noa set nolist nonu')
  141. expected_empty()
  142. end)
  143. it('should be called in setting local acd', function()
  144. command('setlocal acd')
  145. expected_combination({'autochdir', 0, 1, 'local'})
  146. end)
  147. it('should be called in setting autoread', function()
  148. command('set noar')
  149. expected_combination({'autoread', 1, 0, 'global'})
  150. command('setlocal ar')
  151. expected_combination({'autoread', 0, 1, 'local'})
  152. end)
  153. it('should be called in inverting global autoread', function()
  154. command('setglobal invar')
  155. expected_combination({'autoread', 1, 0, 'global'})
  156. end)
  157. it('should be called in setting backspace option through :let', function()
  158. command('let &bs=""')
  159. expected_combination({'backspace', 'indent,eol,start', '', 'global'})
  160. end)
  161. describe('being set by setbufvar()', function()
  162. it('should not trigger because option name is invalid', function()
  163. command('silent! call setbufvar(1, "&l:bk", 1)')
  164. expected_empty()
  165. end)
  166. it('should trigger using correct option name', function()
  167. command('call setbufvar(1, "&backup", 1)')
  168. expected_combination({'backup', 0, 1, 'local'})
  169. end)
  170. it('should trigger if the current buffer is different from the targetted buffer', function()
  171. local new_buffer = make_buffer()
  172. local new_bufnr = buf.get_number(new_buffer)
  173. command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
  174. expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}})
  175. end)
  176. end)
  177. end)
  178. describe('with specific option', function()
  179. before_each(function()
  180. clear()
  181. declare_hook_function()
  182. init_var()
  183. end)
  184. it('should be called iff setting readonly', function()
  185. set_hook('readonly')
  186. command('set nu')
  187. expected_empty()
  188. command('setlocal ro')
  189. expected_combination({'readonly', 0, 1, 'local'})
  190. command('setglobal ro')
  191. expected_combination({'readonly', 0, 1, 'global'})
  192. command('set noro')
  193. expected_combination({'readonly', 1, 0, 'global'})
  194. end)
  195. describe('being set by setbufvar()', function()
  196. it('should not trigger because option name does not match with backup', function()
  197. set_hook('backup')
  198. command('silent! call setbufvar(1, "&l:bk", 1)')
  199. expected_empty()
  200. end)
  201. it('should trigger, use correct option name backup', function()
  202. set_hook('backup')
  203. command('call setbufvar(1, "&backup", 1)')
  204. expected_combination({'backup', 0, 1, 'local'})
  205. end)
  206. it('should trigger if the current buffer is different from the targetted buffer', function()
  207. set_hook('buftype')
  208. local new_buffer = make_buffer()
  209. local new_bufnr = buf.get_number(new_buffer)
  210. command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
  211. expected_combination({'buftype', '', 'nofile', 'local', {bufnr = new_bufnr}})
  212. end)
  213. end)
  214. describe('being set by setwinvar()', function()
  215. it('should not trigger because option name does not match with backup', function()
  216. set_hook('backup')
  217. command('silent! call setwinvar(1, "&l:bk", 1)')
  218. expected_empty()
  219. end)
  220. it('should trigger, use correct option name backup', function()
  221. set_hook('backup')
  222. command('call setwinvar(1, "&backup", 1)')
  223. expected_combination({'backup', 0, 1, 'local'})
  224. end)
  225. it('should not trigger if the current window is different from the targetted window', function()
  226. set_hook('cursorcolumn')
  227. local new_winnr = get_new_window_number()
  228. command('call setwinvar(' .. new_winnr .. ', "&cursorcolumn", 1)')
  229. -- expected_combination({'cursorcolumn', 0, 1, 'local', {winnr = new_winnr}})
  230. expected_empty()
  231. end)
  232. end)
  233. describe('being set by neovim api', function()
  234. it('should trigger if a boolean option be set globally', function()
  235. set_hook('autochdir')
  236. nvim.set_option('autochdir', true)
  237. eq(true, nvim.get_option('autochdir'))
  238. expected_combination({'autochdir', '0', '1', 'global'})
  239. end)
  240. it('should trigger if a number option be set globally', function()
  241. set_hook('cmdheight')
  242. nvim.set_option('cmdheight', 5)
  243. eq(5, nvim.get_option('cmdheight'))
  244. expected_combination({'cmdheight', 1, 5, 'global'})
  245. end)
  246. it('should trigger if a string option be set globally', function()
  247. set_hook('ambiwidth')
  248. nvim.set_option('ambiwidth', 'double')
  249. eq('double', nvim.get_option('ambiwidth'))
  250. expected_combination({'ambiwidth', 'single', 'double', 'global'})
  251. end)
  252. end)
  253. end)
  254. end)