RAHHH
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
#
|
||||
|
||||
|
||||
"""
|
||||
twisted.conch.ui is home to the UI elements for tkconch.
|
||||
|
||||
Maintainer: Paul Swartz
|
||||
"""
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
253
backend/lib/python3.12/site-packages/twisted/conch/ui/ansi.py
Normal file
253
backend/lib/python3.12/site-packages/twisted/conch/ui/ansi.py
Normal file
@@ -0,0 +1,253 @@
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
#
|
||||
"""Module to parse ANSI escape sequences
|
||||
|
||||
Maintainer: Jean-Paul Calderone
|
||||
"""
|
||||
|
||||
import string
|
||||
|
||||
# Twisted imports
|
||||
from twisted.logger import Logger
|
||||
|
||||
_log = Logger()
|
||||
|
||||
|
||||
class ColorText:
|
||||
"""
|
||||
Represents an element of text along with the texts colors and
|
||||
additional attributes.
|
||||
"""
|
||||
|
||||
# The colors to use
|
||||
COLORS = ("b", "r", "g", "y", "l", "m", "c", "w")
|
||||
BOLD_COLORS = tuple(x.upper() for x in COLORS)
|
||||
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(len(COLORS))
|
||||
|
||||
# Color names
|
||||
COLOR_NAMES = (
|
||||
"Black",
|
||||
"Red",
|
||||
"Green",
|
||||
"Yellow",
|
||||
"Blue",
|
||||
"Magenta",
|
||||
"Cyan",
|
||||
"White",
|
||||
)
|
||||
|
||||
def __init__(self, text, fg, bg, display, bold, underline, flash, reverse):
|
||||
self.text, self.fg, self.bg = text, fg, bg
|
||||
self.display = display
|
||||
self.bold = bold
|
||||
self.underline = underline
|
||||
self.flash = flash
|
||||
self.reverse = reverse
|
||||
if self.reverse:
|
||||
self.fg, self.bg = self.bg, self.fg
|
||||
|
||||
|
||||
class AnsiParser:
|
||||
"""
|
||||
Parser class for ANSI codes.
|
||||
"""
|
||||
|
||||
# Terminators for cursor movement ansi controls - unsupported
|
||||
CURSOR_SET = ("H", "f", "A", "B", "C", "D", "R", "s", "u", "d", "G")
|
||||
|
||||
# Terminators for erasure ansi controls - unsupported
|
||||
ERASE_SET = ("J", "K", "P")
|
||||
|
||||
# Terminators for mode change ansi controls - unsupported
|
||||
MODE_SET = ("h", "l")
|
||||
|
||||
# Terminators for keyboard assignment ansi controls - unsupported
|
||||
ASSIGN_SET = ("p",)
|
||||
|
||||
# Terminators for color change ansi controls - supported
|
||||
COLOR_SET = ("m",)
|
||||
|
||||
SETS = (CURSOR_SET, ERASE_SET, MODE_SET, ASSIGN_SET, COLOR_SET)
|
||||
|
||||
def __init__(self, defaultFG, defaultBG):
|
||||
self.defaultFG, self.defaultBG = defaultFG, defaultBG
|
||||
self.currentFG, self.currentBG = self.defaultFG, self.defaultBG
|
||||
self.bold, self.flash, self.underline, self.reverse = 0, 0, 0, 0
|
||||
self.display = 1
|
||||
self.prepend = ""
|
||||
|
||||
def stripEscapes(self, string):
|
||||
"""
|
||||
Remove all ANSI color escapes from the given string.
|
||||
"""
|
||||
result = ""
|
||||
show = 1
|
||||
i = 0
|
||||
L = len(string)
|
||||
while i < L:
|
||||
if show == 0 and string[i] in _sets:
|
||||
show = 1
|
||||
elif show:
|
||||
n = string.find("\x1B", i)
|
||||
if n == -1:
|
||||
return result + string[i:]
|
||||
else:
|
||||
result = result + string[i:n]
|
||||
i = n
|
||||
show = 0
|
||||
i = i + 1
|
||||
return result
|
||||
|
||||
def writeString(self, colorstr):
|
||||
pass
|
||||
|
||||
def parseString(self, str):
|
||||
"""
|
||||
Turn a string input into a list of L{ColorText} elements.
|
||||
"""
|
||||
|
||||
if self.prepend:
|
||||
str = self.prepend + str
|
||||
self.prepend = ""
|
||||
parts = str.split("\x1B")
|
||||
|
||||
if len(parts) == 1:
|
||||
self.writeString(self.formatText(parts[0]))
|
||||
else:
|
||||
self.writeString(self.formatText(parts[0]))
|
||||
for s in parts[1:]:
|
||||
L = len(s)
|
||||
i = 0
|
||||
type = None
|
||||
while i < L:
|
||||
if s[i] not in string.digits + "[;?":
|
||||
break
|
||||
i += 1
|
||||
if not s:
|
||||
self.prepend = "\x1b"
|
||||
return
|
||||
if s[0] != "[":
|
||||
self.writeString(self.formatText(s[i + 1 :]))
|
||||
continue
|
||||
else:
|
||||
s = s[1:]
|
||||
i -= 1
|
||||
if i == L - 1:
|
||||
self.prepend = "\x1b["
|
||||
return
|
||||
type = _setmap.get(s[i], None)
|
||||
if type is None:
|
||||
continue
|
||||
|
||||
if type == AnsiParser.COLOR_SET:
|
||||
self.parseColor(s[: i + 1])
|
||||
s = s[i + 1 :]
|
||||
self.writeString(self.formatText(s))
|
||||
elif type == AnsiParser.CURSOR_SET:
|
||||
cursor, s = s[: i + 1], s[i + 1 :]
|
||||
self.parseCursor(cursor)
|
||||
self.writeString(self.formatText(s))
|
||||
elif type == AnsiParser.ERASE_SET:
|
||||
erase, s = s[: i + 1], s[i + 1 :]
|
||||
self.parseErase(erase)
|
||||
self.writeString(self.formatText(s))
|
||||
elif type == AnsiParser.MODE_SET:
|
||||
s = s[i + 1 :]
|
||||
# self.parseErase('2J')
|
||||
self.writeString(self.formatText(s))
|
||||
elif i == L:
|
||||
self.prepend = "\x1B[" + s
|
||||
else:
|
||||
_log.warn(
|
||||
"Unhandled ANSI control type: {control_type}", control_type=s[i]
|
||||
)
|
||||
s = s[i + 1 :]
|
||||
self.writeString(self.formatText(s))
|
||||
|
||||
def parseColor(self, str):
|
||||
"""
|
||||
Handle a single ANSI color sequence
|
||||
"""
|
||||
# Drop the trailing 'm'
|
||||
str = str[:-1]
|
||||
|
||||
if not str:
|
||||
str = "0"
|
||||
|
||||
try:
|
||||
parts = map(int, str.split(";"))
|
||||
except ValueError:
|
||||
_log.error("Invalid ANSI color sequence: {sequence!r}", sequence=str)
|
||||
self.currentFG, self.currentBG = self.defaultFG, self.defaultBG
|
||||
return
|
||||
|
||||
for x in parts:
|
||||
if x == 0:
|
||||
self.currentFG, self.currentBG = self.defaultFG, self.defaultBG
|
||||
self.bold, self.flash, self.underline, self.reverse = 0, 0, 0, 0
|
||||
self.display = 1
|
||||
elif x == 1:
|
||||
self.bold = 1
|
||||
elif 30 <= x <= 37:
|
||||
self.currentFG = x - 30
|
||||
elif 40 <= x <= 47:
|
||||
self.currentBG = x - 40
|
||||
elif x == 39:
|
||||
self.currentFG = self.defaultFG
|
||||
elif x == 49:
|
||||
self.currentBG = self.defaultBG
|
||||
elif x == 4:
|
||||
self.underline = 1
|
||||
elif x == 5:
|
||||
self.flash = 1
|
||||
elif x == 7:
|
||||
self.reverse = 1
|
||||
elif x == 8:
|
||||
self.display = 0
|
||||
elif x == 22:
|
||||
self.bold = 0
|
||||
elif x == 24:
|
||||
self.underline = 0
|
||||
elif x == 25:
|
||||
self.blink = 0
|
||||
elif x == 27:
|
||||
self.reverse = 0
|
||||
elif x == 28:
|
||||
self.display = 1
|
||||
else:
|
||||
_log.error("Unrecognised ANSI color command: {command}", command=x)
|
||||
|
||||
def parseCursor(self, cursor):
|
||||
pass
|
||||
|
||||
def parseErase(self, erase):
|
||||
pass
|
||||
|
||||
def pickColor(self, value, mode, BOLD=ColorText.BOLD_COLORS):
|
||||
if mode:
|
||||
return ColorText.COLORS[value]
|
||||
else:
|
||||
return self.bold and BOLD[value] or ColorText.COLORS[value]
|
||||
|
||||
def formatText(self, text):
|
||||
return ColorText(
|
||||
text,
|
||||
self.pickColor(self.currentFG, 0),
|
||||
self.pickColor(self.currentBG, 1),
|
||||
self.display,
|
||||
self.bold,
|
||||
self.underline,
|
||||
self.flash,
|
||||
self.reverse,
|
||||
)
|
||||
|
||||
|
||||
_sets = "".join(map("".join, AnsiParser.SETS))
|
||||
|
||||
_setmap = {}
|
||||
for s in AnsiParser.SETS:
|
||||
for r in s:
|
||||
_setmap[r] = s
|
||||
del s
|
||||
249
backend/lib/python3.12/site-packages/twisted/conch/ui/tkvt100.py
Normal file
249
backend/lib/python3.12/site-packages/twisted/conch/ui/tkvt100.py
Normal file
@@ -0,0 +1,249 @@
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
#
|
||||
|
||||
"""Module to emulate a VT100 terminal in Tkinter.
|
||||
|
||||
Maintainer: Paul Swartz
|
||||
"""
|
||||
|
||||
import string
|
||||
import tkinter as Tkinter
|
||||
import tkinter.font as tkFont
|
||||
|
||||
from . import ansi
|
||||
|
||||
ttyFont = None # tkFont.Font(family = 'Courier', size = 10)
|
||||
fontWidth, fontHeight = (
|
||||
None,
|
||||
None,
|
||||
) # max(map(ttyFont.measure, string.letters+string.digits)), int(ttyFont.metrics()['linespace'])
|
||||
|
||||
colorKeys = (
|
||||
"b",
|
||||
"r",
|
||||
"g",
|
||||
"y",
|
||||
"l",
|
||||
"m",
|
||||
"c",
|
||||
"w",
|
||||
"B",
|
||||
"R",
|
||||
"G",
|
||||
"Y",
|
||||
"L",
|
||||
"M",
|
||||
"C",
|
||||
"W",
|
||||
)
|
||||
|
||||
colorMap = {
|
||||
"b": "#000000",
|
||||
"r": "#c40000",
|
||||
"g": "#00c400",
|
||||
"y": "#c4c400",
|
||||
"l": "#000080",
|
||||
"m": "#c400c4",
|
||||
"c": "#00c4c4",
|
||||
"w": "#c4c4c4",
|
||||
"B": "#626262",
|
||||
"R": "#ff0000",
|
||||
"G": "#00ff00",
|
||||
"Y": "#ffff00",
|
||||
"L": "#0000ff",
|
||||
"M": "#ff00ff",
|
||||
"C": "#00ffff",
|
||||
"W": "#ffffff",
|
||||
}
|
||||
|
||||
|
||||
class VT100Frame(Tkinter.Frame):
|
||||
def __init__(self, *args, **kw):
|
||||
global ttyFont, fontHeight, fontWidth
|
||||
ttyFont = tkFont.Font(family="Courier", size=10)
|
||||
fontWidth = max(map(ttyFont.measure, string.ascii_letters + string.digits))
|
||||
fontHeight = int(ttyFont.metrics()["linespace"])
|
||||
self.width = kw.get("width", 80)
|
||||
self.height = kw.get("height", 25)
|
||||
self.callback = kw["callback"]
|
||||
del kw["callback"]
|
||||
kw["width"] = w = fontWidth * self.width
|
||||
kw["height"] = h = fontHeight * self.height
|
||||
Tkinter.Frame.__init__(self, *args, **kw)
|
||||
self.canvas = Tkinter.Canvas(bg="#000000", width=w, height=h)
|
||||
self.canvas.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
|
||||
self.canvas.bind("<Key>", self.keyPressed)
|
||||
self.canvas.bind("<1>", lambda x: "break")
|
||||
self.canvas.bind("<Up>", self.upPressed)
|
||||
self.canvas.bind("<Down>", self.downPressed)
|
||||
self.canvas.bind("<Left>", self.leftPressed)
|
||||
self.canvas.bind("<Right>", self.rightPressed)
|
||||
self.canvas.focus()
|
||||
|
||||
self.ansiParser = ansi.AnsiParser(ansi.ColorText.WHITE, ansi.ColorText.BLACK)
|
||||
self.ansiParser.writeString = self.writeString
|
||||
self.ansiParser.parseCursor = self.parseCursor
|
||||
self.ansiParser.parseErase = self.parseErase
|
||||
# for (a, b) in colorMap.items():
|
||||
# self.canvas.tag_config(a, foreground=b)
|
||||
# self.canvas.tag_config('b'+a, background=b)
|
||||
# self.canvas.tag_config('underline', underline=1)
|
||||
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
self.cursor = self.canvas.create_rectangle(
|
||||
0, 0, fontWidth - 1, fontHeight - 1, fill="green", outline="green"
|
||||
)
|
||||
|
||||
def _delete(self, sx, sy, ex, ey):
|
||||
csx = sx * fontWidth + 1
|
||||
csy = sy * fontHeight + 1
|
||||
cex = ex * fontWidth + 3
|
||||
cey = ey * fontHeight + 3
|
||||
items = self.canvas.find_overlapping(csx, csy, cex, cey)
|
||||
for item in items:
|
||||
self.canvas.delete(item)
|
||||
|
||||
def _write(self, ch, fg, bg):
|
||||
if self.x == self.width:
|
||||
self.x = 0
|
||||
self.y += 1
|
||||
if self.y == self.height:
|
||||
[self.canvas.move(x, 0, -fontHeight) for x in self.canvas.find_all()]
|
||||
self.y -= 1
|
||||
canvasX = self.x * fontWidth + 1
|
||||
canvasY = self.y * fontHeight + 1
|
||||
items = self.canvas.find_overlapping(canvasX, canvasY, canvasX + 2, canvasY + 2)
|
||||
if items:
|
||||
[self.canvas.delete(item) for item in items]
|
||||
if bg:
|
||||
self.canvas.create_rectangle(
|
||||
canvasX,
|
||||
canvasY,
|
||||
canvasX + fontWidth - 1,
|
||||
canvasY + fontHeight - 1,
|
||||
fill=bg,
|
||||
outline=bg,
|
||||
)
|
||||
self.canvas.create_text(
|
||||
canvasX, canvasY, anchor=Tkinter.NW, font=ttyFont, text=ch, fill=fg
|
||||
)
|
||||
self.x += 1
|
||||
|
||||
def write(self, data):
|
||||
self.ansiParser.parseString(data)
|
||||
self.canvas.delete(self.cursor)
|
||||
canvasX = self.x * fontWidth + 1
|
||||
canvasY = self.y * fontHeight + 1
|
||||
self.cursor = self.canvas.create_rectangle(
|
||||
canvasX,
|
||||
canvasY,
|
||||
canvasX + fontWidth - 1,
|
||||
canvasY + fontHeight - 1,
|
||||
fill="green",
|
||||
outline="green",
|
||||
)
|
||||
self.canvas.lower(self.cursor)
|
||||
|
||||
def writeString(self, i):
|
||||
if not i.display:
|
||||
return
|
||||
fg = colorMap[i.fg]
|
||||
bg = i.bg != "b" and colorMap[i.bg]
|
||||
for ch in i.text:
|
||||
b = ord(ch)
|
||||
if b == 7: # bell
|
||||
self.bell()
|
||||
elif b == 8: # BS
|
||||
if self.x:
|
||||
self.x -= 1
|
||||
elif b == 9: # TAB
|
||||
[self._write(" ", fg, bg) for index in range(8)]
|
||||
elif b == 10:
|
||||
if self.y == self.height - 1:
|
||||
self._delete(0, 0, self.width, 0)
|
||||
[
|
||||
self.canvas.move(x, 0, -fontHeight)
|
||||
for x in self.canvas.find_all()
|
||||
]
|
||||
else:
|
||||
self.y += 1
|
||||
elif b == 13:
|
||||
self.x = 0
|
||||
elif 32 <= b < 127:
|
||||
self._write(ch, fg, bg)
|
||||
|
||||
def parseErase(self, erase):
|
||||
if ";" in erase:
|
||||
end = erase[-1]
|
||||
parts = erase[:-1].split(";")
|
||||
[self.parseErase(x + end) for x in parts]
|
||||
return
|
||||
start = 0
|
||||
x, y = self.x, self.y
|
||||
if len(erase) > 1:
|
||||
start = int(erase[:-1])
|
||||
if erase[-1] == "J":
|
||||
if start == 0:
|
||||
self._delete(x, y, self.width, self.height)
|
||||
else:
|
||||
self._delete(0, 0, self.width, self.height)
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
elif erase[-1] == "K":
|
||||
if start == 0:
|
||||
self._delete(x, y, self.width, y)
|
||||
elif start == 1:
|
||||
self._delete(0, y, x, y)
|
||||
self.x = 0
|
||||
else:
|
||||
self._delete(0, y, self.width, y)
|
||||
self.x = 0
|
||||
elif erase[-1] == "P":
|
||||
self._delete(x, y, x + start, y)
|
||||
|
||||
def parseCursor(self, cursor):
|
||||
# if ';' in cursor and cursor[-1]!='H':
|
||||
# end = cursor[-1]
|
||||
# parts = cursor[:-1].split(';')
|
||||
# [self.parseCursor(x+end) for x in parts]
|
||||
# return
|
||||
start = 1
|
||||
if len(cursor) > 1 and cursor[-1] != "H":
|
||||
start = int(cursor[:-1])
|
||||
if cursor[-1] == "C":
|
||||
self.x += start
|
||||
elif cursor[-1] == "D":
|
||||
self.x -= start
|
||||
elif cursor[-1] == "d":
|
||||
self.y = start - 1
|
||||
elif cursor[-1] == "G":
|
||||
self.x = start - 1
|
||||
elif cursor[-1] == "H":
|
||||
if len(cursor) > 1:
|
||||
y, x = map(int, cursor[:-1].split(";"))
|
||||
y -= 1
|
||||
x -= 1
|
||||
else:
|
||||
x, y = 0, 0
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
def keyPressed(self, event):
|
||||
if self.callback and event.char:
|
||||
self.callback(event.char)
|
||||
return "break"
|
||||
|
||||
def upPressed(self, event):
|
||||
self.callback("\x1bOA")
|
||||
|
||||
def downPressed(self, event):
|
||||
self.callback("\x1bOB")
|
||||
|
||||
def rightPressed(self, event):
|
||||
self.callback("\x1bOC")
|
||||
|
||||
def leftPressed(self, event):
|
||||
self.callback("\x1bOD")
|
||||
Reference in New Issue
Block a user