remoteInterface: support append commands to exist sessions
This commit is contained in:
parent
cc862be3f1
commit
3e15bbd2f7
@ -46,6 +46,7 @@ public class TerminalSession extends TerminalOutput {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("JavaReflectionMemberAccess")
|
||||
private static FileDescriptor wrapFileDescriptor(int fileDescriptor) {
|
||||
FileDescriptor result = new FileDescriptor();
|
||||
try {
|
||||
@ -70,18 +71,18 @@ public class TerminalSession extends TerminalOutput {
|
||||
|
||||
public final String mHandle = UUID.randomUUID().toString();
|
||||
|
||||
TerminalEmulator mEmulator;
|
||||
private TerminalEmulator mEmulator;
|
||||
|
||||
/**
|
||||
* A queue written to from a separate thread when the process outputs, and read by main thread to process by
|
||||
* terminal emulator.
|
||||
*/
|
||||
final ByteQueue mProcessToTerminalIOQueue = new ByteQueue(4096);
|
||||
private final ByteQueue mProcessToTerminalIOQueue = new ByteQueue(4096);
|
||||
/**
|
||||
* A queue written to from the main thread due to user interaction, and read by another thread which forwards by
|
||||
* writing to the {@link #mTerminalFileDescriptor}.
|
||||
*/
|
||||
final ByteQueue mTerminalToProcessIOQueue = new ByteQueue(4096);
|
||||
private final ByteQueue mTerminalToProcessIOQueue = new ByteQueue(4096);
|
||||
/** Buffer to write translate code points into utf8 before writing to mTerminalToProcessIOQueue */
|
||||
private final byte[] mUtf8InputBuffer = new byte[5];
|
||||
|
||||
@ -90,13 +91,13 @@ public class TerminalSession extends TerminalOutput {
|
||||
}
|
||||
|
||||
/** Callback which gets notified when a session finishes or changes title. */
|
||||
final SessionChangedCallback mChangeCallback;
|
||||
private final SessionChangedCallback mChangeCallback;
|
||||
|
||||
/** The pid of the executablePath process. 0 if not started and -1 if finished running. */
|
||||
int mShellPid;
|
||||
private int mShellPid;
|
||||
|
||||
/** The exit status of the executablePath process. Only valid if ${@link #mShellPid} is -1. */
|
||||
int mShellExitStatus;
|
||||
private int mShellExitStatus;
|
||||
|
||||
/**
|
||||
* The file descriptor referencing the master half of a pseudo-terminal pair, resulting from calling
|
||||
@ -108,7 +109,7 @@ public class TerminalSession extends TerminalOutput {
|
||||
public String mSessionName;
|
||||
|
||||
@SuppressLint("HandlerLeak")
|
||||
final Handler mMainThreadHandler = new Handler() {
|
||||
private final Handler mMainThreadHandler = new Handler() {
|
||||
final byte[] mReceiveBuffer = new byte[4 * 1024];
|
||||
|
||||
@Override
|
||||
@ -266,7 +267,7 @@ public class TerminalSession extends TerminalOutput {
|
||||
}
|
||||
|
||||
/** Notify the {@link #mChangeCallback} that the screen has changed. */
|
||||
protected void notifyScreenUpdate() {
|
||||
private void notifyScreenUpdate() {
|
||||
mChangeCallback.onTextChanged(this);
|
||||
}
|
||||
|
||||
@ -282,7 +283,8 @@ public class TerminalSession extends TerminalOutput {
|
||||
try {
|
||||
Os.kill(mShellPid, OsConstants.SIGKILL);
|
||||
} catch (ErrnoException e) {
|
||||
Log.w("neoterm-termux", "Failed sending SIGKILL: " + e.getMessage());
|
||||
Log.w("neoterm-shell-session",
|
||||
"Failed sending SIGKILL: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -301,7 +303,7 @@ public class TerminalSession extends TerminalOutput {
|
||||
}
|
||||
|
||||
/** Cleanup resources when the process exits. */
|
||||
void cleanupResources(int exitStatus) {
|
||||
private void cleanupResources(int exitStatus) {
|
||||
synchronized (this) {
|
||||
mShellPid = -1;
|
||||
mShellExitStatus = exitStatus;
|
||||
|
@ -6,6 +6,7 @@ import io.neoterm.backend.TerminalSession
|
||||
* @author kiva
|
||||
*/
|
||||
class ShellParameter {
|
||||
var sessionId: String? = null;
|
||||
var executablePath: String? = null
|
||||
var arguments: Array<String>? = null
|
||||
var cwd: String? = null
|
||||
@ -54,4 +55,13 @@ class ShellParameter {
|
||||
this.shellProfile = shellProfile
|
||||
return this
|
||||
}
|
||||
|
||||
fun session(sessionId: String?): ShellParameter {
|
||||
this.sessionId = sessionId
|
||||
return this
|
||||
}
|
||||
|
||||
fun willCreateNewSession(): Boolean {
|
||||
return sessionId == null
|
||||
}
|
||||
}
|
@ -77,8 +77,7 @@ class NeoTermService : Service() {
|
||||
get() = mXSessions
|
||||
|
||||
fun createTermSession(parameter: ShellParameter): TerminalSession {
|
||||
val session = TerminalUtils.createSession(this, parameter)
|
||||
mTerminalSessions.add(session)
|
||||
val session = createOrFindSession(parameter)
|
||||
updateNotification()
|
||||
return session
|
||||
}
|
||||
@ -108,6 +107,22 @@ class NeoTermService : Service() {
|
||||
return indexOfRemoved
|
||||
}
|
||||
|
||||
private fun createOrFindSession(parameter: ShellParameter): TerminalSession {
|
||||
if (parameter.willCreateNewSession()) {
|
||||
val session = TerminalUtils.createSession(this, parameter)
|
||||
mTerminalSessions.add(session)
|
||||
return session
|
||||
}
|
||||
|
||||
// TODO: find session by id
|
||||
val sessionId = parameter.sessionId!!
|
||||
val session = mTerminalSessions.find { it.mHandle == sessionId }
|
||||
?: throw IllegalArgumentException("cannot find session by given id")
|
||||
|
||||
session.write(parameter.initialCommand + "\n")
|
||||
return session
|
||||
}
|
||||
|
||||
private fun updateNotification() {
|
||||
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
service.notify(NOTIFICATION_ID, createNotification())
|
||||
@ -165,7 +180,8 @@ class NeoTermService : Service() {
|
||||
private fun acquireLock() {
|
||||
if (mWakeLock == null) {
|
||||
val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
|
||||
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG)
|
||||
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
|
||||
EmulatorDebug.LOG_TAG + ":")
|
||||
mWakeLock!!.acquire()
|
||||
|
||||
val wm = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.neoterm.ui.term
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
@ -83,10 +84,16 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
return
|
||||
}
|
||||
val command = intent.getStringExtra(EXTRA_COMMAND)
|
||||
openTerm(command)
|
||||
val foreground = intent.getBooleanExtra(EXTRA_FOREGROUND, true)
|
||||
val session = if (intent.hasExtra(EXTRA_SESSION_ID)) {
|
||||
intent.getStringExtra(EXTRA_SESSION_ID)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
openTerm(command, session, foreground)
|
||||
}
|
||||
|
||||
else -> openTerm(null)
|
||||
else -> openTerm(null, null)
|
||||
}
|
||||
finish()
|
||||
}
|
||||
@ -98,13 +105,15 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
val path = MediaUtils.getPath(this, extra)
|
||||
val file = File(path)
|
||||
val dirPath = if (file.isDirectory) path else file.parent
|
||||
openTerm("cd " + TerminalUtils.escapeString(dirPath))
|
||||
val command = "cd " + TerminalUtils.escapeString(dirPath)
|
||||
openTerm(command, null)
|
||||
}
|
||||
finish()
|
||||
} else {
|
||||
App.get().errorDialog(this,
|
||||
getString(R.string.unsupported_term_here, intent?.toString()),
|
||||
{ finish() })
|
||||
getString(R.string.unsupported_term_here, intent?.toString())) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,10 +133,10 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
when (extra) {
|
||||
is ArrayList<*> -> {
|
||||
extra.takeWhile { it is Uri }
|
||||
.mapTo(filesToHandle, {
|
||||
.mapTo(filesToHandle) {
|
||||
val uri = it as Uri
|
||||
File(MediaUtils.getPath(this, uri)).absolutePath
|
||||
})
|
||||
}
|
||||
}
|
||||
is Uri -> {
|
||||
filesToHandle.add(File(MediaUtils.getPath(this, extra)).absolutePath)
|
||||
@ -142,8 +151,8 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
setupUserScriptView(filesToHandle, userScripts)
|
||||
} else {
|
||||
App.get().errorDialog(this,
|
||||
getString(R.string.no_files_selected, intent?.toString()),
|
||||
{ finish() })
|
||||
getString(R.string.no_files_selected, intent?.toString())
|
||||
) { finish() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,10 +164,10 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
filesList.setOnItemClickListener { _, _, position, _ ->
|
||||
AlertDialog.Builder(this@NeoTermRemoteInterface)
|
||||
.setMessage(R.string.confirm_remove_file_from_list)
|
||||
.setPositiveButton(android.R.string.yes, { _, _ ->
|
||||
.setPositiveButton(android.R.string.yes) { _, _ ->
|
||||
filesToHandle.removeAt(position)
|
||||
filesAdapter.notifyDataSetChanged()
|
||||
})
|
||||
}
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show()
|
||||
}
|
||||
@ -186,17 +195,35 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
return arguments.toTypedArray()
|
||||
}
|
||||
|
||||
private fun openTerm(parameter: ShellParameter) {
|
||||
private fun openTerm(parameter: ShellParameter,
|
||||
foreground: Boolean = true) {
|
||||
val session = termService!!.createTermSession(parameter)
|
||||
|
||||
// Set current session to our new one
|
||||
// In order to switch to it when entering NeoTermActivity
|
||||
NeoPreference.storeCurrentSession(session)
|
||||
if (foreground) {
|
||||
// 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)
|
||||
val intent = Intent(this, NeoTermActivity::class.java)
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
val data = Intent()
|
||||
data.putExtra(EXTRA_SESSION_ID, session.mHandle)
|
||||
setResult(Activity.RESULT_OK, data)
|
||||
}
|
||||
|
||||
private fun openTerm(initialCommand: String?,
|
||||
sessionId: String? = null,
|
||||
foreground: Boolean = true) {
|
||||
val parameter = ShellParameter()
|
||||
.initialCommand(initialCommand)
|
||||
.callback(TermSessionCallback())
|
||||
.systemShell(detectSystemShell())
|
||||
.session(sessionId)
|
||||
openTerm(parameter, foreground)
|
||||
}
|
||||
|
||||
private fun openCustomExecTerm(executablePath: String?, arguments: Array<String>?, cwd: String?) {
|
||||
@ -209,14 +236,6 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
openTerm(parameter)
|
||||
}
|
||||
|
||||
private fun openTerm(initialCommand: String?) {
|
||||
val parameter = ShellParameter()
|
||||
.initialCommand(initialCommand)
|
||||
.callback(TermSessionCallback())
|
||||
.systemShell(detectSystemShell())
|
||||
openTerm(parameter)
|
||||
}
|
||||
|
||||
private fun detectSystemShell(): Boolean {
|
||||
return false
|
||||
}
|
||||
@ -224,5 +243,7 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
|
||||
companion object {
|
||||
const val ACTION_EXECUTE = "neoterm.action.remote.execute"
|
||||
const val EXTRA_COMMAND = "neoterm.extra.remote.execute.command"
|
||||
const val EXTRA_SESSION_ID = "neoterm.extra.remote.execute.session"
|
||||
const val EXTRA_FOREGROUND = "neoterm.extra.remote.execute.foreground"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user