Commit ebb3b4c2 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Make text editor more configurable

Lookup mechanism:

1. Check whether an editor was given with the -E flag:

     topydo edit -E vim

2. Use the value of $TOPYDO_EDITOR
3. Use the value in the configuration file:

   [edit]
   editor = vim

4. Use the value in $EDITOR
5. Use 'vi' if the above fails.

This makes it easier to invoke an editor as vim with additional
parameters, for instance by adding the full todo.txt file to the
completion options (see the tip in issue #164). This trick was added to
the configuration file as a comment.
parent 5e13411a
...@@ -36,6 +36,15 @@ append_parent_projects = 0 ...@@ -36,6 +36,15 @@ append_parent_projects = 0
; Add parent contexts when adding sub todo items ; Add parent contexts when adding sub todo items
append_parent_contexts = 0 append_parent_contexts = 0
[edit]
; Editor to use for the 'edit' subcommand (overrides the EDITOR environment
; variable, but can be overridden with the TOPYDO_EDITOR environment variable
; or the -E flag in the edit command)
; editor = vi
; Vim tip: enable completion using your complete todo.txt file. Use this as
; editor command:
; vim -c 'autocmd Filetype todo set complete=.,w,b,u,t,i,k~/notes/todo.txt'
[colorscheme] [colorscheme]
; Configure colorscheme. Accepted values are: black, [light-]red, [light-]green, ; Configure colorscheme. Accepted values are: black, [light-]red, [light-]green,
; [light-]yellow, [light-]blue, [light-]magenta, [light-]cyan, white ; [light-]yellow, [light-]blue, [light-]magenta, [light-]cyan, white
......
...@@ -23,10 +23,6 @@ from topydo.lib.Config import config ...@@ -23,10 +23,6 @@ from topydo.lib.Config import config
from topydo.lib.MultiCommand import MultiCommand from topydo.lib.MultiCommand import MultiCommand
from topydo.lib.prettyprinters.Numbers import PrettyPrinterNumbers from topydo.lib.prettyprinters.Numbers import PrettyPrinterNumbers
from topydo.lib.Todo import Todo from topydo.lib.Todo import Todo
from topydo.lib.TodoList import TodoList
# the true and only editor
DEFAULT_EDITOR = 'vi'
def _get_file_mtime(p_file): def _get_file_mtime(p_file):
return os.stat(p_file.name).st_mtime return os.stat(p_file.name).st_mtime
...@@ -39,20 +35,32 @@ class EditCommand(MultiCommand): ...@@ -39,20 +35,32 @@ class EditCommand(MultiCommand):
super().__init__(p_args, p_todolist, p_output, super().__init__(p_args, p_todolist, p_output,
p_error, p_input) p_error, p_input)
if len(self.args) == 0: self.editor = config().editor()
self.multi_mode = False
self.is_expression = False self.is_expression = False
self.edit_archive = False self.edit_archive = False
self.last_argument = False self.last_argument = False
def get_flags(self): def get_flags(self):
return ("d", []) return ("dE:", [])
def process_flag(self, p_opt, p_value): def process_flag(self, p_opt, p_value):
if p_opt == '-d': if p_opt == '-d':
self.edit_archive = True self.edit_archive = True
self.multi_mode = False self.multi_mode = False
elif p_opt == '-E':
self.editor = p_value
def _process_flags(self):
"""
Override to add an additional check after processing the flags: when
there are no flags left after argument parsing, then it means we'll be
editing the whole todo.txt file as a whole and therefore we're not in
multi mode.
"""
super()._process_flags()
if len(self.args) == 0:
self.multi_mode = False
def _todos_to_temp(self): def _todos_to_temp(self):
f = tempfile.NamedTemporaryFile(delete=False, suffix='.todo.txt') f = tempfile.NamedTemporaryFile(delete=False, suffix='.todo.txt')
...@@ -74,18 +82,13 @@ class EditCommand(MultiCommand): ...@@ -74,18 +82,13 @@ class EditCommand(MultiCommand):
def _open_in_editor(self, p_file): def _open_in_editor(self, p_file):
try: try:
editor = os.environ['EDITOR'] or DEFAULT_EDITOR return check_call(config().editor() + [p_file])
except(KeyError):
editor = DEFAULT_EDITOR
try:
return check_call([editor, p_file])
except CalledProcessError: except CalledProcessError:
self.error('Something went wrong in the editor...') self.error('Something went wrong in the editor...')
return 1 return 1
except(OSError): except OSError:
self.error('There is no such editor as: ' + editor + '. ' self.error('There is no such editor as: ' + self.editor + '. '
'Check your $EDITOR and/or $PATH') 'Check your configuration file, $TOPYDO_EDITOR, $EDITOR and/or $PATH')
def _catch_todo_errors(self): def _catch_todo_errors(self):
errors = [] errors = []
...@@ -134,12 +137,13 @@ class EditCommand(MultiCommand): ...@@ -134,12 +137,13 @@ class EditCommand(MultiCommand):
return self._open_in_editor(todo) == 0 return self._open_in_editor(todo) == 0
def usage(self): def usage(self):
return """Synopsis: return """Synopsis:
edit edit [-E <EDITOR>]
edit <NUMBER 1> [<NUMBER 2> ...] edit [-E <EDITOR>] <NUMBER 1> [<NUMBER 2> ...]
edit -e [-x] [EXPRESSION] edit [-E <EDITOR>] -e [-x] [EXPRESSION]
edit -d""" edit [-E <EDITOR>] -d"""
def help(self): def help(self):
return """\ return """\
...@@ -150,10 +154,15 @@ edit todo item(s) with the given NUMBER(s) or edit relevant todos matching ...@@ -150,10 +154,15 @@ edit todo item(s) with the given NUMBER(s) or edit relevant todos matching
the given EXPRESSION. See `topydo help ls` for more information on relevant the given EXPRESSION. See `topydo help ls` for more information on relevant
todo items. It is also possible to open the archive file. todo items. It is also possible to open the archive file.
By default it will look to your environment variable $EDITOR, otherwise it will The editor is chosen as follows:
fall back to 'vi'. 1. Check whether the -E flag is given and use it;
2. Use the value of $TOPYDO_EDITOR in the environment;
3. Use the value in the configuration file;
4. Use the value of $EDITOR in the environment;
5. If all else fails, use 'vi'.
-e : Treat the subsequent arguments as an EXPRESSION. -e : Treat the subsequent arguments as an EXPRESSION.
-E : Editor to start.
-x : Edit *all* todos matching the EXPRESSION (i.e. do not filter on -x : Edit *all* todos matching the EXPRESSION (i.e. do not filter on
dependencies or relevance). dependencies or relevance).
-d : Open the archive file.\ -d : Open the archive file.\
......
...@@ -101,6 +101,9 @@ class _Config: ...@@ -101,6 +101,9 @@ class _Config:
'append_parent_contexts': '0', 'append_parent_contexts': '0',
}, },
'edit': {
},
'colorscheme': { 'colorscheme': {
'project_color': 'red', 'project_color': 'red',
'context_color': 'magenta', 'context_color': 'magenta',
...@@ -448,6 +451,23 @@ class _Config: ...@@ -448,6 +451,23 @@ class _Config:
return (keymap_dict, keystates) return (keymap_dict, keystates)
def editor(self):
"""
Returns the editor to invoke. It returns a list with the command in
the first position and its arguments in the remainder.
"""
result = 'vi'
if 'TOPYDO_EDITOR' in os.environ and os.environ['TOPYDO_EDITOR']:
result = os.environ['TOPYDO_EDITOR']
else:
try:
result = str(self.cp.get('edit', 'editor'))
except configparser.NoOptionError:
if 'EDITOR' in os.environ and os.environ['EDITOR']:
result = os.environ['EDITOR']
return shlex.split(result)
def config(p_path=None, p_overrides=None): def config(p_path=None, p_overrides=None):
""" """
......
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