100 lines
2.3 KiB
Python
100 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
import curses
|
|
import curses.textpad
|
|
import locale
|
|
import time
|
|
|
|
locale.setlocale(locale.LC_ALL, '')
|
|
|
|
logs = []
|
|
|
|
|
|
def main(stdscr):
|
|
curses.curs_set(1)
|
|
stdscr.nodelay(False)
|
|
stdscr.keypad(True)
|
|
|
|
prompt = "> "
|
|
|
|
def resize_windows():
|
|
nonlocal main_win, input_win, maxy, maxx, input_box
|
|
stdscr.clear()
|
|
maxy, maxx = stdscr.getmaxyx()
|
|
|
|
main_win = stdscr.derwin(maxy - 1, maxx, 0, 0)
|
|
main_win.keypad(True)
|
|
main_win.nodelay(True)
|
|
main_win.scrollok(True)
|
|
|
|
input_win = stdscr.derwin(1, maxx, maxy - 1, 0)
|
|
input_win.keypad(True)
|
|
|
|
input_box = input_win.derwin(1, maxx - len(prompt), 0, len(prompt))
|
|
draw_screen()
|
|
|
|
def draw_screen():
|
|
if main_win is None or input_win is None:
|
|
return
|
|
|
|
main_win.erase()
|
|
|
|
height, width = main_win.getmaxyx()
|
|
start = max(0, len(logs) - height)
|
|
visible = logs[start:]
|
|
for i, line in enumerate(visible):
|
|
main_win.addnstr(i, 0, line, width - 1)
|
|
main_win.noutrefresh()
|
|
|
|
input_win.erase()
|
|
input_win.addstr(0, 0, prompt)
|
|
|
|
if maxy > 1:
|
|
stdscr.hline(maxy - 2, 0, curses.ACS_HLINE, maxx)
|
|
input_win.noutrefresh()
|
|
curses.doupdate()
|
|
|
|
maxy = maxx = 0
|
|
main_win = input_win = input_box = None
|
|
resize_windows()
|
|
if input_box is None:
|
|
return
|
|
|
|
textbox = curses.textpad.Textbox(input_box, insert_mode=True)
|
|
|
|
while True:
|
|
draw_screen()
|
|
|
|
def validator(ch):
|
|
nonlocal logs
|
|
if ch in (curses.KEY_RESIZE,):
|
|
|
|
resize_windows()
|
|
return 0
|
|
if ch in (10, 13):
|
|
return 7
|
|
return ch
|
|
|
|
input_box.erase()
|
|
input_box.refresh()
|
|
curses.curs_set(1)
|
|
s = textbox.edit(validator).strip()
|
|
curses.curs_set(0)
|
|
|
|
if s:
|
|
|
|
if s.strip().lower() in ("/quit", "/q", "quit"):
|
|
break
|
|
|
|
timestamp = time.strftime("%H:%M:%S")
|
|
logs.append(f"[{timestamp}] {s}")
|
|
else:
|
|
|
|
pass
|
|
|
|
if curses.is_term_resized(maxy, maxx):
|
|
curses.resizeterm(*stdscr.getmaxyx())
|
|
resize_windows()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
curses.wrapper(main)
|