from os import get_terminal_size, O_NONBLOCK from sys import stdin from termios import tcgetattr, tcsetattr, TCSADRAIN 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() old_fl = fcntl(fd, F_GETFL) old_tc = tcgetattr(fd) setcbreak(fd) fcntl(fd, F_SETFL, old_fl | O_NONBLOCK) f(*args) except KeyboardInterrupt: cprint('2J') move(0, 0) pass finally: fcntl(fd, F_SETFL, old_fl) tcsetattr(fd, TCSADRAIN, old_tc) def rprint(*text: str): print(*text, end='', flush=True) def cprint(*code: str): rprint(*['\033[' + c for c in code]) 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 for l in lines: _ = 0 if ln == cur_line: # if this line is the focused line y = my while _ == 0 or l != '': cl = l[:ncols] print(cl) _ += 1 l = l[ncols:] my += _ ln += 1 x = line_pos % ncols if line_pos / ncols >= 1: y += line_pos // ncols move(y, x) return (y, x) 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) 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 y, x = refresh(line_pos, cur_line, lines, terminal_size.columns) key = stdin.read(1) if key == '': continue elif key == KEY_ESCAPE: next = stdin.read(1) 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) elif key == KEY_BACKSPACE: """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) elif key == KEY_ENTER: y, x = nl(y, x) cur_line += 1 line_pos = 0 if len(lines) == cur_line: lines.append('') elif 31 < ord(key) < 127: # keystroke line_pos += 1 x += 1 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 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()