Repository: JuliaLang/julia
File: stdlib/REPL/src/REPLCompletions.jl (Julia)

Code before:

    # Strip the preceding ! operators, if any, and close the expression with a ')'
    s = replace(partial[frange], r"\G\!+([^=\(]+)" => s"\1"; count=1) * ')'
    ex = Meta.parse(s, raise=false, depwarn=false)
    isa(ex, Expr) || return fail

    # `wordrange` is the position of the last argument to complete
    wordrange = nextind(partial, before_last_word_start):last_idx
    return frange, ex, wordrange, method_name_end
end

# Provide completion for keyword arguments in function calls
function complete_keyword_argument(partial::String, last_idx::Int, context_module::Module;
                                   shift::Bool=false)
    frange, ex, wordrange, = identify_possible_method_completion(partial, last_idx)
    fail = Completion[], 0:-1, frange
    ex.head === :call || is_broadcasting_expr(ex) || return fail

    kwargs_flag, funct, args_ex, kwargs_ex = _complete_methods(ex, context_module, true)::Tuple{Int, Any, Vector{Any}, Set{Symbol}}
    kwargs_flag == 2 && return fail # one of the previous kwargs is invalid

    methods = Completion[]
    # limit the number of methods to prevent performance issues while allowing
    # completions for nearly all common functions. This is distinct from the other
    # uses of MAX_METHOD_COMPLETIONS, which primarily used to limit the number
    # of methods to _display_ before showing an alternative message; here we're 
    # searching a larger number to find a subset that contains matching kwargs
    complete_methods!(methods, funct, Any[Vararg{Any}], kwargs_ex, shift ? -1 : 500, kwargs_flag == 1)
    # TODO: use args_ex instead of Any[Vararg{Any}] and only provide kwarg completion for
    # method calls compatible with the current arguments.

    # For each method corresponding to the function call, provide completion suggestions
    # for each keyword that starts like the last word and that is not already used
    # previously in the expression. The corresponding suggestion is "kwname=".
    # If the keyword corresponds to an existing name, also include "kwname" as a suggestion
    # since the syntax "foo(; kwname)" is equivalent to "foo(; kwname=kwname)".
    last_word = partial[wordrange] # the word to complete
    kwargs = Set{String}()
    for m in methods
        # if MAX_METHOD_COMPLETIONS is hit a single TextCompletion is return by complete_methods! with an explanation
        # which can be ignored here
        m isa TextCompletion && continue
        m::MethodCompletion
        possible_kwargs = Base.kwarg_decl(m.method)
        current_kwarg_candidates = String[]
        for _kw in possible_kwargs
            kw = String(_kw)
            if !endswith(kw, "...") && startswith(kw, last_word) && _kw ∉ kwargs_ex
                push!(current_kwarg_candidates, kw)
            end
        end

Review comment (suggestion):
```suggestion
    # of methods to _display_ before showing an alternative message; here we're
```

Code after:
    r, closed = find_str(cur)
    if r !== nothing
        s = do_string_unescape(string[r])
        ret, success = complete_path_string(s, hint; string_escape=true,
                                            dirsep=Sys.iswindows() ? '\\' : '/')
        if length(ret) == 1 && !closed && close_path_completion(ret[1].path)
            ret[1] = PathCompletion(ret[1].path * '"')
        end
        success && return ret, r, success
    end

    # Backlash symbols:
    #   \pi => π
    # Comes after string completion so backslash escapes are not misinterpreted.
    ok, ret = bslash_completions(string, pos)
    ok && return ret

    # Don't fall back to symbol completion inside strings or comments.
    inside_cmdstr = find_parent(cur, K"cmdstring") !== nothing
    (kind(cur) in KSet"String Comment ErrorEofMultiComment" || inside_cmdstr) &&
         return Completion[], 1:0, false

    n, arg_pos = find_prefix_call(cur_not_ws)
    if n !== nothing
        func = first(children_nt(n))
        e = Expr(n)
        # Remove arguments past the first parse error (allows unclosed parens)
        if is_broadcasting_expr(e)
            i = findfirst(x -> x isa Expr && x.head == :error, e.args[2].args)
            i !== nothing && deleteat!(e.args[2].args, i:lastindex(e.args[2].args))
        else
            i = findfirst(x -> x isa Expr && x.head == :error, e.args)
            i !== nothing && deleteat!(e.args, i:lastindex(e.args))
        end

        # Method completion:
        #   foo( TAB     => list of method signatures for foo
        #   foo(x, TAB   => list of methods signatures for foo with x as first argument
        if kind(cur_not_ws) in KSet"( , ;"
            # Don't provide method completions unless the cursor is after: '(' ',' ';'
            return complete_methods(e, context_module, shift, arg_pos), char_range(func), false

        # Keyword argument completion:
        #   foo(ar TAB   => keyword arguments like `arg1=`
        elseif kind(cur) == K"Identifier"
            r = char_range(cur)
            s = string[intersect(r, 1:pos)]
            # Return without adding more suggestions if kwargs only
            complete_keyword_argument!(suggestions, e, s, context_module, arg_pos; shift) &&
                return sort_suggestions(), r, true
        end