class StringEditor(WidgetWrap):
    """ Edit input class
    Initializes and Edit object and attachs its result
    to the `value` accessor.
    """
    def __init__(self, caption=None, default=None, **kwargs):
        if caption is None:
            caption = ""
        self._edit = Edit(caption=caption, **kwargs)
        if default is not None:
            self._edit.set_edit_text(default)
        self.error = None
        super().__init__(self._edit)

    def keypress(self, size, key):
        if self.error:
            self._edit.set_edit_text("")
            self.error = None
        return super().keypress(size, key)

    def set_error(self, msg):
        self.error = msg
        return self._edit.set_edit_text(msg)

    @property
    def value(self):
        if self._edit.get_edit_text() == "":
            return None
        return self._edit.get_edit_text()

    @value.setter  # NOQA
    def value(self, value):
        self._edit.set_edit_text(value)
示例#2
0
class AddTodo(ConnectedComponent):
    def render_component(self, props):
        self.edit = Edit(caption='Todo: ', edit_text='')
        self.button = Button('Add Todo')
        return Columns([
            (1, Text('[')),
            self.edit,
            (1, Text(']')),
            (18, self.button),
        ])

    def keypress(self, size, key):
        if key == 'enter':
            self.on_submit()
            return True
        return super(AddTodo, self).keypress(size, key)

    def on_submit(self):
        if not self.edit.get_edit_text().strip():
            return
        self.store['dispatch'](add_todo(self.edit.get_edit_text()))
        self.edit.set_edit_text('')

    def on_click(self, *args):
        self.on_submit()
示例#3
0
class StringEditor(WidgetWrap):
    """ Edit input class
    Initializes and Edit object and attachs its result
    to the `value` accessor.
    """
    def __init__(self, caption=None, default=None, **kwargs):
        if caption is None:
            caption = ""
        self._edit = Edit(caption=caption, **kwargs)
        if default is not None:
            self._edit.set_edit_text(default)
        self.error = None
        super().__init__(self._edit)

    def keypress(self, size, key):
        if self.error:
            self._edit.set_edit_text("")
            self.error = None
        return super().keypress(size, key)

    def set_error(self, msg):
        self.error = msg
        return self._edit.set_edit_text(msg)

    @property
    def value(self):
        if self._edit.get_edit_text() == "":
            return None
        return self._edit.get_edit_text()

    @value.setter  # NOQA
    def value(self, value):
        self._edit.set_edit_text(value)
示例#4
0
class NoteEditor(WidgetWrap):

    __metaclass__ = signals.MetaSignals
    signals = ['done']

    def __init__(self, done_handler, note=None):
        self.modes = ['title', 'tags', 'text']
        self.mode = self.modes[0]
        self.note = note
        if note is None:
            self.title = ''
            self.tags = ''
            self.text = ''
        else:
            self.title = note.title
            self.tags = note.formatted_tags()
            self.text = note.text

        self.editor = Edit(u'title :: ', self.title)
        connect_signal(self, 'done', done_handler)
        WidgetWrap.__init__(self, self.editor)

    def keypress(self, size, key):
        if key == 'enter':
            if self.mode == 'title':
                self.title = self.editor.get_edit_text()
                self.init_tags_mode()
            elif self.mode == 'tags':
                # Enforce lower case tags for consistency
                self.tags = self.editor.get_edit_text().lower()
                self.init_text_mode()

        elif key == 'esc':
            self.emit_done()
            return

        size = size,
        self.editor.keypress(size, key)

    def init_tags_mode(self):
        self.mode = self.modes[1]
        self.editor.set_caption('tags :: ')
        self.editor.set_edit_text(self.tags)

    def init_text_mode(self):
        self.mode = self.modes[2]
        editor = os.environ.get('EDITOR', 'vim')
        with tempfile.NamedTemporaryFile(prefix="aerende_tmp",
                                         suffix=".tmp") as temp:
            temp.write(self.text.encode('utf-8'))
            temp.flush()
            call([editor, temp.name])
            temp.seek(0)
            self.text = temp.read().decode('utf-8').strip()
            os.system('clear')
            self.emit_done((self.title, self.tags, self.text))

    def emit_done(self, note=None):
        emit_signal(self, 'done', note, self.note)
示例#5
0
class StyledEdit(Padding):
    def __init__(self, content, default, tooltip, left_margin, source=None):
        """
        General Edit Field

        Args:
            content: text of the editbox
            default: default value of the editbox
            tooltip: tooltip of the editbox
            left_margin: left_margin of the editbox
            source: there this item is from for value reference
        """
        text = u" *  " + content + u": "
        self.core = Edit(('editcp', ""), default)
        self.source = source
        self.widget = Pile([
            Text(text),
            Padding(AttrWrap(self.core, 'editbx', 'editfc'), left=4),
            Padding(Text(tooltip), left=4)
        ])
        super().__init__(self.widget, left=2 + left_margin - 4, right=2)

    def get_source(self):
        return self.source

    def get_core_value(self):
        return self.core.get_edit_text()
示例#6
0
文件: ui.py 项目: gigigi/turses
class TextEditor(WidgetWrap):
    """Editor for creating arbitrary text."""

    __metaclass__ = signals.MetaSignals
    signals = ['done']

    def __init__(self, 
                 prompt, 
                 content, 
                 done_signal_handler):
        if content:
            content += ' '
        self.editor = Edit(u'%s (twice enter key to validate or esc) \n>> ' % prompt, content)

        widgets = [self.editor]
        w = AttrMap(Columns(widgets), 'editor')

        connect_signal(self, 'done', done_signal_handler)

        self.__super.__init__(w)

    def keypress(self, size, key):
        if key == 'enter' and self.last_key == 'enter':
            self.emit_done_signal(self.editor.get_edit_text())
            return
        elif key == 'esc':
            self.emit_done_signal()
            return

        self.last_key = key
        size = size,
        self.editor.keypress(size, key)

    def emit_done_signal(self, content=None):
        emit_signal(self, 'done', content)
示例#7
0
class TextEditor(WidgetWrap):
    """Editor for creating arbitrary text."""

    __metaclass__ = signals.MetaSignals
    signals = ['done']

    def __init__(self, prompt, content, done_signal_handler):
        if content:
            content += ' '
        self.editor = Edit(
            u'%s (twice enter key to validate or esc) \n>> ' % prompt, content)

        widgets = [self.editor]
        w = AttrMap(Columns(widgets), 'editor')

        connect_signal(self, 'done', done_signal_handler)

        self.__super.__init__(w)

    def keypress(self, size, key):
        if key == 'enter' and self.last_key == 'enter':
            self.emit_done_signal(self.editor.get_edit_text())
            return
        elif key == 'esc':
            self.emit_done_signal()
            return

        self.last_key = key
        size = size,
        self.editor.keypress(size, key)

    def emit_done_signal(self, content=None):
        emit_signal(self, 'done', content)
示例#8
0
class LockScreen(Overlay):
    LOCKED = "The screen is locked. Please enter a password (this is the " \
             "password you entered for OpenStack during installation). "

    INVALID = ("error", "Invalid password.")

    IOERROR = ("error", "Problem accessing {pwd}. Please make sure "
               "it contains exactly one line that is the lock "
               "password.".format(pwd=pegasus.PASSWORD_FILE))

    def __init__(self, underlying, unlock):
        self.unlock = unlock
        self.password = Edit("Password: "******"")
        w = ListBox([Text(self.LOCKED), self.invalid,
                     self.password])
        w = LineBox(w)
        w = AttrWrap(w, "dialog")
        Overlay.__init__(self, w, underlying, 'center', 60, 'middle', 8)

    def keypress(self, size, key):
        if key == 'enter':
            if pegasus.OPENSTACK_PASSWORD is None:
                self.invalid.set_text(self.IOERROR)
            elif pegasus.OPENSTACK_PASSWORD == self.password.get_edit_text():
                self.unlock()
            else:
                self.invalid.set_text(self.INVALID)
                self.password.set_edit_text("")
        else:
            return Overlay.keypress(self, size, key)
