This is an automated email from the ASF dual-hosted git repository.

aradzinski pushed a commit to branch NLPCRAFT-108
in repository https://gitbox.apache.org/repos/asf/incubator-nlpcraft.git


The following commit(s) were added to refs/heads/NLPCRAFT-108 by this push:
     new 1d0690b  Update NCCli.scala
1d0690b is described below

commit 1d0690bad1ca76d515031703f5ba8864cf4fe656
Author: Aaron Radzinski <[email protected]>
AuthorDate: Fri Oct 2 20:54:29 2020 -0700

    Update NCCli.scala
---
 .../nlpcraft/model/tools/cmdline/NCCli.scala       | 149 +++++++++++----------
 1 file changed, 75 insertions(+), 74 deletions(-)

diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
index 2b4256b..e16a6eb 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/model/tools/cmdline/NCCli.scala
@@ -37,17 +37,16 @@ import org.apache.nlpcraft.common.version.NCVersion
 import java.lang.ProcessBuilder.Redirect
 import java.lang.management.ManagementFactory
 import java.text.DateFormat
+import java.util
 import java.util.Date
 import java.util.regex.PatternSyntaxException
 
 import org.apache.nlpcraft.common.util.NCUtils.IntTimeUnits
-import org.jline.builtins.Completers.TreeCompleter
-import org.jline.builtins.Completers.TreeCompleter.node
+import org.jline.reader.Completer
 import org.jline.reader.impl.DefaultParser
 import org.jline.terminal.TerminalBuilder
-import org.jline.reader.{EndOfFileException, LineReader, LineReaderBuilder, 
UserInterruptException}
+import org.jline.reader.{Candidate, EndOfFileException, LineReader, 
LineReaderBuilder, ParsedLine, UserInterruptException}
 import org.jline.reader.impl.DefaultParser.Bracket
-import org.jline.reader.impl.completer.AggregateCompleter
 import org.jline.widget.AutosuggestionWidgets
 import resource.managed
 
@@ -87,26 +86,13 @@ object NCCli extends App {
 
     // Single CLI command.
     case class Command(
-        id: String,
-        names: Seq[String],
+        name: String,
         synopsis: String,
         desc: Option[String] = None,
         params: Seq[Parameter] = Seq.empty,
         examples: Seq[Example] = Seq.empty,
         body: (Command, Seq[Argument], Boolean) ⇒ Unit
     ) {
-        final val extNames = names.flatMap(name ⇒ // Safeguard against 
"common" errors.
-            Seq(
-                name,
-                s"-$name",
-                s"--$name",
-                s"/$name",
-                s"\\$name"
-            )
-        )
-
-        final val mainName = names.head
-
         /**
          *
          * @param name
@@ -146,8 +132,7 @@ object NCCli extends App {
     // All supported commands.
     private final val CMDS = Seq(
         Command(
-            id = "start-server",
-            names = Seq("start-server"),
+            name = "start-server",
             synopsis = s"Starts local REST server.",
             desc = Some(
                 s"REST server is started in the external JVM process with both 
stdout and stderr piped out into log file. " +
@@ -207,15 +192,13 @@ object NCCli extends App {
             )
         ),
         Command(
-            id = "get-server",
-            names = Seq("get-server"),
+            name = "get-server",
             synopsis = s"Basic information about locally running REST server.",
             body = cmdGetServer
         ),
         Command(
-            id = "no-ansi",
-            names = Seq("no-ansi"),
-            synopsis = s"Disables usage of ANSI escape codes (colors & 
terminal controls).",
+            name = "no-ansi",
+            synopsis = s"Disables usage of ANSI escape codes for colors & 
terminal controls.",
             desc = Some(
                 s"This is a special command that can be combined with any 
other commands."
             ),
@@ -228,9 +211,8 @@ object NCCli extends App {
             )
         ),
         Command(
-            id = "ansi",
-            names = Seq("ansi"),
-            synopsis = s"Enables usage of ANSI escape codes (colors & terminal 
controls).",
+            name = "ansi",
+            synopsis = s"Enables usage of ANSI escape codes for colors & 
terminal controls.",
             desc = Some(
                 s"This is a special command that can be combined with any 
other commands."
             ),
@@ -243,8 +225,7 @@ object NCCli extends App {
             )
         ),
         Command(
-            id = "ping-server",
-            names = Seq("ping-server"),
+            name = "ping-server",
             synopsis = s"Pings REST server.",
             desc = Some(
                 s"REST server is pinged using '/health' REST call to check its 
live status."
@@ -285,8 +266,7 @@ object NCCli extends App {
             )
         ),
         Command(
-            id = "stop-server",
-            names = Seq("stop-server"),
+            name = "stop-server",
             synopsis = s"Stops local REST server.",
             desc = Some(
                 s"Local REST server must be started via $SCRIPT_NAME or 
similar way."
@@ -294,8 +274,12 @@ object NCCli extends App {
             body = cmdStopServer
         ),
         Command(
-            id = "help",
-            names = Seq("help"),
+            name = "quit",
+            synopsis = s"Quits REPL session when in REPL mode.",
+            body = cmdQuit
+        ),
+        Command(
+            name = "help",
             synopsis = s"Displays manual page for '$SCRIPT_NAME'.",
             desc = Some(
                 s"By default, without '-all' or '-cmd' parameters, displays 
the abbreviated form of manual " +
@@ -329,8 +313,7 @@ object NCCli extends App {
             )
         ),
         Command(
-            id = "ver",
-            names = Seq("version", "ver"),
+            name = "version",
             synopsis = s"Displays full version of '$SCRIPT_NAME' script.",
             desc = Some(
                 "Depending on the additional parameters can display only the 
semantic version or the release date."
@@ -354,8 +337,7 @@ object NCCli extends App {
             )
         ),
         Command(
-            id = "repl",
-            names = Seq("repl"),
+            name = "repl",
             synopsis = s"Starts '$SCRIPT_NAME' in interactive REPL mode.",
             desc = Some(
                 s"REPL mode supports all the same commands as command line 
mode. " +
@@ -365,16 +347,17 @@ object NCCli extends App {
             ),
             body = cmdRepl
         )
-    ).sortBy(_.id)
+    ).sortBy(_.name)
 
     require(
-        U.getDups(CMDS.flatMap(_.names)).isEmpty,
+        U.getDups(CMDS.map(_.name)).isEmpty,
         "Dup commands."
     )
 
-    private final val DFLT_CMD = CMDS.find(_.id ==  "repl").get
-    private final val NO_ANSI_CMD = CMDS.find(_.id ==  "no-ansi").get
-    private final val ANSI_CMD = CMDS.find(_.id ==  "ansi").get
+    private final val DFLT_CMD = CMDS.find(_.name ==  "repl").get
+    private final val NO_ANSI_CMD = CMDS.find(_.name ==  "no-ansi").get
+    private final val ANSI_CMD = CMDS.find(_.name ==  "ansi").get
+    private final val QUIT_CMD = CMDS.find(_.name ==  "quit").get
 
     /**
      *
@@ -661,6 +644,14 @@ object NCCli extends App {
         catch {
             case _: Exception ⇒ None
         }
+    /**
+     * @param cmd Command descriptor.
+     * @param args Arguments, if any, for this command.
+     * @param repl Whether or not executing from REPL.
+     */
+    private def cmdQuit(cmd: Command, args: Seq[Argument], repl: Boolean): 
Unit = {
+        // No-op.
+    }
 
     /**
      * @param cmd Command descriptor.
@@ -775,7 +766,7 @@ object NCCli extends App {
                 header()
 
             CMDS.foreach(cmd ⇒ tbl +/ (
-                "" → cmd.names.mkString(ansiGreenFg, ", ", ansiReset),
+                "" → s"${g(cmd.name)}",
                 "align:left, maxWidth:85" → cmd.synopsis
             ))
 
@@ -787,7 +778,7 @@ object NCCli extends App {
 
             CMDS.foreach(cmd ⇒
                 tbl +/ (
-                    "" → cmd.names.mkString(ansiGreenFg, ", ", ansiReset),
+                    "" → s"${g(cmd.name)}",
                     "align:left, maxWidth:85" → mkCmdLines(cmd)
                 )
             )
@@ -801,15 +792,15 @@ object NCCli extends App {
             for (arg ← args) {
                 val cmdName = arg.value.get
 
-                CMDS.find(_.names.contains(cmdName)) match {
+                CMDS.find(_.name.contains(cmdName)) match {
                     case Some(c) ⇒
-                        if (!seen.contains(c.id)) {
+                        if (!seen.contains(c.name)) {
                             tbl +/ (
-                                "" → c.names.mkString(ansiGreenFg, ", ", 
ansiReset),
+                                "" → s"${g(cmd.name)}",
                                 "align:left, maxWidth:85" → mkCmdLines(c)
                             )
 
-                            seen += c.id
+                            seen += c.name
                         }
                     case None ⇒
                         err = true
@@ -870,15 +861,6 @@ object NCCli extends App {
             case None ⇒ ()
         }
 
-        logln(s"Type '${c("help")}' or '${c("help -c=repl")}' to get help.")
-        logln(s"Type '${c("quit")}' to exit.")
-
-        val QUITS = Seq(
-            "quit", "exit", "/q", "\\q"
-        )
-
-        var exit = false
-
         val appName = s"$NAME ver. ${VER.version}"
 
         val term = TerminalBuilder.builder()
@@ -893,15 +875,29 @@ object NCCli extends App {
         parser.setEofOnUnclosedBracket(Bracket.CURLY, Bracket.ROUND, 
Bracket.SQUARE)
         parser.setRegexCommand("*")
 
-        //val cmdNames = CMDS.flatMap(_.names)
-
-        val completer = new AggregateCompleter(
-            new TreeCompleter(
-                CMDS.flatMap(cmd ⇒ cmd.names.map(name ⇒
-                    node(Seq(name) ++ 
cmd.params.flatMap(_.names).map(node(_)): _*)
-                )):_*
-            )
-        )
+        val completer = new Completer {
+            private val cmds = CMDS.map(c ⇒ c.name → c.synopsis)
+
+            override def complete(reader: LineReader, line: ParsedLine, 
candidates: util.List[Candidate]): Unit = {
+                val words = line.words().asScala
+
+                if (words.isEmpty || !cmds.map(_._1).contains(words.head))
+                    candidates.addAll(cmds.map(n ⇒ {
+                        val name = n._1
+                        val desc = n._2.substring(0, n._2.length - 1) // 
Remove last '.'.
+
+                        new Candidate(
+                            name,
+                            name,
+                            null,
+                            desc,
+                            null,
+                            null,
+                            true
+                        )
+                    }).asJava)
+            }
+        }
 
         val reader = LineReaderBuilder
             .builder
@@ -923,6 +919,11 @@ object NCCli extends App {
 
         new AutosuggestionWidgets(reader).enable()
 
+        logln(s"Hit '${c("TAB")}' or type '${c("help")}' to get help.")
+        logln(s"Type '${c("quit")}' to exit.")
+
+        var exit = false
+
         while (!exit) {
             val rawLine =
                 try
@@ -933,7 +934,7 @@ object NCCli extends App {
                     case _: EndOfFileException ⇒ null
                 }
 
-            if (rawLine == null || QUITS.contains(rawLine.trim))
+            if (rawLine == null || QUIT_CMD.name.contains(rawLine.trim))
                 exit = true
             else {
                 val line = rawLine.trim()
@@ -986,7 +987,7 @@ object NCCli extends App {
                     logln(s"${VER.date}")
             }
             else
-                error(s"Invalid parameters for command '${cmd.mainName}': 
${args.mkString(", ")}")
+                error(s"Invalid parameters for command '${cmd.name}': 
${args.mkString(", ")}")
         }
 
 
@@ -1201,11 +1202,11 @@ object NCCli extends App {
      * @param repl
      */
     private def processAnsi(args: Seq[String], repl: Boolean): Unit = {
-        args.find(arg ⇒ NO_ANSI_CMD.names.contains(arg)) match {
+        args.find(arg ⇒ NO_ANSI_CMD.name.contains(arg)) match {
             case Some(_) ⇒ NO_ANSI_CMD.body(NO_ANSI_CMD, Seq.empty, repl)
             case None ⇒ ()
         }
-        args.find(arg ⇒ ANSI_CMD.names.contains(arg)) match {
+        args.find(arg ⇒ ANSI_CMD.name.contains(arg)) match {
             case Some(_) ⇒ ANSI_CMD.body(ANSI_CMD, Seq.empty, repl)
             case None ⇒ ()
         }
@@ -1222,16 +1223,16 @@ object NCCli extends App {
         processAnsi(args, repl)
 
         // Remove 'no-ansi' and 'ansi' commands from the argument list, if any.
-        val xargs = args.filter(arg ⇒ !NO_ANSI_CMD.names.contains(arg) && 
!ANSI_CMD.names.contains(arg))
+        val xargs = args.filter(arg ⇒ !NO_ANSI_CMD.name.contains(arg) && 
!ANSI_CMD.name.contains(arg))
 
         if (xargs.nonEmpty) {
             val cmd = xargs.head
 
-            CMDS.find(_.extNames.contains(cmd)) match {
+            CMDS.find(_.name == cmd) match {
                 case Some(cmd) ⇒
                     exitStatus = 0
 
-                    if (!(repl && cmd.id == "repl")) // Don't call 'repl' from 
'repl'.
+                    if (!(repl && cmd.name == "repl")) // Don't call 'repl' 
from 'repl'.
                         try
                             cmd.body(cmd, processParameters(cmd, xargs.tail), 
repl)
                         catch {

Reply via email to