Added autocompletion on Tab
This commit is contained in:
parent
d5cc078480
commit
09221c5a6c
2 changed files with 226 additions and 74 deletions
|
@ -9,6 +9,8 @@ import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.command.*;
|
import org.bukkit.command.*;
|
||||||
|
@ -22,9 +24,11 @@ public class ScriptCraftPlugin extends JavaPlugin
|
||||||
//protected Map<CommandSender,ScriptCraftEvaluator> playerContexts = new HashMap<CommandSender,ScriptCraftEvaluator>();
|
//protected Map<CommandSender,ScriptCraftEvaluator> playerContexts = new HashMap<CommandSender,ScriptCraftEvaluator>();
|
||||||
protected ScriptEngine engine = null;
|
protected ScriptEngine engine = null;
|
||||||
private static final String JS_PLUGINS_DIR = "js-plugins";
|
private static final String JS_PLUGINS_DIR = "js-plugins";
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void onEnable()
|
* Unzips bundled javascript code.
|
||||||
|
*/
|
||||||
|
private void unzipJS()
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// does the js-plugins directory exist?
|
// does the js-plugins directory exist?
|
||||||
|
@ -66,6 +70,12 @@ public class ScriptCraftPlugin extends JavaPlugin
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable()
|
||||||
|
{
|
||||||
|
unzipJS();
|
||||||
|
|
||||||
if (this.engine == null){
|
if (this.engine == null){
|
||||||
try{
|
try{
|
||||||
|
@ -81,6 +91,28 @@ public class ScriptCraftPlugin extends JavaPlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public List<String> onTabComplete(CommandSender sender, Command cmd,
|
||||||
|
String alias,
|
||||||
|
String[] args)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// delegate to javascript
|
||||||
|
//
|
||||||
|
List<String> result = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
this.engine.put("__onTC_result",result);
|
||||||
|
this.engine.put("__onTC_sender",sender);
|
||||||
|
this.engine.put("__onTC_cmd",cmd);
|
||||||
|
this.engine.put("__onTC_alias",alias);
|
||||||
|
this.engine.put("__onTC_args",args);
|
||||||
|
this.engine.eval("_onTabComplete()");
|
||||||
|
}catch (Exception e){
|
||||||
|
sender.sendMessage(e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
|
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
|
||||||
{
|
{
|
||||||
if(cmd.getName().equalsIgnoreCase("js"))
|
if(cmd.getName().equalsIgnoreCase("js"))
|
||||||
|
|
|
@ -5,80 +5,200 @@ ScriptCraft.core = ScriptCraft.core || {};
|
||||||
// private implementation
|
// private implementation
|
||||||
//
|
//
|
||||||
(function(){
|
(function(){
|
||||||
//
|
//
|
||||||
// don't execute this more than once
|
// don't execute this more than once
|
||||||
//
|
//
|
||||||
if (typeof load == "function")
|
if (typeof load == "function")
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
var _originalScript = __script;
|
var _originalScript = __script;
|
||||||
importPackage(java.io);
|
importPackage(java.io);
|
||||||
var _canonize = function(file){
|
var _canonize = function(file){
|
||||||
return file.getCanonicalPath().replaceAll("\\\\","/");
|
return file.getCanonicalPath().replaceAll("\\\\","/");
|
||||||
};
|
};
|
||||||
var _load = function(filename){
|
var _load = function(filename){
|
||||||
var file = new File(filename);
|
var file = new File(filename);
|
||||||
print("loading " + _canonize(file));
|
print("loading " + _canonize(file));
|
||||||
if (file.exists()){
|
if (file.exists()){
|
||||||
var parent = file.getParentFile();
|
var parent = file.getParentFile();
|
||||||
var reader = new FileReader(file);
|
var reader = new FileReader(file);
|
||||||
__engine.put("__script",_canonize(file));
|
__engine.put("__script",_canonize(file));
|
||||||
__engine.put("__folder",(parent?_canonize(parent):"")+"/");
|
__engine.put("__folder",(parent?_canonize(parent):"")+"/");
|
||||||
__engine.eval(reader);
|
__engine.eval(reader);
|
||||||
}else{
|
}else{
|
||||||
print("Error: " + filename + " not found");
|
print("Error: " + filename + " not found");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var _listJsFiles = function(store,dir)
|
var _listJsFiles = function(store,dir)
|
||||||
{
|
{
|
||||||
if (typeof dir == "undefined"){
|
if (typeof dir == "undefined"){
|
||||||
dir = new File(_originalScript).getParentFile().getParentFile();
|
dir = new File(_originalScript).getParentFile().getParentFile();
|
||||||
}
|
}
|
||||||
var files = dir.listFiles();
|
var files = dir.listFiles();
|
||||||
for (var i = 0;i < files.length; i++){
|
for (var i = 0;i < files.length; i++){
|
||||||
if (files[i].isDirectory()){
|
if (files[i].isDirectory()){
|
||||||
_listJsFiles(store,files[i]);
|
_listJsFiles(store,files[i]);
|
||||||
}else{
|
}else{
|
||||||
if (files[i].getCanonicalPath().endsWith(".js") &&
|
if (files[i].getCanonicalPath().endsWith(".js") &&
|
||||||
!(files[i].getName().startsWith("_")))
|
!(files[i].getName().startsWith("_")))
|
||||||
{
|
{
|
||||||
store.push(files[i]);
|
store.push(files[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var _reload = function(pluginDir)
|
var _reload = function(pluginDir)
|
||||||
{
|
{
|
||||||
var jsFiles = [];
|
var jsFiles = [];
|
||||||
_listJsFiles(jsFiles,pluginDir);
|
_listJsFiles(jsFiles,pluginDir);
|
||||||
//
|
//
|
||||||
// script files whose name begins with _ (underscore)
|
// script files whose name begins with _ (underscore)
|
||||||
// will not be loaded automatically at startup.
|
// will not be loaded automatically at startup.
|
||||||
// These files are assumed to be dependencies/private to plugins
|
// These files are assumed to be dependencies/private to plugins
|
||||||
//
|
//
|
||||||
// E.g. If you have a plugin called myMiniGame.js in the myMiniGame directory
|
// E.g. If you have a plugin called myMiniGame.js in the myMiniGame directory
|
||||||
// and which in addition to myMiniGame.js also includes _myMiniGame_currency.js _myMiniGame_events.js etc.
|
// and which in addition to myMiniGame.js also includes _myMiniGame_currency.js _myMiniGame_events.js etc.
|
||||||
// then it's assumed that _myMiniGame_currency.js and _myMiniGame_events.js will be loaded
|
// then it's assumed that _myMiniGame_currency.js and _myMiniGame_events.js will be loaded
|
||||||
// as dependencies by myMiniGame.js and do not need to be loaded via js reload
|
// as dependencies by myMiniGame.js and do not need to be loaded via js reload
|
||||||
//
|
//
|
||||||
for (var i = 0;i < jsFiles.length; i++){
|
for (var i = 0;i < jsFiles.length; i++){
|
||||||
load(_canonize(jsFiles[i]));
|
load(_canonize(jsFiles[i]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ScriptCraft.core.load = _load;
|
var _isJavaObject = function(o){
|
||||||
ScriptCraft.core.reload = _reload;
|
var result = false;
|
||||||
|
try {
|
||||||
|
o.hasOwnProperty("testForJava");
|
||||||
|
}catch (e){
|
||||||
|
// java will throw an error when an attempt is made to access the
|
||||||
|
// hasOwnProperty method. (it won't exist for Java objects)
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
var _javaLangObjectMethods = ["equals","getClass","class","getClass","hashCode","notify","notifyAll","toString","wait","clone","finalize"];
|
||||||
|
var _getProperties = function(o)
|
||||||
|
{
|
||||||
|
var result = [];
|
||||||
|
if (_isJavaObject(o)){
|
||||||
|
propertyLoop:
|
||||||
|
for (var i in o){
|
||||||
|
//
|
||||||
|
// don't include standard Object methods
|
||||||
|
//
|
||||||
|
var isObjectMethod = false;
|
||||||
|
for (var j = 0;j < _javaLangObjectMethods.length; j++)
|
||||||
|
if (_javaLangObjectMethods[j] == i)
|
||||||
|
continue propertyLoop;
|
||||||
|
if (typeof o[i] == "function")
|
||||||
|
result.push(i+"()");
|
||||||
|
else
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
for (var i in o){
|
||||||
|
if (!o.hasOwnProperty(i))
|
||||||
|
continue;
|
||||||
|
if (i.match(/^[^_]/)){
|
||||||
|
if (typeof o[i] == "function")
|
||||||
|
result.push(i+"()");
|
||||||
|
else
|
||||||
|
result.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.sort();
|
||||||
|
};
|
||||||
|
|
||||||
for (var f in ScriptCraft.core){
|
var __onTabComplete2 = function()
|
||||||
global[f] = ScriptCraft.core[f];
|
{
|
||||||
}
|
var _globalSymbols = _getProperties(global)
|
||||||
ScriptCraft.core.initialized = true;
|
var result = global.__onTC_result;
|
||||||
//
|
var args = global.__onTC_args;
|
||||||
// assumes this was loaded from js-plugins/core/
|
var propsOfLastArg = [];
|
||||||
//
|
var statement = args.join(" ");
|
||||||
reload(new File(__script).getParentFile().getParentFile());
|
statement = statement.replace(/^\s+/,"").replace(/\s+$/,"");
|
||||||
|
|
||||||
|
if (statement.length == 0){
|
||||||
|
propsOfLastArg = _globalSymbols;
|
||||||
|
}else{
|
||||||
|
var statementSyms = statement.split(/[^a-zA-Z0-9_\.]/);
|
||||||
|
var lastSymbol = statementSyms[statementSyms.length-1];
|
||||||
|
//
|
||||||
|
// try to complete the object ala java IDEs.
|
||||||
|
//
|
||||||
|
var parts = lastSymbol.split(/\./);
|
||||||
|
var name = parts[0];
|
||||||
|
var symbol = global[name];
|
||||||
|
var lastGoodSymbol = symbol;
|
||||||
|
if (typeof symbol != "undefined")
|
||||||
|
{
|
||||||
|
for (var i = 1; i < parts.length;i++){
|
||||||
|
name = parts[i];
|
||||||
|
symbol = symbol[name];
|
||||||
|
if (typeof symbol == "undefined")
|
||||||
|
break;
|
||||||
|
lastGoodSymbol = symbol;
|
||||||
|
}
|
||||||
|
if (typeof symbol == "undefined"){
|
||||||
|
//
|
||||||
|
// look up partial matches against last good symbol
|
||||||
|
//
|
||||||
|
var objectProps = _getProperties(lastGoodSymbol);
|
||||||
|
if (name == ""){
|
||||||
|
// if the last symbol looks like this..
|
||||||
|
// ScriptCraft.
|
||||||
|
//
|
||||||
|
for (var i =0;i < objectProps.length;i++)
|
||||||
|
propsOfLastArg.push(statement+objectProps[i]);;
|
||||||
|
}else{
|
||||||
|
// it looks like this..
|
||||||
|
// ScriptCraft.co
|
||||||
|
//
|
||||||
|
var li = statement.lastIndexOf(name);
|
||||||
|
statement = statement.substring(0,li);
|
||||||
|
|
||||||
|
for (var i = 0; i < objectProps.length;i++){
|
||||||
|
if (objectProps[i].indexOf(name) == 0){
|
||||||
|
propsOfLastArg.push(statement + objectProps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
var objectProps = _getProperties(symbol);
|
||||||
|
for (var i = 0; i < objectProps.length; i++){
|
||||||
|
propsOfLastArg.push(statement + objectProps[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// loop thru globalSymbols looking for a good match
|
||||||
|
for (var i = 0;i < _globalSymbols.length; i++){
|
||||||
|
if (_globalSymbols[i].indexOf(lastSymbol) == 0){
|
||||||
|
propsOfLastArg.push(statement.replace(lastSymbol,_globalSymbols[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0;i < propsOfLastArg.length; i++){
|
||||||
|
result.add(propsOfLastArg[i]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
global._onTabComplete = __onTabComplete2;
|
||||||
|
|
||||||
|
|
||||||
|
ScriptCraft.core.load = _load;
|
||||||
|
ScriptCraft.core.reload = _reload;
|
||||||
|
|
||||||
|
for (var f in ScriptCraft.core){
|
||||||
|
global[f] = ScriptCraft.core[f];
|
||||||
|
}
|
||||||
|
ScriptCraft.core.initialized = true;
|
||||||
|
//
|
||||||
|
// assumes this was loaded from js-plugins/core/
|
||||||
|
//
|
||||||
|
reload(new File(__script).getParentFile().getParentFile());
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in a new issue