docs: def natsort_keygen(key=None, alg=ns.DEFAULT):
      """
      Generate a key to sort strings and numbers naturally.
  
      This key is designed for use as the `key` argument to
      functions such as the `sorted` builtin.
  
      The user may customize the generated function with the
      arguments to `natsort_keygen`, including an optional
      `key` function.
  
      Parameters
      ----------
      key : callable, optional
          A key used to manipulate the input value before parsing for
          numbers. It is **not** applied recursively.
          It should accept a single argument and return a single value.
  
      alg : ns enum, optional
          This option is used to control which algorithm `natsort`
          uses when sorting. For details into these options, please see
          the :class:`ns` class documentation. The default is `ns.INT`.
  
      Returns
      -------
      out : function
          A function that parses input for natural sorting that is
          suitable for passing as the `key` argument to functions
          such as `sorted`.
  
      See Also
      --------
      natsorted
      natsort_key
  
      Examples
      --------
      `natsort_keygen` is a convenient way to create a custom key
      to sort lists in-place (for example).::
  
          >>> a = ['num5.10', 'num-3', 'num5.3', 'num2']
          >>> a.sort(key=natsort_keygen(alg=ns.REAL))
          >>> a
          [{u}'num-3', {u}'num2', {u}'num5.10', {u}'num5.3']
  
      """
      try:
          ns.DEFAULT | alg
      except TypeError:
          msg = "natsort_keygen: 'alg' argument must be from the enum 'ns'"
          raise ValueError(msg + ", got {}".format(py23_str(alg)))
  
      # Add the NS_DUMB option if the locale library is broken.
      if alg & ns.LOCALEALPHA and natsort.compat.locale.dumb_sort():
          alg |= NS_DUMB
  
      # Set some variables that will be passed to the factory functions
      if alg & ns.NUMAFTER:
          if alg & ns.LOCALEALPHA:
              sep = natsort.compat.locale.null_string_locale_max
          else:
              sep = natsort.compat.locale.null_string_max
          pre_sep = natsort.compat.locale.null_string_max
      else:
          if alg & ns.LOCALEALPHA:
              sep = natsort.compat.locale.null_string_locale
          else:
              sep = natsort.compat.locale.null_string
          pre_sep = natsort.compat.locale.null_string
      regex = utils.regex_chooser(alg)
  
      # Create the functions that will be used to split strings.
      input_transform = utils.input_string_transform_factory(alg)
      component_transform = utils.string_component_transform_factory(alg)
      final_transform = utils.final_data_transform_factory(alg, sep, pre_sep)
  
      # Create the high-level parsing functions for strings, bytes, and numbers.
      string_func = utils.parse_string_factory(
          alg, sep, regex.split, input_transform, component_transform, final_transform
      )
      if alg & ns.PATH:
          string_func = utils.parse_path_factory(string_func)
      bytes_func = utils.parse_bytes_factory(alg)
      num_func = utils.parse_number_factory(alg, sep, pre_sep)
  
      # Return the natsort key with the parsing path pre-chosen.
      return partial(
          utils.natsort_key,
          key=key,
          string_func=string_func,
          bytes_func=bytes_func,
          num_func=num_func,
      )