Skip to content

Commit 987370c

Browse files
nkakourostbabej
andcommitted
Adds TaskWikiOpen and TaskWikiNote commands
Co-authored-by: Tomas Babej <[email protected]>
1 parent 925d8ed commit 987370c

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

doc/taskwiki.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ vn m |:TaskWikiMod|
531531
n t |:TaskWikiTags|
532532
vn + |:TaskWikiStart|
533533
vn - |:TaskWikiStop|
534+
n o |:TaskWikiOpen|
535+
n n |:TaskWikiNote|
534536

535537
=============================================================================
536538
7. COMMANDS *taskwiki-commands*
@@ -634,6 +636,16 @@ selected tasks.
634636

635637
Supports |cmdline-completion|.
636638

639+
*:TaskWikiOpen*
640+
Opens annotations in the selected task(s) containing links to local files,
641+
urls, etc. This command requires taskopen to be installed
642+
(https://github.com/jschlatow/taskopen).
643+
644+
*:TaskWikiNote*
645+
Adds a note to the task under cursor and opens it to be edited. This
646+
command requires taskopen to be installed
647+
(https://github.com/jschlatow/taskopen).
648+
637649
----------------------------------------------------------------------------
638650
Interactive commands.
639651

ftplugin/vimwiki/taskwiki.vim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ execute "command! -buffer -nargs=* TaskWikiTags :" . g:taskwiki_py .
7575

7676
" Commands that operate on tasks in the buffer
7777
execute "command! -buffer -range TaskWikiInfo :<line1>,<line2>" . g:taskwiki_py . "SelectedTasks().info()"
78+
execute "command! -buffer -range TaskWikiOpen :<line1>,<line2>" . g:taskwiki_py . "SelectedTasks().taskopen('open')"
79+
execute "command! -buffer -range TaskWikiNote :<line1>,<line2>" . g:taskwiki_py . "SelectedTasks().taskopen('note')"
7880
execute "command! -buffer -range TaskWikiEdit :<line1>,<line2>" . g:taskwiki_py . "SelectedTasks().edit()"
7981
execute "command! -buffer -range TaskWikiLink :<line1>,<line2>" . g:taskwiki_py . "SelectedTasks().link()"
8082
execute "command! -buffer -range TaskWikiGrid :<line1>,<line2>" . g:taskwiki_py . "SelectedTasks().grid()"
@@ -130,6 +132,8 @@ if !exists('g:taskwiki_suppress_mappings')
130132
nnoremap <silent><buffer> <LocalLeader>hm :TaskWikiHistoryMonthly<CR>
131133
nnoremap <silent><buffer> <LocalLeader>ha :TaskWikiHistoryAnnual<CR>
132134
nnoremap <silent><buffer> <LocalLeader>i :TaskWikiInfo<CR>
135+
nnoremap <silent><buffer> <LocalLeader>o :TaskWikiOpen<CR>
136+
nnoremap <silent><buffer> <LocalLeader>n :TaskWikiNote<CR>
133137
nnoremap <silent><buffer> <LocalLeader>l :TaskWikiLink<CR>
134138
nnoremap <silent><buffer> <LocalLeader>m :TaskWikiMod<CR>
135139
nnoremap <silent><buffer> <LocalLeader>p :TaskWikiProjects<CR>
@@ -149,6 +153,8 @@ if !exists('g:taskwiki_suppress_mappings')
149153
vnoremap <silent><buffer> <LocalLeader>e :TaskWikiEdit<CR>
150154
vnoremap <silent><buffer> <LocalLeader>g :TaskWikiGrid<CR>
151155
vnoremap <silent><buffer> <LocalLeader>i :TaskWikiInfo<CR>
156+
vnoremap <silent><buffer> <LocalLeader>o :TaskWikiOpen<CR>
157+
vnoremap <silent><buffer> <LocalLeader>n :TaskWikiNote<CR>
152158
vnoremap <silent><buffer> <LocalLeader>l :TaskWikiLink<CR>
153159
vnoremap <silent><buffer> <LocalLeader>m :TaskWikiMod<CR>
154160
vnoremap <silent><buffer> <LocalLeader>. :TaskWikiRedo<CR>

taskwiki/main.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,40 @@ def info(self):
125125
util.show_in_split(out, name='info', activate_cursorline=True)
126126
break # Show only one task
127127

128+
@errors.pretty_exception_handler
129+
def taskopen(self, mode):
130+
if mode == "note":
131+
args = "-n {task_id} -x 'echo'"
132+
if mode == "open":
133+
args = "-N {task_id}"
134+
135+
for vimwikitask in self.tasks:
136+
output, exit_status = util.taskopen(args.format(task_id=vimwikitask["id"]))
137+
138+
if mode == "note":
139+
if exit_status:
140+
vim.command("echohl Error")
141+
vim.command('echo "%s"' % output)
142+
vim.command("echohl None")
143+
# Using `echoerr` is too verbose and scary, using
144+
# echohl+echo instead.
145+
else:
146+
vim.command("edit " + output)
147+
148+
if mode == "open":
149+
if exit_status:
150+
error_msg = "taskopen failed to open task " + str(
151+
vimwikitask["id"]
152+
)
153+
154+
vim.command('echo "%s"' % output)
155+
vim.command("echohl Error")
156+
vim.command('echo "%s"' % error_msg)
157+
vim.command("echohl None")
158+
159+
else:
160+
vim.command("echomsg 'Opened task %s'" % vimwikitask["id"])
161+
128162
@errors.pretty_exception_handler
129163
def edit(self):
130164
for vimwikitask in self.tasks:

taskwiki/util.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import contextlib
66
import os
7+
import pexpect
78
import random
89
import sys
910
import vim # pylint: disable=F0401
@@ -96,6 +97,8 @@ def tw_args_to_kwargs(args):
9697
return output
9798

9899
def get_input(prompt="Enter: ", allow_empty=False, completion=None):
100+
prompt = prompt.replace('"', '\\"')
101+
99102
if completion is not None:
100103
value = vim.eval('input("%s", "", "%s")' % (prompt, completion))
101104
else:
@@ -441,3 +444,48 @@ def is_midnight(dt):
441444
"""
442445

443446
return dt.hour == 0 and dt.minute == 0 and dt.second == 0
447+
448+
def taskopen(args):
449+
"""
450+
Runs taskopen, handles its interactive prompts, returns final output.
451+
452+
Params:
453+
args - arguments to be passed to the taskopen command
454+
"""
455+
try:
456+
p = pexpect.spawn(
457+
"taskopen " + args,
458+
timeout=3,
459+
echo=False,
460+
)
461+
462+
prompts = [
463+
"Type number\(s\): ",
464+
"Config file.* does not exist. Do you want to create it? (Y/n)"
465+
]
466+
467+
while not p.eof():
468+
index = p.expect([pexpect.EOF, *prompts])
469+
470+
if index == 0:
471+
last_lines = p.before.splitlines()
472+
else:
473+
prompt = p.before.splitlines()
474+
prompt += [bytes(prompts[index-1].replace('.*', ''), "utf-8")]
475+
476+
input = get_input(b"\n".join(prompt).decode("utf-8"))
477+
478+
p.sendline(input)
479+
480+
p.close(force=True) # make sure the process is ended
481+
482+
except pexpect.exceptions.ExceptionPexpect as e:
483+
if "command was not found" not in e.value:
484+
return "taskopen is not installed", 127
485+
486+
if p.exitstatus == 3: # xdg-open: no method to open annotation
487+
last_lines = [last_lines[-1]]
488+
489+
last_lines = [l.decode("utf-8").rstrip("\r\n") for l in last_lines]
490+
491+
return "\n".join(last_lines).strip(), p.exitstatus

0 commit comments

Comments
 (0)