You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2015/03/25 09:31:14 UTC

[2/3] karaf git commit: [KARAF-3633] Help mechanism improvements

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/scr/examples/managed-service/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/scr/examples/managed-service/src/main/resources/OSGI-INF/bundle.info b/scr/examples/managed-service/src/main/resources/OSGI-INF/bundle.info
index 6d72846..eae4f9f 100644
--- a/scr/examples/managed-service/src/main/resources/OSGI-INF/bundle.info
+++ b/scr/examples/managed-service/src/main/resources/OSGI-INF/bundle.info
@@ -1,4 +1,22 @@
-\u001B[1mSYNOPSIS\u001B[0m
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
+h1. SYNOPSIS
     ${project.name}
 
     ${project.description}
@@ -6,5 +24,5 @@
     Maven URL:
         \u001B[33mmvn:${project.groupId}/${project.artifactId}/${project.version}\u001B[0m
 
-\u001B[1mDESCRIPTION\u001B[0m
+h1. DESCRIPTION
     An SCR example project for Managed Services.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/scr/examples/service/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/scr/examples/service/src/main/resources/OSGI-INF/bundle.info b/scr/examples/service/src/main/resources/OSGI-INF/bundle.info
index 2d76175..8b9e24c 100644
--- a/scr/examples/service/src/main/resources/OSGI-INF/bundle.info
+++ b/scr/examples/service/src/main/resources/OSGI-INF/bundle.info
@@ -1,4 +1,22 @@
-\u001B[1mSYNOPSIS\u001B[0m
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
+h1. SYNOPSIS
     ${project.name}
 
     ${project.description}
@@ -6,5 +24,5 @@
     Maven URL:
         \u001B[33mmvn:${project.groupId}/${project.artifactId}/${project.version}\u001B[0m
 
-\u001B[1mDESCRIPTION\u001B[0m
+h1. DESCRIPTION
     An SCR example project for basic Services and Components.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/scr/management/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/scr/management/src/main/resources/OSGI-INF/bundle.info b/scr/management/src/main/resources/OSGI-INF/bundle.info
index e8eba83..bc3c130 100644
--- a/scr/management/src/main/resources/OSGI-INF/bundle.info
+++ b/scr/management/src/main/resources/OSGI-INF/bundle.info
@@ -1,4 +1,22 @@
-\u001B[1mSYNOPSIS\u001B[0m
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
+h1. SYNOPSIS
     ${project.name}
 
     ${project.description}
@@ -6,7 +24,7 @@
     Maven URL:
         \u001B[33mmvn:${project.groupId}/${project.artifactId}/${project.version}\u001B[0m
 
-\u001B[1mDESCRIPTION\u001B[0m
+h1. DESCRIPTION
     This bundle provide MBean to manage Declarative Service Components in Karaf features via JMX.
 
     Especially, it provides the ScrServiceMBean supporting the following operations:
@@ -16,5 +34,5 @@
     \u001B[36misComponentActive(String)\u001B[0m Check to see if a given component is in an ACTIVE state.
     
 
-\u001B[1mSEE ALSO\u001B[0m
+h1. SEE ALSO
     \u001B[36mDeclarative Services\u001B[0m and \u001B[Remote Management via JMX\u001B[0m sections of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/service/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/service/core/src/main/resources/OSGI-INF/bundle.info b/service/core/src/main/resources/OSGI-INF/bundle.info
index 3fde000..27fc917 100644
--- a/service/core/src/main/resources/OSGI-INF/bundle.info
+++ b/service/core/src/main/resources/OSGI-INF/bundle.info
@@ -1,19 +1,42 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
-${project.name}
+	${project.name}
 
-${project.description}
+	${project.description}
 
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+	Maven URL:
+		[mvn:${project.groupId}/${project.artifactId}/${project.version}]
 
 h1. Description
 
-The services mbean management bundle exposes a Services MBean that can be used with any JMX client (for instance JConsole).
+	The services mbean management bundle exposes a Services MBean that can be used with any JMX client (for instance JConsole).
 
-The Services MBean allows quite the same action that can be performed using services:* commands:
-  * list()
+	The Services MBean allows quite the same action that can be performed using services:* commands:
+  		* list()
+
+h1. Commands
+
+	The bundle contains the following commands:
+\${command-list|service|indent=8,list,cyan}
 
 h1. See also
 
-  * Monitoring and Administration using JMX - section of the Karaf User Guide
+  	* Monitoring and Administration using JMX - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/service/guard/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/service/guard/src/main/resources/OSGI-INF/bundle.info b/service/guard/src/main/resources/OSGI-INF/bundle.info
index be2ec64..6f69b56 100644
--- a/service/guard/src/main/resources/OSGI-INF/bundle.info
+++ b/service/guard/src/main/resources/OSGI-INF/bundle.info
@@ -1,3 +1,21 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
 ${project.name}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/commands/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/resources/OSGI-INF/bundle.info b/shell/commands/src/main/resources/OSGI-INF/bundle.info
index 873370f..8b16f30 100644
--- a/shell/commands/src/main/resources/OSGI-INF/bundle.info
+++ b/shell/commands/src/main/resources/OSGI-INF/bundle.info
@@ -1,39 +1,39 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
-${project.name}
+	${project.name}
 
-${project.description}
+	${project.description}
 
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+	Maven URL:
+		[mvn:${project.groupId}/${project.artifactId}/${project.version}]
 
 h1. Description
 
-This bundle provides various shell commands.
-
-The following commands are available:
-* shell:cat - Displays the content of a file or url.
-* shell:clear - Clears the console buffer.
-* shell:date - Display the current time in the given FORMAT
-* shell:each - Execute a closure on a list of arguments.
-* shell:echo - Echoes or prints arguments to STDOUT.
-* shell:exec - Executes system processes.
-* shell:grep - Prints lines matching the given pattern.
-* shell:head - Displays the first lines of a file.
-* shell:history - Prints command history.
-* shell:if - If/Then/Else block.
-* shell:info - Prints system information.
-* shell:java - Executes a Java standard application.
-* shell:logout - Disconnects shell from current session.
-* shell:more - File pager.
-* shell:new - Creates a new java object.
-* shell:printf - Formats and prints arguments.
-* shell:sleep - Sleeps for a bit then wakes up.
-* shell:sort - Writes sorted concatenation of all files to standard output.
-* shell:tac - Captures the STDIN and returns it as a string. Optionally writes the content to a file.
-* shell:tail - Displays the last lines of a file.
-* shell:wc - Print newline, word, and byte counts for each file.
+	This bundle provides various shell commands.
+
+h1. Commands
+
+	The following commands are available:
+\${command-list|dev|indent=8,list,cyan}
 
 h1. See also
 
-Commands - and Using the console - sections of the Karaf User Guide.
\ No newline at end of file
+	Commands - and Using the console - sections of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/console/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/shell/console/src/main/resources/OSGI-INF/bundle.info b/shell/console/src/main/resources/OSGI-INF/bundle.info
index 23fcee4..93a9994 100644
--- a/shell/console/src/main/resources/OSGI-INF/bundle.info
+++ b/shell/console/src/main/resources/OSGI-INF/bundle.info
@@ -1,3 +1,21 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
 ${project.name}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/pom.xml
----------------------------------------------------------------------
diff --git a/shell/core/pom.xml b/shell/core/pom.xml
index 75a88c0..89f95f8 100644
--- a/shell/core/pom.xml
+++ b/shell/core/pom.xml
@@ -140,6 +140,7 @@
                         <Private-Package>
                             org.apache.karaf.service.guard.tools,
                             org.apache.karaf.shell.impl.*,
+                            org.apache.karaf.util,
                             org.apache.karaf.util.jaas,
                             org.apache.karaf.util.tracker,
                             org.apache.felix.utils.properties,

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/SubShellCommand.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/SubShellCommand.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/SubShellCommand.java
index d2826f3..1dc46a9 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/SubShellCommand.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/SubShellCommand.java
@@ -18,9 +18,12 @@
  */
 package org.apache.karaf.shell.impl.console.commands;
 
+import java.io.PrintStream;
+import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.impl.console.commands.help.HelpCommand;
 
 public class SubShellCommand extends TopLevelCommand {
 
@@ -55,4 +58,12 @@ public class SubShellCommand extends TopLevelCommand {
         session.put(Session.SCOPE, name + ":" + session.get(Session.SCOPE));
     }
 
+    @Override
+    protected void printHelp(Session session, PrintStream out) {
+        try {
+            new HelpCommand(session.getFactory()).execute(session, Arrays.<Object>asList("shell|" + name));
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to print subshell help", e);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/TopLevelCommand.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/TopLevelCommand.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/TopLevelCommand.java
index 1f52fbe..2a5620a 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/TopLevelCommand.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/TopLevelCommand.java
@@ -53,7 +53,7 @@ public abstract class TopLevelCommand implements Command {
     @Override
     public Object execute(Session session, List<Object> arguments) throws Exception {
         if (arguments.contains("--help")) {
-            printHelp(System.out);
+            printHelp(session, System.out);
             return null;
         }
         if (!arguments.isEmpty()) {
@@ -67,7 +67,7 @@ public abstract class TopLevelCommand implements Command {
         return null;
     }
 
-    protected void printHelp(PrintStream out) {
+    protected void printHelp(Session session, PrintStream out) {
         out.println(INTENSITY_BOLD + "DESCRIPTION" + INTENSITY_NORMAL);
         out.print("        ");
         out.println(INTENSITY_BOLD + getName() + INTENSITY_NORMAL);

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/BundleHelpProvider.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/BundleHelpProvider.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/BundleHelpProvider.java
new file mode 100644
index 0000000..79a8f12
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/BundleHelpProvider.java
@@ -0,0 +1,80 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.impl.console.commands.help;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.URL;
+
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.api.console.Terminal;
+import org.apache.karaf.shell.impl.console.commands.help.wikidoc.AnsiPrintingWikiVisitor;
+import org.apache.karaf.shell.impl.console.commands.help.wikidoc.WikiParser;
+import org.apache.karaf.shell.impl.console.commands.help.wikidoc.WikiVisitor;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+
+public class BundleHelpProvider implements HelpProvider {
+
+    @Override
+    public String getHelp(Session session, String path) {
+        if (path.indexOf('|') > 0) {
+            if (path.startsWith("bundle|")) {
+                path = path.substring("bundle|".length());
+            } else {
+                return null;
+            }
+        }
+
+        if (path.matches("[0-9]*")) {
+            long id = Long.parseLong(path);
+            BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
+            Bundle bundle = bundleContext.getBundle(id);
+            if (bundle != null) {
+                String title = ShellUtil.getBundleName(bundle);
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                PrintStream ps = new PrintStream(baos);
+                ps.println("\n" + title);
+                ps.println(ShellUtil.getUnderlineString(title));
+                URL bundleInfo = bundle.getEntry("OSGI-INF/bundle.info");
+                if (bundleInfo != null) {
+                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(bundleInfo.openStream()))) {
+                        int maxSize = 80;
+                        Terminal terminal = session.getTerminal();
+                        if (terminal != null) {
+                            maxSize = terminal.getWidth();
+                        }
+                        WikiVisitor visitor = new AnsiPrintingWikiVisitor(ps, maxSize);
+                        WikiParser parser = new WikiParser(visitor);
+                        parser.parse(reader);
+                    } catch (Exception e) {
+                        // ignore
+                    }
+                }
+                ps.close();
+                return baos.toString();
+            }
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandListHelpProvider.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandListHelpProvider.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandListHelpProvider.java
index 2c2a1b3..6612402 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandListHelpProvider.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandListHelpProvider.java
@@ -19,8 +19,12 @@ package org.apache.karaf.shell.impl.console.commands.help;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
@@ -28,33 +32,55 @@ import org.apache.karaf.shell.api.console.Command;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.console.Terminal;
 import org.apache.karaf.shell.support.NameScoping;
-import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 import org.apache.karaf.shell.support.table.Col;
 import org.apache.karaf.shell.support.table.ShellTable;
 
 public class CommandListHelpProvider implements HelpProvider {
 
     public String getHelp(Session session, String path) {
+        String mode = "raw";
         if (path.indexOf('|') > 0) {
             if (path.startsWith("command-list|")) {
                 path = path.substring("command-list|".length());
+                if (path.indexOf('|') > 0) {
+                    mode = path.substring(path.indexOf('|') + 1);
+                    path = path.substring(0, path.indexOf('|'));
+                }
             } else {
                 return null;
             }
+        } else {
+            return null;
+        }
+
+        // Retrieve matching commands
+        Set<Command> commands = getCommands(session, path);
+        SortedMap<String,String> descriptions = new TreeMap<>();
+        for (Command command : commands) {
+            String subshell = (String) session.get(Session.SUBSHELL);
+            String name = command.getScope() + ":" + command.getName();
+            String description = command.getDescription();
+            if (name.startsWith("*:")) {
+                name = name.substring(2);
+            }
+            if (subshell != null && !subshell.trim().isEmpty() && name.startsWith(subshell + ":")) {
+                name = name.substring(subshell.length() + 1);
+            }
+            descriptions.put(name, description);
         }
+
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        SortedMap<String, String> commands = getCommandDescriptions(session, path);
-        if (commands.isEmpty()) {
+        if (descriptions.isEmpty()) {
             return null;
-        } else if (commands.size() == 1 && commands.containsKey(path)) {
+        } else if (descriptions.size() == 1 && descriptions.containsKey(path)) {
             return null;
         } else {
-            printMethodList(session, new PrintStream(baos), commands);
+            printMethodList(session, new PrintStream(baos), descriptions, Arrays.asList(mode.split(",")));
             return baos.toString();
         }
     }
 
-    private SortedMap<String, String> getCommandDescriptions(Session session, String path) {
+    private Set<Command> getCommands(Session session, String path) {
         // TODO: this is not really clean
 
         List<Command> commands = session.getRegistry().getCommands();
@@ -62,12 +88,12 @@ public class CommandListHelpProvider implements HelpProvider {
         String subshell = (String) session.get(Session.SUBSHELL);
         String completionMode = (String) session.get(Session.COMPLETION_MODE);
 
-        SortedMap<String,String> descriptions = new TreeMap<String,String>();
+        Set<Command> matchingCommands = new HashSet<>();
         for (Command command : commands) {
 
             String name = command.getScope() + ":" + command.getName();
 
-            if (command != null && !name.startsWith(path)) {
+            if (!name.startsWith(path)) {
                 continue;
             }
 
@@ -88,28 +114,51 @@ public class CommandListHelpProvider implements HelpProvider {
                 }
             }
 
-            String description = command.getDescription();
-            if (name.startsWith("*:")) {
-                name = name.substring(2);
-            }
-            if (subshell != null && !subshell.trim().isEmpty() && name.startsWith(subshell + ":")) {
-                name = name.substring(subshell.length() + 1);
-            }
-            descriptions.put(name, description);
+            matchingCommands.add(command);
         }
-        return descriptions;
+        return matchingCommands;
     }
 
-    protected void printMethodList(Session session, PrintStream out, SortedMap<String, String> commands) {
+    protected void printMethodList(Session session, PrintStream out, SortedMap<String, String> commands, Collection<String> modes) {
+        boolean list = false;
+        boolean cyan = false;
+        int indent = 0;
+        for (String mode : modes) {
+            if (mode.equals("list")) {
+                list = true;
+            } else if (mode.equals("cyan")) {
+                cyan = true;
+            } else if (mode.equals("indent")) {
+                indent = 4;
+            } else if (mode.startsWith("indent=")) {
+                indent = Integer.parseInt(mode.substring("indent=".length()));
+            }
+        }
+
         Terminal term = session.getTerminal();
         int termWidth = term != null ? term.getWidth() : 80;
-        out.println(SimpleAnsi.INTENSITY_BOLD + "COMMANDS" + SimpleAnsi.INTENSITY_NORMAL);
-        ShellTable table = new ShellTable().noHeaders().separator(" ").size(termWidth);
-        table.column(new Col("Command").maxSize(64));
-        table.column(new Col("Description"));
+        ShellTable table = new ShellTable().noHeaders().separator(" ").size(termWidth - 1);
+        Col col = new Col("Command").maxSize(64);
+        if (indent > 0 || list) {
+            table.column(new Col(""));
+        }
+        if (cyan) {
+            col.cyan();
+        } else {
+            col.bold();
+        }
+        table.column(col);
+        table.column(new Col("Description").wrap());
         for (Map.Entry<String,String> entry : commands.entrySet()) {
             String key = NameScoping.getCommandNameWithoutGlobalPrefix(session, entry.getKey());
-            table.addRow().addContent(SimpleAnsi.INTENSITY_BOLD + key + SimpleAnsi.INTENSITY_NORMAL, entry.getValue());
+            String prefix = "";
+            for (int i = 0; i < indent; i++) {
+                prefix += " ";
+            }
+            if (list) {
+                prefix += " *";
+            }
+            table.addRow().addContent(prefix, key, entry.getValue());
         }
         table.print(out, true);
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandsHelpProvider.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandsHelpProvider.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandsHelpProvider.java
new file mode 100644
index 0000000..44ada77
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/CommandsHelpProvider.java
@@ -0,0 +1,87 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.impl.console.commands.help;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.shell.api.console.Command;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
+
+public class CommandsHelpProvider implements HelpProvider {
+
+    public String getHelp(Session session, String path) {
+        if (path.indexOf('|') > 0) {
+            if (path.startsWith("commands|")) {
+                path = path.substring("commands|".length());
+            } else {
+                return null;
+            }
+        }
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream ps = new PrintStream(baos);
+        ps.println(SimpleAnsi.INTENSITY_BOLD + "COMMANDS" + SimpleAnsi.INTENSITY_NORMAL);
+        ps.println("${command-list|" + path + "}");
+        return baos.toString();
+    }
+
+    private Set<Command> getCommands(Session session, String path) {
+        // TODO: this is not really clean
+
+        List<Command> commands = session.getRegistry().getCommands();
+
+        String subshell = (String) session.get(Session.SUBSHELL);
+        String completionMode = (String) session.get(Session.COMPLETION_MODE);
+
+        Set<Command> matchingCommands = new HashSet<>();
+        for (Command command : commands) {
+
+            String name = command.getScope() + ":" + command.getName();
+
+            if (command != null && !name.startsWith(path)) {
+                continue;
+            }
+
+            if (completionMode != null && completionMode.equalsIgnoreCase(Session.COMPLETION_MODE_SUBSHELL)) {
+                // filter the help only for "global" commands
+                if (subshell == null || subshell.trim().isEmpty()) {
+                    if (!name.startsWith(Session.SCOPE_GLOBAL)) {
+                        continue;
+                    }
+                }
+            }
+
+            if (completionMode != null && (completionMode.equalsIgnoreCase(Session.COMPLETION_MODE_SUBSHELL)
+                    || completionMode.equalsIgnoreCase(Session.COMPLETION_MODE_FIRST))) {
+                // filter the help only for commands local to the subshell
+                if (!name.startsWith(subshell)) {
+                    continue;
+                }
+            }
+
+            matchingCommands.add(command);
+        }
+        return matchingCommands;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/HelpCommand.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/HelpCommand.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/HelpCommand.java
index 945a429..3402f8a 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/HelpCommand.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/HelpCommand.java
@@ -18,7 +18,9 @@
  */
 package org.apache.karaf.shell.impl.console.commands.help;
 
+import java.io.BufferedReader;
 import java.io.PrintStream;
+import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -48,8 +50,11 @@ public class HelpCommand implements Command {
         Registry registry = factory.getRegistry();
         registry.register(this);
         registry.register(new SimpleHelpProvider());
-        registry.register(new CommandListHelpProvider());
+        registry.register(new ShellHelpProvider());
         registry.register(new SingleCommandHelpProvider());
+        registry.register(new CommandsHelpProvider());
+        registry.register(new CommandListHelpProvider());
+        registry.register(new BundleHelpProvider());
     }
 
     @Override
@@ -83,7 +88,12 @@ public class HelpCommand implements Command {
         String path = arguments.isEmpty() ? null : arguments.get(0) == null ? null : arguments.get(0).toString();
         String help = getHelp(session, path);
         if (help != null) {
-            System.out.println(help);
+            try (BufferedReader reader = new BufferedReader(new StringReader(help))) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    System.out.println(line);
+                }
+            }
         }
         return null;
     }
@@ -184,7 +194,7 @@ public class HelpCommand implements Command {
 
     private String removeNewLine(String help) {
         if (help != null && help.endsWith("\n")) {
-            help = help.substring(0, help.length()  -1);
+            help = help.substring(0, help.length() - 1);
         }
         return help;
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/ShellHelpProvider.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/ShellHelpProvider.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/ShellHelpProvider.java
new file mode 100644
index 0000000..8285c3e
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/ShellHelpProvider.java
@@ -0,0 +1,144 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.impl.console.commands.help;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.console.Command;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.api.console.Terminal;
+import org.apache.karaf.shell.impl.action.command.ActionCommand;
+import org.apache.karaf.shell.impl.console.commands.help.wikidoc.AnsiPrintingWikiVisitor;
+import org.apache.karaf.shell.impl.console.commands.help.wikidoc.WikiParser;
+import org.apache.karaf.shell.impl.console.commands.help.wikidoc.WikiVisitor;
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+public class ShellHelpProvider implements HelpProvider {
+
+    public String getHelp(Session session, String path) {
+        if (path.indexOf('|') > 0) {
+            if (path.startsWith("shell|")) {
+                path = path.substring("shell|".length());
+            } else {
+                return null;
+            }
+        }
+
+        // Retrieve matching commands
+        Set<Command> commands = getCommands(session, path);
+
+        // Compute the scopes and matching bundles
+        Set<Bundle> bundles = new HashSet<>();
+        Set<String> scopes = new HashSet<>();
+        for (Command command : commands) {
+            if (command instanceof ActionCommand) {
+                Class<? extends Action> action = ((ActionCommand) command).getActionClass();
+                bundles.add(FrameworkUtil.getBundle(action));
+            }
+            scopes.add(command.getScope());
+        }
+        // When there is a single scope / bundle and a matching information file
+        // use that one instead
+        if (scopes.size() == 1 && bundles.size() == 1 && path.equals(scopes.iterator().next())) {
+            Bundle bundle = bundles.iterator().next();
+            URL resource = bundle.getResource("OSGI-INF/shell-" + path + ".info");
+            if (resource != null) {
+                try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.openStream()))) {
+                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    PrintStream ps = new PrintStream(baos);
+                    int maxSize = 80;
+                    Terminal terminal = session.getTerminal();
+                    if (terminal != null) {
+                        maxSize = terminal.getWidth();
+                    }
+                    WikiVisitor visitor = new AnsiPrintingWikiVisitor(ps, maxSize);
+                    WikiParser parser = new WikiParser(visitor);
+                    parser.parse(reader);
+                    return baos.toString();
+                } catch (IOException e) {
+                     // ignore
+                }
+            }
+
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            printShellHelp(session, new PrintStream(baos), path);
+            return baos.toString();
+        }
+
+        return null;
+    }
+
+    private Set<Command> getCommands(Session session, String path) {
+        // TODO: this is not really clean
+
+        List<Command> commands = session.getRegistry().getCommands();
+
+        String subshell = (String) session.get(Session.SUBSHELL);
+        String completionMode = (String) session.get(Session.COMPLETION_MODE);
+
+        Set<Command> matchingCommands = new HashSet<>();
+        for (Command command : commands) {
+
+            String name = command.getScope() + ":" + command.getName();
+
+            if (command != null && !name.startsWith(path)) {
+                continue;
+            }
+
+            if (completionMode != null && completionMode.equalsIgnoreCase(Session.COMPLETION_MODE_SUBSHELL)) {
+                // filter the help only for "global" commands
+                if (subshell == null || subshell.trim().isEmpty()) {
+                    if (!name.startsWith(Session.SCOPE_GLOBAL)) {
+                        continue;
+                    }
+                }
+            }
+
+            if (completionMode != null && (completionMode.equalsIgnoreCase(Session.COMPLETION_MODE_SUBSHELL)
+                                                || completionMode.equalsIgnoreCase(Session.COMPLETION_MODE_FIRST))) {
+                // filter the help only for commands local to the subshell
+                if (!name.startsWith(subshell)) {
+                    continue;
+                }
+            }
+
+            matchingCommands.add(command);
+        }
+        return matchingCommands;
+    }
+
+    protected void printShellHelp(Session session, PrintStream out, String path) {
+        out.println(SimpleAnsi.INTENSITY_BOLD + "SUBSHELL" + SimpleAnsi.INTENSITY_NORMAL);
+        out.println("\t" + SimpleAnsi.INTENSITY_BOLD + path + SimpleAnsi.INTENSITY_NORMAL);
+        out.println();
+        out.println(SimpleAnsi.INTENSITY_BOLD + "COMMANDS" + SimpleAnsi.INTENSITY_NORMAL);
+        out.println("${command-list|" + path + "|embedded}");
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java
new file mode 100644
index 0000000..bd5acd9
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.impl.console.commands.help.wikidoc;
+
+import java.io.PrintStream;
+
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.fusesource.jansi.Ansi;
+import org.fusesource.jansi.Ansi.Attribute;
+import org.fusesource.jansi.Ansi.Color;
+
+/**
+ * Translates the Wiki tags to Ansi escape sequences to display them on the console
+ */
+public class AnsiPrintingWikiVisitor implements WikiVisitor {
+
+	private PrintStream out;
+	private int maxSize;
+	private StringBuilder sb = new StringBuilder();
+	private String indent;
+	
+	public AnsiPrintingWikiVisitor(PrintStream out, int maxSize) {
+		this.out = out;
+		this.maxSize = maxSize;
+	}
+
+	@Override
+	public void startPara(int size) {
+		indent = "";
+		while (size-- > 0) {
+			indent += " ";
+		}
+	}
+
+	@Override
+	public void endPara() {
+		if (sb.length() > 0) {
+			ShellTable table = new ShellTable().noHeaders().separator("").size(maxSize - 1);
+			table.column("").maxSize(indent.length());
+			table.column("").wrap();
+			table.addRow().addContent(indent, sb.toString());
+			table.print(out);
+			sb.setLength(0);
+		} else {
+			out.println();
+		}
+	}
+
+	@Override
+	public void heading(int level, String header) {
+		sb.append(Ansi.ansi().a(Attribute.INTENSITY_BOLD).a(header)
+				.a(Attribute.INTENSITY_BOLD_OFF).toString());
+	}
+	
+	@Override
+	public void link(String target, String title) {
+		sb.append(Ansi.ansi().fg(Color.YELLOW)
+				.a(target).fg(Color.DEFAULT));
+	}
+
+	@Override
+	public void enumeration(String text) {
+		sb.append(Ansi.ansi().a(" * ").fg(Color.CYAN).a(text).fg(Color.DEFAULT).a(" "));
+	}
+
+	@Override
+	public void text(String text) {
+		sb.append(text);
+	}
+
+	@Override
+	public void bold(boolean on) {
+		if (on) {
+			sb.append(Ansi.ansi().bold().toString());
+		} else {
+			sb.append(Ansi.ansi().boldOff().toString());
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParser.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParser.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParser.java
new file mode 100644
index 0000000..783331e
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParser.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.impl.console.commands.help.wikidoc;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.karaf.util.StringEscapeUtils;
+
+/**
+ * Parses wiki syntax from a reader and calls a Wikivisitor with the 
+ * tokens it finds
+ */
+public class WikiParser {
+
+	WikiVisitor visitor;
+	
+	public WikiParser(WikiVisitor visitor) {
+		this.visitor = visitor;
+	}
+
+	public void parse(Reader reader) throws IOException {
+		BufferedReader br = new BufferedReader(reader);
+		String line;
+		while ((line = br.readLine()) != null) {
+			if (!line.startsWith("#")) {
+				parse(line);
+			}
+		}
+	}
+
+	public void parse(String line) {
+        String unescaped = StringEscapeUtils.unescapeJava(line);
+		Tokenizer tokenizer = new Tokenizer(unescaped);
+		String token;
+		boolean bold = false;
+		boolean first = true;
+		while ((token = tokenizer.nextToken("\u001B[h*")) != null) {
+			if (first) {
+				first = false;
+				int tabs = 0;
+				for (int i = 0; i < token.length() && token.charAt(i) == '\t'; i++) {
+					tabs++;
+				}
+				token = token.substring(tabs);
+				for (int i = 0; i < tabs; i++) {
+					token = "    " + token;
+				}
+				int i = 0;
+				while (i < token.length() && token.charAt(i) == ' ') {
+					i++;
+				}
+				visitor.startPara(i);
+				token = token.substring(i);
+			}
+            if ("\u001B".equals(token)) {
+                parseEsc(tokenizer, token);
+            } else if ("[".equals(token)) {
+				parseLink(tokenizer);
+			} else if ("h".equals(token)) {
+				parseHeading(tokenizer);
+			} else if ("*".equals(token)) {
+				parseEnumeration(tokenizer);
+			} else if ("**".equals(token)) {
+				bold = !bold;
+				visitor.bold(bold);
+			} else {
+				visitor.text(token);
+			}
+		}
+		if (first) {
+			visitor.startPara(0);
+		}
+		visitor.endPara();
+	}
+
+    private void parseEsc(Tokenizer tokenizer, String token) {
+        visitor.text(token + tokenizer.nextToken("\u001B[h*") + tokenizer.nextToken("\u001B[]"));
+    }
+	
+	private void parseEnumeration(Tokenizer tokenizer) {
+		String text = tokenizer.nextToken("-\n");
+		visitor.enumeration(text.trim());
+	}
+
+	private void parseHeading(Tokenizer tokenizer) {
+		String level = tokenizer.nextToken("123456789");
+		if (!level.matches("[123456789]")) {
+			visitor.text("h" + level);
+			return;
+		}
+		String dot = tokenizer.nextToken(".\n");
+		if (!".".equals(dot)) {
+			visitor.text("h" + level + dot);
+			return;
+		}
+		String heading = tokenizer.nextToken("\n");
+		if (heading == null) {
+			heading = "";
+		}
+		visitor.heading(Integer.parseInt(level), heading.trim());
+	}
+
+	private void parseLink(Tokenizer tokenizer) {
+		String token = tokenizer.nextToken("]");
+		visitor.link(token, "");
+		tokenizer.nextToken("]");
+	}
+
+	public static class Tokenizer {
+
+		final String str;
+		int pos;
+
+		public Tokenizer(String str) {
+			this.str = str;
+		}
+
+		public String nextToken(String delim) {
+			StringBuilder sb = new StringBuilder();
+			boolean escape = false;
+			boolean del = false;
+			while (pos < str.length()) {
+				char c = str.charAt(pos++);
+				if (escape) {
+					escape = false;
+					sb.append(c);
+				} else if (c == '\\') {
+					if (del) {
+						pos--;
+						break;
+					} else {
+						escape = true;
+					}
+				} else if (delim.indexOf(c) >= 0) {
+					if (sb.length() == 0 || del) {
+						sb.append(c);
+						del = true;
+					} else {
+						pos--;
+						break;
+					}
+				} else {
+					if (del) {
+						pos--;
+						break;
+					}
+					sb.append(c);
+				}
+			}
+			return sb.length() > 0 ? sb.toString() : null;
+		}
+
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiVisitor.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiVisitor.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiVisitor.java
new file mode 100644
index 0000000..b6c1caa
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiVisitor.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.impl.console.commands.help.wikidoc;
+
+/**
+ * Will be used by WikiParser to call the respective handler when it recognizes the tag 
+ */
+public interface WikiVisitor {
+
+	void link(String target, String title);
+	void heading(int level, String title);
+	void enumeration(String text);
+	void text(String text);
+	void bold(boolean on);
+	void startPara(int size);
+	void endPara();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java b/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
index d7d75d7..92ce8b6 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
@@ -23,6 +23,7 @@ import org.fusesource.jansi.Ansi.Color;
 
 public class SimpleAnsi {
     public static String COLOR_RED = Ansi.ansi().fg(Color.RED).toString();
+    public static String COLOR_CYAN = Ansi.ansi().fg(Color.CYAN).toString();
     public static String COLOR_DEFAULT = Ansi.ansi().fg(Color.DEFAULT).toString();
     
     public static String INTENSITY_BOLD = Ansi.ansi().bold().toString();

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/java/org/apache/karaf/shell/support/table/Col.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/table/Col.java b/shell/core/src/main/java/org/apache/karaf/shell/support/table/Col.java
index 95dba51..29bbbb3 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/table/Col.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/table/Col.java
@@ -43,6 +43,8 @@ public class Col {
 
     boolean wrap;
     boolean bold;
+    boolean cyan;
+
 
     /**
      * Alignment
@@ -96,6 +98,15 @@ public class Col {
         return this;
     }
 
+    public Col cyan() {
+        return cyan(true);
+    }
+
+    public Col cyan(boolean cyan) {
+        this.cyan = cyan;
+        return this;
+    }
+
     public int getSize() {
         return size;
     }
@@ -146,6 +157,9 @@ public class Col {
             if (bold) {
                 line = SimpleAnsi.INTENSITY_BOLD + line + SimpleAnsi.INTENSITY_NORMAL;
             }
+            if (cyan) {
+                line = SimpleAnsi.COLOR_CYAN + line + SimpleAnsi.COLOR_DEFAULT;
+            }
             sb.append(line);
         }
         return sb.toString();

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/shell/core/src/main/resources/OSGI-INF/bundle.info b/shell/core/src/main/resources/OSGI-INF/bundle.info
index 4d4296e..2dbd380 100644
--- a/shell/core/src/main/resources/OSGI-INF/bundle.info
+++ b/shell/core/src/main/resources/OSGI-INF/bundle.info
@@ -1,3 +1,21 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
 ${project.name}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/core/src/test/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParserTest.java
----------------------------------------------------------------------
diff --git a/shell/core/src/test/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParserTest.java b/shell/core/src/test/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParserTest.java
new file mode 100644
index 0000000..62cc6ca
--- /dev/null
+++ b/shell/core/src/test/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/WikiParserTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.shell.impl.console.commands.help.wikidoc;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+public class WikiParserTest {
+
+	private static final String TESTDOC = 
+		"h1. myTestdoc\n" +
+		"\n" +
+		"Some text\n" +
+		"* enumeration\n" +
+		" some text [a link] some more text\n" +
+		"h1 is no heading";
+	
+	private static final String HEADINGCASES = 
+		"h1.\n" +
+		"hf.";
+
+	@Test
+	public void parseTestDoc() throws IOException {
+		WikiVisitor visitor = EasyMock.createStrictMock(WikiVisitor.class);
+		visitor.startPara(0);
+		EasyMock.expectLastCall();
+		visitor.heading(1, "myTestdoc");
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+		visitor.startPara(0);
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+		visitor.startPara(0);
+		EasyMock.expectLastCall();
+		visitor.text("Some text");
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+		visitor.startPara(0);
+		EasyMock.expectLastCall();
+		visitor.enumeration("enumeration");
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+		visitor.startPara(1);
+		EasyMock.expectLastCall();
+		visitor.text("some text ");
+		EasyMock.expectLastCall();
+		visitor.link("a link", "");
+		EasyMock.expectLastCall();
+		visitor.text(" some more text");
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+		visitor.startPara(0);
+		EasyMock.expectLastCall();
+		visitor.text("h1 is no heading");
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+
+		EasyMock.replay(visitor);
+		WikiParser parser = new WikiParser(visitor);
+		parser.parse(new StringReader(TESTDOC));
+		EasyMock.verify(visitor);
+	}
+	
+	@Test
+	public void parseHeadingSpecialCases() throws IOException {
+		WikiVisitor visitor = EasyMock.createStrictMock(WikiVisitor.class);
+
+		visitor.startPara(0);
+		EasyMock.expectLastCall();
+		visitor.heading(1, "");
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+
+		visitor.startPara(0);
+		EasyMock.expectLastCall();
+		visitor.text("hf.");
+		EasyMock.expectLastCall();
+		visitor.endPara();
+		EasyMock.expectLastCall();
+		
+		EasyMock.replay(visitor);
+		WikiParser parser = new WikiParser(visitor);
+		parser.parse(new StringReader(HEADINGCASES));
+		EasyMock.verify(visitor);
+	}
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/shell/ssh/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/resources/OSGI-INF/bundle.info b/shell/ssh/src/main/resources/OSGI-INF/bundle.info
index bf0b068..feeda99 100644
--- a/shell/ssh/src/main/resources/OSGI-INF/bundle.info
+++ b/shell/ssh/src/main/resources/OSGI-INF/bundle.info
@@ -1,19 +1,41 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
-${project.name}
+	${project.name}
 
-${project.description}
+	${project.description}
 
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+	Maven URL:
+		[mvn:${project.groupId}/${project.artifactId}/${project.version}]
 
 h1. Description
 
-This bundle provides SSH support for the Karaf shell console.
+	This bundle provides SSH support for the Karaf shell console.
 
-It acts as SSH client and server allowing you to receive SSH connection and be able to
-connect to a remote SSH server.
+	It acts as SSH client and server allowing you to receive SSH connection and be able to connect to a remote SSH server.
+
+h1. Commands
+
+	The following commands are available:
+\${command-list|ssh|indent=8,list,cyan}
 
 h1. See also
 
-Using remote instances - section of the Karaf User Guide
+	Using remote instances - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/system/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/system/src/main/resources/OSGI-INF/bundle.info b/system/src/main/resources/OSGI-INF/bundle.info
index acca1c8..966181e 100644
--- a/system/src/main/resources/OSGI-INF/bundle.info
+++ b/system/src/main/resources/OSGI-INF/bundle.info
@@ -1,16 +1,39 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
-${project.name}
+	${project.name}
 
-${project.description}
+	${project.description}
 
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+	Maven URL:
+		[mvn:${project.groupId}/${project.artifactId}/${project.version}]
 
 h1. Description
 
-This bundle provides support of the system service, which control the Karaf container.
+	This bundle provides support of the system service, which control the Karaf container.
+
+h1. Commands
+
+	The following commands are available:
+\${command-list|system|indent=8,list,cyan}
 
 h1. See also
 
-Shutdown - section of the Karaf User Guide
+	Shutdown - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/web/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/web/src/main/resources/OSGI-INF/bundle.info b/web/src/main/resources/OSGI-INF/bundle.info
index 650fee9..2500de5 100644
--- a/web/src/main/resources/OSGI-INF/bundle.info
+++ b/web/src/main/resources/OSGI-INF/bundle.info
@@ -1,16 +1,39 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
-${project.name}
+	${project.name}
 
-${project.description}
+	${project.description}
 
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+	Maven URL:
+		[mvn:${project.groupId}/${project.artifactId}/${project.version}]
 
 h1. Description
 
-This bundle provides support of the WebContainer service, which allows to manipulate the Karaf embedded web container.
+	This bundle provides support of the WebContainer service, which allows to manipulate the Karaf embedded web container.
+
+h1. Commands
+
+	The following commands are available:
+\${command-list|web|indent=8,list,cyan}
 
 h1. See also
 
-Web Container - section of the Karaf User Guide
+	Web Container - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/webconsole/console/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/webconsole/console/src/main/resources/OSGI-INF/bundle.info b/webconsole/console/src/main/resources/OSGI-INF/bundle.info
index 7fa1614..961cb45 100644
--- a/webconsole/console/src/main/resources/OSGI-INF/bundle.info
+++ b/webconsole/console/src/main/resources/OSGI-INF/bundle.info
@@ -1,3 +1,21 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
 ${project.name}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/webconsole/features/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/webconsole/features/src/main/resources/OSGI-INF/bundle.info b/webconsole/features/src/main/resources/OSGI-INF/bundle.info
index e7ff46c..2547e95 100644
--- a/webconsole/features/src/main/resources/OSGI-INF/bundle.info
+++ b/webconsole/features/src/main/resources/OSGI-INF/bundle.info
@@ -1,3 +1,21 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
 ${project.name}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/webconsole/gogo/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/webconsole/gogo/src/main/resources/OSGI-INF/bundle.info b/webconsole/gogo/src/main/resources/OSGI-INF/bundle.info
index 8c0e7a5..b4fc2a8 100644
--- a/webconsole/gogo/src/main/resources/OSGI-INF/bundle.info
+++ b/webconsole/gogo/src/main/resources/OSGI-INF/bundle.info
@@ -1,3 +1,21 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
 ${project.name}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/webconsole/http/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/webconsole/http/src/main/resources/OSGI-INF/bundle.info b/webconsole/http/src/main/resources/OSGI-INF/bundle.info
index e65c23f..3caaafb 100644
--- a/webconsole/http/src/main/resources/OSGI-INF/bundle.info
+++ b/webconsole/http/src/main/resources/OSGI-INF/bundle.info
@@ -1,4 +1,22 @@
-\u001B[1mSYNOPSIS\u001B[0m
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
+h1. SYNOPSIS
     ${project.name}
 
     ${project.description}
@@ -6,8 +24,8 @@
     Maven URL:
         \u001B[33mmvn:${project.groupId}/${project.artifactId}/${project.version}\u001B[0m
 
-\u001B[1mDESCRIPTION\u001B[0m
+h1. DESCRIPTION
     This bundle provides the Karaf http plugin for the Felix Web Console.
 
-\u001B[1mSEE ALSO\u001B[0m
+h1. SEE ALSO
     \u001B[36mWeb console\u001B[0m section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/webconsole/instance/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/webconsole/instance/src/main/resources/OSGI-INF/bundle.info b/webconsole/instance/src/main/resources/OSGI-INF/bundle.info
index 1000da0..4fd2549 100644
--- a/webconsole/instance/src/main/resources/OSGI-INF/bundle.info
+++ b/webconsole/instance/src/main/resources/OSGI-INF/bundle.info
@@ -1,3 +1,21 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
 ${project.name}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f38a1e20/wrapper/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/OSGI-INF/bundle.info b/wrapper/src/main/resources/OSGI-INF/bundle.info
index 8462cc5..3a9277c 100644
--- a/wrapper/src/main/resources/OSGI-INF/bundle.info
+++ b/wrapper/src/main/resources/OSGI-INF/bundle.info
@@ -1,16 +1,39 @@
+#
+#
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You under the Apache License, Version 2.0
+#    (the "License"); you may not use this file except in compliance with
+#    the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+#
+#
 h1. Synopsis
 
-${project.name}
+	${project.name}
 
-${project.description}
+	${project.description}
 
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+	Maven URL:
+		[mvn:${project.groupId}/${project.artifactId}/${project.version}]
 
 h1. Description
 
-This bundle provides support of the service wrapper, which allows for starting/stopping Karaf as a system service.
+	This bundle provides support of the service wrapper, which allows for starting/stopping Karaf as a system service.
+
+h1. Commands
+
+	The following commands are provided:
+\${command-list|wrapper|indent=8,list,cyan}
 
 h1. See also
 
-Service Wrapper - section of the Karaf User Guide
+	Service Wrapper - section of the Karaf User Guide