text: """Copy records from the first KGTK file to the output file,
  adding ID values.
  
  TODO: Need KgtkWriterOptions
  """
  
  from argparse import Namespace, SUPPRESS
  
  from kgtk.cli_argparse import KGTKArgumentParser, KGTKFiles
  
  def parser():
      return {
          'help': 'Copy a KGTK file, adding ID values.',
          'description': 'Copy a KGTK file, adding ID values.\n\n' +
          'The `--overwrite-id` option can be used to replace existing ID values in the ID column.\n' +
          'It does not update instances of the same ID in other columns, such as node1, elsewhere in the file.\n\n' +
          'Several ID styles are supported.\n\n' +
          'Additional options are shown in expert help.\nkgtk --expert add-id --help'
      }
  
  
  def add_arguments_extended(parser: KGTKArgumentParser, parsed_shared_args: Namespace):
      """
      Parse arguments
      Args:
          parser (argparse.ArgumentParser)
      """
      # import modules locally
      from kgtk.io.kgtkreader import KgtkReader, KgtkReaderOptions
      from kgtk.reshape.kgtkidbuilder import KgtkIdBuilder, KgtkIdBuilderOptions
      from kgtk.value.kgtkvalueoptions import KgtkValueOptions
  
      _expert: bool = parsed_shared_args._expert
  
      # This helper function makes it easy to suppress options from
      # The help message.  The options are still there, and initialize
      # what they need to initialize.
      def h(msg: str)->str:
          if _expert:
              return msg
          else:
              return SUPPRESS
  
      parser.add_input_file(positional=True)
      parser.add_output_file()
  
      KgtkIdBuilderOptions.add_arguments(parser, expert=True) # Show all the options.
      KgtkReader.add_debug_arguments(parser, expert=_expert)
      KgtkReaderOptions.add_arguments(parser, mode_options=True, expert=_expert)
      KgtkValueOptions.add_arguments(parser, expert=_expert)
  
  def run(input_file: KGTKFiles,
          output_file: KGTKFiles,
  
          errors_to_stdout: bool = False,
          errors_to_stderr: bool = True,
          show_options: bool = False,
          verbose: bool = False,
          very_verbose: bool = False,
  
          **kwargs # Whatever KgtkFileOptions and KgtkValueOptions want.
  )->int:
      # import modules locally
      from pathlib import Path
      import sys
      import typing
      
      from kgtk.exceptions import KGTKException
      from kgtk.io.kgtkreader import KgtkReader, KgtkReaderOptions
      from kgtk.io.kgtkwriter import KgtkWriter
      from kgtk.reshape.kgtkidbuilder import KgtkIdBuilder, KgtkIdBuilderOptions
      from kgtk.value.kgtkvalueoptions import KgtkValueOptions
  
      input_kgtk_file: Path = KGTKArgumentParser.get_input_file(input_file)
      output_kgtk_file: Path = KGTKArgumentParser.get_output_file(output_file)
  
      # Select where to send error messages, defaulting to stderr.
      error_file: typing.TextIO = sys.stdout if errors_to_stdout else sys.stderr
  
      # Build the option structures.
      idbuilder_options: KgtkIdBuilderOptions = KgtkIdBuilderOptions.from_dict(kwargs)
      reader_options: KgtkReaderOptions = KgtkReaderOptions.from_dict(kwargs)
      value_options: KgtkValueOptions = KgtkValueOptions.from_dict(kwargs)
  
      # Show the final option structures for debugging and documentation.
      if show_options:
          print("--input-file=%s" % str(input_kgtk_file), file=error_file)
          print("--output-file=%s" % str(output_kgtk_file), file=error_file)
          idbuilder_options.show(out=error_file)
          reader_options.show(out=error_file)
          value_options.show(out=error_file)
          print("=======", file=error_file, flush=True)
  
      try:
  
          # First create the KgtkReader.  It provides parameters used by the ID
          # column builder. Next, create the ID column builder, which provides a
          # possibly revised list of column names for the KgtkWriter.  Create
          # the KgtkWriter.  Last, process the data stream.
  
          # Open the input file.
          kr: KgtkReader =  KgtkReader.open(input_kgtk_file,
                                            error_file=error_file,
                                            options=reader_options,
                                            value_options=value_options,
                                            verbose=verbose,
                                            very_verbose=very_verbose,
          )
          
          # Create the ID builder.
          idb: KgtkIdBuilder = KgtkIdBuilder.new(kr, idbuilder_options)
  
          # Open the output file.
          ew: KgtkWriter = KgtkWriter.open(idb.column_names,
                                           output_kgtk_file,
                                           mode=KgtkWriter.Mode[kr.mode.name],
                                           require_all_columns=True,
                                           prohibit_extra_columns=True,
                                           fill_missing_columns=False,
                                           gzip_in_parallel=False,
                                           verbose=verbose,
                                           very_verbose=very_verbose)
  
          # Process the input file, building IDs.
          idb.process(kr, ew)
  
          # Clean up.
          ew.close()
          kr.close()
  
          return 0
  
      except SystemExit as e:
          raise KGTKException("Exit requested")
      except Exception as e:
          raise KGTKException(str(e))
  
  