View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.jline;
20  
21  import java.util.Map;
22  import java.util.concurrent.ConcurrentHashMap;
23  
24  import org.apache.maven.api.Constants;
25  import org.apache.maven.api.annotations.Experimental;
26  import org.apache.maven.api.di.Named;
27  import org.apache.maven.api.di.Priority;
28  import org.apache.maven.api.di.Singleton;
29  import org.apache.maven.api.services.MessageBuilder;
30  import org.apache.maven.api.services.MessageBuilderFactory;
31  import org.jline.utils.AttributedStringBuilder;
32  import org.jline.utils.AttributedStyle;
33  import org.jline.utils.StyleResolver;
34  
35  @Experimental
36  @Named
37  @Singleton
38  @Priority(10)
39  public class JLineMessageBuilderFactory implements MessageBuilderFactory {
40      private final StyleResolver resolver;
41  
42      public JLineMessageBuilderFactory() {
43          this.resolver = new MavenStyleResolver();
44      }
45  
46      @Override
47      public boolean isColorEnabled() {
48          return MessageUtils.isColorEnabled();
49      }
50  
51      @Override
52      public int getTerminalWidth() {
53          return MessageUtils.getTerminalWidth();
54      }
55  
56      @Override
57      public MessageBuilder builder() {
58          return builder(64);
59      }
60  
61      @Override
62      public MessageBuilder builder(int size) {
63          return new JlineMessageBuilder(resolver, size);
64      }
65  
66      private static class JlineMessageBuilder implements MessageBuilder {
67          private final StyleResolver styleResolver;
68          private final AttributedStringBuilder builder;
69  
70          private JlineMessageBuilder(StyleResolver styleResolver, int size) {
71              this.styleResolver = styleResolver;
72              this.builder = new AttributedStringBuilder(size);
73          }
74  
75          @Override
76          public MessageBuilder style(String style) {
77              if (MessageUtils.isColorEnabled()) {
78                  builder.style(styleResolver.resolve(style));
79              }
80              return this;
81          }
82  
83          @Override
84          public MessageBuilder resetStyle() {
85              builder.style(AttributedStyle.DEFAULT);
86              return this;
87          }
88  
89          @Override
90          public MessageBuilder append(CharSequence cs) {
91              builder.append(cs);
92              return this;
93          }
94  
95          @Override
96          public MessageBuilder append(CharSequence cs, int start, int end) {
97              builder.append(cs, start, end);
98              return this;
99          }
100 
101         @Override
102         public MessageBuilder append(char c) {
103             builder.append(c);
104             return this;
105         }
106 
107         @Override
108         public MessageBuilder setLength(int length) {
109             builder.setLength(length);
110             return this;
111         }
112 
113         @Override
114         public String build() {
115             return builder.toAnsi(MessageUtils.terminal);
116         }
117 
118         @Override
119         public String toString() {
120             return build();
121         }
122     }
123 
124     private static class MavenStyleResolver extends StyleResolver {
125         private final Map<String, AttributedStyle> styles = new ConcurrentHashMap<>();
126 
127         private MavenStyleResolver() {
128             super(key -> {
129                 String v = System.getProperty(Constants.MAVEN_STYLE_PREFIX + key);
130                 if (v == null) {
131                     v = System.getProperty("style." + key);
132                 }
133                 return v;
134             });
135         }
136 
137         @Override
138         public AttributedStyle resolve(String spec) {
139             return styles.computeIfAbsent(spec, this::doResolve);
140         }
141 
142         @Override
143         public AttributedStyle resolve(String spec, String defaultSpec) {
144             return resolve(defaultSpec != null ? spec + ":-" + defaultSpec : spec);
145         }
146 
147         private AttributedStyle doResolve(String spec) {
148             String def = null;
149             int i = spec.indexOf(":-");
150             if (i != -1) {
151                 String[] parts = spec.split(":-");
152                 spec = parts[0].trim();
153                 def = parts[1].trim();
154             }
155             return super.resolve(spec, def);
156         }
157     }
158 }