obsidian-tasks icon indicating copy to clipboard operation
obsidian-tasks copied to clipboard

refactor: Replace the duplication of '\s\t>' regular expressions with single source of truth

Open claremacrae opened this issue 2 years ago • 4 comments

Reviewing #953, I see 4 regular expressions needed to be changed in order to add support for callouts and block quotes:

image

This is an unnecessary duplication of core logic, and a pit-fall for maintainers, as it is easy to not change all locations.

I would like there to be a single source of truth for the identification of the start of a task line.

claremacrae avatar Aug 05 '22 12:08 claremacrae

Yes! This is what I was complaining about with ToggleDone. Only the one in Task.ts is covered by automated tests.

AnnaKornfeldSimpson avatar Aug 05 '22 17:08 AnnaKornfeldSimpson

Possible strategy for this:

  • In Task.ts define constant strings for INDENTATION = "^([\\s\\t>]*)", BULLET = "[-*]", CHECKBOX = "\\[(.)\\]", AFTER_CHECKBOX = " *(.*)"
  • In Task.ts change taskRegex to new RegExp(INDENTATION + BULLET + " +" + CHECKBOX + AFTER_CHECKBOX, 'u');
  • In CreateOrEdit.ts change nonTaskRegex to new RegExp(INDENTATION + BULLET + "? *" + CHECKBOX + "?" + AFTER_CHECKBOX, 'u');
  • In ToggleDone.ts change listItemRegex to new RegExp(INDENTATION + "(" + BULLET + ")"); and the un-named one to line.replace(new RegExp(INDENTATION), '$1- ');

We could even move all the regex definitions into Task.ts to make them easier to cover with automated tests.

Question about this strategy: Is there any performance cost to doing new RegExp instead of using literals? I do not know how this works in JS.

AnnaKornfeldSimpson avatar Aug 06 '22 21:08 AnnaKornfeldSimpson

Possible strategy for this:

  • In Task.ts define constant strings for INDENTATION = "^([\\s\\t>]*)", BULLET = "[-*]", CHECKBOX = "\\[(.)\\]", AFTER_CHECKBOX = " *(.*)"
  • In Task.ts change taskRegex to new RegExp(INDENTATION + BULLET + " +" + CHECKBOX + AFTER_CHECKBOX, 'u');
  • In CreateOrEdit.ts change nonTaskRegex to new RegExp(INDENTATION + BULLET + "? *" + CHECKBOX + "?" + AFTER_CHECKBOX, 'u');
  • In ToggleDone.ts change listItemRegex to new RegExp(INDENTATION + "(" + BULLET + ")"); and the un-named one to line.replace(new RegExp(INDENTATION), '$1- ');

That looks excellent.

We could even move all the regex definitions into Task.ts to make them easier to cover with automated tests.

I like that idea. Having them all together does seem sensible.

Question about this strategy: Is there any performance cost to doing new RegExp instead of using literals? I do not know how this works in JS.

I don't know. Once sytone's logging code is hooked up, we can see how the measurement code works.

But I strongly favour readable, safely maintainable code - and we are making so many other speed improvements to the code, plus the vast bulk of the time is in rendering, not text manipulation, that my assumption is that this will be fine.

claremacrae avatar Aug 07 '22 07:08 claremacrae

There is this method for combining regexes, but I'm unsure it's useful in this case:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source

claremacrae avatar Aug 07 '22 07:08 claremacrae