示例#9
0
文件: ui.py 项目: ivanov/turses
class BaseEditor(WidgetWrap):
    """Base class for editors."""

    __metaclass__ = signals.MetaSignals
    signals = ["done"]

    def __init__(self, prompt, content, done_signal_handler, cursor_position=None):
        """
        Initializes editor, connects 'done' signal.

        When pressing 'enter' twice the `submit` method is called, which by
        default calls `emit_done_signal` with the text that has been
        introduced.

        When pressing 'esc' the `cancel` method is called, which by default
        calls `emit_done_signal` with no arguments.

        The subclasses must call the `_wrap` method with the editor widgets
        and `BaseEditor` will wrap it in a `urwid.Colums` widget, calling to
        `urwid.WidgetWrap.__init__` with the wrapped widget.
        """
        caption = _(u"%s (twice enter key to validate or esc) \n>> ") % prompt
        if content:
            content += " "
        self.content = content
        self.editor = Edit(caption=caption, edit_text=content, edit_pos=cursor_position)
        self.last_key = None

        connect_signal(self, "done", done_signal_handler)

    def _wrap(self, widgets):
        widgets = widgets if isinstance(widgets, list) else [widgets]
        composed_widget = Columns(widgets)

        widget = AttrMap(LineBox(composed_widget), "editor")
        WidgetWrap.__init__(self, widget)

    def keypress(self, size, key):
        if key == "enter" and self.last_key == "enter":
            self.submit()
            return
        elif key == "esc":
            self.cancel()
            return

        self.last_key = key
        size = (size,)
        self.editor.keypress(size, key)

    def submit(self):
        self.emit_done_signal(self.editor.get_edit_text())

    def cancel(self):
        self.emit_done_signal()

    def emit_done_signal(self, content=None):
        emit_signal(self, "done", content)
示例#10
0
class EditInput(WidgetWrap):
    """ Edit input class

    Initializes an Edit object and attaches its result to
    the `value` accessor.
    """
    def __init__(self, caption, **kwargs):
        self._edit = Edit(caption=caption, **kwargs)
        super().__init__(
            Color.string_input(self._edit, focus_map="string_input focus"))

    @property
    def value(self):
        """ Returns text of input
        """
        return self._edit.get_edit_text()
示例#11
0
        async def apply_cb(edit: urwid.Edit) -> None:
            text: str = edit.get_edit_text()

            # In case the text is empty
            if not text:
                return

            sha = await core.full_sha(text)
            for c in reversed(list(itertools.chain(self.new_commits, self.previous_commits))):
                if c.sha == sha:
                    commit = c
                    break
            else:
                raise RuntimeError(f"Couldn't find {sha}")

            await commit.apply(self)
示例#12
0
class EditInput(WidgetWrap):

    """ Edit input class

    Initializes an Edit object and attaches its result to
    the `value` accessor.
    """

    def __init__(self, caption, **kwargs):
        self._edit = Edit(caption=caption, **kwargs)
        super().__init__(self._edit)

    @property
    def value(self):
        """ Returns text of input
        """
        return self._edit.get_edit_text()
示例#13
0
文件: ui.py 项目: gigigi/turses
class TweetEditor(WidgetWrap):
    """Editor for creating tweets."""

    __metaclass__ = signals.MetaSignals
    signals = ['done']

    def __init__(self, 
                 prompt, 
                 content, 
                 done_signal_handler):
        if content:
            content += ' '
        self.editor = Edit(u'%s (twice enter key to validate or esc) \n>> ' % prompt, content)

        self.counter = len(content)
        self.counter_widget = Text(str(self.counter))

        widgets = [('fixed', 4, self.counter_widget), self.editor]
        w = AttrMap(Columns(widgets), 'editor')

        connect_signal(self, 'done', done_signal_handler)
        connect_signal(self.editor, 'change', self.update_counter)

        self.__super.__init__(w)

    def update_counter(self, edit, new_edit_text):
        self.counter = len(new_edit_text)
        self.counter_widget.set_text(str(self.counter))

    def keypress(self, size, key):
        if key == 'enter' and self.last_key == 'enter':
            if self.counter > TWEET_MAX_CHARS:
                return
            else:
                self.emit_done_signal(self.editor.get_edit_text())
        elif key == 'esc':
            self.emit_done_signal()
            return

        self.last_key = key
        size = size,
        self.editor.keypress(size, key)

    def emit_done_signal(self, content=None):
        emit_signal(self, 'done', content)
示例#14
0
class TweetEditor(WidgetWrap):
    """Editor for creating tweets."""

    __metaclass__ = signals.MetaSignals
    signals = ['done']

    def __init__(self, prompt, content, done_signal_handler):
        if content:
            content += ' '
        self.editor = Edit(
            u'%s (twice enter key to validate or esc) \n>> ' % prompt, content)

        self.counter = len(content)
        self.counter_widget = Text(str(self.counter))

        widgets = [('fixed', 4, self.counter_widget), self.editor]
        w = AttrMap(Columns(widgets), 'editor')

        connect_signal(self, 'done', done_signal_handler)
        connect_signal(self.editor, 'change', self.update_counter)

        self.__super.__init__(w)

    def update_counter(self, edit, new_edit_text):
        self.counter = len(new_edit_text)
        self.counter_widget.set_text(str(self.counter))

    def keypress(self, size, key):
        if key == 'enter' and self.last_key == 'enter':
            if self.counter > TWEET_MAX_CHARS:
                return
            else:
                self.emit_done_signal(self.editor.get_edit_text())
        elif key == 'esc':
            self.emit_done_signal()
            return

        self.last_key = key
        size = size,
        self.editor.keypress(size, key)

    def emit_done_signal(self, content=None):
        emit_signal(self, 'done', content)
示例#15
0
class GazuaFrame(Frame):
    column_pos = 0

    def __init__(self, *args, **kwargs):
        self.search_edit = Edit('Search: ')
        self.arrow_callback = kwargs['arrow_callback']
        super(GazuaFrame,
              self).__init__(*args, header=AttrMap(self.search_edit, 'header'))

    def keypress(self, size, key):
        if len(key) == 1 and key.isalpha:
            if re.compile('^[a-zA-Z0-9]$').match(key):
                self.search_edit.insert_text(key)
        elif key == 'backspace':
            self.search_edit.set_edit_text(
                self.search_edit.get_edit_text()[0:-1])
        elif key == 'left':
            if self.column_pos == 0:
                self.arrow_callback(None)
            elif self.column_pos == 1:
                self.column_pos -= 1
                self.arrow_callback(0)
            else:
                self.column_pos -= 1
                self.arrow_callback(1)
        elif key == 'right':
            if self.column_pos == 0:
                self.column_pos += 1
                self.arrow_callback(1)
            elif self.column_pos == 1:
                self.column_pos += 1
                self.arrow_callback(2)
            else:
                self.arrow_callback(None)

        return super(GazuaFrame, self).keypress(size, key)
