1 "SuperCollider/Vim interaction scripts
2 "Copyright 2007 Alex Norman
4 "This file is part of SCVIM.
6 "SCVIM is free software: you can redistribute it and/or modify
7 "it under the terms of the GNU General Public License as published by
8 "the Free Software Foundation, either version 3 of the License, or
9 "(at your option) any later version.
11 "SCVIM is distributed in the hope that it will be useful,
12 "but WITHOUT ANY WARRANTY; without even the implied warranty of
13 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 "GNU General Public License for more details.
16 "You should have received a copy of the GNU General Public License
17 "along with SCVIM. If not, see <http://www.gnu.org/licenses/>.
21 "if exists("$SCVIM_DIR") == 0
22 " echo "$SCVIM_DIR must be defined for SCVIM to work"
27 "source the syntax file as it can change
28 "so $SCVIM_DIR/syntax/supercollider.vim
29 runtime! syntax/supercollider.vim
31 if exists("loaded_scvim") || &cp
36 "first if SCVIM_CACHE_DIR is defined, use that,
37 "otherwise use ~/.scvim
38 if exists("$SCVIM_CACHE_DIR")
39 let s:scvim_cache_dir = $SCVIM_CACHE_DIR
41 let s:scvim_cache_dir = $HOME . "/.scvim"
42 let $SCVIM_CACHE_DIR = s:scvim_cache_dir
45 "source the scvimrc file if it exists
46 "if filereadable($HOME . "/.scvimrc")
47 " source $HOME/.scvimrc
51 set runtimepath+=$SCVIM_CACHE_DIR
53 if exists("g:sclangKillOnExit")
54 let s:sclangKillOnExit = g:sclangKillOnExit
56 let s:sclangKillOnExit = 1
59 if exists("g:sclangPipeLoc")
60 let s:sclangPipeLoc = g:sclangPipeLoc
62 let s:sclangPipeLoc = "/tmp/sclang-pipe"
64 let $SCVIM_PIPE_LOC = s:sclangPipeLoc
66 if exists("g:sclangPipeAppPidLoc")
67 let s:sclangPipeAppPidLoc = g:sclangPipeAppPidLoc
69 let s:sclangPipeAppPidLoc = "/tmp/sclangpipe_app-pid"
71 let $SCVIM_PIPE_PID_LOC = s:sclangPipeAppPidLoc
73 if exists("g:sclangTerm")
74 let s:sclangTerm = g:sclangTerm
76 let s:sclangTerm = "xterm -e"
79 if exists("g:sclangPipeApp")
80 let s:sclangPipeApp = g:sclangPipeApp
82 let s:sclangPipeApp = "sclangpipe_app"
85 "function SClangRunning()
86 " if s:sclang_pid != 0 && `pidof "#{$sclangsclangPipeApp_no_quotes}"`.chomp != ""
95 function! FindOuterMostBlock()
96 "search backwards for parens dont wrap
97 let l:search_expression_up = "call searchpair('(', '', ')', 'bW'," .
98 \"'synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"scComment\" || " .
99 \"synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"scString\" || " .
100 \"synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"scSymbol\"')"
101 "search forward for parens, don't wrap
102 let l:search_expression_down = "call searchpair('(', '', ')', 'W'," .
103 \"'synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"scComment\" || " .
104 \"synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"scString\" || " .
105 \"synIDattr(synID(line(\".\"), col(\".\"), 0), \"name\") =~? \"scSymbol\"')"
107 "save our current cursor position
108 let l:returnline = line(".")
109 let l:returncol = col(".")
111 "if we're on an opening paren then we should actually go to the closing one to start the search
112 "if buf[l:returnline][l:returncol-1,1] == "("
113 if strpart(getline(line(".")),col(".") - 1,1) == "("
114 exe l:search_expression_down
117 let l:origline = line(".")
118 let l:origcol = col(".")
120 "these numbers will define our range, first init them to illegal values
121 let l:range_e = [-1, -1]
122 let l:range_s = [-1, -1]
124 "this is the last line in our search
125 let l:lastline = line(".")
126 let l:lastcol = col(".")
128 exe l:search_expression_up
130 while line(".") != l:lastline || (line(".") == l:lastline && col(".") != l:lastcol)
131 "keep track of the last line/col we were on
132 let l:lastline = line(".")
133 let l:lastcol = col(".")
134 "go to the matching paren
135 exe l:search_expression_down
137 "if there isn't a match print an error
138 if l:lastline == line(".") && l:lastcol == col(".")
139 call cursor(l:returnline,l:returncol)
140 throw "UnmachedParen at line:" . l:lastline . ", col: " . l:lastcol
143 "if this is equal to or later than our original cursor position
144 if line(".") > l:origline || (line(".") == l:origline && col(".") >= l:origcol)
145 let l:range_e = [line("."), col(".")]
146 "go back to opening paren
147 exe l:search_expression_up
148 let l:range_s = [line("."), col(".")]
150 "go back to opening paren
151 exe l:search_expression_up
153 "find next paren (if there is one)
154 exe l:search_expression_up
157 "restore the settings
158 call cursor(l:returnline,l:returncol)
160 if l:range_s[0] == -1 || l:range_s[1] == -1
161 throw "OutsideOfParens"
165 return [l:range_s, l:range_e]
169 "this causes the sclang pipe / terminal app to be killed when you exit vim, if you don't
170 "want that to happen then just comment this out
171 if !exists("loaded_kill_sclang")
172 if s:sclangKillOnExit
173 au VimLeave * call SClangKill()
175 let loaded_kill_sclang = 1
178 "the vim version of SendToSC
179 function SendToSC(text)
180 let l:text = substitute(a:text, '\', '\\\\', 'g')
181 let l:text = substitute(l:text, '"', '\\"', 'g')
182 let l:cmd = system('echo "' . l:text . '" >> ' . s:sclangPipeLoc)
183 "let l:cmd = system('echo "' . l:text . '" >> /tmp/test')
186 function SendLineToSC(linenum)
187 let cmd = a:linenum . "w! >> " . s:sclangPipeLoc
189 "let cmd = a:linenum . "w! >> /tmp/test"
193 function! SClang_send()
194 let cmd = ".w! >> " . s:sclangPipeLoc
196 if line(".") == a:lastline
202 function SClangStart()
203 if !filewritable(s:sclangPipeAppPidLoc)
204 if $TERM[0:5] == "screen"
205 call system("screen -D -R -X split; screen -D -R -X focus; screen -D -R -X screen " . s:sclangPipeApp . "; screen -D -R -X focus")
207 call system(s:sclangTerm . " " . s:sclangPipeApp . "&")
210 throw s:sclangPipeAppPidLoc . " exists, is " . s:sclangPipeApp . " running? If not try deleting " . s:sclangPipeAppPidLoc
214 function SClangKill()
215 if filewritable(s:sclangPipeAppPidLoc)
216 call SendToSC("Server.quitAll;
\f")
218 call system("kill `cat " . s:sclangPipeAppPidLoc . "` && rm " . s:sclangPipeAppPidLoc . " && rm " . s:sclangPipeLoc)
222 function SClangRestart()
223 if filewritable(s:sclangPipeAppPidLoc)
224 call system("kill -HUP `cat " . s:sclangPipeAppPidLoc . "`")
230 function SClang_free(server)
231 call SendToSC('s.freeAll;
\f')
235 function SClang_thisProcess_stop()
236 call SendToSC('thisProcess.stop;
\f')
240 function SClang_TempoClock_clear()
241 call SendToSC('TempoClock.default.clear;
\f')
245 function! SClang_block()
246 let [blkstart,blkend] = FindOuterMostBlock()
247 "blkstart[0],blkend[0] call SClang_send()
248 "these next lines are just a hack, how can i do the above??
249 let cmd = blkstart[0] . "," . blkend[0] . " call SClang_send()"
250 let l:origline = line(".")
251 let l:origcol = col(".")
253 call cursor(l:origline,l:origcol)
255 ""if the range is just one line
256 "if blkstart[0] == blkend[0]
257 " "XXX call SendToSC(strpart(getline(blkstart[0]),blkstart[1] - 1, (blkend[1] - blkstart[1] + 1)))
258 " call SendLineToSC(blkstart[0])
260 " let linen = blkstart[0] - 1
261 " "send the first line as it might not be a full line
262 " "XXX let line = getline(linen)
263 " "XXX call SendToSC(strpart(line, blkstart[1] - 1))
264 " call SendLineToSC(linen)
266 " let endlinen = blkend[0]
267 " while linen < endlinen
268 " "XXX call SendToSC(getline(linen))
269 " call SendLineToSC(linen)
272 " "send the last line as it might not be a full line
273 " "XXX let line = getline(endlinen)
274 " "XXX call SendToSC(strpart(line,0,blkend[1]))
275 " call SendLineToSC(endlinen)
280 function SCdef(subject)
281 let l:tagfile = s:scvim_cache_dir . "/TAGS_SCDEF"
282 let l:tagdest = s:scvim_cache_dir . "/doc/tags"
284 if !filereadable(l:tagfile)
285 echo "definition tag cache does not exist, you must run SCVim.updateCaches in supercollider"
286 let l:dontcare = system("echo 'SC:SCVim SCVim.scd /^' > " . l:tagdest)
289 let l:dontcare = system("grep SCdef:" . a:subject . " " . l:tagfile . " > " . l:tagdest)
290 exe "help SCdef:" . a:subject
294 function SChelp(subject)
295 let l:tagfile = s:scvim_cache_dir . "/doc/TAGS_HELP"
296 let l:tagdest = s:scvim_cache_dir . "/doc/tags"
297 if !filereadable(l:tagfile)
298 echo "help tag cache does not exist, you must run SCVim.updateHelpCache in supercollider in order have help docs"
299 let l:dontcare = system("echo 'SC:SCVim SCVim.scd /^' > $SCVIM_CACHE_DIR/doc/tags")
304 "the keybindings won't find * but will find ** for some reason
306 let l:dontcare = system("grep \"SC:Help\" " . l:tagfile . " > " . l:tagdest)
308 elseif a:subject == "*"
309 let l:dontcare = system("grep \"SC:\\*\" " . l:tagfile . " > " . l:tagdest)
310 exe "help SC:\*" . a:subject
311 elseif a:subject == "**"
312 let l:dontcare = system("grep \"SC:\\*\\*\" " . l:tagfile . " > " . l:tagdest)
313 exe "help SC:\*\*" . a:subject
315 let l:dontcare = system("grep SC:\"" . a:subject . "\" " . l:tagfile . " > " . l:tagdest)
316 exe "help SC:" . a:subject
321 function HelpBrowser()
322 call SendToSC('Help.gui;
\f')
325 "--open help by class name
326 function HelpBrowser_find(subject)
327 let string= "HelpBrowser.openHelpFor"
328 let format= "(\"" . a:subject . "\");
\f"
329 let string= string . format
330 call SendToSC(string)
333 function ListSCObjects(A,L,P)
334 return system("cat $SCVIM_CACHE_DIR/sc_object_completion")
337 function ListSCHelpItems(A,L,P)
338 return system("cat $SCVIM_CACHE_DIR/doc/sc_help_completion")
342 "custom commands (SChelp,SCdef,SClangfree)
343 com -complete=custom,ListSCHelpItems -nargs=? SChelp call SChelp("<args>")
344 com -complete=custom,ListSCObjects -nargs=1 SCdef call SCdef("<args>")
345 com -nargs=1 SClangfree call SClang_free("<args>")
346 com -nargs=0 SClangStart call SClangStart()
347 com -nargs=0 SClangKill call SClangKill()
348 com -nargs=0 SClangRestart call SClangRestart()
350 " end supercollider.vim