From 12e820bb5fc4202a4bb2cb9a9f4de8cc6d18ad55 Mon Sep 17 00:00:00 2001 From: zt515 Date: Tue, 18 Jul 2017 23:55:01 +0800 Subject: [PATCH] Feature: TermHere and UserScript from FileManager --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 34 ++++- .../io/neoterm/backend/TerminalSession.java | 7 +- .../java/io/neoterm/preference/NeoTermPath.kt | 1 + .../io/neoterm/services/NeoTermService.kt | 11 +- .../ui/customization/CustomizationActivity.kt | 2 +- .../io/neoterm/ui/term/NeoTermActivity.kt | 12 +- .../neoterm/ui/term/NeoTermRemoteInterface.kt | 123 ++++++++++++++++++ .../io/neoterm/ui/term/TermHereActivity.kt | 9 -- ...ngedCallback.kt => TermSessionCallback.kt} | 2 +- .../java/io/neoterm/ui/term/tab/TermTab.kt | 2 +- .../utils/{Shaker.kt => ShakeUtils.kt} | 2 +- .../java/io/neoterm/utils/TerminalUtils.kt | 37 +++++- .../java/io/neoterm/view/TerminalDialog.kt | 2 +- app/src/main/res/values-zh/strings.xml | 15 ++- app/src/main/res/values/preference_keys.xml | 1 + app/src/main/res/values/strings.xml | 13 +- app/src/main/res/xml/setting_general.xml | 13 +- 18 files changed, 238 insertions(+), 52 deletions(-) create mode 100644 app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt delete mode 100644 app/src/main/java/io/neoterm/ui/term/TermHereActivity.kt rename app/src/main/java/io/neoterm/ui/term/tab/{TermSessionChangedCallback.kt => TermSessionCallback.kt} (96%) rename app/src/main/java/io/neoterm/utils/{Shaker.kt => ShakeUtils.kt} (96%) diff --git a/app/build.gradle b/app/build.gradle index 982cd4a..ef01627 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { applicationId "io.neoterm" minSdkVersion 21 targetSdkVersion 25 - versionCode 11 - versionName "1.1.9" + versionCode 12 + versionName "1.2.0-rc1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" resConfigs "zh" externalNativeBuild { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 88c53ca..b3a9c66 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,19 +29,45 @@ + + + + + + + + android:label="@string/term_here" + android:targetActivity=".ui.term.NeoTermRemoteInterface"> - - + + + + + + + + + + + + + 0) { + write(mInitialCommand + '\r'); + } } /** Write data to the shell process. */ diff --git a/app/src/main/java/io/neoterm/preference/NeoTermPath.kt b/app/src/main/java/io/neoterm/preference/NeoTermPath.kt index 0936628..be03b9d 100644 --- a/app/src/main/java/io/neoterm/preference/NeoTermPath.kt +++ b/app/src/main/java/io/neoterm/preference/NeoTermPath.kt @@ -18,6 +18,7 @@ object NeoTermPath { const val EKS_DEFAULT_FILE = "$EKS_PATH/default.eks" const val FONT_PATH = "$CUSTOM_PATH/font" const val COLORS_PATH = "$CUSTOM_PATH/color" + const val USER_SCRIPT_PATH = "$CUSTOM_PATH/script" const val SOURCE_FILE = "$USR_PATH/etc/apt/sources.list" const val PACKAGE_LIST_DIR = "$USR_PATH/var/lib/apt/lists" diff --git a/app/src/main/java/io/neoterm/services/NeoTermService.kt b/app/src/main/java/io/neoterm/services/NeoTermService.kt index 3540ae5..a0b5c31 100644 --- a/app/src/main/java/io/neoterm/services/NeoTermService.kt +++ b/app/src/main/java/io/neoterm/services/NeoTermService.kt @@ -12,7 +12,6 @@ import android.os.Binder import android.os.IBinder import android.os.PowerManager import android.support.v4.content.WakefulBroadcastReceiver -import android.util.Log import io.neoterm.R import io.neoterm.backend.EmulatorDebug import io.neoterm.backend.TerminalSession @@ -77,8 +76,8 @@ class NeoTermService : Service() { val sessions: List get() = mTerminalSessions - fun createTermSession(executablePath: String?, arguments: Array?, cwd: String?, env: Array?, sessionCallback: TerminalSession.SessionChangedCallback?, systemShell: Boolean): TerminalSession { - val session = TerminalUtils.createSession(this, executablePath, arguments, cwd, env, sessionCallback, systemShell) + fun createTermSession(executablePath: String?, arguments: Array?, cwd: String?, initialCommand: String?, env: Array?, sessionCallback: TerminalSession.SessionChangedCallback?, systemShell: Boolean): TerminalSession { + val session = TerminalUtils.createSession(this, executablePath, arguments, cwd, initialCommand, env, sessionCallback, systemShell) mTerminalSessions.add(session) updateNotification() return session @@ -165,9 +164,9 @@ class NeoTermService : Service() { } companion object { - val ACTION_SERVICE_STOP = "neoterm.action.service.stop" - val ACTION_ACQUIRE_LOCK = "neoterm.action.service.lock.acquire" - val ACTION_RELEASE_LOCK = "neoterm.action.service.lock.release" + val ACTION_SERVICE_STOP = "neoterm.action.termService.stop" + val ACTION_ACQUIRE_LOCK = "neoterm.action.termService.lock.acquire" + val ACTION_RELEASE_LOCK = "neoterm.action.termService.lock.release" private val NOTIFICATION_ID = 52019 } } diff --git a/app/src/main/java/io/neoterm/ui/customization/CustomizationActivity.kt b/app/src/main/java/io/neoterm/ui/customization/CustomizationActivity.kt index de89a03..f5a610c 100644 --- a/app/src/main/java/io/neoterm/ui/customization/CustomizationActivity.kt +++ b/app/src/main/java/io/neoterm/ui/customization/CustomizationActivity.kt @@ -58,7 +58,7 @@ class CustomizationActivity : AppCompatActivity() { sessionCallback = BasicSessionCallback(terminalView) TerminalUtils.setupTerminalView(terminalView, viewClient) session = TerminalUtils.createSession(this, "${NeoTermPath.USR_PATH}/bin/applets/echo", - arrayOf("echo", "Hello NeoTerm."), null, null, sessionCallback, false) + arrayOf("echo", "Hello NeoTerm."), null, null, null, sessionCallback, false) terminalView.attachSession(session) findViewById(R.id.custom_install_font_button).setOnClickListener { diff --git a/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt b/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt index dac0de6..c8bb623 100644 --- a/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt +++ b/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt @@ -6,7 +6,6 @@ import android.app.Activity import android.app.AlertDialog import android.content.* import android.content.pm.PackageManager -import android.graphics.Rect import android.os.Bundle import android.os.IBinder import android.preference.PreferenceManager @@ -34,7 +33,7 @@ import io.neoterm.ui.bonus.BonusActivity import io.neoterm.ui.pm.PackageManagerActivity import io.neoterm.ui.settings.SettingActivity import io.neoterm.ui.setup.SetupActivity -import io.neoterm.ui.term.tab.TermSessionChangedCallback +import io.neoterm.ui.term.tab.TermSessionCallback import io.neoterm.ui.term.tab.TermTab import io.neoterm.ui.term.tab.TermTabDecorator import io.neoterm.ui.term.tab.TermViewClient @@ -382,8 +381,8 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference .filter { it is TermTab && it.termSession == session } .forEach { return } - val tab = createTab(session.mSessionName) as TermTab - tab.sessionCallback = session.sessionChangedCallback as TermSessionChangedCallback + val tab = createTab(session.title) as TermTab + tab.sessionCallback = session.sessionChangedCallback as TermSessionCallback tab.viewClient = TermViewClient(this) tab.termSession = session @@ -393,9 +392,10 @@ class NeoTermActivity : AppCompatActivity(), ServiceConnection, SharedPreference private fun addNewSession(sessionName: String?, systemShell: Boolean, animation: Animation) { val tab = createTab(sessionName) as TermTab - tab.sessionCallback = TermSessionChangedCallback() + tab.sessionCallback = TermSessionCallback() tab.viewClient = TermViewClient(this) - tab.termSession = termService!!.createTermSession(null, null, null, null, tab.sessionCallback, systemShell) + tab.termSession = termService!!.createTermSession(null, null, + null, null, null, tab.sessionCallback, systemShell) if (sessionName != null) { tab.termSession!!.mSessionName = sessionName diff --git a/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt b/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt new file mode 100644 index 0000000..ecf5a19 --- /dev/null +++ b/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt @@ -0,0 +1,123 @@ +package io.neoterm.ui.term + +import android.content.ComponentName +import android.content.Intent +import android.content.ServiceConnection +import android.net.Uri +import android.os.Bundle +import android.os.IBinder +import android.support.v7.app.AppCompatActivity +import io.neoterm.preference.NeoPreference +import io.neoterm.services.NeoTermService +import io.neoterm.ui.term.tab.TermSessionCallback +import io.neoterm.utils.TerminalUtils +import java.io.File + + +/** + * @author kiva + */ +class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection { + var termService: NeoTermService? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val serviceIntent = Intent(this, NeoTermService::class.java) + startService(serviceIntent) + if (!bindService(serviceIntent, this, 0)) { + finish() + } + } + + override fun onDestroy() { + super.onDestroy() + termService = null + unbindService(this) + } + + override fun onServiceDisconnected(name: ComponentName?) { + if (termService != null) { + finish() + } + } + + override fun onServiceConnected(name: ComponentName?, service: IBinder?) { + termService = (service as NeoTermService.NeoTermBinder).service + if (termService == null) { + finish() + return + } + + handleIntent() + } + + private fun handleIntent() { + val className = intent.component.className.substringAfterLast('.') + when (className) { + "TermHere" -> handleTermHere() + "UserScript" -> handleUserScript() + else -> openTerm(null) + } + } + + private fun openTerm(initialCommand: String?) { + val session = termService!!.createTermSession(null, + null, null, initialCommand, + null, TermSessionCallback(), false) + + // Set current session to our new one + // In order to switch to it when entering NeoTermActivity + NeoPreference.storeCurrentSession(session) + + val intent = Intent(this, NeoTermActivity::class.java) + intent.addCategory(Intent.CATEGORY_DEFAULT) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(intent) + } + + private fun handleTermHere() { + if (intent.hasExtra(Intent.EXTRA_STREAM)) { + val extra = intent.extras.get(Intent.EXTRA_STREAM) + if (extra is Uri) { + val path = extra.path + val file = File(path) + val dirPath = if (file.isDirectory) path else file.parent + openTerm("cd " + TerminalUtils.escapeString(dirPath)) + } + } + finish() + } + + private fun handleUserScript() { + if (intent.hasExtra(Intent.EXTRA_STREAM)) { + val extra = intent.extras.get(Intent.EXTRA_STREAM) + val filesToHandle = mutableListOf() + + when (extra) { + is ArrayList<*> -> { + (0..extra.size - 1) + .map { extra[it] } + .takeWhile { it is Uri } + .mapTo(filesToHandle, { File((it as Uri).path).absolutePath }) + } + is Uri -> { + filesToHandle.add(File(extra.path).absolutePath) + } + } + + if (filesToHandle.isNotEmpty()) { + openTerm("echo -e ${buildUserScriptArgument(filesToHandle)}") + } + } + finish() + } + + private fun buildUserScriptArgument(files: List): String { + val builder = StringBuilder() + files.forEach { + builder.append(TerminalUtils.escapeString(it)) + builder.append(" ") + } + return builder.toString() + } +} \ No newline at end of file diff --git a/app/src/main/java/io/neoterm/ui/term/TermHereActivity.kt b/app/src/main/java/io/neoterm/ui/term/TermHereActivity.kt deleted file mode 100644 index 81f2632..0000000 --- a/app/src/main/java/io/neoterm/ui/term/TermHereActivity.kt +++ /dev/null @@ -1,9 +0,0 @@ -package io.neoterm.ui.term - -import android.support.v7.app.AppCompatActivity - -/** - * @author kiva - */ -class TermHereActivity : AppCompatActivity() { -} \ No newline at end of file diff --git a/app/src/main/java/io/neoterm/ui/term/tab/TermSessionChangedCallback.kt b/app/src/main/java/io/neoterm/ui/term/tab/TermSessionCallback.kt similarity index 96% rename from app/src/main/java/io/neoterm/ui/term/tab/TermSessionChangedCallback.kt rename to app/src/main/java/io/neoterm/ui/term/tab/TermSessionCallback.kt index bc08316..7942dbd 100644 --- a/app/src/main/java/io/neoterm/ui/term/tab/TermSessionChangedCallback.kt +++ b/app/src/main/java/io/neoterm/ui/term/tab/TermSessionCallback.kt @@ -13,7 +13,7 @@ import io.neoterm.view.TerminalView /** * @author kiva */ -class TermSessionChangedCallback : TerminalSession.SessionChangedCallback { +class TermSessionCallback : TerminalSession.SessionChangedCallback { var termView: TerminalView? = null var termTab: TermTab? = null diff --git a/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt b/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt index 4db14fb..3d481e3 100644 --- a/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt +++ b/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt @@ -20,7 +20,7 @@ import org.greenrobot.eventbus.EventBus class TermTab(title: CharSequence) : Tab(title) { var termSession: TerminalSession? = null - var sessionCallback: TermSessionChangedCallback? = null + var sessionCallback: TermSessionCallback? = null var viewClient: TermViewClient? = null var onAutoCompleteListener: OnAutoCompleteListener? = null var toolbar: Toolbar? = null diff --git a/app/src/main/java/io/neoterm/utils/Shaker.kt b/app/src/main/java/io/neoterm/utils/ShakeUtils.kt similarity index 96% rename from app/src/main/java/io/neoterm/utils/Shaker.kt rename to app/src/main/java/io/neoterm/utils/ShakeUtils.kt index c9e4575..fbee5e2 100644 --- a/app/src/main/java/io/neoterm/utils/Shaker.kt +++ b/app/src/main/java/io/neoterm/utils/ShakeUtils.kt @@ -6,7 +6,7 @@ import android.hardware.SensorEvent import android.hardware.SensorEventListener import android.hardware.SensorManager -class Shaker(context: Context) : SensorEventListener { +class ShakeUtils(context: Context) : SensorEventListener { companion object { private val SHAKE_SENSITIVITY = 14 } diff --git a/app/src/main/java/io/neoterm/utils/TerminalUtils.kt b/app/src/main/java/io/neoterm/utils/TerminalUtils.kt index 6590738..6b94132 100644 --- a/app/src/main/java/io/neoterm/utils/TerminalUtils.kt +++ b/app/src/main/java/io/neoterm/utils/TerminalUtils.kt @@ -4,9 +4,9 @@ import android.content.Context import android.widget.Toast import io.neoterm.R import io.neoterm.backend.TerminalSession -import io.neoterm.preference.NeoTermPath import io.neoterm.customize.font.FontManager import io.neoterm.preference.NeoPreference +import io.neoterm.preference.NeoTermPath import io.neoterm.view.BasicViewClient import io.neoterm.view.ExtraKeysView import io.neoterm.view.TerminalView @@ -31,11 +31,16 @@ object TerminalUtils { fun setupTerminalSession(session: TerminalSession?) { } - fun createSession(context: Context, executablePath: String?, arguments: Array?, cwd: String?, env: Array?, sessionCallback: TerminalSession.SessionChangedCallback?, systemShell: Boolean): TerminalSession { + fun createSession(context: Context, executablePath: String?, arguments: Array?, + cwd: String?, initialCommand: String?, env: Array?, + sessionCallback: TerminalSession.SessionChangedCallback?, + systemShell: Boolean): TerminalSession { + var executablePath = executablePath var arguments = arguments - + var initialCommand = initialCommand var cwd = cwd + if (cwd == null) { cwd = NeoTermPath.HOME_PATH } @@ -56,10 +61,34 @@ object TerminalUtils { arguments = arrayOf(executablePath) } - val session = TerminalSession(executablePath, cwd, arguments, + if (initialCommand == null) { + initialCommand = NeoPreference.loadString(R.string.key_general_initial_command, "") + } + + val session = TerminalSession(executablePath, cwd, initialCommand, arguments, env ?: NeoPreference.buildEnvironment(cwd, systemShell, executablePath), sessionCallback) setupTerminalSession(session) return session } + + fun escapeString(s: String?): String { + if (s == null) { + return "" + } + + val builder = StringBuilder() + val specialChars = "\"\\$`!" + builder.append('"') + val length = s.length + for (i in 0..length - 1) { + val c = s[i] + if (specialChars.indexOf(c) >= 0) { + builder.append('\\') + } + builder.append(c) + } + builder.append('"') + return builder.toString() + } } \ No newline at end of file diff --git a/app/src/main/java/io/neoterm/view/TerminalDialog.kt b/app/src/main/java/io/neoterm/view/TerminalDialog.kt index 67deaa3..4e10c5e 100644 --- a/app/src/main/java/io/neoterm/view/TerminalDialog.kt +++ b/app/src/main/java/io/neoterm/view/TerminalDialog.kt @@ -56,7 +56,7 @@ class TerminalDialog(val context: Context) { } .create() - terminalSession = TerminalUtils.createSession(context, executablePath, arguments, null, null, terminalSessionCallback, false) + terminalSession = TerminalUtils.createSession(context, executablePath, arguments, null, null, null, terminalSessionCallback, false) terminalView.attachSession(terminalSession) return this } diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 1f0ac2e..65c9b38 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -8,7 +8,7 @@ 软件包设置 粘贴 返回键发送ESC - 当返回键按下时,发送ESC而不是退出终端 + 当返回键按下时,发送ESC而不是关闭窗口 响铃 收到 \'\\a\' 时响铃 登录时使用指定的 Shell @@ -16,10 +16,12 @@ 收到 \'\\a\' 时振动 程序选择模式 当 NeoTerm 和 系统 中都含有同一个程序时,选择将要被执行的程序的模式 + 初始命令 + 在新的实例创建时执行命令 软件源 向下切换窗口 关闭当前窗口时切换到下一个窗口而不是上一个 - 字体,主题,拓展键盘 + 字体,主题,拓展键盘,自动补全 个性化 全屏 隐藏标题栏 @@ -47,7 +49,7 @@ 软件包: %s\n版本: %s\n依赖: %s\n占用空间: %s\n描述: %s\n主页: %s 软件包列表为空,请检查你的软件源 刷新 - 更新, 刷新 + 更新并刷新 只使用 NeoTerm @@ -63,9 +65,9 @@ 输入… 拓展键盘 - 响铃,振动,Shell - 全屏,标题栏,快捷键盘 - 源,更新,升级 + 响铃,振动,Shell,初始命令 + 全屏,标题栏,切换动画 + 软件源,更新,升级 安装字体 安装配色方案 发现 @@ -83,4 +85,5 @@ 释放休眠锁 退出 在此处打开终端 + 用户脚本 \ No newline at end of file diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 12fbb6f..706136e 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -5,6 +5,7 @@ neoterm_general_backspace_map_to_esc neoterm_general_shell neoterm_general_program_selection + neoterm_general_initial_command neoterm_ui_fullscreen neoterm_ui_hide_toolbar diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d6c2463..7752ab5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,12 +20,12 @@ Discovery Settings General Settings - Bell, Vibrate, Shell + Bell, Vibrate, Shell, Initial Command UI Settings - FullScreen, Title Bar, Suggestions + FullScreen, Title Bar, Animation Package Settings Source, Updates, Upgrades - Font, ColorScheme, ExtraKeys + Font, ColorScheme, ExtraKeys, AutoComplete Customization Toggle IME @@ -41,7 +41,7 @@ Package: %s\nVersion: %s\nDepends: %s\nInstalled Size: %s\nDescription: %s\nHome Page: %s Package list is empty, please check out your source. Refresh - Update, Refresh + Update and Refresh Install Font Install Color Scheme @@ -63,6 +63,8 @@ Which shell should we use when login Program Selection When both Neo Term and your Android OS have a program, which one should we choose? + Initial Command + Execute commands when a session is being created Full Screen Hide Toolbar Hide toolbar when keyboard is showing @@ -78,6 +80,7 @@ Source Exit Term Here + User Script sh @@ -108,7 +111,7 @@ https://mirrors.geekpie.org/neoterm - http://192.243.117.135 + http://neoterm.studio User-Input diff --git a/app/src/main/res/xml/setting_general.xml b/app/src/main/res/xml/setting_general.xml index 22ffc8a..1ab5863 100644 --- a/app/src/main/res/xml/setting_general.xml +++ b/app/src/main/res/xml/setting_general.xml @@ -8,6 +8,11 @@ android:summary="@string/pref_general_shell_desc" android:title="@string/pref_general_shell" /> + + + android:entryValues="@array/pref_general_program_selection_values" + android:key="@string/key_general_program_selection" + android:summary="@string/pref_general_program_selection_desc" + android:title="@string/pref_general_program_selection" /> \ No newline at end of file