import curses import os import textwrap def read_file(filename): with open(filename, 'r', encoding='utf-8') as f: return f.read() def main(stdscr): curses.curs_set(0) # Hide cursor stdscr.keypad(1) # Enable special keys stdscr.timeout(100) # Set timeout for getch current_chapter = 0 offset = 0 # To keep track of scrolling update_needed = True # Flag to check whether an update is needed while True: # Only clear and refresh the screen if an update is needed if update_needed: stdscr.clear() # Read the file if current_chapter == 0: text = read_file('chapters/title.txt') else: text = read_file(f'chapters/chapter{current_chapter}.txt') # Split text by lines, then wrap each line max_y, max_x = stdscr.getmaxyx() lines = text.split('\n') wrapped_lines = [textwrap.fill(line, width=max_x) for line in lines] final_text = '\n'.join(wrapped_lines) final_lines = final_text.split('\n') # Display text for i, line in enumerate(final_lines[offset:]): if i >= max_y - 1: break stdscr.addstr(i, 0, line) stdscr.refresh() update_needed = False # Reset the flag after updating # Get user input c = stdscr.getch() # Scroll up/down if c == curses.KEY_UP and offset > 0: offset -= 1 update_needed = True elif c == curses.KEY_DOWN and offset < len(final_lines) - max_y: offset += 1 update_needed = True # Skip a whole screen up/down elif c == curses.KEY_SR and offset > 0: # Ctrl+Up offset = max(0, offset - max_y) update_needed = True elif c == curses.KEY_SF and offset < len(final_lines) - max_y: # Ctrl+Down offset = min(len(final_lines) - max_y, offset + max_y) update_needed = True # Change chapters elif c == curses.KEY_RIGHT: current_chapter += 1 if not os.path.exists(f'chapters/chapter{current_chapter}.txt'): current_chapter -= 1 offset = 0 update_needed = True elif c == curses.KEY_LEFT and current_chapter > 0: current_chapter -= 1 offset = 0 update_needed = True # Quit elif c == ord('q'): break # No need to set update_needed since we are exiting curses.wrapper(main)