# File lib/rbreadline.rb, line 6738
  def rl_complete_internal(what_to_do)
    rl_setstate(RL_STATE_COMPLETING)
    set_completion_defaults(what_to_do)

    saved_line_buffer = @rl_line_buffer ? @rl_line_buffer.delete(0.chr) : nil
    our_func = @rl_completion_entry_function ?
      @rl_completion_entry_function : :rl_filename_completion_function
    # We now look backwards for the start of a filename/variable word.
    _end = @rl_point
    found_quote = false
    delimiter = 0.chr
    quote_char = 0.chr

    if (@rl_point!=0)
      # This (possibly) changes rl_point.  If it returns a non-zero char,
      #   we know we have an open quote.
      quote_char,found_quote,delimiter = _rl_find_completion_word()
    end

    start = @rl_point
    @rl_point = _end

    text = rl_copy_text(start, _end)
    matches = gen_completion_matches(text, start, _end, our_func, found_quote, quote_char)
    # nontrivial_lcd is set if the common prefix adds something to the word
    #   being completed.
    nontrivial_lcd = !!(matches && text != matches[0])
    text = nil
    if matches.nil?
      rl_ding()
      saved_line_buffer = nil
      @completion_changed_buffer = false
      rl_unsetstate(RL_STATE_COMPLETING)
      return 0
    end

    # If we are matching filenames, the attempted completion function will
    #   have set rl_filename_completion_desired to a non-zero value.  The basic
    #   rl_filename_completion_function does this.
    i = @rl_filename_completion_desired
    if (postprocess_matches(matches, i) == 0)
      rl_ding()
      saved_line_buffer = nil
      @completion_changed_buffer = false
      rl_unsetstate(RL_STATE_COMPLETING)
      return 0
    end

    case (what_to_do)

    when TAB,'!','@'
      # Insert the first match with proper quoting.
      if (matches[0])
        insert_match(matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, quote_char)
      end
    # If there are more matches, ring the bell to indicate.
    # If we are in vi mode, Posix.2 says to not ring the bell.
    # If the `show-all-if-ambiguous' variable is set, display
    # all the matches immediately.  Otherwise, if this was the
    # only match, and we are hacking files, check the file to
    # see if it was a directory.  If so, and the `mark-directories'
    # variable is set, add a '/' to the name.  If not, and we
    # are at the end of the line, then add a space.
    if (matches[1])
      if (what_to_do == '!')
        display_matches(matches)
      elsif (what_to_do == '@')
        if (!nontrivial_lcd)
          display_matches(matches)
        end
      elsif (@rl_editing_mode != @vi_mode)
        rl_ding()   # There are other matches remaining.
      end
    else
      append_to_match(matches[0], delimiter, quote_char, nontrivial_lcd)
    end
    when '*'
      insert_all_matches(matches, start, quote_char)
    when '?'
      display_matches(matches)
    else
      $stderr.write("\r\nreadline: bad value #{what_to_do} for what_to_do in rl_complete\n")
      rl_ding()
      saved_line_buffer = nil
      rl_unsetstate(RL_STATE_COMPLETING)
      return 1
    end

    matches = nil

    # Check to see if the line has changed through all of this manipulation.
    if (saved_line_buffer)
      @completion_changed_buffer = @rl_line_buffer.delete(0.chr) != saved_line_buffer
      saved_line_buffer = nil
    end

    rl_unsetstate(RL_STATE_COMPLETING)
    0
  end