1
0
mirror of https://github.com/gryf/.vim.git synced 2025-12-18 03:50:30 +01:00

Commented changes in plugins, updated vimwiki, repaired zoom plugin, added

buffergator, updated pythonhelper, removed leftovers
This commit is contained in:
2011-06-12 14:28:41 +02:00
parent 3de36e86f4
commit b66769d043
33 changed files with 3064 additions and 4145 deletions

View File

@@ -1,9 +1,7 @@
" File: pythonhelper.vim
" Author: Michal Vitecek <fuf-at-mageo-dot-cz>
" Version: 0.81
" Last Modified: Oct 24, 2002
"
" Modified by Marius Gedminas <mgedmin@b4net.lt>
" Version: 0.83
" Last Modified: Jan 4, 2010
"
" Overview
" --------
@@ -20,12 +18,6 @@
" support by issuing command :ver and looking for +python in the list of
" features.
"
" Note: The script displays current tag on the status line only in NORMAL
" mode. This is because CursorHold event is fired up only in this mode.
" However if you badly need to know what tag you are in even in INSERT or
" VISUAL mode, contact me on the above specified email address and I'll send
" you a patch that enables firing up CursorHold event in those modes as well.
"
" Installation
" ------------
" 1. Make sure your Vim has python feature on (+python). If not, you will need
@@ -33,30 +25,26 @@
" 2. Copy script pythonhelper.vim to the $HOME/.vim/plugin directory
" 3. Run Vim and open any python file.
"
" Marius Gedminas <marius@gedmin.as>:
" 4. change 'statusline' to include
" %{TagInStatusLine()}
"
if has("python")
python << EOS
# import of required modules {{{
import vim
import time
import sys
import re
import sys
import time
import traceback
import vim
# }}}
# global dictionaries of tags and their line numbers, keys are buffer numbers {{{
TAGS = {}
TAGLINENUMBERS = {}
BUFFERTICKS = {}
TAGS = {}
TAGLINENUMBERS = {}
BUFFERTICKS = {}
# }}}
# class PythonTag() {{{
class PythonTag:
class PythonTag(object):
# DOC {{{
"""A simple storage class representing a python tag.
"""
@@ -65,17 +53,17 @@ class PythonTag:
# STATIC VARIABLES {{{
# tag type IDs {{{
TAGTYPE_CLASS = 0
TAGTYPE_METHOD = 1
TAGTYPE_FUNCTION = 2
# possible tag types {{{
TT_CLASS = 0
TT_METHOD = 1
TT_FUNCTION = 2
# }}}
# tag type names {{{
typeName = {
TAGTYPE_CLASS : "class",
TAGTYPE_METHOD : "method",
TAGTYPE_FUNCTION : "function",
TAG_TYPE_NAME = {
TT_CLASS : "class",
TT_METHOD : "method",
TT_FUNCTION : "function",
}
# }}}
@@ -84,9 +72,9 @@ class PythonTag:
# METHODS {{{
def __init__(self, type, name, fullName, lineNumber, indentLevel, parentTag):
def __init__(self, type, name, fullName, lineNumber, indentLevel):
# DOC {{{
"""Initializes instances of class PythonTag().
"""Initializes instances of PythonTag().
Parameters
@@ -103,12 +91,13 @@ class PythonTag:
# }}}
# CODE {{{
self.type = type
self.name = name
self.fullName = fullName
self.lineNumber = lineNumber
self.indentLevel = indentLevel
self.parentTag = parentTag
# remember the settings {{{
self.type = type
self.name = name
self.fullName = fullName
self.lineNumber = lineNumber
self.indentLevel = indentLevel
# }}}
# }}}
@@ -119,10 +108,11 @@ class PythonTag:
# }}}
# CODE {{{
return "%s (%s) [%s, %u, %u]" % (self.name, PythonTag.typeName[self.type],
return "%s (%s) [%s, %u, %u]" % (self.name, PythonTag.TAG_TYPE_NAME[self.type],
self.fullName, self.lineNumber, self.indentLevel,)
# }}}
__repr__ = __str__
@@ -131,10 +121,9 @@ class PythonTag:
# class SimplePythonTagsParser() {{{
class SimplePythonTagsParser:
class SimplePythonTagsParser(object):
# DOC {{{
"""Provides a simple python tag parser. Returns list of PythonTag()
instances.
"""Provides a simple python tag parser.
"""
# }}}
@@ -143,13 +132,12 @@ class SimplePythonTagsParser:
# how many chars a single tab represents (visually)
TABSIZE = 8
# regexp used to get indentation and strip comments
commentsIndentStripRE = re.compile('([ \t]*)([^\n#]*).*')
# regexp used to get class name
classRE = re.compile('class[ \t]+([a-zA-Z0-9_]+)[ \t]*([(:].*|$)')
# regexp used to get method or function name
methodRE = re.compile('def[ \t]+([^(]+).*')
# regexp used to extract indentation and strip comments
COMMENTS_INDENT_RE = re.compile('([ \t]*)([^\n#]*).*')
# regexp used to extract a class name
CLASS_RE = re.compile('class[ \t]+([^(:]+).*')
# regexp used to extract a method or function name
METHOD_RE = re.compile('def[ \t]+([^(]+).*')
# }}}
@@ -158,7 +146,7 @@ class SimplePythonTagsParser:
def __init__(self, source):
# DOC {{{
"""Initializes the instance of class SimplePythonTagsParser().
"""Initializes instances of SimplePythonTagsParser().
Parameters
@@ -169,8 +157,8 @@ class SimplePythonTagsParser:
# CODE {{{
# make sure source has readline() method {{{
if (not(hasattr(source, 'readline') and
callable(source.readline))):
if ((hasattr(source, 'readline') == 0) or
(callable(source.readline) == 0)):
raise AttributeError("Source must have callable readline method.")
# }}}
@@ -181,19 +169,23 @@ class SimplePythonTagsParser:
def getTags(self):
# DOC {{{
"""Determines all the tags for the buffer. Returns tuple in format
"""Determines all the tags for the buffer. Returns a tuple in format
(tagLineNumbers, tags,).
"""
# }}}
# CODE {{{
tagLineNumbers = []
tags = {}
# initialize the resulting list of the tag line numbers and the tag information {{{
tagLineNumbers = []
tags = {}
# }}}
# list (stack) of all currently active tags
tagsStack = []
# initalize local auxiliary variables {{{
tagsStack = []
lineNumber = 0
# }}}
lineNumber = 0
# go through all the lines in the source and localize all python tags in it {{{
while 1:
# get next line
line = self.source.readline()
@@ -203,57 +195,73 @@ class SimplePythonTagsParser:
break
# }}}
# increase the line number
lineNumber += 1
lineMatch = self.commentsIndentStripRE.match(line)
lineContents = lineMatch.group(2)
# class tag {{{
tagMatch = self.classRE.match(lineContents)
# extract the line indentation characters and its content {{{
lineMatch = self.COMMENTS_INDENT_RE.match(line)
lineContent = lineMatch.group(2)
# }}}
# handle the class tag {{{
# match for the class tag
tagMatch = self.CLASS_RE.match(lineContent)
# if the class tag has been found, store some information on it {{{
if (tagMatch):
currentTag = self.getPythonTag(tagsStack, lineNumber, lineMatch.group(1),
tagMatch.group(1), self.tagClassTypeDecidingMethod)
tagLineNumbers.append(lineNumber)
tags[lineNumber] = currentTag
# }}}
# function/method/none tag {{{
# }}}
# handle the function/method/none tag {{{
else:
tagMatch = self.methodRE.match(lineContents)
# match for the method/function tag
tagMatch = self.METHOD_RE.match(lineContent)
# if the method/function tag has been found, store some information on it {{{
if (tagMatch):
currentTag = self.getPythonTag(tagsStack, lineNumber, lineMatch.group(1),
tagMatch.group(1), self.tagFunctionTypeDecidingMethod)
tagLineNumbers.append(lineNumber)
tags[lineNumber] = currentTag
# }}}
# }}}
# }}}
# return the tags data for the source
return (tagLineNumbers, tags,)
# }}}
def getPreviousTag(self, tagsStack):
def getParentTag(self, tagsStack):
# DOC {{{
"""Returns the previous tag (instance of PythonTag()) from the
specified tag list if possible. If not, returns None.
"""Returns the parent/enclosing tag (instance of PythonTag()) from the
specified tag list. If no such parent tag exists, returns None.
Parameters
tagsStack -- list (stack) of currently active PythonTag() instances
tagsStack -- list (stack) of currently open PythonTag() instances
"""
# }}}
# CODE {{{
# determine the parent tag {{{
if (len(tagsStack)):
previousTag = tagsStack[-1]
parentTag = tagsStack[-1]
else:
previousTag = None
parentTag = None
# }}}
# return the tag
return previousTag
return parentTag
# }}}
def computeIndentLevel(self, indentChars):
def computeIndentationLevel(indentChars):
# DOC {{{
"""Computes indent level from the specified string.
"""Computes the indentation level from the specified string.
Parameters
@@ -262,15 +270,21 @@ class SimplePythonTagsParser:
# }}}
# CODE {{{
# initialize the indentation level
indentLevel = 0
# compute the indentation level (expand tabs) {{{
for char in indentChars:
if (char == '\t'):
indentLevel += self.TABSIZE
indentLevel += SimplePythonTagsParser.TABSIZE
else:
indentLevel += 1
# }}}
# return the computed indentation level
return indentLevel
# }}}
computeIndentationLevel = staticmethod(computeIndentationLevel)
def getPythonTag(self, tagsStack, lineNumber, indentChars, tagName, tagTypeDecidingMethod):
@@ -290,58 +304,81 @@ class SimplePythonTagsParser:
tagName -- short name of the current tag
tagTypeDecidingMethod -- reference to method that is called to
determine type of the current tag
determine the type of the current tag
"""
# }}}
# CODE {{{
indentLevel = self.computeIndentLevel(indentChars)
previousTag = self.getPreviousTag(tagsStack)
# code for enclosed tag {{{
while (previousTag):
if (previousTag.indentLevel >= indentLevel):
# compute the indentation level
indentLevel = self.computeIndentationLevel(indentChars)
# get the parent tag
parentTag = self.getParentTag(tagsStack)
# handle an enclosed tag {{{
while (parentTag):
# if the indent level of the parent tag is greater than of the current tag, use parent tag of the parent tag {{{
if (parentTag.indentLevel >= indentLevel):
del tagsStack[-1]
# }}}
# otherwise we have all information on the current tag and can return it {{{
else:
tagType = tagTypeDecidingMethod(previousTag.type)
tag = PythonTag(tagType, tagName, "%s.%s" % (previousTag.fullName, tagName,), lineNumber, indentLevel, previousTag)
tagsStack.append(tag)
return tag
previousTag = self.getPreviousTag(tagsStack)
# create the tag
tag = PythonTag(tagTypeDecidingMethod(parentTag.type), tagName, "%s.%s" % (parentTag.fullName, tagName,), lineNumber, indentLevel)
# break the loop
break
# }}}
# use parent tag of the parent tag
parentTag = self.getParentTag(tagsStack)
# }}}
# code for tag in top indent level {{{
# handle a top-indent level tag {{{
else:
tagType = tagTypeDecidingMethod(None)
tag = PythonTag(tagType, tagName, tagName, lineNumber, indentLevel, None)
tagsStack.append(tag)
return tag
# create the tag
tag = PythonTag(tagTypeDecidingMethod(None), tagName, tagName, lineNumber, indentLevel)
# }}}
# add the tag to the list of tags
tagsStack.append(tag)
# return the tag
return tag
# }}}
def tagClassTypeDecidingMethod(self, previousTagsType):
def tagClassTypeDecidingMethod(self, parentTagType):
# DOC {{{
"""Returns tag type of the current tag based on its previous tag (super
tag) for classes.
Parameters
parentTagType -- type of the enclosing/parent tag
"""
# }}}
# CODE {{{
return PythonTag.TAGTYPE_CLASS
# is always class no matter what
return PythonTag.TT_CLASS
# }}}
def tagFunctionTypeDecidingMethod(self, previousTagsType):
def tagFunctionTypeDecidingMethod(self, parentTagType):
# DOC {{{
"""Returns tag type of the current tag based on its previous tag (super
tag) for functions/methods.
Parameters
parentTagType -- type of the enclosing/parent tag
"""
# }}}
# CODE {{{
if (previousTagsType == PythonTag.TAGTYPE_CLASS):
return PythonTag.TAGTYPE_METHOD
if (parentTagType == PythonTag.TT_CLASS):
return PythonTag.TT_METHOD
else:
return PythonTag.TAGTYPE_FUNCTION
return PythonTag.TT_FUNCTION
# }}}
@@ -350,7 +387,7 @@ class SimplePythonTagsParser:
# class VimReadlineBuffer() {{{
class VimReadlineBuffer:
class VimReadlineBuffer(object):
# DOC {{{
"""A simple wrapper class around vim's buffer that provides readline
method.
@@ -362,7 +399,7 @@ class VimReadlineBuffer:
def __init__(self, vimBuffer):
# DOC {{{
"""Initializes the instance of class VimReadlineBuffer().
"""Initializes instances of VimReadlineBuffer().
Parameters
@@ -371,9 +408,13 @@ class VimReadlineBuffer:
# }}}
# CODE {{{
self.vimBuffer = vimBuffer
self.currentLine = -1
self.bufferLines = len(vimBuffer)
# remember the settings
self.vimBuffer = vimBuffer
# initialize instance attributes {{{
self.currentLine = -1
self.bufferLines = len(vimBuffer)
# }}}
# }}}
@@ -385,6 +426,7 @@ class VimReadlineBuffer:
# }}}
# CODE {{{
# increase the current line counter
self.currentLine += 1
# notify end of file if we reached beyond the last line {{{
@@ -392,9 +434,10 @@ class VimReadlineBuffer:
return ''
# }}}
# return the line with added newline (vim stores the lines without newline)
# return the line with an added newline (vim stores the lines without it)
return "%s\n" % (self.vimBuffer[self.currentLine],)
# }}}
# }}}
# }}}
@@ -402,8 +445,8 @@ class VimReadlineBuffer:
def getNearestLineIndex(row, tagLineNumbers):
# DOC {{{
"""Returns index of line in tagLineNumbers list that is nearest to the
current cursor row.
"""Returns the index of line in 'tagLineNumbers' list that is nearest to the
specified cursor row.
Parameters
@@ -414,27 +457,33 @@ def getNearestLineIndex(row, tagLineNumbers):
# }}}
# CODE {{{
nearestLineNumber = -1
nearestLineIndex = -1
i = 0
for lineNumber in tagLineNumbers:
# initialize local auxiliary variables {{{
nearestLineNumber = -1
nearestLineIndex = -1
# }}}
# go through all tag line numbers and find the one nearest to the specified row {{{
for lineIndex, lineNumber in enumerate(tagLineNumbers):
# if the current line is nearer the current cursor position, take it {{{
if (nearestLineNumber < lineNumber <= row):
nearestLineNumber = lineNumber
nearestLineIndex = i
nearestLineNumber = lineNumber
nearestLineIndex = lineIndex
# }}}
# if we've got past the current cursor position, let's end the search {{{
if (lineNumber >= row):
break
# }}}
i += 1
# }}}
# return index of the line with the nearest tag
return nearestLineIndex
# }}}
def getTags(bufferNumber, changedTick):
# DOC {{{
"""Reads the tags for the specified buffer number. Returns tuple
"""Reads the tags for the specified buffer number. Returns a tuple
(taglinenumber[buffer], tags[buffer],).
Parameters
@@ -447,10 +496,11 @@ def getTags(bufferNumber, changedTick):
# }}}
# CODE {{{
global TAGLINENUMBERS, TAGS, BUFFERTICKS
# define global variables
global TAGLINENUMBERS, TAGS, BUFFERTICKS
# return immediately if there's no need to update the tags {{{
if ((BUFFERTICKS.has_key(bufferNumber)) and (BUFFERTICKS[bufferNumber] == changedTick)):
if (BUFFERTICKS.get(bufferNumber, None) == changedTick):
return (TAGLINENUMBERS[bufferNumber], TAGS[bufferNumber],)
# }}}
@@ -460,12 +510,12 @@ def getTags(bufferNumber, changedTick):
# }}}
# update the global variables {{{
TAGS[bufferNumber] = tags
TAGLINENUMBERS[bufferNumber] = tagLineNumbers
BUFFERTICKS[bufferNumber] = changedTick
TAGS[bufferNumber] = tags
TAGLINENUMBERS[bufferNumber] = tagLineNumbers
BUFFERTICKS[bufferNumber] = changedTick
# }}}
# return the tags data
# return the tuple (tagLineNumbers, tags,)
return (tagLineNumbers, tags,)
# }}}
@@ -484,12 +534,12 @@ def findTag(bufferNumber, changedTick):
# }}}
# CODE {{{
# try to find the best tag {{{
try:
# get the tags data for the current buffer {{{
# get the tags data for the current buffer
tagLineNumbers, tags = getTags(bufferNumber, changedTick)
# }}}
# link to vim internal data {{{
# link to vim's internal data {{{
currentBuffer = vim.current.buffer
currentWindow = vim.current.window
row, col = currentWindow.cursor
@@ -497,66 +547,97 @@ def findTag(bufferNumber, changedTick):
# get the index of the nearest line
nearestLineIndex = getNearestLineIndex(row, tagLineNumbers)
# if any line was found, try to find if the tag is appropriate {{{
# (ie. the cursor can be below the last tag but on a code that has nothing
# to do with the tag, because it's indented differently, in such case no
# appropriate tag has been found.)
if (nearestLineIndex > -1):
nearestLineNumber = tagLineNumbers[nearestLineIndex]
tagInfo = tags[nearestLineNumber]
# walk through all the lines in range (nearestTagLine, cursorRow) {{{
for i in xrange(nearestLineNumber + 1, row):
line = currentBuffer[i]
# count the indentation of the line, if it's lower that the tag's, the found tag is wrong {{{
if (len(line)):
while (nearestLineIndex > -1):
# get the line number of the nearest tag
nearestLineNumber = tagLineNumbers[nearestLineIndex]
# walk through all the lines in range (nearestTagLine, cursorRow) {{{
for lineNumber in xrange(nearestLineNumber + 1, row):
# get the current line
line = currentBuffer[lineNumber]
# count the indentation of the line, if it's lower than the tag's, the tag is invalid {{{
if (len(line)):
# initialize local auxiliary variables {{{
lineStart = 0
i = 0
# }}}
# compute the indentation of the line {{{
lineStart = 0
j = 0
while ((j < len(line)) and (line[j].isspace())):
if (line[j] == '\t'):
lineStart += SimplePythonTagsParser.TABSIZE
else:
lineStart += 1
j += 1
# if the line contains only spaces, it doesn't count {{{
if (j == len(line)):
while ((i < len(line)) and (line[i].isspace())):
# move the start of the line code {{{
if (line[i] == '\t'):
lineStart += SimplePythonTagsParser.TABSIZE
else:
lineStart += 1
# }}}
# go to the next character on the line
i += 1
# }}}
# if the line contains only spaces, skip it {{{
if (i == len(line)):
continue
# }}}
# if the next character is # (python comment), this line doesn't count {{{
if (line[j] == '#'):
# if the next character is a '#' (python comment), skip the line {{{
if (line[i] == '#'):
continue
# }}}
# if the line's indentation starts before or at the nearest tag's one, the tag is invalid {{{
if (lineStart <= tags[nearestLineNumber].indentLevel):
nearestLineIndex -= 1
break
# }}}
# if the line's indentation starts before or at the nearest tag's one, the tag is wrong {{{
while tagInfo is not None and lineStart <= tagInfo.indentLevel:
tagInfo = tagInfo.parentTag
# }}}
# }}}
# }}}
# }}}
# the tag is appropriate, so use it {{{
else:
break
# }}}
# }}}
# no appropriate tag has been found {{{
else:
tagInfo = None
nearestLineNumber = -1
# }}}
# describe the cursor position (what tag it's in) {{{
# describe the cursor position (what tag the cursor is on) {{{
# reset the description
tagDescription = ""
if tagInfo is not None:
## tagDescription = "[in %s (%s)]" % (tagInfo.fullName, PythonTag.typeName[tagInfo.type],)
tagDescription = "[%s]" % (tagInfo.fullName, )
# if an appropriate tag has been found, set the description accordingly {{{
if (nearestLineNumber > -1):
tagInfo = tags[nearestLineNumber]
tagDescription = "[in %s (%s)]" % (tagInfo.fullName, PythonTag.TAG_TYPE_NAME[tagInfo.type],)
# }}}
# }}}
# update the variable for the status line so it will be updated next time
# update the variable for the status line so it get updated with the new description
vim.command("let w:PHStatusLine=\"%s\"" % (tagDescription,))
except:
# spit out debugging information {{{
# }}}
# handle possible exceptions {{{
except Exception:
# bury into the traceback {{{
ec, ei, tb = sys.exc_info()
while (tb != None):
if (tb.tb_next == None):
break
tb = tb.tb_next
# }}}
# spit out the error {{{
print "ERROR: %s %s %s:%u" % (ec.__name__, ei, tb.tb_frame.f_code.co_filename, tb.tb_lineno,)
time.sleep(0.5)
# }}}
# }}}
# }}}
def deleteTags(bufferNumber):
@@ -570,8 +651,10 @@ def deleteTags(bufferNumber):
# }}}
# CODE {{{
global TAGS, TAGLINENUMBERS, BUFFERTICKS
# define global variables
global TAGS, TAGLINENUMBERS, BUFFERTICKS
# try to delete the tags for the buffer {{{
try:
del TAGS[bufferNumber]
del TAGLINENUMBERS[bufferNumber]
@@ -579,6 +662,7 @@ def deleteTags(bufferNumber):
except:
pass
# }}}
# }}}
EOS
@@ -617,33 +701,63 @@ function! TagInStatusLine()
endif
endfunction
function! PHPreviousClassMethod()
call search('^[ \t]*\(class\|def\)\>', 'bw')
endfunction
function! PHNextClassMethod()
call search('^[ \t]*\(class\|def\)\>', 'w')
endfunction
function! PHPreviousClass()
call search('^[ \t]*class\>', 'bw')
endfunction
function! PHNextClass()
call search('^[ \t]*class\>', 'w')
endfunction
function! PHPreviousMethod()
call search('^[ \t]*def\>', 'bw')
endfunction
function! PHNextMethod()
call search('^[ \t]*def\>', 'w')
endfunction
" }}}
" event binding, vim customizing {{{
" autocommands binding
if v:version >= 700
autocmd CursorMoved * call PHCursorHold()
else
autocmd CursorHold * call PHCursorHold()
endif
autocmd CursorHold * call PHCursorHold()
autocmd CursorHoldI * call PHCursorHold()
autocmd BufDelete * silent call PHBufferDelete()
"" " time that determines after how long time of no activity the CursorHold event
"" " is fired up
"" set updatetime=1000
""
"" " color of the current tag in the status line (bold cyan on black)
"" highlight User1 gui=bold guifg=cyan guibg=black
"" " color of the modified flag in the status line (bold black on red)
"" highlight User2 gui=bold guifg=black guibg=red
"" " the status line will be displayed for every window
"" set laststatus=2
"" " set the status line to display some useful information
"" set stl=%-f%r\ %2*%m%*\ \ \ \ %1*%{TagInStatusLine()}%*%=[%l:%c]\ \ \ \ [buf\ %n]
" time that determines after how long time of no activity the CursorHold event
" is fired up
set updatetime=1000
" color of the current tag in the status line (bold cyan on black)
" gryf: i don't like coloring apart from current colorscheme. keep it simple.
"highlight User1 gui=bold guifg=cyan guibg=black
" color of the modified flag in the status line (bold black on red)
" gryf: i don't like coloring apart from current colorscheme. keep it simple.
"highlight User2 gui=bold guifg=black guibg=red
" the status line will be displayed for every window
set laststatus=2
" set the status line to display some useful information
"set stl=%-f%r\ %2*%m%*\ \ \ \ %1*%{TagInStatusLine()}%*%=[%l:%c]\ \ \ \ [buf\ %n]
" gryf: I like my status bar. Don't change it. Just add information.
setlocal statusline=%<%F\ \ \ %{TagInStatusLine()}\ %h%m%r%=%(%l,%c%V%)\ %3p%%
" }}}
" vim:foldmethod=marker
endif " has("python")