Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
topydo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
topydo
Commits
edc11eeb
Commit
edc11eeb
authored
Feb 10, 2017
by
Bram Schoenmakers
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'editor'
parents
4570a210
f6a38845
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
150 additions
and
29 deletions
+150
-29
test/test_edit_command.py
test/test_edit_command.py
+88
-6
topydo.conf
topydo.conf
+9
-0
topydo/commands/EditCommand.py
topydo/commands/EditCommand.py
+33
-23
topydo/lib/Config.py
topydo/lib/Config.py
+20
-0
No files found.
test/test_edit_command.py
View file @
edc11eeb
...
@@ -162,13 +162,12 @@ class EditCommandTest(CommandTest):
...
@@ -162,13 +162,12 @@ class EditCommandTest(CommandTest):
self
.
assertEqual
(
self
.
output
,
expected
)
self
.
assertEqual
(
self
.
output
,
expected
)
self
.
assertEqual
(
self
.
todolist
.
print_todos
(),
u"Foo id:1
\
n
Fo
\
u00f3
B
\
u0105
\
u017a
\
n
Lazy Cat
\
n
Lazy Dog"
)
self
.
assertEqual
(
self
.
todolist
.
print_todos
(),
u"Foo id:1
\
n
Fo
\
u00f3
B
\
u0105
\
u017a
\
n
Lazy Cat
\
n
Lazy Dog"
)
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
'vi'
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_archive
(
self
,
mock_call
):
def
test_edit_archive
(
self
,
mock_call
):
""" Edit archive file. """
""" Edit archive file. """
mock_call
.
return_value
=
0
mock_call
.
return_value
=
0
editor
=
'vi'
os
.
environ
[
'EDITOR'
]
=
editor
archive
=
config
().
archive
()
archive
=
config
().
archive
()
command
=
EditCommand
([
"-d"
],
self
.
todolist
,
self
.
out
,
self
.
error
,
command
=
EditCommand
([
"-d"
],
self
.
todolist
,
self
.
out
,
self
.
error
,
...
@@ -176,15 +175,14 @@ class EditCommandTest(CommandTest):
...
@@ -176,15 +175,14 @@ class EditCommandTest(CommandTest):
command
.
execute
()
command
.
execute
()
self
.
assertEqual
(
self
.
errors
,
""
)
self
.
assertEqual
(
self
.
errors
,
""
)
mock_call
.
assert_called_once_with
([
editor
,
archive
])
mock_call
.
assert_called_once_with
([
'vi'
,
archive
])
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
'vi'
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_todotxt
(
self
,
mock_call
):
def
test_edit_todotxt
(
self
,
mock_call
):
""" Edit todo file. """
""" Edit todo file. """
mock_call
.
return_value
=
0
mock_call
.
return_value
=
0
editor
=
'vi'
os
.
environ
[
'EDITOR'
]
=
editor
todotxt
=
config
().
todotxt
()
todotxt
=
config
().
todotxt
()
result
=
self
.
todolist
.
print_todos
()
# copy TodoList content *before* executing command
result
=
self
.
todolist
.
print_todos
()
# copy TodoList content *before* executing command
...
@@ -194,7 +192,91 @@ class EditCommandTest(CommandTest):
...
@@ -194,7 +192,91 @@ class EditCommandTest(CommandTest):
self
.
assertEqual
(
self
.
errors
,
""
)
self
.
assertEqual
(
self
.
errors
,
""
)
self
.
assertEqual
(
self
.
todolist
.
print_todos
(),
result
)
self
.
assertEqual
(
self
.
todolist
.
print_todos
(),
result
)
mock_call
.
assert_called_once_with
([
editor
,
todotxt
])
mock_call
.
assert_called_once_with
([
'vi'
,
todotxt
])
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
'vi'
})
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'TOPYDO_EDITOR'
:
'nano'
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_editor1
(
self
,
mock_call
):
""" $TOPYDO_EDITOR overrides $EDITOR """
mock_call
.
return_value
=
0
todotxt
=
config
().
todotxt
()
command
=
EditCommand
([],
self
.
todolist
,
self
.
out
,
self
.
error
,
None
)
command
.
execute
()
self
.
assertEqual
(
self
.
errors
,
""
)
mock_call
.
assert_called_once_with
([
'nano'
,
todotxt
])
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
'vi'
})
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'TOPYDO_EDITOR'
:
'nano'
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_editor2
(
self
,
mock_call
):
""" $TOPYDO_EDITOR overrides $EDITOR """
mock_call
.
return_value
=
0
todotxt
=
config
().
todotxt
()
command
=
EditCommand
([],
self
.
todolist
,
self
.
out
,
self
.
error
,
None
)
command
.
execute
()
self
.
assertEqual
(
self
.
errors
,
""
)
mock_call
.
assert_called_once_with
([
'nano'
,
todotxt
])
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
'vi'
})
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'TOPYDO_EDITOR'
:
'nano'
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_editor3
(
self
,
mock_call
):
""" Editor on commandline overrides $TOPYDO_EDITOR """
mock_call
.
return_value
=
0
command
=
EditCommand
([
"-E"
,
"foo"
],
self
.
todolist
,
self
.
out
,
self
.
error
,
None
)
command
.
execute
()
self
.
assertEqual
(
self
.
errors
,
""
)
mock_call
.
assert_called_once_with
([
'foo'
,
config
().
todotxt
()])
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
'vi'
})
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'TOPYDO_EDITOR'
:
'nano'
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_editor4
(
self
,
mock_call
):
""" Editor in configuration file is overridden by $TOPYDO_EDITOR """
mock_call
.
return_value
=
0
config
(
p_overrides
=
{(
'edit'
,
'editor'
):
'foo'
})
command
=
EditCommand
([],
self
.
todolist
,
self
.
out
,
self
.
error
,
None
)
command
.
execute
()
self
.
assertEqual
(
self
.
errors
,
""
)
mock_call
.
assert_called_once_with
([
'nano'
,
config
().
todotxt
()])
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
'vi'
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_editor5
(
self
,
mock_call
):
""" Editor in configuration file overrides $EDITOR """
mock_call
.
return_value
=
0
config
(
p_overrides
=
{(
'edit'
,
'editor'
):
'foo'
})
command
=
EditCommand
([],
self
.
todolist
,
self
.
out
,
self
.
error
,
None
)
command
.
execute
()
self
.
assertEqual
(
self
.
errors
,
""
)
mock_call
.
assert_called_once_with
([
'foo'
,
config
().
todotxt
()])
@
mock
.
patch
.
dict
(
os
.
environ
,
{
'EDITOR'
:
''
})
@
mock
.
patch
(
'topydo.commands.EditCommand.check_call'
)
def
test_edit_editor6
(
self
,
mock_call
):
""" Ultimate fallback is vi """
mock_call
.
return_value
=
0
command
=
EditCommand
([],
self
.
todolist
,
self
.
out
,
self
.
error
,
None
)
command
.
execute
()
self
.
assertEqual
(
self
.
errors
,
""
)
mock_call
.
assert_called_once_with
([
'vi'
,
config
().
todotxt
()])
def
test_edit_name
(
self
):
def
test_edit_name
(
self
):
name
=
EditCommand
.
name
()
name
=
EditCommand
.
name
()
...
...
topydo.conf
View file @
edc11eeb
...
@@ -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
...
...
topydo/commands/EditCommand.py
View file @
edc11eeb
...
@@ -17,16 +17,13 @@
...
@@ -17,16 +17,13 @@
import
os
import
os
import
codecs
import
codecs
import
tempfile
import
tempfile
import
shlex
from
subprocess
import
CalledProcessError
,
check_call
from
subprocess
import
CalledProcessError
,
check_call
from
topydo.lib.Config
import
config
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 +36,32 @@ class EditCommand(MultiCommand):
...
@@ -39,20 +36,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
(
"d
E:
"
,
[])
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
=
shlex
.
split
(
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 +83,13 @@ class EditCommand(MultiCommand):
...
@@ -74,18 +83,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
(
self
.
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 +138,13 @@ class EditCommand(MultiCommand):
...
@@ -134,12 +138,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 +155,15 @@ edit todo item(s) with the given NUMBER(s) or edit relevant todos matching
...
@@ -150,10 +155,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.
\
...
...
topydo/lib/Config.py
View file @
edc11eeb
...
@@ -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
):
"""
"""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment