Repository: logging-log4j2
Updated Branches:
  refs/heads/master 57bbd8825 -> c2818beca


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c2818bec/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/CustomLayoutDemo.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/CustomLayoutDemo.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/CustomLayoutDemo.java
new file mode 100644
index 0000000..1599da4
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/CustomLayoutDemo.java
@@ -0,0 +1,265 @@
+/*
+ * 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.logging.log4j.core.util.picocli;
+
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Help.Ansi.Text;
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Help.Column;
+import 
org.apache.logging.log4j.core.util.picocli.CommandLine.Help.IOptionRenderer;
+import 
org.apache.logging.log4j.core.util.picocli.CommandLine.Help.IParameterRenderer;
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Help.Layout;
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Help.TextTable;
+
+import java.awt.Point;
+import java.lang.reflect.Field;
+
+import static org.apache.logging.log4j.core.util.picocli.CommandLine.*;
+import static 
org.apache.logging.log4j.core.util.picocli.CommandLine.Help.Column.Overflow.*;
+import static 
org.apache.logging.log4j.core.util.picocli.CommandLine.Help.Column.Overflow.SPAN;
+import static 
org.apache.logging.log4j.core.util.picocli.CommandLine.Help.Column.Overflow.TRUNCATE;
+import static 
org.apache.logging.log4j.core.util.picocli.CommandLine.Help.Column.Overflow.WRAP;
+
+/**
+ * Demonstrates how the CommandLine.Help API can be used to create custom 
layouts for usage help messages.
+ */
+@Command(name = "picocli.CustomLayoutDemo", description = "Demonstrates 
picocli custom layouts.",
+        footer = {
+        "Run with -Dpicocli.ansi=true  to force picocli to use ansi codes,",
+        "or  with -Dpicocli.ansi=false to force picocli to NOT use ansi 
codes.",
+        "By default picocli will use ansi codes if the platform supports it."
+        }
+)
+public class CustomLayoutDemo implements Runnable {
+    public static void main(String[] args) {
+        CommandLine.run(new CustomLayoutDemo(), System.err, args);
+    }
+
+    @Option(names = {"-z", "--zip"}, description = "Show usage help for a 
layout with 2 options per row.")
+    private boolean showZip;
+
+    @Option(names = {"-n", "--netstat"}, description = "Show usage help for a 
layout with a narrow options column and a wide description column. Descriptions 
that wrap to the next row are not indented.")
+    private boolean showNetstat;
+
+    public void run() {
+        if (!showZip && !showNetstat) {
+            CommandLine.usage(this, System.err);
+            return;
+        }
+        if (showZip)     { 
System.out.println(createZipUsageFormat(Help.Ansi.AUTO)); }
+        if (showNetstat) { 
System.out.println(createNetstatUsageFormat(Help.Ansi.AUTO)); }
+    }
+
+
+    public static String createZipUsageFormat(Help.Ansi ansi) {
+        @Command(description = {
+                "Copyright (c) 1990-2008 Info-ZIP - Type 'zip \"-L\"' for 
software license.",
+                "Zip 3.0 (July 5th 2008). Command:",
+                "@|bold zip|@ [@|yellow -options|@] [@|yellow -b|@ @|underline 
path|@] [@|yellow -t|@ @|underline mmddyyyy|@] [@|yellow -n|@ @|underline 
suffixes|@] [@|yellow zipfile|@ @|underline list|@] [@|yellow -xi|@ @|underline 
list|@]",
+                "  The default action is to add or replace zipfile entries 
from list, which",
+                "  can include the special name - to compress standard input.",
+                "  If @|yellow zipfile|@ and @|yellow list|@ are omitted, zip 
compresses stdin to stdout."}
+        )
+        class Zip {
+            @Option(names = "-f", description = "freshen: only changed files")
+            boolean freshen;
+            @Option(names = "-u", description = "update: only changed or new 
files")
+            boolean update;
+            @Option(names = "-d", description = "delete entries in zipfile")
+            boolean delete;
+            @Option(names = "-m", description = "move into zipfile (delete OS 
files)")
+            boolean move;
+            @Option(names = "-r", description = "recurse into directories")
+            boolean recurse;
+            @Option(names = "-j", description = "junk (don't record) directory 
names")
+            boolean junk;
+            @Option(names = "-0", description = "store only")
+            boolean store;
+            @Option(names = "-l", description = "convert LF to CR LF (@|yellow 
-ll|@ CR LF to LF)")
+            boolean lf2crlf;
+            @Option(names = "-1", description = "compress faster")
+            boolean faster;
+            @Option(names = "-9", description = "compress better")
+            boolean better;
+            @Option(names = "-q", description = "quiet operation")
+            boolean quiet;
+            @Option(names = "-v", description = "verbose operation/print 
version info")
+            boolean verbose;
+            @Option(names = "-c", description = "add one-line comments")
+            boolean comments;
+            @Option(names = "-z", description = "add zipfile comment")
+            boolean zipComment;
+            @Option(names = "-@", description = "read names from stdin")
+            boolean readFileList;
+            @Option(names = "-o", description = "make zipfile as old as latest 
entry")
+            boolean old;
+            @Option(names = "-x", description = "exclude the following names")
+            boolean exclude;
+            @Option(names = "-i", description = "include only the following 
names")
+            boolean include;
+            @Option(names = "-F", description = "fix zipfile (@|yellow -FF|@ 
try harder)")
+            boolean fix;
+            @Option(names = "-D", description = "do not add directory entries")
+            boolean directories;
+            @Option(names = "-A", description = "adjust self-extracting exe")
+            boolean adjust;
+            @Option(names = "-J", description = "junk zipfile prefix 
(unzipsfx)")
+            boolean junkPrefix;
+            @Option(names = "-T", description = "test zipfile integrity")
+            boolean test;
+            @Option(names = "-X", description = "eXclude eXtra file 
attributes")
+            boolean excludeAttribs;
+            @Option(names = "-y", description = "store symbolic links as the 
link instead of the referenced file")
+            boolean symbolic;
+            @Option(names = "-e", description = "encrypt")
+            boolean encrypt;
+            @Option(names = "-n", description = "don't compress these 
suffixes")
+            boolean dontCompress;
+            @Option(names = "-h2", description = "show more help")
+            boolean moreHelp;
+        }
+
+        class TwoOptionsPerRowLayout extends Layout { // define a custom layout
+            Point previous = new Point(0, 0);
+
+            private TwoOptionsPerRowLayout(Help.ColorScheme colorScheme, 
TextTable textTable,
+                                           IOptionRenderer optionRenderer,
+                                           IParameterRenderer 
parameterRenderer) {
+                super(colorScheme, textTable, optionRenderer, 
parameterRenderer);
+            }
+
+            @Override
+            public void layout(Field field, Text[][] values) {
+                Text[] columnValues = values[0]; // we know renderer creates a 
single row with two values
+
+                // We want to show two options on one row, next to each other,
+                // unless the first option spanned multiple columns (in which 
case there are not enough columns left)
+                int col = previous.x + 1;
+                if (col == 1 || col + columnValues.length > 
table.columns.length) { // if true, write into next row
+
+                    // table also adds an empty row if a text value spanned 
multiple columns
+                    if (table.rowCount() == 0 || table.rowCount() == 
previous.y + 1) { // avoid adding 2 empty rows
+                        table.addEmptyRow(); // create the slots to write the 
text values into
+                    }
+                    col = 0; // we are starting a new row, reset the column to 
write into
+                }
+                for (int i = 0; i < columnValues.length; i++) {
+                    // always write to the last row, column depends on what 
happened previously
+                    previous = table.putValue(table.rowCount() - 1, col + i, 
columnValues[i]);
+                }
+            }
+        }
+        TextTable textTable = new TextTable(ansi,
+                new Column(5, 2, TRUNCATE), // values should fit
+                new Column(30, 2, SPAN), // overflow into adjacent columns
+                new Column(4, 1, TRUNCATE), // values should fit again
+                new Column(39, 2, WRAP));
+        TwoOptionsPerRowLayout layout = new TwoOptionsPerRowLayout(
+                Help.defaultColorScheme(ansi),
+                textTable,
+                Help.createMinimalOptionRenderer(),
+                Help.createMinimalParameterRenderer());
+
+        Help help = new Help(new Zip(), ansi);
+        StringBuilder sb = new StringBuilder();
+        sb.append(help.description()); // show the first 6 lines, including 
copyright, description and usage
+
+        // Note that we don't sort the options, so they appear in the order 
the fields are declared in the Zip class.
+        layout.addOptions(help.optionFields, help.parameterLabelRenderer);
+        sb.append(layout); // finally, copy the options details help text into 
the StringBuilder
+
+        return sb.toString();
+    }
+
+    /** for Netstat test */
+    private enum Protocol {IP, IPv6, ICMP, ICMPv6, TCP, TCPv6, UDP, UDPv6}
+
+    public static String createNetstatUsageFormat(Help.Ansi ansi) {
+        @Command(name = "NETSTAT",
+                separator = " ",
+                abbreviateSynopsis = true,
+                header = "Displays protocol statistics and current TCP/IP 
network connections.%n")
+        class Netstat {
+            @Option(names="-a", description="Displays all connections and 
listening ports.")
+            boolean displayAll;
+            @Option(names="-b", description="Displays the executable involved 
in creating each connection or "
+                    + "listening port. In some cases well-known executables 
host "
+                    + "multiple independent components, and in these cases the 
"
+                    + "sequence of components involved in creating the 
connection "
+                    + "or listening port is displayed. In this case the 
executable "
+                    + "name is in [] at the bottom, on top is the component it 
called, "
+                    + "and so forth until TCP/IP was reached. Note that this 
option "
+                    + "can be time-consuming and will fail unless you have 
sufficient "
+                    + "permissions.")
+            boolean displayExecutable;
+            @Option(names="-e", description="Displays Ethernet statistics. 
This may be combined with the -s option.")
+            boolean displayEthernetStats;
+            @Option(names="-f", description="Displays Fully Qualified Domain 
Names (FQDN) for foreign addresses.")
+            boolean displayFQCN;
+            @Option(names="-n", description="Displays addresses and port 
numbers in numerical form.")
+            boolean displayNumerical;
+            @Option(names="-o", description="Displays the owning process ID 
associated with each connection.")
+            boolean displayOwningProcess;
+            @Option(names="-p", paramLabel = "proto",
+                    description="Shows connections for the protocol specified 
by proto; proto "
+                            + "may be any of: TCP, UDP, TCPv6, or UDPv6.  If 
used with the -s "
+                            + "option to display per-protocol statistics, 
proto may be any of: "
+                            + "IP, IPv6, ICMP, ICMPv6, TCP, TCPv6, UDP, or 
UDPv6.")
+            Protocol proto;
+            @Option(names="-q", description="Displays all connections, 
listening ports, and bound "
+                    + "nonlistening TCP ports. Bound nonlistening ports may or 
may not "
+                    + "be associated with an active connection.")
+            boolean query;
+            @Option(names="-r", description="Displays the routing table.")
+            boolean displayRoutingTable;
+            @Option(names="-s", description="Displays per-protocol statistics. 
 By default, statistics are "
+                    + "shown for IP, IPv6, ICMP, ICMPv6, TCP, TCPv6, UDP, and 
UDPv6; "
+                    + "the -p option may be used to specify a subset of the 
default.")
+            boolean displayStatistics;
+            @Option(names="-t", description="Displays the current connection 
offload state.")
+            boolean displayOffloadState;
+            @Option(names="-x", description="Displays NetworkDirect 
connections, listeners, and shared endpoints.")
+            boolean displayNetDirect;
+            @Option(names="-y", description="Displays the TCP connection 
template for all connections. "
+                    + "Cannot be combined with the other options.")
+            boolean displayTcpConnectionTemplate;
+            @Parameters(arity = "0..1", paramLabel = "interval", description = 
""
+                    + "Redisplays selected statistics, pausing interval 
seconds "
+                    + "between each display.  Press CTRL+C to stop 
redisplaying "
+                    + "statistics.  If omitted, netstat will print the current 
"
+                    + "configuration information once.")
+            int interval;
+        }
+        StringBuilder sb = new StringBuilder();
+        Help help = new Help(new Netstat(), ansi);
+        help.synopsisHeading = "";
+        sb.append(help.header()).append(help.detailedSynopsis(0, null, false));
+        sb.append(System.getProperty("line.separator"));
+
+        TextTable textTable = new TextTable(ansi,
+                new Column(15, 2, TRUNCATE),
+                new Column(65, 1, WRAP));
+        textTable.indentWrappedLines = 0;
+        Layout layout = new Layout(
+                Help.defaultColorScheme(ansi),
+                textTable,
+                Help.createMinimalOptionRenderer(),
+                Help.createMinimalParameterRenderer());
+        layout.addOptions(help.optionFields, help.parameterLabelRenderer);
+        layout.addPositionalParameters(help.positionalParametersFields, 
Help.createMinimalParamLabelRenderer());
+        sb.append(layout);
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c2818bec/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/Demo.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/Demo.java 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/Demo.java
new file mode 100644
index 0000000..5845c8d
--- /dev/null
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/util/picocli/Demo.java
@@ -0,0 +1,652 @@
+/*
+ * 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.logging.log4j.core.util.picocli;
+
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Command;
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Option;
+import org.apache.logging.log4j.core.util.picocli.CommandLine.Parameters;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Demonstrates picocli subcommands.
+ */
+@Command(name = "picocli.Demo", sortOptions = false,
+        header = {
+                "@|green        .__                    .__  .__ |@",
+                "@|green ______ |__| ____  ____   ____ |  | |__||@",
+                "@|green \\____ \\|  |/ ___\\/  _ \\_/ ___\\|  | |  ||@",
+                "@|green |  |_> >  \\  \\__(  <_> )  \\___|  |_|  ||@",
+                "@|green |   __/|__|\\___  >____/ \\___  >____/__||@",
+                "@|green |__|           \\/           \\/         |@",
+                ""},
+        //descriptionHeading = "@|bold %nDescription|@:%n",
+        description = {
+                "",
+                "Demonstrates picocli subcommands parsing and usage help.", },
+        optionListHeading = "@|bold %nOptions|@:%n",
+        footer = {
+                "",
+                "@|bold VM Options|@:",
+                "Run with @|yellow -ea|@ to enable assertions used in the 
tests.",
+                "Run with @|yellow -Dpicocli.ansi|@=@|italic true|@ to force 
picocli to use ansi codes,",
+                " or with @|yellow -Dpicocli.ansi|@=@|italic false|@ to force 
picocli to NOT use ansi codes.",
+                "(By default picocli will use ansi codes if the platform 
supports it.)",
+                "",
+                "@|cyan If you would like to contribute or report an issue|@",
+                "@|cyan go to github: https://github.com/remkop/picocli|@",
+                "",
+                "@|cyan If you like the project star it on github and follow 
me on twitter!|@",
+                "@|cyan This project is created and maintained by Remko Popma 
(@remkopopma)|@",
+                ""})
+public class Demo implements Runnable {
+    public static void main(String[] args) {
+        CommandLine.run(new Demo(), System.err, args);
+    }
+
+    @Option(names = {"-1", "--showUsageForSubcommandGitCommit"}, description = 
"Shows usage help for the git-commit subcommand")
+    private boolean showUsageForSubcommandGitCommit;
+
+    @Option(names = {"-2", "--showUsageForMainCommand"}, description = "Shows 
usage help for a command with subcommands")
+    private boolean showUsageForMainCommand;
+
+    @Option(names = {"-3", "--showUsageForSubcommandGitStatus"}, description = 
"Shows usage help for the git-status subcommand")
+    private boolean showUsageForSubcommandGitStatus;
+
+    @Option(names = "--simple", description = "Show help for the first simple 
Example in the manual")
+    private boolean showSimpleExample;
+
+    @Option(names = "--mixed", hidden = true, description = "Show help with 
mixed Ansi colors and styles in description")
+    private boolean showAnsiInDescription;
+
+    @Option(names = {"-i", "--index"}, description = "" +
+            "@|fg(21) S|@" +
+            "@|fg(57) h|@" +
+            "@|fg(93) o|@" +
+            "@|fg(129) w|@" +
+            "@|fg(129)  |@" +
+            "@|fg(165) 2|@" +
+            "@|fg(201) 5|@" +
+            "@|fg(225) 6|@" +
+            "@|fg(123)  |@" +
+            "@|fg(122) c|@" +
+            "@|fg(120) o|@" +
+            "@|fg(118) l|@" +
+            "@|fg(148) o|@" +
+            "@|fg(142) r|@" +
+            "@|fg(136)  |@" +
+            "@|fg(136) p|@" +
+            "@|fg(130) a|@" +
+            "@|fg(124) l|@" +
+            "@|fg(160) e|@" +
+            "@|fg(196) t|@" +
+            "@|fg(198) t|@" +
+            "@|fg(199) e|@" +
+            "@|fg(200)  |@" +
+            "@|fg(201) i|@" +
+            "@|fg(213) n|@" +
+            "@|fg(219) d|@" +
+            "@|fg(225) e|@" +
+            "@|fg(231) x|@" +
+            "@|fg(230)  |@" +
+            "@|fg(229) v|@" +
+            "@|fg(228) a|@" +
+            "@|fg(227) l|@" +
+            "@|fg(226) u|@" +
+            "@|fg(190) e|@" +
+            "@|fg(154) s|@")
+    private boolean showIndexedColorPalette;
+
+    @Option(names = {"-r", "--rgb"}, description =  "" +
+            "@|fg(0;0;5) S|@" +
+            "@|fg(1;0;5) h|@" +
+            "@|fg(2;0;5) o|@" +
+            "@|fg(3;0;5) w|@" +
+            "@|fg(3;0;5)  |@" +
+            "@|fg(4;0;5) 2|@" +
+            "@|fg(5;0;5) 5|@" +
+            "@|fg(5;4;5) 6|@" +
+            "@|fg(2;5;5)  |@" +
+            "@|fg(2;5;4) c|@" +
+            "@|fg(2;5;2) o|@" +
+            "@|fg(2;5;0) l|@" +
+            "@|fg(3;4;0) o|@" +
+            "@|fg(3;3;0) r|@" +
+            "@|fg(3;2;0)  |@" +
+            "@|fg(3;2;0) p|@" +
+            "@|fg(3;1;0) a|@" +
+            "@|fg(3;0;0) l|@" +
+            "@|fg(4;0;0) e|@" +
+            "@|fg(5;0;0) t|@" +
+            "@|fg(5;0;2) t|@" +
+            "@|fg(5;0;3) e|@" +
+            "@|fg(5;0;4)  |@" +
+            "@|fg(5;0;5) R|@" +
+            "@|fg(5;2;5) G|@" +
+            "@|fg(5;3;5) B|@" +
+            "@|fg(5;4;5)  |@" +
+            "@|fg(5;5;5) c|@" +
+            "@|fg(5;5;4) o|@" +
+            "@|fg(5;5;3) m|@" +
+            "@|fg(5;5;2) p|@" +
+            "@|fg(5;5;1) o|@" +
+            "@|fg(5;5;0) n|@" +
+            "@|fg(4;5;0) e|@" +
+            "@|fg(3;5;0) n|@" +
+            "@|fg(2;5;0) t|@" +
+            "@|fg(1;5;0)  |@" +
+            "@|fg(1;5;0) v|@" +
+            "@|fg(0;5;0) a|@" +
+            "@|fg(0;4;0) l|@" +
+            "@|fg(0;3;0) u|@" +
+            "@|fg(0;2;0) e|@" +
+            "@|fg(0;1;0) s|@" +
+            "")
+    private boolean showRgbColorPalette;
+
+    @Option(names = {"-t", "--tests"}, description = "Runs all tests in this 
class")
+    private boolean runTests;
+
+    public void run() {
+        if (!runTests &&
+                !showSimpleExample &&
+                !showAnsiInDescription &&
+                !showIndexedColorPalette &&
+                !showRgbColorPalette &&
+                !showUsageForMainCommand &&
+                !showUsageForSubcommandGitCommit &&
+                !showUsageForSubcommandGitStatus) {
+            CommandLine.usage(this, System.err);
+            return;
+        }
+        if (runTests)                        { testParseSubCommands(); 
System.out.println("Ran tests OK.");}
+        if (showSimpleExample)               { showSimpleExampleUsage(); }
+        if (showAnsiInDescription)           { showAnsiInDescription(); }
+        if (showIndexedColorPalette)         { showIndexedColorPalette(); }
+        if (showRgbColorPalette)             { showRgbColorPalette(); }
+        if (showUsageForMainCommand)         { testUsageMainCommand(); }
+        if (showUsageForSubcommandGitStatus) { testUsageSubCommandStatus(); }
+        if (showUsageForSubcommandGitCommit) { testUsageSubCommandCommit(); }
+    }
+
+    private void showSimpleExampleUsage() {
+        class Example {
+            @Option(names = { "-v", "--verbose" }, description = "Be verbose.")
+            private boolean verbose = false;
+
+            @Option(names = { "-h", "--help" }, help = true,
+                    description = "Displays this help message and quits.")
+            private boolean helpRequested = false;
+
+            @Parameters(arity = "1..*", paramLabel = "FILE", description = 
"File(s) to process.")
+            private File[] inputFiles;
+        }
+        CommandLine.usage(new Example(), System.out);
+    }
+
+    private void showAnsiInDescription() {
+        @Command(description = "Custom @|bold,underline styles|@ and @|fg(red) 
colors|@.")
+        class AnsiDescription { }
+        CommandLine.usage(new AnsiDescription(), System.out);
+    }
+
+    private void showIndexedColorPalette() {
+        int[] foregroundBackground = {38, 48};
+        for (int fbg : foregroundBackground) {
+            for (int r = 0; r < 2; r++) {
+                for (int g = 0; g < 6; g++) {
+                    for (int b = 0; b < 6; b++) {
+                        int col = 16 + 36 * (0 + 3 * r) + 6 * g + b;
+                        System.out.printf("\u001B[%d;5;%dm%3d \u001B[0m", fbg, 
col, col);
+                    }
+                    for (int b = 0; b < 6; b++) {
+                        int col = 16 + 36 * (1 + 3 * r) + 6 * g + b;
+                        System.out.printf("\u001B[%d;5;%dm%3d \u001B[0m", fbg, 
col, col);
+                    }
+                    for (int b = 0; b < 6; b++) {
+                        int col = 16 + 36 * (2 + 3 * r) + 6 * g + b;
+                        System.out.printf("\u001B[%d;5;%dm%3d \u001B[0m", fbg, 
col, col);
+                    }
+                    System.out.println();
+                }
+                System.out.println();
+            }
+            int r = 6;
+            for (int g = 0; g < 4; g++) {
+                for (int b = 0; b < 6; b++) {
+                    int col = 16 + 36 * r + 6 * g + b;
+                    System.out.printf("\u001B[%d;5;%dm%3d \u001B[0m", fbg, 
col, col);
+                }
+                System.out.println();
+            }
+            System.out.println();
+        }
+    }
+
+    private void showRgbColorPalette() {
+        int[] foregroundBackground = {38, 48};
+        for (int fbg : foregroundBackground) {
+            for (int r = 0; r < 2; r++) {
+                System.out.println("RGB RGB RGB RGB RGB RGB RGB RGB RGB RGB 
RGB RGB RGB RGB RGB RGB RGB RGB ");
+                for (int g = 0; g < 6; g++) {
+                    for (int b = 0; b < 6; b++) {
+                        int col = 16 + 36 * (0 + 3 * r) + 6 * g + b;
+                        System.out.printf("\u001B[%d;5;%dm%d%d%d \u001B[0m", 
fbg, col, (0 + 3 * r),g,b);
+                    }
+                    for (int b = 0; b < 6; b++) {
+                        int col = 16 + 36 * (1 + 3 * r) + 6 * g + b;
+                        System.out.printf("\u001B[%d;5;%dm%d%d%d \u001B[0m", 
fbg, col, (1 + 3 * r),g,b);
+                    }
+                    for (int b = 0; b < 6; b++) {
+                        int col = 16 + 36 * (2 + 3 * r) + 6 * g + b;
+                        System.out.printf("\u001B[%d;5;%dm%d%d%d \u001B[0m", 
fbg, col, (2 + 3 * r),g,b);
+                    }
+                    System.out.println();
+                }
+                System.out.println();
+            }
+            System.out.println("RGB RGB RGB RGB RGB RGB");
+            int r = 6;
+            for (int g = 0; g < 4; g++) {
+                for (int b = 0; b < 6; b++) {
+                    int col = 16 + 36 * r + 6 * g + b;
+                    System.out.printf("\u001B[%d;5;%dm%d%d%d \u001B[0m", fbg, 
col, r,g,b);
+                }
+                System.out.println();
+            }
+            System.out.println();
+        }
+    }
+
+    //------------------------------------------
+    static
+    // tag::Git[]
+    // tag::Git-declaration[]
+    @Command(name = "git", sortOptions = false,
+            description = "Git is a fast, scalable, distributed revision 
control " +
+                          "system with an unusually rich command set that 
provides both " +
+                          "high-level operations and full access to 
internals.",
+            commandListHeading = "%nCommands:%n%nThe most commonly used git 
commands are:%n")
+    class Git { // end::Git-declaration[]
+        @Option(names = {"-V", "--version"}, help = true, description = 
"Prints version information and exits")
+        boolean isVersionRequested;
+
+        @Option(names = {"-h", "--help"}, help = true, description = "Prints 
this help message and exits")
+        boolean isHelpRequested;
+
+        @Option(names = "--git-dir", description = "Set the path to the 
repository")
+        File gitDir;
+    }
+    // end::Git[]
+
+    // the "status" subcommand's has an option "mode" with a fixed number of 
values, modeled by this enum
+    enum GitStatusMode {all, no, normal};
+
+    static
+    @Command(name = "git-status",
+            header = "Show the working tree status.",
+            showDefaultValues = true,
+            customSynopsis = "@|bold git-status|@ [@|yellow <options>|@...] 
[--] [@|yellow <pathspec>|@...]",
+            description = "Displays paths that have differences between the 
index file and the current HEAD commit, " +
+                    "paths that have differences between the working tree and 
the index file, and paths in the " +
+                    "working tree that are not tracked by Git (and are not 
ignored by gitignore(5)). The first " +
+                    "are what you would commit by running git commit; the 
second and third are what you could " +
+                    "commit by running git add before running git commit."
+    )
+    class GitStatus {
+        @Option(names = {"-s", "--short"}, description = "Give the output in 
the short-format")
+        boolean shortFormat;
+
+        @Option(names = {"-b", "--branch"}, description = "Show the branch and 
tracking info even in short-format")
+        boolean branchInfo;
+
+        @Option(names = "--ignored", description = "Show ignored files as 
well") boolean showIgnored;
+
+        @Option(names = {"-u", "--untracked"}, paramLabel = "<mode>", 
description = {
+                "Show untracked files.",
+                "The mode parameter is optional (defaults to `all`), and is 
used to specify the handling of untracked files.",
+                "The possible options are:",
+                " * @|yellow no|@ - Show no untracked files.",
+                " * @|yellow normal|@ - Shows untracked files and 
directories.",
+                " * @|yellow all|@ - Also shows individual files in untracked 
directories."
+        })
+        GitStatusMode mode = GitStatusMode.all;
+    }
+
+    static
+    // tag::GitCommit[]
+    // tag::GitCommit-declaration[]
+    @Command(name = "git-commit",
+            sortOptions = false,
+            headerHeading = "@|bold,underline Usage:|@%n%n",
+            synopsisHeading = "%n",
+            descriptionHeading = "%n@|bold,underline Description:|@%n%n",
+            parameterListHeading = "%n@|bold,underline Parameters:|@%n",
+            optionListHeading = "%n@|bold,underline Options:|@%n",
+            header = "Record changes to the repository.",
+            description = "Stores the current contents of the index in a new 
commit " +
+                    "along with a log message from the user describing the 
changes.")
+    class GitCommit { // end::GitCommit-declaration[]
+        @Option(names = {"-a", "--all"},
+                description = "Tell the command to automatically stage files 
that have been modified " +
+                        "and deleted, but new files you have not told Git 
about are not affected.")
+        boolean all;
+
+        @Option(names = {"-p", "--patch"}, description = "Use the interactive 
patch selection interface to chose which changes to commit")
+        boolean patch;
+
+        @Option(names = {"-C", "--reuse-message"}, paramLabel = "<commit>",
+                description = "Take an existing commit object, and reuse the 
log message and the " +
+                        "authorship information (including the timestamp) when 
creating the commit.")
+        String reuseMessageCommit;
+
+        @Option(names = {"-c", "--reedit-message"}, paramLabel = "<commit>",
+                description = "Like -C, but with -c the editor is invoked, so 
that the user can" +
+                        "further edit the commit message.")
+        String reEditMessageCommit;
+
+        @Option(names = "--fixup", paramLabel = "<commit>",
+                description = "Construct a commit message for use with rebase 
--autosquash.")
+        String fixupCommit;
+
+        @Option(names = "--squash", paramLabel = "<commit>",
+                description = "Construct a commit message for use with rebase 
--autosquash. The commit" +
+                        "message subject line is taken from the specified 
commit with a prefix of " +
+                        "\"squash! \". Can be used with additional commit 
message options (-m/-c/-C/-F).")
+        String squashCommit;
+
+        @Option(names = {"-F", "--file"}, paramLabel = "<file>",
+                description = "Take the commit message from the given file. 
Use - to read the message from the standard input.")
+        File file;
+
+        @Option(names = {"-m", "--message"}, paramLabel = "<msg>",
+                description = " Use the given <msg> as the commit message. If 
multiple -m options" +
+                        " are given, their values are concatenated as separate 
paragraphs.")
+        List<String> message = new ArrayList<String>();
+
+        @Parameters(paramLabel = "<files>", description = "the files to 
commit")
+        List<File> files = new ArrayList<File>();
+    }
+    // end::GitCommit[]
+
+    // defines some commands to show in the list (option/parameters fields 
omitted for this demo)
+    @Command(name = "git-add", header = "Add file contents to the index.") 
static class GitAdd {}
+    @Command(name = "git-branch", header = "List, create, or delete 
branches.") static class GitBranch {}
+    @Command(name = "git-checkout", header = "Checkout a branch or paths to 
the working tree.") static class GitCheckout{}
+    @Command(name = "git-clone", header = "Clone a repository into a new 
directory.") static class GitClone{}
+    @Command(name = "git-diff", header = "Show changes between commits, commit 
and working tree, etc.") static class GitDiff{}
+    @Command(name = "git-merge", header = "Join two or more development 
histories together.") static class GitMerge{}
+    @Command(name = "git-push", header = "Update remote refs along with 
associated objects.") static class GitPush{}
+    @Command(name = "git-rebase", header = "Forward-port local commits to the 
updated upstream head.") static class GitRebase{}
+    @Command(name = "git-tag", header = "Create, list, delete or verify a tag 
object signed with GPG.") static class GitTag{}
+
+    /** @see CommandLineTest#testParseSubCommands() The JUnit test 
implementation of this test. */
+    public static void testParseSubCommands() {
+        CommandLine commandLine = mainCommand();
+
+        String[] args = { "--git-dir=/home/rpopma/picocli", "status", 
"-sbuno"};
+        List<CommandLine> parsed = commandLine.parse(args);
+        assert parsed.size() == 2 : "found 2 commands";
+
+        assert parsed.get(0).getCommand().getClass() == Git.class;
+        assert parsed.get(1).getCommand().getClass() == GitStatus.class;
+
+        Git git = (Git) parsed.get(0).getCommand();
+        assert git.gitDir.equals(new File("/home/rpopma/picocli"));
+
+        GitStatus status = (GitStatus) parsed.get(1).getCommand();
+        assert  status.shortFormat : "status -s";
+        assert  status.branchInfo  : "status -b";
+        assert !status.showIgnored : "status --showIgnored not specified";
+        assert  status.mode == GitStatusMode.no : "status -u=no";
+    }
+
+    static CommandLine mainCommand() {
+        CommandLine commandLine = new CommandLine(new Git());
+        commandLine.addSubcommand("status", new GitStatus());
+        commandLine.addSubcommand("commit", new GitCommit());
+        commandLine.addSubcommand("add", new GitAdd());
+        commandLine.addSubcommand("branch", new GitBranch());
+        commandLine.addSubcommand("checkout", new GitCheckout());
+        commandLine.addSubcommand("clone", new GitClone());
+        commandLine.addSubcommand("diff", new GitDiff());
+        commandLine.addSubcommand("merge", new GitMerge());
+        commandLine.addSubcommand("push", new GitPush());
+        commandLine.addSubcommand("rebase", new GitRebase());
+        commandLine.addSubcommand("tag", new GitTag());
+        return commandLine;
+    }
+
+    public void testUsageMainCommand()  {
+        CommandLine commandLine = mainCommand();
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            commandLine.usage(new PrintStream(baos, true, "UTF8"));
+            String result = baos.toString("UTF8");
+            System.out.println(result);
+            assert String.format(EXPECTED_USAGE_MAIN).equals(result);
+        } catch (UnsupportedEncodingException ex) {
+            throw new InternalError(ex.toString());
+        }
+    }
+    static final String EXPECTED_USAGE_MAIN = "Usage: git [-hV] 
[--git-dir=<gitDir>]%n" +
+            "Git is a fast, scalable, distributed revision control system with 
an unusually%n" +
+            "rich command set that provides both high-level operations and 
full access to%n" +
+            "internals.%n" +
+            "  -V, --version               Prints version information and 
exits%n" +
+            "  -h, --help                  Prints this help message and 
exits%n" +
+            "      --git-dir=<gitDir>      Set the path to the repository%n" +
+            "%n" +
+            "Commands:%n" +
+            "%n" +
+            "The most commonly used git commands are:%n" +
+            "  status    Show the working tree status.%n" +
+            "  commit    Record changes to the repository.%n" +
+            "  add       Add file contents to the index.%n" +
+            "  branch    List, create, or delete branches.%n" +
+            "  checkout  Checkout a branch or paths to the working tree.%n" +
+            "  clone     Clone a repository into a new directory.%n" +
+            "  diff      Show changes between commits, commit and working 
tree, etc.%n" +
+            "  merge     Join two or more development histories together.%n" +
+            "  push      Update remote refs along with associated objects.%n" +
+            "  rebase    Forward-port local commits to the updated upstream 
head.%n" +
+            "  tag       Create, list, delete or verify a tag object signed 
with GPG.%n";
+
+    static final String EXPECTED_USAGE_MAIN_ANSI = "Usage: @|bold git|@ 
[@|yellow -hV|@] [@|yellow --git-dir|@=@|italic <gitDir>|@]%n" +
+            "Git is a fast, scalable, distributed revision control system with 
an unusually%n" +
+            "rich command set that provides both high-level operations and 
full access to%n" +
+            "internals.%n" +
+            "  @|yellow -V|@, @|yellow --version|@               Prints 
version information and exits%n" +
+            "  @|yellow -h|@, @|yellow --help|@                  Prints this 
help message and exits%n" +
+            "      @|yellow --git-dir|@=@|italic <gitDir>|@      Set the path 
to the repository%n" +
+            "%n" +
+            "Commands:%n" +
+            "%n" +
+            "The most commonly used git commands are:%n" +
+            "  @|bold status|@    Show the working tree status.%n" +
+            "  @|bold commit|@    Record changes to the repository.%n" +
+            "  @|bold add|@       Add file contents to the index.%n" +
+            "  @|bold branch|@    List, create, or delete branches.%n" +
+            "  @|bold checkout|@  Checkout a branch or paths to the working 
tree.%n" +
+            "  @|bold clone|@     Clone a repository into a new directory.%n" +
+            "  @|bold diff|@      Show changes between commits, commit and 
working tree, etc.%n" +
+            "  @|bold merge|@     Join two or more development histories 
together.%n" +
+            "  @|bold push|@      Update remote refs along with associated 
objects.%n" +
+            "  @|bold rebase|@    Forward-port local commits to the updated 
upstream head.%n" +
+            "  @|bold tag|@       Create, list, delete or verify a tag object 
signed with GPG.%n";
+
+    public void testUsageSubCommandStatus() {
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            CommandLine.usage(new GitStatus(), new PrintStream(baos, true, 
"UTF8"));
+            String result = baos.toString("UTF8");
+            System.out.println(result);
+            assert String.format(EXPECTED_USAGE_GITSTATUS).equals(result);
+        } catch (UnsupportedEncodingException ex) {
+            throw new InternalError(ex.toString());
+        }
+    }
+    static final String EXPECTED_USAGE_GITSTATUS = "Show the working tree 
status.%n" +
+            "Usage: git-status [<options>...] [--] [<pathspec>...]%n" +
+            "Displays paths that have differences between the index file and 
the current%n" +
+            "HEAD commit, paths that have differences between the working tree 
and the index%n" +
+            "file, and paths in the working tree that are not tracked by Git 
(and are not%n" +
+            "ignored by gitignore(5)). The first are what you would commit by 
running git%n" +
+            "commit; the second and third are what you could commit by running 
git add%n" +
+            "before running git commit.%n" +
+            "      --ignored               Show ignored files as well%n" +
+            "  -b, --branch                Show the branch and tracking info 
even in%n" +
+            "                                short-format%n" +
+            "  -s, --short                 Give the output in the 
short-format%n" +
+            "  -u, --untracked=<mode>      Show untracked files.%n" +
+            "                              The mode parameter is optional 
(defaults to%n" +
+            "                                `all`), and is used to specify 
the handling of%n" +
+            "                                untracked files.%n" +
+            "                              The possible options are:%n" +
+            "                               * no - Show no untracked files.%n" 
+
+            "                               * normal - Shows untracked files 
and directories.%n" +
+            "                               * all - Also shows individual 
files in untracked%n" +
+            "                                directories.%n" +
+            "                                Default: all%n";
+
+    static final String EXPECTED_USAGE_GITSTATUS_ANSI = "Show the working tree 
status.%n" +
+            "Usage: @|bold git-status|@ [@|yellow <options>|@...] [--] 
[@|yellow <pathspec>|@...]%n" +
+            "Displays paths that have differences between the index file and 
the current%n" +
+            "HEAD commit, paths that have differences between the working tree 
and the index%n" +
+            "file, and paths in the working tree that are not tracked by Git 
(and are not%n" +
+            "ignored by gitignore(5)). The first are what you would commit by 
running git%n" +
+            "commit; the second and third are what you could commit by running 
git add%n" +
+            "before running git commit.%n" +
+            "      @|yellow --ignored|@               Show ignored files as 
well%n" +
+            "  @|yellow -b|@, @|yellow --branch|@                Show the 
branch and tracking info even in%n" +
+            "                                short-format%n" +
+            "  @|yellow -s|@, @|yellow --short|@                 Give the 
output in the short-format%n" +
+            "  @|yellow -u|@, @|yellow --untracked|@=@|italic <mode>|@      
Show untracked files.%n" +
+            "                              The mode parameter is optional 
(defaults to%n" +
+            "                                `all`), and is used to specify 
the handling of%n" +
+            "                                untracked files.%n" +
+            "                              The possible options are:%n" +
+            "                               * @|yellow no|@ - Show no 
untracked files.%n" +
+            "                               * @|yellow normal|@ - Shows 
untracked files and directories.%n" +
+            "                               * @|yellow all|@ - Also shows 
individual files in untracked%n" +
+            "                                directories.%n" +
+            "                                Default: all%n";
+
+    public void testUsageSubCommandCommit() {
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            CommandLine.usage(new GitCommit(), new PrintStream(baos, true, 
"UTF8"));
+            String result = baos.toString("UTF8");
+            System.out.println(result);
+            assert String.format(EXPECTED_USAGE_GITCOMMIT).equals(result);
+        } catch (UnsupportedEncodingException ex) {
+            throw new InternalError(ex.toString());
+        }
+    }
+    static final String EXPECTED_USAGE_GITCOMMIT = "Usage:%n" +
+            "%n" +
+            "Record changes to the repository.%n" +
+            "%n" +
+            "git-commit [-ap] [--fixup=<commit>] [--squash=<commit>] 
[-c=<commit>]%n" +
+            "           [-C=<commit>] [-F=<file>] [-m[=<msg>...]] 
[<files>...]%n" +
+            "%n" +
+            "Description:%n" +
+            "%n" +
+            "Stores the current contents of the index in a new commit along 
with a log%n" +
+            "message from the user describing the changes.%n" +
+            "%n" +
+            "Parameters:%n" +
+            "      <files>                 the files to commit%n" +
+            "%n" +
+            "Options:%n" +
+            "  -a, --all                   Tell the command to automatically 
stage files%n" +
+            "                                that have been modified and 
deleted, but new%n" +
+            "                                files you have not told Git about 
are not%n" +
+            "                                affected.%n" +
+            "  -p, --patch                 Use the interactive patch selection 
interface to%n" +
+            "                                chose which changes to commit%n" +
+            "  -C, --reuse-message=<commit>%n" +
+            "                              Take an existing commit object, and 
reuse the log%n" +
+            "                                message and the authorship 
information%n" +
+            "                                (including the timestamp) when 
creating the%n" +
+            "                                commit.%n" +
+            "  -c, --reedit-message=<commit>%n" +
+            "                              Like -C, but with -c the editor is 
invoked, so%n" +
+            "                                that the user canfurther edit the 
commit%n" +
+            "                                message.%n" +
+            "      --fixup=<commit>        Construct a commit message for use 
with rebase%n" +
+            "                                --autosquash.%n" +
+            "      --squash=<commit>       Construct a commit message for use 
with rebase%n" +
+            "                                --autosquash. The commitmessage 
subject line is%n" +
+            "                                taken from the specified commit 
with a prefix%n" +
+            "                                of \"squash! \". Can be used with 
additional%n" +
+            "                                commit message options 
(-m/-c/-C/-F).%n" +
+            "  -F, --file=<file>           Take the commit message from the 
given file. Use%n" +
+            "                                - to read the message from the 
standard input.%n" +
+            "  -m, --message[=<msg>...]     Use the given <msg> as the commit 
message. If%n" +
+            "                                multiple -m options are given, 
their values are%n" +
+            "                                concatenated as separate 
paragraphs.%n";
+
+    static final String EXPECTED_USAGE_GITCOMMIT_ANSI = "@|bold,underline 
Usage:|@%n" +
+            "%n" +
+            "Record changes to the repository.%n" +
+            "%n" +
+            "@|bold git-commit|@ [@|yellow -ap|@] [@|yellow --fixup|@=@|italic 
<commit>|@] [@|yellow --squash|@=@|italic <commit>|@] [@|yellow -c|@=@|italic 
<commit>|@]%n" +
+            "           [@|yellow -C|@=@|italic <commit>|@] [@|yellow 
-F|@=@|italic <file>|@] [@|yellow -m|@[=@|italic <msg>|@...]] [@|yellow 
<files>|@...]%n" +
+            "%n" +
+            "@|bold,underline Description:|@%n" +
+            "%n" +
+            "Stores the current contents of the index in a new commit along 
with a log%n" +
+            "message from the user describing the changes.%n" +
+            "%n" +
+            "@|bold,underline Parameters:|@%n" +
+            "      @|yellow <files>|@                 the files to commit%n" +
+            "%n" +
+            "@|bold,underline Options:|@%n" +
+            "  @|yellow -a|@, @|yellow --all|@                   Tell the 
command to automatically stage files%n" +
+            "                                that have been modified and 
deleted, but new%n" +
+            "                                files you have not told Git about 
are not%n" +
+            "                                affected.%n" +
+            "  @|yellow -p|@, @|yellow --patch|@                 Use the 
interactive patch selection interface to%n" +
+            "                                chose which changes to commit%n" +
+            "  @|yellow -C|@, @|yellow --reuse-message|@=@|italic 
<commit|@@|italic >|@%n" +
+            "                              Take an existing commit object, and 
reuse the log%n" +
+            "                                message and the authorship 
information%n" +
+            "                                (including the timestamp) when 
creating the%n" +
+            "                                commit.%n" +
+            "  @|yellow -c|@, @|yellow --reedit-message|@=@|italic 
<commi|@@|italic t>|@%n" +
+            "                              Like -C, but with -c the editor is 
invoked, so%n" +
+            "                                that the user canfurther edit the 
commit%n" +
+            "                                message.%n" +
+            "      @|yellow --fixup|@=@|italic <commit>|@        Construct a 
commit message for use with rebase%n" +
+            "                                --autosquash.%n" +
+            "      @|yellow --squash|@=@|italic <commit>|@       Construct a 
commit message for use with rebase%n" +
+            "                                --autosquash. The commitmessage 
subject line is%n" +
+            "                                taken from the specified commit 
with a prefix%n" +
+            "                                of \"squash! \". Can be used with 
additional%n" +
+            "                                commit message options 
(-m/-c/-C/-F).%n" +
+            "  @|yellow -F|@, @|yellow --file|@=@|italic <file>|@           
Take the commit message from the given file. Use%n" +
+            "                                - to read the message from the 
standard input.%n" +
+            "  @|yellow -m|@, @|yellow --message|@[=@|italic <msg>|@...]     
Use the given <msg> as the commit message. If%n" +
+            "                                multiple -m options are given, 
their values are%n" +
+            "                                concatenated as separate 
paragraphs.%n";
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c2818bec/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 14837d7..d1b1e13 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
          - "remove" - Removed
     -->
     <release version="2.9.0" date="2017-MM-DD" description="GA Release 2.9.0">
+      <action issue="LOG4J2-2011" dev="rpopma" type="update">
+        Replace JCommander command line parser with picocli to let users run 
Log4j2 utility applications without requiring an external dependency.
+      </action>
       <action issue="LOG4J2-2008" dev="rgoers" type="add">
         Support printing multiple StructuredData elements in RFC5424Layout.
       </action>

Reply via email to