Skip to content

Commit 709968d

Browse files
committed
REPL completions: Enter import mode only when cursor beyond "import"
Fixes JuliaLang#55842
1 parent 28d3bd5 commit 709968d

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

stdlib/REPL/src/REPLCompletions.jl

+8-5
Original file line numberDiff line numberDiff line change
@@ -936,13 +936,16 @@ const superscripts = Dict(k[3]=>v[1] for (k,v) in latex_symbols if startswith(k,
936936
const superscript_regex = Regex("^\\\\\\^[" * join(isdigit(k) || isletter(k) ? "$k" : "\\$k" for k in keys(superscripts)) * "]+\\z")
937937

938938
# Aux function to detect whether we're right after a using or import keyword
939-
function get_import_mode(s::String)
939+
function get_import_mode(s::String, pos::Int)
940940
# allow all of these to start with leading whitespace and macros like @eval and @eval(
941941
# ^\s*(?:@\w+\s*(?:\(\s*)?)?
942942

943+
# Do not enter import mode unless cursor beyond import keyword
944+
beyond_kw(m) = pos >= m.offsets[1] + length(m[1])
945+
943946
# match simple cases like `using |` and `import |`
944947
mod_import_match_simple = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s*$", s)
945-
if mod_import_match_simple !== nothing
948+
if mod_import_match_simple !== nothing && beyond_kw(mod_import_match_simple)
946949
if mod_import_match_simple[1] == "using"
947950
return :using_module
948951
else
@@ -951,7 +954,7 @@ function get_import_mode(s::String)
951954
end
952955
# match module import statements like `using Foo|`, `import Foo, Bar|` and `using Foo.Bar, Baz, |`
953956
mod_import_match = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s+([\w\.]+(?:\s*,\s*[\w\.]+)*),?\s*$", s)
954-
if mod_import_match !== nothing
957+
if mod_import_match !== nothing && beyond_kw(mod_import_match)
955958
if mod_import_match.captures[1] == "using"
956959
return :using_module
957960
else
@@ -960,7 +963,7 @@ function get_import_mode(s::String)
960963
end
961964
# now match explicit name import statements like `using Foo: |` and `import Foo: bar, baz|`
962965
name_import_match = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s+([\w\.]+)\s*:\s*([\w@!\s,]+)$", s)
963-
if name_import_match !== nothing
966+
if name_import_match !== nothing && beyond_kw(name_import_match)
964967
if name_import_match[1] == "using"
965968
return :using_name
966969
else
@@ -1459,7 +1462,7 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
14591462
separatorpos = something(findprev(isequal('.'), string, pos), 0)
14601463
namepos = max(startpos, separatorpos+1)
14611464
name = string[namepos:pos]
1462-
import_mode = get_import_mode(string)
1465+
import_mode = get_import_mode(string, pos)
14631466
if import_mode === :using_module || import_mode === :import_module
14641467
# Given input lines like `using Foo|`, `import Foo, Bar|` and `using Foo.Bar, Baz, |`:
14651468
# Let's look only for packages and modules we can reach from here

stdlib/REPL/test/replcompletions.jl

+8
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ end
180180

181181
test_complete(s) = map_completion_text(@inferred(completions(s, lastindex(s))))
182182
test_scomplete(s) = map_completion_text(@inferred(shell_completions(s, lastindex(s))))
183+
# | is reserved in test_complete_pos
184+
test_complete_pos(s) = map_completion_text(@inferred(completions(replace(s, '|' => ""), findfirst('|', s)-1)))
183185
test_complete_context(s, m=@__MODULE__; shift::Bool=true) =
184186
map_completion_text(@inferred(completions(s,lastindex(s), m, shift)))
185187
test_complete_foo(s) = test_complete_context(s, Main.CompletionFoo)
@@ -2484,3 +2486,9 @@ let (c, r, res) = test_complete_context("global xxx::Number = Base.", Main)
24842486
@test res
24852487
@test "pi" c
24862488
end
2489+
2490+
# #57473
2491+
let (c, r) = test_complete_pos("@tim| using Date")
2492+
@test "@time" in c
2493+
@test r == 1:4
2494+
end

0 commit comments

Comments
 (0)