# Path: esc/consts.py
# STACKDEPTH = 12
# 
# STACKWIDTH = 21  # needs room for sci notation and labels on top of precision
# 
# PROGRAM_NAME = f"esc {VERSION}"
# 
# QUIT_CHARACTER = 'q'
# 
# UNDO_CHARACTER = 'u'
# 
# REDO_CHARACTER = '^R'
# 
# RETRIEVE_REG_CHARACTER = '<'
# 
# STORE_REG_CHARACTER = '>'
# 
# DELETE_REG_CHARACTER = 'X'
# 
# Path: esc/status.py
# class StatusState:
#     class Modality(Enum):
#     class SuccessCode(Enum):
#         READY = (' ', "Ready (<F1> for help)")
#         ENTERING_NUMBER = ('i', "Insert")
#         IN_MENU = ('m', "Expecting menu selection")
#         EXPECTING_REGISTER = ('r', "Expecting register identifier (any letter)")
#         EXPECTING_HELP = ('h', "Browsing help (select a command or menu)")
#         OK = auto()  # pylint: disable=invalid-name
#         ADVISORY = auto()
#         ERROR = auto()
#         def __init__(self, status_char, status_message):
#     def __init__(self):
#     def __repr__(self):
#     def status_char(self):
#     def status_message(self):
#     def _clear_errors(self):
#     def ready(self):
#     def entering_number(self):
#     def in_menu(self):
#     def expecting_register(self):
#     def expecting_help(self):
#     def advisory(self, msg):
#     def error(self, msg):
#     def mark_seen(self):
#     def push_state(self):
#     def pop_state(self):
#     def save_state(self):
# 
# Path: esc/util.py
# def truncate(string: str, max_length: int) -> str:
#     """
#     Truncate /string/ to at most /max_length/ using an ellipsis.
#     max_length must be at least 3.
# 
#     >>> truncate("The quick brown fox jumps over the lazy dog.", 10)
#     'The qui...'
# 
#     >>> truncate("I fit already.", 20)
#     'I fit already.'
# 
#     >>> truncate("The quick brown fox jumps over the lazy dog.", 2)
#     Traceback (most recent call last):
#       ...
#     AssertionError: max_length must be at least 3...
#     """
#     assert max_length > 3, \
#         "max_length must be at least 3, as an ellipsis is 3 characters itself"
#     if len(string) > max_length:
#         string = string[:max_length - 3] + '...'
#     return string
# 
# def quit_if_screen_too_small(max_y, max_x):
#     """
#     If the terminal is too small, quit, providing a useful error message.
#     """
#     if max_y < REQUIRED_TERM_HEIGHT or max_x < REQUIRED_TERM_WIDTH:
#         curses.endwin()
#         sys.stderr.write(f"esc requires at least a "
#                          f"{REQUIRED_TERM_WIDTH}x{REQUIRED_TERM_HEIGHT} terminal "
#                          f"(this terminal is {max_x}x{max_y}).\n")
#         sys.exit(1)
# 
# def centered_position(text: str, width: int) -> int:
#     """
#     Return the integer column to start writing a string /text/ at to
#     center it within a window of width /width/.
# 
#     If width is less than 1 or the text is too long for the provided width,
#     AssertionError is raised.
# 
#     >>> centered_position("Soren", 11)
#     4
# 
#     >>> centered_position("Maud", 10)
#     4
# 
#     >>> centered_position("Soren", 10)
#     3
# 
#     >>> centered_position("Using it all", 12)
#     0
# 
#     >>> centered_position("Using it all.", 13)
#     0
# 
#     >>> centered_position("overwraps", 2)
#     Traceback (most recent call last):
#       ..
#     AssertionError: text 'overwraps' can't fit in 2 columns
# 
#     >>> centered_position("Soren", -8)
#     Traceback (most recent call last):
#       ..
#     AssertionError: width must be a positive number of columns
#     """
#     assert width > 0, "width must be a positive number of columns"
#     assert len(text) <= width, f"text '{text}' can't fit in {width} columns"
#     if len(text) == width:  # if not special-cased, may say to write in column 1
#         return 0
#     return (width - len(text)) // 2 + 1


import curses
import itertools
import textwrap
from typing import Sequence
from .consts import (STACKDEPTH, STACKWIDTH, PROGRAM_NAME,
                     QUIT_CHARACTER, UNDO_CHARACTER, REDO_CHARACTER,
                     RETRIEVE_REG_CHARACTER, STORE_REG_CHARACTER, DELETE_REG_CHARACTER)
from .status import status
from .util import truncate, quit_if_screen_too_small, centered_position

    def set_cursor_posn(self):
        """
        Place the cursor after the current character or on the next available
        line, as appropriate.
        """
        if self.ss.editing_last_item:
            self.window.move(1 + self.ss.stack_posn, self.ss.cursor_posn + 1)
        else:
            # when not editing a number, cursor goes on *next line*
            self.window.move(2 + self.ss.stack_posn, self.ss.cursor_posn + 1)

    def backspace(self, bs_status):
        """
        Update the screen to show that a character was backspaced off the
        stack line being edited.
        """
        if bs_status == 0:  # character backspaced
            self.window.addstr(1 + self.ss.stack_posn, self.ss.cursor_posn + 1, ' ')
            self.window.move(1 + self.ss.stack_posn, self.ss.cursor_posn + 1)
        elif bs_status == 1:  # stack item wiped out
            self.window.addstr(2 + self.ss.stack_posn, self.ss.cursor_posn + 1, ' ')
            self.window.move(2 + self.ss.stack_posn, self.ss.cursor_posn + 1)
        else:  # nothing to backspace
            pass


class HistoryWindow(Window):
    "Window displaying a history of past actions."
    width = 32

# Path: esc/consts.py
# STACKDEPTH = 12
# 
# STACKWIDTH = 21  # needs room for sci notation and labels on top of precision
# 
# PROGRAM_NAME = f"esc {VERSION}"
# 
# QUIT_CHARACTER = 'q'
# 
# UNDO_CHARACTER = 'u'
# 
# REDO_CHARACTER = '^R'
# 
# RETRIEVE_REG_CHARACTER = '<'
# 
# STORE_REG_CHARACTER = '>'
# 
# DELETE_REG_CHARACTER = 'X'
# 
# Path: esc/status.py
# class StatusState:
#     class Modality(Enum):
#     class SuccessCode(Enum):
#         READY = (' ', "Ready (<F1> for help)")
#         ENTERING_NUMBER = ('i', "Insert")
#         IN_MENU = ('m', "Expecting menu selection")
#         EXPECTING_REGISTER = ('r', "Expecting register identifier (any letter)")
#         EXPECTING_HELP = ('h', "Browsing help (select a command or menu)")
#         OK = auto()  # pylint: disable=invalid-name
#         ADVISORY = auto()
#         ERROR = auto()
#         def __init__(self, status_char, status_message):
#     def __init__(self):
#     def __repr__(self):
#     def status_char(self):
#     def status_message(self):
#     def _clear_errors(self):
#     def ready(self):
#     def entering_number(self):
#     def in_menu(self):
#     def expecting_register(self):
#     def expecting_help(self):
#     def advisory(self, msg):
#     def error(self, msg):
#     def mark_seen(self):
#     def push_state(self):
#     def pop_state(self):
#     def save_state(self):
# 
# Path: esc/util.py
# def truncate(string: str, max_length: int) -> str:
#     """
#     Truncate /string/ to at most /max_length/ using an ellipsis.
#     max_length must be at least 3.
# 
#     >>> truncate("The quick brown fox jumps over the lazy dog.", 10)
#     'The qui...'
# 
#     >>> truncate("I fit already.", 20)
#     'I fit already.'
# 
#     >>> truncate("The quick brown fox jumps over the lazy dog.", 2)
#     Traceback (most recent call last):
#       ...
#     AssertionError: max_length must be at least 3...
#     """
#     assert max_length > 3, \
#         "max_length must be at least 3, as an ellipsis is 3 characters itself"
#     if len(string) > max_length:
#         string = string[:max_length - 3] + '...'
#     return string
# 
# def quit_if_screen_too_small(max_y, max_x):
#     """
#     If the terminal is too small, quit, providing a useful error message.
#     """
#     if max_y < REQUIRED_TERM_HEIGHT or max_x < REQUIRED_TERM_WIDTH:
#         curses.endwin()
#         sys.stderr.write(f"esc requires at least a "
#                          f"{REQUIRED_TERM_WIDTH}x{REQUIRED_TERM_HEIGHT} terminal "
#                          f"(this terminal is {max_x}x{max_y}).\n")
#         sys.exit(1)
# 
# def centered_position(text: str, width: int) -> int:
#     """
#     Return the integer column to start writing a string /text/ at to
#     center it within a window of width /width/.
# 
#     If width is less than 1 or the text is too long for the provided width,
#     AssertionError is raised.
# 
#     >>> centered_position("Soren", 11)
#     4
# 
#     >>> centered_position("Maud", 10)
#     4
# 
#     >>> centered_position("Soren", 10)
#     3
# 
#     >>> centered_position("Using it all", 12)
#     0
# 
#     >>> centered_position("Using it all.", 13)
#     0
# 
#     >>> centered_position("overwraps", 2)
#     Traceback (most recent call last):
#       ..
#     AssertionError: text 'overwraps' can't fit in 2 columns
# 
#     >>> centered_position("Soren", -8)
#     Traceback (most recent call last):
#       ..
#     AssertionError: width must be a positive number of columns
#     """
#     assert width > 0, "width must be a positive number of columns"
#     assert len(text) <= width, f"text '{text}' can't fit in {width} columns"
#     if len(text) == width:  # if not special-cased, may say to write in column 1
#         return 0
#     return (width - len(text)) // 2 + 1


# Path: esc/display.py
import curses
import itertools
import textwrap
from typing import Sequence
from .consts import (STACKDEPTH, STACKWIDTH, PROGRAM_NAME,
                     QUIT_CHARACTER, UNDO_CHARACTER, REDO_CHARACTER,
                     RETRIEVE_REG_CHARACTER, STORE_REG_CHARACTER, DELETE_REG_CHARACTER)
from .status import status
from .util import truncate, quit_if_screen_too_small, centered_position


    def set_cursor_posn(self):
        """
        Place the cursor after the current character or on the next available
        line, as appropriate.
        """
        if self.ss.editing_last_item:
            self.window.move(1 + self.ss.stack_posn, self.ss.cursor_posn + 1)
        else:
            # when not editing a number, cursor goes on *next line*
            self.window.move(2 + self.ss.stack_posn, self.ss.cursor_posn + 1)

    def backspace(self, bs_status):
        """
        Update the screen to show that a character was backspaced off the
        stack line being edited.
        """
        if bs_status == 0:  # character backspaced
            self.window.addstr(1 + self.ss.stack_posn, self.ss.cursor_posn + 1, ' ')
            self.window.move(1 + self.ss.stack_posn, self.ss.cursor_posn + 1)
        elif bs_status == 1:  # stack item wiped out
            self.window.addstr(2 + self.ss.stack_posn, self.ss.cursor_posn + 1, ' ')
            self.window.move(2 + self.ss.stack_posn, self.ss.cursor_posn + 1)
        else:  # nothing to backspace
            pass


class HistoryWindow(Window):
    "Window displaying a history of past actions."
    width = 32

    height = 3 + STACKDEPTH