@@ -86,7 +86,7 @@ trait LoopCommands { self: { def echo(msg: String): Unit } =>
8686 }
8787 def ambiguousError (cmd : String ): Result = {
8888 matchingCommands(cmd) match {
89- case Nil => echo(cmd + " : no such command. Type :help for help." )
89+ case Nil => echo(s " No such command ' $cmd ' . Type :help for help." )
9090 case xs => echo(cmd + " is ambiguous: did you mean " + xs.map(" :" + _.name).mkString(" or " ) + " ?" )
9191 }
9292 Result (keepRunning = true , None )
@@ -95,7 +95,7 @@ trait LoopCommands { self: { def echo(msg: String): Unit } =>
9595 // all commands with given prefix
9696 private def matchingCommands (cmd : String ) = commands.filter(_.name.startsWith(cmd.stripPrefix(" :" )))
9797
98- // extract command from partial name, or prefer exact match if multiple matches
98+ // extract unique command from partial name, or prefer exact match if multiple matches
9999 private object CommandMatch {
100100 def unapply (name : String ): Option [LoopCommand ] =
101101 matchingCommands(name) match {
@@ -108,6 +108,7 @@ trait LoopCommands { self: { def echo(msg: String): Unit } =>
108108 // extract command name and rest of line
109109 private val commandish = """ (\S+)(?:\s+)?(.*)""" .r
110110
111+ // expect line includes leading colon
111112 def colonCommand (line : String ): Result = line.trim match {
112113 case " " => helpSummary()
113114 case commandish(CommandMatch (cmd), rest) => cmd(rest)
@@ -117,21 +118,30 @@ trait LoopCommands { self: { def echo(msg: String): Unit } =>
117118
118119 import Completion .Candidates
119120
120- def colonCompletion (line : String , cursor : Int ): Completion = line.trim match {
121- case commandish(name @ CommandMatch (cmd), rest) =>
122- if (name.length > cmd.name.length) cmd.completion
123- else
124- new Completion {
125- def resetVerbosity (): Unit = ()
126- def complete (buffer : String , cursor : Int ) = Candidates (cursor - name.length + 1 , List (cmd.name))
121+ def colonCompletion (line : String , cursor : Int ): Completion =
122+ line match {
123+ case commandish(name0, rest) =>
124+ val name = name0 take cursor
125+ val cmds = matchingCommands(name)
126+ val cursorAtName = cursor <= name.length
127+ cmds match {
128+ case Nil => NoCompletion
129+ case cmd :: Nil if ! cursorAtName => cmd.completion
130+ case cmd :: Nil if cmd.name == name => NoCompletion
131+ case cmd :: Nil =>
132+ val completion = if (cmd.isInstanceOf [NullaryCmd ] || cursor < line.length) cmd.name else cmd.name + " "
133+ new Completion {
134+ def resetVerbosity (): Unit = ()
135+ def complete (buffer : String , cursor : Int ) = Candidates (cursor = 1 , List (completion))
136+ }
137+ case cmd :: rest =>
138+ new Completion {
139+ def resetVerbosity (): Unit = ()
140+ def complete (buffer : String , cursor : Int ) = Candidates (cursor = 1 , cmds.map(_.name))
141+ }
127142 }
128- case commandish(name, _) if matchingCommands(name).nonEmpty =>
129- new Completion {
130- def resetVerbosity (): Unit = ()
131- def complete (buffer : String , cursor : Int ) = Candidates (cursor - name.length + 1 , matchingCommands(name).map(_.name))
132- }
133- case _ => NoCompletion
134- }
143+ case _ => NoCompletion
144+ }
135145
136146 class NullaryCmd (name : String , help : String , detailedHelp : Option [String ],
137147 f : String => Result ) extends LoopCommand (name, help, detailedHelp) {
0 commit comments