diff --git a/taskwiki/viewport.py b/taskwiki/viewport.py index e9a12c8bb..33d588e64 100644 --- a/taskwiki/viewport.py +++ b/taskwiki/viewport.py @@ -325,6 +325,9 @@ def load_tasks(self): # Load all tasks below the viewport for i in range(self.line_number + 1, len(self.cache.buffer)): line = self.cache.buffer[i] + if not line: + continue + match = re.search(regexp.GENERIC_TASK, line) if match: @@ -367,15 +370,28 @@ def sync_with_taskwarrior(self): self.cache.remove_line(vimwikitask['line_number']) # Add the tasks that match the filter and are not listed - added_tasks = 0 existing_tasks = len(self.tasks) sorted_to_add = list(to_add) sorted_to_add.sort(key=lambda x: x['entry']) - for task in sorted_to_add: - added_tasks += 1 - added_at = self.line_number + existing_tasks + added_tasks + # Insert below headers (with separating lines), or below existing tasks + if existing_tasks == 0: + if to_add and self.cache.markup_syntax == 'markdown': + md_h_style = util.get_var('vimwiki_markdown_header_style', 1) + newlines = int(md_h_style) + else: + newlines = 0 + + for _ in range(newlines): + self.cache.insert_line('', self.line_number + 1) + + insert_start_line = self.line_number + newlines + 1 + else: + insert_start_line = max(t['line_number'] for t in self.tasks) + 1 + + for i, task in enumerate(sorted_to_add): + added_at = insert_start_line + i # Add the task object to cache self.cache.task[short.ShortUUID(task['uuid'], self.tw)] = task @@ -393,9 +409,8 @@ def sync_with_taskwarrior(self): sort.TaskSorter(self.cache, self.tasks, self.sort).execute() + # Remove excess task lines beyond limit count if self.count is not None: - for i in range( - self.line_number + self.count, - self.line_number + existing_tasks + added_tasks, - ): - self.cache.remove_line(self.line_number + self.count + 1) + task_lines = sorted(t['line_number'] for t in self.tasks) + for excess_line in reversed(task_lines[self.count:]): + self.cache.remove_line(excess_line) diff --git a/tests/conftest.py b/tests/conftest.py index 41a7b1a03..1d3383e9b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,9 +14,9 @@ 'HEADER3': "=== %s ===", }, 'markdown': { - 'HEADER1': "# %s", - 'HEADER2': "## %s", - 'HEADER3': "### %s", + 'HEADER1': "# %s\n", + 'HEADER2': "## %s\n", + 'HEADER3': "### %s\n", } } diff --git a/tests/test_viewport.py b/tests/test_viewport.py index 2830a9b67..fee911d2f 100644 --- a/tests/test_viewport.py +++ b/tests/test_viewport.py @@ -667,3 +667,28 @@ def execute(self): # testfile3 only has header, so refresh on open makes changes self.client.edit(testfile3) assert self.client.eval('&modified') == '1' + + +class TestViewportsNoChangePreserving(MultiSyntaxIntegrationTest): + + viminput = """ + HEADER2(Work tasks | +work) + + * [ ] tag work task #{uuid} + + + HEADER2(Home tasks | +home) + + + * [ ] tag home task #{uuid} + """ + + vimoutput = viminput + + tasks = [ + dict(description="tag work task", tags=['work']), + dict(description="tag home task", tags=['home']), + ] + + def execute(self): + self.command("w", regex="written$", lines=1)