1

Unnecessary Background

Recently, I discovered that I had subtle problems concerning a wrong number of spaces in my document because LaTeX commands in text mode without arguments consume one space (e. g. \textgreater here gives <here and not < here, as one may expect).

Thus, one should always write commands without arguments in text mode with empty braces (spaces in math mode are not displayed). The example would then become to \textgreater{} here, which actually gives < here. (Math mode does not display spaces in the document.)

To search for these commands (LaTeX commands without braces after them, but with a space character, after this a word character, all in text mode), I'm going to use a regular expression. It might not be the easiest task, but my document is big and uses many commands, so I strive for a more elegant way than manually reviewing hundreds to thousands of false positives with simple searches.

Please remain calm: I'm not willing to automate the task of adding additional braces without a backup and before reviewing all entries found by my intelligent regex. :-)

My Problem

I stumbled upon the regular expression search feature in TeXWorks, which uses a subset of QT 4 regexes. I tried to use a lookahead on my document and it did not work extremely fast (as I expected), but froze the program for infinity.

This happens already with a minimal regex, applied on a minimal document. I'm using a fully updated MikTeX.

I remember that I had big problems with advanced regular expressions while using C++ / QT some time ago. But this might have been because being forced to use an outdated Standard.

Steps for reproduction

  1. Open a new document with the content "a b" (without the "").
  2. Search -> Find... -> Type "(?=a)(?=c)" in the entry field (without the ""). While doing this, please note that spaces in the regex are interpreted as spaces in the document and thus are not allowed to structure the regex.
  3. Activate the "Regular Expression" option.
  4. Your computer should be sweating.

Questions

Can you reproduce it? Why does this happen? Is it my fault or have I discovered a bug in the software (TeXWorks / QT)? Have I understood the base spaces-after-commands-without-arguments matter correctly?

Please excuse my bad english, I'm willing to improve.

EDIT 1: Using an anchor subregex did not work either, but at least a result was generated in no time: I used "\w(?=a)" as new regex (to match the first "a"), but no match was found. (Thanks to @David Carlisle for proposing this.)

EDIT 2: experiences concerning the way towards the solution

For those who are interested: The original idea to recognize wether I am in math mode or not (no, I don't use \$) failed due to the impossibility of variable length lookbehinds in the TeXWorks regex engine (QRegularException class). (I was not willing to waste much more time with circling around this limitation.)

But with a regex tester, I was able to reduce the number of interesting matches with the method of elimination: The big regex (\\ (?!item)(?=\w+) ((?!emptyset) (?!dots\s+\\\}) (?!in) (?!notin) (?!label) (?!coloneqq) (?!forall) (?!to) (?!exists) (?!subset) (?!Gamma) (?!Sigma) (?!times) (?!geq) (?!Omega) (?!cup) (?!setminus) (?!eqqcolon)) \w+[^\S\n]) | (\\item\s\s) shrunk the match number to 28.

I had to work with the tester site, because this regex seems to be invalid in TeXWorks / QT. Perhaps, the freezing problem has something to do with this problem. So, using grep should solve the freezing problem.

It was definitely not worth the effort measured in work progress, but I learned a lot about lookahead and -- it was pure joy.

EDIT 3: Final results I added (?!dots\s\\\\) to further reduce the match number down to 16. The manual check of all matches resulted in one \item with two spaces following: a really small yield. Additionally, the urgence to check the command character of & became clear. I think it is a command, thus, no further steps must be taken.

  • I don't have texworks to test but why just two lookaheads in the regex and no "normal" part to anchor the lookahead? Your description of the space issue is more or less accurate although the space is consumed earlier in the tokenisation and is consumed for all commands whether or not they have an argument. For example \mbox {a} is the same as \mbox{a} the space is used to terminate the token \mbox before it is known whether or not that token is bound to a macro with an argument. – David Carlisle Sep 29 '18 at 23:04
  • @David Carlisle: Interesting parsing detail. Thanks! I thought it would work without an anchor and it would not be much faster. To be honest, I simply adapted this answer. – user7427029 Sep 30 '18 at 10:41
  • the original regex can't match anything as it matched the empty string that was immediately followed by a and also immediately followed by c so it shouldn't make the regex engine loop but it is pretty strange input. the new one matches any letter that is immediately followed by an a, why do you want to match that? – David Carlisle Sep 30 '18 at 11:29
2

regex syntax is off topic here but

(?=a)(?=c)

matches an empty string that is immediately followed by a and immediately followed by c so it will not match anything in any input but it is possible that some regex engines may take a while to not find anything.

the edit proposes

\w(?=a)

which matches any letter that is immediately followed by an a, so would not find anything in the proposed input of a b

  • Aaahhh, that's why lookaheads are called so... In which SX Categorie does this specific problem (regexes in a latex editor's search function) better fit? Interestingly, it seems to be rather easy to freeze TeXWorks by using regular expressions even on small inputs. Thank you! – user7427029 Sep 30 '18 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.