docs: def preprocess_user_variables(userinput):
    """
    <Purpose>
      Command parser for user variables.  Takes the raw userinput and replaces
      each user variable with its set value.
    <Arguments>
      userinput: A raw user string
    <Side Effects>
      Each user variable will be replaced by the value that it was previously
      set to.
    <Exceptions>
      UserError: User typed an unrecognized or invalid variable name
    <Returns>
      The preprocessed string
    """
    retstr = ""
    while '$' in userinput:
      text_before_variable , variable_delimiter, userinput = userinput.partition('$')
      retstr += text_before_variable
  
      # Treat $$ as an escape for a single $.
      # Also escape if there is nothing left
      if not userinput or userinput.startswith('$'):
        retstr += '$'
        userinput = userinput[1:]
        continue
  
      # Look for the next space, or the next $.  The closest one of these will be
      # used as the delimiter.  Then update the remaining user input.
      space_variable_length = userinput.find(' ')
      dollarsign_variable_length = userinput.find('$')
  
      # If the length is -1, then the delimiter was not found.
      # We use the length of the entire string to represent this.
      # If there was one delimiter found, then that delimiter's value
      # will always be less than the string's length.
      # If it is a tie, then it simply means that the entire string
      # is the variable name.
      if space_variable_length == -1:
        space_variable_length = len(userinput)
      if dollarsign_variable_length == -1:
        dollarsign_variable_length = len(userinput)
  
      variable_length = min(space_variable_length, dollarsign_variable_length)
      variable_name = userinput[:variable_length]
      userinput = userinput[variable_length + 1:]  # Skip the actual delimiter
  
      # Perform the replacement!
      # User may type in a variable that has not yet been defined
      try:
        retstr += uservariables[variable_name]
      except KeyError:
        raise seash_exceptions.UserError("Variable does not exist: "+variable_name)
  
      # The user expects a space before the string right after the variable.
      # e.g. 'loadkeys $myname as awesome' should turn into
      #      'loadkeys theusername as awesome'
      if space_variable_length < dollarsign_variable_length:
        retstr += ' '
  
    # Now add the remaining text after the last variable
    else:
      retstr += userinput
  
    return retstr