source: project/wiki/vim @ 37557

Last change on this file since 37557 was 32714, checked in by evhan, 5 years ago

wiki/vim: Add link to Vim blog post

File size: 12.0 KB
Line 
1[[tags: vim editors]]
2[[toc:]]
3
4== Introduction
5
6Following are some settings used to edit Scheme file with VIM.
7
8== Coloring
9
10VIM's default syntax file for Scheme already has some CHICKEN-specific
11settings, we can enable those by adding the following line into
12{{~/.vim/ftplugin/scheme.vim}}.
13
14<enscript highlight=vim>
15let b:is_chicken=1
16</enscript>
17
18But still some annoyances remain.
19
20The following code is a patch to {{syntax/scheme.vim}}, you can patch
21the system-side file, or you can copy it to {{~/.vim/syntax}}, and
22then patch it.  This patch adds S-expression comment and Unix
23hash-bang support.
24
25<enscript highlight=diff>
26--- old-scheme.vim      2008-08-16 09:35:17.000000000 +0800
27+++ scheme.vim  2008-08-16 09:34:38.000000000 +0800
28@@ -29,6 +29,11 @@
29 syn match      schemeError     oneline    ![^ \t()\[\]";]*!
30 syn match      schemeError     oneline    ")"
31 
32+" Add TempStruc before Struc and Quoted.
33+" although TempStruc will be overwritten by them when do hightlighting,
34+" it still can be used to delimit a sexp.
35+syn region schemeTempStruc start="(" end=")" contained transparent contains=schemeTempStruc
36+
37 " Quoted and backquoted stuff
38 
39 syn region schemeQuoted matchgroup=Delimiter start="['`]" end=![ \t()\[\]";]!me=e-1 contains=ALLBUT,schemeStruc,schemeSyntax,schemeFunc
40@@ -231,8 +236,13 @@
41 
42 
43 if exists("b:is_chicken") || exists("is_chicken")
44+    syn match schemeChar oneline "#\\return"
45+    syn match schemeChar oneline "#!eof"
46+
47     " multiline comment
48     syntax region schemeMultilineComment start=/#|/ end=/|#/ contains=schemeMultilineComment
49+    syn region schemeSexpComment start="#;(" end=")" contains=schemeComment,schemeTempStruc
50+    hi def link schemeSexpComment Comment
51 
52     syn match schemeOther oneline    "##[-a-z!$%&*/:<=>?^_~0-9+.@#%]\+"
53     syn match schemeExtSyntax oneline    "#:[-a-z!$%&*/:<=>?^_~0-9+.@#%]\+"
54@@ -268,6 +278,9 @@
55     " suggested by Alex Queiroz
56     syn match schemeExtSyntax oneline    "#![-a-z!$%&*/:<=>?^_~0-9+.@#%]\+"
57     syn region schemeString start=+#<#\s*\z(.*\)+ end=+^\z1$+ 
58+
59+    syn match schemeShebang "^#!/.*csi.*$"
60+    hi def link schemeShebang Comment
61 endif
62 
63 " Synchronization and the wrapping up...
64</enscript>
65
66== Editing
67
68=== Completion
69
70VIM's completion functionality can be configured by 'complete' option.
71There are several useful settings for Scheme editing.
72
73First is the '''k''' flag, we can supply a dict file to it. The
74following code can be used to generate a Scheme dict file.
75
76<enscript highlight=scheme>
77#!/usr/local/bin/csi -script
78;;; Create a dictionary file to be used by vim insert complete.
79
80(use data-structures extras srfi-1 srfi-4 srfi-13)
81(use srfi-14 srfi-69 apropos regex srfi-18 posix utils tcp lolevel)
82
83(call-with-output-file "~/scheme-word-list"
84   (lambda (port)
85     (for-each (lambda (x) (display x port) (newline port))
86               (sort (apropos-list (regexp ".*") #:macros? #t)
87                     (lambda (a b)
88                       (string<? (symbol->string a)
89                                 (symbol->string b)))))))
90</enscript>
91
92Then add the following line to {{~/.vim/ftplugin/scheme.vim}}, and we
93will be able to complete identifier names using CTRL-P and CTRL-N.
94
95<enscript highlight=vim>
96setl complete+=,k~/scheme-word-list
97</enscript>
98
99Also when we edit c files, VIM finds words in not only opened buffers,
100but also included files. These are controlled by the following
101options.
102
103Likewise, VIM can be configured to find words in files which are
104mentioned in '''use''' or '''require-extension'''.  In the example
105below, change the path to match your setup. The follwing lines go into
106{{~/.vim/ftplugin/scheme.vim}}:
107
108<enscript highlight=vim>
109setl include=\^\(\\(use\\\|require-extension\\)\\s\\+
110setl includeexpr=substitute(v:fname,'$','.scm','')
111setl path+=/usr/local/lib/chicken/3
112setl suffixesadd=.scm
113</enscript>
114
115
116=== Indentation
117
118VIM already indents Scheme file well, except it can't recognise some
119CHICKEN keywords. We just have to add them.
120
121<enscript highlight=vim>
122setl lispwords+=let-values,condition-case,with-input-from-string
123setl lispwords+=with-output-to-string,handle-exceptions,call/cc,rec,receive
124setl lispwords+=call-with-output-file
125</enscript>
126
127Also, put those lines in to {{scheme.vim}}.
128
129<enscript highlight=vim>
130nmap <silent> == :call Scheme_indent_top_sexp()<cr>
131
132" Indent a toplevel sexp.
133fun! Scheme_indent_top_sexp()
134        let pos = getpos('.')
135        silent! exec "normal! 99[(=%"
136        call setpos('.', pos)
137endfun
138</enscript>
139
140Then we can use '''==''' to indent a toplevel S-expression.
141
142== Interaction
143
144Vim lacks a cross-platform facility to spawn shells and other commandline programs and interact with them, therefore various methods—or workarounds—have been invented and re-invented over time to address the issue. Each has its own advantages and drawbacks.
145
146=== Using VimSh
147
148This is a Vim extension written in Python that approximates what most users would consider the "ideal" shell interaction from within a text editor. It can spawn any interactive program from inside Vim, display their output in a new buffer (a Vim window) and receive input on the bottom line of the same buffer. Since it's a Vim buffer you can go into normal mode and move around the buffer, yank, paste, use word completion, etc. (Do understand that changing text and typing newlines in places other than the bottom line will give weird results.)
149
150You will need a Vim built with Python support (:version must contain +python) and an OS with pty support (Windows users are SOL.)
151
152Instructions:
153* download [[http://www.vim.org/scripts/script.php?script_id=165|VimSh]]
154* put {{vimsh.py}} into {{~/.vim}}
155* I prefer to discard the {{vimsh.vim}} provided, as it is mostly comments and instructions, and instead put the following in my {{.vimrc}}
156
157 let g:vimsh_sh="/bin/bash"
158 let g:vimsh_pty_prompt_override=0
159 let g:vimsh_show_workaround_msgs=0
160 
161 function! VimShRedraw()
162   redraw
163 endf
164 
165 function! VimShNew()
166   if ! exists("g:vimsh_loaded_python_file")
167     pyfile ~/.vim/vimsh.py
168     let g:vimsh_loaded_python_file=1
169   endif
170   python spawn_buf('_vimsh_')
171 endf
172 
173 function! VimShRun(text)
174   " Called on a string or on a list of lines
175   " Executes the lines in the VimSh window, one by one
176   " (to allow for secondary prompts and/or incremental evaluation)
177 
178   " Parse argument
179   let t = type(a:text)
180   if t == 1
181     let lines = split(a:text, '\n')
182   elseif t == 3
183     let lines = a:text
184   else
185     echoerr 'Argument is neither a list nor a string'
186     return
187   endif
188 
189   " Find VimSh window
190   let win = bufwinnr('_vimsh_')
191   if win == -1
192     echohl WarningMsg
193     echomsg 'Cannot find vimsh window'
194     echohl None
195     return
196   endif
197 
198   " Execute commands
199   exec win . 'wincmd w'
200   for line in lines
201     call setline('$', getline('$') . line)
202     python lookup_buf('_vimsh_').execute_cmd()
203     redraw
204     sleep 1m "why do I need a sleep to apply the redraw?
205   endfor
206   stopinsert
207   wincmd p
208   echo
209 endf
210 
211 function! VimShRunOp(type, ...)
212   " Helper function (copied verbatim from Vim help)
213 
214   let sel_save = &selection
215   let &selection = "inclusive"
216   let reg_save = @@
217 
218   if a:0
219     silent exe "normal! `<" . a:type . "`>y"
220   elseif a:type == 'line'
221     silent exe "normal! '[V']y"
222   elseif a:type == 'block'
223     silent exe "normal! `[\<C-V>`]y"
224   else
225     silent exe "normal! `[v`]y"
226   endif
227 
228   call VimShRun(@@)
229 
230   let &selection = sel_save
231   let @@ = reg_save
232 endf
233 
234 nmap Sn :call VimShNew()<CR>
235 nnoremap S  :set opfunc=VimShRunOp<CR>g@
236 vnoremap S  :<C-U>call VimShRunOp(visualmode(), 1)<CR>
237 nnoremap SS :call VimShRun(getline('.'))<CR>
238 nnoremap Sf :call VimShRun(getline(1,'$'))<CR>
239 nmap St :norm 99[(<CR>vabS
240
241The code above includes work from various sources and contains a few weird tricks (in other words: '''here be dragons''') It provides several features under the '''S''' leading character. Redefining '''S''' as '''S'''hell (or '''S'''end) shouldn't cause problems for most users, as the default '''S'''ubstitute function is just a synonym for '''C'''hange, but you can alter the mappings if you don't like it.
242
243
244<table>
245<tr><td>{{Sn}}</td><td>open a '''n'''ew shell</td></tr>
246<tr><td>{{SS}} or ''count''{{SS}}</td><td>send the current line (or ''count'' lines) to the shell</td></tr>
247<tr><td>{{S}}''motion''</td><td>send the text over ''motion'' to the shell (eg. {{S3w}} sends 3 words to the shell)</td></tr>
248<tr><td>visual mode {{S}}</td><td>send the selected text (either char-, line-, or block-wise selection)</td></tr>
249<tr><td>{{Sf}}</td><td>send the entire '''f'''ile to the shell</td></tr>
250<tr><td>{{St}}</td><td>send the current '''t'''op-level form to the shell</td></tr>
251</table>
252
253A newline is always added at the end of the text being sent, so as to make the shell execute it. If for some reason you don't want to send a complete command, you will have to use Vim's standard yank & pull (copy & paste) from your editing buffer to the shell buffer.
254
255Care is taken to make the shell react to each individual line as if it was typed interactively. As a result, pasting huge chunks will be a slow operation. You are advised to use a source command in this case: {{source}} (or dot) for bash, {{include}} for CHICKEN.
256
257'''Important notice:''' because of a limitation in Vim, when a line takes more than a given timeout (1/10 of a second) to execute, VimSh returns the command to the editor without waiting for the shell to complete the operation. You will have to manually go to the VimSh buffer every once in a while and hit {{F5}} to refresh the view. This is probably the most annoying drawback of this whole method, but it's not that bad in actuality.
258
259The config block above spawns bash, instead of csi, for several reasons:
260
261* to have bash initialize the environment properly
262* to be able to read any csi fatal errors
263* to use this framework for other languages / interpreters.
264
265One last thing, you might like this if you're not using it already:
266
267 set mousefocus
268
269=== Using GNU Screen
270
271Another way to add interaction facility to Vim is to use GNU Screen.
272
273With this method the csi process is completely independent (detached) from Vim. It must be started manually, in a Screen session with a specific ''window title'', and remains running after quitting the editor. This can be either an advantage or a disadvantage, depending on your requirements.
274
275Source: [[http://technotales.wordpress.com/2007/10/03/like-slime-for-vim/|Jonathan Palardy]].
276
277Put following lines into '''ftplugin/scheme.vim''' (make sure that there is no trailing whitespace, especially in the "nmap" lines):
278
279<enscript highlight=vim>
280nmap <silent> <leader>es :call Scheme_eval_defun()<cr>
281nmap <silent> <leader>ef  :call Scheme_send_sexp("(load \"" . expand("%:p") . "\")\n")<cr>
282
283fun! Scheme_send_sexp(sexp)
284    let ss = escape(a:sexp, '\"')
285    call system("screen -p csi -X stuff \"" . ss . "\n\"")
286    "(or for tmux users)
287    "call system("tmux send-keys -t csi \"" . ss . "\n\"")
288endfun
289
290fun! Scheme_eval_defun()
291    let pos = getpos('.')
292    silent! exec "normal! 99[(yab"
293    call Scheme_send_sexp(@")
294    call setpos('.', pos)
295endfun
296</enscript>
297
298First we create a window in screen with the name of '''csi''' and start csi in it.  Then open a scheme file, using '''<leader>es''' to evaluate a sexp and using '''<leader>ef''' to load a file.
299
300Another minimalistic approach is described in the [[http://pestilenz.org/cgi-bin/blosxom.cgi/2013/05/03#slimswan | Endoscreen Cut&Paster]] blogpost.
301
302== SWANK / SLIMV
303
304There is a slime client for vim called slimv.
305
306* [[https://github.com/vim-scripts/slimv.vim | the vim extension slimv]]
307* [[http://kovisoft.bitbucket.org/tutorial.html | a tutorial in text form]]
308
309A tutorial screencast on setting it up can be found at [[http://vimeo.com/38372260/ | vimeo]].
310
311== REPL : Minimalistic REPL
312
313A vim extension which provides a REPL.
314
315* Uses vimproc to run csi (or another interpreter).
316* Partially works (Debian Wheezy).
317* [[http://www.vim.org/scripts/script.php?script_id=4336 | its home at vim.org]]
318
319== Links
320
321* [[http://www.foldling.org/scheme.html#editing-scheme-with-vim|Editing Scheme with Vim]]
322* [[http://www.ccs.neu.edu/home/dorai/scmindent/index.html|Editing Lisp and Scheme files in vi]]
Note: See TracBrowser for help on using the repository browser.