示例#16
0
文件: circ.py 项目: spaceone/circuits
class Client(Component):

    channel = "client"

    def init(self, host, port=6667, opts=None):
        self.host = host
        self.port = port
        self.opts = opts
        self.hostname = gethostname()

        self.nick = opts.nick
        self.ircchannel = opts.channel

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)

        self.create_interface()

    def create_interface(self):
        self.screen = Screen()
        self.screen.start()

        self.screen.register_palette([
            ("title", "white", "dark blue", "standout"),
            ("line", "light gray", "black"),
            ("help", "white", "dark blue")]
        )

        self.body = ListBox(SimpleListWalker([]))
        self.lines = self.body.body

        self.title = Text(MAIN_TITLE)
        self.header = AttrWrap(self.title, "title")

        self.help = AttrWrap(
            Text(HELP_STRINGS["main"]),
            "help"
        )

        self.input = Edit(caption="%s> " % self.ircchannel)
        self.footer = Pile([self.help, self.input])

        self.top = Frame(self.body, self.header, self.footer)

    def ready(self, component):
        """Ready Event

        This event is triggered by the underlying ``TCPClient`` Component
        when it is ready to start making a new connection.
        """

        self.fire(connect(self.host, self.port))

    def connected(self, host, port):
        """connected Event

        This event is triggered by the underlying ``TCPClient`` Component
        when a successfully connection has been made.
        """

        nick = self.nick
        hostname = self.hostname
        name = "%s on %s using circuits/%s" % (nick, hostname, systemVersion)

        self.fire(NICK(nick))
        self.fire(USER(nick, hostname, host, name))

    def numeric(self, source, numeric, *args):
        """Numeric Event

        This event is triggered by the ``IRC`` Protocol Component when we have
        received an IRC Numberic Event from server we are connected to.
        """

        if numeric == ERR_NICKNAMEINUSE:
            self.fire(NICK("{0:s}_".format(args[0])))
        elif numeric in (RPL_ENDOFMOTD, ERR_NOMOTD):
            self.fire(JOIN(self.ircchannel))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.screen.stop()

    @handler("generate_events")
    def _on_generate_events(self, event):
        event.reduce_time_left(0)

        size = self.screen.get_cols_rows()

        if not select(
                self.screen.get_input_descriptors(), [], [], 0.1)[0] == []:
            timeout, keys, raw = self.screen.get_input_nonblocking()

            for k in keys:
                if k == "window resize":
                    size = self.screen.get_cols_rows()
                    continue
                elif k == "enter":
                    self.processCommand(self.input.get_edit_text())
                    self.input.set_edit_text("")
                    continue

                self.top.keypress(size, k)
                self.input.set_edit_text(self.input.get_edit_text() + k)

        self.update_screen(size)

    def unknownCommand(self, command):
        self.lines.append(Text("Unknown command: %s" % command))

    def syntaxError(self, command, args, expected):
        self.lines.append(
            Text("Syntax error ({0:s}): {1:s} Expected: {2:s}".format(
                command, args, expected)
            )
        )

    def processCommand(self, s):  # noqa

        match = CMD_REGEX.match(s)
        if match is not None:

            command = match.groupdict()["command"]
            if not match.groupdict()["args"] == "":
                tokens = match.groupdict()["args"].split(" ")
            else:
                tokens = []

            fn = "cmd" + command.upper()
            if hasattr(self, fn):
                f = getattr(self, fn)
                if callable(f):

                    args, vargs, kwargs, default = getargspec(f)
                    args.remove("self")
                    if len(args) == len(tokens):
                        if len(args) == 0:
                            f()
                        else:
                            f(*tokens)
                    else:
                        if len(tokens) > len(args):
                            if vargs is None:
                                if len(args) > 0:
                                    factor = len(tokens) - len(args) + 1
                                    f(*back_merge(tokens, factor))
                                else:
                                    self.syntaxError(
                                        command, " ".join(tokens),
                                        " ".join(
                                            x for x in args + [vargs]
                                            if x is not None
                                        )
                                    )
                            else:
                                f(*tokens)
                        elif default is not None and \
                                len(args) == (
                                    len(tokens) + len(default)):
                            f(*(tokens + list(default)))
                        else:
                            self.syntaxError(
                                command,
                                " ".join(tokens),
                                " ".join(
                                    x for x in args + [vargs]
                                    if x is not None
                                )
                            )
        else:
            if self.ircchannel is not None:
                self.lines.append(Text("<%s> %s" % (self.nick, s)))
                self.fire(PRIVMSG(self.ircchannel, s))
            else:
                self.lines.append(Text(
                    "No channel joined. Try /join #<channel>"))

    def cmdEXIT(self, message=""):
        self.fire(QUIT(message))
        raise SystemExit(0)

    def cmdSERVER(self, host, port=6667):
        self.fire(connect(host, port))

    def cmdSSLSERVER(self, host, port=6697):
        self.fire(connect(host, port, secure=True))

    def cmdJOIN(self, channel):
        if self.ircchannel is not None:
            self.cmdPART(self.ircchannel, "Joining %s" % channel)
        self.fire(JOIN(channel))
        self.ircchannel = channel

    def cmdPART(self, channel=None, message="Leaving"):
        if channel is None:
            channel = self.ircchannel
        if channel is not None:
            self.fire(PART(channel, message))
            self.ircchannel = None

    def cmdQUOTE(self, message):
        self.fire(request(Message(message)))

    def cmdQUIT(self, message="Bye"):
        self.fire(QUIT(message))

    def update_screen(self, size):
        canvas = self.top.render(size, focus=True)
        self.screen.draw_screen(size, canvas)

    @handler("notice", "privmsg")
    def _on_notice_or_privmsg(self, event, source, target, message):
        nick, ident, host = source

        if event.name == "notice":
            self.lines.append(Text("-%s- %s" % (nick, message)))
        else:
            self.lines.append(Text("<%s> %s" % (nick, message)))
