Skip to content

Commit 3e15bbd

Browse files
committed
remoteInterface: support append commands to exist sessions
1 parent cc862be commit 3e15bbd

File tree

4 files changed

+88
-39
lines changed

4 files changed

+88
-39
lines changed

app/src/main/java/io/neoterm/backend/TerminalSession.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public interface SessionChangedCallback {
4646

4747
}
4848

49+
@SuppressWarnings("JavaReflectionMemberAccess")
4950
private static FileDescriptor wrapFileDescriptor(int fileDescriptor) {
5051
FileDescriptor result = new FileDescriptor();
5152
try {
@@ -70,18 +71,18 @@ private static FileDescriptor wrapFileDescriptor(int fileDescriptor) {
7071

7172
public final String mHandle = UUID.randomUUID().toString();
7273

73-
TerminalEmulator mEmulator;
74+
private TerminalEmulator mEmulator;
7475

7576
/**
7677
* A queue written to from a separate thread when the process outputs, and read by main thread to process by
7778
* terminal emulator.
7879
*/
79-
final ByteQueue mProcessToTerminalIOQueue = new ByteQueue(4096);
80+
private final ByteQueue mProcessToTerminalIOQueue = new ByteQueue(4096);
8081
/**
8182
* A queue written to from the main thread due to user interaction, and read by another thread which forwards by
8283
* writing to the {@link #mTerminalFileDescriptor}.
8384
*/
84-
final ByteQueue mTerminalToProcessIOQueue = new ByteQueue(4096);
85+
private final ByteQueue mTerminalToProcessIOQueue = new ByteQueue(4096);
8586
/** Buffer to write translate code points into utf8 before writing to mTerminalToProcessIOQueue */
8687
private final byte[] mUtf8InputBuffer = new byte[5];
8788

@@ -90,13 +91,13 @@ public SessionChangedCallback getSessionChangedCallback() {
9091
}
9192

9293
/** Callback which gets notified when a session finishes or changes title. */
93-
final SessionChangedCallback mChangeCallback;
94+
private final SessionChangedCallback mChangeCallback;
9495

9596
/** The pid of the executablePath process. 0 if not started and -1 if finished running. */
96-
int mShellPid;
97+
private int mShellPid;
9798

9899
/** The exit status of the executablePath process. Only valid if ${@link #mShellPid} is -1. */
99-
int mShellExitStatus;
100+
private int mShellExitStatus;
100101

101102
/**
102103
* The file descriptor referencing the master half of a pseudo-terminal pair, resulting from calling
@@ -108,7 +109,7 @@ public SessionChangedCallback getSessionChangedCallback() {
108109
public String mSessionName;
109110

110111
@SuppressLint("HandlerLeak")
111-
final Handler mMainThreadHandler = new Handler() {
112+
private final Handler mMainThreadHandler = new Handler() {
112113
final byte[] mReceiveBuffer = new byte[4 * 1024];
113114

114115
@Override
@@ -266,7 +267,7 @@ public TerminalEmulator getEmulator() {
266267
}
267268

268269
/** Notify the {@link #mChangeCallback} that the screen has changed. */
269-
protected void notifyScreenUpdate() {
270+
private void notifyScreenUpdate() {
270271
mChangeCallback.onTextChanged(this);
271272
}
272273

@@ -282,7 +283,8 @@ public void finishIfRunning() {
282283
try {
283284
Os.kill(mShellPid, OsConstants.SIGKILL);
284285
} catch (ErrnoException e) {
285-
Log.w("neoterm-termux", "Failed sending SIGKILL: " + e.getMessage());
286+
Log.w("neoterm-shell-session",
287+
"Failed sending SIGKILL: " + e.getMessage());
286288
}
287289
}
288290
}
@@ -301,7 +303,7 @@ protected String getExitDescription(int exitCode) {
301303
}
302304

303305
/** Cleanup resources when the process exits. */
304-
void cleanupResources(int exitStatus) {
306+
private void cleanupResources(int exitStatus) {
305307
synchronized (this) {
306308
mShellPid = -1;
307309
mShellExitStatus = exitStatus;

app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import io.neoterm.backend.TerminalSession
66
* @author kiva
77
*/
88
class ShellParameter {
9+
var sessionId: String? = null;
910
var executablePath: String? = null
1011
var arguments: Array<String>? = null
1112
var cwd: String? = null
@@ -54,4 +55,13 @@ class ShellParameter {
5455
this.shellProfile = shellProfile
5556
return this
5657
}
58+
59+
fun session(sessionId: String?): ShellParameter {
60+
this.sessionId = sessionId
61+
return this
62+
}
63+
64+
fun willCreateNewSession(): Boolean {
65+
return sessionId == null
66+
}
5767
}

app/src/main/java/io/neoterm/services/NeoTermService.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,7 @@ class NeoTermService : Service() {
7777
get() = mXSessions
7878

7979
fun createTermSession(parameter: ShellParameter): TerminalSession {
80-
val session = TerminalUtils.createSession(this, parameter)
81-
mTerminalSessions.add(session)
80+
val session = createOrFindSession(parameter)
8281
updateNotification()
8382
return session
8483
}
@@ -108,6 +107,22 @@ class NeoTermService : Service() {
108107
return indexOfRemoved
109108
}
110109

110+
private fun createOrFindSession(parameter: ShellParameter): TerminalSession {
111+
if (parameter.willCreateNewSession()) {
112+
val session = TerminalUtils.createSession(this, parameter)
113+
mTerminalSessions.add(session)
114+
return session
115+
}
116+
117+
// TODO: find session by id
118+
val sessionId = parameter.sessionId!!
119+
val session = mTerminalSessions.find { it.mHandle == sessionId }
120+
?: throw IllegalArgumentException("cannot find session by given id")
121+
122+
session.write(parameter.initialCommand + "\n")
123+
return session
124+
}
125+
111126
private fun updateNotification() {
112127
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
113128
service.notify(NOTIFICATION_ID, createNotification())
@@ -165,7 +180,8 @@ class NeoTermService : Service() {
165180
private fun acquireLock() {
166181
if (mWakeLock == null) {
167182
val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
168-
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG)
183+
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
184+
EmulatorDebug.LOG_TAG + ":")
169185
mWakeLock!!.acquire()
170186

171187
val wm = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager

app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.neoterm.ui.term
22

3+
import android.app.Activity
34
import android.content.ComponentName
45
import android.content.Intent
56
import android.content.ServiceConnection
@@ -83,10 +84,16 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
8384
return
8485
}
8586
val command = intent.getStringExtra(EXTRA_COMMAND)
86-
openTerm(command)
87+
val foreground = intent.getBooleanExtra(EXTRA_FOREGROUND, true)
88+
val session = if (intent.hasExtra(EXTRA_SESSION_ID)) {
89+
intent.getStringExtra(EXTRA_SESSION_ID)
90+
} else {
91+
null
92+
}
93+
openTerm(command, session, foreground)
8794
}
8895

89-
else -> openTerm(null)
96+
else -> openTerm(null, null)
9097
}
9198
finish()
9299
}
@@ -98,13 +105,15 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
98105
val path = MediaUtils.getPath(this, extra)
99106
val file = File(path)
100107
val dirPath = if (file.isDirectory) path else file.parent
101-
openTerm("cd " + TerminalUtils.escapeString(dirPath))
108+
val command = "cd " + TerminalUtils.escapeString(dirPath)
109+
openTerm(command, null)
102110
}
103111
finish()
104112
} else {
105113
App.get().errorDialog(this,
106-
getString(R.string.unsupported_term_here, intent?.toString()),
107-
{ finish() })
114+
getString(R.string.unsupported_term_here, intent?.toString())) {
115+
finish()
116+
}
108117
}
109118
}
110119

@@ -124,10 +133,10 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
124133
when (extra) {
125134
is ArrayList<*> -> {
126135
extra.takeWhile { it is Uri }
127-
.mapTo(filesToHandle, {
136+
.mapTo(filesToHandle) {
128137
val uri = it as Uri
129138
File(MediaUtils.getPath(this, uri)).absolutePath
130-
})
139+
}
131140
}
132141
is Uri -> {
133142
filesToHandle.add(File(MediaUtils.getPath(this, extra)).absolutePath)
@@ -142,8 +151,8 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
142151
setupUserScriptView(filesToHandle, userScripts)
143152
} else {
144153
App.get().errorDialog(this,
145-
getString(R.string.no_files_selected, intent?.toString()),
146-
{ finish() })
154+
getString(R.string.no_files_selected, intent?.toString())
155+
) { finish() }
147156
}
148157
}
149158

