add: refactor, jumping for editor

This commit is contained in:
hyb1996
2017-09-29 13:47:19 +08:00
parent bf4e0877a7
commit c114148502
9 changed files with 684 additions and 381 deletions

View File

@@ -0,0 +1,338 @@
function autoJsGlobalScope(){
var globals = {
"modules": [
"app",
"automator",
"console",
"dialogs",
"events",
"images",
"files",
"timers",
"ui",
],
"app": [
"launchPackage",
"launch",
"launchApp",
"getPackageName",
"openAppSetting"
],
"automator": [
"click",
"longClick",
"press",
"swipe",
"gesture",
"gestures",
"gestureAsync",
"gesturesAsync",
"scrollDown",
"scrollUp",
"input",
"setText"
],
"console": [
"print",
"log",
"err",
"openConsole",
"clearConsole"
],
"dialogs": [
"rawInput",
"input",
"alert",
"confirm",
"prompt"
],
"images": [
"requestScreenCapture",
"captureScreen",
"findColor",
"findColorInRegion",
"findColorEquals"
],
"files": [
"open"
],
"selector": [
"id",
"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"
]
};
var modules = {
"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",
"observeNotification",
"onKeyDown",
"onKeyUp",
"onceKeyDown",
"onceKeyUp",
"onToast",
"onNotification",
"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"
]
};
function for_each(obj, func){
for(var key in obj){
if(!obj.hasOwnProperty(key)){
continue;
}
func(key, obj[key]);
}
}
var __global__ = {};
for_each(modules, function(moduleName, moduleVariables){
if(!__global__[moduleName]){
__global__[moduleName] = {};
}
for(var i = 0; i < moduleVariables.length; i++){
if(!__global__[moduleName][moduleVariables[i]]){
__global__[moduleName][moduleVariables[i]] = '';
}
}
});
for_each(globals, function(moduleName, moduleVariables){
for(var i = 0; i < moduleVariables.length; i++){
if(!__global__[moduleVariables[i]]){
__global__[moduleVariables[i]] = '';
}
}
})
return __global__;
}

View File

@@ -1,338 +1,61 @@
function autoJsGlobalScope(){
var globals = {
"modules": [
"app",
"automator",
"console",
"dialogs",
"events",
"images",
"files",
"timers",
"ui",
],
"app": [
"launchPackage",
"launch",
"launchApp",
"getPackageName",
"openAppSetting"
],
"automator": [
"click",
"longClick",
"press",
"swipe",
"gesture",
"gestures",
"gestureAsync",
"gesturesAsync",
"scrollDown",
"scrollUp",
"input",
"setText"
],
"console": [
"print",
"log",
"err",
"openConsole",
"clearConsole"
],
"dialogs": [
"rawInput",
"input",
"alert",
"confirm",
"prompt"
],
"images": [
"requestScreenCapture",
"captureScreen",
"findColor",
"findColorInRegion",
"findColorEquals"
],
"files": [
"open"
],
"selector": [
"id",
"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"
]
};
var modules = {
"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",
"observeNotification",
"onKeyDown",
"onKeyUp",
"onceKeyDown",
"onceKeyUp",
"onToast",
"onNotification",
"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"
]
};
function for_each(obj, func){
for(var key in obj){
if(!obj.hasOwnProperty(key)){
continue;
}
func(key, obj[key]);
function autojs(editor){
function loadJs(url){
var script = document.createElement("script");
// This script has a callback function that will run when the script has
// finished loading.
script.src = url;
script.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(script);
}
var server = null;
var getURL = function(url, c) {
var xhr = new XMLHttpRequest();
xhr.open("get", url, true);
xhr.send();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.status < 400) return c(null, xhr.responseText);
var e = new Error(xhr.responseText || "No response");
e.status = xhr.status;
c(e);
};
}
connect();
editor.tern = {};
editor.tern.showType = function(){
checkServer();
server.showType(editor);
}
editor.tern.jumpToDef = function(){
checkServer();
server.jumpToDef(editor);
}
editor.tern.rename = function(){
checkServer();
server.rename(editor);
}
editor.tern.selectName = function(){
checkServer();
server.selectName(editor);
}
editor.tern.jumpBack = function(){
checkServer();
server.jumpBack(editor);
}
function connect(){
getURL("http://ternjs.net/defs/ecmascript.json", function(err, code) {
if (err) throw new Error("Request for ecmascript.json: " + err);
server = new CodeMirror.TernServer({defs: [JSON.parse(code)]});
editor.tern.server = server;
editor.on("cursorActivity", function(cm) { server.updateArgHints(cm); });
});
}
function checkServer(){
if(!server){
alert("Error: cannot connect to tern server\n联网获取编辑器增强服务失败:(\n");
connect();
}
}
var __global__ = {};
for_each(modules, function(moduleName, moduleVariables){
if(!__global__[moduleName]){
__global__[moduleName] = {};
}
for(var i = 0; i < moduleVariables.length; i++){
if(!__global__[moduleName][moduleVariables[i]]){
__global__[moduleName][moduleVariables[i]] = '';
}
}
});
for_each(globals, function(moduleName, moduleVariables){
for(var i = 0; i < moduleVariables.length; i++){
if(!__global__[moduleVariables[i]]){
__global__[moduleVariables[i]] = '';
}
}
})
return __global__;
}
}

