summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2011-09-10 21:36:22 +0100
committerPatrick Totzke <patricktotzke@gmail.com>2011-09-10 21:36:22 +0100
commit2ad71567def4409aef2d5f2145f879f41834cf44 (patch)
tree3e447d2a13aa387ac55536f0d8b1ffd1e17b0d88
parent4b77957e590cdb16e34e734a80ad7faad153b8d6 (diff)
parentd9cc7c847c6a50bdd0e51ad50a9dead4805688e6 (diff)
Merge branch 'prompt' into develop
-rw-r--r--alot/command.py15
-rw-r--r--alot/ui.py93
-rw-r--r--alot/widgets.py25
3 files changed, 70 insertions, 63 deletions
diff --git a/alot/command.py b/alot/command.py
index 3111f2cd..407634e6 100644
--- a/alot/command.py
+++ b/alot/command.py
@@ -34,6 +34,7 @@ from email.message import Message
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import urwid
+from twisted.internet import defer
import buffer
import settings
@@ -354,6 +355,7 @@ class ComposeCommand(Command):
for key, value in headers.items():
self.mail[key] = encode_header(key, value)
+ @defer.inlineCallbacks
def apply(self, ui):
# TODO: fill with default header (per account)
# get From header
@@ -366,11 +368,11 @@ class ComposeCommand(Command):
a = accounts[0]
else:
cmpl = AccountCompleter(ui.accountman)
- fromaddress = ui.prompt(prefix='From>', completer=cmpl, tab=1)
+ fromaddress = yield ui.prompt(prefix='From>', completer=cmpl, tab=1)
validaddresses = [a.address for a in accounts] + [None]
while fromaddress not in validaddresses: # TODO: not cool
ui.notify('no account for this address. (<esc> cancels)')
- fromaddress = ui.prompt(prefix='From>', completer=cmpl)
+ fromaddress = yield ui.prompt(prefix='From>', completer=cmpl)
if not fromaddress:
ui.notify('canceled')
return
@@ -379,7 +381,7 @@ class ComposeCommand(Command):
#get To header
if 'To' not in self.mail:
- to = ui.prompt(prefix='To>',
+ to = yield ui.prompt(prefix='To>',
completer=ContactsCompleter(ui.accountman))
if to == None:
ui.notify('canceled')
@@ -387,7 +389,7 @@ class ComposeCommand(Command):
self.mail['To'] = encode_header('to', to)
if settings.config.getboolean('general', 'ask_subject') and \
not 'Subject' in self.mail:
- subject = ui.prompt(prefix='Subject>')
+ subject = yield ui.prompt(prefix='Subject>')
if subject == None:
ui.notify('canceled')
return
@@ -728,12 +730,13 @@ class SaveAttachmentCommand(Command):
self.all = all
self.path = path
+ @defer.inlineCallbacks
def apply(self, ui):
pcomplete = completion.PathCompleter()
if self.all:
msg = ui.current_buffer.get_selected_message()
if not self.path:
- self.path = ui.prompt(prefix='save attachments to:',
+ self.path = yield ui.prompt(prefix='save attachments to:',
text=os.path.join('~', ''),
completer=pcomplete)
if self.path:
@@ -752,7 +755,7 @@ class SaveAttachmentCommand(Command):
attachment = focus.get_attachment()
filename = attachment.get_filename()
if not self.path:
- self.path = ui.prompt(prefix='save attachment as:',
+ self.path = yield ui.prompt(prefix='save attachment as:',
text=os.path.join('~', filename),
completer=pcomplete)
if self.path:
diff --git a/alot/ui.py b/alot/ui.py
index 74d5aa51..1ee366f1 100644
--- a/alot/ui.py
+++ b/alot/ui.py
@@ -19,6 +19,7 @@ Copyright (C) 2011 Patrick Totzke <patricktotzke@gmail.com>
import urwid
import os
from urwid.command_map import command_map
+from twisted.internet import defer
from settings import config
from buffer import BufferlistBuffer
@@ -30,7 +31,7 @@ from completion import CommandLineCompleter
class MainWidget(urwid.Frame):
def __init__(self, ui, *args, **kwargs):
- urwid.Frame.__init__(self, urwid.SolidFill(' '), *args, **kwargs)
+ urwid.Frame.__init__(self, urwid.SolidFill(), *args, **kwargs)
self.ui = ui
def keypress(self, size, key):
@@ -61,6 +62,7 @@ class UI:
self.mainloop = urwid.MainLoop(self.mainframe,
config.get_palette(),
handle_mouse=False,
+ event_loop=urwid.TwistedEventLoop(),
unhandled_input=self.keypress)
self.mainloop.screen.set_terminal_properties(colors=colourmode)
@@ -91,59 +93,41 @@ class UI:
:type tab: int
:param history: history to be used for up/down keys
:type history: list of str
+ :returns: a `twisted.defer.Deferred`
"""
- self.logger.info('open prompt')
- history = list(history) # make a local copy
- historypos = None
+ d = defer.Deferred() # create return deferred
+ main = self.mainloop.widget # save main widget
+
+ def select_or_cancel(text):
+ self.mainloop.widget = main # restore main screen
+ d.callback(text)
+
+ #set up widgets
leftpart = urwid.Text(prefix, align='left')
- if completer:
- editpart = CompleteEdit(completer, edit_text=text)
- for i in range(tab):
- editpart.keypress((0,), 'tab')
- else:
- editpart = urwid.Edit(edit_text=text)
+ editpart = CompleteEdit(completer, on_exit=select_or_cancel,
+ edit_text=text, history=history)
+
+ for i in range(tab): # hit some tabs
+ editpart.keypress((0,), 'tab')
+
+ # build promptwidget
both = urwid.Columns(
[
('fixed', len(prefix), leftpart),
('weight', 1, editpart),
])
prompt_widget = urwid.AttrMap(both, 'prompt', 'prompt')
- footer = self.mainframe.get_footer()
- self.mainframe.set_footer(prompt_widget)
- self.mainframe.set_focus('footer')
- self.mainloop.draw_screen()
- while True:
- keys = None
- while not keys:
- keys = self.mainloop.screen.get_input()
- for key in keys:
- self.logger.debug('prompt got key: %s' % key)
- if command_map[key] == 'select':
- self.mainframe.set_footer(footer)
- self.mainframe.set_focus('body')
- return editpart.get_edit_text()
- elif command_map[key] == 'cancel':
- self.mainframe.set_footer(footer)
- self.mainframe.set_focus('body')
- return None
- elif key in ['up', 'down']:
- if history:
- if historypos == None:
- history.append(editpart.get_edit_text())
- historypos = len(history) - 1
- if key == 'cursor up':
- historypos = (historypos - 1) % len(history)
- else:
- historypos = (historypos + 1) % len(history)
- editpart.set_edit_text(history[historypos])
- self.mainloop.draw_screen()
-
- else:
- size = (20,) # don't know why they want a size here
- editpart.keypress(size, key)
- self.mainloop.draw_screen()
+ # put promptwidget as overlay on main widget
+ overlay = urwid.Overlay(both, main,
+ ('fixed left', 0),
+ ('fixed right', 0),
+ ('fixed bottom', 1),
+ None)
+ self.mainloop.widget = overlay
+ return d # return deferred
+ @defer.inlineCallbacks
def commandprompt(self, startstring):
"""prompt for a commandline and interpret/apply it upon enter
@@ -152,15 +136,15 @@ class UI:
"""
self.logger.info('open command shell')
mode = self.current_buffer.typename
- cmdline = self.prompt(prefix=':',
+ cmdline = yield self.prompt(prefix=':',
text=startstring,
completer=CommandLineCompleter(self.dbman,
self.accountman,
mode),
history=self.commandprompthistory,
)
- if cmdline:
- self.interpret_commandline(cmdline)
+ self.logger.debug('CMDLINE: %s' % cmdline)
+ self.interpret_commandline(cmdline)
def interpret_commandline(self, cmdline):
"""interpret and apply a commandstring
@@ -168,13 +152,14 @@ class UI:
:param cmdline: command string to apply
:type cmdline: str
"""
- mode = self.current_buffer.typename
- self.commandprompthistory.append(cmdline)
- cmd = interpret_commandline(cmdline, mode)
- if cmd:
- self.apply_command(cmd)
- else:
- self.notify('invalid command')
+ if cmdline:
+ mode = self.current_buffer.typename
+ self.commandprompthistory.append(cmdline)
+ cmd = interpret_commandline(cmdline, mode)
+ if cmd:
+ self.apply_command(cmd)
+ else:
+ self.notify('invalid command')
def buffer_open(self, b):
"""
diff --git a/alot/widgets.py b/alot/widgets.py
index 4fe7439b..a5b08673 100644
--- a/alot/widgets.py
+++ b/alot/widgets.py
@@ -63,7 +63,7 @@ class ThreadlineWidget(urwid.AttrMap):
authors = self.thread.get_authors() or '(None)'
maxlength = config.getint('general', 'authors_maxlength')
- authorsstring = shorten(authors, maxlength).strip()
+ authorsstring = shorten(authors, maxlength)
self.authors_w = urwid.AttrMap(urwid.Text(authorsstring),
'threadline_authors')
cols.append(('fixed', len(authorsstring), self.authors_w))
@@ -167,8 +167,13 @@ class TagWidget(urwid.AttrMap):
class CompleteEdit(urwid.Edit):
- def __init__(self, completer, edit_text=u'', **kwargs):
+ def __init__(self, completer, on_exit, edit_text=u'',
+ history=None, **kwargs):
self.completer = completer
+ self.on_exit = on_exit
+ self.history = list(history) # we temporarily add stuff here
+ self.historypos = None
+
if not isinstance(edit_text, unicode):
edit_text = unicode(edit_text, errors='replace')
self.start_completion_pos = len(edit_text)
@@ -178,7 +183,7 @@ class CompleteEdit(urwid.Edit):
def keypress(self, size, key):
cmd = command_map[key]
# if we tabcomplete
- if cmd in ['next selectable', 'prev selectable']:
+ if cmd in ['next selectable', 'prev selectable'] and self.completer:
# if not already in completion mode
if not self.completions:
self.completions = [(self.edit_text, self.edit_pos)] + \
@@ -199,6 +204,20 @@ class CompleteEdit(urwid.Edit):
if self.edit_pos >= len(self.edit_text):
self.edit_text += ' '
self.completions = None
+ elif key in ['up', 'down']:
+ if self.history:
+ if self.historypos == None:
+ self.history.append(self.edit_text)
+ self.historypos = len(self.history) - 1
+ if key == 'cursor up':
+ self.historypos = (self.historypos + 1) % len(self.history)
+ else:
+ self.historypos = (self.historypos - 1) % len(self.history)
+ self.set_edit_text(self.history[self.historypos])
+ elif cmd == 'select':
+ self.on_exit(self.edit_text)
+ elif cmd == 'cancel':
+ self.on_exit(None)
else:
result = urwid.Edit.keypress(self, size, key)
self.completions = None