1
2 Author:peter@peterodding.com
3 Last Change:
4 URL:http://peterodding.com/code/vim/publish/
5
6 function! publish#resolve_files(directory, pathnames)
7
8
9
10 let resolved_files = {}
11 for pathname in a:pathnames
12 let pathname = xolox#path#merge(a:directory, pathname)
13 let absolute = fnamemodify(pathname, ':p')
14 let resolved_files[resolve(absolute)] = absolute
15 endfor
16 return resolved_files
17 endfunction
18
19 function! publish#update_tags(pathnames)
20
21 http://peterodding.com/code/vim/easytags/
22 if exists('g:loaded_easytags')
23 call easytags#update(1, 0, a:pathnames)
24 endif
25 endfunction
26
27 function! publish#find_tags(files_to_publish)
28
29 taglist()
30
31 let start = xolox#timer#start()
32 let num_duplicates = 0
33 let tags_to_publish = {}
34 let s:cached_contents = {}
35 for entry in taglist('.')
36 let pathname = xolox#path#absolute(entry.filename)
37 if has_key(a:files_to_publish, pathname) && s:pattern_to_lnum(entry, pathname)
38 if !has_key(tags_to_publish, entry.name)
39 let tags_to_publish[entry.name] = entry
40 else
41 let num_duplicates += 1
42 let other = tags_to_publish[entry.name]
43 if entry.filename == other.filename && entry.lnum < other.lnum
44 let tags_to_publish[entry.name] = entry
45 endif
46 if num_duplicates <= 3
47 let tag_name = string(entry.name)
48 let this_path = string(entry.filename)
49 let other_path = string(other.filename)
50 let msg = "publish.vim: Ignoring duplicate tag %s! (duplicate is in %s, first was in %s)"
51 call xolox#warning(msg, tag_name, this_path, other_path)
52 endif
53 endif
54 endif
55 endfor
56 if num_duplicates > 3
57 let more = num_duplicates - 3
58 let msg = "publish.vim: Ignored %s more duplicate tag%s!"
59 call xolox#warning(msg, more, more == 1 ? '' : 's')
60 endif
61 unlet s:cached_contents
62 let msg = "publish.vim: Found %i tag%s to publish in %s."
63 let numtags = len(tags_to_publish)
64 call xolox#timer#stop(msg, numtags, numtags != 1 ? 's' : '', start)
65 return tags_to_publish
66 endfunction
67
68 function! s:pattern_to_lnum(entry, pathname)
69
70
71
72
73 if a:entry.cmd =~ '^\d\+$'
74 let a:entry.lnum = a:entry.cmd + 0
75 return 1
76 else
77 if !has_key(s:cached_contents, a:pathname)
78 let contents = readfile(a:pathname)
79 let s:cached_contents[a:pathname] = contents
80 else
81 let contents = s:cached_contents[a:pathname]
82 endif
83 :help
84 let pattern = a:entry.cmd
85 let pattern = matchstr(pattern, '^/^\zs.*\ze$/$')
86 let pattern = '^' . xolox#escape#pattern(pattern) . '$'
87 try
88 let index = match(contents, pattern)
89 catch
90 throw "Failed pattern: " . string(pattern)
91 endtry
92 if index >= 0
93 let a:entry.lnum = index + 1
94 return 1
95 endif
96 endif
97 endfunction
98
99 function! publish#create_subst_cmd(tags_to_publish)
100 :substitute
101
102
103
104
105
106
107 let patterns = []
108 let slfunctions = []
109 for name in keys(a:tags_to_publish)
110 let entry = a:tags_to_publish[name]
111 if get(entry, 'language') == 'Vim'
112 let is_slfunc = '\s\(s:\|<[Ss][Ii][Dd]>\)' . xolox#escape#pattern(name) . '\s*('
113 if get(entry, 'cmd') =~ is_slfunc
114 call add(slfunctions, xolox#escape#pattern(name))
115 continue
116 endif
117 endif
118 call add(patterns, xolox#escape#pattern(name))
119 endfor
120 call insert(patterns, '\%(\%(<[Ss][Ii][Dd]>\|s:\)\%(' . join(slfunctions, '\|') . '\)\)')
121 let tag_names_pattern = escape(join(patterns, '\|'), '/')
122
123 return '%s/[A-Za-z0-9_]\@<!\%(' . tag_names_pattern . '\)[A-Za-z0-9_]\@!/\=s:ConvertTagToLink(submatch(0))/eg'
124 endfunction
125
126 function! publish#munge_syntax_items()
127
128
129 if &filetype == 'vim'
130 syntax match vimFuncName /\<s:\w\+\>/ containedin=vim.*
131 syntax match vimFuncName /\c<Sid>\w\+\>/ containedin=vim.*
132 endif
133 endfunction
134
135 function! publish#rsync_check(target)
136 let start = xolox#timer#start()
137 let result = ''
138 let matches = matchlist(a:target, '^sftp://\([^/]\+\)\(.*\)$')
139 if len(matches) >= 3
140 let host = matches[1]
141 let path = substitute(matches[2], '^/', '', '')
142 call system('rsync --version')
143 if !v:shell_error
144 call system('ssh ' . host . ' rsync --version')
145 if !v:shell_error
146 let result = host . ':' . path
147 endif
148 endif
149 endif
150 call xolox#timer#stop("publish.vim: Checked rsync support in %s.", start)
151 return result
152 endfunction
153
154 function! publish#run_rsync(target, tempdir)
155 let start = xolox#timer#start()
156 let target = fnameescape(a:target . '/')
157 let tempdir = fnameescape(a:tempdir . '/')
158 call xolox#message("publish.vim: Uploading files to %s using rsync.", a:target)
159 execute '!rsync -vr' tempdir target
160 call xolox#timer#stop("publish.vim: Finished uploading in %s.", start)
161 if v:shell_error
162 throw "publish.vim: Failed to run rsync!"
163 endif
164 endfunction
165
166 function! publish#create_dirs(target_path)
167
168
169
170 if a:target_path !~ '://'
171 let current_directory = fnamemodify(a:target_path, ':h')
172 if !isdirectory(current_directory)
173 silent! call mkdir(current_directory, 'p')
174 if !isdirectory(current_directory)
175 let msg = "Failed to create directory %s! What now?"
176 if confirm(printf(msg, string(current_directory)), "&Abort\n&Ignore") == 1
177 let msg = "publish.vim: Failed to create %s, aborting .."
178 call xolox#warning(msg, string(current_directory))
179 return 0
180 else
181 let msg = "publish.vim: Failed to create %s, ignoring .."
182 call xolox#warning(msg, string(current_directory))
183 continue
184 endif
185 endif
186 endif
187 endif
188 return 1
189 endfunction
190
191 function! publish#prep_env(enable)
192
193
194
195
196 augroup PluginPublish
197 autocmd!
198 if a:enable
199 autocmd SwapExists * let v:swapchoice = 'e'
200 endif
201 augroup END
202
203
204 if a:enable
205 let s:more_save = &more
206 set nomore
207 else
208 let &more = s:more_save
209 endif
210
211
212 :write
213 :noautocmd:write
214
215
216 if a:enable
217 let s:ei_save = &eventignore
218 set eventignore=BufWritePre
219 else
220 let &eventignore = s:ei_save
221 endif
222
223
224
225 if a:enable
226 let s:mls_save = &modelines
227 set modelines=0
228 else
229 let &modelines = s:mls_save
230 endif
231
232
233
234
235
236
237
238 if a:enable
239 let s:hif_save = exists('g:html_ignore_folding') ? g:html_ignore_folding : 0
240 let s:hnl_save = exists('g:html_number_lines') ? g:html_number_lines : 0
241 let s:huc_save = exists('g:html_use_css') ? g:html_use_css : 0
242 let g:html_ignore_folding = 1
243 let g:html_number_lines = 1
244 let g:html_use_css = 1
245 else
246 let g:html_ignore_folding = s:hif_save
247 let g:html_number_lines = s:hnl_save
248 let g:html_use_css = s:huc_save
249 endif
250
251 endfunction
252
253 function! publish#customize_html(page_title)
254
255
256 silent keepjumps %s@<title>\zs.*\ze</title>@\=publish#html_encode(a:page_title)@e
257
258
259
260 let custom_css = "\nhtml, body, pre { margin: 0; padding: 0; }"
261 let custom_css .= "\na:link, a:visited { color: inherit; text-decoration: none; }"
262 let custom_css .= "\npre:hover a:link, pre:hover a:visited { text-decoration: underline; }"
263 let custom_css .= "\na:link span, a:visited span { text-decoration: inherit; }"
264 let custom_css .= "\n.lnr a:link, .lnr a:visited { text-decoration: none !important; }"
265 silent keepjumps %s@\ze\_s\+-->\_s\+</style>@\= "\n" . custom_css@e
266
267
268 silent keepjumps %s@<span class="lnr">\zs\s*\(\d\+\)\s*\ze</span>@<a name="l\1" href="#l\1">\0</a>@eg
269
270 endfunction
271
272 function! publish#html_encode(s)
273 let s = substitute(a:s, '&', '\&', 'g')
274 let s = substitute(s, '<', '\<', 'g')
275 let s = substitute(s, '>', '\>', 'g')
276 return s
277 endfunction
278
279