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 2016/06/16 15:04:34 UTC

[2/2] zeppelin git commit: [ZEPPELIN-982] Improve interpreter completion API

[ZEPPELIN-982] Improve interpreter completion API

### What is this PR for?
When people implement a new interpreter, they extend [interpreter.java](https://github.com/apache/zeppelin/blob/master/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java) as described in [here](https://zeppelin.apache.org/docs/0.6.0-SNAPSHOT/development/writingzeppelininterpreter.html). Among the several methods in [interpreter.java](https://github.com/apache/zeppelin/blob/master/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java), [completion API](https://github.com/apache/zeppelin/blob/master/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java#L109) enables auto-completion.

However this API is too simple compared to other project's auto-completion and hard to add more at the moment. So for the aspect of further expansion, it would be better to separate and restructure this API before the this release( 0.6.0 ).

### What type of PR is it?
Improvement

### Todos
* [x] - Create new structure : `InterpreterCompletion` in `RemoteInterpreterService.thrift` and regenerate `zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/*` files
* [x] - Change all existing `List<String> completion` -> `List<InterpreterCompletion> completion`
* [x] - Change `paragraph.controller.js` to point real `name` and `value`

### What is the Jira issue?
[ZEPPELIN-982](https://issues.apache.org/jira/browse/ZEPPELIN-982)

### How should this be tested?
Since this improvement is just API change, it should work same as before. So after applying this patch, and check whether auto-completion works well or not.

Use `. + ctrl` for auto-completion. For example,

```
%spark
sc.version
```

When after typing `sc.` and pushing  `. + ctrl` down, `version` should be shown in the auto-completion list.

### Screenshots (if appropriate)
![auto_completion](https://cloud.githubusercontent.com/assets/10060731/15952521/72937782-2e76-11e6-8246-4faf0dd77a5b.gif)

### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No

Author: AhyoungRyu <fb...@hanmail.net>

Closes #984 from AhyoungRyu/ZEPPELIN-982 and squashes the following commits:

311dc29 [AhyoungRyu] Fix travis
9d384ec [AhyoungRyu] Address @minalee feedback
fdfae8f [AhyoungRyu] Address @jongyoul review
bd4f8c0 [AhyoungRyu] Remove abstract and make it return null by default
f8352c7 [AhyoungRyu] Fix travis error
43d81f6 [AhyoungRyu] Remove console.log
24912fa [AhyoungRyu] Fix type casting error in SparkInterpreter
80e295b [AhyoungRyu] Change return type
bd04c22 [AhyoungRyu] Apply new InterpreterCompletion class to all interpreter class files
c283043 [AhyoungRyu] Apply new InterpreterCompletion class under zeppelin-zengine/
dbecc51 [AhyoungRyu] Apply new InterpreterCompletion class under zeppelin-server/
6449455 [AhyoungRyu] Apply new InterpreterCompletion class under zeppelin-interpreter/
919b159 [AhyoungRyu] Add automatically generated thrift class
9e69e11 [AhyoungRyu] Change v -> v.name & v.value in front
73e374e [AhyoungRyu] Define InterpreterCompletion structure to thrift file


Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/7b00dffd
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/7b00dffd
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/7b00dffd

Branch: refs/heads/master
Commit: 7b00dffd9800e06d6eb80c1c06db6085b5b529be
Parents: 048e432
Author: AhyoungRyu <fb...@hanmail.net>
Authored: Sun Jun 12 13:40:37 2016 -0700
Committer: Lee moon soo <mo...@apache.org>
Committed: Thu Jun 16 08:06:07 2016 -0700

----------------------------------------------------------------------
 .../zeppelin/alluxio/AlluxioInterpreter.java    |   5 +-
 .../alluxio/AlluxioInterpreterTest.java         |  21 +-
 .../zeppelin/angular/AngularInterpreter.java    |   5 +-
 .../cassandra/CassandraInterpreter.java         |   5 +-
 .../elasticsearch/ElasticsearchInterpreter.java |   5 +-
 .../apache/zeppelin/file/FileInterpreter.java   |   3 +-
 .../zeppelin/file/HDFSFileInterpreter.java      |   5 +-
 .../apache/zeppelin/flink/FlinkInterpreter.java |   5 +-
 .../zeppelin/geode/GeodeOqlInterpreter.java     |   3 +-
 .../apache/zeppelin/hbase/HbaseInterpreter.java |   3 +-
 .../zeppelin/ignite/IgniteInterpreter.java      |   3 +-
 .../zeppelin/ignite/IgniteSqlInterpreter.java   |   3 +-
 .../apache/zeppelin/jdbc/JDBCInterpreter.java   |   8 +-
 .../apache/zeppelin/kylin/KylinInterpreter.java |   3 +-
 .../apache/zeppelin/lens/LensInterpreter.java   |   3 +-
 .../zeppelin/livy/LivyPySparkInterpreter.java   |   3 +-
 .../zeppelin/livy/LivySparkInterpreter.java     |   3 +-
 .../zeppelin/livy/LivySparkRInterpreter.java    |   3 +-
 .../zeppelin/livy/LivySparkSQLInterpreter.java  |   3 +-
 .../org/apache/zeppelin/markdown/Markdown.java  |   3 +-
 .../zeppelin/phoenix/PhoenixInterpreter.java    |   3 +-
 .../postgresql/PostgreSqlInterpreter.java       |   8 +-
 .../zeppelin/python/PythonInterpreter.java      |   3 +-
 .../org/apache/zeppelin/rinterpreter/KnitR.java |   6 +-
 .../org/apache/zeppelin/rinterpreter/RRepl.java |   6 +-
 .../zeppelin/rinterpreter/RInterpreter.scala    |   4 +-
 .../rinterpreter/RInterpreterTest.scala         |   4 +-
 .../zeppelin/scalding/ScaldingInterpreter.java  |   7 +-
 .../apache/zeppelin/shell/ShellInterpreter.java |   3 +-
 .../apache/zeppelin/spark/DepInterpreter.java   |  22 +-
 .../zeppelin/spark/PySparkInterpreter.java      |   9 +-
 .../apache/zeppelin/spark/SparkInterpreter.java |  23 +-
 .../zeppelin/spark/SparkRInterpreter.java       |   5 +-
 .../zeppelin/spark/SparkSqlInterpreter.java     |   3 +-
 .../interpreter/ClassloaderInterpreter.java     |   6 +-
 .../zeppelin/interpreter/Interpreter.java       |   5 +-
 .../interpreter/LazyOpenInterpreter.java        |   6 +-
 .../interpreter/remote/RemoteInterpreter.java   |   6 +-
 .../remote/RemoteInterpreterServer.java         |  11 +-
 .../thrift/InterpreterCompletion.java           | 520 +++++++++++++++++++
 .../thrift/RemoteInterpreterContext.java        |  19 +-
 .../thrift/RemoteInterpreterEvent.java          |  19 +-
 .../thrift/RemoteInterpreterEventType.java      |  17 +
 .../thrift/RemoteInterpreterResult.java         |  19 +-
 .../thrift/RemoteInterpreterService.java        |  86 +--
 .../main/thrift/RemoteInterpreterService.thrift |  13 +-
 .../remote/mock/MockInterpreterA.java           |   3 +-
 .../remote/mock/MockInterpreterAngular.java     |   3 +-
 .../remote/mock/MockInterpreterB.java           |   3 +-
 .../remote/mock/MockInterpreterEnv.java         |   3 +-
 .../mock/MockInterpreterOutputStream.java       |   3 +-
 .../mock/MockInterpreterResourcePool.java       |   3 +-
 .../apache/zeppelin/socket/NotebookServer.java  |   3 +-
 .../interpreter/mock/MockInterpreter1.java      |   3 +-
 .../notebook/paragraph/paragraph.controller.js  |   6 +-
 .../java/org/apache/zeppelin/notebook/Note.java |   7 +-
 .../org/apache/zeppelin/notebook/Paragraph.java |   6 +-
 .../interpreter/mock/MockInterpreter1.java      |   3 +-
 .../interpreter/mock/MockInterpreter11.java     |   3 +-
 .../interpreter/mock/MockInterpreter2.java      |   3 +-
 60 files changed, 840 insertions(+), 140 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/alluxio/src/main/java/org/apache/zeppelin/alluxio/AlluxioInterpreter.java
----------------------------------------------------------------------
diff --git a/alluxio/src/main/java/org/apache/zeppelin/alluxio/AlluxioInterpreter.java b/alluxio/src/main/java/org/apache/zeppelin/alluxio/AlluxioInterpreter.java
index acc59bd..a6fed71 100644
--- a/alluxio/src/main/java/org/apache/zeppelin/alluxio/AlluxioInterpreter.java
+++ b/alluxio/src/main/java/org/apache/zeppelin/alluxio/AlluxioInterpreter.java
@@ -28,6 +28,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -174,13 +175,13 @@ public class AlluxioInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     String[] words = splitAndRemoveEmpty(splitAndRemoveEmpty(buf, "\n"), " ");
     String lastWord = "";
     if (words.length > 0) {
       lastWord = words[ words.length - 1 ];
     }
-    ArrayList<String> voices = new ArrayList<String>();
+    ArrayList voices = new ArrayList<>();
     for (String command : keywords) {
       if (command.startsWith(lastWord)) {
         voices.add(command);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/alluxio/src/test/java/org/apache/zeppelin/alluxio/AlluxioInterpreterTest.java
----------------------------------------------------------------------
diff --git a/alluxio/src/test/java/org/apache/zeppelin/alluxio/AlluxioInterpreterTest.java b/alluxio/src/test/java/org/apache/zeppelin/alluxio/AlluxioInterpreterTest.java
index 556b037..61d97b5 100644
--- a/alluxio/src/test/java/org/apache/zeppelin/alluxio/AlluxioInterpreterTest.java
+++ b/alluxio/src/test/java/org/apache/zeppelin/alluxio/AlluxioInterpreterTest.java
@@ -31,6 +31,7 @@ import alluxio.client.WriteType;
 import alluxio.client.file.URIStatus;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.junit.*;
 
 import alluxio.Constants;
@@ -76,19 +77,19 @@ public class AlluxioInterpreterTest {
 
   @Test
   public void testCompletion() {
-    List<String> expectedResultOne = Arrays.asList("cat", "chgrp",
+    List expectedResultOne = Arrays.asList("cat", "chgrp",
             "chmod", "chown", "copyFromLocal", "copyToLocal", "count",
             "createLineage");
-    List<String> expectedResultTwo = Arrays.asList("copyFromLocal",
+    List expectedResultTwo = Arrays.asList("copyFromLocal",
             "copyToLocal", "count");
-    List<String> expectedResultThree = Arrays.asList("copyFromLocal", "copyToLocal");
-    List<String> expectedResultNone = new ArrayList<String>();
-
-    List<String> resultOne = alluxioInterpreter.completion("c", 0);
-    List<String> resultTwo = alluxioInterpreter.completion("co", 0);
-    List<String> resultThree = alluxioInterpreter.completion("copy", 0);
-    List<String> resultNotMatch = alluxioInterpreter.completion("notMatch", 0);
-    List<String> resultAll = alluxioInterpreter.completion("", 0);
+    List expectedResultThree = Arrays.asList("copyFromLocal", "copyToLocal");
+    List expectedResultNone = new ArrayList<String>();
+
+    List<InterpreterCompletion> resultOne = alluxioInterpreter.completion("c", 0);
+    List<InterpreterCompletion> resultTwo = alluxioInterpreter.completion("co", 0);
+    List<InterpreterCompletion> resultThree = alluxioInterpreter.completion("copy", 0);
+    List<InterpreterCompletion> resultNotMatch = alluxioInterpreter.completion("notMatch", 0);
+    List<InterpreterCompletion> resultAll = alluxioInterpreter.completion("", 0);
 
     Assert.assertEquals(expectedResultOne, resultOne);
     Assert.assertEquals(expectedResultTwo, resultTwo);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/angular/src/main/java/org/apache/zeppelin/angular/AngularInterpreter.java
----------------------------------------------------------------------
diff --git a/angular/src/main/java/org/apache/zeppelin/angular/AngularInterpreter.java b/angular/src/main/java/org/apache/zeppelin/angular/AngularInterpreter.java
index c7a406d..1b65f0f 100644
--- a/angular/src/main/java/org/apache/zeppelin/angular/AngularInterpreter.java
+++ b/angular/src/main/java/org/apache/zeppelin/angular/AngularInterpreter.java
@@ -26,6 +26,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.InterpreterResult.Type;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 
@@ -69,8 +70,8 @@ public class AngularInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
-    return new LinkedList<String>();
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
+    return new LinkedList<>();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/cassandra/src/main/java/org/apache/zeppelin/cassandra/CassandraInterpreter.java
----------------------------------------------------------------------
diff --git a/cassandra/src/main/java/org/apache/zeppelin/cassandra/CassandraInterpreter.java b/cassandra/src/main/java/org/apache/zeppelin/cassandra/CassandraInterpreter.java
index ca77aba..147fb62 100644
--- a/cassandra/src/main/java/org/apache/zeppelin/cassandra/CassandraInterpreter.java
+++ b/cassandra/src/main/java/org/apache/zeppelin/cassandra/CassandraInterpreter.java
@@ -23,6 +23,7 @@ import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -139,7 +140,7 @@ public class CassandraInterpreter extends Interpreter {
   public static final String LOGGING_DOWNGRADING_RETRY = "LOGGING_DOWNGRADING";
   public static final String LOGGING_FALLTHROUGH_RETRY = "LOGGING_FALLTHROUGH";
 
-  public static final List<String> NO_COMPLETION = new ArrayList<>();
+  public static final List NO_COMPLETION = new ArrayList<>();
 
   InterpreterLogic helper;
   Cluster cluster;
@@ -320,7 +321,7 @@ public class CassandraInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return NO_COMPLETION;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/ElasticsearchInterpreter.java
----------------------------------------------------------------------
diff --git a/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/ElasticsearchInterpreter.java b/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/ElasticsearchInterpreter.java
index b05139f..dfd27e5 100644
--- a/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/ElasticsearchInterpreter.java
+++ b/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/ElasticsearchInterpreter.java
@@ -37,6 +37,7 @@ import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.elasticsearch.action.delete.DeleteResponse;
 import org.elasticsearch.action.get.GetResponse;
 import org.elasticsearch.action.index.IndexResponse;
@@ -244,8 +245,8 @@ public class ElasticsearchInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String s, int i) {
-    final List<String> suggestions = new ArrayList<>();
+  public List<InterpreterCompletion> completion(String s, int i) {
+    final List suggestions = new ArrayList<>();
 
     if (StringUtils.isEmpty(s)) {
       suggestions.addAll(COMMANDS);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/file/src/main/java/org/apache/zeppelin/file/FileInterpreter.java
----------------------------------------------------------------------
diff --git a/file/src/main/java/org/apache/zeppelin/file/FileInterpreter.java b/file/src/main/java/org/apache/zeppelin/file/FileInterpreter.java
index 4d50ce5..9aa3605 100644
--- a/file/src/main/java/org/apache/zeppelin/file/FileInterpreter.java
+++ b/file/src/main/java/org/apache/zeppelin/file/FileInterpreter.java
@@ -23,6 +23,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.InterpreterResult.Type;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -165,7 +166,7 @@ public abstract class FileInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/file/src/main/java/org/apache/zeppelin/file/HDFSFileInterpreter.java
----------------------------------------------------------------------
diff --git a/file/src/main/java/org/apache/zeppelin/file/HDFSFileInterpreter.java b/file/src/main/java/org/apache/zeppelin/file/HDFSFileInterpreter.java
index 245093e..480d96a 100644
--- a/file/src/main/java/org/apache/zeppelin/file/HDFSFileInterpreter.java
+++ b/file/src/main/java/org/apache/zeppelin/file/HDFSFileInterpreter.java
@@ -26,6 +26,7 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterException;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 
 /**
  * HDFS implementation of File interpreter for Zeppelin.
@@ -259,9 +260,9 @@ public class HDFSFileInterpreter extends FileInterpreter {
 
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     logger.info("Completion request at position\t" + cursor + " in string " + buf);
-    final List<String> suggestions = new ArrayList<>();
+    final List suggestions = new ArrayList<>();
     if (StringUtils.isEmpty(buf)) {
       suggestions.add("ls");
       suggestions.add("cd");

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/flink/src/main/java/org/apache/zeppelin/flink/FlinkInterpreter.java
----------------------------------------------------------------------
diff --git a/flink/src/main/java/org/apache/zeppelin/flink/FlinkInterpreter.java b/flink/src/main/java/org/apache/zeppelin/flink/FlinkInterpreter.java
index 743f884..68591d7 100644
--- a/flink/src/main/java/org/apache/zeppelin/flink/FlinkInterpreter.java
+++ b/flink/src/main/java/org/apache/zeppelin/flink/FlinkInterpreter.java
@@ -38,6 +38,7 @@ import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.InterpreterUtils;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -331,8 +332,8 @@ public class FlinkInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
-    return new LinkedList<String>();
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
+    return new LinkedList<>();
   }
 
   private void startFlinkMiniCluster() {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/geode/src/main/java/org/apache/zeppelin/geode/GeodeOqlInterpreter.java
----------------------------------------------------------------------
diff --git a/geode/src/main/java/org/apache/zeppelin/geode/GeodeOqlInterpreter.java b/geode/src/main/java/org/apache/zeppelin/geode/GeodeOqlInterpreter.java
index 6f6b440..12297b6 100644
--- a/geode/src/main/java/org/apache/zeppelin/geode/GeodeOqlInterpreter.java
+++ b/geode/src/main/java/org/apache/zeppelin/geode/GeodeOqlInterpreter.java
@@ -24,6 +24,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -300,7 +301,7 @@ public class GeodeOqlInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/hbase/src/main/java/org/apache/zeppelin/hbase/HbaseInterpreter.java
----------------------------------------------------------------------
diff --git a/hbase/src/main/java/org/apache/zeppelin/hbase/HbaseInterpreter.java b/hbase/src/main/java/org/apache/zeppelin/hbase/HbaseInterpreter.java
index 84e4105..289579f 100644
--- a/hbase/src/main/java/org/apache/zeppelin/hbase/HbaseInterpreter.java
+++ b/hbase/src/main/java/org/apache/zeppelin/hbase/HbaseInterpreter.java
@@ -15,6 +15,7 @@
 package org.apache.zeppelin.hbase;
 
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.jruby.embed.LocalContextScope;
@@ -152,7 +153,7 @@ public class HbaseInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteInterpreter.java
----------------------------------------------------------------------
diff --git a/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteInterpreter.java b/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteInterpreter.java
index 57fa657..8368195 100644
--- a/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteInterpreter.java
+++ b/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteInterpreter.java
@@ -23,6 +23,7 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
 import org.apache.zeppelin.interpreter.*;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -342,7 +343,7 @@ public class IgniteInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return new LinkedList<>();
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteSqlInterpreter.java
----------------------------------------------------------------------
diff --git a/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteSqlInterpreter.java b/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteSqlInterpreter.java
index 15891cc..9a651f8 100644
--- a/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteSqlInterpreter.java
+++ b/ignite/src/main/java/org/apache/zeppelin/ignite/IgniteSqlInterpreter.java
@@ -22,6 +22,7 @@ import org.apache.zeppelin.interpreter.InterpreterException;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -194,7 +195,7 @@ public class IgniteSqlInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return new LinkedList<>();
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
index 610618a..5500ee0 100644
--- a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
+++ b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
@@ -35,6 +35,7 @@ import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -113,7 +114,7 @@ public class JDBCInterpreter extends Interpreter {
         }
       };
 
-  private static final List<String> NO_COMPLETION = new ArrayList<>();
+  private static final List<InterpreterCompletion> NO_COMPLETION = new ArrayList<>();
 
   public JDBCInterpreter(Properties property) {
     super(property);
@@ -438,11 +439,12 @@ public class JDBCInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     List<CharSequence> candidates = new ArrayList<>();
     SqlCompleter sqlCompleter = propertyKeySqlCompleterMap.get(getPropertyKey(buf));
     if (sqlCompleter != null && sqlCompleter.complete(buf, cursor, candidates) >= 0) {
-      return Lists.transform(candidates, sequenceToStringTransformer);
+      List completion = Lists.transform(candidates, sequenceToStringTransformer);
+      return completion;
     } else {
       return NO_COMPLETION;
     }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 e7bba38..72fad1a 100755
--- a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java
+++ b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java
@@ -28,6 +28,7 @@ import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -112,7 +113,7 @@ public class KylinInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 c71dcc0..30e1983 100644
--- a/lens/src/main/java/org/apache/zeppelin/lens/LensInterpreter.java
+++ b/lens/src/main/java/org/apache/zeppelin/lens/LensInterpreter.java
@@ -36,6 +36,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -433,7 +434,7 @@ public class LensInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
   

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java
----------------------------------------------------------------------
diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java
index a24e1ae..4ca629b 100644
--- a/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java
+++ b/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java
@@ -18,6 +18,7 @@
 package org.apache.zeppelin.livy;
 
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -115,7 +116,7 @@ public class LivyPySparkInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java
----------------------------------------------------------------------
diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java
index 0a29d79..e377009 100644
--- a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java
+++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java
@@ -18,6 +18,7 @@
 package org.apache.zeppelin.livy;
 
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -143,7 +144,7 @@ public class LivySparkInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java
----------------------------------------------------------------------
diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java
index a41f4a7..ba929bf 100644
--- a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java
+++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java
@@ -18,6 +18,7 @@
 package org.apache.zeppelin.livy;
 
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -115,7 +116,7 @@ public class LivySparkRInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java
----------------------------------------------------------------------
diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java
index 3637c64..3c60204 100644
--- a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java
+++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java
@@ -18,6 +18,7 @@
 package org.apache.zeppelin.livy;
 
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -158,7 +159,7 @@ public class LivySparkSQLInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 fe96492..a738802 100644
--- a/markdown/src/main/java/org/apache/zeppelin/markdown/Markdown.java
+++ b/markdown/src/main/java/org/apache/zeppelin/markdown/Markdown.java
@@ -26,6 +26,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.InterpreterUtils;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.markdown4j.Markdown4jProcessor;
@@ -87,7 +88,7 @@ public class Markdown extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/phoenix/src/main/java/org/apache/zeppelin/phoenix/PhoenixInterpreter.java
----------------------------------------------------------------------
diff --git a/phoenix/src/main/java/org/apache/zeppelin/phoenix/PhoenixInterpreter.java b/phoenix/src/main/java/org/apache/zeppelin/phoenix/PhoenixInterpreter.java
index c90aece..05d5d31 100644
--- a/phoenix/src/main/java/org/apache/zeppelin/phoenix/PhoenixInterpreter.java
+++ b/phoenix/src/main/java/org/apache/zeppelin/phoenix/PhoenixInterpreter.java
@@ -32,6 +32,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -224,7 +225,7 @@ public class PhoenixInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/postgresql/src/main/java/org/apache/zeppelin/postgresql/PostgreSqlInterpreter.java
----------------------------------------------------------------------
diff --git a/postgresql/src/main/java/org/apache/zeppelin/postgresql/PostgreSqlInterpreter.java b/postgresql/src/main/java/org/apache/zeppelin/postgresql/PostgreSqlInterpreter.java
index f1bcab4..2daa6af 100644
--- a/postgresql/src/main/java/org/apache/zeppelin/postgresql/PostgreSqlInterpreter.java
+++ b/postgresql/src/main/java/org/apache/zeppelin/postgresql/PostgreSqlInterpreter.java
@@ -33,6 +33,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -120,7 +121,7 @@ public class PostgreSqlInterpreter extends Interpreter {
         }
       };
 
-  private static final List<String> NO_COMPLETION = new ArrayList<String>();
+  private static final List NO_COMPLETION = new ArrayList<>();
 
   public PostgreSqlInterpreter(Properties property) {
     super(property);
@@ -321,11 +322,12 @@ public class PostgreSqlInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
 
     List<CharSequence> candidates = new ArrayList<CharSequence>();
     if (sqlCompleter != null && sqlCompleter.complete(buf, cursor, candidates) >= 0) {
-      return Lists.transform(candidates, sequenceToStringTransformer);
+      List completion = Lists.transform(candidates, sequenceToStringTransformer);
+      return completion;
     } else {
       return NO_COMPLETION;
     }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 e80548f..4f390a6 100644
--- a/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java
+++ b/python/src/main/java/org/apache/zeppelin/python/PythonInterpreter.java
@@ -23,6 +23,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Job;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
@@ -175,7 +176,7 @@ public class PythonInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 63c60e2..e0af1d4 100644
--- a/r/src/main/java/org/apache/zeppelin/rinterpreter/KnitR.java
+++ b/r/src/main/java/org/apache/zeppelin/rinterpreter/KnitR.java
@@ -18,6 +18,7 @@
 package org.apache.zeppelin.rinterpreter;
 
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 
 import java.net.URL;
@@ -82,8 +83,9 @@ public class KnitR extends Interpreter implements WrappedInterpreter {
   }
 
   @Override
-  public List<String> completion(String s, int i) {
-    return intp.completion(s, i);
+  public List<InterpreterCompletion> completion(String s, int i) {
+    List completion = intp.completion(s, i);
+    return completion;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 55f7219..220b56e 100644
--- a/r/src/main/java/org/apache/zeppelin/rinterpreter/RRepl.java
+++ b/r/src/main/java/org/apache/zeppelin/rinterpreter/RRepl.java
@@ -18,6 +18,7 @@
 package org.apache.zeppelin.rinterpreter;
 
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 
 import java.net.URL;
@@ -82,8 +83,9 @@ public class RRepl extends Interpreter implements WrappedInterpreter {
   }
 
   @Override
-  public List<String> completion(String s, int i) {
-    return intp.completion(s, i);
+  public List<InterpreterCompletion> completion(String s, int i) {
+    List completion = intp.completion(s, i);
+    return completion;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/r/src/main/scala/org/apache/zeppelin/rinterpreter/RInterpreter.scala
----------------------------------------------------------------------
diff --git a/r/src/main/scala/org/apache/zeppelin/rinterpreter/RInterpreter.scala b/r/src/main/scala/org/apache/zeppelin/rinterpreter/RInterpreter.scala
index 2859f30..959f649 100644
--- a/r/src/main/scala/org/apache/zeppelin/rinterpreter/RInterpreter.scala
+++ b/r/src/main/scala/org/apache/zeppelin/rinterpreter/RInterpreter.scala
@@ -95,12 +95,12 @@ abstract class RInterpreter(properties : Properties, startSpark : Boolean = true
   override def getScheduler : Scheduler = rContext.getScheduler
 
   // TODO:  completion is disabled because it could not be tested with current Zeppelin code
-  def completion(buf :String,cursor : Int) : List[String] = Array[String]("").toList
+  /*def completion(buf :String,cursor : Int) : List[String] = Array[String]("").toList
 
   private[rinterpreter] def hiddenCompletion(buf :String,cursor : Int) : List[String] =
     rContext.evalS1(s"""
        |rzeppelin:::.z.completion("$buf", $cursor)
-     """.stripMargin).toList
+     """.stripMargin).toList*/
 }
 
 object RInterpreter {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/r/src/test/scala/org/apache/zeppelin/rinterpreter/RInterpreterTest.scala
----------------------------------------------------------------------
diff --git a/r/src/test/scala/org/apache/zeppelin/rinterpreter/RInterpreterTest.scala b/r/src/test/scala/org/apache/zeppelin/rinterpreter/RInterpreterTest.scala
index 4b59b00..7208516 100644
--- a/r/src/test/scala/org/apache/zeppelin/rinterpreter/RInterpreterTest.scala
+++ b/r/src/test/scala/org/apache/zeppelin/rinterpreter/RInterpreterTest.scala
@@ -70,10 +70,10 @@ class RInterpreterTest extends FlatSpec {
 
 
 
-  it should "have a functional completion function" taggedAs(RTest) in {
+/*  it should "have a functional completion function" taggedAs(RTest) in {
     val result = rint.hiddenCompletion("hi", 3)
     result should (contain ("hist"))
-  }
+  }*/
 
   it should "have a working progress meter" in {
     rint.getrContext.setProgress(50)

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 4542297..282cd2e 100644
--- a/scalding/src/main/java/org/apache/zeppelin/scalding/ScaldingInterpreter.java
+++ b/scalding/src/main/java/org/apache/zeppelin/scalding/ScaldingInterpreter.java
@@ -24,6 +24,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -53,8 +54,8 @@ public class ScaldingInterpreter extends Interpreter {
   static final String MAX_OPEN_INSTANCES = "max.open.instances";
   static final String MAX_OPEN_INSTANCES_DEFAULT = "50";
 
-  public static final List<String> NO_COMPLETION = 
-    Collections.unmodifiableList(new ArrayList<String>());
+  public static final List NO_COMPLETION =
+    Collections.unmodifiableList(new ArrayList<>());
 
   static {
     Interpreter.register(
@@ -281,7 +282,7 @@ public class ScaldingInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return NO_COMPLETION;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 1331225..8f6f0d0 100644
--- a/shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java
+++ b/shell/src/main/java/org/apache/zeppelin/shell/ShellInterpreter.java
@@ -32,6 +32,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Job;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
@@ -150,7 +151,7 @@ public class ShellInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 f7c164c..28c5885 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/DepInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/DepInterpreter.java
@@ -21,14 +21,14 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.PrintStream;
 import java.io.PrintWriter;
+import java.lang.reflect.Type;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
+import java.util.*;
 
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
 import org.apache.spark.repl.SparkILoop;
 import org.apache.spark.repl.SparkIMain;
 import org.apache.spark.repl.SparkJLineCompletion;
@@ -39,6 +39,7 @@ import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
 import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.WrappedInterpreter;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.spark.dep.SparkDependencyContext;
 import org.slf4j.Logger;
@@ -49,6 +50,7 @@ import org.sonatype.aether.resolution.DependencyResolutionException;
 import scala.Console;
 import scala.None;
 import scala.Some;
+import scala.collection.convert.WrapAsJava$;
 import scala.tools.nsc.Settings;
 import scala.tools.nsc.interpreter.Completion.Candidates;
 import scala.tools.nsc.interpreter.Completion.ScalaCompleter;
@@ -242,10 +244,18 @@ public class DepInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     ScalaCompleter c = completor.completer();
     Candidates ret = c.complete(buf, cursor);
-    return scala.collection.JavaConversions.seqAsJavaList(ret.candidates());
+
+    List<String> candidates = WrapAsJava$.MODULE$.seqAsJavaList(ret.candidates());
+    List<InterpreterCompletion> completions = new LinkedList<InterpreterCompletion>();
+
+    for (String candidate : candidates) {
+      completions.add(new InterpreterCompletion(candidate, candidate));
+    }
+
+    return completions;
   }
 
   private List<File> currentClassPath() {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 1e2ef2e..df9db43 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/PySparkInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/PySparkInterpreter.java
@@ -54,6 +54,7 @@ import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.LazyOpenInterpreter;
 import org.apache.zeppelin.interpreter.WrappedInterpreter;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.spark.dep.SparkDependencyContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -402,7 +403,7 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
 
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     if (buf.length() < cursor) {
       cursor = buf.length();
     }
@@ -413,7 +414,7 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
     SparkInterpreter sparkInterpreter = getSparkInterpreter();
     if (sparkInterpreter.getSparkVersion().isUnsupportedVersion() == false
             && pythonscriptRunning == false) {
-      return new LinkedList<String>();
+      return new LinkedList<>();
     }
 
     pythonInterpretRequest = new PythonInterpretRequest(completionCommand, "");
@@ -430,13 +431,13 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
         } catch (InterruptedException e) {
           // not working
           logger.info("wait drop");
-          return new LinkedList<String>();
+          return new LinkedList<>();
         }
       }
     }
 
     if (statementError) {
-      return new LinkedList<String>();
+      return new LinkedList<>();
     }
     InterpreterResult completionResult = new InterpreterResult(Code.SUCCESS, statementOutput);
     //end code for completion

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 c803cfe..0bbe418 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
@@ -19,10 +19,7 @@ package org.apache.zeppelin.spark;
 
 import java.io.File;
 import java.io.PrintWriter;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import java.lang.reflect.*;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.*;
@@ -30,6 +27,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import com.google.common.base.Joiner;
 
+import com.google.common.reflect.TypeToken;
+import com.google.gson.Gson;
 import org.apache.spark.HttpServer;
 import org.apache.spark.SparkConf;
 import org.apache.spark.SparkContext;
@@ -51,6 +50,7 @@ import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.InterpreterUtils;
 import org.apache.zeppelin.interpreter.WrappedInterpreter;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.apache.zeppelin.spark.dep.SparkDependencyContext;
@@ -63,7 +63,10 @@ import scala.Enumeration.Value;
 import scala.collection.Iterator;
 import scala.collection.JavaConversions;
 import scala.collection.JavaConverters;
+import scala.collection.convert.WrapAsJava;
 import scala.collection.Seq;
+import scala.collection.convert.WrapAsJava$;
+import scala.collection.convert.WrapAsScala;
 import scala.collection.mutable.HashMap;
 import scala.collection.mutable.HashSet;
 import scala.reflect.io.AbstractFile;
@@ -642,7 +645,7 @@ public class SparkInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     if (buf.length() < cursor) {
       cursor = buf.length();
     }
@@ -653,7 +656,15 @@ public class SparkInterpreter extends Interpreter {
     }
     ScalaCompleter c = completor.completer();
     Candidates ret = c.complete(completionText, cursor);
-    return scala.collection.JavaConversions.seqAsJavaList(ret.candidates());
+
+    List<String> candidates = WrapAsJava$.MODULE$.seqAsJavaList(ret.candidates());
+    List<InterpreterCompletion> completions = new LinkedList<InterpreterCompletion>();
+
+    for (String candidate : candidates) {
+      completions.add(new InterpreterCompletion(candidate, candidate));
+    }
+
+    return completions;
   }
 
   private String getCompletionTargetString(String text, int cursor) {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 021c95f..8329641 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/SparkRInterpreter.java
@@ -23,6 +23,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.spark.SparkRBackend;
 import org.apache.zeppelin.interpreter.*;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -166,8 +167,8 @@ public class SparkRInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
-    return new ArrayList<String>();
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
+    return new ArrayList<>();
   }
 
   private SparkInterpreter getSparkInterpreter() {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 ed2e336..a3636a2 100644
--- a/spark/src/main/java/org/apache/zeppelin/spark/SparkSqlInterpreter.java
+++ b/spark/src/main/java/org/apache/zeppelin/spark/SparkSqlInterpreter.java
@@ -34,6 +34,7 @@ import org.apache.zeppelin.interpreter.InterpreterResult;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
 import org.apache.zeppelin.interpreter.LazyOpenInterpreter;
 import org.apache.zeppelin.interpreter.WrappedInterpreter;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -177,7 +178,7 @@ public class SparkSqlInterpreter extends Interpreter {
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     return null;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 3fb4eb4..e20f7c5 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
@@ -21,6 +21,7 @@ import java.net.URL;
 import java.util.List;
 import java.util.Properties;
 
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 
 /**
@@ -151,11 +152,12 @@ public class ClassloaderInterpreter
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
     Thread.currentThread().setContextClassLoader(cl);
     try {
-      return intp.completion(buf, cursor);
+      List completion = intp.completion(buf, cursor);
+      return completion;
     } catch (Exception e) {
       throw new InterpreterException(e);
     } finally {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 1f91938..c52bb4a 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
@@ -27,6 +27,7 @@ import java.util.Properties;
 
 import com.google.gson.annotations.SerializedName;
 import org.apache.zeppelin.annotation.ZeppelinApi;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.slf4j.Logger;
@@ -106,7 +107,9 @@ public abstract class Interpreter {
    * @return list of possible completion. Return empty list if there're nothing to return.
    */
   @ZeppelinApi
-  public abstract List<String> completion(String buf, int cursor);
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
+    return null;
+  }
 
   /**
    * Interpreter can implements it's own scheduler by overriding this method.

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 599a24a..c62ab05 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
@@ -21,6 +21,7 @@ import java.net.URL;
 import java.util.List;
 import java.util.Properties;
 
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.scheduler.Scheduler;
 
 /**
@@ -116,9 +117,10 @@ public class LazyOpenInterpreter
   }
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     open();
-    return intp.completion(buf, cursor);
+    List completion = intp.completion(buf, cursor);
+    return completion;
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 39ddf52..e18edbd 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
@@ -26,6 +26,7 @@ import org.apache.zeppelin.display.GUI;
 import org.apache.zeppelin.display.Input;
 import org.apache.zeppelin.interpreter.*;
 import org.apache.zeppelin.interpreter.InterpreterResult.Type;
+import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
 import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterContext;
 import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterResult;
 import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService.Client;
@@ -377,7 +378,7 @@ public class RemoteInterpreter extends Interpreter {
 
 
   @Override
-  public List<String> completion(String buf, int cursor) {
+  public List<InterpreterCompletion> completion(String buf, int cursor) {
     RemoteInterpreterProcess interpreterProcess = getInterpreterProcess();
     Client client = null;
     try {
@@ -388,7 +389,8 @@ public class RemoteInterpreter extends Interpreter {
 
     boolean broken = false;
     try {
-      return client.completion(noteId, className, buf, cursor);
+      List completion = client.completion(noteId, className, buf, cursor);
+      return completion;
     } catch (TException e) {
       broken = true;
       throw new InterpreterException(e);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 9206e8e..6b4edc4 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
@@ -32,10 +32,7 @@ import org.apache.thrift.transport.TTransportException;
 import org.apache.zeppelin.display.*;
 import org.apache.zeppelin.interpreter.*;
 import org.apache.zeppelin.interpreter.InterpreterResult.Code;
-import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterContext;
-import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterEvent;
-import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterResult;
-import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService;
+import org.apache.zeppelin.interpreter.thrift.*;
 import org.apache.zeppelin.resource.*;
 import org.apache.zeppelin.scheduler.Job;
 import org.apache.zeppelin.scheduler.Job.Status;
@@ -415,10 +412,12 @@ public class RemoteInterpreterServer
   }
 
   @Override
-  public List<String> completion(String noteId, String className, String buf, int cursor)
+  public List<InterpreterCompletion> completion(String noteId,
+      String className, String buf, int cursor)
       throws TException {
     Interpreter intp = getInterpreter(noteId, className);
-    return intp.completion(buf, cursor);
+    List completion = intp.completion(buf, cursor);
+    return completion;
   }
 
   private InterpreterContext convert(RemoteInterpreterContext ric) {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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
new file mode 100644
index 0000000..9ceba88
--- /dev/null
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/InterpreterCompletion.java
@@ -0,0 +1,520 @@
+/**
+ * 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.
+ */
+/**
+ * Autogenerated by Thrift Compiler (0.9.2)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.zeppelin.interpreter.thrift;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import javax.annotation.Generated;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2016-6-8")
+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 Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+  static {
+    schemes.put(StandardScheme.class, new InterpreterCompletionStandardSchemeFactory());
+    schemes.put(TupleScheme.class, new InterpreterCompletionTupleSchemeFactory());
+  }
+
+  public String name; // required
+  public String value; // 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");
+
+    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // NAME
+          return NAME;
+        case 2: // VALUE
+          return VALUE;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.DEFAULT, 
+        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)));
+    metaDataMap = Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(InterpreterCompletion.class, metaDataMap);
+  }
+
+  public InterpreterCompletion() {
+  }
+
+  public InterpreterCompletion(
+    String name,
+    String value)
+  {
+    this();
+    this.name = name;
+    this.value = value;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public InterpreterCompletion(InterpreterCompletion other) {
+    if (other.isSetName()) {
+      this.name = other.name;
+    }
+    if (other.isSetValue()) {
+      this.value = other.value;
+    }
+  }
+
+  public InterpreterCompletion deepCopy() {
+    return new InterpreterCompletion(this);
+  }
+
+  @Override
+  public void clear() {
+    this.name = null;
+    this.value = null;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public InterpreterCompletion setName(String name) {
+    this.name = name;
+    return this;
+  }
+
+  public void unsetName() {
+    this.name = null;
+  }
+
+  /** Returns true if field name is set (has been assigned a value) and false otherwise */
+  public boolean isSetName() {
+    return this.name != null;
+  }
+
+  public void setNameIsSet(boolean value) {
+    if (!value) {
+      this.name = null;
+    }
+  }
+
+  public String getValue() {
+    return this.value;
+  }
+
+  public InterpreterCompletion setValue(String value) {
+    this.value = value;
+    return this;
+  }
+
+  public void unsetValue() {
+    this.value = null;
+  }
+
+  /** Returns true if field value is set (has been assigned a value) and false otherwise */
+  public boolean isSetValue() {
+    return this.value != null;
+  }
+
+  public void setValueIsSet(boolean value) {
+    if (!value) {
+      this.value = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case NAME:
+      if (value == null) {
+        unsetName();
+      } else {
+        setName((String)value);
+      }
+      break;
+
+    case VALUE:
+      if (value == null) {
+        unsetValue();
+      } else {
+        setValue((String)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case NAME:
+      return getName();
+
+    case VALUE:
+      return getValue();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case NAME:
+      return isSetName();
+    case VALUE:
+      return isSetValue();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof InterpreterCompletion)
+      return this.equals((InterpreterCompletion)that);
+    return false;
+  }
+
+  public boolean equals(InterpreterCompletion that) {
+    if (that == null)
+      return false;
+
+    boolean this_present_name = true && this.isSetName();
+    boolean that_present_name = true && that.isSetName();
+    if (this_present_name || that_present_name) {
+      if (!(this_present_name && that_present_name))
+        return false;
+      if (!this.name.equals(that.name))
+        return false;
+    }
+
+    boolean this_present_value = true && this.isSetValue();
+    boolean that_present_value = true && that.isSetValue();
+    if (this_present_value || that_present_value) {
+      if (!(this_present_value && that_present_value))
+        return false;
+      if (!this.value.equals(that.value))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    List<Object> list = new ArrayList<Object>();
+
+    boolean present_name = true && (isSetName());
+    list.add(present_name);
+    if (present_name)
+      list.add(name);
+
+    boolean present_value = true && (isSetValue());
+    list.add(present_value);
+    if (present_value)
+      list.add(value);
+
+    return list.hashCode();
+  }
+
+  @Override
+  public int compareTo(InterpreterCompletion other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetName()).compareTo(other.isSetName());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetName()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetValue()).compareTo(other.isSetValue());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetValue()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.value, other.value);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("InterpreterCompletion(");
+    boolean first = true;
+
+    sb.append("name:");
+    if (this.name == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.name);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("value:");
+    if (this.value == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.value);
+    }
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class InterpreterCompletionStandardSchemeFactory implements SchemeFactory {
+    public InterpreterCompletionStandardScheme getScheme() {
+      return new InterpreterCompletionStandardScheme();
+    }
+  }
+
+  private static class InterpreterCompletionStandardScheme extends StandardScheme<InterpreterCompletion> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, InterpreterCompletion struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // NAME
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.name = iprot.readString();
+              struct.setNameIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 2: // VALUE
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.value = iprot.readString();
+              struct.setValueIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+
+      // check for required fields of primitive type, which can't be checked in the validate method
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, InterpreterCompletion struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (struct.name != null) {
+        oprot.writeFieldBegin(NAME_FIELD_DESC);
+        oprot.writeString(struct.name);
+        oprot.writeFieldEnd();
+      }
+      if (struct.value != null) {
+        oprot.writeFieldBegin(VALUE_FIELD_DESC);
+        oprot.writeString(struct.value);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class InterpreterCompletionTupleSchemeFactory implements SchemeFactory {
+    public InterpreterCompletionTupleScheme getScheme() {
+      return new InterpreterCompletionTupleScheme();
+    }
+  }
+
+  private static class InterpreterCompletionTupleScheme extends TupleScheme<InterpreterCompletion> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, InterpreterCompletion struct) throws org.apache.thrift.TException {
+      TTupleProtocol oprot = (TTupleProtocol) prot;
+      BitSet optionals = new BitSet();
+      if (struct.isSetName()) {
+        optionals.set(0);
+      }
+      if (struct.isSetValue()) {
+        optionals.set(1);
+      }
+      oprot.writeBitSet(optionals, 2);
+      if (struct.isSetName()) {
+        oprot.writeString(struct.name);
+      }
+      if (struct.isSetValue()) {
+        oprot.writeString(struct.value);
+      }
+    }
+
+    @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);
+      if (incoming.get(0)) {
+        struct.name = iprot.readString();
+        struct.setNameIsSet(true);
+      }
+      if (incoming.get(1)) {
+        struct.value = iprot.readString();
+        struct.setValueIsSet(true);
+      }
+    }
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/7b00dffd/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 889e45d..f8b63ff 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
@@ -1,4 +1,21 @@
 /**
+ * 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.
+ */
+/**
  * Autogenerated by Thrift Compiler (0.9.2)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
@@ -34,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 = "2016-3-17")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2016-6-8")
 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/7b00dffd/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 c89a287..0db5697 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
@@ -1,4 +1,21 @@
 /**
+ * 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.
+ */
+/**
  * Autogenerated by Thrift Compiler (0.9.2)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
@@ -34,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 = "2016-3-17")
+@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2016-6-8")
 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/7b00dffd/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEventType.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEventType.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEventType.java
index 8db330a..66631d2 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEventType.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/thrift/RemoteInterpreterEventType.java
@@ -1,4 +1,21 @@
 /**
+ * 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.
+ */
+/**
  * Autogenerated by Thrift Compiler (0.9.2)
  *
  * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING