Skip to content

Commit

Permalink
Add \providecommand
Browse files Browse the repository at this point in the history
fixes #247
  • Loading branch information
torik42 committed Mar 28, 2023
1 parent 3c8630d commit 1f7ee6c
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 26 deletions.
1 change: 1 addition & 0 deletions list-of-macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ tests: [tests/test\_packages/test\_latex\_builtins.py](tests/test_packages/test_
\\paragraph,
\\part,
\\phantom,
\\providecommand (defines macro, but does not overwrite existing ones),
\\qquad,
\\quad,
\\ref,
Expand Down
54 changes: 51 additions & 3 deletions tests/test_newcommand.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@

#
# - test of \newcommand with default value for optional argument
# - test of \def
# Special tests for \newcommand, \renewcommand, \providecommand and \def
#


Expand Down Expand Up @@ -90,6 +88,56 @@ def get_plain(latex):
Xa:aY
"""
),
(
# \newcommand currenly overwrites existing commands
# LaTeX:
r"""
\newcommand{\test}[1]{A #1}
\newcommand{\test}[1]{B #1}
\test{C}
""",
# Plain:
r"""
B C
"""
),
(
# \renewcommand should overwrite existing commands
# LaTeX:
r"""
\newcommand{\test}[1]{A #1}
\renewcommand{\test}[1]{B #1}
\test{C}
""",
# Plain:
r"""
B C
"""
),
(
# \providecommand should NOT overwrite existing commands
# LaTeX:
r"""
\newcommand{\test}[1]{A #1}
\providecommand{\test}[1]{B #1}
\test{C}
""",
# Plain:
r"""
A C
"""
),
(
# LaTeX:
r"""
\providecommand{\test}[1]{B #1}
\test{C}
""",
# Plain:
r"""
B C
"""
),

]

Expand Down
2 changes: 2 additions & 0 deletions tests/test_packages/test_latex_builtins.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ def test_macros_latex(latex, plain_expected):
(r'\part{ho?}', 'ho?'),
(r'A\phantom{X}B', 'A B'),
(r'A\phantom{\label{l}}B', 'AB'),
(r'A\providecommand{\xxx}{X}B', 'AB'),
(r'A\providecommand*{\xxx}[1][x]{X}B', 'AB'),
(r'A\renewcommand{\xxx}{X}B', 'AB'),
(r'A\renewcommand*{\xxx}[1][x]{X}B', 'AB'),
(r'\section[hi]{ho}', 'ho.'),
Expand Down
66 changes: 43 additions & 23 deletions yalafi/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,52 @@
from yalafi import scanner


def h_newcommand(parser, buf, mac, args, delim, pos):
def g_newcommand(overwrite=True):
r"""
Macro handler for `\newcommand` and `\renewcommand`.
Generator for ``\newcommand``, ``\renewcommand`` and ``\providecommand``.
Args:
overwrite: Boolean deciding, whether the returned handler
overwrites existing commands. Defaults to True.
Returns:
Macro Handler for ``\newcommand``, ``\renewcommand`` and
``\providecommand``. Set ``overwrite=False`` for
``\providecommand``.
"""
name = parser.get_text_direct(args[1])
if name in parser.parms.newcommand_ignore:
# pylint: disable-next=redefined-outer-name
def h_newcommand(parser, buf, mac, args, delim, pos):
r"""
Macro handler for `\newcommand` and `\renewcommand`.
"""
name = parser.get_text_direct(args[1])
if name in parser.parms.newcommand_ignore:
return []
if not overwrite and name in parser.the_macros:
return []
nargs = parser.get_text_expanded(args[2])
nargs = int(nargs) if nargs.isdecimal() else 0
for a in [b for b in args[4] if type(b) is defs.ArgumentToken]:
if a.arg < 1 or a.arg > nargs:
return utils.latex_error(parser, 'illegal argument #' + str(a.arg)
+ ' in definition of macro ' + name, a.pos)
if args[3]:
if nargs < 1:
return utils.latex_error(parser,
'illegal default value in definition of macro ' + name,
args[1][0].pos)
parser.the_macros[name] = defs.Macro(parser.parms,
name, args='O' + 'A' * (nargs - 1),
repl=args[4], defaults=[args[3]], scanned=True)
else:
parser.the_macros[name] = defs.Macro(parser.parms,
name, args='A' * nargs,
repl=args[4], scanned=True)
return []
nargs = parser.get_text_expanded(args[2])
nargs = int(nargs) if nargs.isdecimal() else 0
for a in [b for b in args[4] if type(b) is defs.ArgumentToken]:
if a.arg < 1 or a.arg > nargs:
return utils.latex_error(parser, 'illegal argument #' + str(a.arg)
+ ' in definition of macro ' + name, a.pos)
if args[3]:
if nargs < 1:
return utils.latex_error(parser,
'illegal default value in definition of macro ' + name,
args[1][0].pos)
parser.the_macros[name] = defs.Macro(parser.parms,
name, args='O' + 'A' * (nargs - 1),
repl=args[4], defaults=[args[3]], scanned=True)
else:
parser.the_macros[name] = defs.Macro(parser.parms,
name, args='A' * nargs,
repl=args[4], scanned=True)
return []
return h_newcommand


h_newcommand = g_newcommand(overwrite=True)


def h_theorem(name):
Expand Down
1 change: 1 addition & 0 deletions yalafi/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def init_macros(self):
Macro(self, '\\paragraph', args='*OA', repl=hs.h_heading),
Macro(self, '\\part', args='*OA', repl=hs.h_heading),
Macro(self, '\\phantom', args='A', repl=hs.h_phantom),
Macro(self, '\\providecommand', args='*AOOA', repl=hs.g_newcommand(overwrite=False)),
Macro(self, '\\renewcommand', args='*AOOA', repl=hs.h_newcommand),
Macro(self, '\\section', args='*OA', repl=hs.h_heading),
Macro(self, '\\subsection', args='*OA', repl=hs.h_heading),
Expand Down

0 comments on commit 1f7ee6c

Please sign in to comment.