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
; Add parent contexts when adding sub todo items
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]
; Configure colorscheme. Accepted values are: black, [light-]red, [light-]green,
; [light-]yellow, [light-]blue, [light-]magenta, [light-]cyan, white
......
......@@ -23,10 +23,6 @@ from topydo.lib.Config import config
from topydo.lib.MultiCommand import MultiCommand
from topydo.lib.prettyprinters.Numbers import PrettyPrinterNumbers
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):
return os.stat(p_file.name).st_mtime
......@@ -39,20 +35,32 @@ class EditCommand(MultiCommand):
super().__init__(p_args, p_todolist, p_output,
p_error, p_input)
if len(self.args) == 0:
self.multi_mode = False
self.editor = config().editor()
self.is_expression = False
self.edit_archive = False
self.last_argument = False
def get_flags(self):
return ("d", [])
return ("dE:", [])
def process_flag(self, p_opt, p_value):
if p_opt == '-d':
self.edit_archive = True
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):
f = tempfile.NamedTemporaryFile(delete=False, suffix='.todo.txt')
......@@ -74,18 +82,13 @@ class EditCommand(MultiCommand):
def _open_in_editor(self, p_file):
try:
editor = os.environ['EDITOR'] or DEFAULT_EDITOR
except(KeyError):
editor = DEFAULT_EDITOR
try:
return check_call([editor, p_file])
return check_call(config().editor() + [p_file])
except CalledProcessError:
self.error('Something went wrong in the editor...')
return 1
except(OSError):
self.error('There is no such editor as: ' + editor + '. '
'Check your $EDITOR and/or $PATH')
except OSError:
self.error('There is no such editor as: ' + self.editor + '. '
'Check your configuration file, $TOPYDO_EDITOR, $EDITOR and/or $PATH')
def _catch_todo_errors(self):
errors = []
......@@ -134,12 +137,13 @@ class EditCommand(MultiCommand):
return self._open_in_editor(todo) == 0
def usage(self):
return """Synopsis:
edit
edit <NUMBER 1> [<NUMBER 2> ...]
edit -e [-x] [EXPRESSION]
edit -d"""
edit [-E <EDITOR>]
edit [-E <EDITOR>] <NUMBER 1> [<NUMBER 2> ...]
edit [-E <EDITOR>] -e [-x] [EXPRESSION]
edit [-E <EDITOR>] -d"""
def help(self):
return """\
......@@ -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
todo items. It is also possible to open the archive file.
By default it will look to your environment variable $EDITOR, otherwise it will
fall back to 'vi'.
The editor is chosen as follows:
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 : Editor to start.
-x : Edit *all* todos matching the EXPRESSION (i.e. do not filter on
dependencies or relevance).
-d : Open the archive file.\
......
......@@ -101,6 +101,9 @@ class _Config:
'append_parent_contexts': '0',
},
'edit': {
},
'colorscheme': {
'project_color': 'red',
'context_color': 'magenta',
......@@ -448,6 +451,23 @@ class _Config:
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):
"""
......
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