mirror of
https://github.com/chubin/cheat.sh.git
synced 2024-12-01 02:36:48 +03:00
added panela/ (currently used to generate firstpage-v2)
This commit is contained in:
parent
ec73ad8482
commit
70e06280a1
BIN
lib/panela/.panela_colors.py.swp
Normal file
BIN
lib/panela/.panela_colors.py.swp
Normal file
Binary file not shown.
1
lib/panela/colors.json
Normal file
1
lib/panela/colors.json
Normal file
File diff suppressed because one or more lines are too long
25
lib/panela/colors.py
Normal file
25
lib/panela/colors.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
COLORS_JSON = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'colors.json')
|
||||||
|
COLOR_TABLE = json.loads(open(COLORS_JSON, 'r').read())
|
||||||
|
VALID_COLORS = [x['hexString'] for x in COLOR_TABLE]
|
||||||
|
HEX_TO_ANSI = {x['hexString']:x['colorId'] for x in COLOR_TABLE}
|
||||||
|
|
||||||
|
def rgb_from_str(s):
|
||||||
|
# s starts with a #.
|
||||||
|
r, g, b = int(s[1:3],16), int(s[3:5], 16),int(s[5:7], 16)
|
||||||
|
return r, g, b
|
||||||
|
|
||||||
|
def find_nearest_color(hex_color):
|
||||||
|
R, G, B = rgb_from_str(hex_color)
|
||||||
|
mindiff = None
|
||||||
|
for d in VALID_COLORS:
|
||||||
|
r, g, b = rgb_from_str(d)
|
||||||
|
diff = abs(R -r)*256 + abs(G-g)* 256 + abs(B- b)* 256
|
||||||
|
if mindiff is None or diff < mindiff:
|
||||||
|
mindiff = diff
|
||||||
|
mincolorname = d
|
||||||
|
return mincolorname
|
||||||
|
|
||||||
|
|
637
lib/panela/panela_colors.py
Normal file
637
lib/panela/panela_colors.py
Normal file
@ -0,0 +1,637 @@
|
|||||||
|
# vim: encoding=utf-8
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import colored
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
After panela will be ready for it, it will be splitted out in a separate project,
|
||||||
|
that will be used for all chubin's console services.
|
||||||
|
There are several features that not yet implemented (see ___doc___ in Panela)
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
* html output
|
||||||
|
* png output
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from wcwidth import wcswidth
|
||||||
|
from colors import find_nearest_color, HEX_TO_ANSI, rgb_from_str
|
||||||
|
import pyte
|
||||||
|
|
||||||
|
# http://stackoverflow.com/questions/19782975/convert-rgb-color-to-the-nearest-color-in-palette-web-safe-color
|
||||||
|
# pylint: disable=invalid-name
|
||||||
|
|
||||||
|
def color_mapping(clr):
|
||||||
|
if clr == 'default':
|
||||||
|
return None
|
||||||
|
return clr
|
||||||
|
|
||||||
|
class Point(object):
|
||||||
|
"""
|
||||||
|
One point (character) on a terminal
|
||||||
|
"""
|
||||||
|
def __init__(self, char=None, foreground=None, background=None):
|
||||||
|
self.foreground = foreground
|
||||||
|
self.background = background
|
||||||
|
self.char = char
|
||||||
|
|
||||||
|
class Panela:
|
||||||
|
|
||||||
|
"""
|
||||||
|
To implement:
|
||||||
|
|
||||||
|
Blocks manipulation:
|
||||||
|
|
||||||
|
[*] copy
|
||||||
|
[*] crop
|
||||||
|
[*] cut
|
||||||
|
[*] extend
|
||||||
|
[ ] join
|
||||||
|
[ ] move
|
||||||
|
[*] paste
|
||||||
|
[*] strip
|
||||||
|
|
||||||
|
Colors manipulation:
|
||||||
|
|
||||||
|
[*] paint foreground/background
|
||||||
|
[*] paint_line
|
||||||
|
[ ] paint_svg
|
||||||
|
[ ] fill background
|
||||||
|
[ ] fill_line
|
||||||
|
[ ] fill_svg
|
||||||
|
[ ] trans
|
||||||
|
|
||||||
|
Drawing:
|
||||||
|
|
||||||
|
[*] put_point
|
||||||
|
[*] put_line
|
||||||
|
[*] put_circle
|
||||||
|
[*] put_rectangle
|
||||||
|
|
||||||
|
Printing and reading:
|
||||||
|
ansi reads vt100 sequence
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, x=80, y=25, panela=None, field=None):
|
||||||
|
|
||||||
|
if panela:
|
||||||
|
self.field = [x for x in panela.field]
|
||||||
|
self.size_x = panela.size_x
|
||||||
|
self.size_y = panela.size_y
|
||||||
|
return
|
||||||
|
|
||||||
|
if field:
|
||||||
|
self.field = field
|
||||||
|
self.size_x = len(field[0])
|
||||||
|
self.size_y = len(field)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.field = [[Point() for _ in range(x)] for _ in range(y)]
|
||||||
|
self.size_x = x
|
||||||
|
self.size_y = y
|
||||||
|
|
||||||
|
def in_field(self, col, row):
|
||||||
|
if col < 0:
|
||||||
|
return False
|
||||||
|
if row < 0:
|
||||||
|
return False
|
||||||
|
if col >= self.size_x:
|
||||||
|
return False
|
||||||
|
if row >= self.size_y:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
#
|
||||||
|
# Blocks manipulation
|
||||||
|
#
|
||||||
|
|
||||||
|
def copy(self, x1, y1, x2, y2):
|
||||||
|
|
||||||
|
if x1 < 0:
|
||||||
|
x1 += self.size_x
|
||||||
|
if x2 < 0:
|
||||||
|
x2 += self.size_x
|
||||||
|
if x1 > x2:
|
||||||
|
x1, x2 = x2, x1
|
||||||
|
|
||||||
|
if y1 < 0:
|
||||||
|
y1 += self.size_y
|
||||||
|
if y2 < 0:
|
||||||
|
y2 += self.size_y
|
||||||
|
if y1 > y2:
|
||||||
|
y1, y2 = y2, y1
|
||||||
|
|
||||||
|
field = [self.field[i] for i in range(y1, y2+1)]
|
||||||
|
field = [line[x1:x2+1] for line in field]
|
||||||
|
|
||||||
|
return Panela(field=field)
|
||||||
|
|
||||||
|
def cut(self, x1, y1, x2, y2):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
if x1 < 0:
|
||||||
|
x1 += self.size_x
|
||||||
|
if x2 < 0:
|
||||||
|
x2 += self.size_x
|
||||||
|
if x1 > x2:
|
||||||
|
x1, x2 = x2, x1
|
||||||
|
|
||||||
|
if y1 < 0:
|
||||||
|
y1 += self.size_y
|
||||||
|
if y2 < 0:
|
||||||
|
y2 += self.size_y
|
||||||
|
if y1 > y2:
|
||||||
|
y1, y2 = y2, y1
|
||||||
|
|
||||||
|
copied = self.copy(x1, y1, x2, y2)
|
||||||
|
|
||||||
|
for y in range(y1, y2+1):
|
||||||
|
for x in range(x1, x2+1):
|
||||||
|
self.field[y][x] = Point()
|
||||||
|
|
||||||
|
return copied
|
||||||
|
|
||||||
|
def extend(self, cols=None, rows=None):
|
||||||
|
"""
|
||||||
|
Adds [cols] columns from the right
|
||||||
|
and [rows] rows from the bottom
|
||||||
|
"""
|
||||||
|
if cols and cols > 0:
|
||||||
|
self.field = [x + [Point() for _ in range(cols)] for x in self.field]
|
||||||
|
self.size_x += cols
|
||||||
|
|
||||||
|
if rows and rows > 0:
|
||||||
|
self.field = self.field + [[Point() for _ in range(self.size_x)] for _ in range(rows)]
|
||||||
|
self.size_y += rows
|
||||||
|
|
||||||
|
def crop(self, left=None, right=None, top=None, bottom=None):
|
||||||
|
"""
|
||||||
|
Crop panela.
|
||||||
|
Remove <left>, <right> columns from left or right,
|
||||||
|
and <top> and <bottom> rows from top and bottom.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if left:
|
||||||
|
if left >= self.size_x:
|
||||||
|
left = self.size_x
|
||||||
|
self.field = [x[left:] for x in self.field]
|
||||||
|
self.size_x -= left
|
||||||
|
|
||||||
|
if right:
|
||||||
|
if right >= self.size_x:
|
||||||
|
right = self.size_x
|
||||||
|
self.field = [x[:-right] for x in self.field]
|
||||||
|
self.size_x -= right
|
||||||
|
|
||||||
|
if top:
|
||||||
|
if top >= self.size_y:
|
||||||
|
top = self.size_y
|
||||||
|
self.field = self.field[top:]
|
||||||
|
self.size_y -= top
|
||||||
|
|
||||||
|
if bottom:
|
||||||
|
if bottom >= self.size_y:
|
||||||
|
bottom = self.size_y
|
||||||
|
self.field = self.field[:-bottom]
|
||||||
|
self.size_y -= bottom
|
||||||
|
|
||||||
|
def paste(self, panela, x1, y1, extend=False, transparence=False):
|
||||||
|
"""
|
||||||
|
Paste <panela> starting at <x1>, <y1>.
|
||||||
|
If <extend> is True current panela space will be automatically extended
|
||||||
|
If <transparence> is True, then <panela> is overlayed and characters behind them are seen
|
||||||
|
"""
|
||||||
|
|
||||||
|
# FIXME:
|
||||||
|
# negative x1, y1
|
||||||
|
# x1,y1 > size_x, size_y
|
||||||
|
|
||||||
|
if extend:
|
||||||
|
x_extend = 0
|
||||||
|
y_extend = 0
|
||||||
|
if x1 + panela.size_x > self.size_x:
|
||||||
|
x_extend = x1 + panela.size_x - self.size_x
|
||||||
|
if y1 + panela.size_y > self.size_y:
|
||||||
|
y_extend = y1 + panela.size_y - self.size_y
|
||||||
|
self.extend(cols=x_extend, rows=y_extend)
|
||||||
|
|
||||||
|
for i in range(y1, min(self.size_y, y1+panela.size_y)):
|
||||||
|
for j in range(x1, min(self.size_x, x1+panela.size_x)):
|
||||||
|
if transparence:
|
||||||
|
if panela.field[i-y1][j-x1].char and panela.field[i-y1][j-x1].char != " ":
|
||||||
|
if panela.field[i-y1][j-x1].foreground:
|
||||||
|
self.field[i][j].foreground = panela.field[i-y1][j-x1].foreground
|
||||||
|
if panela.field[i-y1][j-x1].background:
|
||||||
|
self.field[i][j].background = panela.field[i-y1][j-x1].background
|
||||||
|
self.field[i][j].char = panela.field[i-y1][j-x1].char
|
||||||
|
else:
|
||||||
|
self.field[i][j] = panela.field[i-y1][j-x1]
|
||||||
|
|
||||||
|
def strip(self):
|
||||||
|
"""
|
||||||
|
Strip panela: remove empty spaces around panels rectangle
|
||||||
|
"""
|
||||||
|
|
||||||
|
def left_spaces(line):
|
||||||
|
answer = 0
|
||||||
|
for elem in line:
|
||||||
|
if not elem.char:
|
||||||
|
answer += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return answer
|
||||||
|
|
||||||
|
def right_spaces(line):
|
||||||
|
return left_spaces(line[::-1])
|
||||||
|
|
||||||
|
def empty_line(line):
|
||||||
|
return left_spaces(line) == len(line)
|
||||||
|
|
||||||
|
left_space = []
|
||||||
|
right_space = []
|
||||||
|
for line in self.field:
|
||||||
|
left_space.append(left_spaces(line))
|
||||||
|
right_space.append(right_spaces(line))
|
||||||
|
left = min(left_space)
|
||||||
|
right = min(right_space)
|
||||||
|
|
||||||
|
top = 0
|
||||||
|
while top < self.size_y and empty_line(self.field[top]):
|
||||||
|
top += 1
|
||||||
|
|
||||||
|
bottom = 0
|
||||||
|
while bottom < self.size_y and empty_line(self.field[-(bottom+1)]):
|
||||||
|
bottom += 1
|
||||||
|
|
||||||
|
self.crop(left=left, right=right, top=top, bottom=bottom)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Drawing and painting
|
||||||
|
#
|
||||||
|
|
||||||
|
def put_point(self, col, row, char=None, color=None, background=None):
|
||||||
|
"""
|
||||||
|
Puts charachter with color and background color on the field.
|
||||||
|
Char can be a Point or a character.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.in_field(col, row):
|
||||||
|
return
|
||||||
|
if isinstance(char, Point):
|
||||||
|
self.field[row][col] = char
|
||||||
|
elif char is None:
|
||||||
|
if background:
|
||||||
|
self.field[row][col].background = background
|
||||||
|
if color:
|
||||||
|
self.field[row][col].foreground = color
|
||||||
|
else:
|
||||||
|
self.field[row][col] = Point(char=char, foreground=color, background=background)
|
||||||
|
|
||||||
|
def put_string(self, col, row, s=None, color=None, background=None):
|
||||||
|
"""
|
||||||
|
Put string <s> with foreground color <color> and background color <background>
|
||||||
|
ad <col>, <row>
|
||||||
|
"""
|
||||||
|
for i, c in enumerate(s):
|
||||||
|
self.put_point(col+i, row, c, color=color, background=background)
|
||||||
|
|
||||||
|
def put_line(self, x1, y1, x2, y2, char=None, color=None, background=None):
|
||||||
|
"""
|
||||||
|
Draw line (x1, y1) - (x2, y2) fith foreground color <color>, background color <background>
|
||||||
|
and charachter <char>, if specified.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_line(start, end):
|
||||||
|
"""Bresenham's Line Algorithm
|
||||||
|
Produces a list of tuples from start and end
|
||||||
|
|
||||||
|
Source: http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm#Python
|
||||||
|
|
||||||
|
>>> points1 = get_line((0, 0), (3, 4))
|
||||||
|
>>> points2 = get_line((3, 4), (0, 0))
|
||||||
|
>>> assert(set(points1) == set(points2))
|
||||||
|
>>> print points1
|
||||||
|
[(0, 0), (1, 1), (1, 2), (2, 3), (3, 4)]
|
||||||
|
>>> print points2
|
||||||
|
[(3, 4), (2, 3), (1, 2), (1, 1), (0, 0)]
|
||||||
|
"""
|
||||||
|
# Setup initial conditions
|
||||||
|
x1, y1 = start
|
||||||
|
x2, y2 = end
|
||||||
|
dx = x2 - x1
|
||||||
|
dy = y2 - y1
|
||||||
|
|
||||||
|
# Determine how steep the line is
|
||||||
|
is_steep = abs(dy) > abs(dx)
|
||||||
|
|
||||||
|
# Rotate line
|
||||||
|
if is_steep:
|
||||||
|
x1, y1 = y1, x1
|
||||||
|
x2, y2 = y2, x2
|
||||||
|
|
||||||
|
# Swap start and end points if necessary and store swap state
|
||||||
|
swapped = False
|
||||||
|
if x1 > x2:
|
||||||
|
x1, x2 = x2, x1
|
||||||
|
y1, y2 = y2, y1
|
||||||
|
swapped = True
|
||||||
|
|
||||||
|
# Recalculate differentials
|
||||||
|
dx = x2 - x1
|
||||||
|
dy = y2 - y1
|
||||||
|
|
||||||
|
# Calculate error
|
||||||
|
error = int(dx / 2.0)
|
||||||
|
ystep = 1 if y1 < y2 else -1
|
||||||
|
|
||||||
|
# Iterate over bounding box generating points between start and end
|
||||||
|
y = y1
|
||||||
|
points = []
|
||||||
|
for x in range(x1, x2 + 1):
|
||||||
|
coord = (y, x) if is_steep else (x, y)
|
||||||
|
points.append(coord)
|
||||||
|
error -= abs(dy)
|
||||||
|
if error < 0:
|
||||||
|
y += ystep
|
||||||
|
error += dx
|
||||||
|
|
||||||
|
# Reverse the list if the coordinates were swapped
|
||||||
|
if swapped:
|
||||||
|
points.reverse()
|
||||||
|
return points
|
||||||
|
|
||||||
|
if color and not isinstance(color, basestring):
|
||||||
|
color_iter = itertools.cycle(color)
|
||||||
|
else:
|
||||||
|
color_iter = itertools.repeat(color)
|
||||||
|
|
||||||
|
if background and not isinstance(background, basestring):
|
||||||
|
background_iter = itertools.cycle(background)
|
||||||
|
else:
|
||||||
|
background_iter = itertools.repeat(background)
|
||||||
|
|
||||||
|
if char:
|
||||||
|
char_iter = itertools.cycle(char)
|
||||||
|
else:
|
||||||
|
char_iter = itertools.repeat(char)
|
||||||
|
|
||||||
|
for x, y in get_line((x1,y1), (x2, y2)):
|
||||||
|
char = char_iter.next()
|
||||||
|
color = color_iter.next()
|
||||||
|
background = next(background_iter)
|
||||||
|
|
||||||
|
self.put_point(x, y, char=char, color=color, background=background)
|
||||||
|
|
||||||
|
def paint(self, x1, y1, x2, y2, c1, c2=None, bg1=None, bg2=None, angle=None, angle_bg=None):
|
||||||
|
"""
|
||||||
|
Paint rectangle (x1,y1) (x2,y2) with foreground color c1 and background bg1 if specified.
|
||||||
|
If spefied colors c2/bg2, rectangle is painted with linear gradient (inclined under angle).
|
||||||
|
"""
|
||||||
|
|
||||||
|
def calculate_color(i, j):
|
||||||
|
if angle == None:
|
||||||
|
a = 0
|
||||||
|
else:
|
||||||
|
a = angle
|
||||||
|
|
||||||
|
r1, g1, b1 = rgb_from_str(c1)
|
||||||
|
r2, g2, b2 = rgb_from_str(c2)
|
||||||
|
k = 1.0*(j-x1)/(x2-x1)*(1-a)
|
||||||
|
l = 1.0*(i-y1)/(y2-y1)*a
|
||||||
|
r3, g3, b3 = int(r1 + 1.0*(r2-r1)*(k+l)), int(g1 + 1.0*(g2-g1)*(k+l)), int(b1 + 1.0*(b2-b1)*(k+l))
|
||||||
|
|
||||||
|
return "#%02x%02x%02x" % (r3, g3, b3)
|
||||||
|
|
||||||
|
def calculate_bg(i, j):
|
||||||
|
if angle_bg == None:
|
||||||
|
a = 0
|
||||||
|
else:
|
||||||
|
a = angle
|
||||||
|
|
||||||
|
r1, g1, b1 = rgb_from_str(bg1)
|
||||||
|
r2, g2, b2 = rgb_from_str(bg2)
|
||||||
|
k = 1.0*(j-x1)/(x2-x1)*(1-a)
|
||||||
|
l = 1.0*(i-y1)/(y2-y1)*a
|
||||||
|
r3, g3, b3 = int(r1 + 1.0*(r2-r1)*(k+l)), int(g1 + 1.0*(g2-g1)*(k+l)), int(b1 + 1.0*(b2-b1)*(k+l))
|
||||||
|
|
||||||
|
return "#%02x%02x%02x" % (r3, g3, b3)
|
||||||
|
|
||||||
|
if c2 == None:
|
||||||
|
for i in range(y1,y2):
|
||||||
|
for j in range(x1, x2):
|
||||||
|
self.field[i][j].foreground = c1
|
||||||
|
if bg1:
|
||||||
|
if bg2:
|
||||||
|
self.field[i][j].background = calculate_bg(i, j)
|
||||||
|
else:
|
||||||
|
self.field[i][j].background = bg1
|
||||||
|
else:
|
||||||
|
for i in range(y1,y2):
|
||||||
|
for j in range(x1, x2):
|
||||||
|
self.field[i][j].foreground = calculate_color(i, j)
|
||||||
|
if bg1:
|
||||||
|
if bg2:
|
||||||
|
self.field[i][j].background = calculate_bg(i, j)
|
||||||
|
else:
|
||||||
|
self.field[i][j].background = bg1
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
def put_rectangle(self, x1, y1, x2, y2, char=None, frame=None, color=None, background=None):
|
||||||
|
"""
|
||||||
|
Draw rectangle (x1,y1), (x2,y2) using <char> character, <color> and <background> color
|
||||||
|
"""
|
||||||
|
|
||||||
|
frame_chars = {
|
||||||
|
'ascii': u'++++-|',
|
||||||
|
'single': u'┌┐└┘─│',
|
||||||
|
'double': u'┌┐└┘─│',
|
||||||
|
}
|
||||||
|
if frame in frame_chars:
|
||||||
|
chars = frame_chars[frame]
|
||||||
|
else:
|
||||||
|
chars = char*6
|
||||||
|
|
||||||
|
for x in range(x1, x2):
|
||||||
|
self.put_point(x, y1, char=chars[4], color=color, background=background)
|
||||||
|
self.put_point(x, y2, char=chars[4], color=color, background=background)
|
||||||
|
|
||||||
|
for y in range(y1, y2):
|
||||||
|
self.put_point(x1, y, char=chars[5], color=color, background=background)
|
||||||
|
self.put_point(x2, y, char=chars[5], color=color, background=background)
|
||||||
|
|
||||||
|
self.put_point(x1, y1, char=chars[0], color=color, background=background)
|
||||||
|
self.put_point(x2, y1, char=chars[1], color=color, background=background)
|
||||||
|
self.put_point(x1, y2, char=chars[2], color=color, background=background)
|
||||||
|
self.put_point(x2, y2, char=chars[3], color=color, background=background)
|
||||||
|
|
||||||
|
|
||||||
|
def put_circle(self, x0, y0, radius, char=None, color=None, background=None):
|
||||||
|
"""
|
||||||
|
Draw cricle with center in (x, y) and radius r (x1,y1), (x2,y2)
|
||||||
|
using <char> character, <color> and <background> color
|
||||||
|
"""
|
||||||
|
|
||||||
|
def k(x):
|
||||||
|
return int(x*1.9)
|
||||||
|
|
||||||
|
f = 1 - radius
|
||||||
|
ddf_x = 1
|
||||||
|
ddf_y = -2 * radius
|
||||||
|
x = 0
|
||||||
|
y = radius
|
||||||
|
self.put_point(x0, y0 + radius, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0, y0 - radius, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 + k(radius), y0, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 - k(radius), y0, char=char, color=color, background=background)
|
||||||
|
|
||||||
|
char = "x"
|
||||||
|
while x < y:
|
||||||
|
if f >= 0:
|
||||||
|
y -= 1
|
||||||
|
ddf_y += 2
|
||||||
|
f += ddf_y
|
||||||
|
x += 1
|
||||||
|
ddf_x += 2
|
||||||
|
f += ddf_x
|
||||||
|
self.put_point(x0 + k(x), y0 + y, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 - k(x), y0 + y, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 + k(x), y0 - y, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 - k(x), y0 - y, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 + k(y), y0 + x, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 - k(y), y0 + x, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 + k(y), y0 - x, char=char, color=color, background=background)
|
||||||
|
self.put_point(x0 - k(y), y0 - x, char=char, color=color, background=background)
|
||||||
|
|
||||||
|
def read_ansi(self, seq, x=0, y=0, transparence=True):
|
||||||
|
"""
|
||||||
|
Read ANSI sequence and render it to the panela starting from x and y.
|
||||||
|
If transparence is True, replace spaces with ""
|
||||||
|
"""
|
||||||
|
screen = pyte.screens.Screen(self.size_x, self.size_y+1)
|
||||||
|
|
||||||
|
stream = pyte.streams.ByteStream()
|
||||||
|
stream.attach(screen)
|
||||||
|
|
||||||
|
stream.feed(seq.replace('\n', '\r\n'))
|
||||||
|
|
||||||
|
for i, line in sorted(screen.buffer.items(), key=lambda x: x[0]):
|
||||||
|
for j, char in sorted(line.items(), key=lambda x: x[0]):
|
||||||
|
if j >= self.size_x:
|
||||||
|
break
|
||||||
|
self.field[i][j] = Point(char.data, color_mapping(char.fg), color_mapping(char.bg))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
answer = ""
|
||||||
|
skip_next = False
|
||||||
|
for i, line in enumerate(self.field):
|
||||||
|
for j, c in enumerate(line):
|
||||||
|
fg_ansi = ""
|
||||||
|
bg_ansi = ""
|
||||||
|
stop = ""
|
||||||
|
|
||||||
|
if self.field[i][j].foreground:
|
||||||
|
fg_ansi = '\033[38;2;%s;%s;%sm' % rgb_from_str(self.field[i][j].foreground)
|
||||||
|
stop = colored.attr("reset")
|
||||||
|
|
||||||
|
if self.field[i][j].background:
|
||||||
|
bg_ansi = '\033[48;2;%s;%s;%sm' % rgb_from_str(self.field[i][j].background)
|
||||||
|
stop = colored.attr("reset")
|
||||||
|
|
||||||
|
char = c.char or " "
|
||||||
|
if not skip_next:
|
||||||
|
answer += fg_ansi + bg_ansi + char.encode('utf-8') + stop
|
||||||
|
skip_next = wcswidth(char) == 2
|
||||||
|
|
||||||
|
# answer += "...\n"
|
||||||
|
answer += "\n"
|
||||||
|
return answer
|
||||||
|
|
||||||
|
########################################################################################################
|
||||||
|
|
||||||
|
class Template(object):
|
||||||
|
def __init__(self):
|
||||||
|
self._mode = 'page'
|
||||||
|
self.page = []
|
||||||
|
self.mask = []
|
||||||
|
self.code = []
|
||||||
|
self.panela = None
|
||||||
|
|
||||||
|
self._colors = {
|
||||||
|
'A': '#00cc00',
|
||||||
|
'B': '#00cc00',
|
||||||
|
'C': '#00aacc',
|
||||||
|
'D': '#888888',
|
||||||
|
'E': '#cccc00',
|
||||||
|
'F': '#ff0000',
|
||||||
|
'H': '#22aa22',
|
||||||
|
'I': '#cc0000',
|
||||||
|
'J': '#000000',
|
||||||
|
}
|
||||||
|
|
||||||
|
self._bg_colors = {
|
||||||
|
'G': '#555555',
|
||||||
|
'J': '#555555',
|
||||||
|
}
|
||||||
|
|
||||||
|
def _process_line(self, line):
|
||||||
|
if line == 'mask':
|
||||||
|
self._mode = 'mask'
|
||||||
|
if line == '':
|
||||||
|
self._mode = 'code'
|
||||||
|
|
||||||
|
def read(self, filename):
|
||||||
|
"""
|
||||||
|
Read template from `filename`
|
||||||
|
"""
|
||||||
|
with open(filename) as f:
|
||||||
|
self._mode = 'page'
|
||||||
|
for line in f.readlines():
|
||||||
|
line = line.rstrip('\n')
|
||||||
|
if line.startswith('==[') and line.endswith(']=='):
|
||||||
|
self._process_line(line[3:-3].strip())
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self._mode == 'page':
|
||||||
|
self.page.append(line)
|
||||||
|
elif self._mode == 'mask':
|
||||||
|
self.mask.append(line)
|
||||||
|
elif self._mode == 'code':
|
||||||
|
self.mask.append(line)
|
||||||
|
|
||||||
|
def apply_mask(self):
|
||||||
|
|
||||||
|
lines = self.page
|
||||||
|
x_size = max([len(x) for x in lines])
|
||||||
|
y_size = len(lines)
|
||||||
|
|
||||||
|
self.panela = Panela(x=x_size, y=y_size)
|
||||||
|
self.panela.read_ansi("".join("%s\n" % x for x in self.page))
|
||||||
|
|
||||||
|
for i, line in enumerate(self.mask):
|
||||||
|
for j, char in enumerate(line):
|
||||||
|
if char in self._colors or char in self._bg_colors:
|
||||||
|
color = self._colors.get(char)
|
||||||
|
bg_color = self._bg_colors.get(char)
|
||||||
|
self.panela.put_point(j, i, color=color, background=bg_color)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
|
||||||
|
if self.panela:
|
||||||
|
return str(self.panela)
|
||||||
|
|
||||||
|
return self.page
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"Only for experiments"
|
||||||
|
|
||||||
|
template = Template()
|
||||||
|
template.read("/home/igor/cheat.sh/share/firstpage-v2.pnl")
|
||||||
|
template.apply_mask()
|
||||||
|
sys.stdout.write(template.show())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user