text: """
  napari command line viewer.
  """
  import argparse
  import logging
  import runpy
  import sys
  from ast import literal_eval
  from textwrap import wrap
  from typing import Any, Dict, List
  
  from . import __version__, gui_qt, layers, view_path
  from .components.add_layers_mixin import valid_add_kwargs
  from .utils import citation_text, sys_info
  
  
  class InfoAction(argparse.Action):
      def __call__(self, *args, **kwargs):
          # prevent unrelated INFO logs when doing "napari --info"
          logging.basicConfig(level=logging.WARNING)
          print(sys_info())
          sys.exit()
  
  
  class CitationAction(argparse.Action):
      def __call__(self, *args, **kwargs):
          # prevent unrelated INFO logs when doing "napari --citation"
          logging.basicConfig(level=logging.WARNING)
          print(citation_text)
          sys.exit()
  
  
  def validate_unknown_args(unknown: List[str]) -> Dict[str, Any]:
      """Convert a list of strings into a dict of valid kwargs for add_* methods.
  
      Will exit program if any of the arguments are unrecognized, or are
      malformed.  Converts string to python type using literal_eval.
  
      Parameters
      ----------
      unknown : List[str]
          a list of strings gathered as "unknown" arguments in argparse.
  
      Returns
      -------
      kwargs : Dict[str, Any]
          {key: val} dict suitable for the viewer.add_* methods where ``val``
          is a ``literal_eval`` result, or string.
      """
  
      out: Dict[str, Any] = dict()
      valid = set.union(*valid_add_kwargs().values())
      for i, arg in enumerate(unknown):
          if not arg.startswith("--"):
              continue
  
          if "=" in arg:
              key, value = arg.split("=", maxsplit=1)
          else:
              key = arg
          key = key.lstrip('-').replace("-", "_")
  
          if key not in valid:
              sys.exit(f"error: unrecognized arguments: {arg}")
  
          if "=" not in arg:
              try:
                  value = unknown[i + 1]
                  if value.startswith("--"):
                      raise IndexError()
              except IndexError:
                  sys.exit(f"error: argument {arg} expected one argument")
          try:
              value = literal_eval(value)
          except Exception:
              value = value
  
          out[key] = value
      return out
  
  
  def main():
      kwarg_options = []
      for layer_type, keys in valid_add_kwargs().items():
          kwarg_options.append(f"  {layer_type.title()}:")
          keys = {k.replace('_', '-') for k in keys}
          lines = wrap(", ".join(sorted(keys)), break_on_hyphens=False)
          kwarg_options.extend([f"    {line}" for line in lines])
  
      parser = argparse.ArgumentParser(
          usage=__doc__,
          formatter_class=argparse.RawDescriptionHelpFormatter,
          epilog="optional layer-type-specific arguments (precede with '--'):\n"
          + "\n".join(kwarg_options),
      )
      parser.add_argument('paths', nargs='*', help='path(s) to view.')
      parser.add_argument(
          '-v',
          '--verbose',
          action='count',
          default=0,
          help="increase output verbosity",
      )
      parser.add_argument(
          '--version', action='version', version=f'napari version {__version__}',
      )
      parser.add_argument(
          '--info',
          action=InfoAction,
          nargs=0,
          help='show system information and exit',
      )
      parser.add_argument(
          '--citation',
          action=CitationAction,
          nargs=0,
          help='show citation information and exit',
      )
      parser.add_argument(
          '--stack',
          action='store_true',
          help='concatenate multiple input files into a single stack.',
      )
      parser.add_argument(
          '--plugin', help='specify plugin name when opening a file',
      )
      parser.add_argument(
          '--layer-type',
          metavar="TYPE",
          choices=set(layers.NAMES),
          help=(
              'force file to be interpreted as a specific layer type. '
              f'one of {set(layers.NAMES)}'
          ),
      )
  
      args, unknown = parser.parse_known_args()
      # this is a hack to allow using "=" as a key=value separator while also
      # allowing nargs='*' on the "paths" argument...
      for idx, item in enumerate(reversed(args.paths)):
          if item.startswith("--"):
              unknown.append(args.paths.pop(len(args.paths) - idx - 1))
      kwargs = validate_unknown_args(unknown) if unknown else {}
  
      # parse -v flags and set the appropriate logging level
      levels = [logging.WARNING, logging.INFO, logging.DEBUG]
      level = levels[min(2, args.verbose)]  # prevent index error
      logging.basicConfig(
          level=level,
          format="%(asctime)s %(levelname)s %(message)s",
          datefmt='%H:%M:%S',
      )
  
      if args.plugin:
          # make sure plugin is only used when files are specified
          if not args.paths:
              sys.exit(
                  "error: The '--plugin' argument is only valid "
                  "when providing a file name"
              )
          # I *think* that Qt is looking in sys.argv for a flag `--plugins`,
          # which emits "WARNING: No such plugin for spec 'builtins'"
          # so remove --plugin from sys.argv to prevent that warningz
          sys.argv.remove('--plugin')
  
      if any(p.endswith('.py') for p in args.paths):
          if len(args.paths) > 1:
              sys.exit(
                  'When providing a python script, only a '
                  'single positional argument may be provided'
              )
  
          with gui_qt(startup_logo=True) as app:
              if hasattr(app, '_splash_widget'):
                  app._splash_widget.close()
              runpy.run_path(args.paths[0])
              if getattr(app, '_existed', False):
                  sys.exit()
      else:
          with gui_qt(startup_logo=True, gui_exceptions=True):
              view_path(
                  args.paths,
                  stack=args.stack,
                  plugin=args.plugin,
                  layer_type=args.layer_type,
                  **kwargs,
              )
  
  
  if __name__ == '__main__':
      sys.exit(main())
  