示例#17
0
class LoginWindow(WidgetWrap):

    signals = ['login', 'logout']

    def __init__(self, app, extra=None, get_user=None, max_time=30):
        self.app = app

        self.extra = extra
        self.get_user = get_user
        self.max_time = max_time
        self._create_widgets()

        self._out_count = 0
        self._evt_time = 0
        self._parent = None
        self._key_sig_id = None
        self._timeout_sig_id = None

        self.__super.__init__(self.login_widget)

    def _create_widgets(self):
        self._create_login_widget()

        if self.extra:
            widget = Frame(LineBox(self.login_widget), footer=self.extra)
        else:
            widget = LineBox(self.login_widget)

        self.overlay = Overlay(
            widget, None,
            'center', ('relative', 100),
            'middle', ('relative', 100),
        )

    def _create_login_widget(self):
        self.username_entry = Edit(align='right')
        self.username_entry.keypress = self._username_keypress
        self.password_entry = Password(align='right')
        self.password_entry.keypress = self._password_keypress

        username_row = Columns([
            ('fixed', 10, Text("Usuario:", align='right')),
            ('fixed', 10, self.username_entry),
        ])

        password_row = Columns([
            ('fixed', 10, Text("Clave:", align='right')),
            ('fixed', 10, self.password_entry),
        ])

        self.pile = Pile([
            username_row,
            Divider(),
            password_row,
        ], focus_item=0)

        self.login_widget = Filler(Columns([Divider(), self.pile, Divider()]))

    def show(self):
        """Show login window"""
        #self.pile.set_focus(0)
        self.clear()
        loop = self.app.loop
        self.overlay.bottom_w = loop.widget
        loop.widget = self.overlay
        if loop.screen.started:
            loop.draw_screen()

    def hide(self):
        """Hide login window"""
        loop = self.app.loop
        loop.widget = self.overlay.bottom_w
        if loop.screen.started:
            loop.draw_screen()

    def login(self, user):
        """
        Login the session, showing all content and hidding login window.
        """
        # connect esc-esc signal to logout
        widget = self.overlay.bottom_w
        widget.orig_keypress = widget.keypress
        widget.keypress = self._wrapped_keypress

        self._last_key_time = time.time()
        self._timeout_sig_id = self.app.loop.set_alarm_in(self.max_time+1,
                                                          self._check_logout)

        if hasattr(widget, 'set_user') and callable(widget.set_user):
            widget.set_user(user)
        self.hide()
        self._emit("login")

    def logout(self):
        """Logout the session, hidding all content and showing login window
        again.
        """
        # disconnect esc-esc signal
        self.app.loop.widget.keypress = self.app.loop.widget.orig_keypress

        self.app.loop.remove_alarm(self._timeout_sig_id)
        self.show()
        self._emit("logout")

    def clear(self):
        self.username_entry.set_edit_text("")
        self.password_entry.set_edit_text("")
        self.pile.set_focus(0)

    def _wrapped_keypress(self, size, key):
        self._last_key_time = time.time()
        if key == 'esc':
            if self._out_count == 1 and (time.time() - self._evt_time) < 1:
                self._out_count = 0
                self._evt_time = 0
                self.logout()
            else:
                self._out_count = 1
                self._evt_time = time.time()
            return None
        else:
            return self.app.loop.widget.orig_keypress(size, key)

    def _username_keypress(self, size, key):
        if key == 'enter':
            key = 'down'
        return self.username_entry.__class__.keypress(self.username_entry, size, key)

    def _password_keypress(self, size, key):
        if key == 'enter':
            password = self.password_entry.get_edit_text()
            username = self.username_entry.get_edit_text()
            self.password_entry.set_edit_text("")
            if password and username:
                user = self.get_user(username, password)
                if user:
                    #self.username_entry.set_edit_text("")
                    self.login(user)
            return
        return self.password_entry.__class__.keypress(self.password_entry, size, key)

    def _check_logout(self, main_loop, user_data=None):
        etime = int(time.time() - self._last_key_time)
        if etime >= self.max_time:
            self.logout()
        else:
            main_loop.remove_alarm(self._timeout_sig_id)
            self._timeout_sig_id = main_loop.set_alarm_in(self.max_time-etime, self._check_logout)
        return False
示例#18
0
文件: ui.py 项目: ripperbone/turses
class BaseEditor(with_metaclass(signals.MetaSignals, WidgetWrap)):
    """Base class for editors."""
    signals = ['done']

    def __init__(self,
                 prompt,
                 content,
                 done_signal_handler,
                 cursor_position=None):
        """
        Initializes editor, connects 'done' signal.

        When pressing 'enter' twice the `submit` method is called, which by
        default calls `emit_done_signal` with the text that has been
        introduced.

        When pressing 'esc' the `cancel` method is called, which by default
        calls `emit_done_signal` with no arguments.

        The subclasses must call the `_wrap` method with the editor widgets
        and `BaseEditor` will wrap it in a `urwid.Colums` widget, calling to
        `urwid.WidgetWrap.__init__` with the wrapped widget.
        """
        caption = _(u'{0} (Enter key twice to validate, '
                    u'Esc or Ctrl-C to cancel) \n>> ').format(prompt)
        if content:
            content += ' '
        self.content = content
        self.editor = Edit(caption=caption,
                           edit_text=content,
                           edit_pos=cursor_position)
        self.last_key = None

        connect_signal(self, 'done', done_signal_handler)

    def _wrap(self, widgets):
        widgets = widgets if isinstance(widgets, list) else [widgets]
        composed_widget = Columns(widgets)

        widget = AttrMap(LineBox(composed_widget), 'editor')
        super(BaseEditor, self).__init__(widget)

    def keypress(self, size, key):
        if key == 'enter' and self.last_key == 'enter':
            self.submit()
            return
        elif key == 'esc':
            self.cancel()
            return

        self.last_key = key
        size = size,
        self.editor.keypress(size, key)

    def submit(self):
        self.emit_done_signal(self.editor.get_edit_text())

    def cancel(self):
        self.emit_done_signal()

    def emit_done_signal(self, content=None):
        emit_signal(self, 'done', content)
