diff options
author | Patrick Totzke <patricktotzke@gmail.com> | 2016-12-15 22:05:30 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-15 22:05:30 +0000 |
commit | ac5e05a515aa6a3b27ed23ce89840b15b900ce33 (patch) | |
tree | 4eb940772d132f378ca81ec235227554817d5386 /alot | |
parent | d633feddaf77c171aafe1586a6306c4ba67d29d6 (diff) | |
parent | 72baf0229ffdebfe2fcd71c82301885fda89db8b (diff) |
Merge pull request #885 from lucc/history
Save command line history across sessions
Diffstat (limited to 'alot')
-rw-r--r-- | alot/commands/globals.py | 12 | ||||
-rw-r--r-- | alot/commands/thread.py | 3 | ||||
-rw-r--r-- | alot/defaults/alot.rc.spec | 6 | ||||
-rw-r--r-- | alot/ui.py | 81 |
4 files changed, 97 insertions, 5 deletions
diff --git a/alot/commands/globals.py b/alot/commands/globals.py index 437b3644..d2d0285c 100644 --- a/alot/commands/globals.py +++ b/alot/commands/globals.py @@ -52,6 +52,7 @@ class ExitCommand(Command): for b in ui.buffers: b.cleanup() ui.apply_command(FlushCommand(callback=ui.exit)) + ui.cleanup() if ui.db_was_locked: msg = 'Database locked. Exit without saving?' @@ -765,10 +766,11 @@ class ComposeCommand(Command): else: cmpl = AccountCompleter() fromaddress = yield ui.prompt('From', completer=cmpl, - tab=1) + tab=1, history=ui.senderhistory) if fromaddress is None: raise CommandCanceled() + ui.senderhistory.append(fromaddress) self.envelope.add('From', fromaddress) # find out the right account @@ -820,12 +822,14 @@ class ComposeCommand(Command): append_remaining=allbooks) logging.debug(abooks) completer = ContactsCompleter(abooks) - to = yield ui.prompt('To', - completer=completer) + to = yield ui.prompt('To', completer=completer, + history=ui.recipienthistory) if to is None: raise CommandCanceled() - self.envelope.add('To', to.strip(' \t\n,')) + to = to.strip(' \t\n,') + ui.recipienthistory.append(to) + self.envelope.add('To', to) if settings.get('ask_subject') and \ 'Subject' not in self.envelope.headers: diff --git a/alot/commands/thread.py b/alot/commands/thread.py index 00ac3f45..4b2221de 100644 --- a/alot/commands/thread.py +++ b/alot/commands/thread.py @@ -436,7 +436,8 @@ class BounceMailCommand(Command): completer = ContactsCompleter(abooks) else: completer = None - to = yield ui.prompt('To', completer=completer) + to = yield ui.prompt('To', completer=completer, + history=ui.recipienthistory) if to is None: raise CommandCanceled() diff --git a/alot/defaults/alot.rc.spec b/alot/defaults/alot.rc.spec index 0bc4f9d9..d99a96e8 100644 --- a/alot/defaults/alot.rc.spec +++ b/alot/defaults/alot.rc.spec @@ -239,6 +239,12 @@ msg_summary_hides_threadwide_tags = boolean(default=True) # first in the account block is used. reply_account_header_priority = force_list(default=list(From,To,Cc,Envelope-To,X-Envelope-To,Delivered-To)) +# The number of command line history entries to save +# +# .. note:: You can set this to -1 to save *all* entries to disk but the +# history file might get *very* long. +history_size = integer(default=50) + # Key bindings [bindings] __many__ = string(default=None) @@ -2,7 +2,9 @@ # This file is released under the GNU GPL, version 3 or a later revision. # For further details see the COPYING file import logging +import os import signal + from twisted.internet import reactor, defer import urwid @@ -46,6 +48,10 @@ class UI(object): """interface mode identifier - type of current buffer""" self.commandprompthistory = [] """history of the command line prompt""" + self.senderhistory = [] + """history of the sender prompt""" + self.recipienthistory = [] + """history of the recipients prompt""" self.input_queue = [] """stores partial keyboard input""" self.last_commandline = None @@ -73,6 +79,21 @@ class UI(object): signal.signal(signal.SIGINT, self.handle_signal) signal.signal(signal.SIGUSR1, self.handle_signal) + # load histories + self._cache = os.path.join( + os.environ.get('XDG_CACHE_HOME', os.path.expanduser('~/.cache')), + 'alot', 'history') + self._cmd_hist_file = os.path.join(self._cache, 'commands') + self._sender_hist_file = os.path.join(self._cache, 'senders') + self._recipients_hist_file = os.path.join(self._cache, 'recipients') + size = settings.get('history_size') + self.commandprompthistory = self._load_history_from_file( + self._cmd_hist_file, size=size) + self.senderhistory = self._load_history_from_file( + self._sender_hist_file, size=size) + self.recipienthistory = self._load_history_from_file( + self._recipients_hist_file, size=size) + # set up main loop self.mainloop = urwid.MainLoop(self.root_widget, handle_mouse=False, @@ -663,3 +684,63 @@ class UI(object): if isinstance(self.current_buffer, SearchBuffer): self.current_buffer.rebuild() self.update() + + def cleanup(self): + """Do the final clean up before shutting down.""" + size = settings.get('history_size') + self._save_history_to_file(self.commandprompthistory, + self._cmd_hist_file, size=size) + self._save_history_to_file(self.senderhistory, self._sender_hist_file, + size=size) + self._save_history_to_file(self.recipienthistory, + self._recipients_hist_file, size=size) + + @staticmethod + def _load_history_from_file(path, size=-1): + """Load a history list from a file and split it into lines. + + :param path: the path to the file that should be loaded + :type path: str + :param size: the number of lines to load (0 means no lines, < 0 means + all lines) + :type size: int + :returns: a list of history items (the lines of the file) + :rtype: list(str) + """ + if size == 0: + return [] + if os.path.exists(path): + with open(path) as histfile: + lines = [line.rstrip('\n') for line in histfile] + if size > 0: + lines = lines[-size:] + return lines + else: + return [] + + @staticmethod + def _save_history_to_file(history, path, size=-1): + """Save a history list to a file for later loading (possibly in another + session). + + :param history: the history list to save + :type history: list(str) + :param path: the path to the file where to save the history + :param size: the number of lines to save (0 means no lines, < 0 means + all lines) + :type size: int + :type path: str + :returns: None + """ + if size == 0: + return + if size > 0: + history = history[-size:] + directory = os.path.dirname(path) + if not os.path.exists(directory): + os.makedirs(directory) + # Write linewise to avoid building a large string in menory. + with open(path, 'w') as histfile: + for line in history: + histfile.write(line) + histfile.write('\n') |