aboutsummaryrefslogtreecommitdiff
path: root/vim/ftplugin/coffee.vim
blob: 12ae3f0bfdad16ad45834e305681b9a736104e5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
" Language:    CoffeeScript
" Maintainer:  Mick Koch <kchmck@gmail.com>
" URL:         http://github.com/kchmck/vim-coffee-script
" License:     WTFPL

if exists("b:did_ftplugin")
  finish
endif

let b:did_ftplugin = 1

setlocal formatoptions-=t formatoptions+=croql
setlocal comments=:#
setlocal commentstring=#\ %s
setlocal omnifunc=javascriptcomplete#CompleteJS

" Enable CoffeeMake if it won't overwrite any settings.
if !len(&l:makeprg)
  compiler coffee
endif

" Reset the global variables used by CoffeeCompile.
function! s:CoffeeCompileResetVars()
  " Position in the source buffer
  let s:coffee_compile_src_buf = -1
  let s:coffee_compile_src_pos = []

  " Position in the CoffeeCompile buffer
  let s:coffee_compile_buf = -1
  let s:coffee_compile_win = -1
  let s:coffee_compile_pos = []

  " If CoffeeCompile is watching a buffer
  let s:coffee_compile_watch = 0
endfunction

" Save the cursor position when moving to and from the CoffeeCompile buffer.
function! s:CoffeeCompileSavePos()
  let buf = bufnr('%')
  let pos = getpos('.')

  if buf == s:coffee_compile_buf
    let s:coffee_compile_pos = pos
  else
    let s:coffee_compile_src_buf = buf
    let s:coffee_compile_src_pos = pos
  endif
endfunction

" Restore the cursor to the source buffer.
function! s:CoffeeCompileRestorePos()
  let win = bufwinnr(s:coffee_compile_src_buf)

  if win != -1
    exec win 'wincmd w'
    call setpos('.', s:coffee_compile_src_pos)
  endif
endfunction

" Close the CoffeeCompile buffer and clean things up.
function! s:CoffeeCompileClose()
  silent! autocmd! CoffeeCompileAuPos
  silent! autocmd! CoffeeCompileAuWatch

  call s:CoffeeCompileRestorePos()
  call s:CoffeeCompileResetVars()
endfunction

" Update the CoffeeCompile buffer given some input lines.
function! s:CoffeeCompileUpdate(startline, endline)
  let input = join(getline(a:startline, a:endline), "\n")

  " Coffee doesn't like empty input.
  if !len(input)
    return
  endif

  " Compile input.
  let output = system('coffee -scb 2>&1', input)

  " Move to the CoffeeCompile buffer.
  exec s:coffee_compile_win 'wincmd w'

  " Replace buffer contents with new output and delete the last empty line.
  setlocal modifiable
    exec '% delete _'
    put! =output
    exec '$ delete _'
  setlocal nomodifiable

  " Highlight as JavaScript if there is no compile error.
  if v:shell_error
    setlocal filetype=
  else
    setlocal filetype=javascript
  endif

  " Restore the cursor in the compiled output.
  call setpos('.', s:coffee_compile_pos)
endfunction

" Update the CoffeeCompile buffer with the whole source buffer and restore the
" cursor.
function! s:CoffeeCompileWatchUpdate()
  call s:CoffeeCompileSavePos()
  call s:CoffeeCompileUpdate(1, '$')
  call s:CoffeeCompileRestorePos()
endfunction

" Peek at compiled CoffeeScript in a scratch buffer. We handle ranges like this
" to prevent the cursor from being moved (and its position saved) before the
" function is called.
function! s:CoffeeCompile(startline, endline, args)
  " Don't compile the CoffeeCompile buffer.
  if bufnr('%') == s:coffee_compile_buf
    return
  endif

  " Parse arguments.
  let watch = a:args =~ '\<watch\>'
  let unwatch = a:args =~ '\<unwatch\>'
  let size = str2nr(matchstr(a:args, '\<\d\+\>'))
   
  " Determine default split direction.
  if exists("g:coffee_compile_vert")
    let vert = 1
  else
    let vert = a:args =~ '\<vert\%[ical]\>'
  endif

  " Remove any watch listeners.
  silent! autocmd! CoffeeCompileAuWatch

  " If just unwatching, don't compile.
  if unwatch
    let s:coffee_compile_watch = 0
    return
  endif

  if watch
    let s:coffee_compile_watch = 1
  endif

  call s:CoffeeCompileSavePos()

  " Build the CoffeeCompile buffer if it doesn't exist.
  if s:coffee_compile_buf == -1
    let src_win = bufwinnr(s:coffee_compile_src_buf)

    " Create the new window and resize it.
    if vert
      let width = size ? size : winwidth(src_win) / 2

      vertical new
      exec 'vertical resize' width
    else
      " Try to guess the compiled output's height.
      let height = size ? size : min([winheight(src_win) / 2,
      \                               a:endline - a:startline + 2])

      botright new
      exec 'resize' height
    endif

    " Set up scratch buffer.
    setlocal bufhidden=wipe buftype=nofile
    setlocal nobuflisted nomodifiable noswapfile nowrap

    autocmd BufWipeout <buffer> call s:CoffeeCompileClose()
    nnoremap <buffer> <silent> q :hide<CR>

    " Save the cursor position on each buffer switch.
    augroup CoffeeCompileAuPos
      autocmd BufEnter,BufLeave * call s:CoffeeCompileSavePos()
    augroup END

    let s:coffee_compile_buf = bufnr('%')
    let s:coffee_compile_win = bufwinnr(s:coffee_compile_buf)
  endif

  " Go back to the source buffer and do the initial compile.
  call s:CoffeeCompileRestorePos()

  if s:coffee_compile_watch
    call s:CoffeeCompileWatchUpdate()

    augroup CoffeeCompileAuWatch
      autocmd InsertLeave <buffer> call s:CoffeeCompileWatchUpdate()
    augroup END
  else
    call s:CoffeeCompileUpdate(a:startline, a:endline)
  endif
endfunction

" Complete arguments for the CoffeeCompile command.
function! s:CoffeeCompileComplete(arg, cmdline, cursor)
  let args = ['unwatch', 'vertical', 'watch']

  if !len(a:arg)
    return args
  endif

  let match = '^' . a:arg

  for arg in args
    if arg =~ match
      return [arg]
    endif
  endfor
endfunction

" Don't let new windows overwrite the CoffeeCompile variables.
if !exists("s:coffee_compile_buf")
  call s:CoffeeCompileResetVars()
endif

" Peek at compiled CoffeeScript.
command! -range=% -bar -nargs=* -complete=customlist,s:CoffeeCompileComplete
\        CoffeeCompile call s:CoffeeCompile(<line1>, <line2>, <q-args>)
" Run some CoffeeScript.
command! -range=% -bar CoffeeRun <line1>,<line2>:w !coffee -s