# File lib/rbreadline.rb, line 1118
  def rl_filename_completion_function(text, state)
    # If we don't have any state, then do some initialization.
    if (state == 0)
      # If we were interrupted before closing the directory or reading
      #all of its contents, close it.
      if(@directory)
        @directory.close
        @directory = nil
      end

      text.delete!(0.chr)
      if text.length == 0
        @dirname = "."
        @filename = ""
      elsif text.rindex(File::SEPARATOR) == text.length-1
        @dirname = text
        @filename = ""
      else
        @dirname, @filename = File.split(text)

        # This preserves the "./" when the user types "./dirname<tab>".
        if @dirname == "." && text[0,2] == ".#{File::SEPARATOR}"
          @dirname += File::SEPARATOR
        end
      end

      # We aren't done yet.  We also support the "~user" syntax.

      # Save the version of the directory that the user typed.
      @users_dirname = @dirname.dup

      if (@dirname[0,1] == '~')
        @dirname = File.expand_path(@dirname)
      end

      # The directory completion hook should perform any necessary
      #   dequoting.
      if (@rl_directory_completion_hook && send(rl_directory_completion_hook,@dirname))
        @users_dirname = @dirname.dup
      elsif (@rl_completion_found_quote && @rl_filename_dequoting_function)
        # delete single and double quotes
        temp = send(@rl_filename_dequoting_function, @users_dirname, @rl_completion_quote_character)
        @users_dirname = temp
        @dirname = @users_dirname.dup
      end

      begin
        @directory = Dir.new(@dirname)
      rescue Errno::ENOENT, Errno::ENOTDIR, Errno::EACCES
      end

      # Now dequote a non-null filename.
      if (@filename && @filename.length>0 && @rl_completion_found_quote && @rl_filename_dequoting_function)
        # delete single and double quotes
        temp = send(@rl_filename_dequoting_function, @filename, @rl_completion_quote_character)
        @filename = temp
      end

      @filename_len = @filename.length
      @rl_filename_completion_desired = true
    end

    # At this point we should entertain the possibility of hacking wildcarded
    #   filenames, like /usr/man/man<WILD>/te<TAB>.  If the directory name
    #   contains globbing characters, then build an array of directories, and
    #   then map over that list while completing.
    # *** UNIMPLEMENTED ***

    # Now that we have some state, we can read the directory.
    entry = nil
    while(@directory && (entry = @directory.read))
      d_name = entry
      # Special case for no filename.  If the user has disabled the
      #   `match-hidden-files' variable, skip filenames beginning with `.'.
      #All other entries except "." and ".." match.
      if (@filename_len == 0)
        next if (!@_rl_match_hidden_files && d_name[0,1] == '.')
        break if (d_name != '.' && d_name != '..')
      else
        # Otherwise, if these match up to the length of filename, then
        #   it is a match.

        if (@_rl_completion_case_fold)
          break if d_name =~ /^#{Regexp.escape(@filename)}/i
        else
          break if d_name =~ /^#{Regexp.escape(@filename)}/
        end
      end
    end

    if entry.nil?
      if @directory
        @directory.close
        @directory = nil
      end
      @dirname = nil
      @filename = nil
      @users_dirname = nil

      return nil
    else
      if (@dirname != '.')
        if (@rl_complete_with_tilde_expansion && @users_dirname[0,1] == "~")
          temp = @dirname
          if(temp[-1,1] != File::SEPARATOR)
            temp += File::SEPARATOR
          end
        else
          temp = @users_dirname
          if(temp[-1,1] != File::SEPARATOR)
            temp += File::SEPARATOR
          end
        end
        temp += entry
      else
        temp = entry.dup
      end
      return (temp)
    end
  end