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 compose(self, title=None): def temp_footer_message(self, string, duration=3):
editor = ExternalEditor if self.prefs["editor"] else InternalEditor self.loop.set_alarm_in(
if self.mode == "index": duration, lambda x,y: self.set_footer(self.bars[self.mode]))
if not title: self.set_footer(string)
return self.footer_prompt("Title", self.compose)
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):
if self.mode == "index" and not title:
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)
return app.refresh() if self.params["body"]:
network.request(self.endpoint, **self.params)
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()