View File

@@ -42,6 +42,7 @@
<script type="text/javascript" src="codemirror/addon/search/searchcursor.js"></script>
<!-- Auto.js -->
<script type="text/javascript" src="codemirror/addon/autojs/autojs-global-scope.js"></script>
<script type="text/javascript" src="codemirror/addon/autojs/autojs.js"></script>
<head>
@@ -50,26 +51,20 @@
<body>
<textarea id="code"></textarea>
</body>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true, // 显示行数
indentUnit: 4, // 缩进单位为4
styleActiveLine: true, // 当前行背景高亮
foldGutter: true,
gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
matchBrackets: true, // 括号匹配
mode: 'javascript', // HMTL混合模式
lineWrapping: false, // 自动换行
theme: 'neo' // 使用neo模版
});
editor.setOption("fullScreen", true);
editor.setOption("hintOptions", {
completeSingle: false,
globalScope: autoJsGlobalScope()
});
editor.on("keyup", function(cm, e) {
editor.execCommand("autocomplete")
})
editor.setCursor({line: 0, ch: 0});
</script>
<!-- Tern -->
<script src="codemirror/addon/tern/tern.js"></script>
<link rel="stylesheet" href="codemirror/addon/tern/tern.css">
<script src="http://ternjs.net/node_modules/acorn/dist/acorn.js"></script>
<script src="http://ternjs.net/node_modules/acorn/dist/acorn_loose.js"></script>
<script src="http://ternjs.net/node_modules/acorn/dist/walk.js"></script>
<script src="http://ternjs.net/doc/demo/polyfill.js"></script>
<script src="http://ternjs.net/lib/signal.js"></script>
<script src="http://ternjs.net/lib/tern.js"></script>
<script src="http://ternjs.net/lib/def.js"></script>
<script src="http://ternjs.net/lib/comment.js"></script>
<script src="http://ternjs.net/lib/infer.js"></script>
<script src="http://ternjs.net/plugin/doc_comment.js"></script>
<script src="index.js"></script>
</html>

View File

@@ -0,0 +1,24 @@
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true, // 显示行数
indentUnit: 4, // 缩进单位为4
styleActiveLine: true, // 当前行背景高亮
foldGutter: true,
gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
matchBrackets: true, // 括号匹配
mode: 'javascript',
lineWrapping: false, // 自动换行
theme: 'neo' // 使用neo主题
});
editor.setOption("fullScreen", true);
editor.setOption("hintOptions", {
completeSingle: false,
globalScope: autoJsGlobalScope()
});
editor.on("keyup", function(cm, e) {
editor.execCommand("autocomplete");
})
editor.setCursor({line: 0, ch: 0});
window.onload = function(){
autojs(editor);
}

View File

