📄 if_python.c
字号:
static PyObject *RangeAppend(PyObject *, PyObject *);
/* Window list type - Implementation functions
* -------------------------------------------
*/
static int WinListLength(PyObject *);
static PyObject *WinListItem(PyObject *, int);
/* Buffer list type - Implementation functions
* -------------------------------------------
*/
static int BufListLength(PyObject *);
static PyObject *BufListItem(PyObject *, int);
/* Current objects type - Implementation functions
* -----------------------------------------------
*/
static PyObject *CurrentGetattr(PyObject *, char *);
static int CurrentSetattr(PyObject *, char *, PyObject *);
/* Vim module - Definitions
*/
static struct PyMethodDef VimMethods[] = {
/* name, function, calling, documentation */
{"command", VimCommand, 1, "" },
{"eval", VimEval, 1, "" },
{ NULL, NULL, 0, NULL }
};
/* Vim module - Implementation
*/
/*ARGSUSED*/
static PyObject *
VimCommand(PyObject *self, PyObject *args)
{
char *cmd;
PyObject *result;
if (!PyArg_ParseTuple(args, "s", &cmd))
return NULL;
PyErr_Clear();
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
do_cmdline((char_u *)cmd, NULL, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
update_screen(NOT_VALID);
Python_Release_Vim();
Py_END_ALLOW_THREADS
if (VimErrorCheck())
result = NULL;
else
result = Py_None;
Py_XINCREF(result);
return result;
}
/*ARGSUSED*/
static PyObject *
VimEval(PyObject *self, PyObject *args)
{
char *expr;
char *str;
PyObject *result;
if (!PyArg_ParseTuple(args, "s", &expr))
return NULL;
#ifdef WANT_EVAL
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
str = (char *)eval_to_string((char_u *)expr, NULL);
Python_Release_Vim();
Py_END_ALLOW_THREADS
if (str == NULL)
{
PyErr_SetVim("invalid expression");
return NULL;
}
#else
PyErr_SetVim("expressions disabled at compile time");
return NULL;
#endif
result = Py_BuildValue("s", str);
Py_BEGIN_ALLOW_THREADS
Python_Lock_Vim();
vim_free(str);
Python_Release_Vim();
Py_END_ALLOW_THREADS
return result;
}
/* Common routines for buffers and line ranges
* -------------------------------------------
*/
static int
CheckBuffer(BufferObject *this)
{
if (this->buf == INVALID_BUFFER_VALUE)
{
PyErr_SetVim("attempt to refer to deleted buffer");
return -1;
}
return 0;
}
static PyObject *
RBItem(BufferObject *self, int n, int start, int end)
{
if (CheckBuffer(self))
return NULL;
if (n < 0 || n > end - start)
{
PyErr_SetString(PyExc_IndexError, "line number out of range");
return NULL;
}
return GetBufferLine(self->buf, n+start);
}
static PyObject *
RBSlice(BufferObject *self, int lo, int hi, int start, int end)
{
int size;
if (CheckBuffer(self))
return NULL;
size = end - start + 1;
if (lo < 0)
lo = 0;
else if (lo > size)
lo = size;
if (hi < 0)
hi = 0;
if (hi < lo)
hi = lo;
else if (hi > size)
hi = size;
return GetBufferLineList(self->buf, lo+start, hi+start);
}
static int
RBAssItem(BufferObject *self, int n, PyObject *val, int start, int end, int *new_end)
{
int len_change;
if (CheckBuffer(self))
return -1;
if (n < 0 || n > end - start)
{
PyErr_SetString(PyExc_IndexError, "line number out of range");
return -1;
}
if (SetBufferLine(self->buf, n+start, val, &len_change) == FAIL)
return -1;
if (new_end)
*new_end = end + len_change;
return 0;
}
static int
RBAssSlice(BufferObject *self, int lo, int hi, PyObject *val, int start, int end, int *new_end)
{
int size;
int len_change;
/* Self must be a valid buffer */
if (CheckBuffer(self))
return -1;
/* Sort out the slice range */
size = end - start + 1;
if (lo < 0)
lo = 0;
else if (lo > size)
lo = size;
if (hi < 0)
hi = 0;
if (hi < lo)
hi = lo;
else if (hi > size)
hi = size;
if (SetBufferLineList(self->buf, lo+start, hi+start, val, &len_change) == FAIL)
return -1;
if (new_end)
*new_end = end + len_change;
return 0;
}
static PyObject *
RBAppend(BufferObject *self, PyObject *args, int start, int end, int *new_end)
{
PyObject *lines;
int len_change;
int max;
int n;
if (CheckBuffer(self))
return NULL;
max = n = end - start + 1;
if (!PyArg_ParseTuple(args, "O|i", &lines, &n))
return NULL;
if (n < 0 || n > max)
{
PyErr_SetString(PyExc_ValueError, "line number out of range");
return NULL;
}
if (InsertBufferLines(self->buf, n + start - 1, lines, &len_change) == FAIL)
return NULL;
if (new_end)
*new_end = end + len_change;
Py_INCREF(Py_None);
return Py_None;
}
/* Buffer object - Definitions
*/
static struct PyMethodDef BufferMethods[] = {
/* name, function, calling, documentation */
{"append", BufferAppend, 1, "" },
{"mark", BufferMark, 1, "" },
{"range", BufferRange, 1, "" },
{ NULL, NULL, 0, NULL }
};
static PySequenceMethods BufferAsSeq = {
(inquiry) BufferLength, /* sq_length, len(x) */
(binaryfunc) 0, /* BufferConcat, */ /* sq_concat, x+y */
(intargfunc) 0, /* BufferRepeat, */ /* sq_repeat, x*n */
(intargfunc) BufferItem, /* sq_item, x[i] */
(intintargfunc) BufferSlice, /* sq_slice, x[i:j] */
(intobjargproc) BufferAssItem, /* sq_ass_item, x[i]=v */
(intintobjargproc) BufferAssSlice, /* sq_ass_slice, x[i:j]=v */
};
static PyTypeObject BufferType = {
PyObject_HEAD_INIT(0)
0,
"buffer",
sizeof(BufferObject),
0,
(destructor) BufferDestructor, /* tp_dealloc, refcount==0 */
(printfunc) 0, /* tp_print, print x */
(getattrfunc) BufferGetattr, /* tp_getattr, x.attr */
(setattrfunc) 0, /* tp_setattr, x.attr=v */
(cmpfunc) 0, /* tp_compare, x>y */
(reprfunc) BufferRepr, /* tp_repr, `x`, print x */
0, /* as number */
&BufferAsSeq, /* as sequence */
0, /* as mapping */
(hashfunc) 0, /* tp_hash, dict(x) */
(ternaryfunc) 0, /* tp_call, x() */
(reprfunc) 0, /* tp_str, str(x) */
};
/* Buffer object - Implementation
*/
static PyObject *
BufferNew(BUF *buf)
{
/* We need to handle deletion of buffers underneath us.
* If we add a "python_ref" field to the BUF structure,
* then we can get at it in buf_freeall() in vim. We then
* need to create only ONE Python object per buffer - if
* we try to create a second, just INCREF the existing one
* and return it. The (single) Python object referring to
* the buffer is stored in "python_ref".
* Question: what to do on a buf_freeall(). We'll probably
* have to either delete the Python object (DECREF it to
* zero - a bad idea, as it leaves dangling refs!) or
* set the BUF* value to an invalid value (-1?), which
* means we need checks in all access functions... Bah.
*/
BufferObject *self;
if (buf->python_ref)
self = buf->python_ref;
else
{
self = PyObject_NEW(BufferObject, &BufferType);
if (self == NULL)
return NULL;
self->buf = buf;
buf->python_ref = self;
}
return (PyObject *)(self);
}
static void
BufferDestructor(PyObject *self)
{
BufferObject *this = (BufferObject *)(self);
if (this->buf && this->buf != INVALID_BUFFER_VALUE)
this->buf->python_ref = NULL;
PyMem_DEL(self);
}
static PyObject *
BufferGetattr(PyObject *self, char *name)
{
BufferObject *this = (BufferObject *)(self);
if (CheckBuffer(this))
return NULL;
if (strcmp(name, "name") == 0)
return Py_BuildValue("s",this->buf->b_ffname);
else if (strcmp(name,"__members__") == 0)
return Py_BuildValue("[s]", "name");
else
return Py_FindMethod(BufferMethods, self, name);
}
static PyObject *
BufferRepr(PyObject *self)
{
static char repr[50];
BufferObject *this = (BufferObject *)(self);
if (this->buf == INVALID_BUFFER_VALUE)
{
sprintf(repr, "<buffer object (deleted) at %8lX>", (long)(self));
return PyString_FromString(repr);
}
else
{
char *name = (char *)this->buf->b_fname;
int len = strlen(name);
if (len > 35)
name = name + (35 - len);
sprintf(repr, "<buffer %s%s>", len > 35 ? "..." : "", name);
return PyString_FromString(repr);
}
}
/******************/
static int
BufferLength(PyObject *self)
{
/* HOW DO WE SIGNAL AN ERROR FROM THIS FUNCTION? */
if (CheckBuffer((BufferObject *)(self)))
return -1; /* ??? */
return (((BufferObject *)(self))->buf->b_ml.ml_line_count);
}
static PyObject *
BufferItem(PyObject *self, int n)
{
return RBItem((BufferObject *)(self), n, 1,
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
}
static PyObject *
BufferSlice(PyObject *self, int lo, int hi)
{
return RBSlice((BufferObject *)(self), lo, hi, 1,
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count);
}
static int
BufferAssItem(PyObject *self, int n, PyObject *val)
{
return RBAssItem((BufferObject *)(self), n, val, 1,
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
NULL);
}
static int
BufferAssSlice(PyObject *self, int lo, int hi, PyObject *val)
{
return RBAssSlice((BufferObject *)(self), lo, hi, val, 1,
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
NULL);
}
static PyObject *
BufferAppend(PyObject *self, PyObject *args)
{
return RBAppend((BufferObject *)(self), args, 1,
(int)((BufferObject *)(self))->buf->b_ml.ml_line_count,
NULL);
}
static PyObject *
BufferMark(PyObject *self, PyObject *args)
{
FPOS *posp;
char mark;
BUF *curbuf_save;
if (CheckBuffer((BufferObject *)(self)))
return NULL;
if (!PyArg_ParseTuple(args, "c", &mark))
return NULL;
curbuf_save = curbuf;
curbuf = ((BufferObject *)(self))->buf;
posp = getmark(mark, FALSE);
curbuf = curbuf_save;
if (posp == NULL)
{
PyErr_SetVim("invalid mark name");
return NULL;
}
/* Ckeck for keyboard interrupt */
if (VimErrorCheck())
return NULL;
if (posp->lnum == 0)
{
/* Or raise an error? */
Py_INCREF(Py_None);
return Py_None;
}
return Py_BuildValue("(ll)", (long)(posp->lnum), (long)(posp->col));
}
static PyObject *
BufferRange(PyObject *self, PyObject *args)
{
int start;
int end;
if (CheckBuffer((BufferObject *)(self)))
return NULL;
if (!PyArg_ParseTuple(args, "ii", &start, &end))
return NULL;
return RangeNew(((BufferObject *)(self))->buf, start, end);
}
/* Line range object - Definitions
*/
static struct PyMethodDef RangeMethods[] = {
/* name, function, calling, documentation */
{"append", RangeAppend, 1, "" },
{ NULL, NULL, 0, NULL }
};
static PySequenceMethods RangeAsSeq = {
(inquiry) RangeLength, /* sq_length, len(x) */
(binaryfunc) 0, /* RangeConcat, */ /* sq_concat, x+y */
(intargfunc) 0, /* RangeRepeat, */ /* sq_repeat, x*n */
(intargfunc) RangeItem, /* sq_item, x[i] */
(intintargfunc) RangeSlice, /* sq_slice, x[i:j] */
(intobjargproc) RangeAssItem, /* sq_ass_item, x[i]=v */
(intintobjargproc) RangeAssSlice, /* sq_ass_slice, x[i:j]=v */
};
static PyTypeObject RangeType = {
PyObject_HEAD_INIT(0)
0,
"range",
sizeof(RangeObject),
0,
(destructor) RangeDestructor, /* tp_dealloc, refcount==0 */
(printfunc) 0, /* tp_print, print x */
(getattrfunc) RangeGetattr, /* tp_getattr, x.attr */
(setattrfunc) 0, /* tp_setattr, x.attr=v */
(cmpfunc) 0, /* tp_compare, x>y */
(reprfunc) RangeRepr, /* tp_repr, `x`, print x */
0, /* as number */
&RangeAsSeq, /* as sequence */
0, /* as mapping */
(hashfunc) 0, /* tp_hash, dict(x) */
(ternaryfunc) 0, /* tp_call, x() */
(reprfunc) 0, /* tp_str, str(x) */
};
/* Line range object - Implementation
*/
static PyObject *
RangeNew(BUF *buf, int start, int end)
{
BufferObject *bufr;
RangeObject *self;
self = PyObject_NEW(RangeObject, &RangeType);
if (self == NULL)
return NULL;
bufr = (BufferObject *)BufferNew(buf);
if (bufr == NULL)
{
PyMem_DEL(self);
return NULL;
}
Py_INCREF(bufr);
self->buf = bufr;
self->start = start;
self->end = end;
return (PyObject *)(self);
}
static void
RangeDestructor(PyObject *self)
{
Py_DECREF(((RangeObject *)(self))->buf);
PyMem_DEL(self);
}
static PyObject *
RangeGetattr(PyObject *self, char *name)
{
return Py_FindMethod(RangeMethods, self, name);
}
static PyObject *
RangeRepr(PyObject *self)
{
static char repr[75];
RangeObject *this = (RangeObject *)(self);
if (this->buf->buf == INVALID_BUFFER_VALUE)
{
sprintf(repr, "<range object (for deleted buffer) at %8lX>",
(long)(self));
return PyString_FromString(repr);
}
else
{
char *name = (char *)this->buf->buf->b_fname;
int len = strlen(name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -