Exemple #1
0
    def on_wnd(self, wnd: _curses.window, theme, y, x, scroll, template,
               **kwargs):
        """
        Render template on the window.

        TODO: Styles are a bit hacky.

        Args:
          y, x: Template start position
          scroll: skip this number of initial template lines (for scrolling)
          template: path to the template
          kwargs: template arguments.
        Returns:
          False: We hit the line limit during render (output cut)
          True: everything filled.
        """
        splitter = re.compile('(<theme=[_a-zA-Z0-9]+>|</theme>)')
        theme_parser = re.compile('^<theme=([_a-zA-Z0-9]+)>$')

        lines, cols = wnd.getmaxyx()
        self.max_cols = cols  # For wrap filter
        try:
            string = self.render_string(template, **kwargs)
        except jinja2.exceptions.TemplateError:
            log.exception(f"Template rendering {template} failed.")
            wnd.addstr(y, x, "*TEMPLATE RENDERING FAILED*")
            return True

        style = 0
        for line in string.split("\n"):
            line = line.rstrip()
            chunks = re.split(splitter, line)
            col = x
            for chunk in chunks:
                match = re.match(theme_parser, chunk)
                if match:
                    style_name = match.groups()[0]
                    style = getattr(theme, style_name)
                    continue
                if chunk == "</theme>":
                    style = 0
                    continue
                chunk = jinja2.Markup(chunk).unescape()
                try:
                    if scroll == 0:
                        wnd.addnstr(y, col, chunk, cols - col, style)
                    col += len(chunk)
                except _curses.error:
                    # Overflow is ok at the LAST character in LAST line.
                    # FIXME: Which makes it difficult to decide if we fit
                    return False

            if scroll > 0:
                scroll -= 1
            else:
                y += 1
            if y == lines:
                return False
        return True
Exemple #2
0
 def redraw(self, wnd: _curses.window):
     "Refresh the view display"
     wnd.clear()
     self.fits = self.app.renderer.on_wnd(wnd, self.app.theme, 0, 0,
                                          self.scroll,
                                          "issue_view.j2",
                                          key=self.issue.key,
                                          issue=self.issue.fields)
Exemple #3
0
 def add_title(self,
               text: str,
               win: _curses.window,
               align: str = "center") -> None:
     if align == "alignleft":
         cw = 2
     elif align == "center":
         ch, cw, text = self.calculateCenter(text, win)
     elif align == "alignright":
         cw = win.getmaxyx()[1] - 2 - len(text)
     win.addstr(0, cw, f" {text.title()} ")
Exemple #4
0
 def __init__(self, stdscr: window, users: UserModel, p: float = 0.5):
     self.stdscr = stdscr
     self.h = 0
     self.w = 0
     self.win = stdscr.subwin(self.h, self.w, 0, 0)
     self._refresh = self.win.refresh
     self.users = users
Exemple #5
0
 def __init__(self, stdscr: window, model: Model) -> None:
     self.stdscr = stdscr
     self.h = 0
     self.w = 0
     self.win = stdscr.subwin(self.h, self.w, 0, 0)
     self._refresh = self.win.refresh
     self.model = model
Exemple #6
0
    def redraw(self, wnd: _curses.window):
        "Refresh debug window"
        lines, cols = wnd.getmaxyx()
        wnd.erase()
        wnd.hline(0, 0, curses.ACS_HLINE, cols)

        self._logs = self._logs[-(lines-1):]
        line = 1
        for log in self._logs:
            wnd.addstr(line, 0, log[:cols-1])
            line += 1

        wnd.refresh()
Exemple #7
0
 def __init__(self, stdscr: window) -> None:
     self.h = 1
     self.w = curses.COLS
     self.y = curses.LINES - 1
     self.x = 0
     self.stdscr = stdscr
     self.win = stdscr.subwin(self.h, self.w, self.y, self.x)
     self._refresh = self.win.refresh
