Commit 8eff0f0c authored by Bram Schoenmakers's avatar Bram Schoenmakers

Prompt mode: reload the todo.txt file if it was modified.

The todo.txt file can be modified while the prompt is running. Make sure
to reload the file when the mtime has changed since the previous load.

This addresses the issue that changes after the 'edit' subcommand were
not visible when returning to the topydo prompt (issue #33).

Also, other changes done while the prompt is running will be picked up.

A safety measure was taken to refuse executing a command when the
todo.txt file was modified while the prompt was visible (i.e. the user
was busy typing a command). By doing so, subcommands such as 'do' and
'del' will only operate on the actual state of the todo.txt file, not
some previous state still in memory.
parent 14dba229
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
""" Entry file for the topydo Prompt interface (CLI). """ """ Entry file for the topydo Prompt interface (CLI). """
import os.path
import sys import sys
from topydo.cli.CLIApplicationBase import CLIApplicationBase, error, usage from topydo.cli.CLIApplicationBase import CLIApplicationBase, error, usage
...@@ -39,6 +40,12 @@ from topydo.commands.SortCommand import SortCommand ...@@ -39,6 +40,12 @@ from topydo.commands.SortCommand import SortCommand
from topydo.lib import TodoFile from topydo.lib import TodoFile
from topydo.lib import TodoList from topydo.lib import TodoList
def _todotxt_mtime():
"""
Returns the mtime for the configured todo.txt file.
"""
return os.path.getmtime(config().todotxt())
class PromptApplication(CLIApplicationBase): class PromptApplication(CLIApplicationBase):
""" """
This class implements a variant of topydo's CLI showing a shell and This class implements a variant of topydo's CLI showing a shell and
...@@ -47,24 +54,50 @@ class PromptApplication(CLIApplicationBase): ...@@ -47,24 +54,50 @@ class PromptApplication(CLIApplicationBase):
def __init__(self): def __init__(self):
super(PromptApplication, self).__init__() super(PromptApplication, self).__init__()
def run(self): self._process_flags()
""" Main entry function. """ self.mtime = None
args = self._process_flags()
def _load_file(self):
"""
Reads the configured todo.txt file and loads it into the todo list
instance.
If the modification time of the todo.txt file is equal to the last time
it was checked, nothing will be done.
"""
current_mtime = _todotxt_mtime()
if self.mtime != current_mtime:
self.todofile = TodoFile.TodoFile(config().todotxt()) self.todofile = TodoFile.TodoFile(config().todotxt())
self.todolist = TodoList.TodoList(self.todofile.read()) self.todolist = TodoList.TodoList(self.todofile.read())
self.mtime = current_mtime
def run(self):
""" Main entry function. """
# suppress upstream issue with Python 2.7 # suppress upstream issue with Python 2.7
# pylint: disable=no-value-for-parameter # pylint: disable=no-value-for-parameter
completer = TopydoCompleter(self.todolist) completer = TopydoCompleter(self.todolist)
history = History() history = History()
while True: while True:
# (re)load the todo.txt file (only if it has been modified)
self._load_file()
try: try:
user_input = get_input(u'topydo> ', history=history, completer=completer).split() user_input = get_input(u'topydo> ', history=history,
completer=completer).split()
except (EOFError, KeyboardInterrupt): except (EOFError, KeyboardInterrupt):
sys.exit(0) sys.exit(0)
mtime_after = _todotxt_mtime()
if self.mtime != mtime_after:
# refuse to perform operations such as 'del' and 'do' if the
# todo.txt file has been changed in the background.
error("WARNING: todo.txt file was modified by another application.\nTo prevent unintended changes, this operation was not executed.")
continue
(subcommand, args) = get_subcommand(user_input) (subcommand, args) = get_subcommand(user_input)
try: try:
...@@ -80,8 +113,9 @@ class PromptApplication(CLIApplicationBase): ...@@ -80,8 +113,9 @@ class PromptApplication(CLIApplicationBase):
usage() usage()
def main(): def main():
""" Main entry point of the CLI. """ """ Main entry point of the prompt interface. """
PromptApplication().run() PromptApplication().run()
if __name__ == '__main__': if __name__ == '__main__':
main() main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment