Skip to content

Commit

Permalink
clear empty list item on return
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamin-kirkbride committed Jul 4, 2023
1 parent 7809f5b commit 8065b37
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 7 deletions.
28 changes: 23 additions & 5 deletions porcupine/plugins/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
log = logging.getLogger(__name__)


setup_before = ["tabs2spaces"]
setup_before = ["tabs2spaces", "autoindent"]


def _list_item(line: str) -> re.Match[str] | None:
"""Regex for markdown list item
First group is the whitespace (if any) preceding the item
Second group is the list item prefix (ex `-`, `+`, `6.`, `#.`)
1st group is the whitespace (if any) preceding the item
2nd group is the list item prefix (ex `-`, `+`, `6.`, `#.`)
3rd group is the item text
According to:
- https://spec.commonmark.org/0.30/#lists
Expand All @@ -36,7 +37,7 @@ def _list_item(line: str) -> re.Match[str] | None:

assert len(line.splitlines()) == 1

list_item_regex = re.compile(r"(^[\t ]*)(\d{1,9}[.)]|[-+*]|#\)|#\.) .*")
list_item_regex = re.compile(r"(^[\t ]*)(\d{1,9}[.)]|[-+*]|#\)|#\.) (.*)")
match = list_item_regex.search(line)
return match if match else None

Expand Down Expand Up @@ -74,17 +75,34 @@ def continue_list(tab: tabs.FileTab, event: tkinter.Event[tkinter.Text]) -> str
current_line = event.widget.get("insert - 1l linestart", "insert -1l lineend")
list_item_match = _list_item(current_line)
if list_item_match:
indentation, prefix = list_item_match.groups()
indentation, prefix, item_text = list_item_match.groups()

tab.textwidget.insert("insert", prefix + " ")
tab.update()

return None


def on_enter_press(tab: tabs.FileTab, event: tkinter.Event[tkinter.Text]) -> str | None:
if tab.settings.get("filetype_name", object) == "Markdown":
current_line = event.widget.get("insert linestart", "insert lineend")
list_item_match = _list_item(current_line)
if list_item_match:
indentation, prefix, item_text = list_item_match.groups()
if item_text:
# there is item text, so we are done here
return None

event.widget.delete("insert linestart", "insert lineend")
return "break"

return None


def on_new_filetab(tab: tabs.FileTab) -> None:
utils.bind_tab_key(tab.textwidget, partial(on_tab_key, tab), add=True)
tab.textwidget.bind("<<post-autoindent>>", partial(continue_list, tab), add=True)
tab.textwidget.bind("<Return>", partial(on_enter_press, tab), add=True)


def setup() -> None:
Expand Down
34 changes: 32 additions & 2 deletions tests/test_markdown_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,6 @@ def test_non_list(line: str, filetab, tmp_path):
@pytest.mark.parametrize(
"li",
[
"- ", # note the space
"1. ", # note the space
"1. item 1",
"1) item 1",
"#) item 1",
Expand All @@ -225,3 +223,35 @@ def test_list_continuation(li: str, filetab, tmp_path):
filetab.update()
current_line = filetab.textwidget.get("insert linestart", "insert lineend")
assert markdown._list_item(current_line)


@pytest.mark.parametrize("prefix", ["-", "+", "*", "#.", "#)", "1.", "1)", "88)", "88."])
def test_return_remove_empty_item(prefix: str, filetab, tmp_path):
"""Pressing 'return' on an empty item should remove it"""
filetab.textwidget.insert("1.0", prefix + " item 1")
filetab.update()

# switch to Markdown filetype format
filetab.save_as(tmp_path / "asdf.md")
assert filetab.settings.get("filetype_name", object) == "Markdown"

# new line
filetab.textwidget.event_generate("<Return>")
filetab.update()
previous_line = filetab.textwidget.get("insert - 1l linestart", "insert - 1l lineend")
current_line = filetab.textwidget.get("insert linestart", "insert lineend")
assert previous_line == f"{prefix} item 1"
assert markdown._list_item(previous_line)
assert current_line == f"{prefix} "
assert markdown._list_item(current_line)

# new line
filetab.textwidget.event_generate("<Return>")
filetab.update()
previous_line = filetab.textwidget.get("insert - 1l linestart", "insert - 1l lineend")
current_line = filetab.textwidget.get("insert linestart", "insert lineend")
assert previous_line == f"{prefix} item 1"
assert markdown._list_item(previous_line)
# current line should now be empty
assert current_line == ""
assert not markdown._list_item(current_line)

0 comments on commit 8065b37

Please sign in to comment.