" -*- vim -*-" FILE: python_fn.vim" LAST MODIFICATION: 2008年08月28日 8:19pm" (C) Copyright 2001-2005 Mikael Berthe <bmikael@lists.lilotux.net>" Maintained by Jon Franklin <jvfranklin@gmail.com>" Version: 1.13" USAGE:"" Save this file to $VIMFILES/ftplugin/python.vim. You can have multiple" python ftplugins by creating $VIMFILES/ftplugin/python and saving your" ftplugins in that directory. If saving this to the global ftplugin" directory, this is the recommended method, since vim ships with an" ftplugin/python.vim file already." 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 (>= 7)"" Shortcuts:" ]t -- Jump to beginning of block" ]e -- Jump to end of block" ]v -- Select (Visual Line Mode) block" ]< -- Shift block to left" ]> -- Shift block to right" ]# -- Comment selection" ]u -- Uncomment selection" ]c -- Select current/previous class" ]d -- Select current/previous function" ]<up> -- Jump to previous line with the same/lower indentation" ]<down> -- Jump to next line with the same/lower indentation" Only do this when not done yet for this bufferif exists("b:loaded_py_ftplugin")finishendiflet b:loaded_py_ftplugin = 1map ]t :PBoB<CR>vmap ]t :<C-U>PBOB<CR>m'gv``map ]e :PEoB<CR>vmap ]e :<C-U>PEoB<CR>m'gv``map ]v ]tV]emap ]< ]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 ]c :call PythonSelectObject("class")<CR>map ]d :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 classmap ]J :call PythonDec("class", -1)<CR>vmap ]J :call PythonDec("class", -1)<CR>" jump to next classmap ]j :call PythonDec("class", 1)<CR>vmap ]j :call PythonDec("class", 1)<CR>" jump to previous functionmap ]F :call PythonDec("function", -1)<CR>vmap ]F :call PythonDec("function", -1)<CR>" jump to next functionmap ]f :call PythonDec("function", 1)<CR>vmap ]f :call PythonDec("function", 1)<CR>" Menu entriesnmenu <silent> &Python.Update\ IM-Python\ Menu\:call UpdateMenu()<CR>nmenu &Python.-Sep1- :nmenu <silent> &Python.Beginning\ of\ Block<Tab>[t\]tnmenu <silent> &Python.End\ of\ Block<Tab>]e\]enmenu &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\]unmenu <silent> &Python.Uncomment\ Selection<Tab>]u\]unmenu &Python.-Sep4- :nmenu <silent> &Python.Previous\ Class<Tab>]J\]Jnmenu <silent> &Python.Next\ Class<Tab>]j\]jnmenu <silent> &Python.Previous\ Function<Tab>]F\]Fnmenu <silent> &Python.Next\ Function<Tab>]f\]fnmenu &Python.-Sep5- :nmenu <silent> &Python.Select\ Block<Tab>]v\]vnmenu <silent> &Python.Select\ Function<Tab>]d\]dnmenu <silent> &Python.Select\ Class<Tab>]c\]cnmenu &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 ignoredfunction! PythonBoB(line, direction, force_sel_comments)let ln = a:linelet ind = indent(ln)let mark = lnlet indent_valid = strlen(getline(ln))let ln = ln + a:directionif (a:direction == 1) && (!a:force_sel_comments) &&\ exists("g:py_select_trailing_comments") &&\ (!g:py_select_trailing_comments)let sel_comments = 0elselet sel_comments = 1endifwhile((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 = lnelseif (strlen(getline(ln)))if (indent(ln) < ind)breakendiflet mark = lnendifendifendiflet ln = ln + a:directionendwhilereturn markendfunction" Go to previous (-1) or next (1) class/function definitionfunction! PythonDec(obj, direction)if (a:obj == "class")let objregexp = "^\\s*class\\s\\+[a-zA-Z0-9_]\\+"\ . "\\s*\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*:"elselet objregexp = "^\\s*def\\s\\+[a-zA-Z0-9_]\\+\\s*(\\_[^:#]*)\\s*:"endiflet flag = "W"if (a:direction == -1)let flag = flag."b"endiflet res = search(objregexp, flag)endfunction" Comment out selected lines" commentString is inserted in non-empty lines, and should be aligned with" the blockfunction! PythonCommentSelection() rangelet commentString = "#"let cl = a:firstlinelet ind = 1000 " I hope nobody use so long lines! :)" Look for smallest indentwhile (cl <= a:lastline)if strlen(getline(cl))let cind = indent(cl)let ind = ((ind < cind) ? ind : cind)endiflet cl = cl + 1endwhileif (ind == 1000)let ind = 1elselet ind = ind + 1endiflet cl = a:firstlineexecute ":".cl" Insert commentString in each non-empty line, in column indwhile (cl <= a:lastline)if strlen(getline(cl))execute "normal ".ind."|i".commentStringendifexecute "normal \<Down>"let cl = cl + 1endwhileendfunction" Uncomment selected linesfunction! PythonUncommentSelection() range" commentString could be different than the one from CommentSelection()" For example, this could be "# \\="let commentString = "#"let cl = a:firstlinewhile (cl <= a:lastline)let ul = substitute(getline(cl),\"\\(\\s*\\)".commentString."\\(.*\\)$", "\1円\2円", "")call setline(cl, ul)let cl = cl + 1endwhileendfunction" Select an object ("class"/"function")function! PythonSelectObject(obj)" Go to the object declarationnormal $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 = begwhile (cl>1)let cl = cl - 1if (indent(cl) == decind) && (getline(cl)[decind] == "#")let beg = clelsebreakendifendwhileendifif (a:obj == "class")let eod = "\\(^\\s*class\\s\\+[a-zA-Z0-9_]\\+\\s*"\ . "\\((\\([a-zA-Z0-9_,. \\t\\n]\\)*)\\)\\=\\s*\\)\\@<=:"elselet 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('.')) == -1let cl = line('.')execute ":".begexecute "normal V".cl."G"else" Select the whole blockexecute "normal \<Down>"let cl = line('.')execute ":".begexecute "normal V".PythonBoB(cl, 1, 0)."G"endifendfunction" 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:directionwhile((ln >= 1) && (ln <= line('$')))if (!indent_valid) && strlen(getline(ln))breakelseif (strlen(getline(ln)))if (indent(ln) <= ind)breakendifendifendiflet ln = ln + a:directionendwhileexecute "normal ".ln."G"endfunctionfunction! 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 bufferif exists("g:menuran")aunmenu IM-Pythonendiflet restore_fe = &foldenableset nofoldenable" preserve disposition of window and cursorlet cline=line('.')let ccol=col('.') - 1norm Hlet hline=line('.')" create the menucall MenuBuilder()" restore disposition of window and cursorexe "norm ".hline."Gzt"let dnscroll=cline-hlineexe "norm ".dnscroll."j".ccol."l"let &foldenable = restore_feendfunctionfunction! MenuBuilder()norm gg0let currentclass = -1let classlist = []let parentclass = ""while line(".") < line("$")" search for a class or functionif match ( getline("."), '^\s*class\s\+[_a-zA-Z].*\|^\s*def\s\+[_a-zA-Z].*' ) != -1norm ^let linenum = line('.')let indentcol = col('.')norm "nyelet classordef=@nnorm w"nywgelet objname=@nlet parentclass = FindParentClass(classlist, indentcol)if classordef == "class"call AddClass(objname, linenum, parentclass)else " this is a functioncall AddFunction(objname, linenum, parentclass)endif" We actually created a menu, so lets set the global variablelet g:menuran=1call RebuildClassList(classlist, [objname, indentcol], classordef)endif " line matchednorm jendwhileendfunction" 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 indentationfunction! RebuildClassList(classlist, newclass, classordef)let i = len(a:classlist) - 1while i > -1if a:newclass[1] <= a:classlist[i][1]call remove(a:classlist, i)endiflet i = i - 1endwhileif a:classordef == "class"call add(a:classlist, a:newclass)endifendfunction" we found a class or function, determine its parent class based on" indentation and what's contained in classlistfunction! FindParentClass(classlist, indentcol)let i = 0let parentclass = ""while i < len(a:classlist)if a:indentcol <= a:classlist[i][1]breakelseif len(parentclass) == 0let parentclass = a:classlist[i][0]elselet parentclass = parentclass.'\.'.a:classlist[i][0]endifendiflet i = i + 1endwhilereturn parentclassendfunction" add a class to the menufunction! AddClass(classname, lineno, parentclass)if len(a:parentclass) > 0let classstring = a:parentclass.'\.'.a:classnameelselet classstring = a:classnameendifexe 'menu IM-Python.classes.'.classstring.' :call <SID>JumpToAndUnfold('.a:lineno.')<CR>'endfunction" add a function to the menu, grouped by member classfunction! AddFunction(functionname, lineno, parentclass)if len(a:parentclass) > 0let funcstring = a:parentclass.'.'.a:functionnameelselet funcstring = a:functionnameendifexe 'menu IM-Python.functions.'.funcstring.' :call <SID>JumpToAndUnfold('.a:lineno.')<CR>'endfunctionfunction! s:JumpToAndUnfold(line)" Go to the right lineexecute 'normal '.a:line.'gg'" Check to see if we are in a foldlet lvl = foldlevel(a:line)if lvl != 0" and if so, then expand the fold out, other wise, ignore this part.execute 'normal 15zo'endifendfunction"" This one will work only on vim 6.2 because of the try/catch expressions." function! s:JumpToAndUnfoldWithExceptions(line)" try" execute 'normal '.a:line.'gg15zo'" catch /^Vim\((\a\+)\)\=:E490:/" " Do nothing, just consume the error" endtry"endfunction" vim:set et sts=2 sw=2:
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。