View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements. See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache license, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License. You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the license for the specific language governing permissions and
    15   * limitations under the license.
    16   */
    17  package org.apache.logging.log4j.core.pattern;
    18
    19  import java.util.Arrays;
    20  import java.util.HashMap;
    21  import java.util.Locale;
    22  import java.util.Map;
    23
    24  import org.apache.logging.log4j.core.util.Patterns;
    25  import org.apache.logging.log4j.util.EnglishEnums;
    26
    27  /**
    28   * Converts text into ANSI escape sequences.
    29   * <p>
    30   * The names for colors and attributes are standard, but the exact shade/hue/value of colors are not, and depend on the
    31   * device used to display them.
    32   * </p>
    33   */
    34  public enum AnsiEscape {
    35
    36      /**
    37       * The Control Sequence Introducer (or Control Sequence Initiator).
    38       * <p>
    39       * Most sequences are more than two characters and start with the characters ESC and [ (the left bracket).
    40       * </p>
    41       */
    42      CSI("\u001b["),
    43
    44      /**
    45       * Escape suffix.
    46       */
    47      SUFFIX("m"),
    48
    49      /**
    50       * Escape separator.
    51       */
    52      SEPARATOR(";"),
    53
    54      /**
    55       * Normal general attribute.
    56       */
    57      NORMAL("0"),
    58
    59      /**
    60       * Bright general attribute.
    61       */
    62      BRIGHT("1"),
    63
    64      /**
    65       * Dim general attribute.
    66       */
    67      DIM("2"),
    68
    69      /**
    70       * Underline general attribute.
    71       */
    72      UNDERLINE("3"),
    73
    74      /**
    75       * Blink general attribute.
    76       */
    77      BLINK("5"),
    78
    79      /**
    80       * Reverse general attribute.
    81       */
    82      REVERSE("7"),
    83
    84      /**
    85       * Normal general attribute.
    86       */
    87      HIDDEN("8"),
    88
    89      /**
    90       * Black foreground color.
    91       */
    92      BLACK("30"),
    93
    94      /**
    95       * Black foreground color.
    96       */
    97      FG_BLACK("30"),
    98
    99      /**
    100      * Red foreground color.
    101      */
    102     RED("31"),
    103
    104     /**
    105      * Red foreground color.
    106      */
    107     FG_RED("31"),
    108
    109     /**
    110      * Green foreground color.
    111      */
    112     GREEN("32"),
    113
    114     /**
    115      * Green foreground color.
    116      */
    117     FG_GREEN("32"),
    118
    119     /**
    120      * Yellow foreground color.
    121      */
    122     YELLOW("33"),
    123
    124     /**
    125      * Yellow foreground color.
    126      */
    127     FG_YELLOW("33"),
    128
    129     /**
    130      * Blue foreground color.
    131      */
    132     BLUE("34"),
    133
    134     /**
    135      * Blue foreground color.
    136      */
    137     FG_BLUE("34"),
    138
    139     /**
    140      * Magenta foreground color.
    141      */
    142     MAGENTA("35"),
    143
    144     /**
    145      * Magenta foreground color.
    146      */
    147     FG_MAGENTA("35"),
    148
    149     /**
    150      * Cyan foreground color.
    151      */
    152     CYAN("36"),
    153
    154     /**
    155      * Cyan foreground color.
    156      */
    157     FG_CYAN("36"),
    158
    159     /**
    160      * White foreground color.
    161      */
    162     WHITE("37"),
    163
    164     /**
    165      * White foreground color.
    166      */
    167     FG_WHITE("37"),
    168
    169     /**
    170      * Default foreground color.
    171      */
    172     DEFAULT("39"),
    173
    174     /**
    175      * Default foreground color.
    176      */
    177     FG_DEFAULT("39"),
    178
    179     /**
    180      * Black background color.
    181      */
    182     BG_BLACK("40"),
    183
    184     /**
    185      * Red background color.
    186      */
    187     BG_RED("41"),
    188
    189     /**
    190      * Green background color.
    191      */
    192     BG_GREEN("42"),
    193
    194     /**
    195      * Yellow background color.
    196      */
    197     BG_YELLOW("43"),
    198
    199     /**
    200      * Blue background color.
    201      */
    202     BG_BLUE("44"),
    203
    204     /**
    205      * Magenta background color.
    206      */
    207     BG_MAGENTA("45"),
    208
    209     /**
    210      * Cyan background color.
    211      */
    212     BG_CYAN("46"),
    213
    214     /**
    215      * White background color.
    216      */
    217     BG_WHITE("47");
    218
    219     private final String code;
    220
    221     private AnsiEscape(final String code) {
    222         this.code = code;
    223     }
    224
    225     /**
    226      * Gets the default style.
    227      *
    228      * @return the default style
    229      */
    230     public static String getDefaultStyle() {
    231         return CSI.getCode() + SUFFIX.getCode();
    232     }
    233
    234     /**
    235      * Gets the escape code.
    236      *
    237      * @return the escape code.
    238      */
    239     public String getCode() {
    240         return code;
    241     }
    242
    243     /**
    244      * Creates a Map from a source array where values are ANSI escape sequences. The format is:
    245      *
    246      * <pre>
    247      * Key1=Value, Key2=Value, ...
    248      * </pre>
    249      *
    250      * For example:
    251      *
    252      * <pre>
    253      * ERROR=red bold, WARN=yellow bold, INFO=green, ...
    254      * </pre>
    255      *
    256      * You can use whitespace around the comma and equal sign. The names in values MUST come from the
    257      * {@linkplain AnsiEscape} enum, case is normalized to upper-case internally.
    258      *
    259      * @param values the source string to parse.
    260      * @param dontEscapeKeys do not escape these keys, leave the values as is in the map
    261      * @return a new map
    262      */
    263     public static Map<String, String> createMap(final String values, final String[] dontEscapeKeys) {
    264         return createMap(values.split(Patterns.COMMA_SEPARATOR), dontEscapeKeys);
    265     }
    266
    267     /**
    268      * Creates a Map from a source array where values are ANSI escape sequences. Each array entry must be in the format:
    269      *
    270      * <pre>
    271      * Key1 = Value
    272      * </pre>
    273      *
    274      * For example:
    275      *
    276      * <pre>
    277      * ERROR=red bold
    278      * </pre>
    279      *
    280      * You can use whitespace around the equal sign and between the value elements. The names in values MUST come from
    281      * the {@linkplain AnsiEscape} enum, case is normalized to upper-case internally.
    282      *
    283      * @param values
    284      *            the source array to parse.
    285      * @param dontEscapeKeys
    286      *            do not escape these keys, leave the values as is in the map
    287      * @return a new map
    288      */
    289     public static Map<String, String> createMap(final String[] values, final String[] dontEscapeKeys) {
    290         final String[] sortedIgnoreKeys = dontEscapeKeys != null ? dontEscapeKeys.clone() : new String[0];
    291         Arrays.sort(sortedIgnoreKeys);
    292         final Map<String, String> map = new HashMap<String, String>();
    293         for (final String string : values) {
    294             final String[] keyValue = string.split(Patterns.toWhitespaceSeparator("="));
    295             if (keyValue.length > 1) {
    296                 final String key = keyValue[0].toUpperCase(Locale.ENGLISH);
    297                 final String value = keyValue[1];
    298                 final boolean escape = Arrays.binarySearch(sortedIgnoreKeys, key) < 0;
    299                 map.put(key, escape ? createSequence(value.split("\\s")) : value);
    300             }
    301         }
    302         return map;
    303     }
    304
    305     /**
    306      * Creates an ANSI escape sequence from the given {@linkplain AnsiEscape} names.
    307      *
    308      * @param names
    309      *            {@linkplain AnsiEscape} names.
    310      * @return An ANSI escape sequence.
    311      */
    312     public static String createSequence(final String... names) {
    313         if (names == null) {
    314             return getDefaultStyle();
    315         }
    316         final StringBuilder sb = new StringBuilder(AnsiEscape.CSI.getCode());
    317         boolean first = true;
    318         for (final String name : names) {
    319             try {
    320                 final AnsiEscape escape = EnglishEnums.valueOf(AnsiEscape.class, name.trim());
    321                 if (!first) {
    322                     sb.append(AnsiEscape.SEPARATOR.getCode());
    323                 }
    324                 first = false;
    325                 sb.append(escape.getCode());
    326             } catch (final Exception ex) {
    327                 // Ignore the error.
    328             }
    329         }
    330         sb.append(AnsiEscape.SUFFIX.getCode());
    331         return sb.toString();
    332     }
    333
    334 }