Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected switch to drawer content #44

Open
kristijanhusak opened this issue Nov 5, 2023 · 0 comments
Open

Unexpected switch to drawer content #44

kristijanhusak opened this issue Nov 5, 2023 · 0 comments

Comments

@kristijanhusak
Copy link
Contributor

Hey,

I've got an issue where user reported freezing. It is caused by my manual markup highlighter, but the problem is also a big file.

I tried to narrow down what's the issue, and I noticed one thing.

Having this file:

* Headline 1
  Text 1
:LOGBOOK:
:LAST_REPEAT: [2023-10-11 Wed 13:46]
:END:
* Headline 2
  Text 2
:LOGBOOK:
:LAST_REPEAT: [2023-10-09 Mon 16:36]
:END:

Parses it correctly:

(document [0, 0] - [10, 0]
  subsection: (section [0, 0] - [5, 0]
    headline: (headline [0, 0] - [1, 0]
      stars: (stars [0, 0] - [0, 1])
      item: (item [0, 2] - [0, 12]
        (expr [0, 2] - [0, 10])
        (expr [0, 11] - [0, 12])))
    body: (body [1, 2] - [5, 0]
      (paragraph [1, 2] - [2, 0]
        (expr [1, 2] - [1, 6])
        (expr [1, 7] - [1, 8]))
      (drawer [2, 0] - [5, 0]
        name: (expr [2, 1] - [2, 8])
        contents: (contents [3, 0] - [4, 0]
          (expr [3, 0] - [3, 13])
          (expr [3, 14] - [3, 25])
          (expr [3, 26] - [3, 29])
          (expr [3, 30] - [3, 36])))))
  subsection: (section [5, 0] - [10, 0]
    headline: (headline [5, 0] - [6, 0]
      stars: (stars [5, 0] - [5, 1])
      item: (item [5, 2] - [5, 12]
        (expr [5, 2] - [5, 10])
        (expr [5, 11] - [5, 12])))
    body: (body [6, 2] - [10, 0]
      (paragraph [6, 2] - [7, 0]
        (expr [6, 2] - [6, 6])
        (expr [6, 7] - [6, 8]))
      (drawer [7, 0] - [10, 0]
        name: (expr [7, 1] - [7, 8])
        contents: (contents [8, 0] - [9, 0]
          (expr [8, 0] - [8, 13])
          (expr [8, 14] - [8, 25])
          (expr [8, 26] - [8, 29])
          (expr [8, 30] - [8, 36]))))))

But when I start adding a headline in between, it converts first :END: and last :END into a drawer, and treats everything in between as a drawer content:

Updated file:

* Headline 1
  Text 1
:LOGBOOK:
:LAST_REPEAT: [2023-10-11 Wed 13:46]
:END:
*
* Headline 2
  Text 2
:LOGBOOK:
:LAST_REPEAT: [2023-10-09 Mon 16:36]
:END:

Parsed as:

(document [0, 0] - [11, 0]
  subsection: (section [0, 0] - [11, 0]
    headline: (headline [0, 0] - [1, 0]
      stars: (stars [0, 0] - [0, 1])
      item: (item [0, 2] - [0, 12]
        (expr [0, 2] - [0, 10])
        (expr [0, 11] - [0, 12])))
    body: (body [1, 2] - [11, 0]
      (paragraph [1, 2] - [4, 0]
        (expr [1, 2] - [1, 6])
        (expr [1, 7] - [1, 8])
        (expr [2, 0] - [2, 9])
        (expr [3, 0] - [3, 13])
        (expr [3, 14] - [3, 25])
        (expr [3, 26] - [3, 29])
        (expr [3, 30] - [3, 36]))
      (drawer [4, 0] - [11, 0]
        name: (expr [4, 1] - [4, 4])
        contents: (contents [5, 0] - [10, 0]
          (expr [5, 0] - [5, 1])
          (expr [6, 0] - [6, 1])
          (expr [6, 2] - [6, 10])
          (expr [6, 11] - [6, 12])
          (expr [7, 2] - [7, 6])
          (expr [7, 7] - [7, 8])
          (expr [8, 0] - [8, 9])
          (expr [9, 0] - [9, 13])
          (expr [9, 14] - [9, 25])
          (expr [9, 26] - [9, 29])
          (expr [9, 30] - [9, 36]))))))

