text: import inspect
  import json
  import shlex
  from typing import Callable, Dict, Iterable, Iterator, List, Optional
  
  import click
  
  
  def get_current_option_help(
      *, filter_names: Optional[Iterable[str]] = None
  ) -> List[str]:
      ctx = click.get_current_context()
      cmd = ctx.command
      opts = [x for x in cmd.params if isinstance(x, click.Option)]
      if filter_names is not None:
          opts = [o for o in opts if o.name is not None and o.name in filter_names]
      return [o.get_error_hint(ctx) for o in opts]
  
  
  def supported_parameters(c: Callable) -> List[str]:
      sig = inspect.signature(c)
      return list(sig.parameters.keys())
  
  
  def format_list_of_words(first: str, *rest: str):
      if not rest:
          return first
      if len(rest) == 1:
          return f"{first} and {rest[0]}"
      return ", ".join([first] + list(rest[:-1])) + f", and {rest[-1]}"
  
  
  def format_plural_str(formatstr: str, pluralizable: Dict[str, str], use_plural: bool):
      """
      Format text with singular or plural forms of words. Use the singular forms as
      keys in the format string.
  
      Usage:
  
      >>> command_list = [...]
      >>> fmtstr = "you need to run {this} {command}:"
      >>> print(
      ...     format_plural_str(
      ...         fmtstr,
      ...         {"this": "these", "command": "commands"},
      ...         len(command_list) == 1
      ...     )
      ... )
      >>> print("  " + "\n  ".join(command_list))
      """
      argdict = {
          singular: plural if use_plural else singular
          for singular, plural in pluralizable.items()
      }
      return formatstr.format(**argdict)
  
  
  def sorted_json_field(key):
      """Define sorted JSON output for text output containing complex types."""
  
      def field_func(data):
          return json.dumps(data[key], sort_keys=True)
  
      field_func._filter_key = key
      return field_func
  
  
  def filter_fields(check_fields, container):
      """
      Given a set of fields, this is a list of fields actually found in some containing
      object.
  
      Always includes keyfunc fields unless they set the magic _filter_key attribute
      sorted_json_field above is a good example of doing this
      """
      fields = []
      for name, key in check_fields:
          check_key = key
          if callable(key) and hasattr(key, "_filter_key"):
              check_key = key._filter_key
  
          # if it's a string lookup, check if it's contained (and skip if not)
          if isinstance(check_key, str):
              subkeys = check_key.split(".")
              skip_subkey = False
  
              check_container = container
              for check_subkey in subkeys[:-1]:
                  if check_subkey not in check_container:
                      skip_subkey = True
                      break
                  check_container = check_container[check_subkey]
              if skip_subkey or subkeys[-1] not in check_container:
                  continue
  
          # anything else falls through to success
          # includes keyfuncs which don't set _filter_key
          fields.append((name, key))
      return fields
  
  
  class CLIStubResponse:
      """
      A stub response class to make arbitrary data accessible in a way similar to a
      GlobusHTTPResponse object.
      """
  
      def __init__(self, data):
          self.data = data
  
      def __getitem__(self, key):
          return self.data[key]
  
  
  # wrap to add a `has_next()` method and `limit` param to a naive iterator
  class PagingWrapper:
      def __init__(self, iterator: Iterator, limit: Optional[int] = None):
          self.iterator = iterator
          self.next = None
          self.limit = limit
          self._step()
  
      def _step(self):
          try:
              self.next = next(self.iterator)
          except StopIteration:
              self.next = None
  
      def has_next(self):
          return self.next is not None
  
      def __iter__(self):
          yielded = 0
          while self.has_next() and (self.limit is None or yielded < self.limit):
              cur = self.next
              self._step()
              yield cur
              yielded += 1
  
  
  def shlex_process_stream(process_command, stream):
      """
      Use shlex to process stdin line-by-line.
      Also prints help text.
  
      Requires that @process_command be a Click command object, used for
      processing single lines of input. helptext is prepended to the standard
      message printed to interactive sessions.
      """
      # use readlines() rather than implicit file read line looping to force
      # python to properly capture EOF (otherwise, EOF acts as a flush and
      # things get weird)
      for line in stream.readlines():
          # get the argument vector:
          # do a shlex split to handle quoted paths with spaces in them
          # also lets us have comments with #
          argv = shlex.split(line, comments=True)
          if argv:
              try:
                  process_command.main(args=argv)
              except SystemExit as e:
                  if e.code != 0:
                      raise
  