diff --git a/after/ftplugin/vimwiki.vim b/after/ftplugin/vimwiki.vim new file mode 100644 index 0000000..c66ccdf --- /dev/null +++ b/after/ftplugin/vimwiki.vim @@ -0,0 +1,5 @@ +if exists('b:did_ftplugin_taskwiki_after') | finish | endif +let b:did_ftplugin_taskwiki_after = 1 + +let b:taskwiki_omnifunc_fallback = len(&omnifunc) ? function(&omnifunc) : '' +setlocal omnifunc=taskwiki#CompleteOmni diff --git a/autoload/taskwiki.vim b/autoload/taskwiki.vim index 0fe00ab..7f9e78f 100644 --- a/autoload/taskwiki.vim +++ b/autoload/taskwiki.vim @@ -36,3 +36,33 @@ endfunction function! taskwiki#CompleteMod(arglead, line, pos) abort return py3eval('cache().get_relevant_completion().modify(vim.eval("a:arglead"))') endfunction + +function! taskwiki#CompleteOmni(findstart, base) abort + if a:findstart == 1 + let line = getline('.')[:col('.')-2] + + " Complete modstring after -- in new tasks + let modstring = py3eval('cache().get_relevant_completion().omni_modstring_findstart(vim.eval("l:line"))') + if modstring >= 0 + let s:omni_method = 'modstring' + return modstring + endif + + " Fallback to vimwiki's omnifunc + if type(b:taskwiki_omnifunc_fallback) is v:t_func + let s:omni_method = 'fallback' + return b:taskwiki_omnifunc_fallback(a:findstart, a:base) + else + let s:omni_method = '' + return -1 + endif + else + if s:omni_method is 'modstring' + return py3eval('cache().get_relevant_completion().omni_modstring(vim.eval("a:base"))') + elseif s:omni_method is 'fallback' + return b:taskwiki_omnifunc_fallback(a:findstart, a:base) + else + return [] + endif + endif +endfunction diff --git a/doc/taskwiki.txt b/doc/taskwiki.txt index 7c627eb..b6ec2c6 100644 --- a/doc/taskwiki.txt +++ b/doc/taskwiki.txt @@ -314,6 +314,11 @@ Taskwarrior: ~ * [ ] This has project home #431f42 +Typing additional metadata can be simplified by using omni completion (see +|compl-omni|), like so: + +~ * [ ] This has project home -- project: + ---------------------------------------------------------------------------- 5.2. Viewports *taskwiki-features-viewport* diff --git a/taskwiki/completion.py b/taskwiki/completion.py index a2df7eb..b7bc373 100644 --- a/taskwiki/completion.py +++ b/taskwiki/completion.py @@ -4,6 +4,7 @@ import re from tasklib import TaskWarrior from taskwiki import constants +from taskwiki import regexp def complete_last_word(f): @@ -121,3 +122,20 @@ class Completion(): self._complete_dates(w) or \ self._complete_recur(w) or \ [] + + def omni_modstring_findstart(self, line): + m = re.search(regexp.GENERIC_TASK, line) + if m and not m.group('uuid') and ' -- ' in line: + return line.rfind(' ') + 1 + else: + return -1 + + def omni_modstring(self, w): + return \ + self._complete_any(w) or \ + self._complete_attributes(w) or \ + self._complete_projects(w) or \ + self._complete_tags(w) or \ + self._complete_dates(w) or \ + self._complete_recur(w) or \ + [] diff --git a/tests/base.py b/tests/base.py index 8861e44..3eccdf3 100644 --- a/tests/base.py +++ b/tests/base.py @@ -85,6 +85,7 @@ class IntegrationTest(object): self.configure_global_variables() self.add_plugin('taskwiki') self.add_plugin('vimwiki', 'plugin/vimwiki.vim') + self.add_plugin('taskwiki/after') self.filepath = os.path.join(self.dir, 'testwiki.txt') self.client.edit(self.filepath) diff --git a/tests/test_completion.py b/tests/test_completion.py index 5ffe3ff..45054a7 100644 --- a/tests/test_completion.py +++ b/tests/test_completion.py @@ -53,8 +53,19 @@ class TestCompletionUnit(): assert c.modify("re:da") == ["re:daily", "re:day"] assert c.modify("recur:q") == ["recur:quarterly"] + def test_omni(self): + c = Completion(FakeTW()) + assert c.omni_modstring_findstart("* [ ] x") == -1 + assert c.omni_modstring_findstart("* [ ] x --") == -1 + assert c.omni_modstring_findstart("* [ ] x #12345678 --") == -1 + assert c.omni_modstring_findstart("* [ ] x -- #12345678") == -1 + assert c.omni_modstring_findstart("* [ ] x -- ") == 11 + assert c.omni_modstring_findstart("* [ ] x -- x") == 11 + assert c.omni_modstring_findstart("* [ ] x -- xy") == 11 + assert c.omni_modstring_findstart("* [ ] x -- x y") == 13 -class TestCompletionIntegration(IntegrationTest): + +class TestCompletionIntegMod(IntegrationTest): viminput = """ * [ ] test task 1 #{uuid} * [ ] test task 2 #{uuid} @@ -74,3 +85,23 @@ class TestCompletionIntegration(IntegrationTest): task.refresh() assert self.tasks[0]['project'] == "DEF" + + +class TestCompletionIntegOmni(IntegrationTest): + viminput = """ + * [ ] test task 1 #{uuid} + """ + + tasks = [ + dict(description="test task 1", project="ABC"), + ] + + def execute(self): + self.client.feedkeys('1gg') + self.client.feedkeys('otest task 2 -- pro\\\\A\\\\\\') + self.client.eval('0') # wait for command completion + self.command("w", regex="written$", lines=1) + + task = self.tw.tasks.pending()[1] + assert task['description'] == 'test task 2' + assert task['project'] == 'ABC'