Exemple #8
0
 def calculateCenter(self, texts: Union[str, list],
                     win: _curses.window) -> tuple:
     if isinstance(texts, str):
         texts = [texts]
     longestText = max(texts)
     ltexts = len(texts)
     ltxt = len(longestText)
     height, width = map(lambda x: (x // 2), win.getmaxyx())
     return height - (ltexts // 2), width - (
         ltxt // 2), longestText if ltexts == 1 else texts
Exemple #9
0
def main_page(scr: window):
    curses.curs_set(0)
    scr.noutrefresh()
    callbacks = {}

    def command_callback(command: str, **kwargs: Any):
        if command in callbacks:
            callbacks[command](**kwargs)

    setup_colours()
    max_rows, max_cols = scr.getmaxyx()
    views: dict[str, AbstractView] = {
        'header': HeaderView(max_cols),
        'footer': FooterView(max_rows, max_cols),
        'a2z': A2ZView(max_rows, command_callback),
        'tabs': TabView(max_cols, command_callback),
        'content': ContentView(max_rows, max_cols, command_callback)
    }
    keypress_table: dict[str, Callable[[int], None]] = {name: view.process_keystroke for name, view in views.items()}
    focus: list[str] = ['a2z']
    dispatch_to: list[Callable[[int], None]] = [keypress_table[focus[0]]]

    full_render_current_state(scr, views, focus[0])
    curses.doupdate()

    callbacks = setup_callbacks(views, focus, dispatch_to)
    command_callback('LOAD_PAGE', page='HOMEPAGE')

    keep_going = True
    while keep_going:
        update_render_current_state(scr, views)
        curses.doupdate()

        key: int = scr.getch()
        if key == ord('q'):
            keep_going = False
        elif key == ord('\t'):
            focus[0] = next_focus(focus[0])
            update_focuses(views, focus[0])
            dispatch_to[0] = keypress_table[focus[0]]
        elif key == curses.KEY_RESIZE:
            curses.resizeterm(*scr.getmaxyx())
            scr.erase()
            scr.noutrefresh()
            resize_all(focus[0], views, scr)
        else:
            dispatch_to[0](key)
Exemple #10
0
def draw_boxes(stdscr: window):
    """
    This method draws the boxes on startup
    """

    h = curses.LINES  #Total height
    w = curses.COLS  #Total width

    #Some debug values, remove these later
    text = "This is the start of a new window"

    # Clear screen
    stdscr.clear()
    stdscr.addstr(0, 0, 'This is the start of a new window')
    stdscr.noutrefresh()

    theight = 2
    swidth = 15
    mheight = h - theight - 2
    mwidth = w - swidth - 2

    win['t'] = curses.newwin(theight, mwidth, h - 1 - theight, 1)
    win['t'].addstr(0, 0, "This is the messages windows")

    win['m'] = curses.newwin(mheight, mwidth, 1, 1)
    win['m'].addstr(0, 0, "Type something here.")
    win['m'].timeout(0)

    win['s'] = curses.newwin(h - 2, swidth, 1, w - swidth - 1)
    win['s'].addstr(0, 0, "This is a side pane")
Exemple #11
0
    def __init__(
        self,
        stdscr: window,
        chat_view: "ChatView",
        msg_view: "MsgView",
        status_view: "StatusView",
    ) -> None:
        curses.noecho()
        curses.cbreak()
        stdscr.keypad(True)
        curses.curs_set(0)

        curses.start_color()
        curses.use_default_colors()
        # init white color first to initialize colors correctly
        get_color(white, -1)

        self.stdscr = stdscr
        self.chats = chat_view
        self.msgs = msg_view
        self.status = status_view
        self.max_read = 2048
Exemple #12
0
    def drawCrossword(self, win: _curses.window, board: Optional[List] = None):
        mh, mw = map(lambda x: x - 4, win.getmaxyx())
        if not self.data:
            self.generateCrosswordBoard(mh, mw)
            self.data = None
        if self.data and (mh < self.data["height"] or mw < self.data["width"]):
            self.data = None

        if self.activeThread.get("gcb"):
            win.addstr(2, 2, f"generating Crossword {mh} x {mw}")
            win.refresh()
        elif self.data:
            ch, cw, board = self.calculateCenter(
                board or self.data["clueless"], win)
            for index, line in enumerate(board, start=ch):
                win.addstr(index, cw, line)

            for h, w, char in self.parseLoc.locaround:
                win.addstr(ch + h, cw + w, char, curses.color_pair(2))
Exemple #13
0
    def redraw(self, wnd: _curses.window):
        "Refresh status and keybindings display"
        # Update size on resize events
        self.lines_max, self.cols_max = wnd.getmaxyx()
        wnd.erase()
        wnd.hline(0, 0, curses.ACS_HLINE, self.cols_max)

        state = self.app.bindings.get_current()
        if state.render_callback is not None:
            state.render_callback()
        cmds = state.commands[:]

        col = self.margin_left

        while cmds:
            cmds, max_width = self._draw_column(wnd, col, cmds, state.disabled)
            col += max_width + self.margin_column

        hints = self.app.bindings.get_current().hints[:]
        while hints:
            hints, max_width = self._draw_hints(wnd, col, hints)
            col += max_width + self.margin_column

        wnd.refresh()
Exemple #14
0
 def redraw(self, wnd: _curses.window):
     "Refresh the view display"
     wnd.clear()
     wnd.addstr(0, 0, "Dashboard", self.app.theme.TITLE)
     if self.update_in_progress:
         wnd.addstr(2, 0, "Updating database")
Exemple #15
0
 def redraw(self, wnd: _curses.window):
     "Refresh the view display"
     wnd.erase()
     wnd.addstr(0, 0, "Secondary view.")
Exemple #16
0
    def redraw(self, wnd: _curses.window):
        "Refresh the view display"
        lines, cols = wnd.getmaxyx()
        wnd.erase()

        line = 0
        wnd.addstr(line, 0, f"View screen ({self.ticks} ticks):")
        line += 1
        for i in range(0, curses.COLORS):
            wnd.addstr(line, i % cols, str(i % 10), curses.color_pair(i))
            if (i+1) % cols == 0:
                line += 1

        line += 1
        for i, message in enumerate(self.messages):
            wnd.addstr(i + line, 0, "Msg: " + message)
        wnd.refresh()
Exemple #17
0
    def redraw(self, wnd: _curses.window):
        "Refresh the view display"
        lines, cols = wnd.getmaxyx()
        wnd.erase()
        msg = "Incremental search: " + self.query
        wnd.addstr(0, 0, msg)
        cursor_position = len(msg)

        self._update_search_state()

        msg = "{}/{}".format(len(self.results), len(self.all_issues))
        wnd.addstr(0, cols - len(msg), msg)

        if self.selected_idx >= len(self.results):
            self.selected_idx = max(0, len(self.results) - 1)

        line = 1
        max_summary = cols - 10 - 5
        for i, result in enumerate(self.results):
            if i == self.selected_idx:
                th_key = self.app.theme.ISSUE_KEY_SELECTED
                th_summary = self.app.theme.ISSUE_SUMMARY_SELECTED
            else:
                th_key = self.app.theme.ISSUE_KEY
                th_summary = self.app.theme.ISSUE_SUMMARY

            # TODO: Unified table generator
            j = result['fields']
            summary = j["summary"]
            if len(summary) > max_summary:
                summary = summary[:max_summary] + "…"
            summary += " " * (cols - len(summary) - 16)
            msg = f"{result['key']:10s} {summary}"
            wnd.addstr(line, 0, "{:15}".format(result['key']), th_key)
            wnd.addstr(line, 15, summary[:cols - 15 - 1], th_summary)
            line += 1
            if line == lines:
                break

        wnd.move(0, cursor_position)
Exemple #18
0
def resize_all(focus: str,
               views: dict[str, AbstractView],
               scr: window):
    for name, view in views.items():
        view.on_resize(*scr.getmaxyx(), focus == name)
Exemple #19
0
def update_render_current_state(scr: window, views: dict[str, AbstractView]):
    for view in views.values():
        view.update_render(*scr.getmaxyx())
Exemple #20
0
def full_render_current_state(scr: window, views: dict[str, AbstractView], focus: str):
    for name, view in views.items():
        view.full_render(*scr.getmaxyx(), focus == name)