6 " Generates a modeline from current settings.
8 " Last Change: 27-Jun-2008.
9 " Maintainer: Shuhei Kubota <chimachima@gmail.com>
12 " execute ':Modeliner'.
13 " Then a modeline is generated.
15 " The modeline will either be appended next to the current line or replace
18 " If you want to customize option, modify g:Modeliner_format.
20 if !exists('g:Modeliner_format')
21 let g:Modeliner_format = 'et ff= fenc= sts= sw= ts='
24 " if the type of a option is NOT 'boolean' (see :help 'option-name'),
25 " append '=' to the end of each option.
29 "[text] vi: tw=80 noai
30 "[text] vim:tw=80 noai
33 "[text] vim: set tw=80 noai:[text]
34 "[text] vim: se tw=80 noai:[text]
35 "[text] vim:set tw=80 noai:[text]
36 " vim: set tw=80 noai: [text]
40 command! Modeliner call <SID>Modeliner_execute()
43 " to retrieve the position
44 let s:Modeline_SEARCH_PATTERN = '\svi:\|vim:\|ex:'
45 " to extract options from existing modeline
46 let s:Modeline_EXTRACT_PATTERN = '\v(.*)\s+(vi|vim|ex):\s*(set?\s+)?(.+)' " very magic
48 "let s:Modeline_EXTRACT_OPTPATTERN1 = '\v(.+)' " very magic
50 let s:Modeline_EXTRACT_OPTPATTERN2 = '\v(.+):(.*)' " very magic
53 function! s:Modeliner_execute()
56 " find existing modeline, and determine the insert position
57 let info = s:SearchExistingModeline()
59 " parse g:Modeliner_format and join options with them
60 let extractedOptStr = g:Modeliner_format . ' ' . info.optStr
61 let extractedOptStr = substitute(extractedOptStr, '[ ,:]\+', ' ', 'g')
62 let extractedOptStr = substitute(extractedOptStr, '=\S*', '=', 'g')
63 let extractedOptStr = substitute(extractedOptStr, 'no\(.\+\)', '\1', 'g')
64 let opts = sort(split(extractedOptStr))
65 "echom 'opt(list): ' . join(opts, ', ')
70 if o == prevO | continue | endif
73 if stridx(o, '=') != -1
74 " let optExpr = 'ts=' . &ts
75 execute 'let optExpr = "' . o . '" . &' . strpart(o, 0, strlen(o) - 1)
77 " let optExpr = (&et ? '' : 'no') . 'et'
78 execute 'let optExpr = (&' . o . '? "" : "no") . "' . o . '"'
81 let optStr = optStr . ' ' . optExpr
85 let modeline = s:Commentify(optStr)
87 let modeline = info.firstText . ' vim: set' . optStr . ' :' . info.lastText
93 "modeline FOUND -> replace the modeline
95 "show the existing modeline
96 let orgLine = line('.')
98 call cursor(info.lineNum, 1)
103 "if confirm('Are you sure to overwrite this existing modeline?', "&Yes\n&No", 1) == 1
104 echo 'Are you sure to overwrite this existing modeline? [y/N]'
105 if char2nr(tolower(nr2char(getchar()))) == char2nr('y')
106 call setline(info.lineNum, modeline)
108 "show the modeline being changed
109 if (info.lineNum != line('.')) && (info.lineNum != line('.') + 1)
115 "back to the previous position
117 execute "normal \<ESC>"
118 call cursor(orgLine, orgCol)
120 "modeline NOT found -> append new modeline
121 call append('.', modeline)
127 function! s:Commentify(s)
128 if exists('g:NERDMapleader') " NERDCommenter
129 let result = b:left . ' vim: set' . a:s . ' : ' . b:right
131 let result = substitute(&commentstring, '%s', ' vim: set' . a:s . ' : ', '')
138 function! s:SearchExistingModeline()
139 let info = {'lineNum':0, 'text':'', 'firstText':'', 'lastText':'', 'optStr':''}
144 call add(candidates, line('.'))
145 " user may position the cursor to previous line...
146 call add(candidates, line('.') + 1)
148 while cnt < &modelines
150 call add(candidates, cnt + 1)
152 call add(candidates, line('$') - cnt)
159 let text = getline(lineNum)
161 if match(text, s:Modeline_SEARCH_PATTERN) != -1
162 let info.lineNum = lineNum
170 "echom 'modeline: ' info.lineNum . ' ' . info.text
172 let info.firstText = substitute(info.text, s:Modeline_EXTRACT_PATTERN, '\1', '')
174 let isSecondForm = (strlen(substitute(info.text, s:Modeline_EXTRACT_PATTERN, '\3', '')) != 0)
175 "echom 'form : ' . string(isSecondForm + 1)
177 let info.lastText = ''
178 let info.optStr = substitute(info.text, s:Modeline_EXTRACT_PATTERN, '\4', '')
180 let info.lastText = substitute(
181 \ substitute(info.text, s:Modeline_EXTRACT_PATTERN, '\4', ''),
182 \ s:Modeline_EXTRACT_OPTPATTERN2,
185 let info.optStr = substitute(
186 \ substitute(info.text, s:Modeline_EXTRACT_PATTERN, '\4', ''),
187 \ s:Modeline_EXTRACT_OPTPATTERN2,
193 "echom 'firstText: ' . info.firstText
194 "echom 'lastText: ' . info.lastText
195 "echom 'optStr: ' . info.optStr
201 function! s:ExtractOptionStringFromModeline(text)
204 let info.firstText = substitute(a:text, s:Modeline_EXTRACT_PATTERN, '\1', '')
206 let isSecondForm = (strlen(substitute(a:text, s:Modeline_EXTRACT_PATTERN, '\3', '') != 0)
208 let info.lastText = ''
209 let info.optStr = substitute(a:text, s:Modeline_EXTRACT_PATTERN, '\2', '')
211 let info.lastText = substitute(
212 \ substitute(a:text, s:Modeline_EXTRACT_PATTERN, '\4', ''),
213 \ s:Modeline_EXTRACT_OPTPATTERN2,
216 let info.optStr = substitute(
217 \ substitute(a:text, s:Modeline_EXTRACT_PATTERN, '\4', ''),
218 \ s:Modeline_EXTRACT_OPTPATTERN2,
226 " vim: set et fenc=utf-8 ff=unix sts=4 sw=4 ts=4 :