Example #1
0
def set_subscription_tags(session, term):
    """
    This function is called to assign a new set of subscription
    tags for a user.  If escape is pressed, the existing value
    is used, or '*' is used if not previously set.

    This should be called for first-time users, and optionally
    at any later time to change a subscription.
    """

    line_no = display_banner(art_file, encoding=art_encoding)

    # introduce the user to the concept ...
    description = (
        u"{term.yellow}You can think of tags as a system of providing "
        u"context to any message stored on this system.  A tag might signify "
        u"that it was received on a particular message network, or it might "
        u"provide the topic of conversation, such as "
        u"{term.bold_yellow}python{term.normal}{term.yellow} or "
        u"{term.bold_yellow}rock music{term.normal}{term.yellow}.  "
        u"This is similar to flicker's tags, or twitter hashtags. "
        u"Use glob expressions as a comma-delimited list, for example, "
        u"the expression {term.bold_yellow}x84net{term.normal}{term.yellow}, "
        u"{term.bold_yellow}sysop{term.normal}{term.yellow}, "
        u"{term.bold_yellow}python*{term.normal}{term.yellow} "
        u"will subscribe to all tags of the x84net message network, "
        u"sysop messages, and any topics that begin with the phrase "
        u"{term.bold_yellow}python{term.normal}{term.yellow}.  You can "
        u"subscribe to all topics using the expression, "
        u"{term.bold_yellow}*{term.normal}{term.yellow}.".format(term=term)
    )

    echo(u"\r\n")
    line_no += 1

    line_no += show_description(description, color=None)

    description = u" ".join(
        [u"tags available:"] + ["{tag}{term.yellow},{term.normal}".format(tag=tag, term=term) for tag in list_tags()]
    )

    echo(u"\r\n\r\n")
    line_no += 2

    # display our prompt prefix, input_prefix:
    input_prefix = u"  {sep} {key:>18}: ".format(sep=term.bright_yellow(u"::"), key="subscription tags")
    echo(input_prefix)

    xloc = term.length(input_prefix)

    # and prompt an editor on that row
    editor = ScrollingEditor(
        xloc=xloc, yloc=line_no, width=(term.width - xloc - 2), colors={"highlight": term.black_on_yellow}
    )

    value = editor.read() or u""
    echo(term.normal + u"\r\n\r\n")

    return map(unicode.strip, value.split(","))
Example #2
0
def get_inputbar(pager):
    """ Return ScrollingEditor for use as inputbar. """
    from x84.bbs import getterminal, ScrollingEditor
    term = getterminal()
    width = pager.visible_width - 2
    yloc = (pager.yloc + pager.height) - 2
    xloc = pager.xloc + 2
    ibar = ScrollingEditor(width, yloc, xloc)
    ibar.enable_scrolling = True
    ibar.max_length = 512
    ibar.colors['highlight'] = term.cyan_reverse
    return ibar
Example #3
0
File: ircchat.py Project: hick/x84
def get_inputbar(pager):
    """ Return ScrollingEditor for use as inputbar. """
    from x84.bbs import getterminal, ScrollingEditor
    term = getterminal()
    width = pager.visible_width - 2
    yloc = (pager.yloc + pager.height) - 2
    xloc = pager.xloc + 2
    ibar = ScrollingEditor(width=width, yloc=yloc, xloc=xloc)
    ibar.enable_scrolling = True
    ibar.max_length = 512
    ibar.colors['highlight'] = term.white_on_blue
    return ibar
Example #4
0
def main():
    """ x/84 script launch point """

    term, session = getterminal(), getsession()
    session.activity = u'Chatting on IRC'

    # move to bottom of screen, reset attribute
    echo(term.pos(term.height) + term.normal)

    # create a new, empty screen
    echo(u'\r\n' * (term.height + 1))

    # move to home, set font
    echo(term.home)
    if SYNCTERM_FONT and term.kind.startswith('ansi'):
        echo(syncterm_setfont(SYNCTERM_FONT))

    scrollback = collections.deque(maxlen=MAX_SCROLLBACK)
    client = establish_connection(term, session)
    if not client:
        return clean_up(term)
    # ignore "not in view" warning for AnsiWindow
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        editor = ScrollingEditor(
            width=term.width + 1,
            xloc=-1,
            yloc=term.height - 2,
            colors={'highlight': getattr(term, COLOR_INPUTBAR)},
            max_length=MAX_INPUT
        )

    # delete 'Connecting' message
    echo(u''.join([term.home, term.clear, editor.refresh()]))

    while True:
        client.reactor.process_once()
        event, data = session.read_events(
            ('irc-quit', 'irc', 'input', 'refresh'), timeout=0.1)
        if event == 'refresh':
            refresh_event(term, scrollback, editor)
            continue
        elif event == 'irc':
            irc_event(term, data, scrollback, editor)
        elif event == 'input':
            if not input_event(term, session, client, data, editor):
                break
        elif event == 'irc-quit':
            time.sleep(0.5)
            break
    client.connection.disconnect()
    clean_up(term)
Example #5
0
def get_lneditor(lightbar):
    """ Returns editor positioned at location of current selection. """
    term = getterminal()
    width = min(80, max(term.width, 40))
    yloc = (lightbar.yloc + lightbar.ypadding + lightbar.position[0] - 1)
    xloc = max(0, (term.width / 2) - (width / 2))
    lneditor = ScrollingEditor(width=width, yloc=yloc, xloc=xloc)
    lneditor.enable_scrolling = True
    lneditor.max_length = 65534
    lneditor.glyphs['bot-horiz'] = u''
    lneditor.glyphs['top-horiz'] = u''
    lneditor.colors['highlight'] = term.red_reverse
    lneditor.colors['border'] = term.bold_red
    # converts u'xxxxxx\r\n' to 'xxxxxx',
    # or 'zzzz\nxxxxxx\n' to u'zzzz xxxxxx',
    lneditor.update(softwrap_join(wrap_rstrip(lightbar.selection[1])))
    return lneditor
Example #6
0
def main():
    """ x/84 script launch point """

    term, session = getterminal(), getsession()
    session.activity = u'Chatting on IRC'
    session.flush_event('irc')

    # move to bottom of screen, reset attribute
    echo(term.pos(term.height) + term.normal)

    # create a new, empty screen
    echo(u'\r\n' * (term.height + 1))
    echo(term.home + term.clear)

    # set font
    if SYNCTERM_FONT and term.kind.startswith('ansi'):
        echo(syncterm_setfont(SYNCTERM_FONT))

    try:
        client, scrollback = establish_connection(term, session)
    except EOFError:
        # connection failed,
        return clean_up(term)

    # ignore "not in view" warning for AnsiWindow
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        editor = ScrollingEditor(
            width=term.width + 1,
            xloc=-1,
            yloc=term.height,
            colors={'highlight': getattr(term, COLOR_INPUTBAR)},
            max_length=MAX_INPUT
        )

    refresh_event(term, scrollback, editor)

    while True:
        client.reactor.process_once()
        event, data = session.read_events(
            ('irc-quit', 'irc', 'input', 'refresh'), timeout=0.1)
        if event == 'refresh':
            refresh_event(term, scrollback, editor)
            continue
        elif event == 'irc':
            irc_event(term, data, scrollback, editor)
        elif event == 'input':
            session.buffer_input(data, pushback=True)
            if not input_event(term, client, editor):
                break
        elif event == 'irc-quit':
            time.sleep(0.5)
            break
    client.connection.disconnect()
    clean_up(term)
