Skip to content

Commit f4fc810

Browse files
committed
REPL completions: Enter import mode only when cursor beyond "import"
Fixes JuliaLang#55842
1 parent 05b4722 commit f4fc810

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
@@ -939,13 +939,16 @@ const superscripts = Dict(k[3]=>v[1] for (k,v) in latex_symbols if startswith(k,
939939
const superscript_regex = Regex("^\\\\\\^[" * join(isdigit(k) || isletter(k) ? "$k" : "\\$k" for k in keys(superscripts)) * "]+\\z")
940940

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

946+
# Do not enter import mode unless cursor beyond import keyword
947+
beyond_kw(m) = pos >= m.offsets[1] + length(m[1])
948+
946949
# match simple cases like `using |` and `import |`
947950
mod_import_match_simple = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s*$", s)
948-
if mod_import_match_simple !== nothing
951+
if mod_import_match_simple !== nothing && beyond_kw(mod_import_match_simple)
949952
if mod_import_match_simple[1] == "using"
950953
return :using_module
951954
else
@@ -954,7 +957,7 @@ function get_import_mode(s::String)
954957
end
955958
# match module import statements like `using Foo|`, `import Foo, Bar|` and `using Foo.Bar, Baz, |`
956959
mod_import_match = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s+([\w\.]+(?:\s*,\s*[\w\.]+)*),?\s*$", s)
957-
if mod_import_match !== nothing
960+
if mod_import_match !== nothing && beyond_kw(mod_import_match)
958961
if mod_import_match.captures[1] == "using"
959962
return :using_module
960963
else
@@ -963,7 +966,7 @@ function get_import_mode(s::String)
963966
end
964967
# now match explicit name import statements like `using Foo: |` and `import Foo: bar, baz|`
965968
name_import_match = match(r"^\s*(?:@\w+\s*(?:\(\s*)?)?\b(using|import)\s+([\w\.]+)\s*:\s*([\w@!\s,]+)$", s)
966-
if name_import_match !== nothing
969+
if name_import_match !== nothing && beyond_kw(name_import_match)
967970
if name_import_match[1] == "using"
968971
return :using_name
969972
else
@@ -1462,7 +1465,7 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
14621465
separatorpos = something(findprev(isequal('.'), string, pos), 0)
14631466
namepos = max(startpos, separatorpos+1)
14641467
name = string[namepos:pos]
1465-
import_mode = get_import_mode(string)
1468+
import_mode = get_import_mode(string, pos)
14661469
if import_mode === :using_module || import_mode === :import_module
14671470
# Given input lines like `using Foo|`, `import Foo, Bar|` and `using Foo.Bar, Baz, |`:
14681471
# 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)