desc.set_time()
global _parse_cache
- _parse_cache[hash(txt.name)] = desc
+ _parse_cache[hash(txt)] = desc
return desc
def get_modules(since=1):
"""
- 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
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
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
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)
# 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'))
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)
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
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 );
"(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,
"couldn't create BPy_Text PyObject" );
pytxt->text = txt;
- pytxt->iol = 0;
- pytxt->ioc = 0;
+ pytxt->iol = NULL;
+ pytxt->ioc = -1;
return ( PyObject * ) pytxt;
}
static PyObject *Text_reset( BPy_Text * self )
{
- self->iol = 0;
- self->ioc = 0;
+ self->iol = NULL;
+ self->ioc = -1;
Py_RETURN_NONE;
}
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;
txt_move_eof( self->text, 0 );
txt_set_undostate( oldstate );
+ Text_reset( self );
+
Py_RETURN_NONE;
}
txt_insert_buf( self->text, str );
txt_set_undostate( oldstate );
+ Text_reset( self );
+
Py_RETURN_NONE;
}
num--;
}
txt_set_undostate( oldstate );
+
+ Text_reset( self );
Py_RETURN_NONE;
}
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;
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;
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
"""
@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():
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
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