]>
Commit | Line | Data |
---|---|---|
1 | " Language: CoffeeScript | |
2 | " Maintainer: Mick Koch <kchmck@gmail.com> | |
3 | " URL: http://github.com/kchmck/vim-coffee-script | |
4 | " License: WTFPL | |
5 | ||
6 | if exists("b:did_ftplugin") | |
7 | finish | |
8 | endif | |
9 | ||
10 | let b:did_ftplugin = 1 | |
11 | ||
12 | setlocal formatoptions-=t formatoptions+=croql | |
13 | setlocal comments=:# | |
14 | setlocal commentstring=#\ %s | |
15 | ||
16 | setlocal errorformat=Error:\ In\ %f\\,\ %m\ on\ line\ %l, | |
17 | \Error:\ In\ %f\\,\ Parse\ error\ on\ line\ %l:\ %m, | |
18 | \SyntaxError:\ In\ %f\\,\ %m, | |
19 | \%-G%.%# | |
20 | ||
21 | " Extra options passed to CoffeeMake | |
22 | if !exists("coffee_make_options") | |
23 | let coffee_make_options = "" | |
24 | endif | |
25 | ||
26 | " Update `makeprg` for the current filename. This is needed to support filenames | |
27 | " with spaces and quotes while also supporting generic `make`. | |
28 | function! s:SetMakePrg() | |
29 | let &l:makeprg = "coffee -c " . g:coffee_make_options . ' $* ' | |
30 | \ . fnameescape(expand('%')) | |
31 | endfunction | |
32 | ||
33 | " Set `makeprg` initially. | |
34 | call s:SetMakePrg() | |
35 | " Set `makeprg` on rename. | |
36 | autocmd BufFilePost,BufWritePost,FileWritePost <buffer> call s:SetMakePrg() | |
37 | ||
38 | " Reset the global variables used by CoffeeCompile. | |
39 | function! s:CoffeeCompileResetVars() | |
40 | " Position in the source buffer | |
41 | let s:coffee_compile_src_buf = -1 | |
42 | let s:coffee_compile_src_pos = [] | |
43 | ||
44 | " Position in the CoffeeCompile buffer | |
45 | let s:coffee_compile_buf = -1 | |
46 | let s:coffee_compile_win = -1 | |
47 | let s:coffee_compile_pos = [] | |
48 | ||
49 | " If CoffeeCompile is watching a buffer | |
50 | let s:coffee_compile_watch = 0 | |
51 | endfunction | |
52 | ||
53 | " Save the cursor position when moving to and from the CoffeeCompile buffer. | |
54 | function! s:CoffeeCompileSavePos() | |
55 | let buf = bufnr('%') | |
56 | let pos = getpos('.') | |
57 | ||
58 | if buf == s:coffee_compile_buf | |
59 | let s:coffee_compile_pos = pos | |
60 | else | |
61 | let s:coffee_compile_src_buf = buf | |
62 | let s:coffee_compile_src_pos = pos | |
63 | endif | |
64 | endfunction | |
65 | ||
66 | " Restore the cursor to the source buffer. | |
67 | function! s:CoffeeCompileRestorePos() | |
68 | let win = bufwinnr(s:coffee_compile_src_buf) | |
69 | ||
70 | if win != -1 | |
71 | exec win 'wincmd w' | |
72 | call setpos('.', s:coffee_compile_src_pos) | |
73 | endif | |
74 | endfunction | |
75 | ||
76 | " Close the CoffeeCompile buffer and clean things up. | |
77 | function! s:CoffeeCompileClose() | |
78 | silent! autocmd! CoffeeCompileAuPos | |
79 | silent! autocmd! CoffeeCompileAuWatch | |
80 | ||
81 | call s:CoffeeCompileRestorePos() | |
82 | call s:CoffeeCompileResetVars() | |
83 | endfunction | |
84 | ||
85 | " Update the CoffeeCompile buffer given some input lines. | |
86 | function! s:CoffeeCompileUpdate(startline, endline) | |
87 | let input = join(getline(a:startline, a:endline), "\n") | |
88 | ||
89 | " Coffee doesn't like empty input. | |
90 | if !len(input) | |
91 | return | |
92 | endif | |
93 | ||
94 | " Compile input. | |
95 | let output = system('coffee -scb 2>&1', input) | |
96 | ||
97 | " Move to the CoffeeCompile buffer. | |
98 | exec s:coffee_compile_win 'wincmd w' | |
99 | ||
100 | " Replace buffer contents with new output and delete the last empty line. | |
101 | setlocal modifiable | |
102 | exec '% delete _' | |
103 | put! =output | |
104 | exec '$ delete _' | |
105 | setlocal nomodifiable | |
106 | ||
107 | " Highlight as JavaScript if there is no compile error. | |
108 | if v:shell_error | |
109 | setlocal filetype= | |
110 | else | |
111 | setlocal filetype=javascript | |
112 | endif | |
113 | ||
114 | " Restore the cursor in the compiled output. | |
115 | call setpos('.', s:coffee_compile_pos) | |
116 | endfunction | |
117 | ||
118 | " Update the CoffeeCompile buffer with the whole source buffer and restore the | |
119 | " cursor. | |
120 | function! s:CoffeeCompileWatchUpdate() | |
121 | call s:CoffeeCompileSavePos() | |
122 | call s:CoffeeCompileUpdate(1, '$') | |
123 | call s:CoffeeCompileRestorePos() | |
124 | endfunction | |
125 | ||
126 | " Peek at compiled CoffeeScript in a scratch buffer. We handle ranges like this | |
127 | " to prevent the cursor from being moved (and its position saved) before the | |
128 | " function is called. | |
129 | function! s:CoffeeCompile(startline, endline, args) | |
130 | " Don't compile the CoffeeCompile buffer. | |
131 | if bufnr('%') == s:coffee_compile_buf | |
132 | return | |
133 | endif | |
134 | ||
135 | " Parse arguments. | |
136 | let watch = a:args =~ '\<watch\>' | |
137 | let unwatch = a:args =~ '\<unwatch\>' | |
138 | let vert = a:args =~ '\<vert\%[ical]\>' | |
139 | let size = str2nr(matchstr(a:args, '\<\d\+\>')) | |
140 | ||
141 | " Remove any watch listeners. | |
142 | silent! autocmd! CoffeeCompileAuWatch | |
143 | ||
144 | " If just unwatching, don't compile. | |
145 | if unwatch | |
146 | let s:coffee_compile_watch = 0 | |
147 | return | |
148 | endif | |
149 | ||
150 | if watch | |
151 | let s:coffee_compile_watch = 1 | |
152 | endif | |
153 | ||
154 | call s:CoffeeCompileSavePos() | |
155 | ||
156 | " Build the CoffeeCompile buffer if it doesn't exist. | |
157 | if s:coffee_compile_buf == -1 | |
158 | let src_win = bufwinnr(s:coffee_compile_src_buf) | |
159 | ||
160 | " Create the new window and resize it. | |
161 | if vert | |
162 | let width = size ? size : winwidth(src_win) / 2 | |
163 | ||
164 | vertical new | |
165 | exec 'vertical resize' width | |
166 | else | |
167 | " Try to guess the compiled output's height. | |
168 | let height = size ? size : min([winheight(src_win) / 2, | |
169 | \ a:endline - a:startline + 2]) | |
170 | ||
171 | botright new | |
172 | exec 'resize' height | |
173 | endif | |
174 | ||
175 | " Set up scratch buffer. | |
176 | setlocal bufhidden=wipe buftype=nofile | |
177 | setlocal nobuflisted nomodifiable noswapfile nowrap | |
178 | ||
179 | autocmd BufWipeout <buffer> call s:CoffeeCompileClose() | |
180 | nnoremap <buffer> <silent> q :hide<CR> | |
181 | ||
182 | " Save the cursor position on each buffer switch. | |
183 | augroup CoffeeCompileAuPos | |
184 | autocmd BufEnter,BufLeave * call s:CoffeeCompileSavePos() | |
185 | augroup END | |
186 | ||
187 | let s:coffee_compile_buf = bufnr('%') | |
188 | let s:coffee_compile_win = bufwinnr(s:coffee_compile_buf) | |
189 | endif | |
190 | ||
191 | " Go back to the source buffer and do the initial compile. | |
192 | call s:CoffeeCompileRestorePos() | |
193 | ||
194 | if s:coffee_compile_watch | |
195 | call s:CoffeeCompileWatchUpdate() | |
196 | ||
197 | augroup CoffeeCompileAuWatch | |
198 | autocmd InsertLeave <buffer> call s:CoffeeCompileWatchUpdate() | |
199 | augroup END | |
200 | else | |
201 | call s:CoffeeCompileUpdate(a:startline, a:endline) | |
202 | endif | |
203 | endfunction | |
204 | ||
205 | " Complete arguments for the CoffeeCompile command. | |
206 | function! s:CoffeeCompileComplete(arg, cmdline, cursor) | |
207 | let args = ['unwatch', 'vertical', 'watch'] | |
208 | ||
209 | if !len(a:arg) | |
210 | return args | |
211 | endif | |
212 | ||
213 | let match = '^' . a:arg | |
214 | ||
215 | for arg in args | |
216 | if arg =~ match | |
217 | return [arg] | |
218 | endif | |
219 | endfor | |
220 | endfunction | |
221 | ||
222 | " Don't let new windows overwrite the CoffeeCompile variables. | |
223 | if !exists("s:coffee_compile_buf") | |
224 | call s:CoffeeCompileResetVars() | |
225 | endif | |
226 | ||
227 | " Peek at compiled CoffeeScript. | |
228 | command! -range=% -bar -nargs=* -complete=customlist,s:CoffeeCompileComplete | |
229 | \ CoffeeCompile call s:CoffeeCompile(<line1>, <line2>, <q-args>) | |
230 | " Compile the current file. | |
231 | command! -bang -bar -nargs=* CoffeeMake make<bang> <args> | |
232 | " Run some CoffeeScript. | |
233 | command! -range=% -bar CoffeeRun <line1>,<line2>:w !coffee -s |