From bcc5ca2b878d2d7937face0aacf99d19874998fa Mon Sep 17 00:00:00 2001 From: paulgb Date: Mon, 6 Dec 2010 15:21:15 -0800 Subject: [PATCH] better autocomplete --- .../java/org/apache/hadoop/hive/cli/CliDriver.java | 76 ++++++++++++++++++-- .../apache/hadoop/hive/ql/parse/ParseDriver.java | 5 ++ 2 files changed, 76 insertions(+), 5 deletions(-) diff --git cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java index 82424eb..334f459 100644 --- cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java +++ cli/src/java/org/apache/hadoop/hive/cli/CliDriver.java @@ -32,7 +32,10 @@ import java.util.List; import java.util.Map; import java.util.Set; +import jline.Completor; import jline.ArgumentCompletor; +import jline.ArgumentCompletor.ArgumentDelimiter; +import jline.ArgumentCompletor.AbstractArgumentDelimiter; import jline.ConsoleReader; import jline.History; import jline.SimpleCompletor; @@ -43,6 +46,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.ql.Driver; +import org.apache.hadoop.hive.ql.parse.ParseDriver; +import org.apache.hadoop.hive.ql.exec.FunctionRegistry; import org.apache.hadoop.hive.ql.exec.Utilities; import org.apache.hadoop.hive.ql.exec.Utilities.StreamPrinter; import org.apache.hadoop.hive.ql.processors.CommandProcessor; @@ -281,6 +286,71 @@ public class CliDriver { ss.setIsSilent(saveSilent); } + public static Completor getCommandCompletor () { + // SimpleCompletor matches against a pre-defined wordlist + // We start with an empty wordlist and build it up + SimpleCompletor sc = new SimpleCompletor(new String[0]); + + // We add Hive function names + // For functions that aren't infix operators, we add an open + // parenthesis at the end. + for (String s : FunctionRegistry.getFunctionNames()) { + if (s.matches("[a-z_]+")) { + sc.addCandidateString(s + "("); + } else { + sc.addCandidateString(s); + } + } + + // We add Hive keywords, including lower-cased versions + for (String s : ParseDriver.getKeywords()) { + sc.addCandidateString(s); + sc.addCandidateString(s.toLowerCase()); + } + + // Because we use parentheses in addition to whitespace + // as a keyword delimiter, we need to define a new ArgumentDelimiter + // that recognizes parenthesis as a delimiter. + ArgumentDelimiter delim = new AbstractArgumentDelimiter () { + public boolean isDelimiterChar (String buffer, int pos) { + char c = buffer.charAt(pos); + return (Character.isWhitespace(c) || c == '(' || c == ')' || + c == '[' || c == ']'); + } + }; + + // The ArgumentCompletor allows us to match multiple tokens + // in the same line. + final ArgumentCompletor ac = new ArgumentCompletor(sc, delim); + // By default ArgumentCompletor is in "strict" mode meaning + // a token is only auto-completed if all prior tokens + // match. We don't want that since there are valid tokens + // that are not in our wordlist (eg. table and column names) + ac.setStrict(false); + + // ArgumentCompletor always adds a space after a matched token. + // This is undesirable for function names because a space after + // the opening parenthesis is unnecessary (and uncommon) in Hive. + // We stack a custom Completor on top of our ArgumentCompletor + // to reverse this. + Completor completor = new Completor () { + public int complete (String buffer, int offset, List completions) { + List comp = (List) completions; + int ret = ac.complete(buffer, offset, completions); + // ConsoleReader will do the substitution if and only if there + // is exactly one valid completion, so we ignore other cases. + if (completions.size() == 1) { + if (comp.get(0).endsWith("( ")) { + comp.set(0, comp.get(0).trim()); + } + } + return ret; + } + }; + + return completor; + } + public static void main(String[] args) throws Exception { OptionsProcessor oproc = new OptionsProcessor(); @@ -347,11 +417,7 @@ public class CliDriver { ConsoleReader reader = new ConsoleReader(); reader.setBellEnabled(false); // reader.setDebug(new PrintWriter(new FileWriter("writer.debug", true))); - - List completors = new LinkedList(); - completors.add(new SimpleCompletor(new String[] {"set", "from", "create", "load", "describe", - "quit", "exit"})); - reader.addCompletor(new ArgumentCompletor(completors)); + reader.addCompletor(getCommandCompletor()); String line; final String HISTORYFILE = ".hivehistory"; diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/ParseDriver.java ql/src/java/org/apache/hadoop/hive/ql/parse/ParseDriver.java index a4afc07..d738c48 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/ParseDriver.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/ParseDriver.java @@ -19,6 +19,7 @@ package org.apache.hadoop.hive.ql.parse; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import org.antlr.runtime.ANTLRStringStream; @@ -191,6 +192,10 @@ public class ParseDriver { xlateMap.put("BITWISEXOR", "^"); } + public static Collection getKeywords() { + return xlateMap.values(); + } + private static String xlate(String name) { String ret = xlateMap.get(name); -- 1.6.6.5.g743753