@@ -1,19 +1,26 @@
package com.stardust.scriptdroid.ui.edit;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.webkit.JavascriptInterface;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.R;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import org.apache.commons.lang3.StringEscapeUtils;
import org.jdeferred.Deferred;
@@ -24,6 +31,8 @@ import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.concurrent.Callable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -32,6 +41,7 @@ import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import retrofit2.http.GET;
/**
* Created by Stardust on 2017/9/27.
@@ -41,7 +51,6 @@ public class CodeMirrorEditor extends FrameLayout {
private static final String LOG_TAG = "CodeMirrorEditor";
public interface Callback {
void onChange();
@@ -158,7 +167,7 @@ public class CodeMirrorEditor extends FrameLayout {
settings.setNeedInitialFocus(true);
settings.setDisplayZoomControls(false);
mWebView.setWebViewClient(new MyWebViewClient());
mWebView.setWebChromeClient(new WebChromeClient());
mWebView.setWebChromeClient(new MyWebChromeClient());
}
public void setProgress(boolean onProgress) {
@@ -268,6 +277,41 @@ public class CodeMirrorEditor extends FrameLayout {
evalJavaScript("editor.execCommand('replaceAll');");
}
public void jumpToDef() {
evalJavaScript("editor.tern.jumpToDef();");
}
public void jumpToLineStart() {
evalJavaScript("editor.execCommand('goLineStart');");
}
public void jumpToLineEnd() {
evalJavaScript("editor.execCommand('goLineEnd')");
}
public void jumpToStart() {
evalJavaScript("editor.execCommand('goDocStart');");
}
public void jumpToEnd() {
evalJavaScript("editor.execCommand('goDocEnd');");
}
public void showType() {
evalJavaScript("editor.tern.showType();");
}
public void rename() {
evalJavaScript("editor.tern.rename();");
}
public void selectName() {
evalJavaScript("editor.tern.selectName();");
}
public void replace(String keywords, String replacement, boolean usingRegex) {
setQuery(keywords, usingRegex);
replacement = replacement.replace("'", "\'");
@@ -275,6 +319,12 @@ public class CodeMirrorEditor extends FrameLayout {
findNext();
}
public Observable<String> getSelection() {
mStringFromJs = PublishSubject.create();
evalJavaScript("__bridge__.setStringFromJs(editor.getSelection());");
return mStringFromJs;
}
public void replaceSelection() {
evalJavaScript("editor.execCommand('replace');");
}
@@ -355,7 +405,61 @@ public class CodeMirrorEditor extends FrameLayout {
mPageFinished.resolve(null);
evalJavaScript(INIT_SCRIPT);
setProgress(false);
// evalJavaScript("editor.setSize(" + mWebView.getMeasuredWidth() + ", " + mWebView.getMeasuredHeight() + ");");
}
}
private class MyWebChromeClient extends WebChromeClient {
private final Pattern RENAME = Pattern.compile("New name for ([a-zA-Z]+)");
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
Matcher m = RENAME.matcher(message);
if (m.matches() && m.groupCount() >= 1) {
showRenamePrompt(m.group(1), defaultValue, result);
return true;
}
return super.onJsPrompt(view, url, message, defaultValue, result);
}
private void showRenamePrompt(String name, String defaultValue, final JsPromptResult result) {
new ThemeColorMaterialDialogBuilder(getContext())
.title(getResources().getString(R.string.text_rename) + name)
.input("", defaultValue, new MaterialDialog.InputCallback() {
@Override
public void onInput(@android.support.annotation.NonNull MaterialDialog dialog, CharSequence input) {
result.confirm(input.toString());
}
})
.show();
}
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
new ThemeColorMaterialDialogBuilder(getContext())
.title(R.string.text_alert)
.content(message)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@android.support.annotation.NonNull MaterialDialog dialog, @android.support.annotation.NonNull DialogAction which) {
result.confirm();
}
})
.cancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
result.cancel();
}
})
.positiveText(R.string.ok)
.show();
return true;
}
@Override
public void onProgressChanged(WebView view, int newProgress) {
mProgressBar.setVisibility(newProgress == 100 ? VISIBLE : GONE);
}
}
}

View File

@@ -38,22 +38,22 @@ public class EditorMenu {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_console:
showConsole();
return true;
case R.id.action_log:
showLog();
return true;
case R.id.action_force_stop:
forceStop();
return true;
case R.id.action_jump:
jump();
return true;
default:
if (onEditOptionsSelected(item)) {
return true;
}
if (onRefactorOptionsSelected(item)) {
return true;
}
if (onJumpOptionsSelected(item)) {
return true;
}
if (onMoreOptionsSelected(item)) {
return true;
}
@@ -61,12 +61,54 @@ public class EditorMenu {
return false;
}
private boolean onJumpOptionsSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_jump_to_line:
jumpToLine();
return true;
case R.id.action_jump_to_def:
mEditor.jumpToDef();
return true;
case R.id.action_jump_to_start:
mEditor.jumpToStart();
return true;
case R.id.action_jump_to_end:
mEditor.jumpToEnd();
return true;
case R.id.action_jump_to_line_start:
mEditor.jumpToLineStart();
return true;
case R.id.action_jump_to_line_end:
mEditor.jumpToLineEnd();
return true;
}
return false;
}
private boolean onMoreOptionsSelected(MenuItem item) {
private boolean onRefactorOptionsSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_beautify:
beautifyCode();
return true;
case R.id.action_rename:
mEditor.rename();
return true;
case R.id.action_select_variable:
mEditor.selectName();
return true;
}
return false;
}
private boolean onMoreOptionsSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_console:
showConsole();
return true;
case R.id.action_show_type:
mEditor.showType();
return true;
case R.id.action_editor_theme:
mEditorView.selectEditorTheme();
return true;
@@ -106,7 +148,7 @@ public class EditorMenu {
return false;
}
private void jump() {
private void jumpToLine() {
mEditor.getLineCount()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@@ -180,8 +222,17 @@ public class EditorMenu {
}
private void findOrReplace() {
new FindOrReplaceDialogBuilder(mContext, mEditorView)
.show();
mEditor.getSelection()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(@NonNull String s) throws Exception {
new FindOrReplaceDialogBuilder(mContext, mEditorView)
.setQueryIfNotEmpty(s)
.show();
}
});
}
private void copyAll() {

View File

@@ -120,4 +120,10 @@ public class FindOrReplaceDialogBuilder extends ThemeColorMaterialDialogBuilder
}
}
public FindOrReplaceDialogBuilder setQueryIfNotEmpty(String s) {
if (!TextUtils.isEmpty(s))
mKeywordsEditText.setText(s);
return this;
}
}

View File

@@ -46,15 +46,64 @@
</item>
<item
android:id="@+id/action_jump"
android:title="@string/text_jump_to_line"
app:showAsAction="never"/>
android:title="@string/text_jump"
app:showAsAction="never">
<menu>
<item
android:id="@+id/action_jump_to_def"
android:title="@string/text_jump_to_def"
app:showAsAction="never"/>
<item
android:id="@+id/action_jump_to_line"
android:title="@string/text_jump_to_line"
app:showAsAction="never"/>
<item
android:id="@+id/action_jump_to_start"
android:title="@string/text_jump_to_start"
app:showAsAction="never"/>
<item
android:id="@+id/action_jump_to_end"
android:title="@string/text_jump_to_end"
app:showAsAction="never"/>
<item
android:id="@+id/action_jump_to_line_start"
android:title="@string/text_jump_to_line_start"
app:showAsAction="never"/>
<item
android:id="@+id/action_jump_to_line_end"
android:title="@string/text_jump_to_line_end"
app:showAsAction="never"/>
</menu>
</item>
<item
android:id="@+id/action_console"
android:title="@string/text_console"
app:showAsAction="never"/>
<item android:title="@string/text_refactor">
<menu>
<item
android:id="@+id/action_rename"
android:title="@string/text_rename"
app:showAsAction="never"/>
<item
android:id="@+id/action_select_variable"
android:title="@string/text_select_variable"
app:showAsAction="never"/>
<item
android:id="@+id/action_beautify"
android:title="@string/text_code_beautify"
app:showAsAction="never"/>
</menu>
</item>
<item
android:id="@+id/action_log"
@@ -63,10 +112,14 @@
<item android:title="@string/text_more">
<menu>
<item
android:id="@+id/action_console"
android:title="@string/text_console"
app:showAsAction="never"/>
<item
android:id="@+id/action_beautify"
android:title="@string/text_code_beautify"
android:id="@+id/action_show_type"
android:title="@string/text_show_type"
app:showAsAction="never"/>
<item

View File

@@ -269,7 +269,16 @@
<string name="text_replace_all">全部替换</string>
<string name="text_find_next">向下</string>
<string name="text_find_prev">向上</string>
<string name="hint_regex">正则语法与JavaScript中相同, 可使用$1-9代替被捕获的匹配</string>
<string name="hint_regex">正则语法与JavaScript中相同, 可使用$1~9代替被捕获的匹配</string>
<string name="text_jump">跳转</string>
<string name="text_jump_to_def">转到定义</string>
<string name="text_jump_to_end">转到文件末尾</string>
<string name="text_jump_to_start">转到文件开始</string>
<string name="text_jump_to_line_start">转到行首</string>
<string name="text_jump_to_line_end">转到行尾</string>
<string name="text_refactor">重构</string>
<string name="text_select_variable">选择变量</string>
<string name="text_show_type">显示变量类型</string>
<string-array name="record_control_keys">