Speed improvements for reading text lines and the option to specify a range for Text.asLines([start[, end]]) Also some tweaks for the plug-in scripts and updates to pydocs.
This commit is contained in:
@@ -449,7 +449,7 @@ def parse_text(txt):
|
||||
desc.set_time()
|
||||
|
||||
global _parse_cache
|
||||
_parse_cache[hash(txt.name)] = desc
|
||||
_parse_cache[hash(txt)] = desc
|
||||
return desc
|
||||
|
||||
def get_modules(since=1):
|
||||
@@ -511,9 +511,12 @@ def get_context(txt):
|
||||
|
||||
"""
|
||||
|
||||
global CTX_NORMAL, CTX_SINGLE_QUOTE, CTX_DOUBLE_QUOTE, CTX_COMMENT
|
||||
l, cursor = txt.getCursorPos()
|
||||
lines = txt.asLines()[:l+1]
|
||||
lines = txt.asLines(0, l+1)
|
||||
|
||||
# FIXME: This method is too slow in large files for it to be called as often
|
||||
# as it is. So for lines below the 1000th line we do this... (quorn)
|
||||
if l > 1000: return CTX_NORMAL
|
||||
|
||||
# Detect context (in string or comment)
|
||||
in_str = CTX_NORMAL
|
||||
|
||||
@@ -49,9 +49,7 @@ def main():
|
||||
immediate = True
|
||||
pos += 5
|
||||
for i in range(pos, c):
|
||||
if line[i]=='.':
|
||||
pos = i+1
|
||||
elif not line[i].isalnum() and line[i] != '_':
|
||||
if not line[i].isalnum() and line[i] != '_' and line[i] != '.':
|
||||
immediate = False
|
||||
break
|
||||
|
||||
@@ -59,7 +57,7 @@ def main():
|
||||
if immediate:
|
||||
items = [(m, 'm') for m in get_modules()]
|
||||
items.sort(cmp = suggest_cmp)
|
||||
txt.suggest(items, '')
|
||||
txt.suggest(items, line[pos:c])
|
||||
return
|
||||
|
||||
# Found 'from' earlier, suggest import if not already there
|
||||
|
||||
@@ -30,23 +30,27 @@ def make_menu(items, eventoffs):
|
||||
letters.append(c)
|
||||
break
|
||||
|
||||
dict = {}
|
||||
entries = {}
|
||||
i = 0
|
||||
for item in items:
|
||||
i += 1
|
||||
c = item[0].lower()
|
||||
if not dict.has_key(c): dict[c] = []
|
||||
dict[c].append((item, i+eventoffs))
|
||||
entries.setdefault(c, []).append((item, i+eventoffs))
|
||||
|
||||
subs = []
|
||||
for c in letters:
|
||||
subs.append((c, dict[c]))
|
||||
subs.append((c, entries[c]))
|
||||
|
||||
return subs
|
||||
|
||||
def find_word(txt, word):
|
||||
i = 0
|
||||
for line in txt.asLines():
|
||||
txt.reset()
|
||||
while True:
|
||||
try:
|
||||
line = txt.readline()
|
||||
except StopIteration:
|
||||
break
|
||||
c = line.find(word)
|
||||
if c != -1:
|
||||
txt.setCursorPos(i, c)
|
||||
|
||||
@@ -66,6 +66,7 @@ def main():
|
||||
# Otherwise we suggest globals, keywords, etc.
|
||||
list = []
|
||||
pre = get_targets(line, c)
|
||||
desc = get_cached_descriptor(txt)
|
||||
|
||||
for k in KEYWORDS:
|
||||
list.append((k, 'k'))
|
||||
@@ -73,13 +74,16 @@ def main():
|
||||
for k, v in get_builtins().items():
|
||||
list.append((k, type_char(v)))
|
||||
|
||||
for k, v in get_imports(txt).items():
|
||||
for k, v in desc.imports.items():
|
||||
list.append((k, type_char(v)))
|
||||
|
||||
for k, v in get_defs(txt).items():
|
||||
for k, v in desc.classes.items():
|
||||
list.append((k, 'f'))
|
||||
|
||||
for k in get_vars(txt):
|
||||
for k, v in desc.defs.items():
|
||||
list.append((k, 'f'))
|
||||
|
||||
for k, v in desc.vars.items():
|
||||
list.append((k, 'v'))
|
||||
|
||||
list.sort(cmp = suggest_cmp)
|
||||
|
||||
@@ -49,7 +49,7 @@ def main():
|
||||
return
|
||||
|
||||
row, c = txt.getCursorPos()
|
||||
line = txt.asLines()[row]
|
||||
line = txt.asLines(row, row+1)[0]
|
||||
indent=0
|
||||
while indent<c and (line[indent]==' ' or line[indent]=='\t'):
|
||||
indent += 1
|
||||
|
||||
@@ -100,7 +100,7 @@ static PyObject *Text_write( BPy_Text * self, PyObject * value );
|
||||
static PyObject *Text_insert( BPy_Text * self, PyObject * value );
|
||||
static PyObject *Text_delete( BPy_Text * self, PyObject * value );
|
||||
static PyObject *Text_set( BPy_Text * self, PyObject * args );
|
||||
static PyObject *Text_asLines( BPy_Text * self );
|
||||
static PyObject *Text_asLines( BPy_Text * self, PyObject * args );
|
||||
static PyObject *Text_getCursorPos( BPy_Text * self );
|
||||
static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args );
|
||||
static PyObject *Text_getSelectPos( BPy_Text * self );
|
||||
@@ -136,8 +136,8 @@ static PyMethodDef BPy_Text_methods[] = {
|
||||
"(chars) - Deletes a number of characters to the left (chars<0) or right (chars>0)"},
|
||||
{"set", ( PyCFunction ) Text_set, METH_VARARGS,
|
||||
"(name, val) - Set attribute 'name' to value 'val'"},
|
||||
{"asLines", ( PyCFunction ) Text_asLines, METH_NOARGS,
|
||||
"() - Return text buffer as a list of lines"},
|
||||
{"asLines", ( PyCFunction ) Text_asLines, METH_VARARGS,
|
||||
"(start=0, end=nlines) - Return text buffer as a list of lines between start and end"},
|
||||
{"getCursorPos", ( PyCFunction ) Text_getCursorPos, METH_NOARGS,
|
||||
"() - Return cursor position as (row, col) tuple"},
|
||||
{"setCursorPos", ( PyCFunction ) Text_setCursorPos, METH_VARARGS,
|
||||
@@ -377,8 +377,8 @@ PyObject *Text_CreatePyObject( Text * txt )
|
||||
"couldn't create BPy_Text PyObject" );
|
||||
|
||||
pytxt->text = txt;
|
||||
pytxt->iol = 0;
|
||||
pytxt->ioc = 0;
|
||||
pytxt->iol = NULL;
|
||||
pytxt->ioc = -1;
|
||||
|
||||
return ( PyObject * ) pytxt;
|
||||
}
|
||||
@@ -430,8 +430,8 @@ static PyObject *Text_clear( BPy_Text * self)
|
||||
|
||||
static PyObject *Text_reset( BPy_Text * self )
|
||||
{
|
||||
self->iol = 0;
|
||||
self->ioc = 0;
|
||||
self->iol = NULL;
|
||||
self->ioc = -1;
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@@ -439,29 +439,33 @@ static PyObject *Text_reset( BPy_Text * self )
|
||||
static PyObject *Text_readline( BPy_Text * self )
|
||||
{
|
||||
PyObject *tmpstr;
|
||||
TextLine *line;
|
||||
int i;
|
||||
|
||||
if( !self->text )
|
||||
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
||||
"This object isn't linked to a Blender Text Object" );
|
||||
|
||||
for (i=0, line=self->text->lines.first; i<self->iol && line; i++, line=line->next);
|
||||
/* Reset */
|
||||
if (!self->iol && self->ioc == -1) {
|
||||
self->iol = self->text->lines.first;
|
||||
self->ioc = 0;
|
||||
}
|
||||
|
||||
if (!line) {
|
||||
if (!self->iol) {
|
||||
PyErr_SetString( PyExc_StopIteration, "End of buffer reached" );
|
||||
return PyString_FromString( "" );
|
||||
}
|
||||
|
||||
if (self->ioc > line->len)
|
||||
if (self->ioc > self->iol->len) {
|
||||
self->iol = NULL;
|
||||
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
||||
"Line length exceeded, text may have changed while reading" );
|
||||
}
|
||||
|
||||
tmpstr = PyString_FromString( line->line + self->ioc );
|
||||
if (line->next)
|
||||
tmpstr = PyString_FromString( self->iol->line + self->ioc );
|
||||
if (self->iol->next)
|
||||
PyString_ConcatAndDel( &tmpstr, PyString_FromString("\n") );
|
||||
|
||||
self->iol++;
|
||||
self->iol = self->iol->next;
|
||||
self->ioc = 0;
|
||||
|
||||
return tmpstr;
|
||||
@@ -485,6 +489,8 @@ static PyObject *Text_write( BPy_Text * self, PyObject * value )
|
||||
txt_move_eof( self->text, 0 );
|
||||
txt_set_undostate( oldstate );
|
||||
|
||||
Text_reset( self );
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
@@ -505,6 +511,8 @@ static PyObject *Text_insert( BPy_Text * self, PyObject * value )
|
||||
txt_insert_buf( self->text, str );
|
||||
txt_set_undostate( oldstate );
|
||||
|
||||
Text_reset( self );
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
@@ -531,6 +539,8 @@ static PyObject *Text_delete( BPy_Text * self, PyObject * value )
|
||||
num--;
|
||||
}
|
||||
txt_set_undostate( oldstate );
|
||||
|
||||
Text_reset( self );
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
@@ -554,27 +564,39 @@ static PyObject *Text_set( BPy_Text * self, PyObject * args )
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject *Text_asLines( BPy_Text * self )
|
||||
static PyObject *Text_asLines( BPy_Text * self, PyObject * args )
|
||||
{
|
||||
TextLine *line;
|
||||
PyObject *list, *tmpstr;
|
||||
int start=0, end=-1, i;
|
||||
|
||||
if( !self->text )
|
||||
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
||||
"This object isn't linked to a Blender Text Object" );
|
||||
|
||||
if( !PyArg_ParseTuple( args, "|ii", &start, &end ) )
|
||||
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
"expected upto two optional ints as arguments" );
|
||||
|
||||
if (start<0)
|
||||
start=0;
|
||||
|
||||
line = self->text->lines.first;
|
||||
for (i = 0; i < start && line->next; i++)
|
||||
line= line->next;
|
||||
|
||||
list = PyList_New( 0 );
|
||||
|
||||
if( !list )
|
||||
return EXPP_ReturnPyObjError( PyExc_MemoryError,
|
||||
"couldn't create PyList" );
|
||||
|
||||
while( line ) {
|
||||
while( line && (i < end || end == -1) ) {
|
||||
tmpstr = PyString_FromString( line->line );
|
||||
PyList_Append( list, tmpstr );
|
||||
Py_DECREF(tmpstr);
|
||||
line = line->next;
|
||||
i++;
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
@@ -41,7 +41,7 @@ extern PyTypeObject Text_Type;
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
Text * text; /* libdata must be second */
|
||||
int iol; /* index of line being read */
|
||||
TextLine * iol; /* current line being read or NULL if reset */
|
||||
int ioc; /* character offset in line being read */
|
||||
} BPy_Text;
|
||||
|
||||
|
||||
@@ -108,7 +108,8 @@ class Text:
|
||||
def readline():
|
||||
"""
|
||||
Reads a line of text from the buffer from the current IO pointer
|
||||
position to the end of the line.
|
||||
position to the end of the line. If the text has changed since the last
|
||||
read, reset() *must* be called.
|
||||
@rtype: string
|
||||
"""
|
||||
|
||||
@@ -137,11 +138,19 @@ class Text:
|
||||
@param data: The string to insert into the text buffer.
|
||||
"""
|
||||
|
||||
def asLines():
|
||||
def asLines(start=0, end=-1):
|
||||
"""
|
||||
Retrieve the contents of this Text buffer as a list of strings.
|
||||
Retrieve the contents of this Text buffer as a list of strings between
|
||||
the start and end lines specified. If end < 0 all lines from start will
|
||||
be included.
|
||||
@type start int
|
||||
@param start: Optional index of first line of the span to return
|
||||
@type end int
|
||||
@param end: Optional index of the line to which the span is taken or
|
||||
-1 to include all lines from start
|
||||
@rtype: list of strings
|
||||
@return: A list of strings, one for each line in the buffer
|
||||
@return: A list of strings, one for each line in the buffer between
|
||||
start and end.
|
||||
"""
|
||||
|
||||
def getCursorPos():
|
||||
@@ -154,7 +163,29 @@ class Text:
|
||||
|
||||
def setCursorPos(row, col):
|
||||
"""
|
||||
Set the position of the cursor in this Text buffer.
|
||||
Set the position of the cursor in this Text buffer. Any selection will
|
||||
be cleared. Use setSelectPos to extend a selection from the point
|
||||
specified here.
|
||||
@type row: int
|
||||
@param row: The index of the line in which to position the cursor.
|
||||
@type col: int
|
||||
@param col: The index of the character within the line to position the
|
||||
cursor.
|
||||
"""
|
||||
|
||||
def getSelectPos():
|
||||
"""
|
||||
Retrieve the position of the selection cursor in this Text buffer.
|
||||
@rtype: (int, int)
|
||||
@return: A pair (row, col) indexing the line and character of the
|
||||
selection cursor.
|
||||
"""
|
||||
|
||||
def setSelectPos(row, col):
|
||||
"""
|
||||
Set the position of the selection cursor in this Text buffer. This
|
||||
method should be called after setCursorPos to extend the selection to
|
||||
the specified point.
|
||||
@type row: int
|
||||
@param row: The index of the line in which to position the cursor.
|
||||
@type col: int
|
||||
@@ -180,7 +211,7 @@ class Text:
|
||||
the list. This is usually whatever precedes the cursor so that
|
||||
backspace will update it.
|
||||
"""
|
||||
|
||||
|
||||
def showDocs(docs):
|
||||
"""
|
||||
Displays a word-wrapped message box containing the specified
|
||||
|
||||
Reference in New Issue
Block a user