Feature: TermHere and UserScript from FileManager

This commit is contained in:
zt515 2017-07-18 23:55:01 +08:00
parent 842aa5a6ca
commit 12e820bb5f
18 changed files with 238 additions and 52 deletions

View File

@ -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 {

View File

@ -29,19 +29,45 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.term.TermHereActivity"
android:name=".ui.term.NeoTermRemoteInterface"
android:excludeFromRecents="true"
android:exported="false">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity-alias
android:name=".ui.term.TermHere"
android:exported="true"
android:label="@string/term_here">
android:label="@string/term_here"
android:targetActivity=".ui.term.NeoTermRemoteInterface">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.MAIN" />
<data android:mimeType="*/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</activity-alias>
<activity-alias
android:name=".ui.term.UserScript"
android:exported="true"
android:label="@string/user_script"
android:targetActivity=".ui.term.NeoTermRemoteInterface">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<action android:name="android.intent.action.MAIN" />
<data android:mimeType="*/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity-alias>
<activity
android:name=".ui.crash.CrashActivity"
android:exported="false"

View File

@ -143,16 +143,18 @@ public final class TerminalSession extends TerminalOutput {
private final String mShellPath;
private final String mCwd;
private final String mInitialCommand;
private final String[] mArgs;
private final String[] mEnv;
public TerminalSession(String shellPath, String cwd, String[] args, String[] env, SessionChangedCallback changeCallback) {
public TerminalSession(String shellPath, String cwd, String initialCommand, String[] args, String[] env, SessionChangedCallback changeCallback) {
mChangeCallback = changeCallback;
this.mShellPath = shellPath;
this.mCwd = cwd;
this.mArgs = args;
this.mEnv = env;
this.mInitialCommand = initialCommand;
}
/** Inform the attached pty of the new size and reflow or initialize the emulator. */
@ -226,6 +228,9 @@ public final class TerminalSession extends TerminalOutput {
}
}.start();
if (mInitialCommand != null && mInitialCommand.length() > 0) {
write(mInitialCommand + '\r');
}
}
/** Write data to the shell process. */

View File

@ -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"

View File

@ -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<TerminalSession>
get() = mTerminalSessions
fun createTermSession(executablePath: String?, arguments: Array<String>?, cwd: String?, env: Array<String>?, sessionCallback: TerminalSession.SessionChangedCallback?, systemShell: Boolean): TerminalSession {
val session = TerminalUtils.createSession(this, executablePath, arguments, cwd, env, sessionCallback, systemShell)
fun createTermSession(executablePath: String?, arguments: Array<String>?, cwd: String?, initialCommand: String?, env: Array<String>?, 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
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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<String>()
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>): String {
val builder = StringBuilder()
files.forEach {
builder.append(TerminalUtils.escapeString(it))
builder.append(" ")
}
return builder.toString()
}
}

View File

@ -1,9 +0,0 @@
package io.neoterm.ui.term
import android.support.v7.app.AppCompatActivity
/**
* @author kiva
*/
class TermHereActivity : AppCompatActivity() {
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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<String>?, cwd: String?, env: Array<String>?, sessionCallback: TerminalSession.SessionChangedCallback?, systemShell: Boolean): TerminalSession {
fun createSession(context: Context, executablePath: String?, arguments: Array<String>?,
cwd: String?, initialCommand: String?, env: Array<String>?,
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<String>(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()
}
}

View File

@ -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
}

View File

@ -8,7 +8,7 @@
<string name="package_settings">软件包设置</string>
<string name="paste_text">粘贴</string>
<string name="pref_general_backspace_map_to_esc">返回键发送ESC</string>
<string name="pref_general_backspace_map_to_esc_desc">当返回键按下时发送ESC而不是退出终端</string>
<string name="pref_general_backspace_map_to_esc_desc">当返回键按下时发送ESC而不是关闭窗口</string>
<string name="pref_general_bell">响铃</string>
<string name="pref_general_bell_desc">收到 \'\\a\' 时响铃</string>
<string name="pref_general_shell_desc">登录时使用指定的 Shell</string>
@ -16,10 +16,12 @@
<string name="pref_general_vibrate_desc">收到 \'\\a\' 时振动</string>
<string name="pref_general_program_selection">程序选择模式</string>
<string name="pref_general_program_selection_desc">当 NeoTerm 和 系统 中都含有同一个程序时,选择将要被执行的程序的模式</string>
<string name="pref_general_initial_command">初始命令</string>
<string name="pref_general_initial_command_desc">在新的实例创建时执行命令</string>
<string name="pref_package_source">软件源</string>
<string name="pref_ui_close_tab_anim_next_tab">向下切换窗口</string>
<string name="pref_ui_close_tab_anim_next_tab_desc">关闭当前窗口时切换到下一个窗口而不是上一个</string>
<string name="customization_settings_desc">字体,主题,拓展键盘</string>
<string name="customization_settings_desc">字体,主题,拓展键盘,自动补全</string>
<string name="customization_settings">个性化</string>
<string name="pref_ui_fullscreen">全屏</string>
<string name="pref_ui_hide_toolbar">隐藏标题栏</string>
@ -47,7 +49,7 @@
<string name="package_details">软件包: %s\n版本: %s\n依赖: %s\n占用空间: %s\n描述: %s\n主页: %s</string>
<string name="package_list_empty">软件包列表为空,请检查你的软件源</string>
<string name="menu_refresh_list">刷新</string>
<string name="menu_update">更新 刷新</string>
<string name="menu_update">更新刷新</string>
<string-array name="pref_general_program_selection_entries">
<item>只使用 NeoTerm</item>
@ -63,9 +65,9 @@
<item>输入…</item>
</string-array>
<string name="pref_customization_eks">拓展键盘</string>
<string name="general_settings_desc">响铃振动Shell</string>
<string name="ui_settings_desc">全屏,标题栏,快捷键盘</string>
<string name="package_settings_desc">源,更新,升级</string>
<string name="general_settings_desc">响铃振动Shell,初始命令</string>
<string name="ui_settings_desc">全屏,标题栏,切换动画</string>
<string name="package_settings_desc">软件源,更新,升级</string>
<string name="install_font">安装字体</string>
<string name="install_color">安装配色方案</string>
<string name="setup_hello">发现</string>
@ -83,4 +85,5 @@
<string name="service_release_lock">释放休眠锁</string>
<string name="exit">退出</string>
<string name="term_here">在此处打开终端</string>
<string name="user_script">用户脚本</string>
</resources>

View File

@ -5,6 +5,7 @@
<string name="key_generaL_backspace_map_to_esc" translatable="false">neoterm_general_backspace_map_to_esc</string>
<string name="key_general_shell" translatable="false">neoterm_general_shell</string>
<string name="key_general_program_selection" translatable="false">neoterm_general_program_selection</string>
<string name="key_general_initial_command" translatable="false">neoterm_general_initial_command</string>
<string name="key_ui_fullscreen" translatable="false">neoterm_ui_fullscreen</string>
<string name="key_ui_hide_toolbar" translatable="false">neoterm_ui_hide_toolbar</string>

View File

@ -20,12 +20,12 @@
<string name="discovery">Discovery</string>
<string name="settings">Settings</string>
<string name="general_settings">General Settings</string>
<string name="general_settings_desc">Bell, Vibrate, Shell</string>
<string name="general_settings_desc">Bell, Vibrate, Shell, Initial Command</string>
<string name="ui_settings">UI Settings</string>
<string name="ui_settings_desc">FullScreen, Title Bar, Suggestions</string>
<string name="ui_settings_desc">FullScreen, Title Bar, Animation</string>
<string name="package_settings">Package Settings</string>
<string name="package_settings_desc">Source, Updates, Upgrades</string>
<string name="customization_settings_desc">Font, ColorScheme, ExtraKeys</string>
<string name="customization_settings_desc">Font, ColorScheme, ExtraKeys, AutoComplete</string>
<string name="customization_settings">Customization</string>
<string name="toggle_ime">Toggle IME</string>
@ -41,7 +41,7 @@
<string name="package_details">Package: %s\nVersion: %s\nDepends: %s\nInstalled Size: %s\nDescription: %s\nHome Page: %s</string>
<string name="package_list_empty">Package list is empty, please check out your source.</string>
<string name="menu_refresh_list">Refresh</string>
<string name="menu_update">Update, Refresh</string>
<string name="menu_update">Update and Refresh</string>
<string name="install_font">Install Font</string>
<string name="install_color">Install Color Scheme</string>
@ -63,6 +63,8 @@
<string name="pref_general_shell_desc">Which shell should we use when login</string>
<string name="pref_general_program_selection">Program Selection</string>
<string name="pref_general_program_selection_desc">When both Neo Term and your Android OS have a program, which one should we choose?</string>
<string name="pref_general_initial_command">Initial Command</string>
<string name="pref_general_initial_command_desc">Execute commands when a session is being created</string>
<string name="pref_ui_fullscreen">Full Screen</string>
<string name="pref_ui_hide_toolbar">Hide Toolbar</string>
<string name="pref_ui_hide_toolbar_desc">Hide toolbar when keyboard is showing</string>
@ -78,6 +80,7 @@
<string name="pref_package_source">Source</string>
<string name="exit">Exit</string>
<string name="term_here">Term Here</string>
<string name="user_script">User Script</string>
<string-array name="pref_general_shell_entries" translatable="false">
<item>sh</item>
@ -108,7 +111,7 @@
<string-array name="pref_package_source_values" translatable="false">
<item>https://mirrors.geekpie.org/neoterm</item>
<item>http://192.243.117.135</item>
<item>http://neoterm.studio</item>
<item>User-Input</item>
</string-array>

View File

@ -8,6 +8,11 @@
android:summary="@string/pref_general_shell_desc"
android:title="@string/pref_general_shell" />
<EditTextPreference
android:key="@string/key_general_initial_command"
android:summary="@string/pref_general_initial_command_desc"
android:title="@string/pref_general_initial_command" />
<CheckBoxPreference
android:defaultValue="false"
android:key="@string/key_general_bell"
@ -28,10 +33,10 @@
<ListPreference
android:defaultValue="NeoTermOnly"
android:key="@string/key_general_program_selection"
android:title="@string/pref_general_program_selection"
android:summary="@string/pref_general_program_selection_desc"
android:entries="@array/pref_general_program_selection_entries"
android:entryValues="@array/pref_general_program_selection_values"/>
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" />
</PreferenceScreen>