示例#19
0
class Client(Component):

    channel = "client"

    def init(self, host, port=6667, opts=None):
        self.host = host
        self.port = port
        self.opts = opts
        self.hostname = gethostname()

        self.nick = opts.nick
        self.ircchannel = opts.channel

        # Add TCPClient and IRC to the system.
        TCPClient(channel=self.channel).register(self)
        IRC(channel=self.channel).register(self)

        self.create_interface()

    def create_interface(self):
        self.screen = Screen()
        self.screen.start()

        self.screen.register_palette([
            ("title", "white", "dark blue", "standout"),
            ("line", "light gray", "black"),
            ("help", "white", "dark blue")]
        )

        self.body = ListBox(SimpleListWalker([]))
        self.lines = self.body.body

        self.title = Text(MAIN_TITLE)
        self.header = AttrWrap(self.title, "title")

        self.help = AttrWrap(
            Text(HELP_STRINGS["main"]),
            "help"
        )

        self.input = Edit(caption="%s> " % self.ircchannel)
        self.footer = Pile([self.help, self.input])

        self.top = Frame(self.body, self.header, self.footer)

    def ready(self, component):
        """Ready Event

        This event is triggered by the underlying ``TCPClient`` Component
        when it is ready to start making a new connection.
        """

        self.fire(connect(self.host, self.port))

    def connected(self, host, port):
        """connected Event

        This event is triggered by the underlying ``TCPClient`` Component
        when a successfully connection has been made.
        """

        nick = self.nick
        hostname = self.hostname
        name = "%s on %s using circuits/%s" % (nick, hostname, systemVersion)

        self.fire(NICK(nick))
        self.fire(USER(nick, hostname, host, name))

    def numeric(self, source, numeric, *args):
        """Numeric Event

        This event is triggered by the ``IRC`` Protocol Component when we have
        received an IRC Numberic Event from server we are connected to.
        """

        if numeric == ERR_NICKNAMEINUSE:
            self.fire(NICK("{0:s}_".format(args[0])))
        elif numeric in (RPL_ENDOFMOTD, ERR_NOMOTD):
            self.fire(JOIN(self.ircchannel))

    @handler("stopped", channel="*")
    def _on_stopped(self, component):
        self.screen.stop()

    @handler("generate_events")
    def _on_generate_events(self, event):
        event.reduce_time_left(0)

        size = self.screen.get_cols_rows()

        if not select(
                self.screen.get_input_descriptors(), [], [], 0.1)[0] == []:
            timeout, keys, raw = self.screen.get_input_nonblocking()

            for k in keys:
                if k == "window resize":
                    size = self.screen.get_cols_rows()
                    continue
                elif k == "enter":
                    self.processCommand(self.input.get_edit_text())
                    self.input.set_edit_text("")
                    continue

                self.top.keypress(size, k)
                self.input.set_edit_text(self.input.get_edit_text() + k)

        self.update_screen(size)

    def unknownCommand(self, command):
        self.lines.append(Text("Unknown command: %s" % command))

    def syntaxError(self, command, args, expected):
        self.lines.append(
            Text("Syntax error ({0:s}): {1:s} Expected: {2:s}".format(
                command, args, expected)
            )
        )

    def processCommand(self, s):  # noqa

        match = CMD_REGEX.match(s)
        if match is not None:

            command = match.groupdict()["command"]
            if not match.groupdict()["args"] == "":
                tokens = match.groupdict()["args"].split(" ")
            else:
                tokens = []

            fn = "cmd" + command.upper()
            if hasattr(self, fn):
                f = getattr(self, fn)
                if callable(f):

                    args, vargs, kwargs, default = getargspec(f)
                    args.remove("self")
                    if len(args) == len(tokens):
                        if len(args) == 0:
                            f()
                        else:
                            f(*tokens)
                    else:
                        if len(tokens) > len(args):
                            if vargs is None:
                                if len(args) > 0:
                                    factor = len(tokens) - len(args) + 1
                                    f(*back_merge(tokens, factor))
                                else:
                                    self.syntaxError(
                                        command, " ".join(tokens),
                                        " ".join(
                                            x for x in args + [vargs]
                                            if x is not None
                                        )
                                    )
                            else:
                                f(*tokens)
                        elif default is not None and \
                                len(args) == (
                                    len(tokens) + len(default)):
                            f(*(tokens + list(default)))
                        else:
                            self.syntaxError(
                                command,
                                " ".join(tokens),
                                " ".join(
                                    x for x in args + [vargs]
                                    if x is not None
                                )
                            )
        else:
            if self.ircchannel is not None:
                self.lines.append(Text("<%s> %s" % (self.nick, s)))
                self.fire(PRIVMSG(self.ircchannel, s))
            else:
                self.lines.append(Text(
                    "No channel joined. Try /join #<channel>"))

    def cmdEXIT(self, message=""):
        self.fire(QUIT(message))
        raise SystemExit(0)

    def cmdSERVER(self, host, port=6667):
        self.fire(connect(host, port))

    def cmdSSLSERVER(self, host, port=6697):
        self.fire(connect(host, port, secure=True))

    def cmdJOIN(self, channel):
        if self.ircchannel is not None:
            self.cmdPART(self.ircchannel, "Joining %s" % channel)
        self.fire(JOIN(channel))
        self.ircchannel = channel

    def cmdPART(self, channel=None, message="Leaving"):
        if channel is None:
            channel = self.ircchannel
        if channel is not None:
            self.fire(PART(channel, message))
            self.ircchannel = None

    def cmdQUOTE(self, message):
        self.fire(request(Message(message)))

    def cmdQUIT(self, message="Bye"):
        self.fire(QUIT(message))

    def update_screen(self, size):
        canvas = self.top.render(size, focus=True)
        self.screen.draw_screen(size, canvas)

    @handler("notice", "privmsg")
    def _on_notice_or_privmsg(self, event, source, target, message):
        nick, ident, host = source

        if event.name == "notice":
            self.lines.append(Text("-%s- %s" % (nick, message)))
        else:
            self.lines.append(Text("<%s> %s" % (nick, message)))
