FELIX-2364, FELIX-2365: The width and height of the terminal should be available on the command session, The help command printer should line wrap the text according to the terminal width

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@952921 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/karaf/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java b/karaf/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
index 4c1ddc6..b124691 100644
--- a/karaf/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
+++ b/karaf/shell/console/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
@@ -114,7 +114,7 @@
             Object param = it.next();
             // Check for help
             if (HELP.name().equals(param) || Arrays.asList(HELP.aliases()).contains(param)) {
-                printUsage(action.getClass().getAnnotation(Command.class), options.keySet(), arguments.keySet(), System.out);
+                printUsage(session, action.getClass().getAnnotation(Command.class), options.keySet(), arguments.keySet(), System.out);
                 return false;
             }
             if (processOptions && param instanceof String && ((String) param).startsWith("-")) {
@@ -205,7 +205,7 @@
         return true;
     }
 
-    protected void printUsage(Command command, Set<Option> options, Set<Argument> arguments, PrintStream out)
+    protected void printUsage(CommandSession session, Command command, Set<Option> options, Set<Argument> arguments, PrintStream out)
     {
         options = new HashSet<Option>(options);
         options.add(HELP);
diff --git a/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/commands/BlueprintCommand.java b/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/commands/BlueprintCommand.java
index 1ae8192..89eade5 100644
--- a/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/commands/BlueprintCommand.java
+++ b/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/commands/BlueprintCommand.java
@@ -26,7 +26,10 @@
 import java.util.HashSet;
 import java.util.Arrays;
 import java.io.PrintStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
+import jline.Terminal;
 import org.apache.felix.gogo.commands.Action;
 import org.apache.felix.gogo.commands.Command;
 import org.apache.felix.gogo.commands.Option;
@@ -85,8 +88,9 @@
         }
 
         @Override
-        protected void printUsage(Command command, Set<Option> options, Set<Argument> args, PrintStream out)
+        protected void printUsage(CommandSession session, Command command, Set<Option> options, Set<Argument> args, PrintStream out)
         {
+            Terminal term = (Terminal) session.get(".jline.terminal");
             List<Argument> arguments = new ArrayList<Argument>(args);
             Collections.sort(arguments, new Comparator<Argument>() {
                 public int compare(Argument o1, Argument o2) {
@@ -98,7 +102,7 @@
             if (command != null && (command.description() != null || command.name() != null))
             {
                 out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("DESCRIPTION").a(Ansi.Attribute.RESET));
-                out.print("\t");
+                out.print("        ");
                 if (command.name() != null) {
                     out.println(Ansi.ansi().a(command.scope()).a(":").a(Ansi.Attribute.INTENSITY_BOLD).a(command.name()).a(Ansi.Attribute.RESET));
                     out.println();
@@ -133,7 +137,7 @@
             }
 
             out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("SYNTAX").a(Ansi.Attribute.RESET));
-            out.print("\t");
+            out.print("        ");
             out.println(syntax.toString());
             out.println();
             if (arguments.size() > 0)
@@ -141,7 +145,9 @@
                 out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("ARGUMENTS").a(Ansi.Attribute.RESET));
                 for (Argument argument : arguments)
                 {
-                    out.println(String.format("\t%-15s%s", argument.name(), argument.description()));
+                    out.print("        ");
+                    out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(argument.name()).a(Ansi.Attribute.RESET));
+                    printFormatted("                ", argument.description(), term != null ? term.getTerminalWidth() : 80, out);
                 }
                 out.println();
             }
@@ -155,9 +161,9 @@
                     {
                         opt += ", " + alias;
                     }
-                    out.print("\t");
-                    out.println(opt);
-                    out.println(String.format("\t%-15s%s", "", option.description()));
+                    out.print("        ");
+                    out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(opt).a(Ansi.Attribute.RESET));
+                    printFormatted("                ", option.description(), term != null ? term.getTerminalWidth() : 80, out);
                 }
                 out.println();
             }
