You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by mo...@apache.org on 2017/04/17 05:18:43 UTC

[2/3] zeppelin git commit: [ZEPPELIN-2297] improvements to jdbc autocompleter

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/jdbc/src/test/java/org/apache/zeppelin/jdbc/SqlCompleterTest.java
----------------------------------------------------------------------
diff --git a/jdbc/src/test/java/org/apache/zeppelin/jdbc/SqlCompleterTest.java b/jdbc/src/test/java/org/apache/zeppelin/jdbc/SqlCompleterTest.java
index 567e975..999f7de 100644
--- a/jdbc/src/test/java/org/apache/zeppelin/jdbc/SqlCompleterTest.java
+++ b/jdbc/src/test/java/org/apache/zeppelin/jdbc/SqlCompleterTest.java
@@ -14,18 +14,26 @@
  */
 package org.apache.zeppelin.jdbc;
 
-import com.google.common.base.Joiner;
-import com.mockrunner.jdbc.BasicJDBCTestCaseAdapter;
-import jline.console.completer.ArgumentCompleter;
-import jline.console.completer.Completer;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.zeppelin.completer.CompletionType;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.*;
+import com.google.common.base.Joiner;
+import jline.console.completer.ArgumentCompleter;
 
 import static com.google.common.collect.Sets.newHashSet;
 import static org.junit.Assert.assertEquals;
@@ -34,18 +42,18 @@ import static org.junit.Assert.assertTrue;
 /**
  * SQL completer unit tests
  */
