add multi-line string support

This commit is contained in:
hyb1996 2017-05-15 19:47:58 +08:00
parent 8ac9a518d7
commit 91a1cb77d8
9 changed files with 312 additions and 18 deletions

View File

@ -0,0 +1,58 @@
"ui";
ui.statusBarColor("#000000")
showLoginUI();
//显示登录界面
function showLoginUI(){
ui.layout(`
<frame>
<vertical h="auto" align="center" margin="0 50">
<linear>
<text w="56" gravity="center" color="#111" size="16">用户名</text>
<input id="name" w="*" h="40"/>
</linear>
<linear>
<text w="56" gravity="center" color="#111" size="16">密码</text>
<input id="password" w="*" h="40" inputType="password"/>
</linear>
<linear gravity="center">
<button id="login" text="登录"/>
<button id="register" text="注册"/>
</linear>
</vertical>
</frame>
`);
ui.login.click(() => {
toast("您输入的用户名为" + ui.name.text() + " 密码为" + ui.password.text());
});
ui.register.click(() => showRegisterUI());
}
//显示注册界面
function showRegisterUI(){
ui.layout(`
<frame>
<vertical h="auto" align="center" margin="0 50">
<linear>
<text w="56" gravity="center" color="#111" size="16">用户名</text>
<input w="*" h="40"/>
</linear>
<linear>
<text w="56" gravity="center" color="#111" size="16">密码</text>
<input w="*" h="40" inputType="password"/>
</linear>
<linear>
<text w="56" gravity="center" color="#111" size="16">邮箱</text>
<input w="*" h="40" inputType="email"/>
</linear>
<linear gravity="center">
<button>确定</button>
<button id="cancel">取消</button>
</linear>
</vertical>
</frame>
`);
ui.cancel.click(() => showLoginUI());
}

View File

