我正在尝试让Scala解释器的代码完成。理想情况下,它的工作方式与REPL(ILoop
)提供的工作方式相同。我使用文本文档作为源代码,因此我不想实例化ILoop
而只是IMain
。
在以下示例中,完成仅适用于特殊情况:
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()
}
预期输出为IndexedSeq
,但为空。如果我将缓冲区设置为Indexe
,则可以正常工作。如果我将缓冲区设置为 Indexe
(前导空格),则完成候选项将再次为空。
因此,处理缓冲区或调用完成时必须有一个额外的步骤。在REPL中按下<tab>
时到底发生了什么?似乎几乎不可能弄清楚哪种方法被称为......
答案 0 :(得分:1)
在JLineReader
中,您可以看到布线。 JLineConsoleReader
设置ArgumentCompleter
,其中ScalaCompleter
为基础完成者。
所以完成者只需要参数,而不是直线。
apm@mara:~$ scalam
Welcome to Scala version 2.11.0-M7 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'. **
** scala.tools.nsc._ has been imported **
** global._, definitions._ also imported **
** Try :help, :vals, power.<tab> **
scala> val b = "Indexe"
b: String = Indexe
scala> completion.completer complete (b, b.length)
res0: scala.tools.nsc.interpreter.Completion.Candidates = Candidates(0,List(IndexedSeq))
在其他击键中,
// paste your code
scala> val buffer = "Indexe"
buffer: String = Indexe
scala> completer.complete(buffer, buffer.length)
res6: scala.tools.nsc.interpreter.Completion.Candidates = Candidates(0,List(IndexedSeq))
scala> import tools.nsc.interpreter.Completion.Candidates
import tools.nsc.interpreter.Completion.Candidates
scala> val Candidates(_, choices) = completer.complete(buffer, buffer.length)
choices: List[String] = List(IndexedSeq)
scala> choices foreach println
IndexedSeq
全力以赴:
scala> val argCompletor: ArgumentCompleter =new ArgumentCompleter(new JLineDelimiter, scalaToJline(comp.completer))
argCompletor: jline.console.completer.ArgumentCompleter = jline.console.completer.ArgumentCompleter@751222c7
scala> val maybes = new java.util.ArrayList[CharSequence]
maybes: java.util.ArrayList[CharSequence] = []
scala> val buffer = "val x = Indexe"
buffer: String = val x = Indexe
scala> argCompletor.setStrict(false)
scala> argCompletor.complete(buffer, buffer.length, maybes)
res32: Int = 8
scala> maybes
res33: java.util.ArrayList[CharSequence] = [IndexedSeq]
分隔符执行行解析。
编辑 - 一些增值分析:
completor的“严格”模式存在,因为您可以为该行上的每个标记提供一个completor,并要求每个前一个参数都是可完成的。对于n个completors,第n个arg之后的所有args都由最后一个completor处理。
答案 1 :(得分:0)
部分答案。我设法通过覆盖scalaToJline
中的JLineReader
在该怪物上挖洞。在跟踪此跟踪之后,使用预先按摩的字符串调用该方法:
at CompletionTest$$anon$1$$anon$2$$anon$3.complete(CompletionTest.scala:37)
at scala.tools.jline.console.completer.ArgumentCompleter.complete(ArgumentCompleter.java:150)
at scala.tools.jline.console.ConsoleReader.complete(ConsoleReader.java:1543)
at scala.tools.jline.console.ConsoleReader.readLine(ConsoleReader.java:1312)
at scala.tools.jline.console.ConsoleReader.readLine(ConsoleReader.java:1170)
at scala.tools.nsc.interpreter.JLineReader.readOneLine(JLineReader.scala:74)
at scala.tools.nsc.interpreter.InteractiveReader$$anonfun$readLine$2.apply(InteractiveReader.scala:42)
at scala.tools.nsc.interpreter.InteractiveReader$$anonfun$readLine$2.apply(InteractiveReader.scala:42)
at scala.tools.nsc.interpreter.InteractiveReader$.restartSysCalls(InteractiveReader.scala:49)
at scala.tools.nsc.interpreter.InteractiveReader$class.readLine(InteractiveReader.scala:42)
at scala.tools.nsc.interpreter.JLineReader.readLine(JLineReader.scala:19)
at scala.tools.nsc.interpreter.ILoop.readOneLine$1(ILoop.scala:568)
at scala.tools.nsc.interpreter.ILoop.innerLoop$1(ILoop.scala:584)
at scala.tools.nsc.interpreter.ILoop.loop(ILoop.scala:587)
答案 2 :(得分:0)
所以这是我的“无线”,似乎按预期工作:
import scala.tools.nsc.interpreter._
import scala.tools.jline.console.completer.{Completer, ArgumentCompleter}
import scala.tools.nsc.interpreter.Completion.{Candidates, ScalaCompleter}
import scala.tools.nsc.Settings
import collection.JavaConverters._
object Completion2 extends App {
val settings = new Settings
settings.usejavacp.tryToSetFromPropertyValue("true")
val intp = new IMain(settings)
intp.initializeSynchronous()
val completion = new JLineCompletion(intp)
def scalaToJline(tc: ScalaCompleter): Completer = new Completer {
def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = {
val buf = if (_buf == null) "" else _buf
val Candidates(newCursor, newCandidates) = tc.complete(buf, cursor)
newCandidates foreach (candidates add _)
newCursor
}
}
val argCompletor: ArgumentCompleter =
new ArgumentCompleter(new JLineDelimiter, scalaToJline(completion.completer()))
argCompletor.setStrict(false)
val jlist: java.util.List[CharSequence] = new java.util.ArrayList
val buffer = "val x = Indexe"
argCompletor.complete(buffer, buffer.length, jlist)
val list = jlist.asScala
println("----BEGIN COMPLETION----")
list.foreach(println)
println("----END COMPLETION----")
intp.close()
}
编辑:出于某种原因,这会导致通配符导入出现问题。就像我执行
一样import mypackage.MySymbol
然后完成者找到MySymbol
。但如果我执行
import mypackage._
然后找不到mypackage
的任何内容。有什么想法吗?