mirror of
https://github.com/gryf/python.vim.git
synced 2025-12-17 11:30:22 +01:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fad734d042 | |||
| e484838bc9 | |||
| 47a79f4251 | |||
| e799ed8118 | |||
|
|
669040957d | ||
|
|
0877af4dff | - | |
|
|
6411a284c5 | - | |
|
|
bf1056d729 | - | |
|
|
ef20af29a9 | - | |
|
|
6dbc984278 | - | |
|
|
97ed3fccdb | - | |
|
|
7a5bb2412f | - | |
|
|
dc9722e464 | - | |
|
|
414dc1c5c0 | - |
15
README
15
README
@@ -1,15 +0,0 @@
|
|||||||
This is a mirror of http://www.vim.org/scripts/script.php?script_id=30
|
|
||||||
|
|
||||||
Written by Mikael Berthe.
|
|
||||||
|
|
||||||
This script can be useful when editing Python scripts. It provides the following menus:
|
|
||||||
- Select a block of lines with the same indentation
|
|
||||||
- Select a function
|
|
||||||
- Select a class
|
|
||||||
- Go to previous/next class/function
|
|
||||||
- Go to the beginning/end of a block
|
|
||||||
- Comment/uncomment the selection
|
|
||||||
- Jump to the last/next line with the same indent
|
|
||||||
- Shift a block (left/right)
|
|
||||||
- Creates list of classes and functions for easy code navigation
|
|
||||||
Version 1.8+ requires Vim 7, earlier versions require Vim 6
|
|
||||||
52
README.rst
Normal file
52
README.rst
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
Python.vim
|
||||||
|
==========
|
||||||
|
|
||||||
|
This is a set of menus/shortcuts to work with Python files. This work is kind
|
||||||
|
continuation of `Mikael Berthe script`_, with some improvements and fixes.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
To install it, any kind of Vim package manager can be used, like NeoBundle_,
|
||||||
|
Pathogen_, Vundle_ or vim-plug_.
|
||||||
|
|
||||||
|
For manual installation, copy subdirectories from this repository to your
|
||||||
|
``~/.vim`` directory.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
Default shortcuts are as follows:
|
||||||
|
|
||||||
|
- ``]]`` - jump to next class
|
||||||
|
- ``[[`` - jump to previous class
|
||||||
|
- ``))`` - jump to next function or method
|
||||||
|
- ``((`` - jump to previous function or method
|
||||||
|
- ``]t`` - jump to beginning of block
|
||||||
|
- ``]e`` - jump to end of block
|
||||||
|
- ``]<up>`` - jump to previous line with the same/lower indentation
|
||||||
|
- ``]<down>`` - jump to next line with the same/lower indentation
|
||||||
|
- ``]<`` - shift block to left
|
||||||
|
- ``]>`` - shift block to right
|
||||||
|
- ``]#`` - comment selection
|
||||||
|
- ``]u`` - uncomment selection
|
||||||
|
- ``vac`` - select (Visual Line Mode) current/previous class
|
||||||
|
- ``vaf`` - select (Visual Line Mode) current/previous function
|
||||||
|
- ``vab`` - select (Visual Line Mode) block
|
||||||
|
|
||||||
|
You can set the global variable ``g:py_select_leading_comments`` to 0
|
||||||
|
if you don't want to select comments preceding a declaration (these
|
||||||
|
are usually the description of the function/class).
|
||||||
|
You can set the global variable ``g:py_select_trailing_comments`` to 0
|
||||||
|
if you don't want to select comments at the end of a function/class.
|
||||||
|
If these variables are not defined, both leading and trailing comments
|
||||||
|
are selected.
|
||||||
|
|
||||||
|
If you use graphical version of vim (like gvim) you can access those options
|
||||||
|
through the menu called *Python*.
|
||||||
|
|
||||||
|
.. _Mikael Berthe script: http://www.vim.org/scripts/script.php?script_id=30
|
||||||
|
.. _Pathogen: https://github.com/tpope/vim-pathogen
|
||||||
|
.. _Vundle: https://github.com/gmarik/Vundle.vim
|
||||||
|
.. _NeoBundle: https://github.com/Shougo/neobundle.vim
|
||||||
|
.. _vim-plug: https://github.com/junegunn/vim-plug
|
||||||
384
ftplugin/python/python_fn.vim
Normal file
384
ftplugin/python/python_fn.vim
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
" -*- vim -*-
|
||||||
|
" FILE: python_fn.vim
|
||||||
|
" LAST MODIFICATION: 2017-05-28 17:47:13
|
||||||
|
" (C) Copyright 2001-2005 Mikael Berthe <bmikael@lists.lilotux.net>
|
||||||
|
" Maintained by Jon Franklin <jvfranklin@gmail.com>
|
||||||
|
" Modifed by Roman Dobosz <gryf73@gmail.com>
|
||||||
|
" Version: 1.14
|
||||||
|
|
||||||
|
" USAGE:
|
||||||
|
" See README.rst
|
||||||
|
|
||||||
|
" Shortcuts:
|
||||||
|
" Only do this when not done yet for this buffer
|
||||||
|
if exists("b:loaded_py_ftplugin")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
let b:loaded_py_ftplugin = 1
|
||||||
|
|
||||||
|
map ]t :PBoB<CR>
|
||||||
|
vmap ]t :<C-U>PBOB<CR>m'gv``
|
||||||
|
map ]e :PEoB<CR>
|
||||||
|
vmap ]e :<C-U>PEoB<CR>m'gv``
|
||||||
|
|
||||||
|
map vab ]tV]e
|
||||||
|
map ]< ]tV]e<
|
||||||
|
vmap ]< <
|
||||||
|
map ]> ]tV]e>
|
||||||
|
vmap ]> >
|
||||||
|
|
||||||
|
map ]# :call PythonCommentSelection()<CR>
|
||||||
|
vmap ]# :call PythonCommentSelection()<CR>
|
||||||
|
map ]u :call PythonUncommentSelection()<CR>
|
||||||
|
vmap ]u :call PythonUncommentSelection()<CR>
|
||||||
|
|
||||||
|
map vac :call PythonSelectObject("class")<CR>
|
||||||
|
map vaf :call PythonSelectObject("function")<CR>
|
||||||
|
|
||||||
|
map ]<up> :call PythonNextLine(-1)<CR>
|
||||||
|
map ]<down> :call PythonNextLine(1)<CR>
|
||||||
|
" You may prefer use <s-up> and <s-down>... :-)
|
||||||
|
|
||||||
|
" jump to previous class
|
||||||
|
map [[ :call PythonDec("class", -1)<CR>
|
||||||
|
vmap [[ :call PythonDec("class", -1)<CR>
|
||||||
|
|
||||||
|
" jump to next class
|
||||||
|
map ]] :call PythonDec("class", 1)<CR>
|
||||||
|
vmap ]] :call PythonDec("class", 1)<CR>
|
||||||
|
|
||||||
|
" jump to previous function
|
||||||
|
map (( :call PythonDec("function", -1)<CR>
|
||||||
|
vmap (( :call PythonDec("function", -1)<CR>
|
||||||
|
|
||||||
|
" jump to next function
|
||||||
|
map )) :call PythonDec("function", 1)<CR>
|
||||||
|
vmap )) :call PythonDec("function", 1)<CR>
|
||||||
|
|
||||||
|
" Menu entries
|
||||||
|
nmenu <silent> &Python.Update\ IM-Python\ Menu :call UpdateMenu()<CR>
|
||||||
|
nmenu &Python.-Sep1- :
|
||||||
|
nmenu <silent> &Python.Beginning\ of\ Block<Tab>[t ]t
|
||||||
|
nmenu <silent> &Python.End\ of\ Block<Tab>]e ]e
|
||||||
|
nmenu &Python.-Sep2- :
|
||||||
|
nmenu <silent> &Python.Shift\ Block\ Left<Tab>]< ]<
|
||||||
|
vmenu <silent> &Python.Shift\ Block\ Left<Tab>]< ]<
|
||||||
|
nmenu <silent> &Python.Shift\ Block\ Right<Tab>]> ]>
|
||||||
|
vmenu <silent> &Python.Shift\ Block\ Right<Tab>]> ]>
|
||||||
|
nmenu &Python.-Sep3- :
|
||||||
|
vmenu <silent> &Python.Comment\ Selection<Tab>]# ]#
|
||||||
|
nmenu <silent> &Python.Comment\ Selection<Tab>]# ]#
|
||||||
|
vmenu <silent> &Python.Uncomment\ Selection<Tab>]u ]u
|
||||||
|
nmenu <silent> &Python.Uncomment\ Selection<Tab>]u ]u
|
||||||
|
nmenu &Python.-Sep4- :
|
||||||
|
nmenu <silent> &Python.Previous\ Class<Tab>[[ [[
|
||||||
|
nmenu <silent> &Python.Next\ Class<Tab>]] ]]
|
||||||
|
nmenu <silent> &Python.Previous\ Function<Tab>{{ ((
|
||||||
|
nmenu <silent> &Python.Next\ Function<Tab>}} ))
|
||||||
|
nmenu &Python.-Sep5- :
|
||||||
|
nmenu <silent> &Python.Select\ Block<Tab>vab vab
|
||||||
|
nmenu <silent> &Python.Select\ Function<Tab>vaf vaf
|
||||||
|
nmenu <silent> &Python.Select\ Class<Tab>vac vac
|
||||||
|
nmenu &Python.-Sep6- :
|
||||||
|
nmenu <silent> &Python.Previous\ Line\ wrt\ indent<Tab>]<up> ]<up>
|
||||||
|
nmenu <silent> &Python.Next\ Line\ wrt\ indent<Tab>]<down> ]<down>
|
||||||
|
|
||||||
|
:com! PBoB execute "normal ".PythonBoB(line('.'), -1, 1)."G"
|
||||||
|
:com! PEoB execute "normal ".PythonBoB(line('.'), 1, 1)."G"
|
||||||
|
:com! UpdateMenu call UpdateMenu()
|
||||||
|
|
||||||
|
|
||||||
|
" Go to a block boundary (-1: previous, 1: next)
|
||||||
|
" If force_sel_comments is true, 'g:py_select_trailing_comments' is ignored
|
||||||
|
function! PythonBoB(line, direction, force_sel_comments)
|
||||||
|
let ln = a:line
|
||||||
|
let ind = indent(ln)
|
||||||
|
let mark = ln
|
||||||
|
let indent_valid = strlen(getline(ln))
|
||||||
|
let ln = ln + a:direction
|
||||||
|
if (a:direction == 1) && (!a:force_sel_comments) &&
|
||||||
|
\ exists("g:py_select_trailing_comments") &&
|
||||||
|
\ (!g:py_select_trailing_comments)
|
||||||
|
let sel_comments = 0
|
||||||
|
else
|
||||||
|
let sel_comments = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
while((ln >= 1) && (ln <= line('$')))
|
||||||
|
if (sel_comments) || (match(getline(ln), "^\\s*#") == -1)
|
||||||
|
if (!indent_valid)
|
||||||
|
let indent_valid = strlen(getline(ln))
|
||||||
|
let ind = indent(ln)
|
||||||
|
let mark = ln
|
||||||
|
else
|
||||||
|
if (strlen(getline(ln)))
|
||||||
|
if (indent(ln) < ind)
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
let mark = ln
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
let ln = ln + a:direction
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
return mark
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Go to previous (-1) or next (1) class/function definition
|
||||||
|
function! PythonDec(obj, direction)
|
||||||
|
if (a:obj == "class")
|
||||||
|
let objregexp = "^\\s*class\\s\\+[a-zA-Z0-9_]\\+"
|
||||||
|
\ . "\\s*\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*:"
|
||||||
|
else
|
||||||
|
let objregexp = "^\\s*\\(async def\\|def\\)\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*:"
|
||||||
|
endif
|
||||||
|
let flag = "W"
|
||||||
|
if (a:direction == -1)
|
||||||
|
let flag = flag."b"
|
||||||
|
endif
|
||||||
|
let res = search(objregexp, flag)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Comment out selected lines
|
||||||
|
" commentString is inserted in non-empty lines, and should be aligned with
|
||||||
|
" the block
|
||||||
|
function! PythonCommentSelection() range
|
||||||
|
let commentString = "# "
|
||||||
|
let cl = a:firstline
|
||||||
|
let ind = 1000 " I hope nobody use so long lines! :)
|
||||||
|
|
||||||
|
" Look for smallest indent
|
||||||
|
while (cl <= a:lastline)
|
||||||
|
if strlen(getline(cl))
|
||||||
|
let cind = indent(cl)
|
||||||
|
let ind = ((ind < cind) ? ind : cind)
|
||||||
|
endif
|
||||||
|
let cl = cl + 1
|
||||||
|
endwhile
|
||||||
|
if (ind == 1000)
|
||||||
|
let ind = 1
|
||||||
|
else
|
||||||
|
let ind = ind + 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let cl = a:firstline
|
||||||
|
execute ":".cl
|
||||||
|
" Insert commentString in each non-empty line, in column ind
|
||||||
|
while (cl <= a:lastline)
|
||||||
|
if strlen(getline(cl))
|
||||||
|
execute "normal ".ind."|i".commentString
|
||||||
|
endif
|
||||||
|
execute "normal \<Down>"
|
||||||
|
let cl = cl + 1
|
||||||
|
endwhile
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Uncomment selected lines
|
||||||
|
function! PythonUncommentSelection() range
|
||||||
|
" commentString could be different than the one from CommentSelection()
|
||||||
|
" For example, this could be "# \\="
|
||||||
|
let commentString = "# "
|
||||||
|
let cl = a:firstline
|
||||||
|
while (cl <= a:lastline)
|
||||||
|
let ul = substitute(getline(cl),
|
||||||
|
\"\\(\\s*\\)".commentString."\\(.*\\)$", "\\1\\2", "")
|
||||||
|
call setline(cl, ul)
|
||||||
|
let cl = cl + 1
|
||||||
|
endwhile
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Select an object ("class"/"function")
|
||||||
|
function! PythonSelectObject(obj)
|
||||||
|
" Go to the object declaration
|
||||||
|
normal $
|
||||||
|
call PythonDec(a:obj, -1)
|
||||||
|
let beg = line('.')
|
||||||
|
|
||||||
|
if !exists("g:py_select_leading_comments") || (g:py_select_leading_comments)
|
||||||
|
let decind = indent(beg)
|
||||||
|
let cl = beg
|
||||||
|
while (cl>1)
|
||||||
|
let cl = cl - 1
|
||||||
|
if (indent(cl) == decind) && (getline(cl)[decind] == "#")
|
||||||
|
let beg = cl
|
||||||
|
else
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endwhile
|
||||||
|
endif
|
||||||
|
|
||||||
|
if (a:obj == "class")
|
||||||
|
let eod = "\\(^\\s*class\\s\\+[a-zA-Z0-9_]\\+\\s*"
|
||||||
|
\ . "\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*\\)\\@<=:"
|
||||||
|
else
|
||||||
|
let eod = "\\(^\\s*\\(async def\\|def\\)\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*\\)\\@<=:"
|
||||||
|
endif
|
||||||
|
" Look for the end of the declaration (not always the same line!)
|
||||||
|
call search(eod, "")
|
||||||
|
|
||||||
|
" Is it a one-line definition?
|
||||||
|
if match(getline('.'), "^\\s*\\(#.*\\)\\=$", col('.')) == -1
|
||||||
|
let cl = line('.')
|
||||||
|
execute ":".beg
|
||||||
|
execute "normal V".cl."G"
|
||||||
|
else
|
||||||
|
" Select the whole block
|
||||||
|
execute "normal \<Down>"
|
||||||
|
let cl = line('.')
|
||||||
|
execute ":".beg
|
||||||
|
execute "normal V".PythonBoB(cl, 1, 0)."G"
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Jump to the next line with the same (or lower) indentation
|
||||||
|
" Useful for moving between "if" and "else", for example.
|
||||||
|
function! PythonNextLine(direction)
|
||||||
|
let ln = line('.')
|
||||||
|
let ind = indent(ln)
|
||||||
|
let indent_valid = strlen(getline(ln))
|
||||||
|
let ln = ln + a:direction
|
||||||
|
|
||||||
|
while((ln >= 1) && (ln <= line('$')))
|
||||||
|
if (!indent_valid) && strlen(getline(ln))
|
||||||
|
break
|
||||||
|
else
|
||||||
|
if (strlen(getline(ln)))
|
||||||
|
if (indent(ln) <= ind)
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
let ln = ln + a:direction
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
execute "normal ".ln."G"
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! UpdateMenu()
|
||||||
|
" delete menu if it already exists, then rebuild it.
|
||||||
|
" this is necessary in case you've got multiple buffers open
|
||||||
|
" a future enhancement to this would be to make the menu aware of
|
||||||
|
" all buffers currently open, and group classes and functions by buffer
|
||||||
|
if exists("g:menuran")
|
||||||
|
aunmenu IM-Python
|
||||||
|
endif
|
||||||
|
let restore_fe = &foldenable
|
||||||
|
set nofoldenable
|
||||||
|
" preserve disposition of window and cursor
|
||||||
|
let cline=line('.')
|
||||||
|
let ccol=col('.') - 1
|
||||||
|
norm H
|
||||||
|
let hline=line('.')
|
||||||
|
" create the menu
|
||||||
|
call MenuBuilder()
|
||||||
|
" restore disposition of window and cursor
|
||||||
|
exe "norm ".hline."Gzt"
|
||||||
|
let dnscroll=cline-hline
|
||||||
|
exe "norm ".dnscroll."j".ccol."l"
|
||||||
|
let &foldenable = restore_fe
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! MenuBuilder()
|
||||||
|
norm gg0
|
||||||
|
let currentclass = -1
|
||||||
|
let classlist = []
|
||||||
|
let parentclass = ""
|
||||||
|
while line(".") < line("$")
|
||||||
|
" search for a class or function
|
||||||
|
if match ( getline("."), '^\s*class\s\+[_a-zA-Z].*\|^\s*\(async def\|def\)\s\+[_a-zA-Z].*' ) != -1
|
||||||
|
norm ^
|
||||||
|
let linenum = line('.')
|
||||||
|
let indentcol = col('.')
|
||||||
|
norm "nye
|
||||||
|
let classordef=@n
|
||||||
|
norm w"nywge
|
||||||
|
let objname=@n
|
||||||
|
let parentclass = FindParentClass(classlist, indentcol)
|
||||||
|
if classordef == "class"
|
||||||
|
call AddClass(objname, linenum, parentclass)
|
||||||
|
else " this is a function
|
||||||
|
call AddFunction(objname, linenum, parentclass)
|
||||||
|
endif
|
||||||
|
" We actually created a menu, so lets set the global variable
|
||||||
|
let g:menuran=1
|
||||||
|
call RebuildClassList(classlist, [objname, indentcol], classordef)
|
||||||
|
endif " line matched
|
||||||
|
norm j
|
||||||
|
endwhile
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" classlist contains the list of nested classes we are in.
|
||||||
|
" in most cases it will be empty or contain a single class
|
||||||
|
" but where a class is nested within another, it will contain 2 or more
|
||||||
|
" this function adds or removes classes from the list based on indentation
|
||||||
|
function! RebuildClassList(classlist, newclass, classordef)
|
||||||
|
let i = len(a:classlist) - 1
|
||||||
|
while i > -1
|
||||||
|
if a:newclass[1] <= a:classlist[i][1]
|
||||||
|
call remove(a:classlist, i)
|
||||||
|
endif
|
||||||
|
let i = i - 1
|
||||||
|
endwhile
|
||||||
|
if a:classordef == "class"
|
||||||
|
call add(a:classlist, a:newclass)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" we found a class or function, determine its parent class based on
|
||||||
|
" indentation and what's contained in classlist
|
||||||
|
function! FindParentClass(classlist, indentcol)
|
||||||
|
let i = 0
|
||||||
|
let parentclass = ""
|
||||||
|
while i < len(a:classlist)
|
||||||
|
if a:indentcol <= a:classlist[i][1]
|
||||||
|
break
|
||||||
|
else
|
||||||
|
if len(parentclass) == 0
|
||||||
|
let parentclass = a:classlist[i][0]
|
||||||
|
else
|
||||||
|
let parentclass = parentclass.'\.'.a:classlist[i][0]
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
let i = i + 1
|
||||||
|
endwhile
|
||||||
|
return parentclass
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" add a class to the menu
|
||||||
|
function! AddClass(classname, lineno, parentclass)
|
||||||
|
if len(a:parentclass) > 0
|
||||||
|
let classstring = a:parentclass.'\.'.a:classname
|
||||||
|
else
|
||||||
|
let classstring = a:classname
|
||||||
|
endif
|
||||||
|
exe 'menu IM-Python.classes.'.classstring.' :call <SID>JumpToAndUnfold('.a:lineno.')<CR>'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" add a function to the menu, grouped by member class
|
||||||
|
function! AddFunction(functionname, lineno, parentclass)
|
||||||
|
if len(a:parentclass) > 0
|
||||||
|
let funcstring = a:parentclass.'.'.a:functionname
|
||||||
|
else
|
||||||
|
let funcstring = a:functionname
|
||||||
|
endif
|
||||||
|
exe 'menu IM-Python.functions.'.funcstring.' :call <SID>JumpToAndUnfold('.a:lineno.')<CR>'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:JumpToAndUnfold(line)
|
||||||
|
" Go to the right line
|
||||||
|
execute 'normal '.a:line.'gg'
|
||||||
|
" Check to see if we are in a fold
|
||||||
|
let lvl = foldlevel(a:line)
|
||||||
|
if lvl != 0
|
||||||
|
" and if so, then expand the fold out, other wise, ignore this part.
|
||||||
|
execute 'normal 15zo'
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" vim:set et sts=2 sw=2:
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
" -*- vim -*-
|
|
||||||
" FILE: python.vim
|
|
||||||
" LAST MODIFICATION: 2001/09/05
|
|
||||||
" (C) Copyright 2001 Mikael Berthe <mikael.berthe@efrei.fr>
|
|
||||||
" Version: 1.4
|
|
||||||
|
|
||||||
" USAGE:
|
|
||||||
"
|
|
||||||
" Juste source this script when editing Python files.
|
|
||||||
" Example: au FileType python source ~me/.vim/scripts/python.vim
|
|
||||||
" You can set the global variable "g:py_select_leading_comments" to 0
|
|
||||||
" if you don't want to select comments preceding a declaration (these
|
|
||||||
" are usually the description of the function/class).
|
|
||||||
" You can set the global variable "g:py_select_trailing_comments" to 0
|
|
||||||
" if you don't want to select comments at the end of a function/class.
|
|
||||||
" If these variables are not defined, both leading and trailing comments
|
|
||||||
" are selected.
|
|
||||||
" Example: (in your .vimrc) "let g:py_select_leading_comments = 0"
|
|
||||||
" You may want to take a look at the 'shiftwidth' option for the
|
|
||||||
" shift commands...
|
|
||||||
"
|
|
||||||
" REQUIREMENTS:
|
|
||||||
" vim (>= 600)
|
|
||||||
"
|
|
||||||
" Shortcuts:
|
|
||||||
" [[ -- Jump to beginning of block
|
|
||||||
" ]] -- Jump to end of block
|
|
||||||
" ]v -- Select (Visual Line Mode) block
|
|
||||||
" ]< -- Shift block to left
|
|
||||||
" ]> -- Shift block to right
|
|
||||||
" ]c -- Select current/previous class
|
|
||||||
" ]f -- Select current/previous function
|
|
||||||
" ]<up> -- Jump to previous line with the same/lower indentation
|
|
||||||
" ]<down> -- Jump to next line with the same/lower indentation
|
|
||||||
|
|
||||||
|
|
||||||
map [[ :PBoB<CR>
|
|
||||||
vmap [[ :<C-U>PBoB<CR>m'gv``
|
|
||||||
map ]] :PEoB<CR>
|
|
||||||
vmap ]] :<C-U>PEoB<CR>m'gv``
|
|
||||||
|
|
||||||
map ]v [[V]]
|
|
||||||
map ]< [[V]]<
|
|
||||||
vmap ]< <
|
|
||||||
map ]> [[V]]>
|
|
||||||
vmap ]> >
|
|
||||||
|
|
||||||
map ]c :call PythonSelectObject("class")<CR>
|
|
||||||
map ]f :call PythonSelectObject("function")<CR>
|
|
||||||
|
|
||||||
map ]<up> :call PythonNextLine(-1)<CR>
|
|
||||||
map ]<down> :call PythonNextLine(1)<CR>
|
|
||||||
" You may prefer use <s-up> and <s-down>... :-)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
" Menu entries
|
|
||||||
nmenu <silent> &Python.Update\ IM-Python\ Menu
|
|
||||||
\:call UpdateMenu()<CR>
|
|
||||||
nmenu &Python.-Sep1- :
|
|
||||||
nmenu <silent> &Python.Beginning\ of\ Block<Tab>[[
|
|
||||||
\[[
|
|
||||||
nmenu <silent> &Python.End\ of\ Block<Tab>]]
|
|
||||||
\]]
|
|
||||||
nmenu &Python.-Sep2- :
|
|
||||||
nmenu <silent> &Python.Shift\ Block\ Left<Tab>]<
|
|
||||||
\]<
|
|
||||||
vmenu <silent> &Python.Shift\ Block\ Left<Tab>]<
|
|
||||||
\]<
|
|
||||||
nmenu <silent> &Python.Shift\ Block\ Right<Tab>]>
|
|
||||||
\]>
|
|
||||||
vmenu <silent> &Python.Shift\ Block\ Right<Tab>]>
|
|
||||||
\]>
|
|
||||||
nmenu &Python.-Sep3- :
|
|
||||||
vmenu <silent> &Python.Comment\ Selection
|
|
||||||
\:call PythonCommentSelection()<CR>
|
|
||||||
nmenu <silent> &Python.Comment\ Selection
|
|
||||||
\:call PythonCommentSelection()<CR>
|
|
||||||
vmenu <silent> &Python.Uncomment\ Selection
|
|
||||||
\:call PythonUncommentSelection()<CR>
|
|
||||||
nmenu <silent> &Python.Uncomment\ Selection
|
|
||||||
\:call PythonUncommentSelection()<CR>
|
|
||||||
nmenu &Python.-Sep4- :
|
|
||||||
nmenu <silent> &Python.Previous\ Class
|
|
||||||
\:call PythonDec("class", -1)<CR>
|
|
||||||
nmenu <silent> &Python.Next\ Class
|
|
||||||
\:call PythonDec("class", 1)<CR>
|
|
||||||
nmenu <silent> &Python.Previous\ Function
|
|
||||||
\:call PythonDec("function", -1)<CR>
|
|
||||||
nmenu <silent> &Python.Next\ Function
|
|
||||||
\:call PythonDec("function", 1)<CR>
|
|
||||||
nmenu &Python.-Sep5- :
|
|
||||||
nmenu <silent> &Python.Select\ Block<Tab>]v
|
|
||||||
\]v
|
|
||||||
nmenu <silent> &Python.Select\ Function<Tab>]f
|
|
||||||
\]f
|
|
||||||
nmenu <silent> &Python.Select\ Class<Tab>]c
|
|
||||||
\]c
|
|
||||||
nmenu &Python.-Sep6- :
|
|
||||||
nmenu <silent> &Python.Previous\ Line\ wrt\ indent<Tab>]<up>
|
|
||||||
\]<up>
|
|
||||||
nmenu <silent> &Python.Next\ Line\ wrt\ indent<Tab>]<down>
|
|
||||||
\]<down>
|
|
||||||
|
|
||||||
|
|
||||||
:com! PBoB execute "normal ".PythonBoB(line('.'), -1, 1)."G"
|
|
||||||
:com! PEoB execute "normal ".PythonBoB(line('.'), 1, 1)."G"
|
|
||||||
:com! UpdateMenu call UpdateMenu()
|
|
||||||
|
|
||||||
|
|
||||||
" Go to a block boundary (-1: previous, 1: next)
|
|
||||||
" If force_sel_comments is true, 'g:py_select_trailing_comments' is ignored
|
|
||||||
function! PythonBoB(line, direction, force_sel_comments)
|
|
||||||
let ln = a:line
|
|
||||||
let ind = indent(ln)
|
|
||||||
let mark = ln
|
|
||||||
let indent_valid = strlen(getline(ln))
|
|
||||||
let ln = ln + a:direction
|
|
||||||
if (a:direction == 1) && (!a:force_sel_comments) &&
|
|
||||||
\ exists("g:py_select_trailing_comments") &&
|
|
||||||
\ (!g:py_select_trailing_comments)
|
|
||||||
let sel_comments = 0
|
|
||||||
else
|
|
||||||
let sel_comments = 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
while((ln >= 1) && (ln <= line('$')))
|
|
||||||
if (sel_comments) || (match(getline(ln), "^\\s*#") == -1)
|
|
||||||
if (!indent_valid)
|
|
||||||
let indent_valid = strlen(getline(ln))
|
|
||||||
let ind = indent(ln)
|
|
||||||
let mark = ln
|
|
||||||
else
|
|
||||||
if (strlen(getline(ln)))
|
|
||||||
if (indent(ln) < ind)
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
let mark = ln
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
let ln = ln + a:direction
|
|
||||||
endwhile
|
|
||||||
|
|
||||||
return mark
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" Go to previous (-1) or next (1) class/function definition
|
|
||||||
function! PythonDec(obj, direction)
|
|
||||||
if (a:obj == "class")
|
|
||||||
let objregexp = "^\\s*class\\s\\+[a-zA-Z0-9_]\\+"
|
|
||||||
\ . "\\s*\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*:"
|
|
||||||
else
|
|
||||||
let objregexp = "^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*:"
|
|
||||||
endif
|
|
||||||
let flag = "W"
|
|
||||||
if (a:direction == -1)
|
|
||||||
let flag = flag."b"
|
|
||||||
endif
|
|
||||||
let res = search(objregexp, flag)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" Comment out selected lines
|
|
||||||
" commentString is inserted in non-empty lines, and should be aligned with
|
|
||||||
" the block
|
|
||||||
function! PythonCommentSelection() range
|
|
||||||
let commentString = "#"
|
|
||||||
let cl = a:firstline
|
|
||||||
let ind = 1000 " I hope nobody use so long lines! :)
|
|
||||||
|
|
||||||
" Look for smallest indent
|
|
||||||
while (cl <= a:lastline)
|
|
||||||
if strlen(getline(cl))
|
|
||||||
let cind = indent(cl)
|
|
||||||
let ind = ((ind < cind) ? ind : cind)
|
|
||||||
endif
|
|
||||||
let cl = cl + 1
|
|
||||||
endwhile
|
|
||||||
if (ind == 1000)
|
|
||||||
let ind = 1
|
|
||||||
else
|
|
||||||
let ind = ind + 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cl = a:firstline
|
|
||||||
execute ":".cl
|
|
||||||
" Insert commentString in each non-empty line, in column ind
|
|
||||||
while (cl <= a:lastline)
|
|
||||||
if strlen(getline(cl))
|
|
||||||
execute "normal ".ind."|i".commentString
|
|
||||||
endif
|
|
||||||
execute "normal j"
|
|
||||||
let cl = cl + 1
|
|
||||||
endwhile
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Uncomment selected lines
|
|
||||||
function! PythonUncommentSelection() range
|
|
||||||
" commentString could be different than the one from CommentSelection()
|
|
||||||
" For example, this could be "# \\="
|
|
||||||
let commentString = "#"
|
|
||||||
let cl = a:firstline
|
|
||||||
while (cl <= a:lastline)
|
|
||||||
let ul = substitute(getline(cl),
|
|
||||||
\"\\(\\s*\\)".commentString."\\(.*\\)$", "\\1\\2", "")
|
|
||||||
call setline(cl, ul)
|
|
||||||
let cl = cl + 1
|
|
||||||
endwhile
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" Select an object ("class"/"function")
|
|
||||||
function! PythonSelectObject(obj)
|
|
||||||
" Go to the object declaration
|
|
||||||
normal $
|
|
||||||
call PythonDec(a:obj, -1)
|
|
||||||
let beg = line('.')
|
|
||||||
|
|
||||||
if !exists("g:py_select_leading_comments") || (g:py_select_leading_comments)
|
|
||||||
let decind = indent(beg)
|
|
||||||
let cl = beg
|
|
||||||
while (cl>1)
|
|
||||||
let cl = cl - 1
|
|
||||||
if (indent(cl) == decind) && (getline(cl)[decind] == "#")
|
|
||||||
let beg = cl
|
|
||||||
else
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endwhile
|
|
||||||
endif
|
|
||||||
|
|
||||||
if (a:obj == "class")
|
|
||||||
let eod = "\\(^\\s*class\\s\\+[a-zA-Z0-9_]\\+\\s*"
|
|
||||||
\ . "\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*\\)\\@<=:"
|
|
||||||
else
|
|
||||||
let eod = "\\(^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*\\)\\@<=:"
|
|
||||||
endif
|
|
||||||
" Look for the end of the declaration (not always the same line!)
|
|
||||||
call search(eod, "")
|
|
||||||
|
|
||||||
" Is it a one-line definition?
|
|
||||||
if match(getline('.'), "^\\s*\\(#.*\\)\\=$", col('.')) == -1
|
|
||||||
let cl = line('.')
|
|
||||||
execute ":".beg
|
|
||||||
execute "normal V".cl."G"
|
|
||||||
else
|
|
||||||
" Select the whole block
|
|
||||||
normal j
|
|
||||||
let cl = line('.')
|
|
||||||
execute ":".beg
|
|
||||||
execute "normal V".PythonBoB(cl, 1, 0)."G"
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" Jump to the next line with the same (or lower) indentation
|
|
||||||
" Useful for moving between "if" and "else", for example.
|
|
||||||
function! PythonNextLine(direction)
|
|
||||||
let ln = line('.')
|
|
||||||
let ind = indent(ln)
|
|
||||||
let indent_valid = strlen(getline(ln))
|
|
||||||
let ln = ln + a:direction
|
|
||||||
|
|
||||||
while((ln >= 1) && (ln <= line('$')))
|
|
||||||
if (!indent_valid) && strlen(getline(ln))
|
|
||||||
break
|
|
||||||
else
|
|
||||||
if (strlen(getline(ln)))
|
|
||||||
if (indent(ln) <= ind)
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
let ln = ln + a:direction
|
|
||||||
endwhile
|
|
||||||
|
|
||||||
execute "normal ".ln."G"
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" update the IM-Python menu, that holds Classes and Functions
|
|
||||||
function! UpdateMenu()
|
|
||||||
let cline=line('.')
|
|
||||||
call MakeClassStructure ()
|
|
||||||
call MakeFuncStructure ()
|
|
||||||
execute "normal ".cline."Gzz"
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" make a menu that holds all of the classes
|
|
||||||
function! MakeClassStructure ()
|
|
||||||
norm mpgg0
|
|
||||||
while line(".") <= line("$")
|
|
||||||
if match ( getline("."), '^\s*class\s\+' ) != -1
|
|
||||||
norm ^w"nyw
|
|
||||||
let name=@n
|
|
||||||
exe 'menu IM-Python.classes.'.name.' '.line(".").'gg'
|
|
||||||
endif
|
|
||||||
if line(".") == line("$")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
norm j
|
|
||||||
endwhile
|
|
||||||
norm 'p
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" make a menu that holds all of the function definitions
|
|
||||||
function! MakeFuncStructure ()
|
|
||||||
norm mpgg0
|
|
||||||
while line(".") <= line("$")
|
|
||||||
if match ( getline("."), '^\s*def\s\+' ) != -1
|
|
||||||
norm ^w"nyw
|
|
||||||
let name=@n
|
|
||||||
exe 'menu IM-Python.functions.'.name.' '.line(".").'gg'
|
|
||||||
endif
|
|
||||||
if line(".") == line("$")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
norm j
|
|
||||||
endwhile
|
|
||||||
norm 'p
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
" vim:set et sts=2 sw=2:
|
|
||||||
Reference in New Issue
Block a user