gruvbox_material.vim 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. " =============================================================================
  2. " URL: https://github.com/sainnhe/gruvbox-material
  3. " Filename: autoload/gruvbox_material.vim
  4. " Author: sainnhe
  5. " Email: i@sainnhe.dev
  6. " License: MIT License
  7. " =============================================================================
  8. function! gruvbox_material#get_configuration() "{{{
  9. return {
  10. \ 'background': get(g:, 'gruvbox_material_background', 'medium'),
  11. \ 'foreground': get(g:, 'gruvbox_material_foreground', get(g:, 'gruvbox_material_palette', 'material')),
  12. \ 'transparent_background': get(g:, 'gruvbox_material_transparent_background', 0),
  13. \ 'dim_inactive_windows': get(g:, 'gruvbox_material_dim_inactive_windows', 0),
  14. \ 'disable_italic_comment': get(g:, 'gruvbox_material_disable_italic_comment', 0),
  15. \ 'enable_bold': get(g:, 'gruvbox_material_enable_bold', 0),
  16. \ 'enable_italic': get(g:, 'gruvbox_material_enable_italic', 0),
  17. \ 'cursor': get(g:, 'gruvbox_material_cursor', 'auto'),
  18. \ 'visual': get(g:, 'gruvbox_material_visual', 'grey background'),
  19. \ 'menu_selection_background': get(g:, 'gruvbox_material_menu_selection_background', 'grey'),
  20. \ 'sign_column_background': get(g:, 'gruvbox_material_sign_column_background', 'none'),
  21. \ 'spell_foreground': get(g:, 'gruvbox_material_spell_foreground', 'none'),
  22. \ 'ui_contrast': get(g:, 'gruvbox_material_ui_contrast', 'low'),
  23. \ 'show_eob': get(g:, 'gruvbox_material_show_eob', 1),
  24. \ 'float_style': get(g:, 'gruvbox_material_float_style', 'bright'),
  25. \ 'current_word': get(g:, 'gruvbox_material_current_word', get(g:, 'gruvbox_material_transparent_background', 0) == 0 ? 'grey background' : 'bold'),
  26. \ 'statusline_style': get(g:, 'gruvbox_material_statusline_style', 'default'),
  27. \ 'lightline_disable_bold': get(g:, 'gruvbox_material_lightline_disable_bold', 0),
  28. \ 'diagnostic_text_highlight': get(g:, 'gruvbox_material_diagnostic_text_highlight', 0),
  29. \ 'diagnostic_line_highlight': get(g:, 'gruvbox_material_diagnostic_line_highlight', 0),
  30. \ 'diagnostic_virtual_text': get(g:, 'gruvbox_material_diagnostic_virtual_text', 'grey'),
  31. \ 'disable_terminal_colors': get(g:, 'gruvbox_material_disable_terminal_colors', 0),
  32. \ 'better_performance': get(g:, 'gruvbox_material_better_performance', 0),
  33. \ 'colors_override': get(g:, 'gruvbox_material_colors_override', {}),
  34. \ }
  35. endfunction "}}}
  36. function! gruvbox_material#get_palette(background, foreground, colors_override) "{{{
  37. if a:background ==# 'hard' "{{{
  38. if &background ==# 'dark'
  39. let palette1 = {
  40. \ 'bg_dim': ['#141617', '232'],
  41. \ 'bg0': ['#1d2021', '234'],
  42. \ 'bg1': ['#282828', '235'],
  43. \ 'bg2': ['#282828', '235'],
  44. \ 'bg3': ['#3c3836', '237'],
  45. \ 'bg4': ['#3c3836', '237'],
  46. \ 'bg5': ['#504945', '239'],
  47. \ 'bg_statusline1': ['#282828', '235'],
  48. \ 'bg_statusline2': ['#32302f', '235'],
  49. \ 'bg_statusline3': ['#504945', '239'],
  50. \ 'bg_diff_green': ['#32361a', '22'],
  51. \ 'bg_visual_green': ['#333e34', '22'],
  52. \ 'bg_diff_red': ['#3c1f1e', '52'],
  53. \ 'bg_visual_red': ['#442e2d', '52'],
  54. \ 'bg_diff_blue': ['#0d3138', '17'],
  55. \ 'bg_visual_blue': ['#2e3b3b', '17'],
  56. \ 'bg_visual_yellow': ['#473c29', '94'],
  57. \ 'bg_current_word': ['#32302f', '236']
  58. \ }
  59. else
  60. let palette1 = {
  61. \ 'bg_dim': ['#f3eac7', '229'],
  62. \ 'bg0': ['#f9f5d7', '230'],
  63. \ 'bg1': ['#f5edca', '229'],
  64. \ 'bg2': ['#f3eac7', '229'],
  65. \ 'bg3': ['#f2e5bc', '228'],
  66. \ 'bg4': ['#eee0b7', '223'],
  67. \ 'bg5': ['#ebdbb2', '223'],
  68. \ 'bg_statusline1': ['#f5edca', '223'],
  69. \ 'bg_statusline2': ['#f3eac7', '223'],
  70. \ 'bg_statusline3': ['#eee0b7', '250'],
  71. \ 'bg_diff_green': ['#e4edc8', '194'],
  72. \ 'bg_visual_green': ['#dde5c2', '194'],
  73. \ 'bg_diff_red': ['#f8e4c9', '217'],
  74. \ 'bg_visual_red': ['#f0ddc3', '217'],
  75. \ 'bg_diff_blue': ['#e0e9d3', '117'],
  76. \ 'bg_visual_blue': ['#d9e1cc', '117'],
  77. \ 'bg_visual_yellow': ['#f9eabf', '226'],
  78. \ 'bg_current_word': ['#f3eac7', '229']
  79. \ }
  80. endif "}}}
  81. elseif a:background ==# 'medium' "{{{
  82. if &background ==# 'dark'
  83. let palette1 = {
  84. \ 'bg_dim': ['#1b1b1b', '233'],
  85. \ 'bg0': ['#282828', '235'],
  86. \ 'bg1': ['#32302f', '236'],
  87. \ 'bg2': ['#32302f', '236'],
  88. \ 'bg3': ['#45403d', '237'],
  89. \ 'bg4': ['#45403d', '237'],
  90. \ 'bg5': ['#5a524c', '239'],
  91. \ 'bg_statusline1': ['#32302f', '236'],
  92. \ 'bg_statusline2': ['#3a3735', '236'],
  93. \ 'bg_statusline3': ['#504945', '240'],
  94. \ 'bg_diff_green': ['#34381b', '22'],
  95. \ 'bg_visual_green': ['#3b4439', '22'],
  96. \ 'bg_diff_red': ['#402120', '52'],
  97. \ 'bg_visual_red': ['#4c3432', '52'],
  98. \ 'bg_diff_blue': ['#0e363e', '17'],
  99. \ 'bg_visual_blue': ['#374141', '17'],
  100. \ 'bg_visual_yellow': ['#4f422e', '94'],
  101. \ 'bg_current_word': ['#3c3836', '237']
  102. \ }
  103. else
  104. let palette1 = {
  105. \ 'bg_dim': ['#f2e5bc', '228'],
  106. \ 'bg0': ['#fbf1c7', '229'],
  107. \ 'bg1': ['#f4e8be', '228'],
  108. \ 'bg2': ['#f2e5bc', '228'],
  109. \ 'bg3': ['#eee0b7', '223'],
  110. \ 'bg4': ['#e5d5ad', '223'],
  111. \ 'bg5': ['#ddccab', '250'],
  112. \ 'bg_statusline1': ['#f2e5bc', '223'],
  113. \ 'bg_statusline2': ['#f2e5bc', '223'],
  114. \ 'bg_statusline3': ['#e5d5ad', '250'],
  115. \ 'bg_diff_green': ['#e6eabc', '194'],
  116. \ 'bg_visual_green': ['#dee2b6', '194'],
  117. \ 'bg_diff_red': ['#f9e0bb', '217'],
  118. \ 'bg_visual_red': ['#f1d9b5', '217'],
  119. \ 'bg_diff_blue': ['#e2e6c7', '117'],
  120. \ 'bg_visual_blue': ['#dadec0', '117'],
  121. \ 'bg_visual_yellow': ['#fae7b3', '226'],
  122. \ 'bg_current_word': ['#f2e5bc', '228']
  123. \ }
  124. endif "}}}
  125. else "{{{
  126. if &background ==# 'dark'
  127. let palette1 = {
  128. \ 'bg_dim': ['#252423', '233'],
  129. \ 'bg0': ['#32302f', '236'],
  130. \ 'bg1': ['#3c3836', '237'],
  131. \ 'bg2': ['#3c3836', '237'],
  132. \ 'bg3': ['#504945', '239'],
  133. \ 'bg4': ['#504945', '239'],
  134. \ 'bg5': ['#665c54', '241'],
  135. \ 'bg_statusline1': ['#3c3836', '237'],
  136. \ 'bg_statusline2': ['#46413e', '237'],
  137. \ 'bg_statusline3': ['#5b534d', '241'],
  138. \ 'bg_diff_green': ['#3d4220', '22'],
  139. \ 'bg_visual_green': ['#424a3e', '22'],
  140. \ 'bg_diff_red': ['#472322', '52'],
  141. \ 'bg_visual_red': ['#543937', '52'],
  142. \ 'bg_diff_blue': ['#0f3a42', '17'],
  143. \ 'bg_visual_blue': ['#404946', '17'],
  144. \ 'bg_visual_yellow': ['#574833', '94'],
  145. \ 'bg_current_word': ['#45403d', '238']
  146. \ }
  147. else
  148. let palette1 = {
  149. \ 'bg_dim': ['#ebdbb2', '223'],
  150. \ 'bg0': ['#f2e5bc', '228'],
  151. \ 'bg1': ['#eddeb5', '223'],
  152. \ 'bg2': ['#ebdbb2', '228'],
  153. \ 'bg3': ['#e6d5ae', '223'],
  154. \ 'bg4': ['#dac9a5', '250'],
  155. \ 'bg5': ['#d5c4a1', '250'],
  156. \ 'bg_statusline1': ['#ebdbb2', '223'],
  157. \ 'bg_statusline2': ['#ebdbb2', '223'],
  158. \ 'bg_statusline3': ['#dac9a5', '250'],
  159. \ 'bg_diff_green': ['#dfe1b4', '194'],
  160. \ 'bg_visual_green': ['#d7d9ae', '194'],
  161. \ 'bg_diff_red': ['#f7d9b9', '217'],
  162. \ 'bg_visual_red': ['#efd2b3', '217'],
  163. \ 'bg_diff_blue': ['#dbddbf', '117'],
  164. \ 'bg_visual_blue': ['#d3d5b8', '117'],
  165. \ 'bg_visual_yellow': ['#f3deaa', '226'],
  166. \ 'bg_current_word': ['#ebdbb2', '227']
  167. \ }
  168. endif
  169. endif "}}}
  170. if a:foreground ==# 'material' "{{{
  171. if &background ==# 'dark'
  172. let palette2 = {
  173. \ 'fg0': ['#d4be98', '223'],
  174. \ 'fg1': ['#ddc7a1', '223'],
  175. \ 'red': ['#ea6962', '167'],
  176. \ 'orange': ['#e78a4e', '208'],
  177. \ 'yellow': ['#d8a657', '214'],
  178. \ 'green': ['#a9b665', '142'],
  179. \ 'aqua': ['#89b482', '108'],
  180. \ 'blue': ['#7daea3', '109'],
  181. \ 'purple': ['#d3869b', '175'],
  182. \ 'bg_red': ['#ea6962', '167'],
  183. \ 'bg_green': ['#a9b665', '142'],
  184. \ 'bg_yellow': ['#d8a657', '214']
  185. \ }
  186. else
  187. let palette2 = {
  188. \ 'fg0': ['#654735', '237'],
  189. \ 'fg1': ['#4f3829', '237'],
  190. \ 'red': ['#c14a4a', '88'],
  191. \ 'orange': ['#c35e0a', '130'],
  192. \ 'yellow': ['#b47109', '136'],
  193. \ 'green': ['#6c782e', '100'],
  194. \ 'aqua': ['#4c7a5d', '165'],
  195. \ 'blue': ['#45707a', '24'],
  196. \ 'purple': ['#945e80', '96'],
  197. \ 'bg_red': ['#ae5858', '88'],
  198. \ 'bg_green': ['#6f8352', '100'],
  199. \ 'bg_yellow': ['#a96b2c', '130']
  200. \ }
  201. endif "}}}
  202. elseif a:foreground ==# 'mix' "{{{
  203. if &background ==# 'dark'
  204. let palette2 = {
  205. \ 'fg0': ['#e2cca9', '223'],
  206. \ 'fg1': ['#e2cca9', '223'],
  207. \ 'red': ['#f2594b', '167'],
  208. \ 'orange': ['#f28534', '208'],
  209. \ 'yellow': ['#e9b143', '214'],
  210. \ 'green': ['#b0b846', '142'],
  211. \ 'aqua': ['#8bba7f', '108'],
  212. \ 'blue': ['#80aa9e', '109'],
  213. \ 'purple': ['#d3869b', '175'],
  214. \ 'bg_red': ['#db4740', '167'],
  215. \ 'bg_green': ['#b0b846', '142'],
  216. \ 'bg_yellow': ['#e9b143', '214']
  217. \ }
  218. else
  219. let palette2 = {
  220. \ 'fg0': ['#514036', '237'],
  221. \ 'fg1': ['#514036', '237'],
  222. \ 'red': ['#af2528', '88'],
  223. \ 'orange': ['#b94c07', '130'],
  224. \ 'yellow': ['#b4730e', '136'],
  225. \ 'green': ['#72761e', '100'],
  226. \ 'aqua': ['#477a5b', '165'],
  227. \ 'blue': ['#266b79', '24'],
  228. \ 'purple': ['#924f79', '96'],
  229. \ 'bg_red': ['#ae5858', '88'],
  230. \ 'bg_green': ['#6f8352', '100'],
  231. \ 'bg_yellow': ['#a96b2c', '130']
  232. \ }
  233. endif "}}}
  234. else "{{{
  235. if &background ==# 'dark'
  236. let palette2 = {
  237. \ 'fg0': ['#ebdbb2', '223'],
  238. \ 'fg1': ['#ebdbb2', '223'],
  239. \ 'red': ['#fb4934', '167'],
  240. \ 'orange': ['#fe8019', '208'],
  241. \ 'yellow': ['#fabd2f', '214'],
  242. \ 'green': ['#b8bb26', '142'],
  243. \ 'aqua': ['#8ec07c', '108'],
  244. \ 'blue': ['#83a598', '109'],
  245. \ 'purple': ['#d3869b', '175'],
  246. \ 'bg_red': ['#cc241d', '124'],
  247. \ 'bg_green': ['#b8bb26', '106'],
  248. \ 'bg_yellow': ['#fabd2f', '172']
  249. \ }
  250. else
  251. let palette2 = {
  252. \ 'fg0': ['#3c3836', '237'],
  253. \ 'fg1': ['#3c3836', '237'],
  254. \ 'red': ['#9d0006', '88'],
  255. \ 'orange': ['#af3a03', '130'],
  256. \ 'yellow': ['#b57614', '136'],
  257. \ 'green': ['#79740e', '100'],
  258. \ 'aqua': ['#427b58', '165'],
  259. \ 'blue': ['#076678', '24'],
  260. \ 'purple': ['#8f3f71', '96'],
  261. \ 'bg_red': ['#ae5858', '88'],
  262. \ 'bg_green': ['#6f8352', '100'],
  263. \ 'bg_yellow': ['#a96b2c', '130']
  264. \ }
  265. endif
  266. endif "}}}
  267. if &background ==# 'dark' "{{{
  268. let palette3 = {
  269. \ 'grey0': ['#7c6f64', '243'],
  270. \ 'grey1': ['#928374', '245'],
  271. \ 'grey2': ['#a89984', '246'],
  272. \ 'none': ['NONE', 'NONE']
  273. \ } "}}}
  274. else "{{{
  275. let palette3 = {
  276. \ 'grey0': ['#a89984', '246'],
  277. \ 'grey1': ['#928374', '245'],
  278. \ 'grey2': ['#7c6f64', '243'],
  279. \ 'none': ['NONE', 'NONE']
  280. \ }
  281. endif "}}}
  282. return extend(extend(extend(palette1, palette2), palette3), a:colors_override)
  283. endfunction "}}}
  284. function! gruvbox_material#highlight(group, fg, bg, ...) "{{{
  285. execute 'highlight' a:group
  286. \ 'guifg=' . a:fg[0]
  287. \ 'guibg=' . a:bg[0]
  288. \ 'ctermfg=' . a:fg[1]
  289. \ 'ctermbg=' . a:bg[1]
  290. \ 'gui=' . (a:0 >= 1 ?
  291. \ a:1 :
  292. \ 'NONE')
  293. \ 'cterm=' . (a:0 >= 1 ?
  294. \ a:1 :
  295. \ 'NONE')
  296. \ 'guisp=' . (a:0 >= 2 ?
  297. \ a:2[0] :
  298. \ 'NONE')
  299. endfunction "}}}
  300. function! gruvbox_material#syn_gen(path, last_modified, msg) "{{{
  301. " Generate the `after/syntax` directory.
  302. let full_content = join(readfile(a:path), "\n") " Get the content of `colors/gruvbox-material.vim`
  303. let syn_content = []
  304. let rootpath = gruvbox_material#syn_rootpath(a:path) " Get the path to place the `after/syntax` directory.
  305. call substitute(full_content, '" syn_begin.\{-}syn_end', '\=add(syn_content, submatch(0))', 'g') " Search for 'syn_begin.\{-}syn_end' (non-greedy) and put all the search results into a list.
  306. for content in syn_content
  307. let syn_list = []
  308. call substitute(matchstr(matchstr(content, 'syn_begin:.\{-}{{{'), ':.\{-}{{{'), '\(\w\|-\)\+', '\=add(syn_list, submatch(0))', 'g') " Get the file types. }}}}}}
  309. for syn in syn_list
  310. call gruvbox_material#syn_write(rootpath, syn, content) " Write the content.
  311. endfor
  312. endfor
  313. call gruvbox_material#syn_write(rootpath, 'text', "let g:gruvbox_material_last_modified = '" . a:last_modified . "'") " Write the last modified time to `after/syntax/text/gruvbox_material.vim`
  314. let syntax_relative_path = has('win32') ? '\after\syntax' : '/after/syntax'
  315. if a:msg ==# 'update'
  316. echohl WarningMsg | echom '[gruvbox-material] Updated ' . rootpath . syntax_relative_path | echohl None
  317. call gruvbox_material#ftplugin_detect(a:path)
  318. else
  319. echohl WarningMsg | echom '[gruvbox-material] Generated ' . rootpath . syntax_relative_path | echohl None
  320. execute 'set runtimepath+=' . fnamemodify(rootpath, ':p') . 'after'
  321. endif
  322. endfunction "}}}
  323. function! gruvbox_material#syn_write(rootpath, syn, content) "{{{
  324. " Write the content.
  325. let syn_path = a:rootpath . '/after/syntax/' . a:syn . '/gruvbox_material.vim' " The path of a syntax file.
  326. " create a new file if it doesn't exist
  327. if !filereadable(syn_path)
  328. call mkdir(a:rootpath . '/after/syntax/' . a:syn, 'p')
  329. call writefile([
  330. \ "if !exists('g:colors_name') || g:colors_name !=# 'gruvbox-material'",
  331. \ ' finish',
  332. \ 'endif'
  333. \ ], syn_path, 'a') " Abort if the current color scheme is not gruvbox-material.
  334. call writefile([
  335. \ "if index(g:gruvbox_material_loaded_file_types, '" . a:syn . "') ==# -1",
  336. \ " call add(g:gruvbox_material_loaded_file_types, '" . a:syn . "')",
  337. \ 'else',
  338. \ ' finish',
  339. \ 'endif'
  340. \ ], syn_path, 'a') " Abort if this file type has already been loaded.
  341. endif
  342. " If there is something like `call gruvbox_material#highlight()`, then add
  343. " code to initialize the palette and configuration.
  344. if matchstr(a:content, 'gruvbox_material#highlight') !=# ''
  345. call writefile([
  346. \ 'let s:configuration = gruvbox_material#get_configuration()',
  347. \ 'let s:palette = gruvbox_material#get_palette(s:configuration.background, s:configuration.foreground, s:configuration.colors_override)'
  348. \ ], syn_path, 'a')
  349. endif
  350. " Append the content.
  351. call writefile(split(a:content, "\n"), syn_path, 'a')
  352. " Add modeline.
  353. call writefile(['" vim: set sw=2 ts=2 sts=2 et tw=80 ft=vim fdm=marker fmr={{{,}}}:'], syn_path, 'a')
  354. endfunction "}}}
  355. function! gruvbox_material#syn_rootpath(path) "{{{
  356. " Get the directory where `after/syntax` is generated.
  357. if (matchstr(a:path, '^/usr/share') ==# '') " Return the plugin directory. The `after/syntax` directory should never be generated in `/usr/share`, even if you are a root user.
  358. return fnamemodify(a:path, ':p:h:h')
  359. else " Use vim home directory.
  360. if has('nvim')
  361. return stdpath('config')
  362. else
  363. return expand('~') . '/.vim'
  364. endif
  365. endif
  366. endfunction "}}}
  367. function! gruvbox_material#syn_newest(path, last_modified) "{{{
  368. " Determine whether the current syntax files are up to date by comparing the last modified time in `colors/gruvbox-material.vim` and `after/syntax/text/gruvbox_material.vim`.
  369. let rootpath = gruvbox_material#syn_rootpath(a:path)
  370. execute 'source ' . rootpath . '/after/syntax/text/gruvbox_material.vim'
  371. return a:last_modified ==# g:gruvbox_material_last_modified ? 1 : 0
  372. endfunction "}}}
  373. function! gruvbox_material#syn_clean(path, msg) "{{{
  374. " Clean the `after/syntax` directory.
  375. let rootpath = gruvbox_material#syn_rootpath(a:path)
  376. " Remove `after/syntax/**/gruvbox_material.vim`.
  377. let file_list = split(globpath(rootpath, 'after/syntax/**/gruvbox_material.vim'), "\n")
  378. for file in file_list
  379. call delete(file)
  380. endfor
  381. " Remove empty directories.
  382. let dir_list = split(globpath(rootpath, 'after/syntax/*'), "\n")
  383. for dir in dir_list
  384. if globpath(dir, '*') ==# ''
  385. call delete(dir, 'd')
  386. endif
  387. endfor
  388. if globpath(rootpath . '/after/syntax', '*') ==# ''
  389. call delete(rootpath . '/after/syntax', 'd')
  390. endif
  391. if globpath(rootpath . '/after', '*') ==# ''
  392. call delete(rootpath . '/after', 'd')
  393. endif
  394. if a:msg
  395. let syntax_relative_path = has('win32') ? '\after\syntax' : '/after/syntax'
  396. echohl WarningMsg | echom '[gruvbox-material] Cleaned ' . rootpath . syntax_relative_path | echohl None
  397. endif
  398. endfunction "}}}
  399. function! gruvbox_material#syn_exists(path) "{{{
  400. return filereadable(gruvbox_material#syn_rootpath(a:path) . '/after/syntax/text/gruvbox_material.vim')
  401. endfunction "}}}
  402. function! gruvbox_material#ftplugin_detect(path) "{{{
  403. " Check if /after/ftplugin exists.
  404. " This directory is generated in earlier versions, users may need to manually clean it.
  405. let rootpath = gruvbox_material#syn_rootpath(a:path)
  406. if filereadable(gruvbox_material#syn_rootpath(a:path) . '/after/ftplugin/text/gruvbox_material.vim')
  407. let ftplugin_relative_path = has('win32') ? '\after\ftplugin' : '/after/ftplugin'
  408. echohl WarningMsg | echom '[gruvbox-material] Detected ' . rootpath . ftplugin_relative_path | echohl None
  409. echohl WarningMsg | echom '[gruvbox-material] This directory is no longer used, you may need to manually delete it.' | echohl None
  410. endif
  411. endfunction "}}}
  412. " vim: set sw=2 ts=2 sts=2 et tw=80 ft=vim fdm=marker fmr={{{,}}}: