external editor polish; overthrowing option

pull/4/head
Blake DeMarcy 2017-04-09 13:20:39 -05:00
parent 3898f19f14
commit f4ddb18470
1 changed files with 62 additions and 16 deletions

View File

@ -51,6 +51,7 @@ editors = ["nano", "emacs", "vim", "micro", "ed", "joe"]
default_prefs = { default_prefs = {
# well, it WILL default to the internal editor when I write it =) # well, it WILL default to the internal editor when I write it =)
"editor": "vim", "editor": "vim",
"integrate_external_editor": True,
"dramatic_exit": True, "dramatic_exit": True,
"date": "%Y/%m/%d", "date": "%Y/%m/%d",
"time": "%H:%M", "time": "%H:%M",
@ -157,9 +158,10 @@ class App(object):
control = "[save/quit to send]" if self.prefs["editor"] else "[F3]Send" control = "[save/quit to send]" if self.prefs["editor"] else "[F3]Send"
self.loop.widget.footer[0].set_text( self.loop.widget.footer[0].set_text(
"[F1]Abort [F2]Swap %s %s" % (control, focus)) "[F1]Abort [F2]Swap %s %s" % (control, focus))
# this hideous and awful sinful horrid unspeakable shithack changes # this hideous and awful sinful horrid unspeakable shithack changes
# the color of the help line and editor border to reflect which # the color of the help/title lines and editor border to reflect which
# object is currently in focus # object is currently in focus.
self.loop.widget.footer.contents[1][0].original_widget.attr_map = \ self.loop.widget.footer.contents[1][0].original_widget.attr_map = \
self.loop.widget.footer.contents[0][0].attr_map = {None: attr[0]} self.loop.widget.footer.contents[0][0].attr_map = {None: attr[0]}
self.loop.widget.header.attr_map = {None: attr[1]} self.loop.widget.header.attr_map = {None: attr[1]}
@ -313,24 +315,65 @@ class App(object):
app.loop.widget.focus_position = "footer" app.loop.widget.focus_position = "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.set_footer(string)
def overthrow_ext_edit(self):
"""
Opens the external editor, but instead of integreating it into the app,
stops the mainloop and blocks until the editor is killed. Returns the
body of text the user composed.
"""
self.loop.stop()
descriptor, path = tempfile.mkstemp()
run("%s %s" % (self.prefs["editor"], path), shell=True)
with open(descriptor) as _:
body = _.read()
os.remove(path)
self.loop.start()
return body.strip()
def compose(self, title=None): def compose(self, title=None):
editor = ExternalEditor if self.prefs["editor"] else InternalEditor if self.mode == "index" and not title:
if self.mode == "index":
if not title:
return self.footer_prompt("Title", self.compose) return self.footer_prompt("Title", self.compose)
elif title:
try: network.validate("title", title) try: network.validate("title", title)
except AssertionError as e: except AssertionError as e:
return self.footer_prompt( return self.footer_prompt(
"Title", self.compose, extra_text=e.description) "Title", self.compose, extra_text=e.description)
if self.prefs["editor"] and not self.prefs["integrate_external_editor"]:
body = self.overthrow_ext_edit()
if not body:
return self.temp_footer_message("EMPTY POST DISCARDED")
params = {"body": body}
thread = False
if self.mode == "thread":
thread = True
params.update({"thread_id": self.thread["thread_id"]})
else:
params.update({"title": title})
network.request("thread_" + ("reply" if thread else "create"), **params)
return self.refresh()
editor = ExternalEditor if self.prefs["editor"] else InternalEditor
if self.mode == "index":
self.set_header('Composing "{}"', title) self.set_header('Composing "{}"', title)
self.set_footer("[F1]Abort [Save and quit to submit your thread]") self.set_footer("[F1]Abort [Save and quit to submit your thread]")
self.loop.widget = urwid.Overlay( self.loop.widget = urwid.Overlay(
urwid.LineBox( urwid.LineBox(
editor("thread_create", title=title), editor("thread_create", title=title),
title=self.prefs["editor"]), title=self.prefs["editor"],
tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
tline="-", bline="-", lline="|", rline="|"),
self.loop.widget, align="center", valign="middle", self.loop.widget, align="center", valign="middle",
width=self.loop.screen_size[0] - 2, width=self.loop.screen_size[0] - 2,
height=(self.loop.screen_size[1] - 4)) height=(self.loop.screen_size[1] - 4))
@ -348,14 +391,11 @@ class App(object):
thread_id=self.thread["thread_id"]), thread_id=self.thread["thread_id"]),
tlcorner="@", trcorner="@", blcorner="@", brcorner="@", tlcorner="@", trcorner="@", blcorner="@", brcorner="@",
tline="-", bline="-", lline="|", rline="|" tline="-", bline="-", lline="|", rline="|"
), ), "bar"),
"bar"), self.loop.screen_size[1] // 2),])
self.loop.screen_size[1] // 2),
])
self.switch_editor() self.switch_editor()
class MessageBody(urwid.Text): class MessageBody(urwid.Text):
pass pass
@ -406,10 +446,13 @@ class ExternalEditor(urwid.Terminal):
if self.terminated: if self.terminated:
app.close_editor() app.close_editor()
with open(self.file_descriptor) as _: with open(self.file_descriptor) as _:
self.params.update({"body": _.read()}) self.params.update({"body": _.read().strip()})
network.request(self.endpoint, **self.params)
os.remove(self.path) os.remove(self.path)
if self.params["body"]:
network.request(self.endpoint, **self.params)
return app.refresh() return app.refresh()
else:
return app.temp_footer_message("EMPTY POST DISCARDED")
elif key not in ["f1", "f2"]: elif key not in ["f1", "f2"]:
return super(ExternalEditor, self).keypress(size, key) return super(ExternalEditor, self).keypress(size, key)
@ -461,6 +504,9 @@ class ActionBox(urwid.ListBox):
elif key == "c": elif key == "c":
app.compose() app.compose()
elif key == "6":
app.set_footer(app.overthrow_ext_edit())
elif key == "r": elif key == "r":
app.refresh() app.refresh()