docs: def jupytext(args=None):
      """Internal implementation of Jupytext command line"""
      args = parse_jupytext_args(args)
  
      def log(text):
          if not args.quiet:
              sys.stdout.write(text + '\n')
  
      if args.version:
          log(__version__)
          return 0
  
      if args.pre_commit:
          if args.notebooks:
              raise ValueError('--pre-commit takes notebooks from the git index. Do not pass any notebook here.')
          args.notebooks = notebooks_in_git_index(args.input_format)
          log('[jupytext] Notebooks in git index are:')
          for nb_file in args.notebooks:
              log(nb_file)
  
      def writef_git_add(notebook_, nb_file_, fmt_):
          writef(notebook_, nb_file_, fmt_)
          if args.pre_commit:
              system('git', 'add', nb_file_)
  
      # Read notebook from stdin
      if not args.notebooks:
          if not args.pre_commit:
              args.notebooks = ['-']
  
      if args.set_formats is not None:
          # Replace empty string with None
          args.update_metadata = recursive_update(args.update_metadata,
                                                  {'jupytext': {'formats': args.set_formats or None}})
  
      if args.paired_paths:
          if len(args.notebooks) != 1:
              raise ValueError('--paired-paths applies to a single notebook')
          print_paired_paths(args.notebooks[0], args.input_format)
          return 1
  
      if not args.to and not args.output and not args.sync \
              and not args.pipe and not args.check \
              and not args.test and not args.test_strict \
              and not args.update_metadata:
          raise ValueError('Please select an action')
  
      if args.output and len(args.notebooks) != 1:
          raise ValueError('Please input a single notebook when using --output')
  
      if args.input_format:
          args.input_format = long_form_one_format(args.input_format)
  
      if args.to:
          args.to = long_form_one_format(args.to)
          set_format_options(args.to, args.format_options)
  
      # Main loop
      round_trip_conversion_errors = 0
  
      # Wildcard extension on Windows #202
      notebooks = []
      for pattern in args.notebooks:
          if '*' in pattern or '?' in pattern:
              notebooks.extend(glob.glob(pattern))
          else:
              notebooks.append(pattern)
  
      for nb_file in notebooks:
          if nb_file == '-' and args.sync:
              raise ValueError('Cannot sync a notebook on stdin')
  
          nb_dest = args.output or (None if not args.to
                                    else ('-' if nb_file == '-' else
                                          full_path(base_path(nb_file, args.input_format), args.to)))
  
          # Just acting on metadata / pipe => save in place
          if not nb_dest and not args.sync:
              nb_dest = nb_file
  
          if nb_dest == '-':
              args.quiet = True
  
          # I. ### Read the notebook ###
          fmt = copy(args.input_format) or {}
          set_format_options(fmt, args.format_options)
          log('[jupytext] Reading {}{}'.format(
              nb_file if nb_file != '-' else 'stdin',
              ' in format {}'.format(short_form_one_format(fmt)) if 'extension' in fmt else ''))
  
          notebook = readf(nb_file, fmt)
          if not fmt:
              text_representation = notebook.metadata.get('jupytext', {}).get('text_representation', {})
              ext = os.path.splitext(nb_file)[1]
              if text_representation.get('extension') == ext:
                  fmt = {key: text_representation[key] for key in text_representation if
                         key in ['extension', 'format_name']}
              elif ext:
                  fmt = {'extension': ext}
  
          # Update the metadata
          if args.update_metadata:
              log('[jupytext] Updating notebook metadata with {}'.format(args.update_metadata))
              # Are we updating a text file that has a metadata filter? #212
              if fmt['extension'] != '.ipynb' and \
                      notebook.metadata.get('jupytext', {}).get('notebook_metadata_filter') == '-all':
                  notebook.metadata.get('jupytext', {}).pop('notebook_metadata_filter')
              recursive_update(notebook.metadata, args.update_metadata)
  
          # Read paired notebooks
          if args.sync:
              set_prefix_and_suffix(fmt, notebook, nb_file)
              notebook, inputs_nb_file, outputs_nb_file = load_paired_notebook(notebook, fmt, nb_file, log)
  
          # II. ### Apply commands onto the notebook ###
          # Pipe the notebook into the desired commands
          for cmd in args.pipe or []:
              notebook = pipe_notebook(notebook, cmd, args.pipe_fmt)
  
          # and/or test the desired commands onto the notebook
          for cmd in args.check or []:
              pipe_notebook(notebook, cmd, args.pipe_fmt, update=False)
  
          # III. ### Possible actions ###
          modified = args.update_metadata or args.pipe
          # a. Test round trip conversion
          if args.test or args.test_strict:
              try:
                  test_round_trip_conversion(notebook, args.to,
                                             update=args.update,
                                             allow_expected_differences=not args.test_strict,
                                             stop_on_first_error=args.stop_on_first_error)
              except NotebookDifference as err:
                  round_trip_conversion_errors += 1
                  sys.stdout.write('{}: {}'.format(nb_file, str(err)))
              continue
  
          # b. Output to the desired file or format
          if nb_dest:
              if nb_dest == nb_file and not args.to:
                  args.to = fmt
  
              # Test consistency between dest name and output format
              if args.to and nb_dest != '-':
                  base_path(nb_dest, args.to)
  
              # Describe what jupytext is doing
              if os.path.isfile(nb_dest) and args.update:
                  if not nb_dest.endswith('.ipynb'):
                      raise ValueError('--update is only for ipynb files')
                  action = ' (destination file updated)'
                  check_file_version(notebook, nb_file, nb_dest)
                  combine_inputs_with_outputs(notebook, readf(nb_dest), fmt)
              elif os.path.isfile(nb_dest):
                  action = ' (destination file replaced)'
              else:
                  action = ''
  
              log('[jupytext] Writing {nb_dest}{format}{action}'
                  .format(nb_dest=nb_dest,
                          format=' in format ' + short_form_one_format(
                              args.to) if args.to and 'format_name' in args.to else '',
                          action=action))
              writef_git_add(notebook, nb_dest, args.to)
  
          # c. Synchronize paired notebooks
          if args.sync:
              # Also update the original notebook if the notebook was modified
              if modified:
                  inputs_nb_file = outputs_nb_file = None
              formats = notebook.metadata['jupytext']['formats']
  
              for ipynb in [True, False]:
                  # Write first format last so that it is the most recent file
                  for alt_path, alt_fmt in paired_paths(nb_file, fmt, formats)[::-1]:
                      # Write ipynb first for compatibility with our contents manager
                      if alt_path.endswith('.ipynb') != ipynb:
                          continue
                      # Do not write the ipynb file if it was not modified
                      # But, always write text representations to make sure they are the most recent
                      if alt_path == inputs_nb_file and alt_path == outputs_nb_file:
                          continue
                      log("[jupytext] Updating '{}'".format(alt_path))
                      writef_git_add(notebook, alt_path, alt_fmt)
  
      return round_trip_conversion_errors