Commit c91d56bc authored by Jacek Sowiński's avatar Jacek Sowiński

Very early implementation of editing todos in $EDITOR

implements #2

- `topydo edit` will still open todofile in $EDITOR
- `topydo edit 1 2 3` will open tmpfile with corresponding todos
- `topydo edit -e @Home due:today` will open tmpfile with todos matching
   the expression
parent 1139c19f
......@@ -15,27 +15,122 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
from subprocess import call
from subprocess import call, check_call, CalledProcessError
import tempfile
from topydo.lib.Command import Command
from topydo.lib.ListCommand import ListCommand
from topydo.lib.MultiCommand import MultiCommand
from topydo.lib.Config import config
from topydo.lib.Todo import Todo
from topydo.lib.TodoListBase import InvalidTodoException
from topydo.lib.TodoList import TodoList
from topydo.lib.PrettyPrinterFilter import PrettyPrinterNumbers
class EditCommand(Command):
class EditCommand(MultiCommand, ListCommand):
def __init__(self, p_args, p_todolist, p_output, p_error, p_input):
super(EditCommand, self).__init__(p_args, p_todolist, p_output,
p_error, p_input)
self.is_expression = False
def _process_flags(self):
opts, args = self.getopt('xe')
for opt, value in opts:
if opt == '-x':
self.show_all = True
elif opt == '-e':
self.is_expression = True
self.args = args
def _todos_to_temp(self):
f = tempfile.NamedTemporaryFile()
for todo in self.todos:
f.write("%s\n" % todo.__str__())
f.seek(0)
return f
def _todos_from_temp(self, temp_file):
temp_file.seek(0)
todos = temp_file.read().splitlines()
todo_objs = []
for todo in todos:
todo_objs.append(Todo(todo))
return todo_objs
def _open_in_editor(self, temp_file, editor):
try:
return check_call([editor, temp_file.name])
except(CalledProcessError):
self.error('Something went wrong in the editor...')
return 1
def _catch_todo_errors(self):
errors = []
if len(self.invalid_numbers) > 1 or len(self.invalid_numbers) > 0 and len(self.todos) > 0:
for number in self.invalid_numbers:
errors.append("Invalid todo number given: {}.".format(number))
elif len(self.invalid_numbers) == 1 and len(self.todos) == 0:
errors.append("Invalid todo number given.")
if len(errors) > 0:
return errors
else:
return None
def execute(self):
if not super(EditCommand, self).execute():
if not super(ListCommand, self).execute():
return False
self.printer.add_filter(PrettyPrinterNumbers(self.todolist))
try:
editor = os.environ['EDITOR'] or 'vi'
except(KeyError):
editor = 'vi'
todo = config().todotxt()
return call([editor, todo]) == 0
try:
if len(self.args) < 1:
todo = config().todotxt()
return call([editor, todo]) == 0
else:
self._process_flags()
if self.is_expression:
self.todos = self._view()._viewdata
else:
self.get_todos(self.args)
todo_errors = self._catch_todo_errors()
if not todo_errors:
temp_todos = self._todos_to_temp()
if not self._open_in_editor(temp_todos, editor):
new_todos = self._todos_from_temp(temp_todos)
if len(new_todos) == len(self.todos):
for todo in self.todos:
super(TodoList, self.todolist).delete(todo)
for todo in new_todos:
self.todolist.add_todo(todo)
self.out(self.printer.print_todo(todo))
else:
self.error('Number of edited todos is not equal to '
'number of supplied todo IDs.')
else:
self.error(self.usage())
else:
for error in todo_errors:
self.error(error)
except(OSError):
self.error('There is no such editor as: ' + editor + '. '
'Check your $EDITOR and/or $PATH')
def usage(self):
return """Synopsis: edit"""
......
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