示例#20
0
class BaseEditor(WidgetWrap, metaclass=signals.MetaSignals):
    """Base class for editors."""
    signals = ['done']

    def __init__(self,
                 prompt,
                 content,
                 done_signal_handler,
                 cursor_position=None):
        """
        Initializes editor, connects 'done' signal.

        When pressing 'enter' twice the `submit` method is called, which by
        default calls `emit_done_signal` with the text that has been
        introduced.

        When pressing 'esc' the `cancel` method is called, which by default
        calls `emit_done_signal` with no arguments.

        The subclasses must call the `_wrap` method with the editor widgets
        and `BaseEditor` will wrap it in a `urwid.Colums` widget, calling to
        `urwid.WidgetWrap.__init__` with the wrapped widget.
        """
        caption = _(u'{0} (Enter key twice to validate, '
                    u'Esc or Ctrl-C to cancel) \n>> ').format(prompt)
        if content:
            content += ' '
        self.content = content
        self.editor = Edit(caption=caption,
                           edit_text=content,
                           edit_pos=cursor_position)
        self.last_key = None

        connect_signal(self, 'done', done_signal_handler)

    def _wrap(self, widgets):
        widgets = widgets if isinstance(widgets, list) else [widgets]
        composed_widget = Columns(widgets)

        widget = AttrMap(LineBox(composed_widget), 'editor')
        super(BaseEditor, self).__init__(widget)

    def keypress(self, size, key):
        if key == 'enter' and self.last_key == 'enter':
            self.submit()
            return
        elif key == 'esc':
            self.cancel()
            return

        self.last_key = key
        size = size,
        self.editor.keypress(size, key)

    def submit(self):
        self.emit_done_signal(self.editor.get_edit_text())

    def cancel(self):
        self.emit_done_signal()

    def emit_done_signal(self, content=None):
        emit_signal(self, 'done', content)