-
Notifications
You must be signed in to change notification settings - Fork 218
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
2,133 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
Copyright (c) 2002-2016, the original author or authors. | ||
This software is distributable under the BSD license. See the terms of the | ||
BSD license in the documentation provided with this software. | ||
http://www.opensource.org/licenses/bsd-license.php | ||
--> | ||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
|
||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.jline</groupId> | ||
<artifactId>jline-parent</artifactId> | ||
<version>3.4.0-SNAPSHOT</version> | ||
</parent> | ||
|
||
<artifactId>jline-style</artifactId> | ||
<name>JLine Style</name> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.jline</groupId> | ||
<artifactId>jline-terminal</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>com.google.code.findbugs</groupId> | ||
<artifactId>jsr305</artifactId> | ||
<version>3.0.2</version> | ||
<optional>true</optional> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>org.codehaus.groovy</groupId> | ||
<artifactId>groovy-all</artifactId> | ||
<!-- keep in sync with groovy-eclipse-batch version --> | ||
<version>2.4.4</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<dependencies> | ||
<dependency> | ||
<groupId>org.codehaus.groovy</groupId> | ||
<artifactId>groovy-eclipse-compiler</artifactId> | ||
<version>2.9.2-01</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.codehaus.groovy</groupId> | ||
<artifactId>groovy-eclipse-batch</artifactId> | ||
<version>2.4.3-01</version> | ||
</dependency> | ||
</dependencies> | ||
<configuration> | ||
<compilerId>groovy-eclipse-compiler</compilerId> | ||
<showWarnings>true</showWarnings> | ||
<compilerArgs> | ||
<arg>-Xlint:all,-options</arg> | ||
<!-- groovy-eclipse compiler does not support these options --> | ||
<!--<arg>-Werror</arg>--> | ||
<!--<arg>-profile</arg>--> | ||
<!--<arg>compact1</arg>--> | ||
</compilerArgs> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
122 changes: 122 additions & 0 deletions
122
style/src/main/java/org/jline/style/InterpolationHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
* Copyright (c) 2002-2017, the original author or authors. | ||
* | ||
* This software is distributable under the BSD license. See the terms of the | ||
* BSD license in the documentation provided with this software. | ||
* | ||
* http://www.opensource.org/licenses/bsd-license.php | ||
*/ | ||
package org.jline.style; | ||
|
||
import java.util.function.Function; | ||
|
||
/** | ||
* Interpolation. | ||
* Borrowed and adapted from Apache Felix Utils module. | ||
*/ | ||
public final class InterpolationHelper { | ||
|
||
private InterpolationHelper() { | ||
} | ||
|
||
private static final char ESCAPE_CHAR = '\\'; | ||
private static final String DELIM_START = "@{"; | ||
private static final String DELIM_STOP = "}"; | ||
private static final String MARKER = "@__"; | ||
|
||
|
||
public static String substVars(String val, | ||
Function<String, String> callback, | ||
boolean defaultsToEmptyString) | ||
throws IllegalArgumentException { | ||
return unescape(doSubstVars(val, callback, defaultsToEmptyString)); | ||
} | ||
|
||
private static String doSubstVars(String val, | ||
Function<String, String> callback, | ||
boolean defaultsToEmptyString) | ||
throws IllegalArgumentException { | ||
// Assume we have a value that is something like: | ||
// "leading @{foo.@{bar}} middle @{baz} trailing" | ||
|
||
// Find the first ending '}' variable delimiter, which | ||
// will correspond to the first deepest nested variable | ||
// placeholder. | ||
int startDelim; | ||
int stopDelim = -1; | ||
do { | ||
stopDelim = val.indexOf(DELIM_STOP, stopDelim + 1); | ||
while (stopDelim > 0 && val.charAt(stopDelim - 1) == ESCAPE_CHAR) { | ||
stopDelim = val.indexOf(DELIM_STOP, stopDelim + 1); | ||
} | ||
|
||
// Find the matching starting "@{" variable delimiter | ||
// by looping until we find a start delimiter that is | ||
// greater than the stop delimiter we have found. | ||
startDelim = val.indexOf(DELIM_START); | ||
while (stopDelim >= 0) { | ||
int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length()); | ||
if ((idx < 0) || (idx > stopDelim)) { | ||
break; | ||
} else if (idx < stopDelim) { | ||
startDelim = idx; | ||
} | ||
} | ||
} | ||
while (startDelim >= 0 && stopDelim >= 0 && stopDelim < startDelim + DELIM_START.length()); | ||
|
||
// If we do not have a start or stop delimiter, then just | ||
// return the existing value. | ||
if ((startDelim < 0) || (stopDelim < 0)) { | ||
return val; | ||
} | ||
|
||
// At this point, we have found a variable placeholder so | ||
// we must perform a variable substitution on it. | ||
// Using the start and stop delimiter indices, extract | ||
// the first, deepest nested variable placeholder. | ||
String variable = val.substring(startDelim + DELIM_START.length(), stopDelim); | ||
|
||
String substValue = null; | ||
// Get the value of the deepest nested variable placeholder. | ||
if (variable.length() > 0 && callback != null) { | ||
substValue = callback.apply(variable); | ||
} | ||
|
||
if (substValue == null) { | ||
if (defaultsToEmptyString) { | ||
substValue = ""; | ||
} else { | ||
// alters the original token to avoid infinite recursion | ||
// altered tokens are reverted in unescape() | ||
substValue = MARKER + "{" + variable + "}"; | ||
} | ||
} | ||
|
||
// Append the leading characters, the substituted value of | ||
// the variable, and the trailing characters to get the new | ||
// value. | ||
val = val.substring(0, startDelim) + substValue + val.substring(stopDelim + DELIM_STOP.length(), val.length()); | ||
|
||
// Now perform substitution again, since there could still | ||
// be substitutions to make. | ||
val = doSubstVars(val, callback, defaultsToEmptyString); | ||
|
||
// Return the value. | ||
return val; | ||
} | ||
|
||
private static String unescape(String val) { | ||
val = val.replaceAll(MARKER, "@"); | ||
int escape = val.indexOf(ESCAPE_CHAR); | ||
while (escape >= 0 && escape < val.length() - 1) { | ||
char c = val.charAt(escape + 1); | ||
if (c == '{' || c == '}' || c == ESCAPE_CHAR) { | ||
val = val.substring(0, escape) + val.substring(escape + 1); | ||
} | ||
escape = val.indexOf(ESCAPE_CHAR, escape + 1); | ||
} | ||
return val; | ||
} | ||
|
||
} |
103 changes: 103 additions & 0 deletions
103
style/src/main/java/org/jline/style/MemoryStyleSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
/* | ||
* Copyright (c) 2002-2017, the original author or authors. | ||
* | ||
* This software is distributable under the BSD license. See the terms of the | ||
* BSD license in the documentation provided with this software. | ||
* | ||
* http://www.opensource.org/licenses/bsd-license.php | ||
*/ | ||
package org.jline.style; | ||
|
||
import javax.annotation.Nullable; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
/** | ||
* In-memory {@link StyleSource}. | ||
* | ||
* @since 3.4 | ||
*/ | ||
public class MemoryStyleSource | ||
implements StyleSource { | ||
private static final Logger log = Logger.getLogger(MemoryStyleSource.class.getName()); | ||
|
||
private final Map<String, Map<String, String>> backing = new ConcurrentHashMap<>(); | ||
|
||
@Nullable | ||
@Override | ||
public String get(final String group, final String name) { | ||
String style = null; | ||
Map<String, String> styles = backing.get(group); | ||
if (styles != null) { | ||
style = styles.get(name); | ||
} | ||
|
||
if (log.isLoggable(Level.FINEST)) { | ||
log.finest(String.format("Get: [%s] %s -> %s", group, name, style)); | ||
} | ||
|
||
return style; | ||
} | ||
|
||
@Override | ||
public void set(final String group, final String name, final String style) { | ||
requireNonNull(group); | ||
requireNonNull(name); | ||
requireNonNull(style); | ||
backing.computeIfAbsent(group, k -> new ConcurrentHashMap<>()).put(name, style); | ||
|
||
if (log.isLoggable(Level.FINEST)) { | ||
log.finest(String.format("Set: [%s] %s -> %s", group, name, style)); | ||
} | ||
} | ||
|
||
@Override | ||
public void remove(final String group) { | ||
requireNonNull(group); | ||
if (backing.remove(group) != null) { | ||
if (log.isLoggable(Level.FINEST)) { | ||
log.finest(String.format("Removed: [%s]", group)); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void remove(final String group, final String name) { | ||
requireNonNull(group); | ||
requireNonNull(name); | ||
Map<String, String> styles = backing.get(group); | ||
if (styles != null) { | ||
styles.remove(name); | ||
|
||
if (log.isLoggable(Level.FINEST)) { | ||
log.finest(String.format("Removed: [%s] %s", group, name)); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
backing.clear(); | ||
log.finest("Cleared"); | ||
} | ||
|
||
@Override | ||
public Iterable<String> groups() { | ||
return Collections.unmodifiableSet(backing.keySet()); | ||
} | ||
|
||
@Override | ||
public Map<String, String> styles(final String group) { | ||
requireNonNull(group); | ||
Map<String, String> result = backing.get(group); | ||
if (result == null) { | ||
result = Collections.emptyMap(); | ||
} | ||
return Collections.unmodifiableMap(result); | ||
} | ||
} |
Oops, something went wrong.