mirror of
https://github.com/gryf/pythonhelper.git
synced 2026-04-24 06:21:25 +02:00
Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4a65fbb8b1 | |||
| 468b229276 | |||
| 154c343257 | |||
| 81bdd2f51c | |||
| 839012de28 | |||
| c41a450990 | |||
| 81a638762b | |||
| 3164a9e568 | |||
| 4f1dbc74bd | |||
| b2ca2a2fca | |||
| c011e488ce | |||
| d8a44e8439 | |||
| 03f3c9ef1e | |||
| c9e210a331 | |||
| 327dce4b7a | |||
| 9809859c73 | |||
| d40dbfe22b | |||
| e37a64afc4 | |||
| c6b824f536 | |||
| 8f88e4bc7f | |||
| 476707b687 | |||
| e1d3306adc | |||
| 1e1d1cc6f1 | |||
| 4a9a963dd6 | |||
| dcf5507d0f | |||
| 1b61929c9a | |||
| 0cccd82b2a | |||
| 702b07e390 | |||
| a361304e73 | |||
| aee6f328aa | |||
| ba115f64cc | |||
| d6046886a3 | |||
| f323d3cc74 | |||
| fe86a19e35 | |||
| c9dc1f3ec0 | |||
| e70cca0a11 | |||
| 005a35dcf6 | |||
| 42d72d9e6b | |||
| 6494b9de1c | |||
| 864d36fd02 | |||
| 333db2d78e | |||
| 888970d931 | |||
| 2e27597939 | |||
| 0ce33afc6c | |||
| 49d018fdc6 | |||
| 2caa97d75f | - | ||
| b0841be7ee | - | ||
| ab9d0e5e69 | - | ||
| f5b70c33bb | - | ||
| 91b230cb51 | - |
@@ -0,0 +1,24 @@
|
|||||||
|
Copyright (c) 2016, Roman Dobosz at al.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the organization nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL ROMAN DOBOSZ BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
This is a mirror of http://www.vim.org/scripts/script.php?script_id=435
|
|
||||||
|
|
||||||
Vim script to help moving around in larger Python source files. It displays current class, method or function the cursor is placed in in the status line for every python file. It's more clever than Yegappan Lakshmanan's taglist.vim because it takes into account indetation and comments to determine what tag the cursor is placed in and from version 0.80 doesn't need exuberant ctags utility.
|
|
||||||
|
|
||||||
Note: The script displays current tag on the status line only in NORMAL mode. This is because CursorHold event in VIM is fired up only in this mode. However if you'd like to know what tag you are in even in INSERT or VISUAL mode, contact me (email specified in the script) and I'll send you a patch that enables firing up CursorHold event in those modes as well.
|
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
Pythonhelper
|
||||||
|
============
|
||||||
|
|
||||||
|
This was a mirror of `http://www.vim.org/scripts/script.php?script_id=435`_.
|
||||||
|
|
||||||
|
This Vim plugin helps in Python development by placing a name of current class,
|
||||||
|
method or function under the cursor on the status line in normal and insert
|
||||||
|
mode.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
To use this plugin either ``+python`` or ``+python3`` feature compiled in vim is
|
||||||
|
required. To check it, issue ``:version`` in vim instance and look for python
|
||||||
|
entries.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Next, place one of the available functions either on your ``.vimrc``:
|
||||||
|
|
||||||
|
.. code:: vim
|
||||||
|
|
||||||
|
set statusline=[....]\ %{TagInStatusLine()}\ [.....]
|
||||||
|
|
||||||
|
or under ``~/.vim/ftplugin/python/your_file.vim``:
|
||||||
|
|
||||||
|
.. code:: vim
|
||||||
|
|
||||||
|
setlocal statusline=[....]\ %{TagInStatusLine()}\ [.....]
|
||||||
|
|
||||||
|
Functions, which may be placed on the status line are as follows:
|
||||||
|
|
||||||
|
* ``TagInStatusLine`` - shows name and type of the tag, i.e.:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
ClassName.some_method_name (method)
|
||||||
|
|
||||||
|
* ``TagInStatusLineTag`` - shows only the name:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
ClassName.some_method_name
|
||||||
|
|
||||||
|
* ``TagInStatusLineType`` - shows only the tag type:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
method
|
||||||
|
|
||||||
|
Restart vim, and you all set.
|
||||||
|
|
||||||
|
Changelog
|
||||||
|
---------
|
||||||
|
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| Version | Date | Author | Notes |
|
||||||
|
+=========+============+================+===========================================================================================================================================================================================+
|
||||||
|
| 1.1 | 2016-12-10 | Roman Dobosz | Fixed python3 enabled vim (without python2) |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 1.0 | 2016-05-30 | Roman Dobosz | Rewrite python part (simplifying the code, clean it up, separate from vimscript, add some tests), make it Python3 compatible, lots of other changes |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| | 2012-02-12 | cheater | `Several bug fixes`_, code cleanup, docs update |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| | 2010-02-13 | Oluf Lorenzen | `Updated the way how to display information on status line`_ |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 0.83 | 2010-01-04 | Michal Vitecek | Added support for the CursorHoldI event so that the class/method/function is recognized also in Insert mode |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 0.82 | 2009-07-10 | Michal Vitecek | fixed a bug when nested functions/classes were not properly detected |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 0.81 | 2003-03-13 | Michal Vitecek | fixed a small bug in indent level recognition |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 0.80 | 2002-10-18 | Michal Vitecek | removed the dependency on exuberant ctags which parsed the python source code wrongly anyways. From now on only VIM with python support is needed. This might greatly help windoze users. |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 0.72 | 2002-10-03 | Michal Vitecek | fixed problem with parsing ctags output on python files that use tabs |
|
||||||
|
| | | | when there is a syntax error in the file and ctags parses it incorrectly a warning is displayed in the command line |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 0.71 | 2002-10-02 | Michal Vitecek | fixed problem with undefined window-bound variable w:PHStatusLine when a window has been split into two. |
|
||||||
|
| | | | unbound event BufWinEnter because it's not needed because of the above change now |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
| 0.70 | 2002-10-02 | Michal Vitecek | Initial upload |
|
||||||
|
+---------+------------+----------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Originally, there was no licence whatsoever, so I've put it under under 3-clause
|
||||||
|
BSD license. See LICENSE file for details.
|
||||||
|
|
||||||
|
.. _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
|
||||||
|
.. _http://www.vim.org/scripts/script.php?script_id=435: http://www.vim.org/scripts/script.php?script_id=435
|
||||||
|
.. _Updated the way how to display information on status line: https://github.com/Finkregh/pythonhelper/commit/49d018fdc638f759a4d3d89f97ba5d26baddb1cd
|
||||||
|
.. _Several bug fixes: https://github.com/Finkregh/pythonhelper/pull/2
|
||||||
@@ -0,0 +1,241 @@
|
|||||||
|
"""
|
||||||
|
Simple analyzer for python source files. Collect and give info about file
|
||||||
|
structure: classes, its methods and functions.
|
||||||
|
|
||||||
|
Note, it'll probably not be behaving well with mixed spaces and tabs
|
||||||
|
indentation.
|
||||||
|
|
||||||
|
version: 1.0
|
||||||
|
date: 2016-05-30
|
||||||
|
author: Roman Dobosz <gryf@vimja.com>
|
||||||
|
"""
|
||||||
|
from collections import OrderedDict
|
||||||
|
import re
|
||||||
|
|
||||||
|
import vim
|
||||||
|
|
||||||
|
|
||||||
|
RE_TAG_TYPE = re.compile(r'\s*(def|class)[ \t]+([^(:]+).*')
|
||||||
|
RE_INDENT = re.compile(r'([ \t]*).*')
|
||||||
|
|
||||||
|
|
||||||
|
class PythonTag(object):
|
||||||
|
"""A simple storage class representing a python tag."""
|
||||||
|
|
||||||
|
def __init__(self, tag_type='', full_name='', line_number=0,
|
||||||
|
indent_level=0):
|
||||||
|
"""Initializes instances of Python tags.
|
||||||
|
|
||||||
|
:param tag_type: Tag type as string
|
||||||
|
:param full_name: Full tag name (in dotted notation)
|
||||||
|
:param line_number: line number on which the tag starts
|
||||||
|
:param indent_level: indentation level of the tag (number)
|
||||||
|
"""
|
||||||
|
self.tag_type = tag_type
|
||||||
|
self.name = full_name.split(".")[-1]
|
||||||
|
self.full_name = full_name
|
||||||
|
self.line_number = line_number
|
||||||
|
self.indent_level = indent_level
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
"""Representation for the PythonTag objects"""
|
||||||
|
return ("<PythonTag object at %s: %0.2d [%d] %s %s>" %
|
||||||
|
(hex(id(self)),
|
||||||
|
self.line_number,
|
||||||
|
self.indent_level,
|
||||||
|
self.tag_type,
|
||||||
|
self.full_name))
|
||||||
|
|
||||||
|
|
||||||
|
class EvenSimplerPythonTagsParser(object):
|
||||||
|
"""Simplified version for Python source code tag parser."""
|
||||||
|
|
||||||
|
def get_tags(self):
|
||||||
|
"""
|
||||||
|
Find tag in current buffer. Store them in OrderedDict and return.
|
||||||
|
|
||||||
|
:returns: OrderedDict with tags for current buffer or empty
|
||||||
|
OrderedDict in case of no tags found.
|
||||||
|
"""
|
||||||
|
tags_stack = []
|
||||||
|
tags = OrderedDict()
|
||||||
|
|
||||||
|
for line_no, line in enumerate(vim.current.buffer):
|
||||||
|
|
||||||
|
tag_match = RE_TAG_TYPE.match(line)
|
||||||
|
|
||||||
|
if not tag_match:
|
||||||
|
continue
|
||||||
|
|
||||||
|
indent_level = self._get_indent_level(line)
|
||||||
|
|
||||||
|
for _ in range(len(tags_stack)):
|
||||||
|
if tags_stack and tags_stack[-1].indent_level >= indent_level:
|
||||||
|
tags_stack.pop()
|
||||||
|
|
||||||
|
if not tags_stack:
|
||||||
|
break
|
||||||
|
|
||||||
|
tag = PythonTag(tag_match.group(1),
|
||||||
|
self._get_full_name(tags_stack,
|
||||||
|
tag_match.group(2)),
|
||||||
|
line_no,
|
||||||
|
indent_level)
|
||||||
|
tag.tag_type = self._get_tag_type(tag, tags_stack)
|
||||||
|
|
||||||
|
tags[line_no] = tag
|
||||||
|
tags_stack.append(tag)
|
||||||
|
|
||||||
|
return tags
|
||||||
|
|
||||||
|
def _get_tag_type(self, tag, tags_stack):
|
||||||
|
"""
|
||||||
|
Calculate name for provided tag.
|
||||||
|
|
||||||
|
:param tag: PythonTag object
|
||||||
|
:param tags_stack: list of PythonTag objects ordered from root to leaf
|
||||||
|
|
||||||
|
:returns: 'class', 'method' or 'function' as a tag type
|
||||||
|
"""
|
||||||
|
if tag.tag_type == 'class':
|
||||||
|
return 'class'
|
||||||
|
|
||||||
|
if tags_stack and tags_stack[-1].tag_type == 'class':
|
||||||
|
return 'method'
|
||||||
|
|
||||||
|
return 'function'
|
||||||
|
|
||||||
|
def _get_full_name(self, tags_stack, name):
|
||||||
|
"""
|
||||||
|
Return full logical name dot separated starting from upper entity
|
||||||
|
|
||||||
|
:param tags_stack: list of PythonTag objects ordered from root to leaf
|
||||||
|
:param name: class, method or function name
|
||||||
|
|
||||||
|
:returns: full name starting from root, separated by dot, like:
|
||||||
|
function_name
|
||||||
|
ClassName
|
||||||
|
ClassName.method_name
|
||||||
|
ClassName.method_name.inner_function_name
|
||||||
|
"""
|
||||||
|
if tags_stack:
|
||||||
|
return tags_stack[-1].full_name + "." + name
|
||||||
|
|
||||||
|
return name
|
||||||
|
|
||||||
|
def _get_indent_level(self, line):
|
||||||
|
"""
|
||||||
|
Calculate and get the indentation level for provided line
|
||||||
|
|
||||||
|
:param line: a string, against which indentation should be calculated
|
||||||
|
|
||||||
|
:returns: counted number of whitespaces
|
||||||
|
|
||||||
|
"""
|
||||||
|
return len(RE_INDENT.match(line).group(1))
|
||||||
|
|
||||||
|
|
||||||
|
class PythonHelper(object):
|
||||||
|
TAGS = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def find_tag(cls, buffer_number, changed_tick):
|
||||||
|
"""
|
||||||
|
Tries to find the best tag for the current cursor position.
|
||||||
|
|
||||||
|
:param buffer_number: buffer number in vim
|
||||||
|
:param changed_tick: always-increasing number used to indicate that
|
||||||
|
the buffer has been modified since the last time
|
||||||
|
"""
|
||||||
|
tag = PythonHelper._get_tag(buffer_number, changed_tick)
|
||||||
|
|
||||||
|
s_line = '%s (%s)' % (tag.full_name, tag.tag_type) if tag else ''
|
||||||
|
s_line_tag = tag.full_name if tag else ''
|
||||||
|
s_line_type = tag.tag_type if tag else ''
|
||||||
|
|
||||||
|
vim.command('let w:PHStatusLine="%s"' % s_line)
|
||||||
|
vim.command('let w:PHStatusLineTag="%s"' % s_line_tag)
|
||||||
|
vim.command('let w:PHStatusLineType="%s"' % s_line_type)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_tag(cls, buffer_number, changed_tick):
|
||||||
|
"""
|
||||||
|
Get the nearest tag object or None.
|
||||||
|
|
||||||
|
:param buffer_number: buffer number in vim
|
||||||
|
:param changed_tick: always-increasing number used to indicate that
|
||||||
|
the buffer has been modified since the last time
|
||||||
|
|
||||||
|
:returns: PythonTag tag object or None
|
||||||
|
"""
|
||||||
|
|
||||||
|
if PythonHelper.TAGS.get(buffer_number) and \
|
||||||
|
PythonHelper.TAGS[buffer_number]['changed_tick'] == changed_tick:
|
||||||
|
tags = PythonHelper.TAGS[buffer_number]['tags']
|
||||||
|
else:
|
||||||
|
parser = EvenSimplerPythonTagsParser()
|
||||||
|
tags = parser.get_tags()
|
||||||
|
PythonHelper.TAGS['buffer_number'] = {'changed_tick': changed_tick,
|
||||||
|
'tags': tags}
|
||||||
|
|
||||||
|
# get line number of current cursor position from Vim's internal data.
|
||||||
|
# It is always a positive number, starts from 1. Let's decrease it by
|
||||||
|
# one, so that it will not confuse us while operating vim interface by
|
||||||
|
# python, where everything starts from 0.
|
||||||
|
line_number = vim.current.window.cursor[0] - 1
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
line = vim.current.buffer[line_number]
|
||||||
|
except IndexError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
line_indent = len(RE_INDENT.match(line).group(1))
|
||||||
|
if line.strip():
|
||||||
|
break
|
||||||
|
# line contains nothing but white characters, looking up to grab
|
||||||
|
# some more context
|
||||||
|
line_number -= 1
|
||||||
|
|
||||||
|
tag = tags.get(line_number)
|
||||||
|
|
||||||
|
# if we have something at the beginning of the line, just return it;
|
||||||
|
# it doesn't matter if it is the tag found there or not
|
||||||
|
if line_indent == 0 or tag:
|
||||||
|
return tag
|
||||||
|
|
||||||
|
# get nearest tag
|
||||||
|
for line_no in range(line_number - 1, 0, -1):
|
||||||
|
tag = tags.get(line_no)
|
||||||
|
line = vim.current.buffer[line_no]
|
||||||
|
upper_line_indent = len(RE_INDENT.match(line).group(1))
|
||||||
|
|
||||||
|
if tag and upper_line_indent < line_indent:
|
||||||
|
return tag
|
||||||
|
|
||||||
|
if not line.strip():
|
||||||
|
continue
|
||||||
|
|
||||||
|
if upper_line_indent == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if upper_line_indent >= line_indent:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if tag and tag.indent_level >= line_indent:
|
||||||
|
tag = None
|
||||||
|
continue
|
||||||
|
|
||||||
|
return tag
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def delete_tags(cls, buffer_number):
|
||||||
|
"""Removes tag data for the specified buffer number.
|
||||||
|
|
||||||
|
:param buffer_number: buffer number in vim
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
del PythonHelper.TAGS[buffer_number]
|
||||||
|
except KeyError:
|
||||||
|
# If we don't have tags for specified buffer, just pass
|
||||||
|
pass
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
" File: pythonhelper.vim
|
||||||
|
" Author: Michal Vitecek <fuf-at-mageo-dot-cz>
|
||||||
|
" Author: Roman Dobosz <gryf@vimja.com>
|
||||||
|
" Version: 1.1
|
||||||
|
" License: 3-clause BSD license
|
||||||
|
" Last Modified: 2016-12-10
|
||||||
|
|
||||||
|
" VIM functions {{{
|
||||||
|
let s:plugin_path = expand('<sfile>:p:h', 1)
|
||||||
|
|
||||||
|
|
||||||
|
function! s:SetPython(msg)
|
||||||
|
if !exists('g:_python')
|
||||||
|
if has('python')
|
||||||
|
let g:_python = {'exec': 'python', 'file': 'pyfile'}
|
||||||
|
elseif has('python3')
|
||||||
|
let g:_python = {'exec': 'python3', 'file': 'py3file'}
|
||||||
|
else
|
||||||
|
echohl WarningMsg|echomsg a:msg|echohl None
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:PHLoader()
|
||||||
|
if !exists('g:pythonhelper_py_loaded')
|
||||||
|
call s:SetPython("PythonHelper unavailable: "
|
||||||
|
\ . "requires Vim with Python support")
|
||||||
|
execute g:_python['file'] . ' ' . s:plugin_path . '/pythonhelper.py'
|
||||||
|
let g:pythonhelper_py_loaded = 1
|
||||||
|
else
|
||||||
|
echohl "already loaded"
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! PHCursorHold()
|
||||||
|
" only Python is supported {{{
|
||||||
|
if (!exists('b:current_syntax') || (b:current_syntax != 'python'))
|
||||||
|
let w:PHStatusLine = ''
|
||||||
|
let w:PHStatusLineTag = ''
|
||||||
|
let w:PHStatusLineType = ''
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
" }}}
|
||||||
|
|
||||||
|
" call Python function findTag() with the current buffer number and change
|
||||||
|
" status indicator
|
||||||
|
execute g:_python['exec'] . ' PythonHelper.find_tag(' . expand("<abuf>") .
|
||||||
|
\ ', ' . b:changedtick . ')'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! PHBufferDelete()
|
||||||
|
" set the PHStatusLine etc for this window to an empty string
|
||||||
|
let w:PHStatusLine = ""
|
||||||
|
let w:PHStatusLineTag = ''
|
||||||
|
let w:PHStatusLineType = ''
|
||||||
|
|
||||||
|
" call Python function deleteTags() with the current buffer number and
|
||||||
|
" change status indicator
|
||||||
|
execute g:_python['exec'] . ' PythonHelper.delete_tags(' . expand("<abuf>") . ')'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! TagInStatusLine()
|
||||||
|
" return value of w:PHStatusLine in case it's set
|
||||||
|
if (exists("w:PHStatusLine"))
|
||||||
|
return w:PHStatusLine
|
||||||
|
" otherwise just return an empty string
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! TagInStatusLineTag()
|
||||||
|
" return value of w:PHStatusLineTag in case it's set
|
||||||
|
if (exists("w:PHStatusLineTag"))
|
||||||
|
return w:PHStatusLineTag
|
||||||
|
" otherwise just return an empty string
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! TagInStatusLineType()
|
||||||
|
" return value of w:PHStatusLineType in case it's set
|
||||||
|
if (exists("w:PHStatusLineType"))
|
||||||
|
return w:PHStatusLineType
|
||||||
|
" otherwise just return an empty string
|
||||||
|
else
|
||||||
|
return ""
|
||||||
|
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 customization {{{
|
||||||
|
|
||||||
|
" load Python code
|
||||||
|
call s:PHLoader()
|
||||||
|
|
||||||
|
" autocommands
|
||||||
|
autocmd CursorHold * call PHCursorHold()
|
||||||
|
autocmd CursorHoldI * call PHCursorHold()
|
||||||
|
autocmd BufDelete * silent call PHBufferDelete()
|
||||||
|
|
||||||
|
" period of no activity after which the CursorHold event is triggered
|
||||||
|
if (exists("g:pythonhelper_updatetime"))
|
||||||
|
let &updatetime = g:pythonhelper_updatetime
|
||||||
|
endif
|
||||||
|
|
||||||
|
" }}}
|
||||||
|
|
||||||
|
" vim:foldmethod=marker
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class Foo(object):
|
||||||
|
"""Some doc"""
|
||||||
|
CLASS_ATTR = {"dict": 1,
|
||||||
|
"bla": "foobar"}
|
||||||
|
|
||||||
|
def __init__(self, arg):
|
||||||
|
"""initializaion"""
|
||||||
|
self.arg = arg
|
||||||
|
|
||||||
|
def method(self, x, y):
|
||||||
|
"""very important method"""
|
||||||
|
|
||||||
|
def inner_funtion(x, y):
|
||||||
|
for i in y:
|
||||||
|
x = x + i
|
||||||
|
|
||||||
|
result = y[:]
|
||||||
|
result.append(x)
|
||||||
|
return result
|
||||||
|
|
||||||
|
result = None
|
||||||
|
result2 = """\
|
||||||
|
multiline
|
||||||
|
string
|
||||||
|
the
|
||||||
|
annoying
|
||||||
|
bastard"""
|
||||||
|
|
||||||
|
if self.arg < 100:
|
||||||
|
result = inner_funtion(x, y)
|
||||||
|
|
||||||
|
return result if result else result2
|
||||||
|
|
||||||
|
def main():
|
||||||
|
instance = Foo(10)
|
||||||
|
print(os.path.curdir, instance.method(2, [1, 2, 3]))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Executable
+146
@@ -0,0 +1,146 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
class Command(object):
|
||||||
|
def __call__(self, args):
|
||||||
|
print(args)
|
||||||
|
|
||||||
|
|
||||||
|
class Window(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.cursor = (1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
class Current(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.buffer = []
|
||||||
|
self.window = Window()
|
||||||
|
|
||||||
|
|
||||||
|
class MockVim(object):
|
||||||
|
current = Current()
|
||||||
|
command = Command()
|
||||||
|
|
||||||
|
with open('test_py_example.py') as fobj:
|
||||||
|
BUFFER = fobj.read().split('\n')
|
||||||
|
|
||||||
|
|
||||||
|
sys.modules['vim'] = vim = MockVim
|
||||||
|
|
||||||
|
|
||||||
|
import pythonhelper
|
||||||
|
|
||||||
|
|
||||||
|
class TestTagsHelperWithEmptyBuffer(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
vim.current.buffer = []
|
||||||
|
|
||||||
|
def test_get_tag(self):
|
||||||
|
vim.current.window.cursor = (1, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 2)
|
||||||
|
self.assertIsNone(tag)
|
||||||
|
|
||||||
|
|
||||||
|
class TestTagsHelper(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
vim.current.buffer = BUFFER
|
||||||
|
|
||||||
|
def test_import(self):
|
||||||
|
vim.current.window.cursor = (1, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 2)
|
||||||
|
self.assertIsNone(tag)
|
||||||
|
|
||||||
|
def test_class(self):
|
||||||
|
vim.current.window.cursor = (4, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'class')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (6, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'class')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (7, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'class')
|
||||||
|
|
||||||
|
def test_init(self):
|
||||||
|
vim.current.window.cursor = (9, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'method')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (11, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'method')
|
||||||
|
|
||||||
|
def test_method(self):
|
||||||
|
vim.current.window.cursor = (13, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'method')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (15, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'method')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (24, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'method')
|
||||||
|
|
||||||
|
# those tests should run if we have some kind of lexer analiser, not a
|
||||||
|
# simple py source parser.
|
||||||
|
#
|
||||||
|
# vim.current.window.cursor = (32, 1)
|
||||||
|
# tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
# self.assertEqual(tag.tag_type, 'method')
|
||||||
|
|
||||||
|
# vim.current.window.cursor = (34, 1)
|
||||||
|
# tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
# self.assertEqual(tag.tag_type, 'method')
|
||||||
|
|
||||||
|
def test_inner_function(self):
|
||||||
|
vim.current.window.cursor = (16, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'function')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (18, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'function')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (22, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'function')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (23, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'function')
|
||||||
|
|
||||||
|
def test_main(self):
|
||||||
|
vim.current.window.cursor = (37, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'function')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (38, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'function')
|
||||||
|
|
||||||
|
vim.current.window.cursor = (40, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertEqual(tag.tag_type, 'function')
|
||||||
|
|
||||||
|
def test_ifmain(self):
|
||||||
|
vim.current.window.cursor = (41, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertIsNone(tag)
|
||||||
|
|
||||||
|
vim.current.window.cursor = (42, 1)
|
||||||
|
tag = pythonhelper.PythonHelper._get_tag(1, 3)
|
||||||
|
self.assertIsNone(tag)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -1,364 +0,0 @@
|
|||||||
" File: pythonhelper.vim
|
|
||||||
" Author: Michal Vitecek <fuf-at-mageo-dot-cz>
|
|
||||||
" Version: 0.7
|
|
||||||
" Last Modified: Oct 2, 2002
|
|
||||||
"
|
|
||||||
" Overview
|
|
||||||
" --------
|
|
||||||
" Vim script to help moving around in larger Python source files. It displays
|
|
||||||
" current class, method or function the cursor is placed in in the status
|
|
||||||
" line for every python file. It's more clever than Yegappan Lakshmanan's
|
|
||||||
" taglist.vim because it takes into account indetation and comments to
|
|
||||||
" determine what tag the cursor is placed in.
|
|
||||||
"
|
|
||||||
" Requirements
|
|
||||||
" ------------
|
|
||||||
" This script needs VIM compiled with Python interpreter and relies on
|
|
||||||
" exuberant ctags utility to generate the tag listing. You can determine
|
|
||||||
" whether your VIM has Python support by issuing command :ver and looking for
|
|
||||||
" +python in the list of features.
|
|
||||||
"
|
|
||||||
" The exuberant ctags can be downloaded from http://ctags.sourceforge.net/ and
|
|
||||||
" should be reasonably new version (tested with 5.3).
|
|
||||||
"
|
|
||||||
" Note: The script doesn't display 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 on even in INSERT or
|
|
||||||
" VISUAL mode, contact me on the above specified email address and I'll send
|
|
||||||
" you patch that enables it.
|
|
||||||
"
|
|
||||||
" Installation
|
|
||||||
" ------------
|
|
||||||
" 1. Make sure your Vim has python feature on (+python). If not, you will need
|
|
||||||
" to recompile it with --with-pythoninterp option to the configure script
|
|
||||||
" 2. Copy script pythonhelper.vim to the $HOME/.vim/plugin directory
|
|
||||||
" 3. Edit the script and modify the location of your exuberant tags utility
|
|
||||||
" (variable CTAGS_PROGRAM).
|
|
||||||
" 4. Run Vim and open any python file.
|
|
||||||
"
|
|
||||||
python << EOS
|
|
||||||
|
|
||||||
# import of required modules {{{
|
|
||||||
import vim
|
|
||||||
import os
|
|
||||||
import popen2
|
|
||||||
import time
|
|
||||||
import sys
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
# CTAGS program and parameters {{{
|
|
||||||
CTAGS_PROGRAM = "/usr/local/bin/ctags"
|
|
||||||
CTAGS_PARAMETERS = "--language-force=python --format=2 --sort=0 --fields=+nK -L - -f - "
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# global dictionaries of tags and their line numbers, keys are buffer numbers {{{
|
|
||||||
TAGS = {}
|
|
||||||
TAGLINENUMBERS = {}
|
|
||||||
BUFFERTICKS = {}
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
def getNearestLineIndex(row, tagLineNumbers):
|
|
||||||
# DOC {{{
|
|
||||||
"""Returns index of line in tagLineNumbers list that is nearest to the
|
|
||||||
current cursor row.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
|
|
||||||
row -- current cursor row
|
|
||||||
|
|
||||||
tagLineNumbers -- list of tags' line numbers (ie. their position)
|
|
||||||
"""
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# CODE {{{
|
|
||||||
nearestLineNumber = -1
|
|
||||||
nearestLineIndex = -1
|
|
||||||
i = 0
|
|
||||||
for lineNumber in tagLineNumbers:
|
|
||||||
# if the current line is nearer the current cursor position, take it {{{
|
|
||||||
if (nearestLineNumber < lineNumber <= row):
|
|
||||||
nearestLineNumber = lineNumber
|
|
||||||
nearestLineIndex = i
|
|
||||||
# }}}
|
|
||||||
# if we've got past the current cursor position, let's end the search {{{
|
|
||||||
if (lineNumber >= row):
|
|
||||||
break
|
|
||||||
# }}}
|
|
||||||
i += 1
|
|
||||||
return nearestLineIndex
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
def getTags(bufferNumber, changedTick):
|
|
||||||
# DOC {{{
|
|
||||||
"""Reads the tags for the specified buffer number. It does so by executing
|
|
||||||
the CTAGS program and parsing its output. Returns tuple
|
|
||||||
(taglinenumber[buffer], tags[buffer]).
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
|
|
||||||
bufferNumber -- number of the current buffer
|
|
||||||
|
|
||||||
changedTick -- ever increasing number used to tell if the buffer has
|
|
||||||
been modified since the last time
|
|
||||||
"""
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# CODE {{{
|
|
||||||
global CTAGS_PROGRAM, CTAGS_PARAMETERS
|
|
||||||
global TAGLINENUMBERS, TAGS, BUFFERTICKS
|
|
||||||
|
|
||||||
|
|
||||||
# return immediately if there's no need to update the tags {{{
|
|
||||||
if ((BUFFERTICKS.has_key(bufferNumber)) and (BUFFERTICKS[bufferNumber] == changedTick)):
|
|
||||||
return (TAGLINENUMBERS[bufferNumber], TAGS[bufferNumber],)
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# read the tags and fill the global variables {{{
|
|
||||||
currentBuffer = vim.current.buffer
|
|
||||||
currentWindow = vim.current.window
|
|
||||||
row, col = currentWindow.cursor
|
|
||||||
|
|
||||||
# create a temporary file with the current content of the buffer {{{
|
|
||||||
fileName = "/tmp/.%s.%u.ph" % (os.path.basename(currentBuffer.name), os.getpid(),)
|
|
||||||
f = open(fileName, "w")
|
|
||||||
|
|
||||||
for line in currentBuffer:
|
|
||||||
f.write(line)
|
|
||||||
f.write('\n')
|
|
||||||
f.close()
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# run ctags on it {{{
|
|
||||||
try:
|
|
||||||
ctagsOutPut, ctagsInPut = popen2.popen4("%s %s" % (CTAGS_PROGRAM, CTAGS_PARAMETERS,))
|
|
||||||
ctagsInPut.write(fileName + "\n")
|
|
||||||
ctagsInPut.close()
|
|
||||||
except:
|
|
||||||
os.unlink(fileName)
|
|
||||||
return
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# parse the ctags' output {{{
|
|
||||||
tagLineNumbers = []
|
|
||||||
tags = {}
|
|
||||||
while 1:
|
|
||||||
line = ctagsOutPut.readline()
|
|
||||||
# if empty line has been read, it's the end of the file {{{
|
|
||||||
if (line == ''):
|
|
||||||
break
|
|
||||||
# }}}
|
|
||||||
# if the line starts with !, then it's a comment line {{{
|
|
||||||
if (line[0] == '!'):
|
|
||||||
continue
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# split the line into parts and parse the data {{{
|
|
||||||
# the format is: [0]tagName [1]fileName [2]tagLine [3]tagType [4]tagLineNumber [[5]tagOwner]
|
|
||||||
tagData = line.split('\t')
|
|
||||||
name = tagData[0]
|
|
||||||
# get the tag's indentation {{{
|
|
||||||
start = 2
|
|
||||||
j = 2
|
|
||||||
while ((j < len(tagData[2])) and (tagData[2][j].isspace())):
|
|
||||||
if (tagData[2][j] == '\t'):
|
|
||||||
start += 8
|
|
||||||
else:
|
|
||||||
start += 1
|
|
||||||
j += 1
|
|
||||||
# }}}
|
|
||||||
type = tagData[3]
|
|
||||||
line = int(tagData[4][5:])
|
|
||||||
if (len(tagData) == 6):
|
|
||||||
owner = tagData[5].strip()
|
|
||||||
else:
|
|
||||||
owner = None
|
|
||||||
# }}}
|
|
||||||
tagLineNumbers.append(line)
|
|
||||||
tags[line] = (name, type, owner, start)
|
|
||||||
ctagsOutPut.close()
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# clean up the now unnecessary stuff {{{
|
|
||||||
os.unlink(fileName)
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# update the global variables {{{
|
|
||||||
TAGS[bufferNumber] = tags
|
|
||||||
TAGLINENUMBERS[bufferNumber] = tagLineNumbers
|
|
||||||
BUFFERTICKS[bufferNumber] = changedTick
|
|
||||||
# }}}
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
return (TAGLINENUMBERS[bufferNumber], TAGS[bufferNumber],)
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
def findTag(bufferNumber, changedTick):
|
|
||||||
# DOC {{{
|
|
||||||
"""Tries to find the best tag for the current cursor position.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
|
|
||||||
bufferNumber -- number of the current buffer
|
|
||||||
|
|
||||||
changedTick -- ever increasing number used to tell if the buffer has
|
|
||||||
been modified since the last time
|
|
||||||
"""
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# CODE {{{
|
|
||||||
try:
|
|
||||||
# get the tags data for the current buffer
|
|
||||||
tagLineNumbers, tags = getTags(bufferNumber, changedTick)
|
|
||||||
|
|
||||||
# link to vim internal data {{{
|
|
||||||
currentBuffer = vim.current.buffer
|
|
||||||
currentWindow = vim.current.window
|
|
||||||
row, col = currentWindow.cursor
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# 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]
|
|
||||||
# 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)):
|
|
||||||
# compute the indentation of the line {{{
|
|
||||||
lineStart = 0
|
|
||||||
j = 0
|
|
||||||
while ((j < len(line)) and (line[j].isspace())):
|
|
||||||
if (line[j] == '\t'):
|
|
||||||
lineStart += 8
|
|
||||||
else:
|
|
||||||
lineStart += 1
|
|
||||||
j += 1
|
|
||||||
# if the line contains only spaces, it doesn't count {{{
|
|
||||||
if (j == len(line)):
|
|
||||||
continue
|
|
||||||
# }}}
|
|
||||||
# if the next character is # (python comment), this line doesn't count {{{
|
|
||||||
if (line[j] == '#'):
|
|
||||||
continue
|
|
||||||
# }}}
|
|
||||||
# }}}
|
|
||||||
# if the line's indentation starts before the nearest tag's one, the tag is wrong {{{
|
|
||||||
if (lineStart < tags[nearestLineNumber][3]):
|
|
||||||
nearestLineNumber = -1
|
|
||||||
break
|
|
||||||
# }}}
|
|
||||||
# }}}
|
|
||||||
# }}}
|
|
||||||
else:
|
|
||||||
nearestLineNumber = -1
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# describe the cursor position (what tag it's in) {{{
|
|
||||||
tagDescription = ""
|
|
||||||
if (nearestLineNumber > -1):
|
|
||||||
tagInfo = tags[nearestLineNumber]
|
|
||||||
# use the owner if any exists {{{
|
|
||||||
if (tagInfo[2] != None):
|
|
||||||
fullTagName = "%s.%s()" % (tagInfo[2].split(':')[1], tagInfo[0],)
|
|
||||||
# }}}
|
|
||||||
# otherwise use just the tag name {{{
|
|
||||||
else:
|
|
||||||
fullTagName = tagInfo[0]
|
|
||||||
# }}}
|
|
||||||
tagDescription = "[in %s (%s)]" % (fullTagName, tagInfo[1],)
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# update the variable for the status line so it will be updated next time
|
|
||||||
vim.command("let w:PHStatusLine=\"%s\"" % (tagDescription,))
|
|
||||||
except:
|
|
||||||
# spit out debugging information {{{
|
|
||||||
ec, ei, tb = sys.exc_info()
|
|
||||||
while (tb != None):
|
|
||||||
if (tb.tb_next == None):
|
|
||||||
break
|
|
||||||
tb = tb.tb_next
|
|
||||||
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):
|
|
||||||
# DOC {{{
|
|
||||||
"""Removes tags data for the specified buffer number.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
|
|
||||||
bufferNumber -- number of the buffer
|
|
||||||
"""
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
# CODE {{{
|
|
||||||
global TAGS, TAGLINENUMBERS, BUFFERTICKS
|
|
||||||
|
|
||||||
try:
|
|
||||||
del TAGS[bufferNumber]
|
|
||||||
del TAGLINENUMBERS[bufferNumber]
|
|
||||||
del BUFFERTICKS[bufferNumber]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
|
|
||||||
EOS
|
|
||||||
|
|
||||||
|
|
||||||
function! PHCursorHold()
|
|
||||||
" only python is supported {{{
|
|
||||||
if (exists('b:current_syntax') && (b:current_syntax != 'python'))
|
|
||||||
let w:PHStatusLine = ''
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
" }}}
|
|
||||||
|
|
||||||
" call python function findTag() with the current buffer number and changed ticks
|
|
||||||
execute 'python findTag(' . expand("<abuf>") . ', ' . b:changedtick . ')'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! PHBufferDelete()
|
|
||||||
" call python function deleteTags() with the cur
|
|
||||||
execute 'python deleteTags(' . expand("<abuf>") . ')'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! TagInStatusLine()
|
|
||||||
if (exists("w:PHStatusLine"))
|
|
||||||
return w:PHStatusLine
|
|
||||||
else
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
" autocommands binding
|
|
||||||
autocmd CursorHold * silent 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]
|
|
||||||
Reference in New Issue
Block a user