예제 #1
0
def main():
    txt = urwid_readline.ReadlineEdit(multiline=True)
    txt.enable_autocomplete(compl)
    fill = urwid.Filler(txt, "top")
    loop = urwid.MainLoop(
        fill, unhandled_input=lambda key: unhandled_input(txt, key))
    loop.run()
예제 #2
0
def main():
    txt = urwid_readline.ReadlineEdit(multiline=True)
    fill = urwid.Filler(txt, "top")
    #bash("ns " + txt.text)

    urwid.connect_signal(txt, 'change', handle_change)

    loop = urwid.MainLoop(
        fill  #, unhandled_input=lambda key: unhandled_input(txt, key)
    )
    loop.run()
예제 #3
0
    def __init__(self, app: 'application.Application', note: gkeepapi.node.TopLevelNode):
        self.application = app
        self.note = note

        tmp = urwid.Text('')

        self.w_title = urwid_readline.ReadlineEdit(wrap=urwid.CLIP)
        self.w_text = urwid_readline.ReadlineEdit(multiline=True)
        self.w_list = Items()
        self.w_labels = labels.Labels()

        self.w_state = urwid.Text(u'', align=urwid.RIGHT)
        self.w_footer = urwid.Text(u'', align=urwid.RIGHT)
        self.w_content = urwid.Frame(
            tmp,
            header=tmp,
            footer=tmp
        )
        self.w_frame = urwid.Frame(
            urwid.Padding(
                self.w_content,
                align=urwid.CENTER,
                left=1,
                right=1
            ),
            header=self.w_state,
            footer=self.w_footer,
        )

        self.zen_mode = False

        super(Edit, self).__init__(
            self.w_frame,
            note.color.value
        )

        self._updateContent()
        self._updateLabels()
        self._updateState()
예제 #4
0
    def __init__(self, item: gkeepapi.node.ListItem, indented=None):
        self.id = item.id
        self.checked = item.checked
        self.indented = indented if indented is not None else item.indented
        self.w_indent = urwid.Text('')
        self.w_checkbox = urwid.Text('')
        self.w_text = urwid_readline.ReadlineEdit(edit_text=item.text)
        super(Item, self).__init__([
            (urwid.PACK, self.w_indent),
            (urwid.PACK, self.w_checkbox),
            self.w_text,
        ], dividechars=1)

        self._updateIndent()
        self.updateChecked(self.checked)
예제 #5
0
    def __init__(self, keymap: dict, account) -> None:
        self.text_caption = " >> "
        self.status_bar = urwid.Text(("status_bar", " "), align="left")
        self.attr = urwid.AttrMap(self.status_bar, "status_bar")

        self.widgetEdit = urwid_readline.ReadlineEdit(
            self.text_caption, "", multiline=True
        )

        self.pile = urwid.Pile([self.attr, self.widgetEdit])
        super().__init__(self.pile)

        self.model = account
        self.keymap = keymap
        self.current_chat: Optional[Chat] = None
        self.typing = False

        self.model.add_chatlist_monitor(self)
예제 #6
0
def urwid_main(game_state,
               text_lines,
               highlight_list,
               excludes_list,
               quit_event,
               screen_refresh_speed=0.05):
    ''' just the main process for urwid... needs renamed and fixed up
    '''

    #uc_u = '\u25B2'
    '''
    uc_u = '\u2191'
    uc_d = '\u2193'
    uc_l = '\u2190'
    uc_r = '\u2192'

    uc_ul = '\u2196'
    uc_ur = '\u2197'
    uc_dr = '\u2198'
    uc_dl = '\u2199'
    '''

    color_palette = [
        ('banner', '', '', '', '#fff', 'g35'),
        ('statusbar', 'white', 'black'),
        ('highlight', 'white', '', '', 'g0', 'g35'),
        ('white', 'white', '', '', 'g0', 'g35'),
        ('inside', '', '', '', 'g0', 'g35'),
        ('outside', '', '', '', 'g0', 'g35'),
        ('bg', '', '', '', 'g35', '#fff'),
    ]

    # note that these are ordered in Python 3.6+, this assumes you are running 3.6+ !!!
    arrows = {}
    arrows['n'] = 'n'
    arrows['e'] = 'e'
    arrows['s'] = 's'
    arrows['w'] = 'w'
    arrows['nw'] = 'nw'
    arrows['ne'] = 'ne'
    arrows['sw'] = 'sw'
    arrows['se'] = 'se'

    exit_string = ' '
    for k, v in arrows.items():
        if game_state.exits.get(k):
            exit_string += v
        else:
            exit_string += ' ' * len(v)  # preserve spacing from glyph
        exit_string += ' '  # separator whitespace

    # consider padding roundtime with 3 spaces
    status_line_string = '[ RT:  {roundtime}{roundtime_stable} ]' + '[{exit_string}]'
    #status_line_string = '[ RT:  {roundtime} ]' + '[ ' + ' '.join([v for k, v in arrows.items()]) + ' ]'

    # imagine a function that adds a space or the arrow depending on
    # whether the compass arrow last received game state
    # currently just used to display them all as a placeholder

    fixed_size_for_now = 1000
    main_window_buffer_size = 40
    main_window_stack = StackedWidget()

    # must be initalized with an empty string
    # these should probably go in a map instead of hardcoded...
    # probably want to map N xml-defined tags to M message deques
    story_window = ScrollBar(Scrollable(urwid.Text('')))
    tcp_window = ScrollBar(Scrollable(urwid.Text('')))
    chat_window = ScrollBar(Scrollable(urwid.Text('')))

    main_window_stack.push_widget(story_window)
    main_window_stack.push_widget(tcp_window)
    main_window_stack.push_widget(chat_window)

    input_box = urwid_readline.ReadlineEdit(
        '> ', '')  # pretty sure urwid_readline package needs Python3

    status_line = urwid.Text(status_line_string)

    mainframe = urwid.Pile([
        ('weight', fixed_size_for_now,
         urwid.Filler(main_window_stack,
                      height=main_window_buffer_size,
                      valign='bottom')),
        ('fixed', 1, urwid.Filler(status_line, 'bottom')),
        ('fixed', 1, urwid.Filler(input_box, 'bottom')),
    ],
                           focus_item=2)

    # these were for the terminal
    def set_title(widget, title):
        mainframe.set_title(title)

    def quit(*args, **kwargs):
        raise urwid.ExitMainLoop()

    def unhandled_input(txt, key):
        ''' 
        much of this input should be handled in the pile or widgets inside the pile
        
        q: why is this called unhandled input if it is the input handler??
        a: ... urwid thing, this can probably be changed to whatever is appropriate, just use care

        '''
        if key in ("`"):
            if main_window_stack.current + 1 >= main_window_stack.widget_count:
                main_window_stack.current = 0
            else:
                # don't use the fake setter, it's doing some weird modulo stuff
                # maybe after reviewing the module code more...
                main_window_stack.current += 1

        if key in ("tab"):
            # rudimentary focus bouncer for now
            # ideally focus bounce will toggle buffers in the future
            if mainframe.focus_position == 2:
                mainframe.focus_position = 0
            else:
                mainframe.focus_position = 2
            return

        if key in ("enter"):

            game_state.history_scroll_mode = False  # toggle history scroll mode off

            if len(txt.edit_text) == 0:
                ''' ignore an empty command
                '''
                return

            submitted_command = txt.edit_text

            # used to have a command splitter here, decided not to use it
            game_state.input_history.append(submitted_command)
            game_state.command_queue.put(submitted_command.encode('utf-8'))

            txt.set_edit_text('')
            txt.set_edit_pos(0)

            return

        if key in ("up", "down"):

            # deal with the 0 history case here
            if len(game_state.input_history) == 0:
                return

            # enter history scroll mode until the user presses enter
            if game_state.history_scroll_mode == False:
                game_state.history_scroll_mode = True
                game_state.input_history_counter = len(
                    game_state.input_history) - 1

            # don't do this if you just set it to true! (elif)
            elif game_state.history_scroll_mode == True:

                if key in ("up"):
                    if game_state.input_history_counter > 0:
                        game_state.input_history_counter -= 1

                if key in ("down"):
                    if game_state.input_history_counter < len(
                            game_state.input_history) - 1:
                        game_state.input_history_counter += 1

            input_box.set_edit_text(
                game_state.input_history[game_state.input_history_counter])
            input_box.set_edit_pos(len(txt.edit_text))
            return

        if key in ("left"):
            input_box.set_edit_text('')
            input_box.set_edit_pos(len(txt.edit_text))
            return

        if key in ("right"):
            ''' 
            interestingly, because of urwid-readline, i can use right and left arrows
            but only when there is already text on the line, and not on the far edges
            so on the far left, a left key will trigger this
            on the far right, a right key will trigger unknown key: right
            '''
            # need the mutex because this uses a function of the underlying deque
            # see: https://stackoverflow.com/a/6518011
            with game_state.rt_command_queue.mutex:
                game_state.rt_command_queue.queue.clear()
            return

        # not working
        if key in ("ctrl q", "ctrl Q"):
            #raise urwid.ExitMainLoop()
            quit()

        #input_box.set_edit_text("unknown key: " + repr(key))
        #input_box.set_edit_pos(len(txt.edit_text))
        return

    '''
    # supposed to fix focus loss, i don't have that issue yet
    # and it may be solved where i set handle_mouse=False in MainLoop
    def mouse_event(self, size, event, button, col, row, focus):
        pass
    '''

    #urwid.connect_signal(term, 'title', set_title)
    #urwid.connect_signal(term, 'closed', quit)

    # reference: http://urwid.org/reference/main_loop.html
    loop = urwid.MainLoop(
        mainframe,
        color_palette,
        handle_mouse=False,
        unhandled_input=lambda key: unhandled_input(input_box, key))

    def refresh_screen(game_state, loop):
        #view_lines_buffer = list() # a buffer of lines sent to the terminal
        while True:
            # ideally we could just check if loop is running
            # is there a data flag on loop we can pause until is True (loop.run() started)

            # do this first so that the urwid MainLoop 'loop' exists! otherwise too fast
            # it would be better to kick this off inside loop.run I think
            time.sleep(screen_refresh_speed)

            # this really should be in the main thread...
            # urwid has event_loop that can probably handle this
            if quit_event.is_set():
                raise Exception(
                    'Client has exited, use exception to cleanup for now.')

            status_line_contents = dict()
            # calculate remaining roundtime
            current_roundtime = int(game_state.roundtime - game_state.time)
            if current_roundtime < 0:
                current_roundtime = 0
            if current_roundtime < 10:
                # pad < 10
                status_line_contents['roundtime'] = ' ' + str(
                    current_roundtime)
            else:
                # don't pad > 10, note, for roundtimes 100+ there will be a shift in the UI. #wontfix
                status_line_contents['roundtime'] = '' + str(current_roundtime)

            exit_string = ''
            for k, v in arrows.items():
                if game_state.exits.get(k):
                    exit_string += v
                else:
                    exit_string += ' ' * len(v)  # preserve spacing from glyph
                exit_string += ' '  # separator whitespace

            status_line_contents['exit_string'] = exit_string

            # show the roundtime stable indicator if both time and roundtime are reported
            # this will be false only when the displayed roundtime is based on projected time
            # (game_state.time is projected time)
            if game_state.reported_time >= game_state.roundtime:
                status_line_contents['roundtime_stable'] = '.'
            else:
                status_line_contents['roundtime_stable'] = ' '

            # format the status line with the current content values
            status_line_output = status_line_string.format(
                **status_line_contents)
            # set the status line
            mainframe.contents[1][0].original_widget.set_text(
                ('statusbar', status_line_output))

            # fill up the urwid main view text
            if not text_lines.empty():
                extend_view_buffer(game_state, text_lines, highlight_list,
                                   excludes_list)

            # this target is one below main_window so lets try that instead
            # mainframe is the pile, contents[0] is the first item
            #scrollable_textbox = mainframe.contents[0][0].original_widget.current_widget._original_widget
            # this one is dynamic based on active stacked window
            current_main_window = mainframe.contents[0][
                0].original_widget.current_widget._original_widget
            # scrollable_textbox = story_window._original_widget

            # we can use python names instead of drilling down...
            #    - this is critical to future urwid organization
            # the contents object is a list of (widget, option) tuples
            # http://urwid.org/reference/widget.html#urwid.Pile
            # apparently it will not take a deque, so coerce to a list
            story_window._original_widget._original_widget.set_text(
                list(game_state.urwid_views['urwid_main_view']))
            tcp_window._original_widget._original_widget.set_text(
                list(game_state.urwid_views['urwid_tcp_view']))
            chat_window._original_widget._original_widget.set_text(
                list(game_state.urwid_views['urwid_chat_view']))

            # MUST - scroll the active window
            # scroll unless item 0 is in focus - is item 0 the filler?
            if mainframe.focus_position != 0:
                # set and record the most recent position
                current_main_window._original_widget._invalidate  # invalidate the visible text widget cache
                current_main_window.set_scrollpos(-1)
                game_state.urwid_scrollbar_last = current_main_window.get_scrollpos(
                )

            loop.draw_screen()

    # refresh the screen in its own thread.
    # this camn probably get moved to main() in pylanthia.py
    refresh = threading.Thread(target=refresh_screen, args=(game_state, loop))
    refresh.daemon = True  # kill the thread if the process dies
    refresh.start()

    loop.run()