Once I add the space after the * it parses it correctly.
This is more-less expected, but for that 1 change a lot of nodes are updated. In the reported issue this happens between two headlines where it ends up putting ~500 lines into the drawer content for a split second and freezes the editor.

I can think of a few solutions here, but I was able to test only one myself:

  1. Never allow :END: to be a start of a drawer
  2. Consider asterisk(s) at the start of a line a valid node (expr) even if it does not have a space after it

For the 2. point, what I mean is this:

Content:

* TODO Test
  Content
*
* TODO Test
  Content

Parsed:

(document [0, 0] - [5, 0]
  (ERROR [0, 0] - [2, 1]
    subsection: (section [0, 0] - [2, 0]
      headline: (headline [0, 0] - [1, 0]
        stars: (stars [0, 0] - [0, 1])
        item: (item [0, 2] - [0, 11]
          (expr [0, 2] - [0, 6])
          (expr [0, 7] - [0, 11])))
      body: (body [1, 2] - [2, 0]
        (paragraph [1, 2] - [2, 0]
          (expr [1, 2] - [1, 9]))))
    (stars [2, 0] - [2, 1]))
  body: (body [2, 1] - [3, 0])
  subsection: (section [3, 0] - [5, 0]
    headline: (headline [3, 0] - [4, 0]
      stars: (stars [3, 0] - [3, 1])
      item: (item [3, 2] - [3, 11]
        (expr [3, 2] - [3, 6])
        (expr [3, 7] - [3, 11])))
    body: (body [4, 2] - [5, 0]
      (paragraph [4, 2] - [5, 0]
        (expr [4, 2] - [4, 9])))))

When something is added to that line that's not a space:

* TODO Test
  Content
*t
* TODO Test
  Content
(document [0, 0] - [5, 0]
  subsection: (section [0, 0] - [3, 0]
    headline: (headline [0, 0] - [1, 0]
      stars: (stars [0, 0] - [0, 1])
      item: (item [0, 2] - [0, 11]
        (expr [0, 2] - [0, 6])
        (expr [0, 7] - [0, 11])))
    body: (body [1, 2] - [3, 0]
      (paragraph [1, 2] - [3, 0]
        (expr [1, 2] - [1, 9])
        (expr [2, 0] - [2, 2]))))
  subsection: (section [3, 0] - [5, 0]
    headline: (headline [3, 0] - [4, 0]
      stars: (stars [3, 0] - [3, 1])
      item: (item [3, 2] - [3, 11]
        (expr [3, 2] - [3, 6])
        (expr [3, 7] - [3, 11])))
    body: (body [4, 2] - [5, 0]
      (paragraph [4, 2] - [5, 0]
        (expr [4, 2] - [4, 9])))))

This change in the parser does the trick for me:

diff --git a/src/scanner.c b/src/scanner.c
index f305612..37be99e 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -267,6 +267,10 @@ bool scan(Scanner *scanner, TSLexer *lexer, const bool *valid_symbols) {
             skip(lexer);
         }
 
+        if (lexer->lookahead == '\n') {
+          return false;
+        }
+
         if (valid_symbols[SECTIONEND] && iswspace(lexer->lookahead) &&
             stars > 0 && stars <= VEC_BACK(scanner->section_stack)) {
             VEC_POP(scanner->section_stack);

I think the 2nd option is simpler and probably more correct. Unless there is a space after *, there's no need to treat it as headline.

Let me know what you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant