Use the new native screen class
This commit is contained in:
parent
6c39b07552
commit
3ce2c0553f
@ -9,19 +9,20 @@ import select
|
||||
import subprocess
|
||||
import struct
|
||||
from itertools import repeat
|
||||
from functools import partial
|
||||
from time import monotonic
|
||||
from threading import Thread, current_thread
|
||||
from queue import Queue, Empty
|
||||
|
||||
import glfw
|
||||
from pyte.streams import Stream, DebugStream
|
||||
|
||||
from .constants import appname
|
||||
from .char_grid import CharGrid
|
||||
from .keys import interpret_text_event, interpret_key_event
|
||||
from .screen import Screen
|
||||
from .utils import resize_pty, create_pty, sanitize_title
|
||||
from .fast_data_types import BRACKETED_PASTE_START, BRACKETED_PASTE_END
|
||||
from .fast_data_types import (
|
||||
BRACKETED_PASTE_START, BRACKETED_PASTE_END, Screen, parse_bytes_dump, parse_bytes
|
||||
)
|
||||
|
||||
|
||||
def handle_unix_signals():
|
||||
@ -53,10 +54,9 @@ class Boss(Thread):
|
||||
self.queue_action(self.initialize)
|
||||
self.profile = args.profile
|
||||
self.window, self.opts = window, opts
|
||||
self.screen = Screen(self.opts.scrollback_lines, self)
|
||||
self.screen = Screen(self)
|
||||
self.char_grid = CharGrid(self.screen, opts, window_width, window_height)
|
||||
sclass = DebugStream if args.dump_commands else Stream
|
||||
self.stream = sclass(self.screen)
|
||||
self.parse_bytes = partial(parse_bytes_dump, print) if args.dump_commands else parse_bytes
|
||||
self.write_buf = memoryview(b'')
|
||||
glfw.glfwSetCharModsCallback(window, self.on_text_input)
|
||||
glfw.glfwSetKeyCallback(window, self.on_key)
|
||||
@ -181,7 +181,7 @@ class Boss(Thread):
|
||||
if self.pending_update_screen is not None:
|
||||
if monotonic() > self.pending_update_screen:
|
||||
self.apply_update_screen()
|
||||
elif self.screen.is_dirty:
|
||||
elif self.screen.is_dirty():
|
||||
self.pending_update_screen = monotonic() + self.SCREEN_UPDATE_DELAY
|
||||
|
||||
def close(self):
|
||||
@ -209,7 +209,7 @@ class Boss(Thread):
|
||||
except EnvironmentError:
|
||||
data = b''
|
||||
if data:
|
||||
self.stream.feed(data)
|
||||
self.parse_bytes(self.screen, data)
|
||||
else: # EOF
|
||||
self.shutdown()
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
// of the line if there is no earlier tab stop.
|
||||
#define HT 0x09
|
||||
|
||||
// *Linefeed*: Give a line feed, and, if :data:`pyte.modes.LNM` (new
|
||||
// *Linefeed*: Give a line feed, and, if LNM (new
|
||||
// line mode) is set also a carriage return.
|
||||
#define LF 10
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
// at the bottom margin, the screen performs a scroll-up.
|
||||
#define IND 'D'
|
||||
|
||||
// *Next line*: Same as :data:`pyte.control.LF`.
|
||||
// *Next line*: Same as LF.
|
||||
#define NEL 'E'
|
||||
|
||||
// Tabulation set: Set a horizontal tab stop at cursor position.
|
||||
@ -197,7 +197,7 @@
|
||||
|
||||
// *Select graphics rendition*: The terminal can display the following
|
||||
// character attributes that change the character display without
|
||||
// changing the character (see :mod:`pyte.graphics`).
|
||||
// changing the character
|
||||
#define SGR 'm'
|
||||
|
||||
// *Device status report*.
|
||||
|
||||
@ -504,7 +504,7 @@ parse_bytes(PyObject UNUSED *self, PyObject *args) {
|
||||
Py_buffer pybuf;
|
||||
Screen *screen;
|
||||
#ifdef DUMP_COMMANDS
|
||||
if (!PyArg_ParseTuple(args, "O!y*O", &Screen_Type, &screen, &pybuf, &dump_callback)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "OO!y*", &dump_callback, &Screen_Type, &screen, &pybuf)) return NULL;
|
||||
if (!PyCallable_Check(dump_callback)) { PyErr_SetString(PyExc_TypeError, "The dump callback must be a callable object"); return NULL; }
|
||||
#else
|
||||
if (!PyArg_ParseTuple(args, "O!y*", &Screen_Type, &screen, &pybuf)) return NULL;
|
||||
|
||||
@ -18,7 +18,7 @@ static PyObject*
|
||||
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
|
||||
Screen *self;
|
||||
PyObject *callbacks = Py_None;
|
||||
unsigned int columns, lines;
|
||||
unsigned int columns=80, lines=24;
|
||||
if (!PyArg_ParseTuple(args, "|OII", &callbacks, &lines, &columns)) return NULL;
|
||||
|
||||
self = (Screen *)type->tp_alloc(type, 0);
|
||||
@ -102,6 +102,12 @@ static bool screen_resize(Screen *self, unsigned int lines, unsigned int columns
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool screen_change_scrollback_size(Screen UNUSED *self, unsigned int UNUSED size) {
|
||||
// TODO: Implement this
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dealloc(Screen* self) {
|
||||
Py_CLEAR(self->callbacks);
|
||||
@ -980,6 +986,36 @@ resize(Screen *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
change_scrollback_size(Screen *self, PyObject *args) {
|
||||
unsigned int count = 1;
|
||||
if (!PyArg_ParseTuple(args, "|I", &count)) return NULL;
|
||||
if (!screen_change_scrollback_size(self, MAX(100, count))) return NULL;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
screen_update_cell_data(Screen *self, PyObject *args) {
|
||||
SpriteMap *spm;
|
||||
ColorProfile *color_profile;
|
||||
PyObject *dp;
|
||||
unsigned int *data;
|
||||
unsigned long default_bg, default_fg;
|
||||
int force_screen_refresh;
|
||||
if (!PyArg_ParseTuple(args, "O!O!O!kkp", &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL;
|
||||
data = PyLong_AsVoidPtr(dp);
|
||||
PyObject *cursor_changed = self->change_tracker->cursor_changed ? Py_True : Py_False;
|
||||
if (!tracker_update_cell_data(self->change_tracker, self->linebuf, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL;
|
||||
Py_INCREF(cursor_changed);
|
||||
return cursor_changed;
|
||||
}
|
||||
|
||||
static PyObject* is_dirty(Screen *self) {
|
||||
PyObject *ans = self->change_tracker->dirty ? Py_True : Py_False;
|
||||
Py_INCREF(ans);
|
||||
return ans;
|
||||
}
|
||||
|
||||
#define COUNT_WRAP(name) \
|
||||
static PyObject* name(Screen *self, PyObject *args) { \
|
||||
unsigned int count = 1; \
|
||||
@ -1015,6 +1051,7 @@ static PyMethodDef methods[] = {
|
||||
MND(delete_lines, METH_VARARGS)
|
||||
MND(insert_characters, METH_VARARGS)
|
||||
MND(delete_characters, METH_VARARGS)
|
||||
MND(change_scrollback_size, METH_VARARGS)
|
||||
MND(erase_characters, METH_VARARGS)
|
||||
MND(cursor_up, METH_VARARGS)
|
||||
MND(cursor_up1, METH_VARARGS)
|
||||
@ -1023,7 +1060,9 @@ static PyMethodDef methods[] = {
|
||||
MND(cursor_forward, METH_VARARGS)
|
||||
MND(index, METH_NOARGS)
|
||||
MND(reverse_index, METH_NOARGS)
|
||||
MND(is_dirty, METH_NOARGS)
|
||||
MND(resize, METH_VARARGS)
|
||||
{"update_cell_data", (PyCFunction)screen_update_cell_data, METH_VARARGS, ""},
|
||||
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
1031
kitty/screen.py
1031
kitty/screen.py
File diff suppressed because it is too large
Load Diff
@ -97,25 +97,15 @@ update_cell_range(ChangeTracker *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
update_cell_data(ChangeTracker *self, PyObject *args) {
|
||||
#define update_cell_data_doc "update_cell_data(line_buf, sprite_map, color_profile, data_ptr, default_fg, default_bg, force_screen_refresh)"
|
||||
SpriteMap *spm;
|
||||
LineBuf *lb;
|
||||
ColorProfile *color_profile;
|
||||
PyObject *dp;
|
||||
unsigned int *data, y;
|
||||
unsigned long default_bg, default_fg;
|
||||
bool tracker_update_cell_data(ChangeTracker *self, LineBuf *lb, SpriteMap *spm, ColorProfile *color_profile, unsigned int *data, unsigned long default_fg, unsigned long default_bg, bool force_screen_refresh) {
|
||||
unsigned int y;
|
||||
Py_ssize_t start;
|
||||
int force_screen_refresh;
|
||||
if (!PyArg_ParseTuple(args, "O!O!O!O!kkp", &LineBuf_Type, &lb, &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL;
|
||||
data = PyLong_AsVoidPtr(dp);
|
||||
default_fg &= COL_MASK;
|
||||
default_bg &= COL_MASK;
|
||||
|
||||
#define UPDATE_RANGE(xstart, xmax) \
|
||||
linebuf_init_line(lb, y); \
|
||||
if (!update_cell_range_data(spm, lb->line, (xstart), (xmax), color_profile, default_bg, default_fg, data)) return NULL;
|
||||
if (!update_cell_range_data(spm, lb->line, (xstart), (xmax), color_profile, default_bg, default_fg, data)) return false;
|
||||
|
||||
if (self->screen_changed || force_screen_refresh) {
|
||||
for (y = 0; y < self->ynum; y++) {
|
||||
@ -146,9 +136,24 @@ update_cell_data(ChangeTracker *self, PyObject *args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *cursor_changed = self->cursor_changed ? Py_True : Py_False;
|
||||
tracker_reset(self);
|
||||
return true;
|
||||
}
|
||||
|
||||
PyObject*
|
||||
update_cell_data(ChangeTracker *self, PyObject *args) {
|
||||
#define update_cell_data_doc "update_cell_data(line_buf, sprite_map, color_profile, data_ptr, default_fg, default_bg, force_screen_refresh)"
|
||||
SpriteMap *spm;
|
||||
LineBuf *lb;
|
||||
ColorProfile *color_profile;
|
||||
PyObject *dp;
|
||||
unsigned int *data;
|
||||
unsigned long default_bg, default_fg;
|
||||
int force_screen_refresh;
|
||||
if (!PyArg_ParseTuple(args, "O!O!O!O!kkp", &LineBuf_Type, &lb, &SpriteMap_Type, &spm, &ColorProfile_Type, &color_profile, &PyLong_Type, &dp, &default_fg, &default_bg, &force_screen_refresh)) return NULL;
|
||||
data = PyLong_AsVoidPtr(dp);
|
||||
PyObject *cursor_changed = self->cursor_changed ? Py_True : Py_False;
|
||||
if (!tracker_update_cell_data(self, lb, spm, color_profile, data, default_fg, default_bg, (bool)force_screen_refresh)) return NULL;
|
||||
Py_INCREF(cursor_changed);
|
||||
return cursor_changed;
|
||||
}
|
||||
|
||||
@ -52,3 +52,4 @@ static inline void tracker_reset(ChangeTracker *self) {
|
||||
|
||||
PyObject* tracker_consolidate_changes(ChangeTracker *self);
|
||||
bool tracker_resize(ChangeTracker *self, unsigned int ynum, unsigned int xnum);
|
||||
bool tracker_update_cell_data(ChangeTracker *, LineBuf *, SpriteMap *, ColorProfile *, unsigned int *, unsigned long, unsigned long, bool);
|
||||
|
||||
@ -41,7 +41,7 @@ class TestScreen(BaseTest):
|
||||
cd = CmdDump()
|
||||
if isinstance(x, str):
|
||||
x = x.encode('utf-8')
|
||||
parse_bytes_dump(s, x, cd)
|
||||
parse_bytes_dump(cd, s, x)
|
||||
self.ae(tuple(cd), cmds)
|
||||
|
||||
def test_simple_parsing(self):
|
||||
|
||||
14
pyte/AUTHORS
14
pyte/AUTHORS
@ -1,14 +0,0 @@
|
||||
Authors
|
||||
=======
|
||||
|
||||
- George Shuklin
|
||||
- Sergei Lebedev
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
- Alexey Shamrin
|
||||
- Steve Cohen
|
||||
- Jonathan Slenders
|
||||
- David O'Shea
|
||||
- Andreas Stührk
|
||||
165
pyte/LICENSE
165
pyte/LICENSE
@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@ -1,52 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte
|
||||
~~~~
|
||||
|
||||
`pyte` implements a mix of VT100, VT220 and VT520 specification,
|
||||
and aims to support most of the `TERM=linux` functionality.
|
||||
|
||||
Two classes: :class:`~pyte.streams.Stream`, which parses the
|
||||
command stream and dispatches events for commands, and
|
||||
:class:`~pyte.screens.Screen` which, when used with a stream
|
||||
maintains a buffer of strings representing the screen of a
|
||||
terminal.
|
||||
|
||||
.. warning:: From ``xterm/main.c`` "If you think you know what all
|
||||
of this code is doing, you are probably very mistaken.
|
||||
There be serious and nasty dragons here" -- nothing
|
||||
has changed.
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
__all__ = ("Screen", "DiffScreen", "HistoryScreen",
|
||||
"Stream", "DebugStream")
|
||||
|
||||
import io
|
||||
|
||||
from .streams import Stream, DebugStream
|
||||
|
||||
|
||||
if __debug__:
|
||||
from .compat import str
|
||||
|
||||
def dis(chars):
|
||||
"""A :func:`dis.dis` for terminals.
|
||||
|
||||
>>> dis(b"\x07") # doctest: +NORMALIZE_WHITESPACE
|
||||
BELL
|
||||
>>> dis(b"\x1b[20m") # doctest: +NORMALIZE_WHITESPACE
|
||||
SELECT_GRAPHIC_RENDITION 20
|
||||
"""
|
||||
if isinstance(chars, str):
|
||||
chars = chars.encode("utf-8")
|
||||
|
||||
with io.StringIO() as buf:
|
||||
DebugStream(to=buf).feed(chars)
|
||||
print(buf.getvalue())
|
||||
@ -1,33 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte
|
||||
~~~~
|
||||
|
||||
Command-line tool for "disassembling" escape and CSI sequences::
|
||||
|
||||
$ echo -e "\e[Jfoo" | python -m pyte
|
||||
ERASE_IN_DISPLAY 0
|
||||
DRAW f
|
||||
DRAW o
|
||||
DRAW o
|
||||
LINEFEED
|
||||
|
||||
$ python -m pyte foo
|
||||
DRAW f
|
||||
DRAW o
|
||||
DRAW o
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import pyte
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
pyte.dis(sys.stdin.read())
|
||||
else:
|
||||
pyte.dis("".join(sys.argv[1:]))
|
||||
143
pyte/charsets.py
143
pyte/charsets.py
@ -1,143 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte.charsets
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This module defines ``G0`` and ``G1`` charset mappings the same way
|
||||
they are defined for linux terminal, see
|
||||
``linux/drivers/tty/consolemap.c`` @ http://git.kernel.org
|
||||
|
||||
.. note:: ``VT100_MAP`` and ``IBMPC_MAP`` were taken unchanged
|
||||
from linux kernel source and therefore are licensed
|
||||
under **GPL**.
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .compat import chr, map
|
||||
|
||||
|
||||
#: Latin1.
|
||||
LAT1_MAP = "".join(map(chr, range(256)))
|
||||
|
||||
#: VT100 graphic character set.
|
||||
VT100_MAP = "".join(chr(c) for c in [
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
|
||||
0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
|
||||
0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
|
||||
0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
|
||||
0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
|
||||
0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
|
||||
0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
|
||||
0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
|
||||
0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
|
||||
0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
|
||||
0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
|
||||
0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
|
||||
0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
|
||||
0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
|
||||
0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
|
||||
0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
|
||||
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
|
||||
0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
|
||||
0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
|
||||
0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
|
||||
0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
|
||||
0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
|
||||
0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
|
||||
0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
|
||||
])
|
||||
|
||||
#: IBM Codepage 437.
|
||||
IBMPC_MAP = "".join(chr(c) for c in [
|
||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
||||
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
|
||||
0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
])
|
||||
|
||||
|
||||
#: VAX42 character set.
|
||||
VAX42_MAP = "".join(chr(c) for c in [
|
||||
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
|
||||
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
|
||||
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
|
||||
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
|
||||
0x0020, 0x043b, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
|
||||
0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
|
||||
0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x0435,
|
||||
0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
|
||||
0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
|
||||
0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
|
||||
0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
|
||||
0x0060, 0x0441, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
|
||||
0x0435, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x043a,
|
||||
0x0070, 0x0071, 0x0442, 0x0073, 0x043b, 0x0435, 0x0076, 0x0077,
|
||||
0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
|
||||
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
|
||||
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
|
||||
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
|
||||
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
|
||||
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
|
||||
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
|
||||
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
|
||||
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
])
|
||||
|
||||
|
||||
MAPS = {
|
||||
b"B": LAT1_MAP,
|
||||
b"0": VT100_MAP,
|
||||
b"U": IBMPC_MAP,
|
||||
b"V": VAX42_MAP
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte.compat
|
||||
~~~~~~~~~~~
|
||||
|
||||
Python version specific compatibility fixes.
|
||||
|
||||
:copyright: (c) 2015-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
from future_builtins import map
|
||||
|
||||
range = xrange
|
||||
str = unicode
|
||||
chr = unichr
|
||||
|
||||
from functools import partial
|
||||
iter_bytes = partial(map, ord)
|
||||
else:
|
||||
from builtins import map, range, str, chr
|
||||
iter_bytes = iter
|
||||
@ -1,73 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte.control
|
||||
~~~~~~~~~~~~
|
||||
|
||||
This module defines simple control sequences, recognized by
|
||||
:class:`~pyte.streams.Stream`, the set of codes here is for
|
||||
``TERM=linux`` which is a superset of VT102.
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
#: *Space*: Not suprisingly -- ``" "``.
|
||||
SP = b" "
|
||||
|
||||
#: *Null*: Does nothing.
|
||||
NUL = b"\x00"
|
||||
|
||||
#: *Bell*: Beeps.
|
||||
BEL = b"\x07"
|
||||
|
||||
#: *Backspace*: Backspace one column, but not past the begining of the
|
||||
#: line.
|
||||
BS = b"\x08"
|
||||
|
||||
#: *Horizontal tab*: Move cursor to the next tab stop, or to the end
|
||||
#: of the line if there is no earlier tab stop.
|
||||
HT = b"\x09"
|
||||
|
||||
#: *Linefeed*: Give a line feed, and, if :data:`pyte.modes.LNM` (new
|
||||
#: line mode) is set also a carriage return.
|
||||
LF = b"\n"
|
||||
#: *Vertical tab*: Same as :data:`LF`.
|
||||
VT = b"\x0b"
|
||||
#: *Form feed*: Same as :data:`LF`.
|
||||
FF = b"\x0c"
|
||||
|
||||
#: *Carriage return*: Move cursor to left margin on current line.
|
||||
CR = b"\r"
|
||||
|
||||
#: *Shift out*: Activate G1 character set.
|
||||
SO = b"\x0e"
|
||||
|
||||
#: *Shift in*: Activate G0 character set.
|
||||
SI = b"\x0f"
|
||||
|
||||
#: *Cancel*: Interrupt escape sequence. If received during an escape or
|
||||
#: control sequence, cancels the sequence and displays substitution
|
||||
#: character.
|
||||
CAN = b"\x18"
|
||||
#: *Substitute*: Same as :data:`CAN`.
|
||||
SUB = b"\x1a"
|
||||
|
||||
#: *Escape*: Starts an escape sequence.
|
||||
ESC = b"\x1b"
|
||||
|
||||
#: *Delete*: Is ignored.
|
||||
DEL = b"\x7f"
|
||||
|
||||
#: *Control sequence introducer*: An equivalent for ``ESC [``.
|
||||
CSI = b"\x9b"
|
||||
|
||||
#: *String terminator*.
|
||||
ST = b"\x9c"
|
||||
|
||||
#: *Operating system command*.
|
||||
OSC = b"\x9d"
|
||||
|
||||
#: Device Control function (DCS)
|
||||
DCS = ESC + b"P"
|
||||
165
pyte/escape.py
165
pyte/escape.py
@ -1,165 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte.escape
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module defines both CSI and non-CSI escape sequences, recognized
|
||||
by :class:`~pyte.streams.Stream` and subclasses.
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
#: *Reset*.
|
||||
RIS = b"c"
|
||||
|
||||
#: *Index*: Move cursor down one line in same column. If the cursor is
|
||||
#: at the bottom margin, the screen performs a scroll-up.
|
||||
IND = b"D"
|
||||
|
||||
#: *Next line*: Same as :data:`pyte.control.LF`.
|
||||
NEL = b"E"
|
||||
|
||||
#: Tabulation set: Set a horizontal tab stop at cursor position.
|
||||
HTS = b"H"
|
||||
|
||||
#: *Reverse index*: Move cursor up one line in same column. If the
|
||||
#: cursor is at the top margin, the screen performs a scroll-down.
|
||||
RI = b"M"
|
||||
|
||||
#: Save cursor: Save cursor position, character attribute (graphic
|
||||
#: rendition), character set, and origin mode selection (see
|
||||
#: :data:`DECRC`).
|
||||
DECSC = b"7"
|
||||
|
||||
#: *Restore cursor*: Restore previously saved cursor position, character
|
||||
#: attribute (graphic rendition), character set, and origin mode
|
||||
#: selection. If none were saved, move cursor to home position.
|
||||
DECRC = b"8"
|
||||
|
||||
#: Set normal keypad mode
|
||||
DECPNM = b'>'
|
||||
|
||||
#: Set alternate keypad mode
|
||||
DECPAM = b'='
|
||||
|
||||
# "Sharp" escape sequences.
|
||||
# -------------------------
|
||||
|
||||
#: *Alignment display*: Fill screen with uppercase E's for testing
|
||||
#: screen focus and alignment.
|
||||
DECALN = b"8"
|
||||
|
||||
|
||||
# ECMA-48 CSI sequences.
|
||||
# ---------------------
|
||||
|
||||
#: *Insert character*: Insert the indicated # of blank characters.
|
||||
ICH = b"@"
|
||||
|
||||
#: *Cursor up*: Move cursor up the indicated # of lines in same column.
|
||||
#: Cursor stops at top margin.
|
||||
CUU = b"A"
|
||||
|
||||
#: *Cursor down*: Move cursor down the indicated # of lines in same
|
||||
#: column. Cursor stops at bottom margin.
|
||||
CUD = b"B"
|
||||
|
||||
#: *Cursor forward*: Move cursor right the indicated # of columns.
|
||||
#: Cursor stops at right margin.
|
||||
CUF = b"C"
|
||||
|
||||
#: *Cursor back*: Move cursor left the indicated # of columns. Cursor
|
||||
#: stops at left margin.
|
||||
CUB = b"D"
|
||||
|
||||
#: *Cursor next line*: Move cursor down the indicated # of lines to
|
||||
#: column 1.
|
||||
CNL = b"E"
|
||||
|
||||
#: *Cursor previous line*: Move cursor up the indicated # of lines to
|
||||
#: column 1.
|
||||
CPL = b"F"
|
||||
|
||||
#: *Cursor horizontal align*: Move cursor to the indicated column in
|
||||
#: current line.
|
||||
CHA = b"G"
|
||||
|
||||
#: *Cursor position*: Move cursor to the indicated line, column (origin
|
||||
#: at ``1, 1``).
|
||||
CUP = b"H"
|
||||
|
||||
#: *Erase data* (default: from cursor to end of line).
|
||||
ED = b"J"
|
||||
|
||||
#: *Erase in line* (default: from cursor to end of line).
|
||||
EL = b"K"
|
||||
|
||||
#: *Insert line*: Insert the indicated # of blank lines, starting from
|
||||
#: the current line. Lines displayed below cursor move down. Lines moved
|
||||
#: past the bottom margin are lost.
|
||||
IL = b"L"
|
||||
|
||||
#: *Delete line*: Delete the indicated # of lines, starting from the
|
||||
#: current line. As lines are deleted, lines displayed below cursor
|
||||
#: move up. Lines added to bottom of screen have spaces with same
|
||||
#: character attributes as last line move up.
|
||||
DL = b"M"
|
||||
|
||||
#: *Delete character*: Delete the indicated # of characters on the
|
||||
#: current line. When character is deleted, all characters to the right
|
||||
#: of cursor move left.
|
||||
DCH = b"P"
|
||||
|
||||
#: *Erase character*: Erase the indicated # of characters on the
|
||||
#: current line.
|
||||
ECH = b"X"
|
||||
|
||||
#: *Horizontal position relative*: Same as :data:`CUF`.
|
||||
HPR = b"a"
|
||||
|
||||
#: *Device Attributes*.
|
||||
DA = b"c"
|
||||
|
||||
#: *Vertical position adjust*: Move cursor to the indicated line,
|
||||
#: current column.
|
||||
VPA = b"d"
|
||||
|
||||
#: *Vertical position relative*: Same as :data:`CUD`.
|
||||
VPR = b"e"
|
||||
|
||||
#: *Horizontal / Vertical position*: Same as :data:`CUP`.
|
||||
HVP = b"f"
|
||||
|
||||
#: *Tabulation clear*: Clears a horizontal tab stop at cursor position.
|
||||
TBC = b"g"
|
||||
|
||||
#: *Set mode*.
|
||||
SM = b"h"
|
||||
|
||||
#: *Reset mode*.
|
||||
RM = b"l"
|
||||
|
||||
#: *Select graphics rendition*: The terminal can display the following
|
||||
#: character attributes that change the character display without
|
||||
#: changing the character (see :mod:`pyte.graphics`).
|
||||
SGR = b"m"
|
||||
|
||||
#: *Device status report*.
|
||||
DSR = b"n"
|
||||
|
||||
#: *Select top and bottom margins*: Selects margins, defining the
|
||||
#: scrolling region; parameters are top and bottom line. If called
|
||||
#: without any arguments, whole screen is used.
|
||||
DECSTBM = b"r"
|
||||
|
||||
#: *Horizontal position adjust*: Same as :data:`CHA`.
|
||||
HPA = b"'"
|
||||
|
||||
|
||||
# Misc sequences
|
||||
|
||||
#: Change cursor shape/blink
|
||||
DECSCUSR = b'q'
|
||||
160
pyte/graphics.py
160
pyte/graphics.py
@ -1,160 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte.graphics
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This module defines graphic-related constants, mostly taken from
|
||||
:manpage:`console_codes(4)` and
|
||||
http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html.
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
#: A mapping of ANSI text style codes to style names, "+" means the:
|
||||
#: attribute is set, "-" -- reset; example:
|
||||
#:
|
||||
#: >>> text[1]
|
||||
#: '+bold'
|
||||
#: >>> text[9]
|
||||
#: '+strikethrough'
|
||||
TEXT = {
|
||||
1: "+bold",
|
||||
3: "+italics",
|
||||
4: "+underscore",
|
||||
7: "+reverse",
|
||||
9: "+strikethrough",
|
||||
22: "-bold",
|
||||
23: "-italics",
|
||||
24: "-underscore",
|
||||
27: "-reverse",
|
||||
29: "-strikethrough",
|
||||
}
|
||||
|
||||
DISPLAY = {
|
||||
1: ("bold", True),
|
||||
3: ("italic", True),
|
||||
4: ("decoration", 1),
|
||||
7: ("reverse", True),
|
||||
9: ("strikethrough", True),
|
||||
22: ("bold", False),
|
||||
23: ("italic", False),
|
||||
24: ("decoration", 0),
|
||||
27: ("reverse", False),
|
||||
29: ("strikethrough", False),
|
||||
}
|
||||
|
||||
#: A mapping of ANSI foreground color codes to color names.
|
||||
#:
|
||||
#: >>> FG_ANSI[30]
|
||||
#: 'black'
|
||||
#: >>> FG_ANSI[38]
|
||||
#: 'default'
|
||||
FG_ANSI = {
|
||||
30: "black",
|
||||
31: "red",
|
||||
32: "green",
|
||||
33: "brown",
|
||||
34: "blue",
|
||||
35: "magenta",
|
||||
36: "cyan",
|
||||
37: "white",
|
||||
39: "default" # white.
|
||||
}
|
||||
|
||||
#: An alias to :data:`~pyte.graphics.FG_ANSI` for compatibility.
|
||||
FG = FG_ANSI
|
||||
|
||||
#: A mapping of non-standard ``aixterm`` foreground color codes to
|
||||
#: color names. These are high intensity colors and thus should be
|
||||
#: complemented by ``+bold``.
|
||||
FG_AIXTERM = {
|
||||
90: "black",
|
||||
91: "red",
|
||||
92: "green",
|
||||
93: "brown",
|
||||
94: "blue",
|
||||
95: "magenta",
|
||||
96: "cyan",
|
||||
97: "white"
|
||||
}
|
||||
|
||||
#: A mapping of ANSI background color codes to color names.
|
||||
#:
|
||||
#: >>> BG_ANSI[40]
|
||||
#: 'black'
|
||||
#: >>> BG_ANSI[48]
|
||||
#: 'default'
|
||||
BG_ANSI = {
|
||||
40: "black",
|
||||
41: "red",
|
||||
42: "green",
|
||||
43: "brown",
|
||||
44: "blue",
|
||||
45: "magenta",
|
||||
46: "cyan",
|
||||
47: "white",
|
||||
49: "default" # black.
|
||||
}
|
||||
|
||||
#: An alias to :data:`~pyte.graphics.BG_ANSI` for compatibility.
|
||||
BG = BG_ANSI
|
||||
|
||||
#: A mapping of non-standard ``aixterm`` background color codes to
|
||||
#: color names. These are high intensity colors and thus should be
|
||||
#: complemented by ``+bold``.
|
||||
BG_AIXTERM = {
|
||||
100: "black",
|
||||
101: "red",
|
||||
102: "green",
|
||||
103: "brown",
|
||||
104: "blue",
|
||||
105: "magenta",
|
||||
106: "cyan",
|
||||
107: "white"
|
||||
}
|
||||
|
||||
#: SGR code for foreground in 256 or True color mode.
|
||||
FG_256 = 38
|
||||
|
||||
#: SGR code for background in 256 or True color mode.
|
||||
BG_256 = 48
|
||||
|
||||
#: A table of 256 foreground or background colors.
|
||||
# The following code is part of the Pygments project (BSD licensed).
|
||||
FG_BG_256 = [
|
||||
(0x00, 0x00, 0x00), # 0
|
||||
(0xcd, 0x00, 0x00), # 1
|
||||
(0x00, 0xcd, 0x00), # 2
|
||||
(0xcd, 0xcd, 0x00), # 3
|
||||
(0x00, 0x00, 0xee), # 4
|
||||
(0xcd, 0x00, 0xcd), # 5
|
||||
(0x00, 0xcd, 0xcd), # 6
|
||||
(0xe5, 0xe5, 0xe5), # 7
|
||||
(0x7f, 0x7f, 0x7f), # 8
|
||||
(0xff, 0x00, 0x00), # 9
|
||||
(0x00, 0xff, 0x00), # 10
|
||||
(0xff, 0xff, 0x00), # 11
|
||||
(0x5c, 0x5c, 0xff), # 12
|
||||
(0xff, 0x00, 0xff), # 13
|
||||
(0x00, 0xff, 0xff), # 14
|
||||
(0xff, 0xff, 0xff), # 15
|
||||
]
|
||||
|
||||
# colors 16..232: the 6x6x6 color cube
|
||||
valuerange = (0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff)
|
||||
|
||||
for i in range(217):
|
||||
r = valuerange[(i // 36) % 6]
|
||||
g = valuerange[(i // 6) % 6]
|
||||
b = valuerange[i % 6]
|
||||
FG_BG_256.append((r, g, b))
|
||||
|
||||
# colors 233..253: grayscale
|
||||
for i in range(1, 22):
|
||||
v = 8 + i * 10
|
||||
FG_BG_256.append((v, v, v))
|
||||
@ -1,77 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte.modes
|
||||
~~~~~~~~~~
|
||||
|
||||
This module defines terminal mode switches, used by
|
||||
:class:`~pyte.screens.Screen`. There're two types of terminal modes:
|
||||
|
||||
* `non-private` which should be set with ``ESC [ N h``, where ``N``
|
||||
is an integer, representing mode being set; and
|
||||
* `private` which should be set with ``ESC [ ? N h``.
|
||||
|
||||
The latter are shifted 5 times to the right, to be easily
|
||||
distinguishable from the former ones; for example `Origin Mode`
|
||||
-- :data:`DECOM` is ``192`` not ``6``.
|
||||
|
||||
>>> DECOM
|
||||
192
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
#: *Line Feed/New Line Mode*: When enabled, causes a received
|
||||
#: :data:`~pyte.control.LF`, :data:`pyte.control.FF`, or
|
||||
#: :data:`~pyte.control.VT` to move the cursor to the first column of
|
||||
#: the next line.
|
||||
LNM = 20
|
||||
|
||||
#: *Insert/Replace Mode*: When enabled, new display characters move
|
||||
#: old display characters to the right. Characters moved past the
|
||||
#: right margin are lost. Otherwise, new display characters replace
|
||||
#: old display characters at the cursor position.
|
||||
IRM = 4
|
||||
|
||||
|
||||
# Private modes.
|
||||
# ..............
|
||||
|
||||
#: *Text Cursor Enable Mode*: determines if the text cursor is
|
||||
#: visible.
|
||||
DECTCEM = 25 << 5
|
||||
|
||||
#: *Screen Mode*: toggles screen-wide reverse-video mode.
|
||||
DECSCNM = 5 << 5
|
||||
|
||||
#: *Origin Mode*: allows cursor addressing relative to a user-defined
|
||||
#: origin. This mode resets when the terminal is powered up or reset.
|
||||
#: It does not affect the erase in display (ED) function.
|
||||
DECOM = 6 << 5
|
||||
|
||||
#: *Auto Wrap Mode*: selects where received graphic characters appear
|
||||
#: when the cursor is at the right margin.
|
||||
DECAWM = 7 << 5
|
||||
|
||||
#: *Column Mode*: selects the number of columns per line (80 or 132)
|
||||
#: on the screen.
|
||||
DECCOLM = 3 << 5
|
||||
|
||||
#: Bracketed paste mode
|
||||
# http://cirw.in/blog/bracketed-paste
|
||||
BRACKETED_PASTE = 2004 << 5
|
||||
BRACKETED_PASTE_START = '\033[200~'.encode('ascii')
|
||||
BRACKETED_PASTE_END = '\033[201~'.encode('ascii')
|
||||
|
||||
#: Alternate screen buffer
|
||||
ALTERNATE_SCREEN = 1049 << 5
|
||||
|
||||
#: Xterm mouse protocol
|
||||
SEND_MOUSE_ON_PRESS_AND_RELEASE = 1000 << 5
|
||||
HILITE_MOUSE_TRACKING = 1001 << 5
|
||||
CELL_MOTION_MOUSE_TRACKING = 1002 << 5
|
||||
FOCUS_TRACKING = 1004 << 5
|
||||
UTF8_MOUSE_MODE = 1005 << 5
|
||||
SGR_MOUSE_MODE = 1006 << 6
|
||||
419
pyte/streams.py
419
pyte/streams.py
@ -1,419 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pyte.streams
|
||||
~~~~~~~~~~~~
|
||||
|
||||
This module provides three stream implementations with different
|
||||
features; for starters, here's a quick example of how streams are
|
||||
typically used:
|
||||
|
||||
>>> import pyte
|
||||
>>> screen = pyte.Screen(80, 24)
|
||||
>>> stream = pyte.Stream(screen)
|
||||
>>> stream.feed(b"\x1B[5B") # Move the cursor down 5 rows.
|
||||
>>> screen.cursor.y
|
||||
5
|
||||
|
||||
:copyright: (c) 2011-2012 by Selectel.
|
||||
:copyright: (c) 2012-2016 by pyte authors and contributors,
|
||||
see AUTHORS for details.
|
||||
:license: LGPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from functools import wraps
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
|
||||
from . import control as ctrl, escape as esc
|
||||
from .compat import str
|
||||
|
||||
|
||||
class Stream(object):
|
||||
"""A stream is a state machine that parses a stream of bytes and
|
||||
dispatches events based on what it sees.
|
||||
|
||||
:param pyte.screens.Screen screen: a screen to dispatch events to.
|
||||
:param bool strict: check if a given screen implements all required
|
||||
events.
|
||||
|
||||
.. note::
|
||||
|
||||
Stream only accepts :func:`bytes` as input. Decoding it into text
|
||||
is the responsibility of the :class:`~pyte.screens.Screen`.
|
||||
|
||||
.. versionchanged 0.6.0::
|
||||
|
||||
For performance reasons the binding between stream events and
|
||||
screen methods was made static. As a result, the stream **will
|
||||
not** dispatch events to methods added to screen **after** the
|
||||
stream was created.
|
||||
|
||||
.. seealso::
|
||||
|
||||
`man console_codes <http://linux.die.net/man/4/console_codes>`_
|
||||
For details on console codes listed bellow in :attr:`basic`,
|
||||
:attr:`escape`, :attr:`csi`, :attr:`sharp` and :attr:`percent`.
|
||||
"""
|
||||
|
||||
#: Control sequences, which don't require any arguments.
|
||||
basic = {
|
||||
ctrl.BEL: "bell",
|
||||
ctrl.BS: "backspace",
|
||||
ctrl.HT: "tab",
|
||||
ctrl.LF: "linefeed",
|
||||
ctrl.VT: "linefeed",
|
||||
ctrl.FF: "linefeed",
|
||||
ctrl.CR: "carriage_return",
|
||||
ctrl.SO: "shift_out",
|
||||
ctrl.SI: "shift_in",
|
||||
}
|
||||
|
||||
#: non-CSI escape sequences.
|
||||
escape = {
|
||||
esc.RIS: "reset",
|
||||
esc.IND: "index",
|
||||
esc.NEL: "linefeed",
|
||||
esc.RI: "reverse_index",
|
||||
esc.HTS: "set_tab_stop",
|
||||
esc.DECSC: "save_cursor",
|
||||
esc.DECRC: "restore_cursor",
|
||||
esc.DECPNM: 'normal_keypad_mode',
|
||||
esc.DECPAM: 'alternate_keypad_mode',
|
||||
}
|
||||
|
||||
#: "sharp" escape sequences -- ``ESC # <N>``.
|
||||
sharp = {
|
||||
esc.DECALN: "alignment_display",
|
||||
}
|
||||
|
||||
#: CSI escape sequences -- ``CSI P1;P2;...;Pn <fn>``.
|
||||
csi = {
|
||||
esc.ICH: "insert_characters",
|
||||
esc.CUU: "cursor_up",
|
||||
esc.CUD: "cursor_down",
|
||||
esc.CUF: "cursor_forward",
|
||||
esc.CUB: "cursor_back",
|
||||
esc.CNL: "cursor_down1",
|
||||
esc.CPL: "cursor_up1",
|
||||
esc.CHA: "cursor_to_column",
|
||||
esc.CUP: "cursor_position",
|
||||
esc.ED: "erase_in_display",
|
||||
esc.EL: "erase_in_line",
|
||||
esc.IL: "insert_lines",
|
||||
esc.DL: "delete_lines",
|
||||
esc.DCH: "delete_characters",
|
||||
esc.ECH: "erase_characters",
|
||||
esc.HPR: "cursor_forward",
|
||||
esc.DA: "report_device_attributes",
|
||||
esc.VPA: "cursor_to_line",
|
||||
esc.VPR: "cursor_down",
|
||||
esc.HVP: "cursor_position",
|
||||
esc.TBC: "clear_tab_stop",
|
||||
esc.SM: "set_mode",
|
||||
esc.RM: "reset_mode",
|
||||
esc.SGR: "select_graphic_rendition",
|
||||
esc.DSR: "report_device_status",
|
||||
esc.DECSTBM: "set_margins",
|
||||
esc.HPA: "cursor_to_column",
|
||||
esc.DECSCUSR: 'set_cursor_shape',
|
||||
}
|
||||
|
||||
#: A set of all events dispatched by the stream.
|
||||
events = frozenset(itertools.chain(
|
||||
basic.values(), escape.values(), sharp.values(), csi.values(),
|
||||
["define_charset", "select_other_charset"],
|
||||
["set_icon", "set_title", 'set_dynamic_color'], # OSC.
|
||||
["draw", "debug"]))
|
||||
|
||||
#: A regular expression pattern matching everything what can be
|
||||
#: considered plain text.
|
||||
_special = set([ctrl.ESC, ctrl.CSI, ctrl.NUL, ctrl.DEL, ctrl.OSC])
|
||||
_special.update(basic)
|
||||
_text_pattern = re.compile(
|
||||
b"[^" + b"".join(map(re.escape, _special)) + b"]+")
|
||||
del _special
|
||||
|
||||
def __init__(self, screen=None, strict=True):
|
||||
self.listener = None
|
||||
self.strict = False
|
||||
|
||||
if screen is not None:
|
||||
self.attach(screen)
|
||||
|
||||
def attach(self, screen, only=()):
|
||||
"""Adds a given screen to the listener queue.
|
||||
|
||||
:param pyte.screens.Screen screen: a screen to attach to.
|
||||
:param list only: a list of events you want to dispatch to a
|
||||
given screen (empty by default, which means
|
||||
-- dispatch all events).
|
||||
"""
|
||||
if self.strict:
|
||||
for event in self.events:
|
||||
if not hasattr(screen, event):
|
||||
error_message = "{0} is missing {1}".format(screen, event)
|
||||
raise TypeError(error_message)
|
||||
|
||||
self.listener = screen
|
||||
self._parser = self._parser_fsm()
|
||||
self._taking_plain_text = next(self._parser)
|
||||
|
||||
def detach(self, screen):
|
||||
"""Removes a given screen from the listener queue and fails
|
||||
silently if it's not attached.
|
||||
|
||||
:param pyte.screens.Screen screen: a screen to detach.
|
||||
"""
|
||||
if screen is self.listener:
|
||||
self.listener = None
|
||||
|
||||
def feed(self, data: bytes) -> None:
|
||||
"""Consumes a string and advances the state as necessary.
|
||||
|
||||
:param bytes data: a blob of data to feed from.
|
||||
"""
|
||||
send = self._parser.send
|
||||
draw = self.listener.draw
|
||||
match_text = self._text_pattern.match
|
||||
taking_plain_text = self._taking_plain_text
|
||||
|
||||
# TODO: use memoryview?
|
||||
length = len(data)
|
||||
offset = 0
|
||||
while offset < length:
|
||||
if taking_plain_text:
|
||||
match = match_text(data, offset)
|
||||
if match is not None:
|
||||
start, offset = match.span()
|
||||
draw(data[start:offset])
|
||||
else:
|
||||
taking_plain_text = False
|
||||
else:
|
||||
taking_plain_text = send(data[offset:offset + 1])
|
||||
offset += 1
|
||||
|
||||
self._taking_plain_text = taking_plain_text
|
||||
|
||||
def _parser_fsm(self):
|
||||
"""An FSM implemented as a coroutine.
|
||||
|
||||
This generator is not the most beautiful, but it is as performant
|
||||
as possible. When a process generates a lot of output, then this
|
||||
will be the bottleneck, because it processes just one character
|
||||
at a time.
|
||||
|
||||
We did many manual optimizations to this function in order to make
|
||||
it as efficient as possible. Don't change anything without profiling
|
||||
first.
|
||||
"""
|
||||
basic = self.basic
|
||||
listener = self.listener
|
||||
draw = listener.draw
|
||||
debug = listener.debug
|
||||
|
||||
ESC, CSI = ctrl.ESC, ctrl.CSI
|
||||
OSC, ST, DCS = ctrl.OSC, ctrl.ST, ctrl.DCS
|
||||
SP_OR_GT = ctrl.SP + b">"
|
||||
NUL_OR_DEL = ctrl.NUL + ctrl.DEL
|
||||
CAN_OR_SUB = ctrl.CAN + ctrl.SUB
|
||||
ALLOWED_IN_CSI = b"".join([ctrl.BEL, ctrl.BS, ctrl.HT, ctrl.LF,
|
||||
ctrl.VT, ctrl.FF, ctrl.CR])
|
||||
|
||||
def create_dispatcher(mapping):
|
||||
return defaultdict(lambda: debug, dict(
|
||||
(event, getattr(listener, attr))
|
||||
for event, attr in mapping.items()))
|
||||
|
||||
basic_dispatch = create_dispatcher(basic)
|
||||
sharp_dispatch = create_dispatcher(self.sharp)
|
||||
escape_dispatch = create_dispatcher(self.escape)
|
||||
csi_dispatch = create_dispatcher(self.csi)
|
||||
|
||||
while True:
|
||||
# ``True`` tells ``Screen.feed`` that it is allowed to send
|
||||
# chunks of plain text directly to the listener, instead
|
||||
# of this generator.)
|
||||
char = yield True
|
||||
|
||||
if char == ESC:
|
||||
# Most non-VT52 commands start with a left-bracket after the
|
||||
# escape and then a stream of parameters and a command; with
|
||||
# a single notable exception -- :data:`escape.DECOM` sequence,
|
||||
# which starts with a sharp.
|
||||
#
|
||||
# .. versionchanged:: 0.4.10
|
||||
#
|
||||
# For compatibility with Linux terminal stream also
|
||||
# recognizes ``ESC % C`` sequences for selecting control
|
||||
# character set. However, in the current version these
|
||||
# are noop.
|
||||
char = yield
|
||||
if char == b"[":
|
||||
char = CSI # Go to CSI.
|
||||
elif char == b"]":
|
||||
char = OSC # Go to OSC.
|
||||
elif char == b'P':
|
||||
char = DCS # Go to DCS
|
||||
else:
|
||||
if char == b"#":
|
||||
sharp_dispatch[(yield)]()
|
||||
if char == b"%":
|
||||
listener.select_other_charset((yield))
|
||||
elif char in b"()":
|
||||
listener.define_charset((yield), mode=char)
|
||||
else:
|
||||
escape_dispatch[char]()
|
||||
continue # Don't go to CSI.
|
||||
|
||||
if char in basic:
|
||||
basic_dispatch[char]()
|
||||
elif char == CSI:
|
||||
# All parameters are unsigned, positive decimal integers, with
|
||||
# the most significant digit sent first. Any parameter greater
|
||||
# than 9999 is set to 9999. If you do not specify a value, a 0
|
||||
# value is assumed.
|
||||
#
|
||||
# .. seealso::
|
||||
#
|
||||
# `VT102 User Guide <http://vt100.net/docs/vt102-ug/>`_
|
||||
# For details on the formatting of escape arguments.
|
||||
#
|
||||
# `VT220 Programmer Ref. <http://vt100.net/docs/vt220-rm/>`_
|
||||
# For details on the characters valid for use as
|
||||
# arguments.
|
||||
params = []
|
||||
current = bytearray()
|
||||
private = secondary = False
|
||||
while True:
|
||||
char = yield
|
||||
if char == b"?":
|
||||
private = True
|
||||
elif char in ALLOWED_IN_CSI:
|
||||
basic_dispatch[char]()
|
||||
elif char in SP_OR_GT:
|
||||
secondary = char.decode('ascii') # Added by Kovid
|
||||
elif char in CAN_OR_SUB:
|
||||
# If CAN or SUB is received during a sequence, the
|
||||
# current sequence is aborted; terminal displays
|
||||
# the substitute character, followed by characters
|
||||
# in the sequence received after CAN or SUB.
|
||||
draw(char)
|
||||
break
|
||||
elif char.isdigit():
|
||||
current.extend(char)
|
||||
else:
|
||||
params.append(min(int(bytes(current) or 0), 9999))
|
||||
|
||||
if char == b";":
|
||||
current = bytearray()
|
||||
else:
|
||||
if private:
|
||||
csi_dispatch[char](*params, private=True)
|
||||
else:
|
||||
if secondary: # Added by Kovid
|
||||
csi_dispatch[char](*params, secondary=secondary)
|
||||
else:
|
||||
csi_dispatch[char](*params)
|
||||
break # CSI is finished.
|
||||
elif char == OSC:
|
||||
code = bytearray()
|
||||
while True:
|
||||
char = yield
|
||||
if char == ST or char == ctrl.BEL or char == b';':
|
||||
break
|
||||
code.extend(char)
|
||||
code = bytes(code)
|
||||
param = bytearray()
|
||||
if char == b';':
|
||||
while True:
|
||||
char = yield
|
||||
if char == ST or char == ctrl.BEL:
|
||||
break
|
||||
else:
|
||||
param.extend(char)
|
||||
|
||||
param = bytes(param)
|
||||
try:
|
||||
code = int(code)
|
||||
except Exception:
|
||||
code = None
|
||||
if code == 0:
|
||||
listener.set_title(param)
|
||||
listener.set_icon_name(param)
|
||||
elif code == 1:
|
||||
listener.set_icon_name(param)
|
||||
elif code == 2:
|
||||
listener.set_title(param)
|
||||
elif 9 < code < 20:
|
||||
listener.set_dynamic_color(code, param)
|
||||
elif 109 < code < 120:
|
||||
listener.set_dynamic_color(code)
|
||||
elif char == DCS:
|
||||
# See http://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Device-Control-functions
|
||||
code = yield
|
||||
param = bytearray()
|
||||
while True:
|
||||
char = yield
|
||||
if char == ST:
|
||||
break
|
||||
else:
|
||||
param.extend(char)
|
||||
# TODO: Implement these
|
||||
elif char not in NUL_OR_DEL:
|
||||
draw(char)
|
||||
|
||||
|
||||
class DebugStream(Stream):
|
||||
r"""Stream, which dumps a subset of the dispatched events to a given
|
||||
file-like object (:data:`sys.stdout` by default).
|
||||
|
||||
>>> import io
|
||||
>>> with io.StringIO() as buf:
|
||||
... stream = DebugStream(to=buf)
|
||||
... stream.feed(b"\x1b[1;24r\x1b[4l\x1b[24;1H\x1b[0;10m")
|
||||
... print(buf.getvalue())
|
||||
...
|
||||
... # doctest: +NORMALIZE_WHITESPACE
|
||||
SET_MARGINS 1; 24
|
||||
RESET_MODE 4
|
||||
CURSOR_POSITION 24; 1
|
||||
SELECT_GRAPHIC_RENDITION 0; 10
|
||||
|
||||
:param file to: a file-like object to write debug information to.
|
||||
:param list only: a list of events you want to debug (empty by
|
||||
default, which means -- debug all events).
|
||||
"""
|
||||
|
||||
def __init__(self, screen, to=sys.stdout, only=()):
|
||||
stream = super(DebugStream, self)
|
||||
|
||||
def safe_str(chunk):
|
||||
if isinstance(chunk, bytes):
|
||||
chunk = chunk.decode("utf-8")
|
||||
elif not isinstance(chunk, str):
|
||||
chunk = str(chunk)
|
||||
|
||||
return chunk
|
||||
|
||||
class Bugger:
|
||||
|
||||
def __getattr__(self, event):
|
||||
|
||||
@wraps(getattr(screen, event))
|
||||
def inner(*args, **kwargs):
|
||||
if not only or event in only:
|
||||
to.write(event.upper() + " ")
|
||||
to.write("; ".join(map(safe_str, args)))
|
||||
to.write(" ")
|
||||
to.write(", ".join("{0}: {1}".format(k, safe_str(v))
|
||||
for k, v in kwargs.items()))
|
||||
to.write(os.linesep)
|
||||
getattr(screen, event)(*args, **kwargs)
|
||||
|
||||
return inner
|
||||
stream.__init__(Bugger())
|
||||
@ -1,5 +1,5 @@
|
||||
" Scan the following dirs recursively for tags
|
||||
let g:project_tags_dirs = ['kitty', 'pyte']
|
||||
let g:project_tags_dirs = ['kitty']
|
||||
let g:syntastic_python_flake8_exec = 'flake8'
|
||||
let g:ycm_python_binary_path = 'python3'
|
||||
set wildignore+==template.py
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user