aboutsummaryrefslogtreecommitdiffstats
path: root/clients/urwid/main.py
diff options
context:
space:
mode:
authorBlake DeMarcy <ofunknowndescent@gmail.com>2017-04-10 06:05:20 -0500
committerBlake DeMarcy <ofunknowndescent@gmail.com>2017-04-10 06:05:20 -0500
commit88f43d023a9fa31d2912a74c78c279ddded426ee (patch)
tree420d9b58c41198ad7146c31ba88f5752fdfddb4d /clients/urwid/main.py
parentf4ddb18470b0199acd5bffe69f814bc81783cbba (diff)
downloadbbj-88f43d023a9fa31d2912a74c78c279ddded426ee.tar.gz
Options menu
Diffstat (limited to 'clients/urwid/main.py')
-rw-r--r--clients/urwid/main.py206
1 files changed, 161 insertions, 45 deletions
diff --git a/clients/urwid/main.py b/clients/urwid/main.py
index face685..b77280d 100644
--- a/clients/urwid/main.py
+++ b/clients/urwid/main.py
@@ -68,6 +68,7 @@ class App(object):
}
colors = [
+ ("default", "default", "default"),
("bar", "light magenta", "default"),
("button", "light red", "default"),
("dim", "dark gray", "default"),
@@ -91,10 +92,10 @@ class App(object):
self.walker = urwid.SimpleFocusListWalker([])
self.loop = urwid.MainLoop(urwid.Frame(
- urwid.LineBox(ActionBox(self.walker),
+ urwid.LineBox(
+ ActionBox(self.walker),
title=self.prefs["frame_title"],
- tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
- tline="=", bline="=", lline="|", rline="|"
+ **frame_theme()
)), colors)
self.index()
@@ -286,18 +287,88 @@ class App(object):
self.walker += self.make_message_body(message)
- def refresh(self):
+ def refresh(self, bottom=False):
if self.mode == "index":
return self.index()
self.thread_load(None, self.thread["thread_id"])
- self.loop.widget.body.base_widget.set_focus(len(self.walker) - 1)
+ if bottom:
+ self.loop.widget.body.base_widget.set_focus(len(self.walker) - 5)
def back(self):
- if self.mode == "thread":
+ if app.mode == "index":
+ frilly_exit()
+ elif app.mode == "thread":
self.index()
+ def set_new_editor(self, button, value, key):
+ if value == False:
+ return
+ elif key == "internal":
+ key = None
+ self.prefs.update({"editor": key})
+ bbjrc("update", **self.prefs)
+
+
+ def set_editor_mode(self, button, value):
+ self.prefs["integrate_external_editor"] = value
+ bbjrc("update", **self.prefs)
+
+
+ def options_menu(self):
+ editor_buttons = []
+ edit_mode = []
+
+ urwid.RadioButton(
+ editor_buttons, "Internal",
+ state=not self.prefs["editor"],
+ on_state_change=self.set_new_editor,
+ user_data="internal")
+
+ for editor in editors:
+ urwid.RadioButton(
+ editor_buttons, editor.title(),
+ state=self.prefs["editor"] == editor,
+ on_state_change=self.set_new_editor,
+ user_data=editor)
+
+ urwid.RadioButton(
+ edit_mode, "Integrate",
+ state=self.prefs["integrate_external_editor"],
+ on_state_change=self.set_editor_mode)
+
+ urwid.RadioButton(
+ edit_mode, "Overthrow",
+ state=not self.prefs["integrate_external_editor"])
+
+ widget = OptionsMenu(
+ urwid.Filler(
+ urwid.Pile([
+ urwid.AttrMap(urwid.Text("Text editor:"), "button"),
+ urwid.Divider(),
+ *editor_buttons,
+ urwid.Divider("-"),
+ urwid.AttrMap(urwid.Text("External text editor mode:"), "button"),
+ urwid.Text("If you have problems using an external text editor, "
+ "set this to Overthrow."),
+ urwid.Divider(),
+ *edit_mode,
+ urwid.Divider("-"),
+ ]), "top"),
+ title="BBJ Options",
+ **frame_theme()
+ )
+
+ self.loop.widget = urwid.Overlay(
+ widget, self.loop.widget,
+ align="center",
+ valign="middle",
+ width=30,
+ height=(self.loop.screen_size[1] - 10)
+ )
+
+
def footer_prompt(self, text, callback, *callback_args, extra_text=None):
text = "(%s)> " % text
widget = urwid.Columns([
@@ -312,12 +383,20 @@ class App(object):
])
self.loop.widget.footer = widget
- app.loop.widget.focus_position = "footer"
+ self.loop.widget.focus_position = "footer"
+
+
+ def reset_footer(self, *_, **__):
+ try:
+ self.set_footer(self.bars[self.mode])
+ self.loop.widget.focus_position = "body"
+ except:
+ # just keep trying until the widget can handle it
+ self.loop.set_alarm_in(0.5, self.reset_footer)
def temp_footer_message(self, string, duration=3):
- self.loop.set_alarm_in(
- duration, lambda x,y: self.set_footer(self.bars[self.mode]))
+ self.loop.set_alarm_in(duration, self.reset_footer)
self.set_footer(string)
@@ -353,46 +432,52 @@ class App(object):
return self.temp_footer_message("EMPTY POST DISCARDED")
params = {"body": body}
- thread = False
if self.mode == "thread":
- thread = True
+ endpoint = "reply"
params.update({"thread_id": self.thread["thread_id"]})
else:
+ endpoint = "create"
params.update({"title": title})
- network.request("thread_" + ("reply" if thread else "create"), **params)
- return self.refresh()
+ network.request("thread_" + endpoint, **params)
+ return self.refresh(True)
- editor = ExternalEditor if self.prefs["editor"] else InternalEditor
if self.mode == "index":
self.set_header('Composing "{}"', title)
- self.set_footer("[F1]Abort [Save and quit to submit your thread]")
+ if self.prefs["editor"]:
+ editor = ExternalEditor("thread_create", title=title)
+ self.set_footer("[F1]Abort [Save and quit to submit your thread]")
+ else:
+ editor = urwid.Filler(
+ InternalEditor("thread_create", title=title),
+ valign=urwid.TOP)
+ self.set_footer("[F1]Abort [F3]Send")
self.loop.widget = urwid.Overlay(
urwid.LineBox(
- editor("thread_create", title=title),
- title=self.prefs["editor"],
- tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
- tline="-", bline="-", lline="|", rline="|"),
- self.loop.widget, align="center", valign="middle",
+ editor,
+ title=self.prefs["editor"] or "",
+ **frame_theme()),
+ self.loop.widget,
+ align="center",
+ valign="middle",
width=self.loop.screen_size[0] - 2,
height=(self.loop.screen_size[1] - 4))
elif self.mode == "thread":
self.window_split=True
self.set_header('Replying to "{}"', self.thread["title"])
+ if self.prefs["editor"]:
+ editor = ExternalEditor("thread_reply", thread_id=self.thread["thread_id"])
+ else:
+ editor = urwid.AttrMap(urwid.Filler(
+ InternalEditor("thread_reply", thread_id=self.thread["thread_id"]),
+ valign=urwid.TOP), "default")
self.loop.widget.footer = urwid.Pile([
urwid.AttrMap(urwid.Text(""), "bar"),
- urwid.BoxAdapter(
- urwid.AttrMap(
- urwid.LineBox(
- editor(
- "thread_reply",
- thread_id=self.thread["thread_id"]),
- tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
- tline="-", bline="-", lline="|", rline="|"
- ), "bar"),
- self.loop.screen_size[1] // 2),])
+ urwid.BoxAdapter(urwid.AttrMap(urwid.LineBox(
+ editor, **frame_theme()
+ ), "bar"), self.loop.screen_size[1] // 2),])
self.switch_editor()
@@ -417,18 +502,28 @@ class FootPrompt(urwid.Edit):
class InternalEditor(urwid.Edit):
def __init__(self, endpoint, **params):
- super(InternalEditor, self).__init__()
+ super(InternalEditor, self).__init__(multiline=True)
self.endpoint = endpoint
self.params = params
def keypress(self, size, key):
- if key not in ["f1", "f2"]:
+ if key not in ["f1", "f2", "f3"]:
return super(InternalEditor, self).keypress(size, key)
elif key == "f1":
- return app.close_editor()
+ app.close_editor()
+ return app.refresh()
elif key == "f2":
return app.switch_editor()
+ body = self.get_edit_text().strip()
+ app.close_editor()
+ if body:
+ self.params.update({"body": body})
+ network.request(self.endpoint, **self.params)
+ app.refresh(True)
+ else:
+ app.temp_footer_message("EMPTY POST DISCARDED")
+
class ExternalEditor(urwid.Terminal):
def __init__(self, endpoint, **params):
@@ -450,7 +545,7 @@ class ExternalEditor(urwid.Terminal):
os.remove(self.path)
if self.params["body"]:
network.request(self.endpoint, **self.params)
- return app.refresh()
+ return app.refresh(True)
else:
return app.temp_footer_message("EMPTY POST DISCARDED")
@@ -465,9 +560,21 @@ class ExternalEditor(urwid.Terminal):
app.switch_editor()
+class OptionsMenu(urwid.LineBox):
+ def keypress(self, size, key):
+ super(OptionsMenu, self).keypress(size, key)
+ if key.lower() == "q":
+ app.loop.widget = app.loop.widget[0]
+ elif key in ["ctrl n", "j", "n"]:
+ return self.keypress(size, "down")
+ elif key in ["ctrl p", "k", "p"]:
+ return self.keypress(size, "up")
+
+
class ActionBox(urwid.ListBox):
"""
- The listwalker used by all the browsing pages. Handles keys.
+ The listwalker used by all the browsing pages. Most of the application
+ takes place in an instance of this box. Handles many keybinds.
"""
def keypress(self, size, key):
super(ActionBox, self).keypress(size, key)
@@ -495,26 +602,23 @@ class ActionBox(urwid.ListBox):
elif key in ["l", "right"]:
self.keypress(size, "enter")
- elif key.lower() == "b":
+ elif key == "b":
self.change_focus(size, len(app.walker) - 1)
- elif key.lower() == "t":
+ elif key == "t":
self.change_focus(size, 0)
- elif key == "c":
+ elif key in ["c", "R", "+"]:
app.compose()
- elif key == "6":
- app.set_footer(app.overthrow_ext_edit())
-
elif key == "r":
app.refresh()
+ elif key == "o":
+ app.options_menu()
+
elif key.lower() == "q":
- if app.mode == "index":
- frilly_exit()
- else:
- app.back()
+ app.back()
def frilly_exit():
@@ -675,6 +779,18 @@ def log_in():
motherfucking_rainbows("~~welcome to the party, %s!~~" % network.user_name)
+def frame_theme(mode="default"):
+ """
+ Return the kwargs for a frame theme.
+ """
+ if mode == "default":
+ return dict(
+ tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
+ tline="=", bline="=", lline="|", rline="|"
+ )
+
+
+
def bbjrc(mode, **params):
"""
Maintains a user a preferences file, setting or returning
Un proyecto texto-plano.xyz