예제 #7
0
def urwid_main(game_state, text_lines, screen_refresh_speed=0.05):
    """ just the main process for urwid... needs renamed and fixed up
    """

    # uc_u = '\u25B2'
    """
    uc_u = '\u2191'
    uc_d = '\u2193'
    uc_l = '\u2190'
    uc_r = '\u2192'

    uc_ul = '\u2196'
    uc_ur = '\u2197'
    uc_dr = '\u2198'
    uc_dl = '\u2199'
    """

    color_palette = [
        ("banner", "", "", "", "#fff", "g35"),
        ("statusbar", "white", "black"),
        ("highlight", "white", "", "", "g0", "g35"),
        ("white", "white", "", "", "g0", "g35"),
        ("inside", "", "", "", "g0", "g35"),
        ("outside", "", "", "", "g0", "g35"),
        ("bg", "", "", "", "g35", "#fff"),
    ]

    # note that these are ordered in Python 3.6+, this assumes you are running 3.6+ !!!
    arrows = {}
    arrows["n"] = "n"
    arrows["e"] = "e"
    arrows["s"] = "s"
    arrows["w"] = "w"
    arrows["nw"] = "nw"
    arrows["ne"] = "ne"
    arrows["sw"] = "sw"
    arrows["se"] = "se"

    exit_string = " "
    for k, v in arrows.items():
        if game_state.exits.get(k):
            exit_string += v
        else:
            exit_string += " " * len(v)  # preserve spacing from glyph
        exit_string += " "  # separator whitespace

    # imagine a function that adds a space or the arrow depending on
    # whether the compass arrow last received game state
    # currently just used to display them all as a placeholder

    fixed_size_for_now = 1000
    main_window_buffer_size = 40
    main_window_stack = StackedWidget()

    # must be initalized with an empty string
    # these should probably go in a map instead of hardcoded...
    # probably want to map N xml-defined tags to M message deques
    story_window = ScrollBar(Scrollable(urwid.Text("")))
    tcp_window = ScrollBar(Scrollable(urwid.Text("")))
    chat_window = ScrollBar(Scrollable(urwid.Text("")))

    main_window_stack.push_widget(story_window)
    main_window_stack.push_widget(tcp_window)
    main_window_stack.push_widget(chat_window)

    input_box = urwid_readline.ReadlineEdit(
        "> ", "")  # pretty sure urwid_readline package needs Python3

    status_line = urwid.Text(game_state.status_line_string)

    mainframe = urwid.Pile(
        [
            (
                "weight",
                fixed_size_for_now,
                urwid.Filler(main_window_stack,
                             height=main_window_buffer_size,
                             valign="bottom"),
            ),
            ("fixed", 1, urwid.Filler(status_line, "bottom")),
            ("fixed", 1, urwid.Filler(input_box, "bottom")),
        ],
        focus_item=2,
    )

    # these were for the terminal
    def set_title(widget, title):
        mainframe.set_title(title)

    def quit(*args, **kwargs):
        pass  # this method is never called

    def unhandled_input(txt, key):
        """
        much of this input should be handled in the pile or widgets inside the pile
        q: why is this called unhandled input if it is the input handler??
        a: ... urwid thing, this can probably be changed to whatever is appropriate, just use care
        """
        if key in ("`"):
            if main_window_stack.current + 1 >= main_window_stack.widget_count:
                main_window_stack.current = 0
            else:
                # don't use the fake setter, it's doing some weird modulo stuff
                # maybe after reviewing the module code more...
                main_window_stack.current += 1

        if key in ("tab"):
            # rudimentary focus bouncer for now
            # ideally focus bounce will toggle buffers in the future
            if mainframe.focus_position == 2:
                mainframe.focus_position = 0
            else:
                mainframe.focus_position = 2
            return

        if key in ("enter"):

            game_state.history_scroll_mode = False  # toggle history scroll mode off

            if len(txt.edit_text) == 0:
                """ ignore an empty command
                """
                return

            submitted_command = txt.edit_text

            # used to have a command splitter here, decided not to use it
            game_state.input_history.append(submitted_command)
            game_state.command_queue.put(submitted_command.encode("utf-8"))

            txt.set_edit_text("")
            txt.set_edit_pos(0)

            return

        if key in ("up", "down"):

            # deal with the 0 history case here
            if len(game_state.input_history) == 0:
                return

            # enter history scroll mode until the user presses enter
            if game_state.history_scroll_mode == False:
                game_state.history_scroll_mode = True
                game_state.input_history_counter = len(
                    game_state.input_history) - 1

            # don't do this if you just set it to true! (elif)
            elif game_state.history_scroll_mode == True:

                if key in ("up"):
                    if game_state.input_history_counter > 0:
                        game_state.input_history_counter -= 1

                if key in ("down"):
                    if (game_state.input_history_counter <
                            len(game_state.input_history) - 1):
                        game_state.input_history_counter += 1

            input_box.set_edit_text(
                game_state.input_history[game_state.input_history_counter])
            input_box.set_edit_pos(len(txt.edit_text))
            return

        if key in ("left"):
            input_box.set_edit_text("")
            input_box.set_edit_pos(len(txt.edit_text))
            return

        if key in ("right"):
            """
            interestingly, because of urwid-readline, i can use right and left arrows
            but only when there is already text on the line, and not on the far edges
            so on the far left, a left key will trigger this
            on the far right, a right key will trigger unknown key: right
            """
            # need the mutex because this uses a function of the underlying deque
            # see: https://stackoverflow.com/a/6518011
            with game_state.rt_command_queue.mutex:
                game_state.rt_command_queue.queue.clear()
            return

        # not working
        if key in ("ctrl q", "ctrl Q"):
            # raise urwid.ExitMainLoop()
            # quit()
            pass

        # input_box.set_edit_text("unknown key: " + repr(key))
        # input_box.set_edit_pos(len(txt.edit_text))
        return

    """
    # supposed to fix focus loss, i don't have that issue yet
    # and it may be solved where i set handle_mouse=False in MainLoop
    def mouse_event(self, size, event, button, col, row, focus):
        pass
    """

    # urwid.connect_signal(term, 'title', set_title)
    # urwid.connect_signal(term, 'closed', quit)

    # reference: http://urwid.org/reference/main_loop.html
    loop = urwid.MainLoop(
        mainframe,
        color_palette,
        handle_mouse=False,
        unhandled_input=lambda key: unhandled_input(input_box, key),
    )

    def refresh_screen(game_state, loop):
        # view_lines_buffer = list() # a buffer of lines sent to the terminal
        while True:
            # ideally we could just check if loop is running
            # is there a data flag on loop we can pause until is True (loop.run() started)

            # do this first so that the urwid MainLoop 'loop' exists! otherwise too fast
            # it would be better to kick this off inside loop.run I think
            time.sleep(screen_refresh_speed)

            # lets test this somewhere else...
            if game_state.quit_event.is_set():
                # from: https://stackoverflow.com/a/7099229/1693693
                os.kill(os.getpid(),
                        signal.SIGINT)  # give SIGINT to main for cleanup
                # TODO: raise doesn't interrupt main, not working, explore later
                # raise urwid.ExitMainLoop()

            # set character name
            game_state.status_line_contents[
                "character_firstname"] = game_state.character_firstname

            # calculate remaining roundtime
            current_roundtime = int(game_state.roundtime - game_state.time)
            if current_roundtime < 0:
                current_roundtime = 0
            if current_roundtime < 10:
                # pad < 10
                game_state.status_line_contents["roundtime"] = " " + str(
                    current_roundtime)
            else:
                # don't pad > 10, note, for roundtimes 100+ there will be a shift in the UI. #wontfix
                game_state.status_line_contents["roundtime"] = "" + str(
                    current_roundtime)

            exit_string = ""
            for k, v in arrows.items():
                if game_state.exits.get(k):
                    exit_string += v
                else:
                    exit_string += " " * len(v)  # preserve spacing from glyph
                exit_string += " "  # separator whitespace

            game_state.status_line_contents["exit_string"] = exit_string

            # show the roundtime stable indicator if both time and roundtime are reported
            # this will be false only when the displayed roundtime is based on projected time
            # (game_state.time is projected time)
            if game_state.reported_time >= game_state.roundtime:
                game_state.status_line_contents["roundtime_stable"] = "."
            else:
                game_state.status_line_contents["roundtime_stable"] = " "

            # format the status line with the current content values
            status_line_output = game_state.status_line_string.format(
                **game_state.status_line_contents)[:80]
            # set the status line
            mainframe.contents[1][0].original_widget.set_text(
                ("statusbar", status_line_output))

            # fill up the urwid main view text
            if not text_lines.empty():
                extend_view_buffer(game_state, text_lines)

            # this target is one below main_window so lets try that instead
            # mainframe is the pile, contents[0] is the first item
            # scrollable_textbox = mainframe.contents[0][0].original_widget.current_widget._original_widget
            # this one is dynamic based on active stacked window
            current_main_window = mainframe.contents[0][
                0].original_widget.current_widget._original_widget
            # scrollable_textbox = story_window._original_widget

            # we can use python names instead of drilling down...
            #    - this is critical to future urwid organization
            # the contents object is a list of (widget, option) tuples
            # http://urwid.org/reference/widget.html#urwid.Pile
            # apparently it will not take a deque, so coerce to a list
            story_window._original_widget._original_widget.set_text(
                list(game_state.urwid_views["urwid_main_view"]))
            tcp_window._original_widget._original_widget.set_text(
                list(game_state.urwid_views["urwid_tcp_view"]))
            chat_window._original_widget._original_widget.set_text(
                list(game_state.urwid_views["urwid_chat_view"]))

            # MUST - scroll the active window
            # scroll unless item 0 is in focus - is item 0 the filler?
            if mainframe.focus_position != 0:
                # set and record the most recent position
                current_main_window._original_widget._invalidate  # invalidate the visible text widget cache
                current_main_window.set_scrollpos(-1)
                game_state.urwid_scrollbar_last = current_main_window.get_scrollpos(
                )

            loop.draw_screen()

    # refresh the screen in its own thread.
    # this camn probably get moved to main() in pylanthia.py
    refresh = threading.Thread(target=refresh_screen, args=(game_state, loop))
    refresh.daemon = True  # kill the thread if the process dies
    refresh.start()

    loop.run()
예제 #8
0
 def widgets(self):
     return dict(edit=urwid_readline.ReadlineEdit(
         caption=("bold", "Name: "), edit_text=self.orig_value or ""))