secretproject/writer/__main__.py

308 lines
8.3 KiB
Python
Raw Normal View History

2024-06-30 18:08:02 +02:00
from os import get_terminal_size, O_NONBLOCK
from sys import stdin
2024-07-01 15:25:23 +02:00
from termios import tcgetattr, tcsetattr, TCSADRAIN
2024-06-30 18:08:02 +02:00
from tty import setcbreak
from fcntl import fcntl, F_GETFL, F_SETFL
from keys import *
def wrapper(f: callable, *args: any):
try:
fd = stdin.fileno()
2024-07-01 15:25:23 +02:00
old_fl = fcntl(fd, F_GETFL)
old_tc = tcgetattr(fd)
2024-06-30 18:08:02 +02:00
setcbreak(fd)
2024-07-01 15:25:23 +02:00
fcntl(fd, F_SETFL, old_fl | O_NONBLOCK)
2024-06-30 18:08:02 +02:00
f(*args)
2024-07-01 15:25:23 +02:00
except KeyboardInterrupt:
cprint('2J')
move(0, 0)
pass
2024-06-30 18:08:02 +02:00
finally:
2024-07-01 15:25:23 +02:00
fcntl(fd, F_SETFL, old_fl)
tcsetattr(fd, TCSADRAIN, old_tc)
2024-06-30 18:08:02 +02:00
def rprint(*text: str):
print(*text, end='', flush=True)
def cprint(*code: str):
rprint(*['\033[' + c for c in code])
2024-07-01 15:25:23 +02:00
def move(y: int, x: int):
cprint(f'{y+1};{x+1}H')
def refresh(line_pos: int, cur_line: int, lines: list[str], ncols: int) -> tuple[int, int]:
cprint('2J') # clear screen
move(0, 0)
my = 0 # max y
cl = '' # current screen line
ln = 0 # line number
y = 0 # output pos
x = 0
2024-06-30 18:08:02 +02:00
for l in lines:
_ = 0
2024-07-01 15:25:23 +02:00
if ln == cur_line: # if this line is the focused line
y = my
2024-06-30 18:08:02 +02:00
while _ == 0 or l != '':
cl = l[:ncols]
print(cl)
_ += 1
l = l[ncols:]
2024-07-01 15:25:23 +02:00
my += _
ln += 1
2024-06-30 18:08:02 +02:00
2024-07-01 15:25:23 +02:00
x = line_pos % ncols
if line_pos / ncols >= 1:
y += line_pos // ncols
move(y, x)
2024-06-30 18:08:02 +02:00
return (y, x)
2024-07-01 15:25:23 +02:00
def insert_str(text: str, to_insert: str, index: int) -> str:
return text[:index] + to_insert + text[index:]
def remove_str(text: str, index: int) -> str:
return text[:index] + text[index + 1:]
def nl(y: int, x: int) -> tuple[int]:
cprint('E')
return (y + 1, 0)
def move_back(y: int, x: int, line_pos: int, cur_line: int, lines: list[str], ncols: int) -> tuple[int]:
if x != 0:
line_pos -= 1
x -= 1
elif y != 0:
if line_pos == 0:
cur_line -= 1
line_pos = len(lines[cur_line])
x = line_pos % ncols
y -= 1
else:
rprint(KEY_BELL)
return (y, x, line_pos, cur_line)
def move_forward(y: int, x: int, line_pos: int, cur_line: int, lines: list[str], ncols: int) -> tuple[int]:
lines_count = len(lines) - 1
line_len = len(lines[cur_line])
if line_pos == line_len: # if the cursor is on the last char of line
if cur_line == lines_count: # if the line is the last line
rprint(KEY_BELL)
else: # if not then switch to next line
x = 0
y += 1
line_pos = 0
cur_line += 1
else:
line_pos += 1
if x - 1 == ncols: # if cursor is at the right edge of screen
x = 0
y += 1
return (y, x, line_pos, cur_line)
2024-06-30 18:08:02 +02:00
def main():
terminal_size = None
y = 0
x = 0
lines = ['']
cur_line = 0
line_pos = 0
while True:
new_terminal_size = get_terminal_size()
if new_terminal_size != terminal_size:
terminal_size = new_terminal_size
2024-07-01 15:25:23 +02:00
y, x = refresh(line_pos, cur_line, lines, terminal_size.columns)
2024-06-30 18:08:02 +02:00
key = stdin.read(1)
2024-07-01 15:25:23 +02:00
2024-06-30 18:08:02 +02:00
if key == '':
continue
elif key == KEY_ESCAPE:
next = stdin.read(1)
2024-07-01 15:25:23 +02:00
if next == '[':
next = stdin.read(1)
if next == 'A':
cprint('A')
elif next == 'B':
cprint('B')
elif next == 'C':
y, x, line_pos, cur_line = move_forward(y, x, line_pos, cur_line, lines, terminal_size.columns)
move(y, x)
elif next == 'D':
y, x, line_pos, cur_line = move_back(y, x, line_pos, cur_line, lines, terminal_size.columns)
move(y, x)
2024-06-30 18:08:02 +02:00
elif key == KEY_BACKSPACE:
2024-07-01 15:25:23 +02:00
"""if x != 0:
line_pos -= 1
x -= 1
else:
if y == 0:
rprint(KEY_BELL)
continue
if line_pos == 0:
cur_line -= 1
line_pos = len(lines[cur_line])
x = line_pos % terminal_size.columns
y -= 1"""
y, x, line_pos, cur_line = move_back(y, x, line_pos, cur_line, lines, terminal_size.columns)
move(y, x)
rprint(' ')
move(y, x)
lines[cur_line] = remove_str(lines[cur_line], line_pos)
2024-06-30 18:08:02 +02:00
elif key == KEY_ENTER:
2024-07-01 15:25:23 +02:00
y, x = nl(y, x)
2024-06-30 18:08:02 +02:00
cur_line += 1
2024-07-01 15:25:23 +02:00
line_pos = 0
if len(lines) == cur_line:
2024-06-30 18:08:02 +02:00
lines.append('')
2024-07-01 15:25:23 +02:00
elif 31 < ord(key) < 127: # keystroke
line_pos += 1
2024-06-30 18:08:02 +02:00
x += 1
2024-07-01 15:25:23 +02:00
if x - 1 == terminal_size.columns:
y, x = nl(y, x)
rprint(key)
lines[cur_line] = insert_str(lines[cur_line], key, line_pos)
y, x = refresh(line_pos, cur_line, lines, terminal_size.columns) # TODO make this not needed
2024-06-30 18:08:02 +02:00
if __name__ == "__main__":
wrapper(main)
exit()
def main(screen: curses.window):
curses.use_default_colors()
for i in range(0, curses.COLORS):
curses.init_pair(i + 1, i, -1)
nlines = 0
ncols = 0
y = 0
x = 0
content = ""
lines = ['']
cur_line = 0
color = curses.color_pair()
while True:
nnlines, nncols = screen.getmaxyx()
if nnlines != nlines or nncols != ncols:
print('resized')
nlines, ncols = nnlines, nncols
screen.erase()
curses.resizeterm(nlines, ncols)
i = 0
for l in lines:
if l == '':
i += 1
continue
while l != '':
try:
screen.addstr(i, 0, l[:ncols])
except curses.error:
continue # TODO don't loop
l = l[ncols:]
i += 1
screen.refresh()
key = screen.getch()
y, x = screen.getyx()
#print(key, chr(key), 31 < key < 256, end='', flush=True)
if 31 < key < 256:
if key == 38: # ;
if color is None:
screen.addch(sy, sx, ' ')
screen.move(sy, sx)
else:
sy, sx = y, x
screen.addch('?', curses.color_pair(2))
screen.move(sy, sx)
continue
elif color == None:
screen.addch(sy, sx, ' ')
screen.move(sy, sx)
if 48 < key < 57:
# print(key - 49)
color = curses.color_pair(key - 49)
else:
color = -1
continue
ch = chr(key)
screen.addch(ch, color)
lines[cur_line] += ch
elif key == curses.KEY_ENTER or key == 10:
cur_line += 1
if cur_line+1 >= len(lines):
lines.append('')
screen.move(y+1, 0)
elif key == curses.KEY_BACKSPACE:
lines[cur_line] = lines[cur_line][:-1]
x -= 1
if x == -1:
if y == 0:
continue
y -= 1
if len(lines[cur_line]) == 0:
x = len(lines[y])
cur_line -= 1
else:
x = ncols
screen.addch(y, x, ' ')
screen.move(y, x)
elif key == curses.KEY_HOME:
screen.move(y, 0)
elif key == curses.KEY_END:
x = len(lines[y])
screen.move(y, x)
if __name__ == "__main__":
curses.wrapper(main)
exit()
print("loading shart...")
shard = Shard.load_shard('myfile')
print("Size:", shard.size)
print("now creating entry")
entry = Entry(shard)
entry.add_content("Lorm Ipsum dolor sit ammet, consectetuer adipiscng elit, We're no strangers to luv You know the rules and so do I A full commitment's wat I'm thinkin of You wouldn't get this from any other guy very good very nice".encode())
print("entry created, its length:", len(entry.to_bytes()), "now writing it")
try:
shard.write_entry(entry)
print("entry written")
except EOFError:
print("oops, looks like the file wont fit this")
shard.close()