Skip to content

Instantly share code, notes, and snippets.

@xoolive
Last active February 23, 2021 05:39
Show Gist options
  • Save xoolive/610901f2054510b42fa97076e76ba268 to your computer and use it in GitHub Desktop.
Save xoolive/610901f2054510b42fa97076e76ba268 to your computer and use it in GitHub Desktop.
Explore \index{} elements in your LaTeX aborescence
import sys
from collections import defaultdict
from itertools import repeat
from pathlib import Path
from typing import DefaultDict, Iterator, List, Optional, Tuple
import click
import regex as re
from rich import print
help_msg = """
This script helps you find all occurrences of \\index{} commands matching one
or several patterns
Example:
$ python parse_index.py foo bar 'regex[-like]?'"
"""
def get_lines() -> Iterator[Tuple[Path, Tuple[int, str]]]:
if False:
yield from sys.stdin.readlines()
else:
for file in Path(".").glob("**/*.tex"):
yield from zip(
repeat(file), enumerate(file.read_text().split("\n"), 1)
)
@click.command(help=help_msg)
@click.argument("pattern", default=None, nargs=-1)
def main(pattern: List[str]):
indexes: DefaultDict[str, List[Tuple[Path, int]]] = defaultdict(list)
for file, (nb, line) in get_lines():
regex = r"\{((?:[^\}\{]+|(?R))*+)\}" # match balanced {}
for m in re.finditer(r"\\index\{", line):
for elt in re.finditer(regex, line[m.span()[1] - 1 :], re.VERSION1):
indexes[elt.group(1)].append((file, nb))
break
for kwd in sorted(indexes):
match = list(next(re.finditer(p, kwd), None) for p in pattern)
if len(match) == 0 or any(match):
first_match = next(m for m in match if m is not None)
start, stop = first_match.span()
for file, nb in indexes[kwd]:
print(
f"{file}:{nb}: {kwd[:start]}"
f"[bold red]{kwd[start:stop]}[/bold red]{kwd[stop:]}"
)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment