Skip to content

Instantly share code, notes, and snippets.

@jgosmann
Created January 20, 2017 20:54
Show Gist options
  • Save jgosmann/8d07ae5f0a7b94ee4d7219ab778bf563 to your computer and use it in GitHub Desktop.
Save jgosmann/8d07ae5f0a7b94ee4d7219ab778bf563 to your computer and use it in GitHub Desktop.
Format latex with one sentence per line
import re
import sys
import pyparsing as pp
escaped = pp.Combine(
pp.Literal('\\') + pp.CharsNotIn('', exact=1)).setResultsName('percent').leaveWhitespace()
comment = pp.Combine(pp.Literal('%') + pp.restOfLine).setResultsName('comment').leaveWhitespace()
args = pp.Forward()
group = pp.Forward()
cmd = pp.Group(pp.Or([
escaped.setResultsName('cmd_name'),
pp.Combine(pp.Literal('\\') + pp.Word(pp.alphas, pp.alphanums + '_')).setResultsName('cmd_name') +
pp.Group(pp.Or([
pp.OneOrMore(args),
pp.FollowedBy(pp.CharsNotIn(pp.alphanums + '_'))
])).setResultsName('args')
])).setResultsName('cmd')
text = pp.CharsNotIn(r'\%{}').leaveWhitespace()
in_arg_text = pp.CharsNotIn(r'\%{}[]<>').leaveWhitespace()
in_arg = pp.ZeroOrMore(pp.MatchFirst([cmd, comment, args, in_arg_text])).leaveWhitespace()
latex = pp.ZeroOrMore(pp.MatchFirst([cmd, comment, group, text])).leaveWhitespace()
group << (pp.Literal('{') + latex + pp.Literal('}')).leaveWhitespace()
args << pp.Or([
pp.Literal('{') + in_arg + pp.Literal('}'),
pp.Literal('[') + in_arg + pp.Literal(']'),
pp.Literal('<') + in_arg + pp.Literal('>')
]).leaveWhitespace()
context = []
def format(x):
if type(x) is str:
is_para = x[0] not in r'\{}%'
for env in ['figure', 'table', 'equation']:
if env in context or env + '*' in context:
is_para = False
if is_para:
x = re.sub('\\b\\s+[\r\n]+', ' ', x)
x = '\n'.join(re.split(r'(?<=[.?!])\s+\b', x))
# print(re.split(r'(?<=[.?!])\s+', x))
sys.stdout.write(x)
else:
if x.getName() == 'cmd' and x['cmd_name'] == r'\begin':
context.append(x['args'][1])
for y in x:
format(y)
if x.getName() == 'cmd' and x['cmd_name'] == r'\end':
assert context.pop() == x['args'][1]
format(latex.parseFile(sys.argv[1]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment