--- /dev/null 2015-04-26 06:51:08.003313989 -0700 +++ new/jdk/src/jdk.jline/share/classes/jdk/internal/jline/internal/TerminalLineSettings.java 2015-06-18 03:04:53.123725108 -0700 @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2002-2012, 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 jdk.internal.jline.internal; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.MessageFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static jdk.internal.jline.internal.Preconditions.checkNotNull; + +/** + * Provides access to terminal line settings via stty. + * + * @author Marc Prud'hommeaux + * @author Dale Kemp + * @author Jason Dillon + * @author Jean-Baptiste Onofr\u00E9 + * @since 2.0 + */ +public final class TerminalLineSettings +{ + public static final String JLINE_STTY = "jline.stty"; + + public static final String DEFAULT_STTY = "stty"; + + public static final String JLINE_SH = "jline.sh"; + + public static final String DEFAULT_SH = "sh"; + + private String sttyCommand; + + private String shCommand; + + private String config; + private String initialConfig; + + private long configLastFetched; + + public TerminalLineSettings() throws IOException, InterruptedException { + sttyCommand = Configuration.getString(JLINE_STTY, DEFAULT_STTY); + shCommand = Configuration.getString(JLINE_SH, DEFAULT_SH); + initialConfig = get("-g").trim(); + config = get("-a"); + configLastFetched = System.currentTimeMillis(); + + Log.debug("Config: ", config); + + // sanity check + if (config.length() == 0) { + throw new IOException(MessageFormat.format("Unrecognized stty code: {0}", config)); + } + } + + public String getConfig() { + return config; + } + + public void restore() throws IOException, InterruptedException { + set(initialConfig); + } + + public String get(final String args) throws IOException, InterruptedException { + return stty(args); + } + + public void set(final String args) throws IOException, InterruptedException { + stty(args); + } + + /** + *
+ * Get the value of a stty property, including the management of a cache. + *
+ * + * @param name the stty property. + * @return the stty property value. + */ + public int getProperty(String name) { + checkNotNull(name); + long currentTime = System.currentTimeMillis(); + try { + // tty properties are cached so we don't have to worry too much about getting term width/height + if (config == null || currentTime - configLastFetched > 1000) { + config = get("-a"); + } + } catch (Exception e) { + if (e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + } + Log.debug("Failed to query stty ", name, "\n", e); + if (config == null) { + return -1; + } + } + + // always update the last fetched time and try to parse the output + if (currentTime - configLastFetched > 1000) { + configLastFetched = currentTime; + } + + return getProperty(name, config); + } + + /** + *+ * Parses a stty output (provided by stty -a) and return the value of a given property. + *
+ * + * @param name property name. + * @param stty string resulting of stty -a execution. + * @return value of the given property. + */ + protected static int getProperty(String name, String stty) { + // try the first kind of regex + Pattern pattern = Pattern.compile(name + "\\s+=\\s+(.*?)[;\\n\\r]"); + Matcher matcher = pattern.matcher(stty); + if (!matcher.find()) { + // try a second kind of regex + pattern = Pattern.compile(name + "\\s+([^;]*)[;\\n\\r]"); + matcher = pattern.matcher(stty); + if (!matcher.find()) { + // try a second try of regex + pattern = Pattern.compile("(\\S*)\\s+" + name); + matcher = pattern.matcher(stty); + if (!matcher.find()) { + return -1; + } + } + } + return parseControlChar(matcher.group(1)); + } + + private static int parseControlChar(String str) { + // under + if ("