@ -1,5 +1,6 @@
module.exports = function(__runtime__, scope){
var ui = Object(__runtime__.ui);
ui.__id_cache__ = {};
ui.layout = function(xml){
view = ui.inflate(activity, xml);
@ -8,6 +9,7 @@ module.exports = function(__runtime__, scope){
ui.setContentView = function(view){
ui.view = view;
ui.__id_cache__ = {};
activity.setContentView(view);
}
@ -31,6 +33,13 @@ module.exports = function(__runtime__, scope){
__runtime__.getUiHandler().postDelay(action, delay);
}
ui.statusBarColor = function(color){
if(typeof(color) == 'string'){
color = android.graphics.Color.parseColor(color);
}
activity.getWindow().setStatusBarColor(color);
}
function decorate(view){
var view = Object.create(view);
view._id = function(id){
@ -59,10 +68,14 @@ module.exports = function(__runtime__, scope){
},
get: function(name, start) {
if(!ui[name]){
var widget = ui.id(name);
if(widget){
ui[name] = widget;
return widget;
var cacheView = ui.__id_cache__[name];
if(cacheView){
return cacheView;
}
cacheView = ui.id(name);
if(cacheView){
ui.__id_cache__[name] = cacheView;
return cacheView;
}
}
return ui[name];

View File

@ -0,0 +1,99 @@
package com.stardust.autojs.engine;
import android.support.annotation.VisibleForTesting;
import com.stardust.autojs.engine.preprocess.AbstractProcessor;
import java.io.Reader;
import java.io.StringReader;
/**
* Created by Stardust on 2017/5/15.
*/
public class MultiLinePreprocessor extends AbstractProcessor {
private static final int STATE_SINGLE_QUOTE_LITERAL = 0x00000001;
private static final int STATE_DOUBLE_QUOTE_LITERAL = 0x00000010;
private static final int STATE_MULTI_LINE = 0x00001100;
private int mState = 0;
private int mStateBeforeLiteral = 0;
private StringBuilder mNewScript;
private int mLastReturnCharPosition;
private int i;
@Override
protected void handleChar(int ch) {
boolean shouldAppend = true;
switch (ch) {
case '"':
if (mState == STATE_DOUBLE_QUOTE_LITERAL) {
mState = mStateBeforeLiteral;
} else if (mState != STATE_SINGLE_QUOTE_LITERAL) {
mStateBeforeLiteral = mState;
mState = STATE_DOUBLE_QUOTE_LITERAL;
}
break;
case '\'':
if (mState == STATE_SINGLE_QUOTE_LITERAL) {
if ((mStateBeforeLiteral & STATE_MULTI_LINE) != 0) {
mNewScript.append('\\');
}
mState = mStateBeforeLiteral;
} else if (mState != STATE_DOUBLE_QUOTE_LITERAL) {
mStateBeforeLiteral = mState;
mState = STATE_SINGLE_QUOTE_LITERAL;
if ((mStateBeforeLiteral & STATE_MULTI_LINE) != 0) {
mNewScript.append('\\');
}
}
break;
case '`':
if (mState == 0) {
mState = STATE_MULTI_LINE;
mNewScript.append("'");
shouldAppend = false;
} else if (mState == STATE_MULTI_LINE) {
mState = 0;
mNewScript.append("'");
shouldAppend = false;
}
break;
case '\r':
case '\n':
if (ch == '\n' && mLastReturnCharPosition == i - 1) {
shouldAppend = false;
break;
}
if (ch == '\r')
mLastReturnCharPosition = i;
if (mState == STATE_MULTI_LINE) {
mNewScript.append("\\n'+\n'");
shouldAppend = false;
}
break;
}
if (shouldAppend) {
mNewScript.append((char) ch);
}
i++;
}
@Override
public void reset() {
mState = 0;
mStateBeforeLiteral = 0;
mNewScript = new StringBuilder();
mLastReturnCharPosition = -2;
i = 0;
}
@Override
public Reader getReaderAndClear() {
Reader reader = new StringReader(mNewScript.toString());
mNewScript = null;
return reader;
}
}

View File

@ -2,6 +2,7 @@ package com.stardust.autojs.engine;
import android.util.Log;
import com.stardust.autojs.engine.preprocess.Preprocessor;
import com.stardust.autojs.rhino_android.AndroidContextFactory;
import com.stardust.autojs.rhino_android.RhinoAndroidHelper;
import com.stardust.autojs.runtime.ScriptInterruptedException;
@ -10,27 +11,23 @@ import com.stardust.pio.UncheckedIOException;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.ErrorReporter;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.commonjs.module.RequireBuilder;
import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider;
import org.mozilla.javascript.xmlimpl.XMLLibImpl;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.xml.parsers.DocumentBuilderFactory;
/**
* Created by Stardust on 2017/4/2.
*/
@ -38,6 +35,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
public class RhinoJavaScriptEngine implements ScriptEngine {
private static final String LOG_TAG = "RhinoJavaScriptEngine";
private static final Preprocessor PREPROCESSOR = new MultiLinePreprocessor();
private static int contextCount = 0;
private String[] mRequirePath = new String[0];
@ -62,17 +60,19 @@ public class RhinoJavaScriptEngine implements ScriptEngine {
@Override
public Object execute(ScriptSource source) {
Reader reader = source.getScriptReader();
if (reader == null) {
return mContext.evaluateString(mScriptable, source.getScript(), "<script>", 1, null);
}
Reader reader = source.getNonNullScriptReader();
try {
return mContext.evaluateReader(mScriptable, source.getScriptReader(), "<script>", 1, null);
reader = preprocess(reader);
return mContext.evaluateReader(mScriptable, reader, "<script>", 1, null);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
private Reader preprocess(Reader script) throws IOException {
return PREPROCESSOR.preprocess(script);
}
@Override
public void forceStop() {
Log.d(LOG_TAG, "forceStop: interrupt Thread: " + mThread);

View File

@ -0,0 +1,31 @@
package com.stardust.autojs.engine.preprocess;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
/**
* Created by Stardust on 2017/5/15.
*/
public abstract class AbstractProcessor implements Preprocessor {
@Override
public Reader preprocess(Reader reader) throws IOException {
reset();
int ch;
if (!(reader instanceof BufferedReader))
reader = new BufferedReader(reader);
while ((ch = reader.read()) != -1) {
handleChar(ch);
}
return getReaderAndClear();
}
protected abstract void handleChar(int ch);
public abstract void reset();
public abstract Reader getReaderAndClear();
}

View File

@ -0,0 +1,13 @@
package com.stardust.autojs.engine.preprocess;
import java.io.IOException;
import java.io.Reader;
/**
* Created by Stardust on 2017/5/15.
*/
public interface Preprocessor {
Reader preprocess(Reader reader) throws IOException;
}

View File

@ -3,6 +3,7 @@ package com.stardust.autojs.execution;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
@ -29,6 +30,7 @@ public class ScriptExecuteActivity extends AppCompatActivity {
if (execution != null) {
return null;
}
execution = new ActivityScriptExecution(service, task);
context.startActivity(new Intent(context, ScriptExecuteActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));

View File

@ -11,6 +11,7 @@ import android.support.annotation.Nullable;
import com.stardust.autojs.runtime.ScriptInterface;
import com.stardust.util.IntentUtil;
import java.lang.ref.WeakReference;
import java.util.List;
/**
@ -20,7 +21,7 @@ import java.util.List;
public class AppUtils {
private Context mContext;
private Activity mCurrentActivity;
private WeakReference<Activity> mCurrentActivity;
public AppUtils(Context context) {
mContext = context;
@ -62,7 +63,7 @@ public class AppUtils {
@Nullable
public Activity getCurrentActivity() {
return mCurrentActivity;
return mCurrentActivity.get();
}
@ScriptInterface
@ -72,6 +73,6 @@ public class AppUtils {
}
public void setCurrentActivity(Activity currentActivity) {
mCurrentActivity = currentActivity;
mCurrentActivity = new WeakReference<>(currentActivity);
}
}

View File

@ -0,0 +1,77 @@
package com.stardust.autojs.engine;
import org.junit.Test;
import java.io.Reader;
import java.io.StringReader;
import static org.junit.Assert.*;
import static com.stardust.autojs.engine.MultiLinePreprocessor.*;
/**
* Created by Stardust on 2017/5/15.
*/
public class MultiLinePreprocessorTest {
@Test
public void test1() throws Exception {
process("(`2\n3\n4`)0\n0");
}
@Test
public void test2() throws Exception {
process("(`\n23\n4`)0\n0");
}
@Test
public void test3() throws Exception {
process("(`\n1\n23\n`)0\n0");
}
@Test
public void test4() throws Exception {
process("(2`\n\"999\"\n3`)0\n0");
}
@Test
public void test5() throws Exception {
process("(2`\n\"99`99\"\n3`)0\n0");
}
@Test
public void test6() throws Exception {
process("(2`\n'999'\n3`)0\n0");
}
@Test
public void test7() throws Exception {
process("12'345\"6789'\n");
}
@Test
public void test8() throws Exception {
process("12\"345\"6789'\n\"'''");
}
@Test
public void test9() throws Exception {
process("(2`\n\"99`88'7799\"\n3`)0\n0");
}
@Test
public void test10() throws Exception {
process("(`\r\n1\r\n23\r\n`)0\r\n0");
}
private void process(String s) throws Exception {
MultiLinePreprocessor preprocessor = new MultiLinePreprocessor();
Reader reader = preprocessor.preprocess(new StringReader(s));
int ch;
while ((ch = reader.read()) != -1) {
System.out.print((char) ch);
}
System.out.println();
}
}