@@ -165,7 +171,13 @@
 
         protected void printFormatted(String prefix, String str, int termWidth, PrintStream out) {
             int pfxLen = length(prefix);
-            
+            int maxwidth = termWidth - pfxLen;
+            Pattern wrap = Pattern.compile("(\\S\\S{" + maxwidth + ",}|.{1," + maxwidth + "})(\\s+|$)");
+            Matcher m = wrap.matcher(str);
+            while (m.find()) {
+                out.print(prefix);
+                out.println(m.group());
+            }
         }
 
         protected int length(String str) {
diff --git a/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/jline/ConsoleFactory.java b/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/jline/ConsoleFactory.java
index ff0a8df..8dde072 100644
--- a/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/jline/ConsoleFactory.java
+++ b/karaf/shell/console/src/main/java/org/apache/felix/karaf/shell/console/jline/ConsoleFactory.java
@@ -93,6 +93,9 @@
             CommandSession session = console.getSession();
             session.put("USER", "karaf");
             session.put("APPLICATION", System.getProperty("karaf.name", "root"));
+            session.put("LINES", Integer.toString(terminal.getTerminalHeight()));
+            session.put("COLUMNS", Integer.toString(terminal.getTerminalWidth()));
+            session.put(".jline.terminal", terminal);
             new Thread(console, "Karaf Shell Console Thread").start();
         }
     }
diff --git a/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/ShellFactoryImpl.java b/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/ShellFactoryImpl.java
index 996a2f4..98cadda 100644
--- a/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/ShellFactoryImpl.java
+++ b/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/ShellFactoryImpl.java
@@ -30,6 +30,7 @@
 import java.util.Properties;
 import java.util.concurrent.Callable;
 
+import jline.Terminal;
 import org.apache.felix.karaf.shell.console.Completer;
 import org.apache.felix.karaf.shell.console.completer.AggregateCompleter;
 import org.apache.felix.karaf.shell.console.jline.Console;
@@ -37,6 +38,8 @@
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.Environment;
 import org.apache.sshd.server.ExitCallback;
+import org.apache.sshd.server.Signal;
+import org.apache.sshd.server.SignalListener;
 import org.osgi.service.blueprint.container.ReifiedType;
 import org.osgi.service.command.CommandProcessor;
 import org.osgi.service.command.CommandSession;
@@ -93,22 +96,32 @@
 
         public void start(final Environment env) throws IOException {
             try {
+                final Terminal terminal = new SshTerminal(env);
                 Console console = new Console(commandProcessor,
                                               in,
                                               new PrintStream(new LfToCrLfFilterOutputStream(out), true),
                                               new PrintStream(new LfToCrLfFilterOutputStream(err), true),
-                                              new SshTerminal(env),
+                                              terminal,
                                               new AggregateCompleter(completers),
                                               new Runnable() {
                                                   public void run() {
                                                       destroy();
                                                   }
                                               });
-                CommandSession session = console.getSession();
+                final CommandSession session = console.getSession();
                 session.put("APPLICATION", System.getProperty("karaf.name", "root"));
                 for (Map.Entry<String,String> e : env.getEnv().entrySet()) {
                     session.put(e.getKey(), e.getValue());
                 }
+                session.put("LINES", Integer.toString(terminal.getTerminalHeight()));
+                session.put("COLUMNS", Integer.toString(terminal.getTerminalWidth()));
+                env.addSignalListener(new SignalListener() {
+                    public void signal(Signal signal) {
+                        session.put("LINES", Integer.toString(terminal.getTerminalHeight()));
+                        session.put("COLUMNS", Integer.toString(terminal.getTerminalWidth()));
+                    }
+                }, Signal.WINCH);
+                session.put(".jline.terminal", terminal);
                 new Thread(console).start();
             } catch (Exception e) {
                 throw (IOException) new IOException("Unable to start shell").initCause(e);
diff --git a/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/SshTerminal.java b/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/SshTerminal.java
index 9c4d42f..b4fe699 100644
--- a/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/SshTerminal.java
+++ b/karaf/shell/ssh/src/main/java/org/apache/felix/karaf/shell/ssh/SshTerminal.java
@@ -28,7 +28,7 @@
 import org.apache.sshd.server.Signal;
 import org.apache.sshd.server.SignalListener;
 
-public class SshTerminal extends Terminal implements SignalListener {
+public class SshTerminal extends Terminal {
 
     public static final short ARROW_START = 27;
     public static final short ARROW_PREFIX = 91;
@@ -52,7 +52,6 @@
 
     public SshTerminal(Environment environment) {
         this.environment = environment;
-        this.environment.addSignalListener(this);
         try {
             replayReader = new InputStreamReader(replayStream, encoding);
         } catch (Exception e) {
@@ -100,9 +99,6 @@
     public void disableEcho() {
     }
 
-    public void signal(Signal signal) {
-    }
-
     public int readVirtualKey(InputStream in) throws IOException {
         int c = readCharacter(in);