imporve code completion
This commit is contained in:
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -48,7 +48,7 @@
|
|||||||
<ConfirmationsSetting value="0" id="Add" />
|
<ConfirmationsSetting value="0" id="Add" />
|
||||||
<ConfirmationsSetting value="0" id="Remove" />
|
<ConfirmationsSetting value="0" id="Remove" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "com.stardust.scriptdroid"
|
applicationId "com.stardust.scriptdroid"
|
||||||
minSdkVersion 17
|
minSdkVersion 17
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 153
|
versionCode 154
|
||||||
versionName "2.0.15 Beta"
|
versionName "2.0.15 Alpha2"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
ndk {
|
ndk {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
返回路径path是否是文件夹。
|
返回路径path是否是文件夹。
|
||||||
|
|
||||||
### files.isDirEmpty(path)
|
### files.isEmptyDir(path)
|
||||||
* path \<String\> 路径
|
* path \<String\> 路径
|
||||||
|
|
||||||
返回文件夹path是否为空文件夹。如果该路径并非文件夹,则直接返回false。
|
返回文件夹path是否为空文件夹。如果该路径并非文件夹,则直接返回false。
|
||||||
|
|||||||
@@ -1,62 +1,305 @@
|
|||||||
[ "toast",
|
{
|
||||||
"app",
|
"global" : {
|
||||||
"launchPackage",
|
"modules": [
|
||||||
"launch",
|
"app",
|
||||||
"launchApp",
|
"automator",
|
||||||
"getPackageName",
|
"console",
|
||||||
"openAppSetting",
|
"dialogs",
|
||||||
"sleep",
|
"events",
|
||||||
"isStopped",
|
"images",
|
||||||
"notStopped",
|
"files",
|
||||||
"stop",
|
"timers",
|
||||||
"console",
|
"ui"
|
||||||
"log",
|
],
|
||||||
"print",
|
"app": [
|
||||||
"err",
|
"launchPackage",
|
||||||
"openConsole",
|
"launch",
|
||||||
"clearConsole",
|
"launchApp",
|
||||||
"shell",
|
"getPackageName",
|
||||||
"currentPackage",
|
"openAppSetting"
|
||||||
"currentActivity",
|
],
|
||||||
"back",
|
"automator": [
|
||||||
"home",
|
"click",
|
||||||
"powerDialog",
|
"longClick",
|
||||||
"notifications",
|
"press",
|
||||||
"quickSettings",
|
"swipe",
|
||||||
"recents",
|
"gesture",
|
||||||
"splitScreen",
|
"gestures",
|
||||||
"click",
|
"gestureAsync",
|
||||||
"longClick",
|
"gesturesAsync",
|
||||||
"scrollDown",
|
"scrollDown",
|
||||||
"scrollUp",
|
"scrollUp",
|
||||||
"input",
|
"input",
|
||||||
"setClip",
|
"setText"
|
||||||
"SetScreenMetrics",
|
],
|
||||||
"Tap",
|
"console": [
|
||||||
"Swipe",
|
"print",
|
||||||
"Screencap",
|
"log",
|
||||||
"KeyCode",
|
"err",
|
||||||
"Home",
|
"openConsole",
|
||||||
"Back",
|
"clearConsole"
|
||||||
"Power",
|
],
|
||||||
"Up",
|
"dialogs":[
|
||||||
"Down",
|
"rawInput",
|
||||||
"Left",
|
"input",
|
||||||
"Right",
|
"alert",
|
||||||
"OK",
|
"confirm",
|
||||||
"VolumeUp",
|
"prompt"
|
||||||
"VolumeDown",
|
],
|
||||||
"Menu",
|
"images": [
|
||||||
"Camera",
|
"requestScreenCapture",
|
||||||
"Text",
|
"captureScreen",
|
||||||
"selector",
|
"findColor",
|
||||||
"open",
|
"findColorInRegion",
|
||||||
"newInjectableWebClient",
|
"findColorEquals"
|
||||||
"newInjectableWebView",
|
],
|
||||||
"dialogs",
|
"files": [
|
||||||
"rawInput",
|
"open"
|
||||||
"input",
|
],
|
||||||
"alert",
|
"selector": [
|
||||||
"confirm",
|
"id",
|
||||||
"prompt"
|
"idContains",
|
||||||
]
|
"idStartsWith",
|
||||||
|
"idEndsWith",
|
||||||
|
"idMatches",
|
||||||
|
"text",
|
||||||
|
"textContains",
|
||||||
|
"textStartsWith",
|
||||||
|
"textEndsWith",
|
||||||
|
"textMatches",
|
||||||
|
"desc",
|
||||||
|
"descContains",
|
||||||
|
"descStartsWith",
|
||||||
|
"descEndsWith",
|
||||||
|
"descMatches",
|
||||||
|
"className",
|
||||||
|
"classNameContains",
|
||||||
|
"classNameStartsWith",
|
||||||
|
"classNameEndsWith",
|
||||||
|
"classNameMatches",
|
||||||
|
"packageName",
|
||||||
|
"packageNameContains",
|
||||||
|
"packageNameStartsWith",
|
||||||
|
"packageNameEndsWith",
|
||||||
|
"packageNameMatches",
|
||||||
|
"bounds",
|
||||||
|
"boundsInside",
|
||||||
|
"boundsContains",
|
||||||
|
"drawingOrder",
|
||||||
|
"checkable",
|
||||||
|
"checked",
|
||||||
|
"focusable",
|
||||||
|
"focused",
|
||||||
|
"visibleToUser",
|
||||||
|
"accessibilityFocused",
|
||||||
|
"selected",
|
||||||
|
"clickable",
|
||||||
|
"longClickable",
|
||||||
|
"enabled",
|
||||||
|
"password",
|
||||||
|
"scrollable",
|
||||||
|
"editable",
|
||||||
|
"contentInvalid",
|
||||||
|
"contextClickable",
|
||||||
|
"multiLine",
|
||||||
|
"dismissable",
|
||||||
|
"checkable",
|
||||||
|
"checked",
|
||||||
|
"focusable",
|
||||||
|
"focused",
|
||||||
|
"visibleToUser",
|
||||||
|
"accessibilityFocused",
|
||||||
|
"selected",
|
||||||
|
"clickable",
|
||||||
|
"longClickable",
|
||||||
|
"enabled",
|
||||||
|
"password",
|
||||||
|
"scrollable",
|
||||||
|
"editable",
|
||||||
|
"contentInvalid",
|
||||||
|
"contextClickable",
|
||||||
|
"multiLine",
|
||||||
|
"dismissable"
|
||||||
|
],
|
||||||
|
"shell": [
|
||||||
|
"SetScreenMetrics",
|
||||||
|
"Tap",
|
||||||
|
"Swipe",
|
||||||
|
"Screencap",
|
||||||
|
"KeyCode",
|
||||||
|
"Home",
|
||||||
|
"Back",
|
||||||
|
"Power",
|
||||||
|
"Up",
|
||||||
|
"Down",
|
||||||
|
"Left",
|
||||||
|
"Right",
|
||||||
|
"OK",
|
||||||
|
"VolumeUp",
|
||||||
|
"VolumeDown",
|
||||||
|
"Menu",
|
||||||
|
"Camera",
|
||||||
|
"Text"
|
||||||
|
],
|
||||||
|
"timers": [
|
||||||
|
"loop",
|
||||||
|
"setTimeout",
|
||||||
|
"clearTimeout",
|
||||||
|
"setInterval",
|
||||||
|
"clearInterval",
|
||||||
|
"setImmediate",
|
||||||
|
"clearImmediate"
|
||||||
|
],
|
||||||
|
"web": [
|
||||||
|
"newInjectableWebClient",
|
||||||
|
"newInjectableWebView"
|
||||||
|
],
|
||||||
|
"general": [
|
||||||
|
"toast",
|
||||||
|
"toastLog",
|
||||||
|
"sleep",
|
||||||
|
"isStopped",
|
||||||
|
"notStopped",
|
||||||
|
"exit",
|
||||||
|
"setClip",
|
||||||
|
"getClip",
|
||||||
|
"currentPackage",
|
||||||
|
"currentActivity",
|
||||||
|
"waitForActivity",
|
||||||
|
"waitForPackage",
|
||||||
|
"setScreenMetrics"
|
||||||
|
],
|
||||||
|
"variables": [
|
||||||
|
"context",
|
||||||
|
"activity"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"app": [
|
||||||
|
"uninstall",
|
||||||
|
"viewFile",
|
||||||
|
"editFile",
|
||||||
|
"openUrl",
|
||||||
|
"launchPackage",
|
||||||
|
"launch",
|
||||||
|
"launchApp",
|
||||||
|
"getPackageName",
|
||||||
|
"openAppSetting"
|
||||||
|
],
|
||||||
|
"automator": [
|
||||||
|
"click",
|
||||||
|
"longClick",
|
||||||
|
"press",
|
||||||
|
"swipe",
|
||||||
|
"gesture",
|
||||||
|
"gestures",
|
||||||
|
"gestureAsync",
|
||||||
|
"gesturesAsync",
|
||||||
|
"scrollDown",
|
||||||
|
"scrollUp",
|
||||||
|
"input",
|
||||||
|
"setText"
|
||||||
|
],
|
||||||
|
"console": [
|
||||||
|
"show",
|
||||||
|
"hide",
|
||||||
|
"clear",
|
||||||
|
"verbose",
|
||||||
|
"print",
|
||||||
|
"info",
|
||||||
|
"log",
|
||||||
|
"warn",
|
||||||
|
"error",
|
||||||
|
"assert"
|
||||||
|
],
|
||||||
|
"dialogs":[
|
||||||
|
"select",
|
||||||
|
"singleChoice",
|
||||||
|
"multiChoice",
|
||||||
|
"rawInput",
|
||||||
|
"input",
|
||||||
|
"alert",
|
||||||
|
"confirm",
|
||||||
|
"prompt"
|
||||||
|
],
|
||||||
|
"images": [
|
||||||
|
"saveImage",
|
||||||
|
"pixel",
|
||||||
|
"read",
|
||||||
|
"requestScreenCapture",
|
||||||
|
"captureScreen",
|
||||||
|
"findColor",
|
||||||
|
"findColorInRegion",
|
||||||
|
"findColorEquals"
|
||||||
|
],
|
||||||
|
"colors": [
|
||||||
|
"red",
|
||||||
|
"green",
|
||||||
|
"blue",
|
||||||
|
"alpha",
|
||||||
|
"toString",
|
||||||
|
"rgb",
|
||||||
|
"argb"
|
||||||
|
],
|
||||||
|
"events": [
|
||||||
|
"emitter",
|
||||||
|
"observeKey",
|
||||||
|
"observeTouch",
|
||||||
|
"onKeyDown",
|
||||||
|
"onKeyUp",
|
||||||
|
"onceKeyDown",
|
||||||
|
"onceKeyUp",
|
||||||
|
"removeAllKeyDownListeners",
|
||||||
|
"removeAllKeyUpListeners",
|
||||||
|
"onTouch",
|
||||||
|
"removeAllTouchListeners",
|
||||||
|
"getTouchEventTimeout",
|
||||||
|
"setTouchEventTimeout",
|
||||||
|
"on",
|
||||||
|
"once",
|
||||||
|
"emit",
|
||||||
|
"getListeners",
|
||||||
|
"addListener",
|
||||||
|
"eventNames",
|
||||||
|
"listenerCount",
|
||||||
|
"listeners",
|
||||||
|
"prependListener",
|
||||||
|
"prependOnceListener",
|
||||||
|
"removeAllListeners",
|
||||||
|
"removeAllListeners",
|
||||||
|
"removeListener",
|
||||||
|
"setMaxListeners",
|
||||||
|
"getMaxListeners",
|
||||||
|
"defaultMaxListeners"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"open",
|
||||||
|
"isFile",
|
||||||
|
"isDir",
|
||||||
|
"isEmptyDir",
|
||||||
|
"join",
|
||||||
|
"create",
|
||||||
|
"createIfNotExists",
|
||||||
|
"exists",
|
||||||
|
"ensureDir",
|
||||||
|
"read",
|
||||||
|
"write",
|
||||||
|
"copy",
|
||||||
|
"rename",
|
||||||
|
"renameWithoutExtension",
|
||||||
|
"getName",
|
||||||
|
"getExtension",
|
||||||
|
"remove",
|
||||||
|
"removeDir",
|
||||||
|
"getSdcardPath",
|
||||||
|
"listDir"
|
||||||
|
],
|
||||||
|
"timers": [
|
||||||
|
"loop",
|
||||||
|
"setTimeout",
|
||||||
|
"clearTimeout",
|
||||||
|
"setInterval",
|
||||||
|
"clearInterval",
|
||||||
|
"setImmediate",
|
||||||
|
"clearImmediate"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import com.stardust.autojs.runtime.api.AutomatorConfig;
|
|||||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.NativeArray;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,8 +145,6 @@ public class Pref {
|
|||||||
}
|
}
|
||||||
def().edit().putLong(KEY_LAST_SHOW_AD_MILLIS, System.currentTimeMillis()).apply();
|
def().edit().putLong(KEY_LAST_SHOW_AD_MILLIS, System.currentTimeMillis()).apply();
|
||||||
return true;
|
return true;
|
||||||
case "Off":
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.stardust.scriptdroid.tool;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Stardust on 2017/7/21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GsonUtils {
|
||||||
|
|
||||||
|
public static List<String> toReservedStringList(JsonElement element) {
|
||||||
|
JsonArray array = element.getAsJsonArray();
|
||||||
|
List<String> list = new ArrayList<>(array.size());
|
||||||
|
for (int i = array.size() - 1; i >= 0; i--) {
|
||||||
|
list.add(array.get(i).getAsString());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> toStringList(JsonElement element) {
|
||||||
|
JsonArray array = element.getAsJsonArray();
|
||||||
|
List<String> list = new ArrayList<>(array.size());
|
||||||
|
for (int i = 0; i < array.size(); i++) {
|
||||||
|
list.add(array.get(i).getAsString());
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,20 @@
|
|||||||
package com.stardust.scriptdroid.ui.edit.completion;
|
package com.stardust.scriptdroid.ui.edit.completion;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.support.annotation.NonNull;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.stardust.pio.PFile;
|
|
||||||
import com.stardust.pio.UncheckedIOException;
|
|
||||||
import com.stardust.scriptdroid.App;
|
|
||||||
import com.stardust.scriptdroid.Pref;
|
import com.stardust.scriptdroid.Pref;
|
||||||
import com.jecelyin.editor.v2.core.widget.TextView;
|
import com.jecelyin.editor.v2.core.widget.TextView;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
@@ -48,19 +46,26 @@ public class CodeCompletion implements TextWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(CodeCompletionItem o) {
|
public int compareTo(@NonNull CodeCompletionItem o) {
|
||||||
return mDisplayText.compareTo(o.mDisplayText);
|
return mDisplayText.compareTo(o.mDisplayText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface OnCodeCompletionChangeListener {
|
interface OnCodeCompletionChangeListener {
|
||||||
void OnCodeCompletionChange(Collection<CodeCompletionItem>... list);
|
void OnCodeCompletionChange(@NonNull Collection<CodeCompletionItem> list1, @NonNull Collection<CodeCompletionItem> list2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String TAG = "CodeCompletion";
|
private static final String TAG = "CodeCompletion";
|
||||||
|
|
||||||
private OnCodeCompletionChangeListener mOnCodeCompletionChangeListener;
|
private OnCodeCompletionChangeListener mOnCodeCompletionChangeListener;
|
||||||
private TextView mEditText;
|
private TextView mEditText;
|
||||||
|
private static final List<String> KEYWORDS = Arrays.asList("arguments", "break", "case", "catch", "class", "continue", "default", "do", "else", "eval", "export", "false", "for", "function", "if", "import", "in", "int", "new", "null", "package", "return", "switch", "this", "throw", "throws", "true", "try", "typeof", "var", "volatile", "while", "with", "Array", "Date", "hasOwnProperty", "Infinity", "isFinite", "isNaN", "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String", "toString", "undefined", "valueOf");
|
||||||
|
private static final int KEY_WORD_LENGTH_MAX = 15;
|
||||||
|
|
||||||
|
|
||||||
|
private List<String> mGlobal = Collections.emptyList();
|
||||||
|
private Map<String, List<String>> mVariableProperties = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
public CodeCompletion(OnCodeCompletionChangeListener listener) {
|
public CodeCompletion(OnCodeCompletionChangeListener listener) {
|
||||||
mOnCodeCompletionChangeListener = listener;
|
mOnCodeCompletionChangeListener = listener;
|
||||||
@@ -71,6 +76,14 @@ public class CodeCompletion implements TextWatcher {
|
|||||||
mEditText.addTextChangedListener(this);
|
mEditText.addTextChangedListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGlobal(List<String> functions) {
|
||||||
|
mGlobal = functions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVariableProperties(Map<String, List<String>> variableProperties) {
|
||||||
|
mVariableProperties = variableProperties;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
}
|
}
|
||||||
@@ -82,60 +95,94 @@ public class CodeCompletion implements TextWatcher {
|
|||||||
@Override
|
@Override
|
||||||
public void afterTextChanged(Editable s) {
|
public void afterTextChanged(Editable s) {
|
||||||
int position = mEditText.getSelectionStart();
|
int position = mEditText.getSelectionStart();
|
||||||
String str = parseWordBefore(s, position);
|
|
||||||
if (!TextUtils.isEmpty(str))
|
String[] str = parseWordBefore(s, position);
|
||||||
searchCodeCompletion(str);
|
if (str != null) {
|
||||||
else
|
if (str[1] != null) {
|
||||||
mOnCodeCompletionChangeListener.OnCodeCompletionChange(DEFAULT_CODE_COMPLETION_LIST);
|
searchCodeCompletionForVariable(str[0], str[1]);
|
||||||
|
} else {
|
||||||
|
searchCodeCompletionForGlobal(str[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mOnCodeCompletionChangeListener.OnCodeCompletionChange(DEFAULT_CODE_COMPLETION_LIST, Collections.<CodeCompletionItem>emptyList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parseWordBefore(Editable s, int position) {
|
private String[] parseWordBefore(Editable s, int position) {
|
||||||
|
int i;
|
||||||
|
for (i = position - 1; i >= 0; i--) {
|
||||||
|
if (position - i > KEY_WORD_LENGTH_MAX) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
char c = s.charAt(i);
|
||||||
|
if (c == '.') {
|
||||||
|
return new String[]{parseWordBeforeDot(s, i), s.subSequence(i + 1, position).toString()};
|
||||||
|
}
|
||||||
|
if (!Character.isLetter(s.charAt(i))) {
|
||||||
|
if (i < position - 1) {
|
||||||
|
return new String[]{s.subSequence(i + 1, position).toString(), null};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String parseWordBeforeDot(Editable s, int position) {
|
||||||
int i;
|
int i;
|
||||||
for (i = position - 1; i >= 0; i--) {
|
for (i = position - 1; i >= 0; i--) {
|
||||||
if (position - i > KEY_WORD_LENGTH_MAX) {
|
if (position - i > KEY_WORD_LENGTH_MAX) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!Character.isLetter(s.charAt(i))) {
|
if (!Character.isLetter(s.charAt(i))) {
|
||||||
break;
|
if (i < position - 1) {
|
||||||
|
return s.subSequence(i + 1, position).toString();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i < position - 1) {
|
|
||||||
return s.subSequence(i + 1, position).toString();
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static final String[] KEYWORDS = {"arguments", "break", "case", "catch", "class", "continue", "default", "do", "else", "eval", "export", "false", "for", "function", "if", "import", "in", "int", "new", "null", "package", "return", "switch", "this", "throw", "throws", "true", "try", "typeof", "var", "volatile", "while", "with", "Array", "Date", "hasOwnProperty", "Infinity", "isFinite", "isNaN", "isPrototypeOf", "length", "Math", "NaN", "name", "Number", "Object", "prototype", "String", "toString", "undefined", "valueOf"};
|
private boolean searchCodeCompletionForGlobal(String str) {
|
||||||
private static final int KEY_WORD_LENGTH_MAX = 15;
|
|
||||||
|
|
||||||
public void setFunctions(String[] functions) {
|
|
||||||
mFunctions = functions;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String[] mFunctions = new String[0];
|
|
||||||
|
|
||||||
private boolean searchCodeCompletion(String str) {
|
|
||||||
Collection<CodeCompletionItem> c = searchWordCompletion(str);
|
Collection<CodeCompletionItem> c = searchWordCompletion(str);
|
||||||
c.addAll(searchCodeCompletion(str, mFunctions));
|
c.addAll(searchCodeCompletion(str, mGlobal));
|
||||||
c.addAll(searchKeyWordCompletion(str));
|
c.addAll(searchKeyWordCompletion(str));
|
||||||
if (c.size() > 0) {
|
if (c.size() > 0) {
|
||||||
mOnCodeCompletionChangeListener.OnCodeCompletionChange(c, DEFAULT_CODE_COMPLETION_LIST);
|
mOnCodeCompletionChangeListener.OnCodeCompletionChange(c, DEFAULT_CODE_COMPLETION_LIST);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
mOnCodeCompletionChangeListener.OnCodeCompletionChange(DEFAULT_CODE_COMPLETION_LIST);
|
mOnCodeCompletionChangeListener.OnCodeCompletionChange(DEFAULT_CODE_COMPLETION_LIST, Collections.<CodeCompletionItem>emptyList());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean searchCodeCompletionForVariable(String variable, String str) {
|
||||||
|
List<String> properties = getPropertiesForVariable(variable);
|
||||||
|
Collection<CodeCompletionItem> c = searchCodeCompletion(str, properties);
|
||||||
|
mOnCodeCompletionChangeListener.OnCodeCompletionChange(c, Collections.<CodeCompletionItem>emptyList());
|
||||||
|
return !c.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getPropertiesForVariable(String str) {
|
||||||
|
List<String> properties = mVariableProperties.get(str);
|
||||||
|
if (properties == null)
|
||||||
|
return Collections.emptyList();
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Collection<CodeCompletionItem> searchWordCompletion(String str) {
|
private Collection<CodeCompletionItem> searchWordCompletion(String str) {
|
||||||
if (mEditText.getEditableText().length() < Pref.getMaxTextLengthForCodeCompletion()) {
|
if (mEditText.getEditableText().length() < Pref.getMaxTextLengthForCodeCompletion()) {
|
||||||
return searchCodeCompletion(str, splitWord(mEditText.getEditableText().toString()));
|
return searchCodeCompletion(str, Arrays.asList(splitWord(mEditText.getEditableText().toString())));
|
||||||
}
|
}
|
||||||
return new TreeSet<>();
|
return new TreeSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<CodeCompletionItem> searchCodeCompletion(String str, String[] words) {
|
private Collection<CodeCompletionItem> searchCodeCompletion(String str, Iterable<String> words) {
|
||||||
Set<CodeCompletionItem> set = new TreeSet<>();
|
Set<CodeCompletionItem> set = new TreeSet<>();
|
||||||
for (String word : words) {
|
for (String word : words) {
|
||||||
// TODO: 2017/2/18 优化 字典树
|
// TODO: 2017/2/18 优化 字典树
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package com.stardust.scriptdroid.ui.edit.completion;
|
|||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -15,21 +15,27 @@ import android.widget.Toast;
|
|||||||
import android.workground.WrapContentLinearLayoutManager;
|
import android.workground.WrapContentLinearLayoutManager;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
import com.stardust.pio.UncheckedIOException;
|
import com.stardust.pio.UncheckedIOException;
|
||||||
import com.stardust.scriptdroid.App;
|
|
||||||
import com.stardust.scriptdroid.R;
|
import com.stardust.scriptdroid.R;
|
||||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
import com.stardust.scriptdroid.tool.GsonUtils;
|
||||||
|
import com.stardust.util.UnderuseExecutors;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Stardust on 2017/2/17.
|
* Created by Stardust on 2017/2/17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO: 2017/7/21 refactor
|
||||||
public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletion.OnCodeCompletionChangeListener {
|
public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletion.OnCodeCompletionChangeListener {
|
||||||
|
|
||||||
|
|
||||||
@@ -48,6 +54,14 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void OnCodeCompletionChange(@NonNull Collection<CodeCompletion.CodeCompletionItem> list1, @NonNull Collection<CodeCompletion.CodeCompletionItem> list2) {
|
||||||
|
mCodeCompletionList.clear();
|
||||||
|
mCodeCompletionList.addAll(list1);
|
||||||
|
mCodeCompletionList.addAll(list2);
|
||||||
|
getAdapter().notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public interface EditTextBridge {
|
public interface EditTextBridge {
|
||||||
void appendText(CharSequence text);
|
void appendText(CharSequence text);
|
||||||
|
|
||||||
@@ -56,6 +70,9 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
|
|||||||
com.jecelyin.editor.v2.core.widget.TextView getEditText();
|
com.jecelyin.editor.v2.core.widget.TextView getEditText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<String> global;
|
||||||
|
private static Map<String, List<String>> variables = new HashMap<>();
|
||||||
|
|
||||||
EditTextBridge mEditTextBridge;
|
EditTextBridge mEditTextBridge;
|
||||||
private CodeCompletion mCodeCompletion = new CodeCompletion(this);
|
private CodeCompletion mCodeCompletion = new CodeCompletion(this);
|
||||||
private List<CodeCompletion.CodeCompletionItem> mCodeCompletionList = new ArrayList<>();
|
private List<CodeCompletion.CodeCompletionItem> mCodeCompletionList = new ArrayList<>();
|
||||||
@@ -83,7 +100,16 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
|
|||||||
private void init() {
|
private void init() {
|
||||||
setAdapter(new CodeCompletionAdapter());
|
setAdapter(new CodeCompletionAdapter());
|
||||||
setLayoutManager(new WrapContentLinearLayoutManager(getContext(), HORIZONTAL, false));
|
setLayoutManager(new WrapContentLinearLayoutManager(getContext(), HORIZONTAL, false));
|
||||||
mCodeCompletion.setFunctions(readFunctions(getContext(), "js/functions.json"));
|
if (global == null) {
|
||||||
|
UnderuseExecutors.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
readCompletions(getContext(), "js/functions.json");
|
||||||
|
mCodeCompletion.setGlobal(global);
|
||||||
|
mCodeCompletion.setVariableProperties(variables);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEditTextBridge(EditTextBridge editTextBridge) {
|
public void setEditTextBridge(EditTextBridge editTextBridge) {
|
||||||
@@ -91,16 +117,6 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
|
|||||||
mCodeCompletion.setEditText(mEditTextBridge.getEditText());
|
mCodeCompletion.setEditText(mEditTextBridge.getEditText());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void OnCodeCompletionChange(Collection<CodeCompletion.CodeCompletionItem>... lists) {
|
|
||||||
mCodeCompletionList.clear();
|
|
||||||
for (Collection<CodeCompletion.CodeCompletionItem> list : lists) {
|
|
||||||
mCodeCompletionList.addAll(list);
|
|
||||||
}
|
|
||||||
getAdapter().notifyDataSetChanged();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private class CodeCompletionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
private class CodeCompletionAdapter extends RecyclerView.Adapter<ViewHolder> {
|
||||||
|
|
||||||
@@ -129,13 +145,29 @@ public class InputMethodEnhanceBar extends RecyclerView implements CodeCompletio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] readFunctions(Context context, String path) {
|
private static void readCompletions(Context context, String path) {
|
||||||
Gson gson = new Gson();
|
|
||||||
try {
|
try {
|
||||||
return gson.fromJson(new InputStreamReader(context.getAssets().open(path)), String[].class);
|
JsonParser parser = new JsonParser();
|
||||||
|
JsonObject object = parser.parse(new InputStreamReader(context.getAssets().open(path))).getAsJsonObject();
|
||||||
|
InputMethodEnhanceBar.global = readGlobal(object.remove("global").getAsJsonObject());
|
||||||
|
readModules(object);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void readModules(JsonObject object) {
|
||||||
|
for (Map.Entry<String, JsonElement> module : object.entrySet()) {
|
||||||
|
variables.put(module.getKey(), GsonUtils.toStringList(module.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> readGlobal(JsonObject global) {
|
||||||
|
List<String> globalFunctions = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, JsonElement> moduleGlobal : global.entrySet()) {
|
||||||
|
globalFunctions.addAll(GsonUtils.toStringList(moduleGlobal.getValue()));
|
||||||
|
}
|
||||||
|
return globalFunctions;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,13 +228,11 @@
|
|||||||
<string-array name="ad_showing_mode_keys">
|
<string-array name="ad_showing_mode_keys">
|
||||||
<item>默认</item>
|
<item>默认</item>
|
||||||
<item>每天显示一次</item>
|
<item>每天显示一次</item>
|
||||||
<item>关闭广告</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="ad_showing_mode_values">
|
<string-array name="ad_showing_mode_values">
|
||||||
<item>Default</item>
|
<item>Default</item>
|
||||||
<item>OncePerDay</item>
|
<item>OncePerDay</item>
|
||||||
<item>Off</item>
|
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import com.stardust.automator.filter.DfsFilter;
|
|||||||
import com.stardust.util.DeveloperUtils;
|
import com.stardust.util.DeveloperUtils;
|
||||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.NativeArray;
|
||||||
|
|
||||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
|
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
|
||||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT;
|
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_COLUMN_INT;
|
||||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE;
|
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ARGUMENT_PROGRESS_VALUE;
|
||||||
@@ -58,21 +60,6 @@ import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.
|
|||||||
|
|
||||||
public class UiSelector extends UiGlobalSelector {
|
public class UiSelector extends UiGlobalSelector {
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
private class FindCommand extends AccessibilityEventCommandHost.AbstractCommand {
|
|
||||||
|
|
||||||
UiObjectCollection result;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(AccessibilityService service, AccessibilityEvent event) {
|
|
||||||
AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
|
||||||
if (root != null) {
|
|
||||||
result = findOf(UiObject.createRoot(root, mAllocator));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String TAG = "UiSelector";
|
private static final String TAG = "UiSelector";
|
||||||
|
|
||||||
private AccessibilityBridge mAccessibilityBridge;
|
private AccessibilityBridge mAccessibilityBridge;
|
||||||
|
|||||||
@@ -238,4 +238,5 @@ public class UiObjectCollection {
|
|||||||
public boolean nonEmpty() {
|
public boolean nonEmpty() {
|
||||||
return size() != 0;
|
return size() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ public class PFile {
|
|||||||
return new File(path).isDirectory();
|
return new File(path).isDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isDirEmpty(String path) {
|
public static boolean isEmptyDir(String path) {
|
||||||
File file = new File(path);
|
File file = new File(path);
|
||||||
return file.isDirectory() && file.list().length == 0;
|
return file.isDirectory() && file.list().length == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user