Example #1
0
def prompt_tags(session, term, msg, colors, public=True):
    xpos = max(0, (term.width // 2) - (80 // 2))

    # conditionally enforce tag moderation
    moderated = get_ini("msg", "moderated_tags", getter="getboolean")
    tag_moderators = set(get_ini("msg", "tag_moderators", split=True))

    # enforce 'public' tag
    if public and "public" not in msg.tags:
        msg.tags.add("public")
    elif not public and "public" in msg.tags:
        msg.tags.remove("public")

    # describe all available tags, as we oft want to do.
    do_describe_available_tags(term, colors)

    # and remind ourselves of the available network tags,
    description = get_network_tag_description(term, colors)
    if description:
        show_description(term=term, color=None, description=description)

    echo(
        u"".join(
            (term.move_x(xpos), term.clear_eos, u"Enter tags, separated by commas.\r\n", term.move_x(xpos), u":: ")
        )
    )

    all_tags = list_tags()

    while True:
        inp = LineEditor(
            subject_max_length, u", ".join(sorted(msg.tags)), colors={"highlight": colors["backlight"]}
        ).read()
        if inp is None:
            echo(u"".join((term.move_x(xpos), colors["highlight"]("Message canceled."), term.clear_eol)))
            term.inkey(1)
            return False

        msg.tags = set(filter(None, set(map(unicode.strip, inp.split(",")))))
        if moderated and not (tag_moderators | session.user.groups):
            cannot_tag = [_tag for _tag in msg.tags if _tag not in all_tags]
            if cannot_tag:
                echo(
                    u"".join(
                        (
                            u"\r\n",
                            term.move_x(xpos),
                            u", ".join((quote(tag, colors) for tag in cannot_tag)),
                            u": not allowed; this system is moderated.",
                        )
                    )
                )
                term.inkey(2)
                echo(term.move_up)
                map(msg.tags.remove, cannot_tag)
                continue

        return True
Example #2
0
def prompt_tags(session, term, msg, colors, public=True):
    xpos = max(0, (term.width // 2) - (80 // 2))

    # conditionally enforce tag moderation
    moderated = get_ini('msg', 'moderated_tags', getter='getboolean')
    tag_moderators = set(get_ini('msg', 'tag_moderators', split=True))

    # enforce 'public' tag
    if public and 'public' not in msg.tags:
        msg.tags.add('public')
    elif not public and 'public' in msg.tags:
        msg.tags.remove('public')

    # describe all available tags, as we oft want to do.
    do_describe_available_tags(term, colors)

    # and remind ourselves of the available network tags,
    description = get_network_tag_description(term, colors)
    if description:
        show_description(term=term, color=None, description=description)

    echo(u''.join(
        (term.move_x(xpos), term.clear_eos,
         u'Enter tags, separated by commas.\r\n', term.move_x(xpos), u':: ')))

    all_tags = list_tags()

    while True:
        inp = LineEditor(subject_max_length,
                         u', '.join(sorted(msg.tags)),
                         colors={
                             'highlight': colors['backlight']
                         }).read()
        if inp is None:
            echo(u''.join(
                (term.move_x(xpos), colors['highlight']('Message canceled.'),
                 term.clear_eol)))
            term.inkey(1)
            return False

        msg.tags = set(filter(None, set(map(unicode.strip, inp.split(',')))))
        if moderated and not (tag_moderators | session.user.groups):
            cannot_tag = [_tag for _tag in msg.tags if _tag not in all_tags]
            if cannot_tag:
                echo(u''.join((u'\r\n', term.move_x(xpos), u', '.join(
                    (quote(tag, colors) for tag in cannot_tag)),
                               u': not allowed; this system is moderated.')))
                term.inkey(2)
                echo(term.move_up)
                map(msg.tags.remove, cannot_tag)
                continue

        return True
Example #3
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 #4
0
def do_nua(user):
    """ Perform new user account field setting and validation. """
    session, term = getsession(), getterminal()
    session.activity = u'Applying for an account'

    idx = 0
    validation_fields = get_validation_fields(user)
    while idx != len(validation_fields):
        field = validation_fields.values()[idx]
        echo(fixate_next(term, newlines=1))
        if field.description:
            show_description(term, field.description,
                             color=getattr(term, color_secondary))
            echo(u'\r\n')
            echo(fixate_next(term, newlines=0))
        value = prompt_input(term=term,
                             key=field.prompt_key,
                             content=field.getter(),
                             **field.kwargs)

        # user pressed escape, prompt for cancellation
        if value is None:
            if prompt_yesno('Cancel'):
                return None
            # re-prompt for current field
            continue

        value = value.strip()

        # validate using function, `field.validation_function()'
        if field.validation_function:
            errmsg, mod = field.validation_function(user, value)
            if errmsg:
                show_validation_error(errmsg)
                # re-prompt for current field
                idx += mod
                continue

        # set local variable, increment index to next field; money shot for passing pass to glftpd
        if field.name:
            if field.name == 'password':
                plaintext_password = value
            setattr(user, field.name, value)
        idx += 1

    return user, plaintext_password
Example #5
0
def do_nua(user):
    """ Perform new user account field setting and validation. """
    session, term = getsession(), getterminal()
    session.activity = u'Applying for an account'

    idx = 0
    validation_fields = get_validation_fields(user)
    while idx != len(validation_fields):
        field = validation_fields.values()[idx]
        echo(fixate_next(term, newlines=1))
        if field.description:
            show_description(term, field.description,
                             color=getattr(term, color_secondary))
            echo(u'\r\n')
            echo(fixate_next(term, newlines=0))
        value = prompt_input(term=term,
                             key=field.prompt_key,
                             content=field.getter(),
                             **field.kwargs)

        # user pressed escape, prompt for cancellation
        if value is None:
            if prompt_yesno('Cancel'):
                return None
            # re-prompt for current field
            continue

        value = value.strip()

        # validate using function, `field.validation_function()'
        if field.validation_function:
            errmsg, mod = field.validation_function(user, value)
            if errmsg:
                show_validation_error(errmsg)
                # re-prompt for current field
                idx += mod
                continue

        # set local variable, increment index to next field
        if field.name:
            setattr(user, field.name, value)
        idx += 1

    return user
Example #6
0
def do_describe_available_tags(term, colors):
    sorted_tags = sorted([(len(list_msgs(tags=(tag,))), tag) for tag in list_tags() or [u"public"]], reverse=True)
    decorated_tags = [
        colors["text"](tag) + colors["lowlight"]("({0})".format(num_msgs)) for num_msgs, tag in sorted_tags
    ]

    description = u"".join(
        (colors["highlight"](u"available tags"), ": ", colors["text"](u", ").join(decorated_tags), colors["text"](u"."))
    )
    return show_description(term, description, color=None)
Example #7
0
def do_describe_message_system(term, colors):
    """ Display help text about message tagging. """

    def describe_group_tags():
        groups = getsession().user.groups
        if not groups:
            return u""

        return u"".join(
            (
                u"\r\n\r\n",
                colors["text"](
                    u"Finally, private messages may be shared among groups.  You "
                    u"may post messages to any group you are a member of: "
                ),
                colors["text"](u", ".join(quote(grp, colors) for grp in groups)),
                colors["text"](u"."),
            )
        )

    description = u"".join(
        (
            u"\r\n",
            colors["text"](
                u"You can think of tags as a system of providing context to any "
                u"message stored on this system.  A tag might provide the "
                u"general label of the topic of conversation, which may be "
                u"subscribed to.  For example, "
            ),
            quote(u"python", colors),
            colors["text"](
                u" may be used for topics related to the python programming "
                u"language.  This is similar to flicker or gmail tags, or "
                u"hashtags.  Public messages are always tagged "
            ),
            quote(u"public", colors),
            colors["text"](u".  "),
            get_network_tag_description(term, colors),
            u"\r\n\r\n",
            colors["text"](u"Furthermore, glob expressions may be used such as "),
            quote(u"*", colors),
            u" ",
            colors["text"]("for all messages, or expression "),
            quote(u"lang-*", colors),
            u" ",
            colors["text"]("might subscribe to both "),
            quote(u"lang-python", colors),
            colors["text"](u" and "),
            quote(u"lang-go", colors),
            colors["text"](u"."),
            describe_group_tags(),
        )
    )
    return show_description(term, description, color=None)
Example #8
0
def do_describe_message_system(term, colors):
    """ Display help text about message tagging. """

    def describe_group_tags():
        groups = getsession().user.groups
        if not groups:
            return u''

        return u''.join((
            u'\r\n\r\n',
            colors['text'](
                u'Finally, private messages may be shared among groups.  You '
                u'may post messages to any group you are a member of: '),
            colors['text'](
                u', '.join(quote(grp, colors) for grp in groups)),
            colors['text'](u'.')
        ))

    description = u''.join((
        u'\r\n',
        colors['text'](
            u'You can think of tags as a system of providing context to any '
            u'message stored on this system.  A tag might provide the '
            u'general label of the topic of conversation, which may be '
            u'subscribed to.  For example, '),
        quote(u'python', colors),
        colors['text'](
            u' may be used for topics related to the python programming '
            u'language.  This is similar to flicker or gmail tags, or '
            u'hashtags.  Public messages are always tagged '),
        quote(u'public', colors),
        colors['text'](u'.  '),
        get_network_tag_description(term, colors),
        u'\r\n\r\n',
        colors['text'](
            u'Furthermore, glob expressions may be used such as '),
        quote(u'*', colors),
        u' ',
        colors['text']('for all messages, or expression '),
        quote(u'lang-*', colors),
        u' ',
        colors['text']('might subscribe to both '),
        quote(u'lang-python', colors),
        colors['text'](u' and '),
        quote(u'lang-go', colors),
        colors['text'](u'.'),
        describe_group_tags(),
    ))
    return show_description(term, description, color=None)
Example #9
0
def do_describe_available_tags(term, colors):
    sorted_tags = sorted([(len(list_msgs(tags=(tag,))), tag)
                          for tag in list_tags() or [u'public']
                          ], reverse=True)
    decorated_tags = [
        colors['text'](tag) +
        colors['lowlight']('({0})'.format(num_msgs))
        for num_msgs, tag in sorted_tags]

    description = u''.join((
        colors['highlight'](u'available tags'), ': ',
        colors['text'](u', ').join(decorated_tags),
        colors['text'](u'.'),
    ))
    return show_description(term, description, color=None)
Example #10
0
def do_describe_available_tags(term, colors):
    sorted_tags = sorted([(len(list_msgs(tags=(tag, ))), tag)
                          for tag in list_tags() or [u'public']],
                         reverse=True)
    decorated_tags = [
        colors['text'](tag) + colors['lowlight']('({0})'.format(num_msgs))
        for num_msgs, tag in sorted_tags
    ]

    description = u''.join((
        colors['highlight'](u'available tags'),
        ': ',
        colors['text'](u', ').join(decorated_tags),
        colors['text'](u'.'),
    ))
    return show_description(term, description, color=None)
Example #11
0
def do_describe_message_system(term, colors):
    """ Display help text about message tagging. """
    def describe_group_tags():
        groups = getsession().user.groups
        if not groups:
            return u''

        return u''.join(
            (u'\r\n\r\n', colors['text'](
                u'Finally, private messages may be shared among groups.  You '
                u'may post messages to any group you are a member of: '),
             colors['text'](u', '.join(quote(grp, colors) for grp in groups)),
             colors['text'](u'.')))

    description = u''.join((
        u'\r\n',
        colors['text'](
            u'You can think of tags as a system of providing context to any '
            u'message stored on this system.  A tag might provide the '
            u'general label of the topic of conversation, which may be '
            u'subscribed to.  For example, '),
        quote(u'python', colors),
        colors['text'](
            u' may be used for topics related to the python programming '
            u'language.  This is similar to flicker or gmail tags, or '
            u'hashtags.  Public messages are always tagged '),
        quote(u'public', colors),
        colors['text'](u'.  '),
        get_network_tag_description(term, colors),
        u'\r\n\r\n',
        colors['text'](u'Furthermore, glob expressions may be used such as '),
        quote(u'*', colors),
        u' ',
        colors['text']('for all messages, or expression '),
        quote(u'lang-*', colors),
        u' ',
        colors['text']('might subscribe to both '),
        quote(u'lang-python', colors),
        colors['text'](u' and '),
        quote(u'lang-go', colors),
        colors['text'](u'.'),
        describe_group_tags(),
    ))
    return show_description(term, description, color=None)
Example #12
0
def main(quick=False):
    """ Main procedure. """

    session, term = getsession(), getterminal()
    session.activity = 'checking for new messages'

    # set syncterm font, if any
    if term.kind.startswith('ansi'):
        echo(syncterm_setfont(syncterm_font))

    colors = dict(highlight=lambda txt: txt,
                  lowlight=lambda txt: txt,
                  backlight=lambda txt: txt,
                  text=lambda txt: txt) if not colored_menu_items else dict(
                      highlight=getattr(term, color_highlight),
                      lowlight=getattr(term, color_lowlight),
                      backlight=getattr(term, color_backlight),
                      text=getattr(term, color_text))

    yloc = top_margin = 0
    subscription = session.user.get('msg_subscription', [])
    dirty = 2

    while True:
        if dirty == 2:
            # display header art,
            yloc = display_banner(art_file, encoding=art_encoding, center=True)
            xloc = max(0, (term.width // 2) - 40)
            echo(u'\r\n')
            top_margin = yloc = (yloc + 1)

        elif dirty:
            echo(term.move(top_margin, 0) + term.normal + term.clear_eos)
            echo(term.move(top_margin, xloc))

        if dirty:

            if not subscription:
                # prompt the user for a tag subscription, and loop
                # back again when completed to re-draw and show new messages.
                subscription = session.user['msg_subscription'] = (
                    prompt_subscription(session=session,
                                        term=term,
                                        yloc=top_margin,
                                        subscription=subscription,
                                        colors=colors))
                continue

            messages, messages_bytags = get_messages_by_subscription(
                session, subscription)

            # When quick login ('y') selected in top.py, return immediately
            # when no new messages are matched any longer.
            if quick and not messages['new']:
                echo(term.move_x(xloc) + u'\r\nNo new messages.\r\n')
                return waitprompt(term)

            txt = describe_message_area(term=term,
                                        subscription=subscription,
                                        messages_bytags=messages_bytags,
                                        colors=colors)

            yloc = top_margin + show_description(
                term=term,
                description=txt,
                color=None,
                subsequent_indent=' ' * len('message area: '))

            echo(
                render_menu_entries(term=term,
                                    top_margin=yloc,
                                    menu_items=get_menu(messages),
                                    colors=colors,
                                    max_cols=2))
            echo(display_prompt(term=term, colors=colors))
            echo(colors['backlight'](u' \b'))
            dirty = False

        event, data = session.read_events(('refresh', 'newmsg', 'input'))

        if event == 'refresh':
            # screen resized, redraw.
            dirty = 2
            continue

        elif event == 'newmsg':
            # When a new message is sent, 'newmsg' event is broadcasted.
            session.flush_event('newmsg')
            nxt_msgs, nxt_bytags = get_messages_by_subscription(
                session, subscription)
            if nxt_msgs['new'] - messages['new']:
                # beep and re-display when a new message has arrived.
                echo(u'\b')
                messages, messages_bytags = nxt_msgs, nxt_bytags
                dirty = True
                continue

        elif event == 'input':
            # on input, block until carriage return
            session.buffer_input(data, pushback=True)
            given_inp = LineEditor(1,
                                   colors={
                                       'highlight': colors['backlight']
                                   }).read()

            if given_inp is None:
                # escape/cancel
                continue

            inp = given_inp.strip()
            if inp.lower() in (u'n', 'a', 'v'):
                # read new/all/private messages
                message_indices = sorted(
                    list({
                        'n': messages['new'],
                        'a': messages['all'],
                        'v': messages['private'],
                    }[inp.lower()]))
                if message_indices:
                    dirty = 2
                    read_messages(session=session,
                                  term=term,
                                  message_indices=message_indices,
                                  colors=colors)
            elif inp.lower() == u'm' and messages['new']:
                # mark all messages as read
                dirty = 1
                do_mark_as_read(session, messages['new'])
            elif inp.lower() in (u'p', u'w'):
                # write new public/private message
                dirty = 2
                public = bool(inp.lower() == u'p')
                msg = Msg()
                if (not prompt_recipient(
                        term=term, msg=msg, colors=colors, public=public) or
                        not prompt_subject(term=term, msg=msg, colors=colors)
                        or not prompt_body(term=term, msg=msg, colors=colors)
                        or not prompt_tags(session=session,
                                           term=term,
                                           msg=msg,
                                           colors=colors,
                                           public=public)):
                    continue
                do_send_message(session=session,
                                term=term,
                                msg=msg,
                                colors=colors)
            elif inp.lower() == u'c':
                # prompt for new tag subscription (at next loop)
                subscription = []
                dirty = 1
            elif inp.lower() == u'?':
                # help
                echo(term.move(top_margin, 0) + term.clear_eos)
                do_describe_message_system(term, colors)
                waitprompt(term)
                dirty = 2
            elif inp.lower() == u'q':
                return
            if given_inp:
                # clear out line editor prompt
                echo(colors['backlight'](u'\b \b'))
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
Example #14
0
def main(quick=False):
    """ Main procedure. """

    session, term = getsession(), getterminal()
    session.activity = 'checking for new messages'

    # set syncterm font, if any
    if term.kind.startswith('ansi'):
        echo(syncterm_setfont(syncterm_font))

    colors = dict(
        highlight=lambda txt: txt,
        lowlight=lambda txt: txt,
        backlight=lambda txt: txt,
        text=lambda txt: txt
    ) if not colored_menu_items else dict(
        highlight=getattr(term, color_highlight),
        lowlight=getattr(term, color_lowlight),
        backlight=getattr(term, color_backlight),
        text=getattr(term, color_text))

    yloc = top_margin = 0
    subscription = session.user.get('msg_subscription', [])
    dirty = 2

    while True:
        if dirty == 2:
            # display header art,
            yloc = display_banner(art_file, encoding=art_encoding, center=True)
            xloc = max(0, (term.width // 2) - 40)
            echo(u'\r\n')
            top_margin = yloc = (yloc + 1)

        elif dirty:
            echo(term.move(top_margin, 0) + term.normal + term.clear_eos)
            echo(term.move(top_margin, xloc))

        if dirty:

            if not subscription:
                # prompt the user for a tag subscription, and loop
                # back again when completed to re-draw and show new messages.
                subscription = session.user['msg_subscription'] = (
                    prompt_subscription(
                        session=session, term=term, yloc=top_margin,
                        subscription=subscription, colors=colors))
                continue

            messages, messages_bytags = get_messages_by_subscription(
                session, subscription)

            # When quick login ('y') selected in top.py, return immediately
            # when no new messages are matched any longer.
            if quick and not messages['new']:
                echo(term.move_x(xloc) + u'\r\nNo new messages.\r\n')
                return waitprompt(term)

            txt = describe_message_area(
                term=term, subscription=subscription,
                messages_bytags=messages_bytags, colors=colors)

            yloc = top_margin + show_description(
                term=term, description=txt, color=None,
                subsequent_indent=' ' * len('message area: '))

            echo(render_menu_entries(
                term=term, top_margin=yloc,
                menu_items=get_menu(messages),
                colors=colors, max_cols=2))
            echo(display_prompt(term=term, colors=colors))
            echo(colors['backlight'](u' \b'))
            dirty = False

        event, data = session.read_events(('refresh', 'newmsg', 'input'))

        if event == 'refresh':
            # screen resized, redraw.
            dirty = 2
            continue

        elif event == 'newmsg':
            # When a new message is sent, 'newmsg' event is broadcasted.
            session.flush_event('newmsg')
            nxt_msgs, nxt_bytags = get_messages_by_subscription(
                session, subscription)
            if nxt_msgs['new'] - messages['new']:
                # beep and re-display when a new message has arrived.
                echo(u'\b')
                messages, messages_bytags = nxt_msgs, nxt_bytags
                dirty = True
                continue

        elif event == 'input':
            # on input, block until carriage return
            session.buffer_input(data, pushback=True)
            given_inp = LineEditor(
                1, colors={'highlight': colors['backlight']}
            ).read()

            if given_inp is None:
                # escape/cancel
                continue

            inp = given_inp.strip()
            if inp.lower() in (u'n', 'a', 'v'):
                # read new/all/private messages
                message_indices = sorted(list(
                    {'n': messages['new'],
                     'a': messages['all'],
                     'v': messages['private'],
                     }[inp.lower()]))
                if message_indices:
                    dirty = 2
                    read_messages(session=session, term=term,
                                  message_indices=message_indices,
                                  colors=colors)
            elif inp.lower() == u'm' and messages['new']:
                # mark all messages as read
                dirty = 1
                do_mark_as_read(session, messages['new'])
            elif inp.lower() in (u'p', u'w'):
                # write new public/private message
                dirty = 2
                public = bool(inp.lower() == u'p')
                msg = Msg()
                if (
                        not prompt_recipient(
                            term=term, msg=msg,
                            colors=colors, public=public
                        ) or not prompt_subject(
                            term=term, msg=msg, colors=colors
                        ) or not prompt_body(
                            term=term, msg=msg, colors=colors
                        ) or not prompt_tags(
                            session=session, term=term, msg=msg,
                            colors=colors, public=public
                        )):
                    continue
                do_send_message(session=session, term=term,
                                msg=msg, colors=colors)
            elif inp.lower() == u'c':
                # prompt for new tag subscription (at next loop)
                subscription = []
                dirty = 1
            elif inp.lower() == u'?':
                # help
                echo(term.move(top_margin, 0) + term.clear_eos)
                do_describe_message_system(term, colors)
                waitprompt(term)
                dirty = 1
            elif inp.lower() == u'q':
                return
            if given_inp:
                # clear out line editor prompt
                echo(colors['backlight'](u'\b \b'))
Example #15
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