diff options
author | Blake DeMarcy <ofunknowndescent@gmail.com> | 2017-04-12 09:09:16 -0500 |
---|---|---|
committer | Blake DeMarcy <ofunknowndescent@gmail.com> | 2017-04-12 09:09:16 -0500 |
commit | 09077baeac68fdf4fa1178f7d410665387a74ca0 (patch) | |
tree | e8cd39673a844b197e8307eb47c175ff6c11ca95 /clients/urwid/main.py | |
parent | 7eef803084d58b9a67736a5e67efd63ea825bd94 (diff) | |
download | bbj-09077baeac68fdf4fa1178f7d410665387a74ca0.tar.gz |
fake messages, formatting endpoint, new help menus
Diffstat (limited to 'clients/urwid/main.py')
-rw-r--r-- | clients/urwid/main.py | 184 |
1 files changed, 168 insertions, 16 deletions
diff --git a/clients/urwid/main.py b/clients/urwid/main.py index 110f3d0..3cf98dd 100644 --- a/clients/urwid/main.py +++ b/clients/urwid/main.py @@ -20,7 +20,6 @@ Please mail me (~desvox) for feedback and for any of your "OH MY GOD WHY WOULD YOU DO THIS"'s or "PEP8 IS A THING"'s. """ - from network import BBJ, URLError from string import punctuation from datetime import datetime @@ -62,6 +61,86 @@ welcome = """>>> Welcome to Bulletin Butter & Jelly! ------------------@ @_________________________________________________________@ """ +format_help = [ + "BBJ supports **bolding**, __underlining__, and [rainbow: coloring] text " + "using markdown-style symbols as well as tag-like expressions. Markdown " + "is **NOT** fully implemented, but several of the more obvious concepts " + "have been brought over. Additionally, we have chan-style greentext and " + "numeric post referencing, ala >>3 for the third reply.", + + "[red: Whitespace]", + + "When you're composing, it is desirable to introduce linebreaks into the " + "body to keep it from overflowing the screen. However, you __dont__ want " + "that same spacing to bleed over to other people's screens, because clients " + "will wrap the text themselves.", + + "Single line breaks in the body join into eachother to form sentences, " + "putting a space where the break was. This works like html. When you want " + "to split it off into a paragraph, **use two line breaks.**", + + "[red: Colors, Bold, Underline & Expressions]", + + "You can use [rainbow: rainbow], [red: red], [yellow: yellow], [green: green], " + "[blue: blue], [cyan: cyan], [magenta: and magenta], **bold**, and __underline__ " + "inside of your posts. **bold\nworks like this**, __and\nunderlines like this__. " + "The symbolic, markdown form of these directives does NOT allow escaping, and " + "can only apply to up to 20 characters on the same line. They are best used on short " + "phrases. However, you can use a different syntax for it, which is also required to use " + "colors: these expressions \[bold: look like this] and are much more reliable. " + "The colon and the space following it are important. When you use these " + "expressions, the __first__ space is not part of the content, but any characters, " + "including spaces, that follow it are included in the body. The formatting will " + "apply until the closing ]. You can escape such an expression \\[cyan: like this]" + "and can also \\[blue: escape \\] other closing brackets] inside of it. Only " + "closing brackets need to be escaped within an expression. Any backslashes used " + "for escaping will not show in the body unless you use two slashes.", + + "This peculiar syntax elimiates false positives. You never have to escape [normal] " + "brackets when using the board. Only expressions with **valid and defined** directives " + "will be affected. [so: this is totally valid and requires no escapes] because 'so' is " + "not a directive. [red this will pass too] because the colon is missing.", + + "The following directives may be used in this form: red, yellow, green, blue, cyan, " + "magenta, bold, underline, and rainbow. Nesting expressions into eachother will " + "override the parent directives until it closes. Thus, nesting is valid but doesn't produce " + "layered results.", + + "[red: Quotes & Greentext]", + + "You can refer to a post number using two angle brackets pointing into a number. >>432 " + "like this. You can color a whole line green by proceeding it with a '>'. Note that " + "this violates the sentence structure outlined in the **Whitespace** section above, " + "so you may introduce >greentext without splicing into seperate paragraphs. The '>' " + "must be the first character on the line with no whitespace before it.\n>it looks like this\n" + "and the paragraph doesnt have to break on either side.", + + "When using numeric quotes, they are highlighted and the author's name will show " + "next to them in the thread. You can press enter when focused on a message to view " + "the parent posts. You may insert these directives manually or use the <Reply> function " + "on post menus.", + + "Quoting directives cannot be escaped." +] + +general_help = [ + ("bold", "use q or escape to close dialogs and menus (including this one)\n\n"), + + "You may use the arrow keys, or use jk/np/Control-n|p to move up and down by " + "an element. If an element is overflowing the screen, it will scroll only one line. " + "To make scrolling faster, hold shift when using a control: it will repeat 5 times.\n\n" + + "To go back and forth between threads, you may also use the left/right arrow keys, " + "or h/l to do it vi-style.\n\n" + + "In the thread index and any open thread, the b and t keys may be used to go to " + "very top or bottom.\n\n" + + "Aside from those, primary controls are shown on the very bottom of the screen " + "in the footer line, or may be placed in window titles for other actions like " + "dialogs or composers." +] + colornames = [ "none", "red", "yellow", "green", "blue", "cyan", "magenta" @@ -87,7 +166,7 @@ default_prefs = { class App(object): def __init__(self): self.bars = { - "index": "[Arrows|JK|NP]Navigate [RET]Open [C]ompose [R]efresh [O]ptions [?]Help [Q]uit", + "index": "[JKNP]Navigate [RET]Open [C]ompose [R]efresh [O]ptions [?]Help [Q]uit", "thread": "[C]ompose [RET]Interact [Q]Back [R]efresh [B/T]End [?]Help/More" } @@ -222,9 +301,8 @@ class App(object): focus = "[focused on thread]" attr = ("dim", "bar") - control = "[save/quit to send]" if self.prefs["editor"] else "[F3]Send" self.loop.widget.footer[0].set_text( - "[F1]Abort [F2]Swap %s %s" % (control, focus)) + "[F1]Abort [F2]Swap [F3]Formatting Help [save/quit to send] " + focus) # this hideous and awful sinful horrid unspeakable shithack changes # the color of the help/title lines and editor border to reflect which @@ -339,7 +417,7 @@ class App(object): init_body=message["body"], post_id=post_id, thread_id=thread_id), - title="[F1]Abort (save/quit to commit)", + title="[F1]Abort [F3]Formatting Help (save/quit to commit)", **frame_theme()), self.loop.widget, align="center", @@ -382,7 +460,7 @@ class App(object): align=("relative", 50), valign=("relative", 50), width=30, - height=len(buttons) + 3 + height=len(buttons) + 2 ) @@ -399,7 +477,7 @@ class App(object): return [value_type(q) for q in quotes] - def make_message_body(self, message): + def make_message_body(self, message, no_action=False): """ Returns the widgets that comprise a message in a thread, including the text body, author info and the action button @@ -408,11 +486,12 @@ class App(object): if message["edited"]: info += " [edited]" + callback = self.on_post if not no_action else ignore name = urwid.Text("~{}".format(self.usermap[message["author"]]["user_name"])) post = str(message["post_id"]) head = urwid.Columns([ (2 + len(post), urwid.AttrMap( - cute_button(">" + post, self.on_post, message), "button", "hover")), + cute_button(">" + post, callback, message), "button", "hover")), (len(name._text) + 1, urwid.AttrMap( name, str(self.usermap[message["author"]]["color"]))), urwid.AttrMap(urwid.Text(info), "dim") @@ -508,7 +587,7 @@ class App(object): self.set_bars() - def refresh(self, bottom=False): + def refresh(self, bottom=True): self.remove_overlays() if self.mode == "index": return self.index() @@ -578,6 +657,60 @@ class App(object): self.options_menu() + def general_help(self): + """ + Show a general help dialog. In all honestly, its not + very useful and will only help people who have never + really used terminal software before =) + """ + widget = OptionsMenu( + urwid.ListBox( + urwid.SimpleFocusListWalker([ + urwid_rainbows( + "This is BBJ, a client/server textboard made for tilde.town!", + True), + urwid.Text(("dim", "...by ~desvox")), + urwid.Divider("-"), + urwid.Button("Post Formatting Help", self.formatting_help), + urwid.Divider("-"), + urwid.Text(general_help) + ])), + title="?????", + **frame_theme() + ) + + app.loop.widget = urwid.Overlay( + widget, app.loop.widget, + align=("relative", 50), + valign=("relative", 50), + width=30, + height=("relative", 60) + ) + + + def formatting_help(self, *_): + """ + Pops a help window with formatting directives. + """ + message = network.fake_message("\n\n".join(format_help)) + widget = OptionsMenu( + urwid.ListBox( + urwid.SimpleFocusListWalker([ + *app.make_message_body(message, True) + ])), + title="Formatting Help", + **frame_theme() + ) + + app.loop.widget = urwid.Overlay( + widget, app.loop.widget, + align=("relative", 50), + valign=("relative", 50), + width=("relative", 98), + height=("relative", 60) + ) + + def set_color(self, button, value, color): if value == False: return @@ -854,7 +987,7 @@ class App(object): if self.mode == "index": self.set_header('Composing "{}"', title) - self.set_footer("[F1]Abort [Save and quit to submit your thread]") + self.set_footer("[F1]Abort [F3]Formatting Help [Save and quit to submit your thread]") self.loop.widget = urwid.Overlay( urwid.LineBox( ExternalEditor("thread_create", title=title), @@ -1049,15 +1182,17 @@ class ExternalEditor(urwid.Terminal): else: return app.temp_footer_message("EMPTY POST DISCARDED") - elif key not in ["f1", "f2"]: + elif key not in ["f1", "f2", "f3"]: return super(ExternalEditor, self).keypress(size, key) elif key == "f1": self.terminate() app.close_editor() app.refresh() - # key == "f2" - app.switch_editor() + elif key == "f2": + app.switch_editor() + elif key == "f3": + app.formatting_help() def __del__(self): @@ -1077,6 +1212,12 @@ class OptionsMenu(urwid.LineBox): # try to let the base class handle the key, if not, we'll take over elif not super(OptionsMenu, self).keypress(size, key): return + elif key in ["shift down", "J", "N"]: + for x in range(5): + self.keypress(size, "down") + elif key in ["shift up", "K", "P"]: + for x in range(5): + self.keypress(size, "up") elif key.lower() == "q": app.loop.widget = app.loop.widget[0] elif key in ["ctrl n", "j", "n"]: @@ -1102,11 +1243,11 @@ class ActionBox(urwid.ListBox): elif key in ["k", "p", "ctrl p"]: self._keypress_up(size) - elif key in ["J", "N"]: + elif key in ["shift down", "J", "N"]: for x in range(5): self._keypress_down(size) - elif key in ["K", "P"]: + elif key in ["shift up", "K", "P"]: for x in range(5): self._keypress_up(size) @@ -1131,6 +1272,9 @@ class ActionBox(urwid.ListBox): elif key == "o": app.options_menu() + elif key == "?": + app.general_help() + elif key.lower() == "q": app.back() @@ -1168,12 +1312,13 @@ def cute_button(label, callback=None, data=None): return button -def urwid_rainbows(string): +def urwid_rainbows(string, bold=False): """ Same as below, but instead of printing rainbow text, returns a markup list suitable for urwid's Text contructor. """ colors = [str(x) for x in range(1, 7)] + if bold: colors = [(c + "0") for c in colors] return urwid.Text([(choice(colors), char) for char in string]) @@ -1345,6 +1490,13 @@ def bbjrc(mode, **params): return values +def ignore(*_, **__): + """ + The blackness of my soul. + """ + pass + + def main(): run("clear", shell=True) |