diff --git a/src/get_todo.py b/src/get_todo.py index ad6da87..8a614e6 100644 --- a/src/get_todo.py +++ b/src/get_todo.py @@ -7,6 +7,7 @@ from src.class_todo import Todo from src.get_args import INDENT, TKINTER_GUI from src.keys import Key +from src.utils import set_header if TKINTER_GUI: from tcurses import curses @@ -14,12 +15,6 @@ import curses -def set_header(stdscr: Any, message: str) -> None: - stdscr.addstr( - 0, 0, message.ljust(stdscr.getmaxyx()[1]), curses.A_BOLD | curses.color_pair(2) - ) - - def hline(win: Any, y_loc: int, x_loc: int, char: str | int, width: int) -> None: win.addch(y_loc, x_loc, curses.ACS_LTEE) win.hline(y_loc, x_loc + 1, char, width - 2) diff --git a/src/menus.py b/src/menus.py new file mode 100644 index 0000000..f377f80 --- /dev/null +++ b/src/menus.py @@ -0,0 +1,110 @@ +""" +Various helpful menus and their helper functions. +""" + +# pylint: disable=missing-function-docstring + +from typing import Any + +try: + from pyfiglet import figlet_format as big + + FIGLET_FORMAT_EXISTS = True +except ImportError: + FIGLET_FORMAT_EXISTS = False + +from src.class_cursor import Cursor +from src.class_todo import Todo +from src.get_args import ( + CONTROLS_BEGIN_INDEX, + CONTROLS_END_INDEX, + HELP_FILE, + TKINTER_GUI, +) +from src.get_todo import hline +from src.keys import Key +from src.md_to_py import md_table_to_lines +from src.print_todos import make_printable_sublist +from src.utils import clamp, set_header + +if TKINTER_GUI: + from tcurses import curses +else: + import curses + + +def simple_scroll_keybinds( + win: Any, cursor: int, len_lines: int, len_new_lines: int +) -> int: + try: + key = win.getch() + except Key.ctrl_c: + return -1 + if key in (Key.up, Key.k): + cursor = clamp(cursor - 1, 0, len_lines - 2) + elif key in (Key.down, Key.j, Key.enter): + cursor = clamp(cursor + 1, 0, len_lines - len_new_lines - 1) + else: + return -1 + return cursor + + +def help_menu(parent_win: Any) -> None: + parent_win.clear() + set_header(parent_win, "Help (k/j to scroll):") + lines = [] + for line in md_table_to_lines( + CONTROLS_BEGIN_INDEX, + CONTROLS_END_INDEX, + str(HELP_FILE), + ("", "", "(arranged alphabetically)"), + ): + lines.append(line[:-2]) + win = curses.newwin( + min(parent_win.getmaxyx()[0] - 1, len(lines) + 2), + len(lines[0]) + 2, + 1, + (parent_win.getmaxyx()[1] - (len(lines[0]) + 1)) // 2, + ) + win.box() + parent_win.refresh() + cursor = 0 + win.addstr(1, 1, lines[0]) + hline(win, 2, 0, curses.ACS_HLINE, win.getmaxyx()[1]) + while True: + new_lines, _, _ = make_printable_sublist( + win.getmaxyx()[0] - 4, lines[2:], cursor, 0 + ) + for i, line in enumerate(new_lines): + win.addstr(i + 3, 1, line) + win.refresh() + cursor = simple_scroll_keybinds(win, cursor, len(lines), len(new_lines)) + if cursor < 0: + break + parent_win.clear() + + +def magnify(stdscr: Any, todos: list[Todo], selected: Cursor) -> None: + if not FIGLET_FORMAT_EXISTS: + set_header(stdscr, "Magnify dependency not available") + return + stdscr.clear() + set_header(stdscr, "Magnifying...") + lines = big( # pyright: ignore + todos[int(selected)].display_text, width=stdscr.getmaxyx()[1] + ).split("\n") + lines.append("") + lines = [line.ljust(stdscr.getmaxyx()[1] - 2) for line in lines] + cursor = 0 + while True: + new_lines, _, _ = make_printable_sublist( + stdscr.getmaxyx()[0] - 2, lines, cursor, 0 + ) + for i, line in enumerate(new_lines): + stdscr.addstr(i + 1, 1, line) + stdscr.refresh() + cursor = simple_scroll_keybinds(stdscr, cursor, len(lines), len(new_lines)) + if cursor < 0: + break + stdscr.refresh() + stdscr.clear() diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..4e3c9ac --- /dev/null +++ b/src/utils.py @@ -0,0 +1,28 @@ +""" +General utilities, useful across multiple other files +""" + +from typing import Any + +from src.get_args import TKINTER_GUI + +if TKINTER_GUI: + from tcurses import curses +else: + import curses + + +def clamp(number: int, minimum: int, maximum: int) -> int: + """ + Clamp a number in between a minimum and maximum. + """ + return min(max(number, minimum), maximum - 1) + + +def set_header(stdscr: Any, message: str) -> None: + """ + Set the header to a specific message. + """ + stdscr.addstr( + 0, 0, message.ljust(stdscr.getmaxyx()[1]), curses.A_BOLD | curses.color_pair(2) + ) diff --git a/todo.py b/todo.py index 9b947c2..7dc5a04 100755 --- a/todo.py +++ b/todo.py @@ -1,20 +1,12 @@ #!/usr/bin/env python3 # pyright: reportMissingModuleSource=false -# pylint: disable=no-name-in-module, import-error, missing-class-docstring -# pylint: disable=missing-function-docstring, missing-module-docstring +# pylint: disable=no-name-in-module, import-error, missing-docstring from os import stat from pathlib import Path from sys import exit as sys_exit from typing import Any, Callable -try: - from pyfiglet import figlet_format as big - - FIGLET_FORMAT_EXISTS = True -except ImportError: - FIGLET_FORMAT_EXISTS = False - try: from pyperclip import copy, paste @@ -27,18 +19,16 @@ from src.class_mode import SingleLineMode, SingleLineModeImpl from src.class_todo import Todo from src.get_args import ( - CONTROLS_BEGIN_INDEX, - CONTROLS_END_INDEX, FILENAME, HEADER, - HELP_FILE, NO_GUI, TKINTER_GUI, ) -from src.get_todo import hline, set_header, wgetnstr -from src.md_to_py import md_table_to_lines -from src.print_todos import make_printable_sublist, print_todos +from src.get_todo import set_header, wgetnstr from src.keys import Key +from src.menus import help_menu, magnify +from src.print_todos import print_todos +from src.utils import clamp if TKINTER_GUI: from tcurses import curses @@ -77,10 +67,6 @@ def get_file_modified_time(filename: Path) -> float: return stat(filename).st_ctime -def clamp(counter: int, minimum: int, maximum: int) -> int: - return min(max(counter, minimum), maximum - 1) - - def overflow(counter: int, minimum: int, maximum: int) -> int: if counter >= maximum: return minimum + (counter - maximum) @@ -156,83 +142,6 @@ def move_todos(todos: list[Todo], selected: int, destination: int) -> list[Todo] return todos -def simple_scroll_keybinds( - win: Any, cursor: int, len_lines: int, len_new_lines: int -) -> int: - try: - key = win.getch() - except Key.ctrl_c: - return -1 - if key in (Key.up, Key.k): - cursor = clamp(cursor - 1, 0, len_lines - 2) - elif key in (Key.down, Key.j, Key.enter): - cursor = clamp(cursor + 1, 0, len_lines - len_new_lines - 1) - else: - return -1 - return cursor - - -def help_menu(parent_win: Any) -> None: - parent_win.clear() - set_header(parent_win, "Help (k/j to scroll):") - lines = [] - for line in md_table_to_lines( - CONTROLS_BEGIN_INDEX, - CONTROLS_END_INDEX, - str(HELP_FILE), - ("", "", "(arranged alphabetically)"), - ): - lines.append(line[:-2]) - win = curses.newwin( - min(parent_win.getmaxyx()[0] - 1, len(lines) + 2), - len(lines[0]) + 2, - 1, - (parent_win.getmaxyx()[1] - (len(lines[0]) + 1)) // 2, - ) - win.box() - parent_win.refresh() - cursor = 0 - win.addstr(1, 1, lines[0]) - hline(win, 2, 0, curses.ACS_HLINE, win.getmaxyx()[1]) - while True: - new_lines, _, _ = make_printable_sublist( - win.getmaxyx()[0] - 4, lines[2:], cursor, 0 - ) - for i, line in enumerate(new_lines): - win.addstr(i + 3, 1, line) - win.refresh() - cursor = simple_scroll_keybinds(win, cursor, len(lines), len(new_lines)) - if cursor < 0: - break - parent_win.clear() - - -def magnify(stdscr: Any, todos: list[Todo], selected: Cursor) -> None: - if not FIGLET_FORMAT_EXISTS: - set_header(stdscr, "Magnify dependency not available") - return - stdscr.clear() - set_header(stdscr, "Magnifying...") - lines = big( # pyright: ignore - todos[int(selected)].display_text, width=stdscr.getmaxyx()[1] - ).split("\n") - lines.append("") - lines = [line.ljust(stdscr.getmaxyx()[1] - 2) for line in lines] - cursor = 0 - while True: - new_lines, _, _ = make_printable_sublist( - stdscr.getmaxyx()[0] - 2, lines, cursor, 0 - ) - for i, line in enumerate(new_lines): - stdscr.addstr(i + 1, 1, line) - stdscr.refresh() - cursor = simple_scroll_keybinds(stdscr, cursor, len(lines), len(new_lines)) - if cursor < 0: - break - stdscr.refresh() - stdscr.clear() - - def get_color(color: str) -> int: return COLORS[color]