I am trying to get the code completion for a Scala interpreter to work. Ideally it would work identically to the one provided by the REPL (ILoop
). I am using a text document as source, so I do not want to instantiate an ILoop
but just IMain
.
In the following example, the completion only works for special cases:
import scala.tools.nsc.interpreter.{JLineCompletion, IMain}
import scala.tools.nsc.Settings
object CompletionTest extends App {
val settings = new Settings
settings.usejavacp.tryToSetFromPropertyValue("true")
val intp = new IMain(settings)
intp.initializeSynchronous()
assert(intp.isInitializeComplete)
val comp = new JLineCompletion(intp)
val completer = comp.completer()
val buffer = "val x = Indexe"
val choices = completer.complete(buffer, buffer.length)
println("----BEGIN COMPLETION----")
choices.candidates.foreach(println)
println("----END COMPLETION----")
intp.close()
}
The expected output would be IndexedSeq
, but it is empty. If I set the buffer to just Indexe
, it works. If I set the buffer to Indexe
(leading whitespace), the completion candidates are empty again.
So there must be an additional step involved in processing the buffer or invoking the completion. What exactly happens when <tab>
is pressed in the REPL? It seems almost impossible to figure out which methods are called...
In
JLineReader
, you can see the wiring.JLineConsoleReader
sets up anArgumentCompleter
with theScalaCompleter
as the underlying completer.So the completer wants just the argument, not the line.
In other keystrokes,
To hand it the full line:
The delimiter does the line parse.
Edit - some value-added analysis:
"Strict" mode for the completor exists because you can supply a completor for each token on the line, and require each previous argument to be completable. For n completors, all args after nth arg are handled by the last completor.