Skip to content

Support command prefixes in REPL #8901

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions compiler/src/dotty/tools/repl/ParseResult.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ sealed trait Command extends ParseResult
/** An unknown command that will not be handled by the REPL */
case class UnknownCommand(cmd: String) extends Command

/** An ambiguous prefix that matches multiple commands */
case class AmbiguousCommand(cmd: String, matchingCommands: List[String]) extends Command

/** `:load <path>` interprets a scala file as if entered line-by-line into
* the REPL
*/
Expand Down Expand Up @@ -116,19 +119,27 @@ object ParseResult {
stats
}

private val commands: List[(String, String => ParseResult)] = List(
Quit.command -> (_ => Quit),
Help.command -> (_ => Help),
Reset.command -> (_ => Reset),
Imports.command -> (_ => Imports),
Load.command -> (arg => Load(arg)),
TypeOf.command -> (arg => TypeOf(arg)),
DocOf.command -> (arg => DocOf(arg))
)

def apply(source: SourceFile)(implicit state: State): ParseResult = {
val sourceCode = source.content().mkString
sourceCode match {
case "" => Newline
case CommandExtract(cmd, arg) => cmd match {
case Quit.command => Quit
case Help.command => Help
case Reset.command => Reset
case Imports.command => Imports
case Load.command => Load(arg)
case TypeOf.command => TypeOf(arg)
case DocOf.command => DocOf(arg)
case _ => UnknownCommand(cmd)
case CommandExtract(cmd, arg) => {
val matchingCommands = commands.filter((command, _) => command.startsWith(cmd))
matchingCommands match {
case Nil => UnknownCommand(cmd)
case (_, f) :: Nil => f(arg)
case multiple => AmbiguousCommand(cmd, multiple.map(_._1))
}
}
case _ =>
implicit val ctx: Context = state.context
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ class ReplDriver(settings: Array[String],
out.println(s"""Unknown command: "$cmd", run ":help" for a list of commands""")
state

case AmbiguousCommand(cmd, matching) =>
out.println(s""""$cmd" matches ${matching.mkString(", ")}. Try typing a few more characters. Run ":help" for a list of commands""")
state

case Help =>
out.println(Help.text)
state
Expand Down
6 changes: 6 additions & 0 deletions compiler/test-resources/repl/commandPrefixes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
scala>:t 123
Int
scala>:type 123
Int
scala>:typee 123
Unknown command: ":typee", run ":help" for a list of commands