Example #7
0
def make_editor_series(winsize, editors):
    colors = {'highlight': u''}
    # prevent horizontal scrolling prior to final column
    margin_pct = 100 - (100 / (winsize.width - 3))
    # scroll at final column
    scroll_pct = 100 / (winsize.width - 3)
    return [
        ScrollingEditor(
            yloc=_yloc, xloc=winsize.xloc, width=winsize.width,
            colors=colors, margin_pct=margin_pct, scroll_pct=scroll_pct,
            content=(u'' if not editors or _idx >= len(editors)
                     else editors[_idx].content),
            max_length=winsize.width
        ) for _idx, _yloc in enumerate(range(
            winsize.yloc, winsize.yloc + winsize.height + -2))]
Example #8
0
def do_command(term, session, inp, fields, tgt_user, point):
    """ Perform action by given input. """
    _color1, _color2, _color3 = [
        getattr(term, _color)
        for _color in (color_lowlight, color_highlight, color_field_edit)
    ]

    # discover edit field by matching command key
    field_name = None
    for _fname, field in fields.items():
        if field.key == inp.lower():
            field_name = _fname
            break

    if field_name is None:
        # return False if no field matches this key
        return False

    # only 'sysop' may edit user groups
    if field_name == 'groups' and not session.user.is_sysop:
        return False

    # pylint: disable=W0631
    #         Using possibly undefined loop variable 'field'

    # TODO: we could probably stand to do a bit of a better job of detecting
    # screen resizes and providing ^L full-screen refresh during the remainder
    # of this procedure ... It would require quite the refactor, though.

    # special case; ssh public keys and groups use scrolling editor
    if field_name in ('pubkey', 'groups'):
        editor = ScrollingEditor(
            # issue #161; because of a 'border' (that we don't draw),
            # y must be offset by 1 and height by 2.
            yloc=field.edit_location.y - 1,
            xloc=field.edit_location.x - 1,
            width=field.width + 2,
            colors={'highlight': _color3})
        # limit input to 1K
        editor.max_length = 1024
    else:
        editor = LineEditor(field.width, colors={'highlight': _color3})

    # find width for displaying description text and validation errors
    width = term.width - (point.x * 2)

    # show field description and cancellation
    description = (field.description or u'') + '  Press escape to cancel.'
    description_text = term.wrap(description, width=width)
    for y_offset, txt in enumerate(description_text):
        echo(term.move(point.y + y_offset, point.x))
        echo(_color1(txt) + term.clear_eol)
    echo(term.clear_eos)

    # edit input field (occludes display field).
    echo(term.move(*field.edit_location))
    inp = editor.read()
    if inp is None:
        # escape was pressed
        echo(term.move(*point))
        echo(_color2('Canceled !') + term.clear_eos)
        time.sleep(1)
        return True

    else:
        # validate input
        if field.validate_fn is not None:
            errmsg, _ = field.validate_fn(tgt_user, inp)
            if errmsg:
                # failed validation, display validation error
                errmsg += '  Press any key.'
                for y_offset, txt in enumerate(term.wrap(errmsg, width=width)):
                    echo(term.move(point.y + y_offset, point.x))
                    echo(_color2(txt) + term.clear_eol)
                echo(term.clear_eos)
                term.inkey()
                return True

        # well, it has validated, shall we apply it, then?
        if field_name in (
                'password',
                'location',
                'email',
        ):
            # except for anonymous,
            if tgt_user.handle != 'anonymous':
                setattr(tgt_user, field_name, inp)
        elif field_name in (
                'timeout',
                'pubkey',
        ):
            if field_name == 'timeout':
                # coerce to integer, set, and if tgt_user is our current
                # user, then send new value for as engine event
                try:
                    timeout_val = int(inp)
                except ValueError:
                    return True
                if tgt_user.handle != 'anonymous':
                    tgt_user[field_name] = timeout_val
                if tgt_user.handle == session.user.handle:
                    session.send_event('set-timeout', timeout_val)
            elif field_name == 'pubkey':
                if tgt_user.handle != 'anonymous':
                    tgt_user[field_name] = inp
        elif field_name in ('groups'):
            new_groups = set(
                filter(None, set(map(unicode.strip, inp.split(',')))))
            for old_grp in tgt_user.groups.copy():
                if old_grp not in new_groups:
                    tgt_user.group_del(old_grp)
            for new_grp in new_groups:
                if new_grp not in tgt_user.groups:
                    tgt_user.group_add(new_grp)
        else:
            raise ValueError('unknown field name: {0}'.format(field_name))
    if tgt_user.handle != 'anonymous':
        tgt_user.save()
    return True
Example #9
0
def prompt_subscription(session, term, yloc, subscription, colors):
    """
    This function is called to assign a new set of subscription
    tags for a user.  If escape is pressed, the existing value
    is used, or '*' is used if not previously set.

    This should be called for first-time users, and optionally
    at any later time to change a subscription.
    """

    if session.user.get('msg_subscription', None) is None:
        # force-display introductory description for first-time users.
        yloc += do_describe_message_system(term, colors)
        echo(u'\r\n\r\n')
        yloc += 2

    # remind ourselves of all available tags
    yloc += do_describe_available_tags(term, colors) + 2

    # for small screens, scroll and leave room for prompt & errors
    if yloc > term.height + 3:
        echo(u'\r\n' * 3)
        yloc = term.height - 3

    # and prompt for setting of message tags
    xloc = max(0, (term.width // 2) - 40)
    input_prefix = u':: subscription tags:'
    echo(u''.join((term.move(yloc, xloc), input_prefix)))

    xloc += len(input_prefix)
    wide = min(40, (term.width - xloc - 2))

    while True:
        editor = ScrollingEditor(xloc=xloc,
                                 yloc=yloc - 1,
                                 width=wide,
                                 colors={'highlight': colors['backlight']},
                                 content=u', '.join(subscription),
                                 max_length=100)

        # Prompt for and evaluate the given input, splitting by comma,
        # removing any empty items, and defaulting to ['*'] on escape.
        inp = editor.read() or u''
        subscription = filter(None, set(map(unicode.strip,
                                            inp.split(',')))) or set([u'*'])

        # Then, reduce to only validate tag patterns, tracking those
        # that do not match any known tags, and display a warning and
        # re-prompt if any are removed.
        removed, subscription = validate_tag_patterns(subscription)

        # clear existing warning, if any
        echo(u''.join((term.normal, u'\r\n\r\n', term.clear_eos)))
        if removed:
            # and display any unmatched tags as a warning, re-prompt
            txt = ''.join(
                (term.bold_red(u"The following patterns are not matched: "),
                 u', '.join(removed)))
            show_description(term, txt, color=None)
            continue

        # otherwise everything is fine,
        # return new subscription set
        return subscription
Example #10
0
def do_command(term, session, inp, fields, tgt_user, point):
    """ Perform action by given input. """
    _color1, _color2, _color3 = [
        getattr(term, _color) for _color in (
            color_lowlight, color_highlight, color_field_edit)]

    # discover edit field by matching command key
    field_name = None
    for _fname, field in fields.items():
        if field.key == inp.lower():
            field_name = _fname
            break

    if field_name is None:
        # return False if no field matches this key
        return False

    # only 'sysop' may edit user groups
    if field_name == 'groups' and not session.user.is_sysop:
        return False

    # pylint: disable=W0631
    #         Using possibly undefined loop variable 'field'

    # TODO: we could probably stand to do a bit of a better job of detecting
    # screen resizes and providing ^L full-screen refresh during the remainder
    # of this procedure ... It would require quite the refactor, though.

    # special case; ssh public keys and groups use scrolling editor
    if field_name in ('pubkey', 'groups'):
        editor = ScrollingEditor(
            # issue #161; because of a 'border' (that we don't draw),
            # y must be offset by 1 and height by 2.
            yloc=field.edit_location.y - 1,
            xloc=field.edit_location.x - 1,
            width=field.width + 2,
            colors={'highlight': _color3})
        # limit input to 1K
        editor.max_length = 1024
    else:
        editor = LineEditor(field.width, colors={'highlight': _color3})

    # find width for displaying description text and validation errors
    width = term.width - (point.x * 2)

    # show field description and cancellation
    description = (field.description or u'') + '  Press escape to cancel.'
    description_text = term.wrap(description, width=width)
    for y_offset, txt in enumerate(description_text):
        echo(term.move(point.y + y_offset, point.x))
        echo(_color1(txt) + term.clear_eol)
    echo(term.clear_eos)

    # edit input field (occludes display field).
    echo(term.move(*field.edit_location))
    inp = editor.read()
    if inp is None:
        # escape was pressed
        echo(term.move(*point))
        echo(_color2('Canceled !') + term.clear_eos)
        time.sleep(1)
        return True

    else:
        # validate input
        if field.validate_fn is not None:
            errmsg, _ = field.validate_fn(tgt_user, inp)
            if errmsg:
                # failed validation, display validation error
                errmsg += '  Press any key.'
                for y_offset, txt in enumerate(term.wrap(errmsg, width=width)):
                    echo(term.move(point.y + y_offset, point.x))
                    echo(_color2(txt) + term.clear_eol)
                echo(term.clear_eos)
                term.inkey()
                return True

        # well, it has validated, shall we apply it, then?
        if field_name in ('password', 'location', 'email',):
            # except for anonymous,
            if tgt_user.handle != 'anonymous':
                setattr(tgt_user, field_name, inp)
        elif field_name in ('timeout', 'pubkey',):
            if field_name == 'timeout':
                # coerce to integer, set, and if tgt_user is our current
                # user, then send new value for as engine event
                timeout_val = int(inp)
                if tgt_user.handle != 'anonymous':
                    tgt_user[field_name] = timeout_val
                if tgt_user.handle == session.user.handle:
                    session.send_event('set-timeout', timeout_val)
            elif field_name == 'pubkey':
                if tgt_user.handle != 'anonymous':
                    tgt_user[field_name] = inp
        elif field_name in ('groups'):
            new_groups = set(filter(None, set(map(unicode.strip, inp.split(',')))))
            for old_grp in tgt_user.groups.copy():
                if old_grp not in new_groups:
                    tgt_user.group_del(old_grp)
            for new_grp in new_groups:
                if new_grp not in tgt_user.groups:
                    tgt_user.group_add(new_grp)
        else:
            raise ValueError('unknown field name: {0}'.format(field_name))
    if tgt_user.handle != 'anonymous':
        tgt_user.save()
    return True
Example #11
0
def process_keystroke(inp, user):
    """ Process keystroke, ``inp``, for target ``user``. """
    # pylint: disable=R0914,R0912,R0915,R0911,W0603
    #         Too many local variables
    #         Too many branches
    #         Too many statements
    #         Too many return statements
    #         Using the global statement
    # ^ lol, this is one of those things that should be
    #   refactored into smaller subroutines =)
    from x84.bbs import getsession, getterminal, echo, getch, gosub
    from x84.bbs import LineEditor, ScrollingEditor
    from x84.default.nua import set_email, set_location
    from x84.bbs.ini import CFG
    def_timeout = CFG.getint('system', 'timeout')
    global EXIT
    session, term = getsession(), getterminal()
    is_self = bool(user.handle == session.user.handle)
    invalid = u'\r\niNVAlid.'
    assert is_self or 'sysop' in session.user.groups

    if is_self and inp in (u'c', u'C'):
        gosub('charset')

    elif is_self and inp in (u't', u'T'):
        echo(term.move(term.height - 1, 0))
        echo(ABOUT_TERM + u'\r\n')
        echo(u'\r\ntERMiNAl tYPE: ')
        term = LineEditor(30, session.env.get('TERM')).read()
        echo(u"\r\n\r\nset TERM to '%s'? [yn]" % (term,))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                session.env['TERM'] = term
                break
            elif inp2 in (u'n', u'N'):
                break

    elif is_self and inp in (u'w', u'W'):
        echo(u'\r\ntERMiNAl Width: ')
        width = LineEditor(3, str(term.width)).read()
        try:
            width = int(width)
        except ValueError:
            echo(invalid)
            return True
        if width < 0 or width > 999:
            echo(invalid)
            return True
        echo(u"\r\n\r\nset COLUMNS=%d? [yn]" % (width,))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                term.columns = width
                break
            elif inp2 in (u'n', u'N'):
                break

    elif is_self and inp in (u'h', u'H'):
        echo(u'\r\ntERMiNAl hEiGht: ')
        height = LineEditor(3, str(term.height)).read()
        try:
            height = int(height)
        except ValueError:
            echo(invalid)
            return True
        if height < 0 or height > 999:
            echo(invalid)
            return True
        echo(u"\r\n\r\nset LINES=%d? [yn]" % (height,))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                term.rows = height
                break
            elif inp2 in (u'n', u'N'):
                break

    elif 'sysop' in session.user.groups and inp in (u'd', u'D',):
        echo(u"\r\n\r\ndElEtE %s ? [yn]" % (user.handle,))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                user.delete()
                break
            elif inp2 in (u'n', u'N'):
                break
        EXIT = True

    elif 'sysop' in session.user.groups and inp in (u's', u'S',):
        sysop = not 'sysop' in user.groups
        echo(u"\r\n\r\n%s SYSOP ACCESS? [yn]" % (
            'ENAblE' if sysop else 'diSAblE',))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                if sysop:
                    user.groups.add('sysop')
                else:
                    user.groups.remove('sysop')
                user.save()
                break
            elif inp2 in (u'n', u'N'):
                break
    elif inp in (u'p', u'P'):
        from x84.default.nua import set_password
        set_password(user)
        echo(u"\r\n\r\nSEt PASSWORd ? [yn]")
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                user.save()
                break
            elif inp2 in (u'n', u'N'):
                break
    elif inp in (u'k', 'K',):
        change = True
        if user.get('pubkey', False):
            echo(u"\r\n\r\nSSh PUbliC kEY AlREAdY SEt, ChANGE ? [yn]")
            while True:
                inp2 = getch()
                if inp2 in (u'y', u'Y'):
                    break
                elif inp2 in (u'n', u'N'):
                    change = False
                    break
        if change:
            echo(u"\r\n\r\njUSt PAStE iN YOUR PUbliC kEY, MAkE SURE itS "
                 u"All iN ONE lINE!\r\n\r\n\r\n")
            editor = ScrollingEditor(width=term.width - 6,
                                     yloc=term.height - 3,
                                     xloc=3)
            echo(term.reverse_yellow)
            pubkey = editor.read()
            echo(term.normal)
            if pubkey is not None:
                if not pubkey.strip():
                    if user.get('pubkey', None):
                        del user['pubkey']
                    echo(u'\r\n\r\nYOUR SECREtS ARE NEVER SAfE!\r\n')
                else:
                    echo(u'\r\n\r\nWElCOME tO thE bROthERhOOd!\r\n')
                    user['pubkey'] = pubkey
                user.save()
                getch(timeout=1.5)
            else:
                echo(u'\r\n\r\nCANCElEd!!\r\n')
                getch(timeout=0.5)

    elif inp in (u'.',):
        echo(term.move(0, 0) + term.normal + term.clear)
        echo(term.move(int(term.height * .8), 0))
        for line in term.wrap(ABOUT_DOT_PLAN, term.width / 3):
            echo(line.center(term.width).rstrip() + u'\r\n')
        echo(u'\r\n\r\nPRESS ANY kEY ...')
        getch()
        if is_self:
            gosub('editor', '.plan')
        else:
            tmpkey = '%s-%s' % (user.handle, user.plan)
            draft = user.get('.plan', u'')
            session.user[tmpkey] = draft
            gosub('editor', tmpkey)
            if session.user.get(tmpkey, u'') != draft:
                echo(u"\r\n\r\nSEt .PlAN ? [yn]")
                while True:
                    inp2 = getch()
                    if inp2 in (u'y', u'Y'):
                        user['.plan'] = session.user[tmpkey]
                        break
                    elif inp2 in (u'n', u'N'):
                        break
    elif inp in (u'l', u'L'):
        echo(term.move(term.height - 1, 0))
        set_location(user)
        echo(u"\r\n\r\nSEt lOCAtiON tO '%s'? [yn]" % (user.location,))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                user.save()
                break
            elif inp2 in (u'n', u'N'):
                break
    elif inp in (u'e', u'E'):
        echo(term.move(term.height - 1, 0))
        set_email(user)
        echo(u"\r\n\r\nSEt EMAil tO '%s'? [yn]" % (user.email,))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                user.save()
                break
            elif inp2 in (u'n', u'N'):
                break
    elif inp in (u'i', u'I'):
        echo(u'\r\ntiMEOUt (0=NONE): ')
        timeout = LineEditor(6, str(user.get('timeout', def_timeout))).read()
        try:
            timeout = int(timeout)
        except ValueError:
            echo(invalid)
            return True
        if timeout < 0:
            echo(invalid)
            return True
        echo(u"\r\n\r\nSet tiMEOUt=%s? [yn]" % (
            timeout if timeout else 'None',))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                user['timeout'] = timeout
                session.send_event('set-timeout', timeout)
                break
            elif inp2 in (u'n', u'N'):
                break

    elif inp in (u'm', u'M'):
        mesg = False if user.get('mesg', True) else True
        echo(u"\r\n\r\n%s iNStANt MESSAGiNG? [yn]" % (
            'ENAblE' if mesg else 'DiSAblE',))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                user['mesg'] = mesg
                break
            elif inp2 in (u'n', u'N'):
                break
    elif inp in (u'x', u'X'):
        expert = not user.get('expert', False)
        echo(u"\r\n\r\n%s EXPERt MOdE? [yn]" % (
            'ENAblE' if expert else 'DiSAblE',))
        while True:
            inp2 = getch()
            if inp2 in (u'y', u'Y'):
                user['expert'] = expert
                break
            elif inp2 in (u'n', u'N'):
                break
    elif inp in (u'q', u'Q',):
        EXIT = True
    else:
        return False
    return True
Example #12
0
def do_command(term, session, inp, fields, tgt_user, point):
    """ Perform action by given input. """
    _color1, _color2, _color3 = [
        getattr(term, _color) for _color in (color_lowlight, color_highlight, color_field_edit)
    ]

    # discover edit field by matching command key
    field_name = None
    for _fname, field in fields.items():
        if field.key == inp.lower():
            field_name = _fname
            break
    if field_name is None:
        # return False if no field matches this key
        return False

    # TODO: we could probably stand to do a bit of a better job of detecting
    # screen resizes and providing ^L full-screen refresh during the remainder
    # of this procedure ... It would require quite the refactor, though.

    # special case; ssh public keys require scrolling editor
    if field_name == "pubkey":
        editor = ScrollingEditor(
            # issue #161; because of a 'border' (that we don't draw),
            # y must be offset by 1 and height by 2.
            yloc=field.edit_location.y - 1,
            xloc=field.edit_location.x - 1,
            width=field.width + 2,
            colors={"highlight": _color3},
        )
        # limit input to 1K, scroll at final field character
        editor.max_length = 1024
    else:
        editor = LineEditor(field.width, colors={"highlight": _color3})

    # find width for displaying description text and validation errors
    width = term.width - (point.x * 2)

    # show field description and cancellation
    description = (field.description or u"") + "  Press escape to cancel."
    description_text = term.wrap(description, width=width)
    for y_offset, txt in enumerate(description_text):
        echo(term.move(point.y + y_offset, point.x))
        echo(_color1(txt) + term.clear_eol)
    echo(term.clear_eos)

    # edit input field (occludes display field).
    echo(term.move(*field.edit_location))
    inp = editor.read()
    if inp is None:
        # escape was pressed
        echo(term.move(*point))
        echo(_color2("Canceled !") + term.clear_eos)
        time.sleep(1)
        return True

    else:
        # validate input
        if field.validate_fn is not None:
            errmsg, _ = field.validate_fn(tgt_user, inp)
            if errmsg:
                # failed validation, display validation error
                errmsg += "  Press any key."
                for y_offset, txt in enumerate(term.wrap(errmsg, width=width)):
                    echo(term.move(point.y + y_offset, point.x))
                    echo(_color2(txt) + term.clear_eol)
                echo(term.clear_eos)
                term.inkey()
                return True

        # well, it has validated, shall we apply it, then?
        if field_name in ("password", "location", "email"):
            # except for anonymous,
            if tgt_user.handle != "anonymous":
                setattr(tgt_user, field_name, inp)
        elif field_name in ("timeout", "pubkey"):
            if field_name == "timeout":
                # coerce to integer, set, and if tgt_user is our current
                # user, then send new value for as engine event
                timeout_val = int(inp)
                if tgt_user.handle != "anonymous":
                    tgt_user[field_name] = timeout_val
                if tgt_user.handle == session.user.handle:
                    session.send_event("set-timeout", timeout_val)
            elif field_name == "pubkey":
                if tgt_user.handle != "anonymous":
                    tgt_user[field_name] = inp
        else:
            raise ValueError("unknown field.name: {0}".format(field.name))
    if tgt_user.handle != "anonymous":
        tgt_user.save()
    return True
Example #13
0
def prompt_subscription(session, term, yloc, subscription, colors):
    """
    This function is called to assign a new set of subscription
    tags for a user.  If escape is pressed, the existing value
    is used, or '*' is used if not previously set.

    This should be called for first-time users, and optionally
    at any later time to change a subscription.
    """

    if session.user.get('msg_subscription', None) is None:
        # force-display introductory description for first-time users.
        yloc += do_describe_message_system(term, colors)
        echo(u'\r\n\r\n')
        yloc += 2

    # remind ourselves of all available tags
    yloc += do_describe_available_tags(term, colors) + 2

    # for small screens, scroll and leave room for prompt & errors
    if yloc > term.height + 3:
        echo(u'\r\n' * 3)
        yloc = term.height - 3

    # and prompt for setting of message tags
    xloc = max(0, (term.width // 2) - 40)
    input_prefix = u':: subscription tags:'
    echo(u''.join((term.move(yloc, xloc), input_prefix)))

    xloc += len(input_prefix)
    wide = min(40, (term.width - xloc - 2))

    while True:
        editor = ScrollingEditor(xloc=xloc, yloc=yloc - 1, width=wide,
                                 colors={'highlight': colors['backlight']},
                                 content=u', '.join(subscription),
                                 max_length=100)

        # Prompt for and evaluate the given input, splitting by comma,
        # removing any empty items, and defaulting to ['*'] on escape.
        inp = editor.read() or u''
        subscription = filter(None, set(map(unicode.strip, inp.split(',')))
                              ) or set([u'*'])

        # Then, reduce to only validate tag patterns, tracking those
        # that do not match any known tags, and display a warning and
        # re-prompt if any are removed.
        removed, subscription = validate_tag_patterns(subscription)

        # clear existing warning, if any
        echo(u''.join((term.normal, u'\r\n\r\n', term.clear_eos)))
        if removed:
            # and display any unmatched tags as a warning, re-prompt
            txt = ''.join((
                term.bold_red(u"The following patterns are not matched: "),
                u', '.join(removed)))
            show_description(term, txt, color=None)
            continue

        # otherwise everything is fine,
        # return new subscription set
        return subscription