mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-15 18:02:58 +08:00
feat: OSC 1337 (#244)
This commit is contained in:
@@ -5,6 +5,17 @@ import org.apache.commons.lang3.StringUtils
|
||||
import java.util.*
|
||||
|
||||
|
||||
fun Map<*, *>.toPropertiesString(): String {
|
||||
val env = StringBuilder()
|
||||
for ((i, e) in entries.withIndex()) {
|
||||
env.append(e.key).append('=').append(e.value)
|
||||
if (i != size - 1) {
|
||||
env.appendLine()
|
||||
}
|
||||
}
|
||||
return env.toString()
|
||||
}
|
||||
|
||||
fun UUID.toSimpleString(): String {
|
||||
return toString().replace("-", StringUtils.EMPTY)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package app.termora
|
||||
|
||||
import app.termora.actions.DataProvider
|
||||
import app.termora.actions.DataProviders
|
||||
import app.termora.terminal.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -12,7 +14,7 @@ abstract class HostTerminalTab(
|
||||
val windowScope: WindowScope,
|
||||
val host: Host,
|
||||
protected val terminal: Terminal = TerminalFactory.getInstance(windowScope).createTerminal()
|
||||
) : PropertyTerminalTab() {
|
||||
) : PropertyTerminalTab(), DataProvider {
|
||||
companion object {
|
||||
val Host = DataKey(app.termora.Host::class)
|
||||
}
|
||||
@@ -69,4 +71,11 @@ abstract class HostTerminalTab(
|
||||
unread = false
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any> getData(dataKey: DataKey<T>): T? {
|
||||
if (dataKey == DataProviders.Terminal) {
|
||||
return terminal as T?
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package app.termora
|
||||
|
||||
import app.termora.actions.DataProviders
|
||||
import app.termora.terminal.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.swing.Swing
|
||||
@@ -135,4 +136,12 @@ abstract class PtyHostTerminalTab(
|
||||
}
|
||||
|
||||
abstract suspend fun openPtyConnector(): PtyConnector
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any> getData(dataKey: DataKey<T>): T? {
|
||||
if (dataKey == DataProviders.TerminalPanel) {
|
||||
return terminalPanel as T?
|
||||
}
|
||||
return super.getData(dataKey)
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,14 @@ class SFTPPtyTerminalTab(windowScope: WindowScope, host: Host) : PtyHostTerminal
|
||||
// 设置认证信息
|
||||
setAuthentication(commands, host)
|
||||
|
||||
commands.add("${host.username}@${host.host}")
|
||||
|
||||
val envs = host.options.envs()
|
||||
if (envs.containsKey("CurrentDir")) {
|
||||
val currentDir = envs.getValue("CurrentDir")
|
||||
commands.add("${host.username}@${host.host}:${currentDir}")
|
||||
} else {
|
||||
commands.add("${host.username}@${host.host}")
|
||||
}
|
||||
|
||||
val winSize = terminalPanel.winSize()
|
||||
val ptyConnector = ptyConnectorFactory.createPtyConnector(
|
||||
|
||||
@@ -236,21 +236,12 @@ class TerminalTabbed(
|
||||
})
|
||||
|
||||
if (tab is HostTerminalTab) {
|
||||
if (tab.host.protocol == Protocol.SSH || tab.host.protocol == Protocol.SFTPPty) {
|
||||
popupMenu.addSeparator()
|
||||
val sftpCommand = popupMenu.add(I18n.getString("termora.tabbed.contextmenu.sftp-command"))
|
||||
sftpCommand.addActionListener {
|
||||
if (SFTPPtyTerminalTab.canSupports) {
|
||||
actionManager.getAction(OpenHostAction.OPEN_HOST)
|
||||
?.actionPerformed(OpenHostActionEvent(this, tab.host.copy(protocol = Protocol.SFTPPty), it))
|
||||
} else {
|
||||
OptionPane.showMessageDialog(
|
||||
SwingUtilities.getWindowAncestor(this),
|
||||
I18n.getString("termora.tabbed.contextmenu.sftp-not-install"),
|
||||
messageType = JOptionPane.ERROR_MESSAGE
|
||||
)
|
||||
}
|
||||
|
||||
val openHostAction = actionManager.getAction(OpenHostAction.OPEN_HOST)
|
||||
if (openHostAction != null) {
|
||||
if (tab.host.protocol == Protocol.SSH || tab.host.protocol == Protocol.SFTPPty) {
|
||||
popupMenu.addSeparator()
|
||||
val sftpCommand = popupMenu.add(I18n.getString("termora.tabbed.contextmenu.sftp-command"))
|
||||
sftpCommand.addActionListener { openSFTPPtyTab(tab, openHostAction, it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,6 +319,36 @@ class TerminalTabbed(
|
||||
Disposer.register(this, tab)
|
||||
}
|
||||
|
||||
private fun openSFTPPtyTab(tab: HostTerminalTab, openHostAction: Action, evt: EventObject) {
|
||||
if (!SFTPPtyTerminalTab.canSupports) {
|
||||
OptionPane.showMessageDialog(
|
||||
SwingUtilities.getWindowAncestor(this),
|
||||
I18n.getString("termora.tabbed.contextmenu.sftp-not-install"),
|
||||
messageType = JOptionPane.ERROR_MESSAGE
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
var host = tab.host
|
||||
|
||||
if (host.protocol == Protocol.SSH) {
|
||||
val envs = tab.host.options.envs().toMutableMap()
|
||||
val currentDir = tab.getData(DataProviders.Terminal)?.getTerminalModel()
|
||||
?.getData(DataKey.CurrentDir, StringUtils.EMPTY) ?: StringUtils.EMPTY
|
||||
|
||||
if (currentDir.isNotBlank()) {
|
||||
envs["CurrentDir"] = currentDir
|
||||
}
|
||||
|
||||
host = host.copy(
|
||||
protocol = Protocol.SFTPPty,
|
||||
options = host.options.copy(env = envs.toPropertiesString())
|
||||
)
|
||||
}
|
||||
|
||||
openHostAction.actionPerformed(OpenHostActionEvent(this, host, evt))
|
||||
}
|
||||
|
||||
/**
|
||||
* 对着 ToolBar 右键
|
||||
*/
|
||||
|
||||
@@ -74,6 +74,13 @@ class DataKey<T : Any>(val clazz: KClass<T>) {
|
||||
*/
|
||||
val Workdir = DataKey(String::class)
|
||||
|
||||
/**
|
||||
* OSC 1337 CurrentDir
|
||||
*
|
||||
* https://iterm2.com/documentation-escape-codes.html
|
||||
*/
|
||||
val CurrentDir = DataKey(String::class)
|
||||
|
||||
/**
|
||||
* true: alternate keypad.
|
||||
* false: Normal Keypad (DECKPNM)
|
||||
|
||||
@@ -4,6 +4,8 @@ import org.apache.commons.codec.binary.Base64
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.awt.Toolkit
|
||||
import java.awt.datatransfer.StringSelection
|
||||
import java.io.StringReader
|
||||
import java.util.*
|
||||
|
||||
class OperatingSystemCommandProcessor(terminal: Terminal, reader: TerminalReader) :
|
||||
AbstractProcessor(terminal, reader) {
|
||||
@@ -85,6 +87,19 @@ class OperatingSystemCommandProcessor(terminal: Terminal, reader: TerminalReader
|
||||
}
|
||||
}
|
||||
|
||||
// https://iterm2.com/documentation-escape-codes.html
|
||||
1337 -> {
|
||||
val properties = Properties()
|
||||
properties.load(StringReader(suffix))
|
||||
if (properties.containsKey("CurrentDir")) {
|
||||
val currentDir = properties.getProperty("CurrentDir")
|
||||
terminal.getTerminalModel().setData(DataKey.CurrentDir, currentDir)
|
||||
if (log.isDebugEnabled) {
|
||||
log.debug("CurrentDir: $currentDir")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 11: background color
|
||||
// 10: foreground color
|
||||
11, 10 -> {
|
||||
|
||||
Reference in New Issue
Block a user