@@ -155,10 +164,10 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
155164
filesList.setOnItemClickListener { _, _, position, _ ->
156165
AlertDialog.Builder(this@NeoTermRemoteInterface)
157166
.setMessage(R.string.confirm_remove_file_from_list)
158-
.setPositiveButton(android.R.string.yes, { _, _ ->
167+
.setPositiveButton(android.R.string.yes) { _, _ ->
159168
filesToHandle.removeAt(position)
160169
filesAdapter.notifyDataSetChanged()
161-
})
170+
}
162171
.setNegativeButton(android.R.string.no, null)
163172
.show()
164173
}
@@ -186,32 +195,42 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
186195
return arguments.toTypedArray()
187196
}
188197

189-
private fun openTerm(parameter: ShellParameter) {
198+
private fun openTerm(parameter: ShellParameter,
199+
foreground: Boolean = true) {
190200
val session = termService!!.createTermSession(parameter)
191201

192-
// Set current session to our new one
193-
// In order to switch to it when entering NeoTermActivity
194-
NeoPreference.storeCurrentSession(session)
202+
if (foreground) {
203+
// Set current session to our new one
204+
// In order to switch to it when entering NeoTermActivity
205+
NeoPreference.storeCurrentSession(session)
206+
207+
val intent = Intent(this, NeoTermActivity::class.java)
208+
intent.addCategory(Intent.CATEGORY_DEFAULT)
209+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
210+
startActivity(intent)
211+
}
195212

196-
val intent = Intent(this, NeoTermActivity::class.java)
197-
intent.addCategory(Intent.CATEGORY_DEFAULT)
198-
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
199-
startActivity(intent)
213+
val data = Intent()
214+
data.putExtra(EXTRA_SESSION_ID, session.mHandle)
215+
setResult(Activity.RESULT_OK, data)
200216
}
201217

202-
private fun openCustomExecTerm(executablePath: String?, arguments: Array<String>?, cwd: String?) {
218+
private fun openTerm(initialCommand: String?,
219+
sessionId: String? = null,
220+
foreground: Boolean = true) {
203221
val parameter = ShellParameter()
204-
.executablePath(executablePath)
205-
.arguments(arguments)
206-
.currentWorkingDirectory(cwd)
222+
.initialCommand(initialCommand)
207223
.callback(TermSessionCallback())
208224
.systemShell(detectSystemShell())
209-
openTerm(parameter)
225+
.session(sessionId)
226+
openTerm(parameter, foreground)
210227
}
211228

212-
private fun openTerm(initialCommand: String?) {
229+
private fun openCustomExecTerm(executablePath: String?, arguments: Array<String>?, cwd: String?) {
213230
val parameter = ShellParameter()
214-
.initialCommand(initialCommand)
231+
.executablePath(executablePath)
232+
.arguments(arguments)
233+
.currentWorkingDirectory(cwd)
215234
.callback(TermSessionCallback())
216235
.systemShell(detectSystemShell())
217236
openTerm(parameter)
@@ -224,5 +243,7 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
224243
companion object {
225244
const val ACTION_EXECUTE = "neoterm.action.remote.execute"
226245
const val EXTRA_COMMAND = "neoterm.extra.remote.execute.command"
246+
const val EXTRA_SESSION_ID = "neoterm.extra.remote.execute.session"
247+
const val EXTRA_FOREGROUND = "neoterm.extra.remote.execute.foreground"
227248
}
228249
}

0 commit comments

Comments
 (0)