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 a40ece7  WIP.
a40ece7 is described below

commit a40ece7c52b3b95ecfce58deb25565d176eca94c
Author: Aaron Radzinski <[email protected]>
AuthorDate: Mon Oct 5 21:41:44 2020 -0700

    WIP.
---
 .../nlpcraft/common/ansi/NCAnsiProgressBar.scala   |  43 ++---
 .../nlpcraft/common/ansi/NCAnsiSpinner.scala       |  14 +-
 .../scala/org/apache/nlpcraft/common/package.scala |  51 +++---
 .../org/apache/nlpcraft/common/util/NCUtils.scala  |   9 +
 .../nlpcraft/model/tools/cmdline/NCCli.scala       | 190 +++++++++++++++------
 5 files changed, 214 insertions(+), 93 deletions(-)

diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiProgressBar.scala
 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiProgressBar.scala
index a1e0e05..1b08615 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiProgressBar.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiProgressBar.scala
@@ -19,6 +19,7 @@ package org.apache.nlpcraft.common.ansi
 
 import java.io.PrintWriter
 
+import org.apache.nlpcraft.common._
 import NCAnsi._
 import org.apache.nlpcraft.common.ansi.NCAnsiProgressBar._
 
@@ -42,10 +43,10 @@ class NCAnsiProgressBar(
     @volatile private var tick = 0
 
     //noinspection ZeroIndexToHead
-    private final val PB_LEFT = s"$ansiBlueFg${CHAR_SET(0)}$ansiReset"
-    private final val PB_RIGHT = s"$ansiBlueFg${CHAR_SET(3)}$ansiReset"
-    private final val PB_EMPTY =s"$ansiWhiteFg${CHAR_SET(2)}$ansiReset"
-    private final val PB_FULL = s"$ansiRedFg$ansiBold${CHAR_SET(1)}$ansiReset"
+    private final val PB_LEFT = s"$B${CHAR_SET(0)}$RST"
+    private final val PB_RIGHT = s"$B${CHAR_SET(3)}$RST"
+    private final val PB_EMPTY =s"$W${CHAR_SET(2)}$RST"
+    private final val PB_FULL = s"$R$BO${CHAR_SET(1)}$RST"
 
     /**
      *
@@ -62,7 +63,7 @@ class NCAnsiProgressBar(
     def start(): Unit = {
         tick = 0
 
-        if (useAnsi) {
+        if (useAnsi) out.synchronized {
             // Hide cursor to avoid blinking.
             out.print(ansiCursorHide)
 
@@ -80,20 +81,22 @@ class NCAnsiProgressBar(
     def ticked(): Unit = {
         tick += 1
 
-        if (useAnsi) {
-            clean()
-
-            val bar = if (tick == 1) 1 else Math.round((tick.toFloat / 
totalTicks.toFloat) * dispSize)
-
-            out.print(PB_LEFT)
-            for (i ← 0 until dispSize)
-                out.print(if (i < bar) PB_FULL else PB_EMPTY)
-            out.print(PB_RIGHT)
-            out.flush()
-        }
-        else if (tick == 1 || tick % (totalTicks / dispSize) == 0) {
-            out.print(NON_ANSI_CHAR)
-            out.flush()
+        out.synchronized {
+            if (useAnsi) {
+                clean()
+
+                val bar = if (tick == 1) 1 else Math.round((tick.toFloat / 
totalTicks.toFloat) * dispSize)
+
+                out.print(PB_LEFT)
+                for (i ← 0 until dispSize)
+                    out.print(if (i < bar) PB_FULL else PB_EMPTY)
+                out.print(PB_RIGHT)
+                out.flush()
+            }
+            else if (tick == 1 || tick % (totalTicks / dispSize) == 0) {
+                out.print(NON_ANSI_CHAR)
+                out.flush()
+            }
         }
     }
 
@@ -109,7 +112,7 @@ class NCAnsiProgressBar(
      * Stops progress bar.
      */
     def stop(): Unit = {
-        if (useAnsi && clearOnComplete) {
+        if (useAnsi && clearOnComplete) out.synchronized {
             clean()
 
             // Show cursor.
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiSpinner.scala 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiSpinner.scala
index fe8733c..7af9b8f 100644
--- 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiSpinner.scala
+++ 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/ansi/NCAnsiSpinner.scala
@@ -73,11 +73,13 @@ class NCAnsiSpinner(out: PrintWriter, useAnsi: Boolean = 
true) {
                 out.flush()
 
                 while (!t.isInterrupted) {
-                    if (frame > 0)
-                        clean()
+                    out.synchronized {
+                        if (frame > 0)
+                            clean()
 
-                    out.print(s"$prefix$ansiCyanFg${CHAR_SET(frame % 
CHAR_SET.size)}$ansiReset$suffix")
-                    out.flush()
+                        out.print(s"$prefix$ansiCyanFg${CHAR_SET(frame % 
CHAR_SET.size)}$ansiReset$suffix")
+                        out.flush()
+                    }
 
                     lastLength = U.stripAnsi(prefix).length + 1 + 
U.stripAnsi(suffix).length
 
@@ -89,7 +91,7 @@ class NCAnsiSpinner(out: PrintWriter, useAnsi: Boolean = 
true) {
 
             thread.start()
         }
-        else {
+        else out.synchronized {
             out.print("... ")
             out.flush()
         }
@@ -100,7 +102,7 @@ class NCAnsiSpinner(out: PrintWriter, useAnsi: Boolean = 
true) {
     def stop(): Unit = {
         U.stopThread(thread)
 
-        if (useAnsi && frame > 0) {
+        if (useAnsi && frame > 0) out.synchronized {
             clean()
 
             // Show cursor.
diff --git a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/package.scala 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/package.scala
index d266c4b..e82f220 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/package.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/package.scala
@@ -41,27 +41,40 @@ package object common {
     final val MDL_META_ALL_ALIASES_KEY = "__NLPCRAFT_MDL_META_ALL_ALIASES"
     final val TOK_META_ALIASES_KEY = "__NLPCRAFT_TOK_META_ALIASES"
 
-    // Real foreground color shortcuts...
-    def g(s: Any): String = s"$ansiGreenFg${s.toString}$ansiReset"
-    def r(s: Any): String = s"$ansiRedFg${s.toString}$ansiReset"
-    def c(s: Any): String = s"$ansiCyanFg${s.toString}$ansiReset"
-    def y(s: Any): String = s"$ansiYellowFg${s.toString}$ansiReset"
-    def w(s: Any): String = s"$ansiWhiteFg${s.toString}$ansiReset"
-    def b(s: Any): String = s"$ansiBlueFg${s.toString}$ansiReset"
-    def k(s: Any): String = s"$ansiBlackFg${s.toString}$ansiReset"
-
-    // Real background color shortcuts...
-    def gb(s: Any): String = s"$ansiGreenBg${s.toString}$ansiReset"
-    def rb(s: Any): String = s"$ansiRedBg${s.toString}$ansiReset"
-    def cb(s: Any): String = s"$ansiCyanBg${s.toString}$ansiReset"
-    def yb(s: Any): String = s"$ansiYellowBg${s.toString}$ansiReset"
-    def wb(s: Any): String = s"$ansiWhiteBg${s.toString}$ansiReset"
-    def bb(s: Any): String = s"$ansiBlueBg${s.toString}$ansiReset"
-    def kb(s: Any): String = s"$ansiBlackBg${s.toString}$ansiReset"
+    def G: String = ansiGreenFg
+    def R: String = ansiRedFg
+    def C: String = ansiCyanFg
+    def Y: String = ansiYellowFg
+    def W: String = ansiWhiteFg
+    def B: String = ansiBlueFg
+    def BO: String = ansiBold
+    def K: String = ansiBlackFg
+    def GB: String = ansiGreenBg
+    def RB: String = ansiRedBg
+    def CB: String = ansiCyanBg
+    def YB: String = ansiYellowBg
+    def WB: String = ansiWhiteBg
+    def BB: String = ansiBlueBg
+    def KB: String = ansiBlackBg
+    def RST: String = ansiReset
+    def g(s: Any): String = s"$G${s.toString}$RST"
+    def r(s: Any): String = s"$R${s.toString}$RST"
+    def c(s: Any): String = s"$C${s.toString}$RST"
+    def y(s: Any): String = s"$Y${s.toString}$RST"
+    def w(s: Any): String = s"$W${s.toString}$RST"
+    def b(s: Any): String = s"$B${s.toString}$RST"
+    def k(s: Any): String = s"$K${s.toString}$RST"
+    def gb(s: Any): String = s"$GB${s.toString}$RST"
+    def rb(s: Any): String = s"$RB${s.toString}$RST"
+    def cb(s: Any): String = s"$CB${s.toString}$RST"
+    def yb(s: Any): String = s"$YB${s.toString}$RST"
+    def wb(s: Any): String = s"$WB${s.toString}$RST"
+    def bb(s: Any): String = s"$BB${s.toString}$RST"
+    def kb(s: Any): String = s"$KB${s.toString}$RST"
 
     // Real color effect shortcuts...
-    def rv(s: Any): String = s"$ansiReversed${s.toString}$ansiReset"
-    def bo(s: Any): String = s"$ansiBold${s.toString}$ansiReset"
+    def rv(s: Any): String = s"$ansiReversed${s.toString}$RST"
+    def bo(s: Any): String = s"$ansiBold${s.toString}$RST"
 
     /**
      * Pimps integers with KB, MB, GB units of measure.
diff --git 
a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala 
b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
index df80d9a..731db6c 100644
--- a/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
+++ b/nlpcraft/src/main/scala/org/apache/nlpcraft/common/util/NCUtils.scala
@@ -946,6 +946,15 @@ object NCUtils extends LazyLogging {
         }
 
     /**
+     * Makes thread.
+     *
+     * @param name Name.
+     * @param body Thread body.
+     */
+    def mkThread(name: String, body: Runnable): Thread =
+        mkThread(name) { _ ⇒ body.run() }
+
+    /**
       * System-wide process of normalizing emails (trim & lower case).
       *
       * @param email Email to normalize.
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 f46a7bb..3aea6d1 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
@@ -38,16 +38,19 @@ import java.util
 import java.util.Date
 import java.io._
 import java.nio.charset.StandardCharsets
+import java.nio.file.Paths
 import java.util.regex.Pattern
 
 import org.apache.commons.io.input.{ReversedLinesFileReader, Tailer, 
TailerListenerAdapter}
 import org.apache.http.util.EntityUtils
+import org.jline.builtins.Commands
 import org.jline.reader.Completer
 import org.jline.reader.impl.DefaultParser
 import org.jline.terminal.{Terminal, TerminalBuilder}
 import org.jline.reader.{Candidate, EndOfFileException, LineReader, 
LineReaderBuilder, ParsedLine, UserInterruptException}
 import org.jline.reader.impl.DefaultParser.Bracket
 import org.jline.reader.impl.history.DefaultHistory
+import org.jline.utils.InfoCmp.Capability
 import org.jline.widget.AutosuggestionWidgets
 import resource.managed
 
@@ -69,32 +72,33 @@ object NCCli extends App {
 
     // TODO: this needs to be loaded dynamically from OpenAPI spec.
     private final val REST_PATHS = Seq(
-        "signin",
-        "signout",
-        "cancel",
-        "check",
-        "clear",
-        "clear",
-        "company/add",
-        "company/get",
-        "company/update",
-        "company/token/reset",
-        "company/delete",
-        "user/get",
-        "user/add",
-        "user/update",
-        "user/delete",
-        "user/admin",
-        "user/passwd/reset",
-        "user/all",
-        "feedback/add",
-        "feedback/all",
-        "feedback/delete",
-        "probe/all",
-        "model/sugsyn",
-        "ask",
-        "ask/sync",        
+        "clear/conversation" -> "Clears conversation STM",
+        "clear/dialog" -> "Clears dialog flow",
+        "model/sugsyn" -> "Runs model synonym suggestion tool",
+        "check" -> "Gets status and result of submitted requests",
+        "cancel" -> "Cancels a question",
+        "ask" -> "Asks a question",
+        "ask/sync" -> "Asks a question in synchronous mode",
+        "user/get" -> "Gets current user information",
+        "user/all" -> "Gets all users",
+        "user/update" -> "Updates regular user",
+        "user/delete" -> "Deletes user",
+        "user/admin" -> "Updates user admin permissions",
+        "user/passwd/reset" -> "Resets password for the user",
+        "user/add" -> "Adds new user",
+        "company/get" -> "Gets current user company information",
+        "company/add" -> "Adds new company",
+        "company/update" -> "Updates company data",
+        "company/delete" -> "Deletes company",
+        "company/token/reset" -> "Resets company probe auth token",
+        "feedback/add" -> "Adds feedback",
+        "feedback/delete" -> "Deletes feedback",
+        "feedback/all" -> "Gets all feedback",
+        "signin" -> "Signs in and obtains new access token",
+        "signout" -> "Signs out and releases access token",
+        "probe/all" -> "Gets all probes"
     )
+    .sortBy(_._1)
 
     // Number of server services that need to be started + 1 for log marker.
     // Used for progress bar functionality.
@@ -129,8 +133,8 @@ object NCCli extends App {
     case class SplitError(index: Int) extends Exception
     case class NoLocalServer() extends IllegalStateException(s"Cannot detect 
locally running REST server.")
     case class MissingParameter(cmd: Command, paramId: String) extends 
IllegalArgumentException(
-        s"Missing mandatory parameter: $ansiCyanFg${"'" + cmd.params.find(_.id 
== paramId).get.names.head + "'"}$ansiReset. " +
-        s"Type $ansiCyanFg${"'help --cmd="}${c(cmd.name) + "'"}$ansiReset to 
get help."
+        s"Missing mandatory parameter: $C${"'" + cmd.params.find(_.id == 
paramId).get.names.head + "'"}$RST, " +
+        s"type $C${"'help --cmd="}${c(cmd.name) + "'"}$RST to get help."
     )
     case class HttpError(httpCode: Int) extends IllegalStateException(s"REST 
error (HTTP ${c(httpCode)}).")
 
@@ -211,8 +215,9 @@ object NCCli extends App {
                     value = Some("path"),
                     desc =
                         s"REST path, e.g. ${y("'signin'")} or 
${y("'ask/sync'")}. " +
-                        s"Note that you don't need supply '/' at the 
beginning." +
-                        s"See more details at 
https://nlpcraft.apache.org/using-rest.html";
+                        s"Note that you don't need supply '/' at the 
beginning. " +
+                        s"See more details at 
https://nlpcraft.apache.org/using-rest.html " +
+                        s"In REPL mode, hit ${rv(" Tab ")} to see 
auto-suggestion for possible REST paths."
                 ),
                 Parameter(
                     id = "json",
@@ -367,6 +372,32 @@ object NCCli extends App {
             body = cmdInfoServer
         ),
         Command(
+            name = "cls",
+            synopsis = s"Clears terminal screen.",
+            body = cmdCls
+        ),
+        Command(
+            name = "nano",
+            synopsis = s"Runs built-in ${y("'nano'")} editor.",
+            body = cmdNano,
+            params = Seq(
+                Parameter(
+                    id = "file",
+                    names = Seq("--file", "-f"),
+                    value = Some("path"),
+                    optional = true,
+                    desc =
+                        s"File to open with built-in ${y("'nano'")} editor. 
Relative paths will based off user home directory."
+                )
+            ),
+            examples = Seq(
+                Example(
+                    usage = Seq(s"$PROMPT $SCRIPT_NAME nano -f=my_model.yml"),
+                    desc = s"Opens ${y("'my_model.yml'")} file in built-in 
nano editor."
+                )
+            )
+        ),
+        Command(
             name = "no-ansi",
             synopsis = s"Disables usage of ANSI escape codes for colors & 
terminal controls.",
             desc = Some(
@@ -502,6 +533,7 @@ object NCCli extends App {
     private final val ANSI_CMD = CMDS.find(_.name ==  "ansi").get
     private final val QUIT_CMD = CMDS.find(_.name ==  "quit").get
     private final val HELP_CMD = CMDS.find(_.name ==  "help").get
+    private final val REST_CMD = CMDS.find(_.name ==  "rest").get
     private final val STOP_SRV_CMD = CMDS.find(_.name ==  "stop-server").get
     private final val START_SRV_CMD = CMDS.find(_.name ==  "start-server").get
 
@@ -697,7 +729,7 @@ object NCCli extends App {
                     500.ms
                 )
 
-                U.mkThread("server-start-progress-bar") { _ ⇒ tailer }.start()
+                U.mkThread("server-start-progress-bar", tailer).start()
 
                 var beacon: NCCliServerBeacon = null
                 var online = false
@@ -775,9 +807,9 @@ object NCCli extends App {
                         for (_ ← 0 to lines)
                             tail ::= in.readLine()
 
-                        logln(bb(w(s"+----< ${ansiBlackFg}Last $lines server 
log lines $ansiWhiteFg>---")))
+                        logln(bb(w(s"+----< ${K}Last $lines server log lines 
$W>---")))
                         tail.foreach(line ⇒ logln(s"${bb(w("| "))}  $line"))
-                        logln(bb(w(s"+----< ${ansiBlackFg}Last $lines server 
log lines $ansiWhiteFg>---")))
+                        logln(bb(w(s"+----< ${K}Last $lines server log lines 
$W>---")))
                     }
                 catch {
                     case e: Exception ⇒ error(s"Failed to read log file: 
${e.getLocalizedMessage}")
@@ -1152,14 +1184,38 @@ object NCCli extends App {
      * @param args Arguments, if any, for this command.
      * @param repl Whether or not executing from REPL.
      */
+    private def cmdCls(cmd: Command, args: Seq[Argument], repl: Boolean): Unit 
=
+        term.puts(Capability.clear_screen)
+
+    /**
+     *
+     * @param cmd Command descriptor.
+     * @param args Arguments, if any, for this command.
+     * @param repl Whether or not executing from REPL.
+     */
+    private def cmdNano(cmd: Command, args: Seq[Argument], repl: Boolean): 
Unit =
+        Commands.nano(term,
+            System.out,
+            System.err,
+            Paths.get(""),
+            Array(args.map(_.value.get): _*)
+        )
+
+    /**
+     *
+     * @param cmd Command descriptor.
+     * @param args Arguments, if any, for this command.
+     * @param repl Whether or not executing from REPL.
+     */
     private def cmdRest(cmd: Command, args: Seq[Argument], repl: Boolean): 
Unit = {
         val path = args.find(_.parameter.id == "path").getOrElse(throw 
MissingParameter(cmd, "path")).value.get
         val rawJson = args.find(_.parameter.id == "json").getOrElse(throw 
MissingParameter(cmd, "json")).value.get
 
-        if (!REST_PATHS.contains(path))
-            throw new IllegalArgumentException(s"Unknown REST path: $path")
+        // TODO: verify JSON
+
+        if (!REST_PATHS.exists(_._1 == path))
+            throw new IllegalArgumentException(s"Unknown REST path 
$C'$path'$RST, type ${c("'help --cmd=rest'")} to get help.")
 
-        val json = stripQuotes(rawJson)
         val endpoint = getRestEndpointFromBeacon
 
         val handler = new ResponseHandler[HttpRestResponse] {
@@ -1175,12 +1231,24 @@ object NCCli extends App {
             }
         }
 
-        val resp = httpPost(endpoint, path, handler, json)
+        val resp = httpPost(endpoint, path, handler, stripQuotes(rawJson))
 
-        val code = if (resp.code == 200) g("200") else r(resp.code)
+        // Ack HTTP response code.
+        logln(s"HTTP ${if (resp.code == 200) g("200") else r(resp.code)}")
 
-        logln(s"HTTP $code")
-        logln(resp.data)
+        if (resp.code == 200) {
+            if (path == "signin") {
+                // TODO
+            }
+            else if (path == "signout") {
+                // TODO
+            }
+        }
+
+        if (resp.code == 200 || resp.code == 400)
+            logln(resp.data) // TODO
+        else
+            logln(resp.data)
     }
 
     /**
@@ -1196,8 +1264,6 @@ object NCCli extends App {
 
         parser.setEofOnUnclosedBracket(Bracket.CURLY, Bracket.ROUND, 
Bracket.SQUARE)
         parser.setEofOnUnclosedQuote(true)
-        parser.setRegexCommand("")
-        parser.setRegexVariable("")
 
         val completer = new Completer {
             private val cmds = CMDS.map(c ⇒ c.name → c.synopsis)
@@ -1210,8 +1276,8 @@ object NCCli extends App {
              * @param completed
              * @return
              */
-            private def mkCandidate(id: String, disp: String, desc: String, 
completed: Boolean): Candidate =
-                new Candidate(id, disp, null, desc, null, null, completed)
+            private def mkCandidate(id: String, disp: String, grp: String, 
desc: String, completed: Boolean): Candidate =
+                new Candidate(id, disp, grp, desc, null, null, completed)
 
             override def complete(reader: LineReader, line: ParsedLine, 
candidates: util.List[Candidate]): Unit = {
                 val words = line.words().asScala
@@ -1221,7 +1287,13 @@ object NCCli extends App {
                         val name = n._1
                         val desc = n._2.substring(0, n._2.length - 1) // 
Remove last '.'.
 
-                        mkCandidate(name, name, desc, completed = true)
+                        mkCandidate(
+                            id = name,
+                            disp = name,
+                            grp = null,
+                            desc = desc,
+                            completed = true
+                        )
                     }).asJava)
                 else {
                     val cmd = words.head
@@ -1232,7 +1304,13 @@ object NCCli extends App {
                                 val hasVal = param.value.isDefined
                                 val names = 
param.names.filter(_.startsWith("--")) // Skip shorthands from auto-completion.
 
-                                names.map(name ⇒ mkCandidate(if (hasVal) name 
+ "=" else name, name,null, !hasVal))
+                                names.map(name ⇒ mkCandidate(
+                                    id = if (hasVal) name + "=" else name,
+                                    disp = name,
+                                    grp = null,
+                                    desc = null,
+                                    completed = !hasVal)
+                                )
                             })
                             .asJava
 
@@ -1241,7 +1319,21 @@ object NCCli extends App {
 
                     // For 'help' - add additional auto-completion candidates.
                     if (cmd == HELP_CMD.name)
-                        candidates.addAll(CMDS.map(c ⇒ 
s"--cmd=${c.name}").map(s ⇒ mkCandidate(s, s, null, completed = true)).asJava)
+                        candidates.addAll(CMDS.map(c ⇒ 
s"--cmd=${c.name}").map(s ⇒
+                            mkCandidate(
+                                id = s,
+                                disp = s,
+                                grp = null,
+                                desc = null,
+                                completed = true
+                            ))
+                            .asJava
+                        )
+
+                    // For 'rest' - add additional auto-completion candidates.
+                    if (cmd == REST_CMD.name) {
+
+                    }
                 }
             }
         }
@@ -1292,7 +1384,7 @@ object NCCli extends App {
             catch {
                 case _: UserInterruptException ⇒ "" // Ignore.
                 case _: EndOfFileException ⇒ null
-                case e: Exception ⇒ e.printStackTrace(); "" // Guard against 
JLine hiccups.
+                case e: Exception ⇒ "" // Guard against JLine hiccups.
             }
 
             if (rawLine == null || QUIT_CMD.name == rawLine.trim)
@@ -1388,7 +1480,7 @@ object NCCli extends App {
      *
      */
     private def unknownCommand(cmd: String): Unit = {
-        val c2 = y(s"'$cmd'")
+        val c2 = c(s"'$cmd'")
         val h2 = c(s"'help'")
 
         error(s"Unknown command $c2, type $h2 to get help.")
@@ -1620,6 +1712,8 @@ object NCCli extends App {
         term = TerminalBuilder.builder()
             .name(NAME)
             .system(true)
+            .nativeSignals(true)
+            .signalHandler(Terminal.SignalHandler.SIG_IGN)
             .dumb(true)
             .jansi(true)
             .build()

Reply via email to