docs: def parse_args(args=None):
      """Parse command line arguments and return a dictionary of options
      for ttfautohint.ttfautohint function.
  
      `args` can be either None, a list of strings, or a single string,
      that is split into individual options with `shlex.split`.
  
      When `args` is None, the console's default sys.argv are used, and any
      SystemExit exceptions raised by argparse are propagated.
  
      If args is a string list or a string, it is assumed that the function
      was not called from a console script's `main` entry point, but from
      other client code, and thus the SystemExit exceptions are muted and
      a `None` value is returned.
      """
      import argparse
      from ttfautohint import __version__, libttfautohint
      from ttfautohint.cli import USAGE, DESCRIPTION, EPILOG
  
      version_string = "ttfautohint-py %s (libttfautohint %s)" % (
          __version__, libttfautohint.version_string)
  
      if args is None:
          capture_sys_exit = False
      else:
          capture_sys_exit = True
          if isinstance(args, basestring):
              import shlex
              args = shlex.split(args)
  
      parser = argparse.ArgumentParser(
          prog="ttfautohint",
          usage=USAGE,
          description=DESCRIPTION,
          epilog=EPILOG,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      parser.add_argument(
          "in_file", nargs="?", metavar="IN-FILE", default="-",
          type=stdin_or_input_path_type,
          help="input file (default: standard input)")
      parser.add_argument(
          "out_file", nargs="?", metavar="OUT-FILE", default="-",
          type=stdout_or_output_path_type,
          help="output file (default: standard output)")
      parser.add_argument(
          "--debug", action="store_true", help="print debugging information")
  
      stem_width_group = parser.add_mutually_exclusive_group(required=False)
      stem_width_group.add_argument(
          "-a", "--stem-width-mode", type=stem_width_mode, metavar="S",
          default=STEM_WIDTH_MODE_OPTIONS,
          help=("select stem width mode for grayscale, GDI ClearType, and DW "
                "ClearType, where S is a string of three letters with possible "
                "values 'n' for natural, 'q' for quantized, and 's' for strong "
                "(default: qsq)"))
      stem_width_group.add_argument(  # deprecated
          "-w", "--strong-stem-width", type=strong_stem_width, metavar="S",
          help=argparse.SUPPRESS)
  
      parser.add_argument(
          "-c", "--composites", dest="hint_composites", action="store_true",
          help="hint glyph composites also")
      parser.add_argument(
          "-d", "--dehint", action="store_true", help="remove all hints")
      parser.add_argument(
          "-D", "--default-script", metavar="SCRIPT",
          default=USER_OPTIONS["default_script"],
          help="set default OpenType script (default: %(default)s)")
      parser.add_argument(
          "-f", "--fallback-script", metavar="SCRIPT",
          default=USER_OPTIONS["fallback_script"],
          help="set fallback script (default: %(default)s)")
      parser.add_argument(
          "-F", "--family-suffix", metavar="SUFFIX",
          help="append SUFFIX to the family name string(s) in the `name' table")
      parser.add_argument(
          "-G", "--hinting-limit", type=int, metavar="PPEM",
          default=USER_OPTIONS["hinting_limit"],
          help=("switch off hinting above this PPEM value (default: "
                "%(default)s); value 0 means no limit"))
      parser.add_argument(
          "-H", "--fallback-stem-width", type=int, metavar="UNITS",
          default=USER_OPTIONS["fallback_stem_width"],
          help=("set fallback stem width (default: %(default)s font units at "
                "2048 UPEM)"))
      parser.add_argument(
          "-i", "--ignore-restrictions", action="store_true",
          help="override font license restrictions")
      parser.add_argument(
          "-I", "--detailed-info", action="store_true",
          help=("add detailed ttfautohint info to the version string(s) in "
                "the `name' table"))
      parser.add_argument(
          "-l", "--hinting-range-min", type=int, metavar="PPEM",
          default=USER_OPTIONS["hinting_range_min"],
          help="the minimum PPEM value for hint sets (default: %(default)s)")
      parser.add_argument(
          "-m", "--control-file", metavar="FILE",
          help="get control instructions from FILE")
      parser.add_argument(
          "-n", "--no-info", action="store_true",
          help=("don't add ttfautohint info to the version string(s) in the "
                "`name' table"))
      parser.add_argument(
          "-p", "--adjust-subglyphs", action="store_true",
          help="handle subglyph adjustments in exotic fonts")
      parser.add_argument(
          "-r", "--hinting-range-max", type=int, metavar="PPEM",
          default=USER_OPTIONS["hinting_range_max"],
          help="the maximum PPEM value for hint sets (default: %(default)s)")
      parser.add_argument(
          "-R", "--reference", dest="reference_file", metavar="FILE",
          help="derive blue zones from reference font FILE")
      parser.add_argument(
          "-s", "--symbol", action="store_true",
          help="input is symbol font")
      parser.add_argument(
          "-S", "--fallback-scaling", action="store_true",
          help="use fallback scaling, not hinting")
      parser.add_argument(
          "-t", "--ttfa-table", action="store_true", dest="TTFA_info",
          help="add TTFA information table")
      parser.add_argument(
          "-T", "--ttfa-info", dest="show_TTFA_info", action="store_true",
          help="display TTFA table in IN-FILE and exit")
      parser.add_argument(
          "-v", "--verbose", action="store_true",
          help="show progress information")
      parser.add_argument(
          "-V", "--version", action="version",
          version=version_string,
          help="print version information and exit")
      parser.add_argument(
          "-W", "--windows-compatibility", action="store_true",
          help=("add blue zones for `usWinAscent' and `usWinDescent' to avoid "
                "clipping"))
      parser.add_argument(
          "-x", "--increase-x-height", type=int, metavar="PPEM",
          default=USER_OPTIONS["increase_x_height"],
          help=("increase x height for sizes in the range 6<=PPEM<=N; value "
                "0 switches off this feature (default: %(default)s)"))
      parser.add_argument(
          "-X", "--x-height-snapping-exceptions", metavar="STRING",
          default=USER_OPTIONS["x_height_snapping_exceptions"],
          help=('specify a comma-separated list of x-height snapping exceptions'
                ', for example "-9, 13-17, 19" (default: "%(default)s")'))
      parser.add_argument(
          "-Z", "--reference-index", type=int, metavar="NUMBER",
          default=USER_OPTIONS["reference_index"],
          help="face index of reference font (default: %(default)s)")
  
      try:
          options = vars(parser.parse_args(args))
      except SystemExit:
          if capture_sys_exit:
              return None
          raise
  
      # if either input/output are interactive, print help and exit
      if (not capture_sys_exit and
              (options["in_file"] is None or options["out_file"] is None)):
          parser.print_help()
          parser.exit(1)
  
      # check SOURCE_DATE_EPOCH environment variable
      source_date_epoch = os.environ.get("SOURCE_DATE_EPOCH")
      if source_date_epoch:
          try:
              options["epoch"] = int(source_date_epoch)
          except ValueError:
              import warnings
              warnings.warn(
                  UserWarning("invalid SOURCE_DATE_EPOCH: %r" % source_date_epoch))
  
      if options.pop("show_TTFA_info"):
          # TODO use fonttools to dump TTFA table?
          raise NotImplementedError()
  
      stem_width_options = options.pop("stem_width_mode")
      strong_stem_width_options = options.pop("strong_stem_width")
      if strong_stem_width_options:
          import warnings
          warnings.warn(
              UserWarning("Option '-w' is deprecated! Use option '-a' instead"))
          stem_width_options = strong_stem_width_options
      options.update(stem_width_options)
  
      return options