Skip to content

Commit

Permalink
Merge branch 'style', fixes #134
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Jun 16, 2017
2 parents b120987 + 97120a6 commit bf6e24c
Show file tree
Hide file tree
Showing 20 changed files with 2,133 additions and 17 deletions.
39 changes: 23 additions & 16 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,12 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.jline</groupId>
<artifactId>jline-style</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>
Expand Down Expand Up @@ -225,6 +231,22 @@

<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<showWarnings>true</showWarnings>
<compilerArgs>
<arg>-Xlint:all,-options</arg>
<arg>-Werror</arg>
<arg>-profile</arg>
<arg>compact1</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
Expand Down Expand Up @@ -298,22 +320,6 @@
</pluginManagement>

<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<showWarnings>true</showWarnings>
<compilerArgs>
<arg>-Xlint:all,-options</arg>
<arg>-Werror</arg>
<arg>-profile</arg>
<arg>compact1</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
Expand Down Expand Up @@ -438,6 +444,7 @@
<module>remote-telnet</module>
<module>jline</module>
<module>demo</module>
<module>style</module>
</modules>

</project>
86 changes: 86 additions & 0 deletions style/pom.xml
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 style/src/main/java/org/jline/style/InterpolationHelper.java
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 style/src/main/java/org/jline/style/MemoryStyleSource.java
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);
}
}
Loading

0 comments on commit bf6e24c

Please sign in to comment.