-public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
+public class SqlCompleterTest {
 
   public class CompleterTester {
 
-    private Completer completer;
+    private SqlCompleter completer;
 
     private String buffer;
     private int fromCursor;
     private int toCursor;
-    private Set<String> expectedCompletions;
+    private Set<InterpreterCompletion> expectedCompletions;
 
-    public CompleterTester(Completer completer) {
+    public CompleterTester(SqlCompleter completer) {
       this.completer = completer;
     }
 
@@ -64,7 +72,7 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
       return this;
     }
 
-    public CompleterTester expect(Set<String> expectedCompletions) {
+    public CompleterTester expect(Set<InterpreterCompletion> expectedCompletions) {
       this.expectedCompletions = expectedCompletions;
       return this;
     }
@@ -75,9 +83,13 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
       }
     }
 
-    private void expectedCompletions(String buffer, int cursor, Set<String> expected) {
+    private void expectedCompletions(String buffer, int cursor,
+        Set<InterpreterCompletion> expected) {
+      if (StringUtils.isNotEmpty(buffer) && buffer.length() > cursor) {
+        buffer = buffer.substring(0, cursor + 1);
+      }
 
-      ArrayList<CharSequence> candidates = new ArrayList<>();
+      List<InterpreterCompletion> candidates = new ArrayList<>();
 
       completer.complete(buffer, cursor, candidates);
 
@@ -85,11 +97,15 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
 
       logger.info(explain);
 
-      assertEquals("Buffer [" + buffer.replace(" ", ".") + "] and Cursor[" + cursor + "] "
-              + explain, expected, newHashSet(candidates));
+      Assert.assertEquals("Buffer [" + buffer.replace(" ", ".") + "] and Cursor[" + cursor + "] "
+          + explain, expected, newHashSet(candidates));
     }
 
-    private String explain(String buffer, int cursor, ArrayList<CharSequence> candidates) {
+    private String explain(String buffer, int cursor, List<InterpreterCompletion> candidates) {
+      List<String> cndidateStrings = new ArrayList<>();
+      for (InterpreterCompletion candidate : candidates) {
+        cndidateStrings.add(candidate.getValue());
+      }
       StringBuffer sb = new StringBuffer();
 
       for (int i = 0; i <= Math.max(cursor, buffer.length()); i++) {
@@ -109,7 +125,7 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
           sb.append(")");
         }
       }
-      sb.append(" >> [").append(Joiner.on(",").join(candidates)).append("]");
+      sb.append(" >> [").append(Joiner.on(",").join(cndidateStrings)).append("]");
 
       return sb.toString();
     }
@@ -122,7 +138,7 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
   private CompleterTester tester;
 
   private ArgumentCompleter.WhitespaceArgumentDelimiter delimiter =
-          new ArgumentCompleter.WhitespaceArgumentDelimiter();
+      new ArgumentCompleter.WhitespaceArgumentDelimiter();
 
   private SqlCompleter sqlCompleter = new SqlCompleter();
 
@@ -178,7 +194,7 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
   }
 
   @Test
-  public void testFindAliasesInSQL_Simple(){
+  public void testFindAliasesInSQL_Simple() {
     String sql = "select * from prod_emart.financial_account a";
     Map<String, String> res = sqlCompleter.findAliasesInSQL(delimiter.delimit(sql, 0).getArguments());
     assertEquals(1, res.size());
@@ -186,7 +202,7 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
   }
 
   @Test
-  public void testFindAliasesInSQL_Two(){
+  public void testFindAliasesInSQL_Two() {
     String sql = "select * from prod_dds.financial_account a, prod_dds.customer b";
     Map<String, String> res = sqlCompleter.findAliasesInSQL(sqlCompleter.getSqlDelimiter().delimit(sql, 0).getArguments());
     assertEquals(2, res.size());
@@ -195,7 +211,7 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
   }
 
   @Test
-  public void testFindAliasesInSQL_WrongTables(){
+  public void testFindAliasesInSQL_WrongTables() {
     String sql = "select * from prod_ddsxx.financial_account a, prod_dds.customerxx b";
     Map<String, String> res = sqlCompleter.findAliasesInSQL(sqlCompleter.getSqlDelimiter().delimit(sql, 0).getArguments());
     assertEquals(0, res.size());
@@ -205,116 +221,145 @@ public class SqlCompleterTest extends BasicJDBCTestCaseAdapter {
   public void testCompleteName_Empty() {
     String buffer = "";
     int cursor = 0;
-    List<CharSequence> candidates = new ArrayList<>();
+    List<InterpreterCompletion> candidates = new ArrayList<>();
     Map<String, String> aliases = new HashMap<>();
-    sqlCompleter.completeName(buffer, cursor, candidates, aliases, false);
-    assertEquals(9, candidates.size());
-    assertTrue(candidates.contains("prod_dds"));
-    assertTrue(candidates.contains("prod_emart"));
-    assertTrue(candidates.contains("SUM"));
-    assertTrue(candidates.contains("SUBSTRING"));
-    assertTrue(candidates.contains("SUBCLASS_ORIGIN"));
-    assertTrue(candidates.contains("SELECT"));
-    assertTrue(candidates.contains("ORDER"));
-    assertTrue(candidates.contains("LIMIT"));
-    assertTrue(candidates.contains("FROM"));
+    sqlCompleter.completeName(buffer, cursor, candidates, aliases, true);
+    assertEquals(17, candidates.size());
+    assertTrue(candidates.contains(new InterpreterCompletion("prod_dds", "prod_dds", CompletionType.schema.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("prod_emart", "prod_emart", CompletionType.schema.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("SUM", "SUM", CompletionType.keyword.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("SUBSTRING", "SUBSTRING", CompletionType.keyword.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("SUBCLASS_ORIGIN", "SUBCLASS_ORIGIN", CompletionType.keyword.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("SELECT", "SELECT", CompletionType.keyword.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("ORDER", "ORDER", CompletionType.keyword.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("LIMIT", "LIMIT", CompletionType.keyword.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("FROM", "FROM", CompletionType.keyword.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("financial_account", "financial_account", CompletionType.table.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("customer", "customer", CompletionType.table.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_id", "account_id", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("customer_rk", "customer_rk", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_rk", "account_rk", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("name", "name", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("birth_dt", "birth_dt", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("balance_amt", "balance_amt", CompletionType.column.name())));
   }
 
   @Test
   public void testCompleteName_SimpleSchema() {
     String buffer = "prod_";
     int cursor = 3;
-    List<CharSequence> candidates = new ArrayList<>();
+    List<InterpreterCompletion> candidates = new ArrayList<>();
     Map<String, String> aliases = new HashMap<>();
     sqlCompleter.completeName(buffer, cursor, candidates, aliases, false);
     assertEquals(2, candidates.size());
-    assertTrue(candidates.contains("prod_dds"));
-    assertTrue(candidates.contains("prod_emart"));
+    assertTrue(candidates.contains(new InterpreterCompletion("prod_dds", "prod_dds", CompletionType.schema.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("prod_emart", "prod_emart", CompletionType.schema.name())));
   }
 
   @Test
   public void testCompleteName_SimpleTable() {
     String buffer = "prod_dds.fin";
     int cursor = 11;
-    List<CharSequence> candidates = new ArrayList<>();
+    List<InterpreterCompletion> candidates = new ArrayList<>();
     Map<String, String> aliases = new HashMap<>();
     sqlCompleter.completeName(buffer, cursor, candidates, aliases, false);
     assertEquals(1, candidates.size());
-    assertTrue(candidates.contains("financial_account "));
+    assertTrue(candidates.contains(new InterpreterCompletion("financial_account", "financial_account", CompletionType.table.name())));
   }
 
   @Test
   public void testCompleteName_SimpleColumn() {
     String buffer = "prod_dds.financial_account.acc";
     int cursor = 30;
-    List<CharSequence> candidates = new ArrayList<>();
+    List<InterpreterCompletion> candidates = new ArrayList<>();
     Map<String, String> aliases = new HashMap<>();
     sqlCompleter.completeName(buffer, cursor, candidates, aliases, true);
     assertEquals(2, candidates.size());
-    assertTrue(candidates.contains("account_rk"));
-    assertTrue(candidates.contains("account_id"));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_rk", "account_rk", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_id", "account_id", CompletionType.column.name())));
   }
 
   @Test
   public void testCompleteName_WithAlias() {
     String buffer = "a.acc";
     int cursor = 4;
-    List<CharSequence> candidates = new ArrayList<>();
+    List<InterpreterCompletion> candidates = new ArrayList<>();
     Map<String, String> aliases = new HashMap<>();
     aliases.put("a", "prod_dds.financial_account");
     sqlCompleter.completeName(buffer, cursor, candidates, aliases, true);
     assertEquals(2, candidates.size());
-    assertTrue(candidates.contains("account_rk"));
-    assertTrue(candidates.contains("account_id"));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_rk", "account_rk", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_id", "account_id", CompletionType.column.name())));
   }
 
   @Test
   public void testCompleteName_WithAliasAndPoint() {
     String buffer = "a.";
     int cursor = 2;
-    List<CharSequence> candidates = new ArrayList<>();
+    List<InterpreterCompletion> candidates = new ArrayList<>();
     Map<String, String> aliases = new HashMap<>();
     aliases.put("a", "prod_dds.financial_account");
     sqlCompleter.completeName(buffer, cursor, candidates, aliases, true);
     assertEquals(2, candidates.size());
-    assertTrue(candidates.contains("account_rk"));
-    assertTrue(candidates.contains("account_id"));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_rk", "account_rk", CompletionType.column.name())));
+    assertTrue(candidates.contains(new InterpreterCompletion("account_id", "account_id", CompletionType.column.name())));
   }
 
+  @Test
   public void testSchemaAndTable() {
-    String buffer = "select * from prod_v_emart.fi";
-    tester.buffer(buffer).from(15).to(26).expect(newHashSet("prod_v_emart ")).test();
-    tester.buffer(buffer).from(27).to(29).expect(newHashSet("financial_account ")).test();
+    String buffer = "select * from prod_emart.fi";
+    tester.buffer(buffer).from(19).to(23).expect(newHashSet(new InterpreterCompletion("prod_emart ", "prod_emart ", CompletionType.schema.name()))).test();
+    tester.buffer(buffer).from(25).to(27).expect(newHashSet(new InterpreterCompletion("financial_account ", "financial_account ", CompletionType.table.name()))).test();
   }
 
   @Test
   public void testEdges() {
     String buffer = "  ORDER  ";
-    tester.buffer(buffer).from(0).to(7).expect(newHashSet("ORDER ")).test();
-    tester.buffer(buffer).from(8).to(15).expect(newHashSet("ORDER", "SUBCLASS_ORIGIN", "SUBSTRING",
-            "prod_emart", "LIMIT", "SUM", "prod_dds", "SELECT", "FROM")).test();
+    tester.buffer(buffer).from(2).to(6).expect(newHashSet(new InterpreterCompletion("ORDER ", "ORDER ", CompletionType.keyword.name()))).test();
+    tester.buffer(buffer).from(0).to(1).expect(newHashSet(
+        new InterpreterCompletion("ORDER", "ORDER", CompletionType.keyword.name()),
+        new InterpreterCompletion("SUBCLASS_ORIGIN", "SUBCLASS_ORIGIN", CompletionType.keyword.name()),
+        new InterpreterCompletion("SUBSTRING", "SUBSTRING", CompletionType.keyword.name()),
+        new InterpreterCompletion("prod_emart", "prod_emart", CompletionType.schema.name()),
+        new InterpreterCompletion("LIMIT", "LIMIT", CompletionType.keyword.name()),
+        new InterpreterCompletion("SUM", "SUM", CompletionType.keyword.name()),
+        new InterpreterCompletion("prod_dds", "prod_dds", CompletionType.schema.name()),
+        new InterpreterCompletion("SELECT", "SELECT", CompletionType.keyword.name()),
+        new InterpreterCompletion("FROM", "FROM", CompletionType.keyword.name()),
+        new InterpreterCompletion("financial_account", "financial_account", CompletionType.table.name()),
+        new InterpreterCompletion("customer", "customer", CompletionType.table.name()),
+        new InterpreterCompletion("account_rk", "account_rk", CompletionType.column.name()),
+        new InterpreterCompletion("account_id", "account_id", CompletionType.column.name()),
+        new InterpreterCompletion("customer_rk", "customer_rk", CompletionType.column.name()),
+        new InterpreterCompletion("name", "name", CompletionType.column.name()),
+        new InterpreterCompletion("birth_dt", "birth_dt", CompletionType.column.name()),
+        new InterpreterCompletion("balance_amt", "balance_amt", CompletionType.column.name())
+    )).test();
   }
 
   @Test
   public void testMultipleWords() {
     String buffer = "SELE FRO LIM";
-    tester.buffer(buffer).from(0).to(4).expect(newHashSet("SELECT ")).test();
-    tester.buffer(buffer).from(5).to(8).expect(newHashSet("FROM ")).test();
-    tester.buffer(buffer).from(9).to(12).expect(newHashSet("LIMIT ")).test();
+    tester.buffer(buffer).from(1).to(3).expect(newHashSet(new InterpreterCompletion("SELECT ", "SELECT ", CompletionType.keyword.name()))).test();
+    tester.buffer(buffer).from(6).to(7).expect(newHashSet(new InterpreterCompletion("FROM ", "FROM ", CompletionType.keyword.name()))).test();
+    tester.buffer(buffer).from(9).to(12).expect(newHashSet(new InterpreterCompletion("LIMIT ", "LIMIT ", CompletionType.keyword.name()))).test();
   }
 
   @Test
   public void testMultiLineBuffer() {
     String buffer = " \n SELE\nFRO";
-    tester.buffer(buffer).from(0).to(7).expect(newHashSet("SELECT ")).test();
-    tester.buffer(buffer).from(8).to(11).expect(newHashSet("FROM ")).test();
+    tester.buffer(buffer).from(4).to(6).expect(newHashSet(new InterpreterCompletion("SELECT ", "SELECT ", CompletionType.keyword.name()))).test();
+    tester.buffer(buffer).from(9).to(11).expect(newHashSet(new InterpreterCompletion("FROM ", "FROM ", CompletionType.keyword.name()))).test();
   }
 
   @Test
   public void testMultipleCompletionSuggestions() {
     String buffer = "SU";
-    tester.buffer(buffer).from(0).to(2).expect(newHashSet("SUBCLASS_ORIGIN", "SUM", "SUBSTRING"))
-            .test();
+    tester.buffer(buffer).from(1).to(2).expect(newHashSet(
+        new InterpreterCompletion("SUBCLASS_ORIGIN", "SUBCLASS_ORIGIN", CompletionType.keyword.name()),
+        new InterpreterCompletion("SUM", "SUM", CompletionType.keyword.name()),
+        new InterpreterCompletion("SUBSTRING", "SUBSTRING", CompletionType.keyword.name()))
+    ).test();
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java
----------------------------------------------------------------------
diff --git a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java
index 5969717..6b68d28 100755
--- a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java
+++ b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java
@@ -95,7 +95,8 @@ public class KylinInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/lens/src/main/java/org/apache/zeppelin/lens/LensInterpreter.java
----------------------------------------------------------------------
diff --git a/lens/src/main/java/org/apache/zeppelin/lens/LensInterpreter.java b/lens/src/main/java/org/apache/zeppelin/lens/LensInterpreter.java
index 17e3a46..9727a27 100644
--- a/lens/src/main/java/org/apache/zeppelin/lens/LensInterpreter.java
+++ b/lens/src/main/java/org/apache/zeppelin/lens/LensInterpreter.java
@@ -420,7 +420,8 @@ public class LensInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
   

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/markdown/src/main/java/org/apache/zeppelin/markdown/Markdown.java
----------------------------------------------------------------------
diff --git a/markdown/src/main/java/org/apache/zeppelin/markdown/Markdown.java b/markdown/src/main/java/org/apache/zeppelin/markdown/Markdown.java
index c908a54..45fa6ce 100644
--- a/markdown/src/main/java/org/apache/zeppelin/markdown/Markdown.java
+++ b/markdown/src/main/java/org/apache/zeppelin/markdown/Markdown.java
@@ -124,7 +124,8 @@ public class Markdown extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/pig/pom.xml
----------------------------------------------------------------------
diff --git a/pig/pom.xml b/pig/pom.xml
index 918b551..e58a62a 100644
--- a/pig/pom.xml
+++ b/pig/pom.xml
@@ -47,6 +47,12 @@
             <artifactId>zeppelin-interpreter</artifactId>
             <version>${project.version}</version>
             <scope>provided</scope>
+            <exclusions>
+              <exclusion>
+                <groupId>jline</groupId>
+                <artifactId>jline</artifactId>
+              </exclusion>
+            </exclusions>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java
----------------------------------------------------------------------
diff --git a/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java b/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java
index 7f6a7eb..0bfcae0 100644
--- a/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java
+++ b/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java
@@ -435,7 +435,8 @@ public class PythonInterpreter extends Interpreter implements ExecuteResultHandl
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/r/src/main/java/org/apache/zeppelin/rinterpreter/KnitR.java
----------------------------------------------------------------------
diff --git a/r/src/main/java/org/apache/zeppelin/rinterpreter/KnitR.java b/r/src/main/java/org/apache/zeppelin/rinterpreter/KnitR.java
index 51a790c..bdc5b86 100644
--- a/r/src/main/java/org/apache/zeppelin/rinterpreter/KnitR.java
+++ b/r/src/main/java/org/apache/zeppelin/rinterpreter/KnitR.java
@@ -77,8 +77,9 @@ public class KnitR extends Interpreter implements WrappedInterpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String s, int i) {
-    List completion = intp.completion(s, i);
+  public List<InterpreterCompletion> completion(String s, int i,
+      InterpreterContext interpreterContext) {
+    List completion = intp.completion(s, i, interpreterContext);
     return completion;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/r/src/main/java/org/apache/zeppelin/rinterpreter/RRepl.java
----------------------------------------------------------------------
diff --git a/r/src/main/java/org/apache/zeppelin/rinterpreter/RRepl.java b/r/src/main/java/org/apache/zeppelin/rinterpreter/RRepl.java
index 0c46670..81891f8 100644
--- a/r/src/main/java/org/apache/zeppelin/rinterpreter/RRepl.java
+++ b/r/src/main/java/org/apache/zeppelin/rinterpreter/RRepl.java
@@ -77,8 +77,9 @@ public class RRepl extends Interpreter implements WrappedInterpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String s, int i) {
-    List completion = intp.completion(s, i);
+  public List<InterpreterCompletion> completion(String s, int i,
+      InterpreterContext interpreterContext) {
+    List completion = intp.completion(s, i, interpreterContext);
     return completion;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/scalding/src/main/java/org/apache/zeppelin/scalding/ScaldingInterpreter.java
----------------------------------------------------------------------
diff --git a/scalding/src/main/java/org/apache/zeppelin/scalding/ScaldingInterpreter.java b/scalding/src/main/java/org/apache/zeppelin/scalding/ScaldingInterpreter.java
index db58268..7156c37 100644
--- a/scalding/src/main/java/org/apache/zeppelin/scalding/ScaldingInterpreter.java
+++ b/scalding/src/main/java/org/apache/zeppelin/scalding/ScaldingInterpreter.java
@@ -270,7 +270,8 @@ public class ScaldingInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return NO_COMPLETION;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java
----------------------------------------------------------------------
diff --git a/shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java b/shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java
index abf5ee8..ec75684 100644
--- a/shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java
+++ b/shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java
@@ -138,7 +138,8 @@ public class ShellInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/spark/src/main/java/org/apache/zeppelin/spark/DepInterpreter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/zeppelin/spark/DepInterpreter.java b/spark/src/main/java/org/apache/zeppelin/spark/DepInterpreter.java
index 478d0bc..6b1f0a9 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/DepInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/DepInterpreter.java
@@ -33,6 +33,8 @@ import java.util.Properties;
 
 import com.google.common.reflect.TypeToken;
 import com.google.gson.Gson;
+
+import org.apache.commons.lang.StringUtils;
 import org.apache.spark.repl.SparkILoop;
 import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterContext;
@@ -284,7 +286,8 @@ public class DepInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     if (Utils.isScala2_10()) {
       ScalaCompleter c = (ScalaCompleter) Utils.invokeMethod(completer, "completer");
       Candidates ret = c.complete(buf, cursor);
@@ -293,7 +296,7 @@ public class DepInterpreter extends Interpreter {
       List<InterpreterCompletion> completions = new LinkedList<>();
 
       for (String candidate : candidates) {
-        completions.add(new InterpreterCompletion(candidate, candidate));
+        completions.add(new InterpreterCompletion(candidate, candidate, StringUtils.EMPTY));
       }
 
       return completions;

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/spark/src/main/java/org/apache/zeppelin/spark/PySparkInterpreter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/zeppelin/spark/PySparkInterpreter.java b/spark/src/main/java/org/apache/zeppelin/spark/PySparkInterpreter.java
index da99b9f..bf0a915 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/PySparkInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/PySparkInterpreter.java
@@ -42,6 +42,7 @@ import org.apache.commons.exec.ExecuteResultHandler;
 import org.apache.commons.exec.ExecuteWatchdog;
 import org.apache.commons.exec.PumpStreamHandler;
 import org.apache.commons.exec.environment.EnvironmentUtils;
+import org.apache.commons.lang.StringUtils;
 import org.apache.spark.SparkConf;
 import org.apache.spark.api.java.JavaSparkContext;
 import org.apache.spark.sql.SQLContext;
@@ -457,7 +458,8 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
 
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     if (buf.length() < cursor) {
       cursor = buf.length();
     }
@@ -508,7 +510,7 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
 
     List<InterpreterCompletion> results = new LinkedList<>();
     for (String name: completionList) {
-      results.add(new InterpreterCompletion(name, name));
+      results.add(new InterpreterCompletion(name, name, StringUtils.EMPTY));
     }
     return results;
   }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java b/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
index 49c83dc..bd2d453 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
@@ -1068,7 +1068,8 @@ public class SparkInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     if (completer == null) {
       logger.warn("Can't find completer");
       return new LinkedList<>();
@@ -1090,7 +1091,7 @@ public class SparkInterpreter extends Interpreter {
     List<InterpreterCompletion> completions = new LinkedList<>();
 
     for (String candidate : candidates) {
-      completions.add(new InterpreterCompletion(candidate, candidate));
+      completions.add(new InterpreterCompletion(candidate, candidate, StringUtils.EMPTY));
     }
 
     return completions;

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java b/spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java
index c6b0796..606c8a0 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java
@@ -212,7 +212,8 @@ public class SparkRInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return new ArrayList<>();
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/spark/src/main/java/org/apache/zeppelin/spark/SparkSqlInterpreter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/zeppelin/spark/SparkSqlInterpreter.java b/spark/src/main/java/org/apache/zeppelin/spark/SparkSqlInterpreter.java
index d2de9a1..f59c0d0 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/SparkSqlInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/SparkSqlInterpreter.java
@@ -177,7 +177,8 @@ public class SparkSqlInterpreter extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/spark/src/test/java/org/apache/zeppelin/spark/PySparkInterpreterTest.java
----------------------------------------------------------------------
diff --git a/spark/src/test/java/org/apache/zeppelin/spark/PySparkInterpreterTest.java b/spark/src/test/java/org/apache/zeppelin/spark/PySparkInterpreterTest.java
index d47a8bd..ce0c86c 100644
--- a/spark/src/test/java/org/apache/zeppelin/spark/PySparkInterpreterTest.java
+++ b/spark/src/test/java/org/apache/zeppelin/spark/PySparkInterpreterTest.java
@@ -118,7 +118,7 @@ public class PySparkInterpreterTest {
   @Test
   public void testCompletion() {
     if (getSparkVersionNumber() > 11) {
-      List<InterpreterCompletion> completions = pySparkInterpreter.completion("sc.", "sc.".length());
+      List<InterpreterCompletion> completions = pySparkInterpreter.completion("sc.", "sc.".length(), null);
       assertTrue(completions.size() > 0);
     }
   }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java
----------------------------------------------------------------------
diff --git a/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java b/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java
index ba5feea..3a31e5d 100644
--- a/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java
+++ b/spark/src/test/java/org/apache/zeppelin/spark/SparkInterpreterTest.java
@@ -301,7 +301,7 @@ public class SparkInterpreterTest {
 
   @Test
   public void testCompletion() {
-    List<InterpreterCompletion> completions = repl.completion("sc.", "sc.".length());
+    List<InterpreterCompletion> completions = repl.completion("sc.", "sc.".length(), null);
     assertTrue(completions.size() > 0);
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/pom.xml
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/pom.xml b/zeppelin-interpreter/pom.xml
index 6b75111..e55144c 100644
--- a/zeppelin-interpreter/pom.xml
+++ b/zeppelin-interpreter/pom.xml
@@ -43,6 +43,7 @@
     <aether.version>1.12</aether.version>
     <maven.aeither.provider.version>3.0.3</maven.aeither.provider.version>
     <wagon.version>1.0</wagon.version>
+    <jline.version>2.12.1</jline.version>
 
     <!--plugin versions-->
     <plugin.shade.version>2.3</plugin.shade.version>
@@ -203,6 +204,17 @@
     </dependency>
 
     <dependency>
+      <groupId>jline</groupId>
+      <artifactId>jline</artifactId>
+      <version>${jline.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/CompletionType.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/CompletionType.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/CompletionType.java
new file mode 100644
index 0000000..20cceda
--- /dev/null
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/CompletionType.java
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.zeppelin.completer;
+
+/**
+ * Types of completion
+ */
+public enum CompletionType {
+  schema,
+  table,
+  column,
+  setting,
+  command,
+  keyword,
+  path
+}

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/StringsCompleter.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/StringsCompleter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/StringsCompleter.java
new file mode 100644
index 0000000..c7dcebe
--- /dev/null
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/completer/StringsCompleter.java
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.zeppelin.completer;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import jline.console.completer.Completer;
+import jline.internal.Preconditions;
+
+/**
+ * Case-insensitive completer for a set of strings.
+ */
+public class StringsCompleter implements Completer {
+  private final SortedSet<String> strings = new TreeSet<String>(new Comparator<String>() {
+    @Override
+    public int compare(String o1, String o2) {
+      return o1.compareToIgnoreCase(o2);
+    }
+  });
+
+  public StringsCompleter() {
+  }
+
+  public StringsCompleter(final Collection<String> strings) {
+    Preconditions.checkNotNull(strings);
+    getStrings().addAll(strings);
+  }
+
+  public Collection<String> getStrings() {
+    return strings;
+  }
+
+  public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+    return completeCollection(buffer, cursor, candidates);
+  }
+
+  public int complete(final String buffer, final int cursor, final Set<CharSequence> candidates) {
+    return completeCollection(buffer, cursor, candidates);
+  }
+
+  private int completeCollection(final String buffer, final int cursor,
+      final Collection<CharSequence> candidates) {
+    Preconditions.checkNotNull(candidates);
+    if (buffer == null) {
+      candidates.addAll(strings);
+    } else {
+      String bufferTmp = buffer.toUpperCase();
+      for (String match : strings.tailSet(buffer)) {
+        String matchTmp = match.toUpperCase();
+        if (!matchTmp.startsWith(bufferTmp)) {
+          break;
+        }
+
+        candidates.add(match);
+      }
+    }
+
+    return candidates.isEmpty() ? -1 : 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/ClassloaderInterpreter.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/ClassloaderInterpreter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/ClassloaderInterpreter.java
index e20f7c5..a1dafd9 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/ClassloaderInterpreter.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/ClassloaderInterpreter.java
@@ -152,11 +152,12 @@ public class ClassloaderInterpreter
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
     Thread.currentThread().setContextClassLoader(cl);
     try {
-      List completion = intp.completion(buf, cursor);
+      List completion = intp.completion(buf, cursor, interpreterContext);
       return completion;
     } catch (Exception e) {
       throw new InterpreterException(e);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java
index b64530a..a327b55 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java
@@ -102,10 +102,12 @@ public abstract class Interpreter {
    *
    * @param buf statements
    * @param cursor cursor position in statements
+   * @param interpreterContext
    * @return list of possible completion. Return empty list if there're nothing to return.
    */
   @ZeppelinApi
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext)  {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/LazyOpenInterpreter.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/LazyOpenInterpreter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/LazyOpenInterpreter.java
index ad85ded..bb09d19 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/LazyOpenInterpreter.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/LazyOpenInterpreter.java
@@ -121,9 +121,10 @@ public class LazyOpenInterpreter
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     open();
-    List completion = intp.completion(buf, cursor);
+    List completion = intp.completion(buf, cursor, interpreterContext);
     return completion;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java
index aae50ae..2f9d2bb 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java
@@ -481,7 +481,8 @@ public class RemoteInterpreter extends Interpreter {
 
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     RemoteInterpreterProcess interpreterProcess = getInterpreterProcess();
     Client client = null;
     try {
@@ -492,7 +493,8 @@ public class RemoteInterpreter extends Interpreter {
 
     boolean broken = false;
     try {
-      List completion = client.completion(sessionKey, className, buf, cursor);
+      List completion = client.completion(sessionKey, className, buf, cursor,
+          convert(interpreterContext));
       return completion;
     } catch (TException e) {
       broken = true;

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java
index effaf85..3b7ec5c 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterServer.java
@@ -562,10 +562,10 @@ public class RemoteInterpreterServer
 
   @Override
   public List<InterpreterCompletion> completion(String noteId,
-      String className, String buf, int cursor)
+      String className, String buf, int cursor, RemoteInterpreterContext remoteInterpreterContext)
       throws TException {
     Interpreter intp = getInterpreter(noteId, className);
-    List completion = intp.completion(buf, cursor);
+    List completion = intp.completion(buf, cursor, convert(remoteInterpreterContext, null));
     return completion;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/InterpreterCompletion.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/InterpreterCompletion.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/InterpreterCompletion.java
index 8a1bc7d..43713e9 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/InterpreterCompletion.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/InterpreterCompletion.java
@@ -51,12 +51,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class InterpreterCompletion implements org.apache.thrift.TBase<InterpreterCompletion, InterpreterCompletion._Fields>, java.io.Serializable, Cloneable, Comparable<InterpreterCompletion> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("InterpreterCompletion");
 
   private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)1);
   private static final org.apache.thrift.protocol.TField VALUE_FIELD_DESC = new org.apache.thrift.protocol.TField("value", org.apache.thrift.protocol.TType.STRING, (short)2);
+  private static final org.apache.thrift.protocol.TField META_FIELD_DESC = new org.apache.thrift.protocol.TField("meta", org.apache.thrift.protocol.TType.STRING, (short)3);
 
   private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
   static {
@@ -66,11 +67,13 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
 
   public String name; // required
   public String value; // required
+  public String meta; // required
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
     NAME((short)1, "name"),
-    VALUE((short)2, "value");
+    VALUE((short)2, "value"),
+    META((short)3, "meta");
 
     private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
 
@@ -89,6 +92,8 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
           return NAME;
         case 2: // VALUE
           return VALUE;
+        case 3: // META
+          return META;
         default:
           return null;
       }
@@ -136,6 +141,8 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
     tmpMap.put(_Fields.VALUE, new org.apache.thrift.meta_data.FieldMetaData("value", org.apache.thrift.TFieldRequirementType.DEFAULT, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.META, new org.apache.thrift.meta_data.FieldMetaData("meta", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
     metaDataMap = Collections.unmodifiableMap(tmpMap);
     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(InterpreterCompletion.class, metaDataMap);
   }
@@ -145,11 +152,13 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
 
   public InterpreterCompletion(
     String name,
-    String value)
+    String value,
+    String meta)
   {
     this();
     this.name = name;
     this.value = value;
+    this.meta = meta;
   }
 
   /**
@@ -162,6 +171,9 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
     if (other.isSetValue()) {
       this.value = other.value;
     }
+    if (other.isSetMeta()) {
+      this.meta = other.meta;
+    }
   }
 
   public InterpreterCompletion deepCopy() {
@@ -172,6 +184,7 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
   public void clear() {
     this.name = null;
     this.value = null;
+    this.meta = null;
   }
 
   public String getName() {
@@ -222,6 +235,30 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
     }
   }
 
+  public String getMeta() {
+    return this.meta;
+  }
+
+  public InterpreterCompletion setMeta(String meta) {
+    this.meta = meta;
+    return this;
+  }
+
+  public void unsetMeta() {
+    this.meta = null;
+  }
+
+  /** Returns true if field meta is set (has been assigned a value) and false otherwise */
+  public boolean isSetMeta() {
+    return this.meta != null;
+  }
+
+  public void setMetaIsSet(boolean value) {
+    if (!value) {
+      this.meta = null;
+    }
+  }
+
   public void setFieldValue(_Fields field, Object value) {
     switch (field) {
     case NAME:
@@ -240,6 +277,14 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
       }
       break;
 
+    case META:
+      if (value == null) {
+        unsetMeta();
+      } else {
+        setMeta((String)value);
+      }
+      break;
+
     }
   }
 
@@ -251,6 +296,9 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
     case VALUE:
       return getValue();
 
+    case META:
+      return getMeta();
+
     }
     throw new IllegalStateException();
   }
@@ -266,6 +314,8 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
       return isSetName();
     case VALUE:
       return isSetValue();
+    case META:
+      return isSetMeta();
     }
     throw new IllegalStateException();
   }
@@ -301,6 +351,15 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
         return false;
     }
 
+    boolean this_present_meta = true && this.isSetMeta();
+    boolean that_present_meta = true && that.isSetMeta();
+    if (this_present_meta || that_present_meta) {
+      if (!(this_present_meta && that_present_meta))
+        return false;
+      if (!this.meta.equals(that.meta))
+        return false;
+    }
+
     return true;
   }
 
@@ -318,6 +377,11 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
     if (present_value)
       list.add(value);
 
+    boolean present_meta = true && (isSetMeta());
+    list.add(present_meta);
+    if (present_meta)
+      list.add(meta);
+
     return list.hashCode();
   }
 
@@ -349,6 +413,16 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
         return lastComparison;
       }
     }
+    lastComparison = Boolean.valueOf(isSetMeta()).compareTo(other.isSetMeta());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetMeta()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.meta, other.meta);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
     return 0;
   }
 
@@ -384,6 +458,14 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
       sb.append(this.value);
     }
     first = false;
+    if (!first) sb.append(", ");
+    sb.append("meta:");
+    if (this.meta == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.meta);
+    }
+    first = false;
     sb.append(")");
     return sb.toString();
   }
@@ -443,6 +525,14 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
             }
             break;
+          case 3: // META
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.meta = iprot.readString();
+              struct.setMetaIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
           default:
             org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
         }
@@ -468,6 +558,11 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
         oprot.writeString(struct.value);
         oprot.writeFieldEnd();
       }
+      if (struct.meta != null) {
+        oprot.writeFieldBegin(META_FIELD_DESC);
+        oprot.writeString(struct.meta);
+        oprot.writeFieldEnd();
+      }
       oprot.writeFieldStop();
       oprot.writeStructEnd();
     }
@@ -492,19 +587,25 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
       if (struct.isSetValue()) {
         optionals.set(1);
       }
-      oprot.writeBitSet(optionals, 2);
+      if (struct.isSetMeta()) {
+        optionals.set(2);
+      }
+      oprot.writeBitSet(optionals, 3);
       if (struct.isSetName()) {
         oprot.writeString(struct.name);
       }
       if (struct.isSetValue()) {
         oprot.writeString(struct.value);
       }
+      if (struct.isSetMeta()) {
+        oprot.writeString(struct.meta);
+      }
     }
 
     @Override
     public void read(org.apache.thrift.protocol.TProtocol prot, InterpreterCompletion struct) throws org.apache.thrift.TException {
       TTupleProtocol iprot = (TTupleProtocol) prot;
-      BitSet incoming = iprot.readBitSet(2);
+      BitSet incoming = iprot.readBitSet(3);
       if (incoming.get(0)) {
         struct.name = iprot.readString();
         struct.setNameIsSet(true);
@@ -513,6 +614,10 @@ public class InterpreterCompletion implements org.apache.thrift.TBase<Interprete
         struct.value = iprot.readString();
         struct.setValueIsSet(true);
       }
+      if (incoming.get(2)) {
+        struct.meta = iprot.readString();
+        struct.setMetaIsSet(true);
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteApplicationResult.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteApplicationResult.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteApplicationResult.java
index ebb8579..cf8e50a 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteApplicationResult.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteApplicationResult.java
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class RemoteApplicationResult implements org.apache.thrift.TBase<RemoteApplicationResult, RemoteApplicationResult._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteApplicationResult> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteApplicationResult");
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java
index 6a24e56..d6619fc 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterContext.java
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteInterpreterContext, RemoteInterpreterContext._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterContext> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterContext");
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEvent.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEvent.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEvent.java
index 39c4f81..e252775 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEvent.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEvent.java
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class RemoteInterpreterEvent implements org.apache.thrift.TBase<RemoteInterpreterEvent, RemoteInterpreterEvent._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterEvent> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterEvent");
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResult.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResult.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResult.java
index 4929efa..b18bad5 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResult.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResult.java
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteInterpreterResult, RemoteInterpreterResult._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterResult> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterResult");
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResultMessage.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResultMessage.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResultMessage.java
index eb1261e..a2aff29 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResultMessage.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterResultMessage.java
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class RemoteInterpreterResultMessage implements org.apache.thrift.TBase<RemoteInterpreterResultMessage, RemoteInterpreterResultMessage._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterResultMessage> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterResultMessage");
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterService.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterService.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterService.java
index 7b2a76e..def96fa 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterService.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterService.java
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class RemoteInterpreterService {
 
   public interface Iface {
@@ -70,7 +70,7 @@ public class RemoteInterpreterService {
 
     public String getFormType(String sessionKey, String className) throws org.apache.thrift.TException;
 
-    public List<InterpreterCompletion> completion(String sessionKey, String className, String buf, int cursor) throws org.apache.thrift.TException;
+    public List<InterpreterCompletion> completion(String sessionKey, String className, String buf, int cursor, RemoteInterpreterContext interpreterContext) throws org.apache.thrift.TException;
 
     public void shutdown() throws org.apache.thrift.TException;
 
@@ -126,7 +126,7 @@ public class RemoteInterpreterService {
 
     public void getFormType(String sessionKey, String className, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
 
-    public void completion(String sessionKey, String className, String buf, int cursor, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+    public void completion(String sessionKey, String className, String buf, int cursor, RemoteInterpreterContext interpreterContext, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
 
     public void shutdown(org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
 
@@ -349,19 +349,20 @@ public class RemoteInterpreterService {
       throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getFormType failed: unknown result");
     }
 
-    public List<InterpreterCompletion> completion(String sessionKey, String className, String buf, int cursor) throws org.apache.thrift.TException
+    public List<InterpreterCompletion> completion(String sessionKey, String className, String buf, int cursor, RemoteInterpreterContext interpreterContext) throws org.apache.thrift.TException
     {
-      send_completion(sessionKey, className, buf, cursor);
+      send_completion(sessionKey, className, buf, cursor, interpreterContext);
       return recv_completion();
     }
 
-    public void send_completion(String sessionKey, String className, String buf, int cursor) throws org.apache.thrift.TException
+    public void send_completion(String sessionKey, String className, String buf, int cursor, RemoteInterpreterContext interpreterContext) throws org.apache.thrift.TException
     {
       completion_args args = new completion_args();
       args.setSessionKey(sessionKey);
       args.setClassName(className);
       args.setBuf(buf);
       args.setCursor(cursor);
+      args.setInterpreterContext(interpreterContext);
       sendBase("completion", args);
     }
 
@@ -1064,9 +1065,9 @@ public class RemoteInterpreterService {
       }
     }
 
-    public void completion(String sessionKey, String className, String buf, int cursor, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+    public void completion(String sessionKey, String className, String buf, int cursor, RemoteInterpreterContext interpreterContext, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
       checkReady();
-      completion_call method_call = new completion_call(sessionKey, className, buf, cursor, resultHandler, this, ___protocolFactory, ___transport);
+      completion_call method_call = new completion_call(sessionKey, className, buf, cursor, interpreterContext, resultHandler, this, ___protocolFactory, ___transport);
       this.___currentMethod = method_call;
       ___manager.call(method_call);
     }
@@ -1076,12 +1077,14 @@ public class RemoteInterpreterService {
       private String className;
       private String buf;
       private int cursor;
-      public completion_call(String sessionKey, String className, String buf, int cursor, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+      private RemoteInterpreterContext interpreterContext;
+      public completion_call(String sessionKey, String className, String buf, int cursor, RemoteInterpreterContext interpreterContext, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
         super(client, protocolFactory, transport, resultHandler, false);
         this.sessionKey = sessionKey;
         this.className = className;
         this.buf = buf;
         this.cursor = cursor;
+        this.interpreterContext = interpreterContext;
       }
 
       public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
@@ -1091,6 +1094,7 @@ public class RemoteInterpreterService {
         args.setClassName(className);
         args.setBuf(buf);
         args.setCursor(cursor);
+        args.setInterpreterContext(interpreterContext);
         args.write(prot);
         prot.writeMessageEnd();
       }
@@ -1933,7 +1937,7 @@ public class RemoteInterpreterService {
 
       public completion_result getResult(I iface, completion_args args) throws org.apache.thrift.TException {
         completion_result result = new completion_result();
-        result.success = iface.completion(args.sessionKey, args.className, args.buf, args.cursor);
+        result.success = iface.completion(args.sessionKey, args.className, args.buf, args.cursor, args.interpreterContext);
         return result;
       }
     }
@@ -2742,7 +2746,7 @@ public class RemoteInterpreterService {
       }
 
       public void start(I iface, completion_args args, org.apache.thrift.async.AsyncMethodCallback<List<InterpreterCompletion>> resultHandler) throws TException {
-        iface.completion(args.sessionKey, args.className, args.buf, args.cursor,resultHandler);
+        iface.completion(args.sessionKey, args.className, args.buf, args.cursor, args.interpreterContext,resultHandler);
       }
     }
 
@@ -9809,6 +9813,7 @@ public class RemoteInterpreterService {
     private static final org.apache.thrift.protocol.TField CLASS_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("className", org.apache.thrift.protocol.TType.STRING, (short)2);
     private static final org.apache.thrift.protocol.TField BUF_FIELD_DESC = new org.apache.thrift.protocol.TField("buf", org.apache.thrift.protocol.TType.STRING, (short)3);
     private static final org.apache.thrift.protocol.TField CURSOR_FIELD_DESC = new org.apache.thrift.protocol.TField("cursor", org.apache.thrift.protocol.TType.I32, (short)4);
+    private static final org.apache.thrift.protocol.TField INTERPRETER_CONTEXT_FIELD_DESC = new org.apache.thrift.protocol.TField("interpreterContext", org.apache.thrift.protocol.TType.STRUCT, (short)5);
 
     private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
     static {
@@ -9820,13 +9825,15 @@ public class RemoteInterpreterService {
     public String className; // required
     public String buf; // required
     public int cursor; // required
+    public RemoteInterpreterContext interpreterContext; // required
 
     /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
     public enum _Fields implements org.apache.thrift.TFieldIdEnum {
       SESSION_KEY((short)1, "sessionKey"),
       CLASS_NAME((short)2, "className"),
       BUF((short)3, "buf"),
-      CURSOR((short)4, "cursor");
+      CURSOR((short)4, "cursor"),
+      INTERPRETER_CONTEXT((short)5, "interpreterContext");
 
       private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
 
@@ -9849,6 +9856,8 @@ public class RemoteInterpreterService {
             return BUF;
           case 4: // CURSOR
             return CURSOR;
+          case 5: // INTERPRETER_CONTEXT
+            return INTERPRETER_CONTEXT;
           default:
             return null;
         }
@@ -9902,6 +9911,8 @@ public class RemoteInterpreterService {
           new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
       tmpMap.put(_Fields.CURSOR, new org.apache.thrift.meta_data.FieldMetaData("cursor", org.apache.thrift.TFieldRequirementType.DEFAULT, 
           new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+      tmpMap.put(_Fields.INTERPRETER_CONTEXT, new org.apache.thrift.meta_data.FieldMetaData("interpreterContext", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, RemoteInterpreterContext.class)));
       metaDataMap = Collections.unmodifiableMap(tmpMap);
       org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(completion_args.class, metaDataMap);
     }
@@ -9913,7 +9924,8 @@ public class RemoteInterpreterService {
       String sessionKey,
       String className,
       String buf,
-      int cursor)
+      int cursor,
+      RemoteInterpreterContext interpreterContext)
     {
       this();
       this.sessionKey = sessionKey;
@@ -9921,6 +9933,7 @@ public class RemoteInterpreterService {
       this.buf = buf;
       this.cursor = cursor;
       setCursorIsSet(true);
+      this.interpreterContext = interpreterContext;
     }
 
     /**
@@ -9938,6 +9951,9 @@ public class RemoteInterpreterService {
         this.buf = other.buf;
       }
       this.cursor = other.cursor;
+      if (other.isSetInterpreterContext()) {
+        this.interpreterContext = new RemoteInterpreterContext(other.interpreterContext);
+      }
     }
 
     public completion_args deepCopy() {
@@ -9951,6 +9967,7 @@ public class RemoteInterpreterService {
       this.buf = null;
       setCursorIsSet(false);
       this.cursor = 0;
+      this.interpreterContext = null;
     }
 
     public String getSessionKey() {
@@ -10048,6 +10065,30 @@ public class RemoteInterpreterService {
       __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __CURSOR_ISSET_ID, value);
     }
 
+    public RemoteInterpreterContext getInterpreterContext() {
+      return this.interpreterContext;
+    }
+
+    public completion_args setInterpreterContext(RemoteInterpreterContext interpreterContext) {
+      this.interpreterContext = interpreterContext;
+      return this;
+    }
+
+    public void unsetInterpreterContext() {
+      this.interpreterContext = null;
+    }
+
+    /** Returns true if field interpreterContext is set (has been assigned a value) and false otherwise */
+    public boolean isSetInterpreterContext() {
+      return this.interpreterContext != null;
+    }
+
+    public void setInterpreterContextIsSet(boolean value) {
+      if (!value) {
+        this.interpreterContext = null;
+      }
+    }
+
     public void setFieldValue(_Fields field, Object value) {
       switch (field) {
       case SESSION_KEY:
@@ -10082,6 +10123,14 @@ public class RemoteInterpreterService {
         }
         break;
 
+      case INTERPRETER_CONTEXT:
+        if (value == null) {
+          unsetInterpreterContext();
+        } else {
+          setInterpreterContext((RemoteInterpreterContext)value);
+        }
+        break;
+
       }
     }
 
@@ -10099,6 +10148,9 @@ public class RemoteInterpreterService {
       case CURSOR:
         return Integer.valueOf(getCursor());
 
+      case INTERPRETER_CONTEXT:
+        return getInterpreterContext();
+
       }
       throw new IllegalStateException();
     }
@@ -10118,6 +10170,8 @@ public class RemoteInterpreterService {
         return isSetBuf();
       case CURSOR:
         return isSetCursor();
+      case INTERPRETER_CONTEXT:
+        return isSetInterpreterContext();
       }
       throw new IllegalStateException();
     }
@@ -10171,6 +10225,15 @@ public class RemoteInterpreterService {
           return false;
       }
 
+      boolean this_present_interpreterContext = true && this.isSetInterpreterContext();
+      boolean that_present_interpreterContext = true && that.isSetInterpreterContext();
+      if (this_present_interpreterContext || that_present_interpreterContext) {
+        if (!(this_present_interpreterContext && that_present_interpreterContext))
+          return false;
+        if (!this.interpreterContext.equals(that.interpreterContext))
+          return false;
+      }
+
       return true;
     }
 
@@ -10198,6 +10261,11 @@ public class RemoteInterpreterService {
       if (present_cursor)
         list.add(cursor);
 
+      boolean present_interpreterContext = true && (isSetInterpreterContext());
+      list.add(present_interpreterContext);
+      if (present_interpreterContext)
+        list.add(interpreterContext);
+
       return list.hashCode();
     }
 
@@ -10249,6 +10317,16 @@ public class RemoteInterpreterService {
           return lastComparison;
         }
       }
+      lastComparison = Boolean.valueOf(isSetInterpreterContext()).compareTo(other.isSetInterpreterContext());
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+      if (isSetInterpreterContext()) {
+        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.interpreterContext, other.interpreterContext);
+        if (lastComparison != 0) {
+          return lastComparison;
+        }
+      }
       return 0;
     }
 
@@ -10296,6 +10374,14 @@ public class RemoteInterpreterService {
       sb.append("cursor:");
       sb.append(this.cursor);
       first = false;
+      if (!first) sb.append(", ");
+      sb.append("interpreterContext:");
+      if (this.interpreterContext == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.interpreterContext);
+      }
+      first = false;
       sb.append(")");
       return sb.toString();
     }
@@ -10303,6 +10389,9 @@ public class RemoteInterpreterService {
     public void validate() throws org.apache.thrift.TException {
       // check for required fields
       // check for sub-struct validity
+      if (interpreterContext != null) {
+        interpreterContext.validate();
+      }
     }
 
     private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
@@ -10373,6 +10462,15 @@ public class RemoteInterpreterService {
                 org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
               }
               break;
+            case 5: // INTERPRETER_CONTEXT
+              if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
+                struct.interpreterContext = new RemoteInterpreterContext();
+                struct.interpreterContext.read(iprot);
+                struct.setInterpreterContextIsSet(true);
+              } else { 
+                org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+              }
+              break;
             default:
               org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
           }
@@ -10406,6 +10504,11 @@ public class RemoteInterpreterService {
         oprot.writeFieldBegin(CURSOR_FIELD_DESC);
         oprot.writeI32(struct.cursor);
         oprot.writeFieldEnd();
+        if (struct.interpreterContext != null) {
+          oprot.writeFieldBegin(INTERPRETER_CONTEXT_FIELD_DESC);
+          struct.interpreterContext.write(oprot);
+          oprot.writeFieldEnd();
+        }
         oprot.writeFieldStop();
         oprot.writeStructEnd();
       }
@@ -10436,7 +10539,10 @@ public class RemoteInterpreterService {
         if (struct.isSetCursor()) {
           optionals.set(3);
         }
-        oprot.writeBitSet(optionals, 4);
+        if (struct.isSetInterpreterContext()) {
+          optionals.set(4);
+        }
+        oprot.writeBitSet(optionals, 5);
         if (struct.isSetSessionKey()) {
           oprot.writeString(struct.sessionKey);
         }
@@ -10449,12 +10555,15 @@ public class RemoteInterpreterService {
         if (struct.isSetCursor()) {
           oprot.writeI32(struct.cursor);
         }
+        if (struct.isSetInterpreterContext()) {
+          struct.interpreterContext.write(oprot);
+        }
       }
 
       @Override
       public void read(org.apache.thrift.protocol.TProtocol prot, completion_args struct) throws org.apache.thrift.TException {
         TTupleProtocol iprot = (TTupleProtocol) prot;
-        BitSet incoming = iprot.readBitSet(4);
+        BitSet incoming = iprot.readBitSet(5);
         if (incoming.get(0)) {
           struct.sessionKey = iprot.readString();
           struct.setSessionKeyIsSet(true);
@@ -10471,6 +10580,11 @@ public class RemoteInterpreterService {
           struct.cursor = iprot.readI32();
           struct.setCursorIsSet(true);
         }
+        if (incoming.get(4)) {
+          struct.interpreterContext = new RemoteInterpreterContext();
+          struct.interpreterContext.read(iprot);
+          struct.setInterpreterContextIsSet(true);
+        }
       }
     }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/ZeppelinServerResourceParagraphRunner.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/ZeppelinServerResourceParagraphRunner.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/ZeppelinServerResourceParagraphRunner.java
index 74cb25d..78cb090 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/ZeppelinServerResourceParagraphRunner.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/ZeppelinServerResourceParagraphRunner.java
@@ -51,7 +51,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
-@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-1-25")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
 public class ZeppelinServerResourceParagraphRunner implements org.apache.thrift.TBase<ZeppelinServerResourceParagraphRunner, ZeppelinServerResourceParagraphRunner._Fields>, java.io.Serializable, Cloneable, Comparable<ZeppelinServerResourceParagraphRunner> {
   private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("ZeppelinServerResourceParagraphRunner");
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift b/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift
index fc09ade..f2eb13f 100644
--- a/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift
+++ b/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift
@@ -84,7 +84,8 @@ struct ZeppelinServerResourceParagraphRunner {
  */
 struct InterpreterCompletion {
   1: string name,
-  2: string value
+  2: string value,
+  3: string meta
 }
 
 service RemoteInterpreterService {
@@ -96,7 +97,7 @@ service RemoteInterpreterService {
   void cancel(1: string sessionKey, 2: string className, 3: RemoteInterpreterContext interpreterContext);
   i32 getProgress(1: string sessionKey, 2: string className, 3: RemoteInterpreterContext interpreterContext);
   string getFormType(1: string sessionKey, 2: string className);
-  list<InterpreterCompletion> completion(1: string sessionKey, 2: string className, 3: string buf, 4: i32 cursor);
+  list<InterpreterCompletion> completion(1: string sessionKey, 2: string className, 3: string buf, 4: i32 cursor, 5: RemoteInterpreterContext interpreterContext);
   void shutdown();
 
   string getStatus(1: string sessionKey, 2:string jobId);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterA.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterA.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterA.java
index aef3a00..81a9164 100644
--- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterA.java
+++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterA.java
@@ -78,7 +78,8 @@ public class MockInterpreterA extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java
index 6805da2..d4b26ad 100644
--- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java
+++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterAngular.java
@@ -106,7 +106,8 @@ public class MockInterpreterAngular extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterB.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterB.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterB.java
index 4262500..7103335 100644
--- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterB.java
+++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterB.java
@@ -78,7 +78,8 @@ public class MockInterpreterB extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterEnv.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterEnv.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterEnv.java
index 2bd7893..12e11f7 100644
--- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterEnv.java
+++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterEnv.java
@@ -67,7 +67,8 @@ public class MockInterpreterEnv extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4d398ef2/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterOutputStream.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterOutputStream.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterOutputStream.java
index 8181df1..349315c 100644
--- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterOutputStream.java
+++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/mock/MockInterpreterOutputStream.java
@@ -78,7 +78,8 @@ public class MockInterpreterOutputStream extends Interpreter {
   }
 
   @Override
-  public List<InterpreterCompletion> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor,
+      InterpreterContext interpreterContext) {
     return null;
   }