1212import sys
1313import textwrap
1414from pathlib import Path
15- from typing import Any , Optional , Type , TypeVar , cast
15+ from typing import Any , Optional , Tuple , Type , TypeVar , cast
1616
1717
1818class _LazyVersionAction (argparse ._VersionAction ):
@@ -37,6 +37,26 @@ def __call__(
3737 parser .exit ()
3838
3939
40+ def keyvalue (arg : str ) -> Tuple [str , Any ]:
41+ """
42+ Parse a key=value string into a tuple.
43+
44+ :param arg: String in the format "key=value"
45+ :return: Tuple of (key, value)
46+ :raises ValueError: If the string is not in key=value format
47+ """
48+ try :
49+ key , value = arg .split ("=" , 1 )
50+ value_stripped : Any = value .strip ()
51+ if value_stripped == "false" :
52+ value_stripped = False
53+ elif value_stripped == "true" :
54+ value_stripped = True
55+ return (key .strip (), value_stripped )
56+ except ValueError :
57+ raise ValueError (f'"{ arg } " is not in key=value format' ) from None
58+
59+
4060ParserT = TypeVar ("ParserT" )
4161"""
4262Type variable for the concrete parser to create.
@@ -310,14 +330,14 @@ def _make_parser(parser_type: Type[ParserT]) -> ParserT:
310330
311331 # looks for all_types.j2 in the c_jinja template directory and generates
312332 # generated/include/all_types.h from all types in all DSDL namespaces.
313- nnvg --index-file all_types.h --outdir generated/include --templates c_jinja \
314- path/to/types/animal:cat.1.0.dsdl \
333+ nnvg --index-file all_types.h --outdir generated/include --templates c_jinja \\
334+ path/to/types/animal:cat.1.0.dsdl \\
315335 path/to/types/animal:dog.1.0.dsdl
316336
317337 # looks for manifest.j2 in the json_jinja template directory and generates
318338 # generated/include/manifest.json from all types in all DSDL namespaces.
319- nnvg --index-file include/manifest.json --outdir generated --templates json_jinja \
320- path/to/types/animal:cat.1.0.dsdl \
339+ nnvg --index-file include/manifest.json --outdir generated --templates json_jinja \\
340+ path/to/types/animal:cat.1.0.dsdl \\
321341 path/to/types/animal:dog.1.0.dsdl
322342
323343 """
@@ -344,7 +364,7 @@ def _make_parser(parser_type: Type[ParserT]) -> ParserT:
344364 )
345365
346366 def extension_type (raw_arg : str ) -> str :
347- if len ( raw_arg ) > 0 and not raw_arg .startswith ("." ):
367+ if raw_arg and not raw_arg .startswith ("." ):
348368 return "." + raw_arg
349369 else :
350370 return raw_arg
@@ -823,7 +843,7 @@ def extension_type(raw_arg: str) -> str:
823843 ln_opt_group .add_argument (
824844 "--language-standard" ,
825845 "-std" ,
826- choices = ["c11" , "c++14" , "cetl++14-17" , "c++17" , "c++17-pmr" , "c++20" , "c++20-pmr" ],
846+ choices = ["c11" , "c17" , "c23" , " c++14" , "cetl++14-17" , "c++17" , "c++17-pmr" , "c++20" , "c++20-pmr" ],
827847 help = textwrap .dedent (
828848 """
829849
@@ -870,6 +890,29 @@ def extension_type(raw_arg: str) -> str:
870890 ).lstrip (),
871891 )
872892
893+ ln_opt_group .add_argument (
894+ "--option" ,
895+ "-o" ,
896+ nargs = "*" ,
897+ type = keyvalue ,
898+ help = textwrap .dedent (
899+ """
900+ Passes a key=value pair to the template as a language option overriding default options where they are
901+ specified. This is useful for passing options to the template that are not available as command-line
902+ arguments. For example, if you have a template that uses the
903+ "foo" variable you can pass a value to it using this argument::
904+
905+ nnvg -o foo=value ...
906+
907+ where "foo" is then available in the template as `{{ options.foo }}`.
908+
909+ This option is similar to the `--configuration` option but only applies to the options section of the target
910+ language and doesn't require a file to be created.
911+
912+ """
913+ ).lstrip (),
914+ )
915+
873916 return cast (ParserT , parser )
874917
875918
0 commit comments