Subversion Repositories programming

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
160 ira 1
" -*- vim -*-
2
" FILE: python.vim
3
" LAST MODIFICATION: 2003/07/25 19:00
4
" (C) Copyright 2001-2003 Mikael Berthe <mikael.b@netcourrier.com>
5
" Version: 1.7
6
 
7
" USAGE:
8
"
9
" Just source this script when editing Python files.
10
" Example: au FileType python source ~me/.vim/scripts/python.vim
11
" You can set the global variable "g:py_select_leading_comments" to 0
12
" if you don't want to select comments preceding a declaration (these
13
" are usually the description of the function/class).
14
" You can set the global variable "g:py_select_trailing_comments" to 0
15
" if you don't want to select comments at the end of a function/class.
16
" If these variables are not defined, both leading and trailing comments
17
" are selected.
18
" Example: (in your .vimrc) "let g:py_select_leading_comments = 0"
19
" You may want to take a look at the 'shiftwidth' option for the
20
" shift commands...
21
"
22
" REQUIREMENTS:
23
" vim (>= 6)
24
"
25
" Shortcuts:
26
"   [[      -- Jump to beginning of block
27
"   ]]      -- Jump to end of block
28
"   ]v      -- Select (Visual Line Mode) block
29
"   ]<      -- Shift block to left
30
"   ]>      -- Shift block to right
31
"   ]c      -- Select current/previous class
32
"   ]f      -- Select current/previous function
33
"   ]<up>   -- Jump to previous line with the same/lower indentation
34
"   ]<down> -- Jump to next line with the same/lower indentation
35
 
36
 
37
map  [[   :PBoB<CR>
38
vmap [[   :<C-U>PBoB<CR>m'gv``
39
map  ]]   :PEoB<CR>
40
vmap ]]   :<C-U>PEoB<CR>m'gv``
41
 
42
map  ]v   [[V]]
43
map  ]<   [[V]]<
44
vmap ]<   <
45
map  ]>   [[V]]>
46
vmap ]>   >
47
 
48
map  ]c   :call PythonSelectObject("class")<CR>
49
map  ]f   :call PythonSelectObject("function")<CR>
50
 
51
map  ]<up>    :call PythonNextLine(-1)<CR>
52
map  ]<down>  :call PythonNextLine(1)<CR>
53
" You may prefer use <s-up> and <s-down>... :-)
54
 
55
 
56
 
57
" Menu entries
58
nmenu <silent> &Python.Update\ IM-Python\ Menu 
59
    \:call UpdateMenu()<CR>
60
nmenu &Python.-Sep1- :
61
nmenu <silent> &Python.Beginning\ of\ Block<Tab>[[ 
62
    \[[
63
nmenu <silent> &Python.End\ of\ Block<Tab>]] 
64
    \]]
65
nmenu &Python.-Sep2- :
66
nmenu <silent> &Python.Shift\ Block\ Left<Tab>]< 
67
    \]<
68
vmenu <silent> &Python.Shift\ Block\ Left<Tab>]< 
69
    \]<
70
nmenu <silent> &Python.Shift\ Block\ Right<Tab>]> 
71
    \]>
72
vmenu <silent> &Python.Shift\ Block\ Right<Tab>]> 
73
    \]>
74
nmenu &Python.-Sep3- :
75
vmenu <silent> &Python.Comment\ Selection 
76
    \:call PythonCommentSelection()<CR>
77
nmenu <silent> &Python.Comment\ Selection 
78
    \:call PythonCommentSelection()<CR>
79
vmenu <silent> &Python.Uncomment\ Selection 
80
    \:call PythonUncommentSelection()<CR>
81
nmenu <silent> &Python.Uncomment\ Selection 
82
    \:call PythonUncommentSelection()<CR>
83
nmenu &Python.-Sep4- :
84
nmenu <silent> &Python.Previous\ Class 
85
    \:call PythonDec("class", -1)<CR>
86
nmenu <silent> &Python.Next\ Class 
87
    \:call PythonDec("class", 1)<CR>
88
nmenu <silent> &Python.Previous\ Function 
89
    \:call PythonDec("function", -1)<CR>
90
nmenu <silent> &Python.Next\ Function 
91
    \:call PythonDec("function", 1)<CR>
92
nmenu &Python.-Sep5- :
93
nmenu <silent> &Python.Select\ Block<Tab>]v 
94
    \]v
95
nmenu <silent> &Python.Select\ Function<Tab>]f 
96
    \]f
97
nmenu <silent> &Python.Select\ Class<Tab>]c 
98
    \]c
99
nmenu &Python.-Sep6- :
100
nmenu <silent> &Python.Previous\ Line\ wrt\ indent<Tab>]<up> 
101
    \]<up>
102
nmenu <silent> &Python.Next\ Line\ wrt\ indent<Tab>]<down> 
103
    \]<down>
104
 
105
 
106
:com! PBoB execute "normal ".PythonBoB(line('.'), -1, 1)."G"
107
:com! PEoB execute "normal ".PythonBoB(line('.'), 1, 1)."G"
108
:com! UpdateMenu call UpdateMenu()
109
 
110
 
111
" Go to a block boundary (-1: previous, 1: next)
112
" If force_sel_comments is true, 'g:py_select_trailing_comments' is ignored
113
function! PythonBoB(line, direction, force_sel_comments)
114
  let ln = a:line
115
  let ind = indent(ln)
116
  let mark = ln
117
  let indent_valid = strlen(getline(ln))
118
  let ln = ln + a:direction
119
  if (a:direction == 1) && (!a:force_sel_comments) && 
120
      \ exists("g:py_select_trailing_comments") && 
121
      \ (!g:py_select_trailing_comments)
122
    let sel_comments = 0
123
  else
124
    let sel_comments = 1
125
  endif
126
 
127
  while((ln >= 1) && (ln <= line('$')))
128
    if  (sel_comments) || (match(getline(ln), "^\\s*#") == -1)
129
      if (!indent_valid)
130
        let indent_valid = strlen(getline(ln))
131
        let ind = indent(ln)
132
        let mark = ln
133
      else
134
        if (strlen(getline(ln)))
135
          if (indent(ln) < ind)
136
            break
137
          endif
138
          let mark = ln
139
        endif
140
      endif
141
    endif
142
    let ln = ln + a:direction
143
  endwhile
144
 
145
  return mark
146
endfunction
147
 
148
 
149
" Go to previous (-1) or next (1) class/function definition
150
function! PythonDec(obj, direction)
151
  if (a:obj == "class")
152
    let objregexp = "^\\s*class\\s\\+[a-zA-Z0-9_]\\+"
153
        \ . "\\s*\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*:"
154
  else
155
    let objregexp = "^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*:"
156
  endif
157
  let flag = "W"
158
  if (a:direction == -1)
159
    let flag = flag."b"
160
  endif
161
  let res = search(objregexp, flag)
162
endfunction
163
 
164
 
165
" Comment out selected lines
166
" commentString is inserted in non-empty lines, and should be aligned with
167
" the block
168
function! PythonCommentSelection()  range
169
  let commentString = "#"
170
  let cl = a:firstline
171
  let ind = 1000    " I hope nobody use so long lines! :)
172
 
173
  " Look for smallest indent
174
  while (cl <= a:lastline)
175
    if strlen(getline(cl))
176
      let cind = indent(cl)
177
      let ind = ((ind < cind) ? ind : cind)
178
    endif
179
    let cl = cl + 1
180
  endwhile
181
  if (ind == 1000)
182
    let ind = 1
183
  else
184
    let ind = ind + 1
185
  endif
186
 
187
  let cl = a:firstline
188
  execute ":".cl
189
  " Insert commentString in each non-empty line, in column ind
190
  while (cl <= a:lastline)
191
    if strlen(getline(cl))
192
      execute "normal ".ind."|i".commentString
193
    endif
194
    execute "normal \<Down>"
195
    let cl = cl + 1
196
  endwhile
197
endfunction
198
 
199
" Uncomment selected lines
200
function! PythonUncommentSelection()  range
201
  " commentString could be different than the one from CommentSelection()
202
  " For example, this could be "# \\="
203
  let commentString = "#"
204
  let cl = a:firstline
205
  while (cl <= a:lastline)
206
    let ul = substitute(getline(cl),
207
             \"\\(\\s*\\)".commentString."\\(.*\\)$", "\\1\\2", "")
208
    call setline(cl, ul)
209
    let cl = cl + 1
210
  endwhile
211
endfunction
212
 
213
 
214
" Select an object ("class"/"function")
215
function! PythonSelectObject(obj)
216
  " Go to the object declaration
217
  normal $
218
  call PythonDec(a:obj, -1)
219
  let beg = line('.')
220
 
221
  if !exists("g:py_select_leading_comments") || (g:py_select_leading_comments)
222
    let decind = indent(beg)
223
    let cl = beg
224
    while (cl>1)
225
      let cl = cl - 1
226
      if (indent(cl) == decind) && (getline(cl)[decind] == "#")
227
        let beg = cl
228
      else
229
        break
230
      endif
231
    endwhile
232
  endif
233
 
234
  if (a:obj == "class")
235
    let eod = "\\(^\\s*class\\s\\+[a-zA-Z0-9_]\\+\\s*"
236
            \ . "\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*\\)\\@<=:"
237
  else
238
   let eod = "\\(^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*\\)\\@<=:"
239
  endif
240
  " Look for the end of the declaration (not always the same line!)
241
  call search(eod, "")
242
 
243
  " Is it a one-line definition?
244
  if match(getline('.'), "^\\s*\\(#.*\\)\\=$", col('.')) == -1
245
    let cl = line('.')
246
    execute ":".beg
247
    execute "normal V".cl."G"
248
  else
249
    " Select the whole block
250
    execute "normal \<Down>"
251
    let cl = line('.')
252
    execute ":".beg
253
    execute "normal V".PythonBoB(cl, 1, 0)."G"
254
  endif
255
endfunction
256
 
257
 
258
" Jump to the next line with the same (or lower) indentation
259
" Useful for moving between "if" and "else", for example.
260
function! PythonNextLine(direction)
261
  let ln = line('.')
262
  let ind = indent(ln)
263
  let indent_valid = strlen(getline(ln))
264
  let ln = ln + a:direction
265
 
266
  while((ln >= 1) && (ln <= line('$')))
267
    if (!indent_valid) && strlen(getline(ln)) 
268
        break
269
    else
270
      if (strlen(getline(ln)))
271
        if (indent(ln) <= ind)
272
          break
273
        endif
274
      endif
275
    endif
276
    let ln = ln + a:direction
277
  endwhile
278
 
279
  execute "normal ".ln."G"
280
endfunction
281
 
282
 
283
" Update the IM-Python menu, that holds Classes and Functions
284
function! UpdateMenu()
285
  let restore_fe = &foldenable
286
  set nofoldenable
287
  let cline=line('.')
288
  call MakeClassStructure ()
289
  call MakeFuncStructure ()
290
  execute "normal ".cline."Gzz"
291
  let &foldenable = restore_fe
292
endfunction
293
 
294
" Make a menu that holds all of the classes
295
function! MakeClassStructure () 
296
  norm mpgg0
297
  while line(".") <= line("$")
298
    if match ( getline("."), '^\s*class\s\+' ) != -1
299
      norm ^w"nyw
300
      let name=@n
301
      "exe 'menu IM-Python.classes.'.name.' '.line(".").'gg15zo'
302
      exe 'menu IM-Python.classes.'.name.' :call <SID>JumpToAndUnfold('.line(".").')<CR>'
303
    endif
304
    if line(".") == line("$")
305
      return
306
    endif
307
    norm j
308
  endwhile
309
  norm 'p
310
endfunction
311
 
312
" Make a menu that holds all of the function definitions
313
function! MakeFuncStructure () 
314
  norm mpgg0
315
  while line(".") <= line("$")
316
    if match ( getline("."), '^\s*def\s\+' ) != -1
317
      norm ^w"nyw
318
      let name=@n
319
      "exe 'menu IM-Python.functions.'.name.' '.line(".").'gg15zo'
320
      exe 'menu IM-Python.functions.'.name.' :call <SID>JumpToAndUnfold('.line(".").')<CR>'
321
    endif
322
    if line(".") == line("$")
323
      return
324
    endif
325
    norm j
326
  endwhile
327
  norm 'p
328
endfunction
329
 
330
function! s:JumpToAndUnfold(line)
331
  " Go to the right line
332
  execute 'normal '.a:line.'gg'
333
  " Check to see if we are in a fold
334
  let lvl = foldlevel(a:line)
335
  if lvl != 0
336
    " and if so, then expand the fold out, other wise, ignore this part.
337
    execute 'normal 15zo'
338
  endif
339
endfunction
340
 
341
"" This one will work only on vim 6.2 because of the try/catch expressions.
342
" function! s:JumpToAndUnfoldWithExceptions(line)
343
"  try 
344
"    execute 'normal '.a:line.'gg15zo'
345
"  catch /^Vim\((\a\+)\)\=:E490:/
346
"    " Do nothing, just consume the error
347
"  endtry
348
"endfunction
349
 
350
 
351
" vim:set et sts=2 sw=2:
352