mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
feat: support modifying log format
This commit is contained in:
@@ -4,7 +4,7 @@ slf4j = "2.0.17"
|
|||||||
pty4j = "0.13.6"
|
pty4j = "0.13.6"
|
||||||
tinylog = "2.7.0"
|
tinylog = "2.7.0"
|
||||||
kotlinx-coroutines = "1.10.2"
|
kotlinx-coroutines = "1.10.2"
|
||||||
flatlaf = "3.6.1-SNAPSHOT"
|
flatlaf = "3.6.1"
|
||||||
kotlinx-serialization-json = "1.9.0"
|
kotlinx-serialization-json = "1.9.0"
|
||||||
commons-codec = "1.18.0"
|
commons-codec = "1.18.0"
|
||||||
commons-lang3 = "3.18.0"
|
commons-lang3 = "3.18.0"
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ internal class MyTermoraToolbar(private val windowScope: WindowScope, private va
|
|||||||
if (action is StateAction) {
|
if (action is StateAction) {
|
||||||
button.isSelected = action.isSelected(windowScope)
|
button.isSelected = action.isSelected(windowScope)
|
||||||
}
|
}
|
||||||
|
button.icon = action.getValue(Action.SMALL_ICON) as? Icon
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class ActionManager : org.jdesktop.swingx.action.ActionManager() {
|
|||||||
addAction(QuickConnectAction.QUICK_CONNECT, QuickConnectAction.instance)
|
addAction(QuickConnectAction.QUICK_CONNECT, QuickConnectAction.instance)
|
||||||
|
|
||||||
addAction(Actions.KEYWORD_HIGHLIGHT, KeywordHighlightAction())
|
addAction(Actions.KEYWORD_HIGHLIGHT, KeywordHighlightAction())
|
||||||
addAction(Actions.TERMINAL_LOGGER, TerminalLoggerAction())
|
addAction(Actions.TERMINAL_LOGGER, TerminalLoggerAction.getInstance())
|
||||||
addAction(Actions.SFTP, TransferAnAction())
|
addAction(Actions.SFTP, TransferAnAction())
|
||||||
addAction(SFTPCommandAction.SFTP_COMMAND, SFTPCommandAction())
|
addAction(SFTPCommandAction.SFTP_COMMAND, SFTPCommandAction())
|
||||||
addAction(MultipleAction.MULTIPLE, MultipleAction.getInstance())
|
addAction(MultipleAction.MULTIPLE, MultipleAction.getInstance())
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package app.termora.terminal
|
package app.termora.terminal
|
||||||
|
|
||||||
class TextProcessor(private val terminal: Terminal, private val reader: TerminalReader) : Processor {
|
internal class TextProcessor(private val terminal: Terminal, private val reader: TerminalReader) : Processor {
|
||||||
|
companion object {
|
||||||
|
val Written = DataKey(String::class)
|
||||||
|
}
|
||||||
|
|
||||||
private val sb = StringBuilder()
|
private val sb = StringBuilder()
|
||||||
private val terminals = setOf(
|
private val terminals = setOf(
|
||||||
ControlCharacters.ESC, ControlCharacters.BEL, ControlCharacters.CR, ControlCharacters.LF,
|
ControlCharacters.ESC, ControlCharacters.BEL, ControlCharacters.CR, ControlCharacters.LF,
|
||||||
@@ -31,7 +35,9 @@ class TextProcessor(private val terminal: Terminal, private val reader: Terminal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun process() {
|
private fun process() {
|
||||||
terminal.getDocument().write(sb.toString())
|
val text = sb.toString()
|
||||||
|
terminal.getDocument().write(text)
|
||||||
|
terminal.getTerminalModel().setData(Written, text)
|
||||||
sb.clear()
|
sb.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package app.termora.tlog
|
|||||||
|
|
||||||
import app.termora.TerminalFactory
|
import app.termora.TerminalFactory
|
||||||
import app.termora.terminal.*
|
import app.termora.terminal.*
|
||||||
|
import app.termora.terminal.panel.TerminalPanel
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
class LogViewerTerminal : TerminalFactory.MyVisualTerminal() {
|
class LogViewerTerminal : TerminalFactory.MyVisualTerminal() {
|
||||||
@@ -50,6 +51,8 @@ class LogViewerTerminal : TerminalFactory.MyVisualTerminal() {
|
|||||||
override fun <T : Any> getData(key: DataKey<T>, defaultValue: T): T {
|
override fun <T : Any> getData(key: DataKey<T>, defaultValue: T): T {
|
||||||
if (key == DataKey.ShowCursor) {
|
if (key == DataKey.ShowCursor) {
|
||||||
return false as T
|
return false as T
|
||||||
|
} else if (key == TerminalPanel.FocusMode) {
|
||||||
|
return false as T
|
||||||
}
|
}
|
||||||
return super.getData(key, defaultValue)
|
return super.getData(key, defaultValue)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,24 @@ import app.termora.database.DatabaseManager
|
|||||||
import com.formdev.flatlaf.extras.components.FlatPopupMenu
|
import com.formdev.flatlaf.extras.components.FlatPopupMenu
|
||||||
import com.formdev.flatlaf.util.SystemInfo
|
import com.formdev.flatlaf.util.SystemInfo
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import java.awt.Window
|
import java.awt.Window
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.swing.JComponent
|
import javax.swing.*
|
||||||
import javax.swing.JFileChooser
|
|
||||||
import javax.swing.SwingUtilities
|
class TerminalLoggerAction private constructor() :
|
||||||
|
AnAction(I18n.getString("termora.terminal-logger"), Icons.listFiles) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun getInstance(): TerminalLoggerAction {
|
||||||
|
return ApplicationScope.forApplicationScope()
|
||||||
|
.getOrCreate(TerminalLoggerAction::class) { TerminalLoggerAction() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private val log = LoggerFactory.getLogger(TerminalLoggerAction::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
class TerminalLoggerAction : AnAction(I18n.getString("termora.terminal-logger"), Icons.listFiles) {
|
|
||||||
private val properties get() = DatabaseManager.getInstance().properties
|
private val properties get() = DatabaseManager.getInstance().properties
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +38,12 @@ class TerminalLoggerAction : AnAction(I18n.getString("termora.terminal-logger"),
|
|||||||
properties.putString("terminal.logger.isRecording", value.toString())
|
properties.putString("terminal.logger.isRecording", value.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPlainText = properties.getString("terminal.logger.isPlainText")?.toBoolean() ?: false
|
||||||
|
private set(value) {
|
||||||
|
field = value
|
||||||
|
properties.putString("terminal.logger.isPlainText", value.toString())
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
smallIcon = if (isRecording) Icons.dotListFiles else Icons.listFiles
|
smallIcon = if (isRecording) Icons.dotListFiles else Icons.listFiles
|
||||||
}
|
}
|
||||||
@@ -51,6 +67,19 @@ class TerminalLoggerAction : AnAction(I18n.getString("termora.terminal-logger"),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val settingMenu = JMenu(I18n.getString("termora.setting"))
|
||||||
|
val plainText = settingMenu.add(JCheckBoxMenuItem(I18n.getString("termora.terminal-logger.plain-text")))
|
||||||
|
val styledText = settingMenu.add(JCheckBoxMenuItem(I18n.getString("termora.terminal-logger.styled-text")))
|
||||||
|
plainText.isSelected = isPlainText
|
||||||
|
styledText.isSelected = plainText.isSelected.not()
|
||||||
|
plainText.isEnabled = isRecording.not()
|
||||||
|
styledText.isEnabled = plainText.isEnabled
|
||||||
|
|
||||||
|
plainText.addActionListener { isPlainText = plainText.isSelected }
|
||||||
|
styledText.addActionListener { isPlainText = styledText.isSelected.not() }
|
||||||
|
|
||||||
|
popupMenu.add(settingMenu)
|
||||||
|
|
||||||
popupMenu.addSeparator()
|
popupMenu.addSeparator()
|
||||||
|
|
||||||
// 打开日志浏览
|
// 打开日志浏览
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package app.termora.tlog
|
package app.termora.tlog
|
||||||
|
|
||||||
import app.termora.*
|
import app.termora.Host
|
||||||
|
import app.termora.HostTerminalTab
|
||||||
|
import app.termora.I18n
|
||||||
|
import app.termora.randomUUID
|
||||||
import app.termora.terminal.*
|
import app.termora.terminal.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
@@ -9,7 +11,6 @@ import kotlinx.coroutines.channels.onFailure
|
|||||||
import kotlinx.coroutines.channels.onSuccess
|
import kotlinx.coroutines.channels.onSuccess
|
||||||
import org.apache.commons.io.IOUtils
|
import org.apache.commons.io.IOUtils
|
||||||
import org.apache.commons.lang3.time.DateFormatUtils
|
import org.apache.commons.lang3.time.DateFormatUtils
|
||||||
import org.jdesktop.swingx.action.ActionManager
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.beans.PropertyChangeListener
|
import java.beans.PropertyChangeListener
|
||||||
import java.io.BufferedWriter
|
import java.io.BufferedWriter
|
||||||
@@ -73,7 +74,7 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onChanged(key: DataKey<*>, data: Any) {
|
override fun onChanged(key: DataKey<*>, data: Any) {
|
||||||
if (key != VisualTerminal.Written || isClosed.get()) {
|
if (isClosed.get()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,14 +83,24 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val host = this.host ?: return
|
if (key != VisualTerminal.Written && key != TextProcessor.Written) {
|
||||||
val action = ActionManager.getInstance().getAction(Actions.TERMINAL_LOGGER)
|
|
||||||
if (action !is TerminalLoggerAction || !action.isRecording) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {// 尝试记录
|
val host = this.host ?: return
|
||||||
tryRecord(data as String, host, action)
|
val action = TerminalLoggerAction.getInstance()
|
||||||
|
if (action.isRecording.not()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (action.isPlainText) {
|
||||||
|
if (key == TextProcessor.Written) {
|
||||||
|
tryRecord(data as String, host, action)
|
||||||
|
}
|
||||||
|
} else if (key == VisualTerminal.Written) {
|
||||||
|
tryRecord(data as String, host, action)
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (log.isErrorEnabled) {
|
if (log.isErrorEnabled) {
|
||||||
log.error(e.message, e)
|
log.error(e.message, e)
|
||||||
@@ -160,8 +171,8 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 移除监听
|
// 移除监听
|
||||||
ActionManager.getInstance().getAction(Actions.TERMINAL_LOGGER)
|
TerminalLoggerAction.getInstance()
|
||||||
?.removePropertyChangeListener(terminalLoggerActionPropertyChangeListener)
|
.removePropertyChangeListener(terminalLoggerActionPropertyChangeListener)
|
||||||
|
|
||||||
|
|
||||||
this.channel?.close()
|
this.channel?.close()
|
||||||
|
|||||||
@@ -261,6 +261,8 @@ termora.tabbed.tab.close-prompt=Are you sure you want to close this tab?
|
|||||||
# Terminal logger
|
# Terminal logger
|
||||||
termora.terminal-logger=Terminal Logger
|
termora.terminal-logger=Terminal Logger
|
||||||
termora.terminal-logger.start-recording=Start Recording
|
termora.terminal-logger.start-recording=Start Recording
|
||||||
|
termora.terminal-logger.plain-text=Plain text
|
||||||
|
termora.terminal-logger.styled-text=Styled text
|
||||||
termora.terminal-logger.stop-recording=Stop Recording
|
termora.terminal-logger.stop-recording=Stop Recording
|
||||||
termora.terminal-logger.open-log-viewer=Open Log Viewer
|
termora.terminal-logger.open-log-viewer=Open Log Viewer
|
||||||
termora.terminal-logger.open-in-folder=Open in {0}
|
termora.terminal-logger.open-in-folder=Open in {0}
|
||||||
|
|||||||
@@ -221,6 +221,8 @@ termora.tabbed.tab.close-prompt=Вы уверены, что хотите зак
|
|||||||
# Terminal logger
|
# Terminal logger
|
||||||
termora.terminal-logger=Журнал Терминала
|
termora.terminal-logger=Журнал Терминала
|
||||||
termora.terminal-logger.start-recording=Начать Запись
|
termora.terminal-logger.start-recording=Начать Запись
|
||||||
|
termora.terminal-logger.plain-text=Обычный текст
|
||||||
|
termora.terminal-logger.styled-text=Стилизованный текст
|
||||||
termora.terminal-logger.stop-recording=Остановить Запись
|
termora.terminal-logger.stop-recording=Остановить Запись
|
||||||
termora.terminal-logger.open-log-viewer=Открыть Журнал
|
termora.terminal-logger.open-log-viewer=Открыть Журнал
|
||||||
termora.terminal-logger.open-in-folder=Открыть в {0}
|
termora.terminal-logger.open-in-folder=Открыть в {0}
|
||||||
|
|||||||
@@ -258,6 +258,8 @@ termora.tabbed.tab.close-prompt=你确定要关闭这个标签页吗?
|
|||||||
# Terminal logger
|
# Terminal logger
|
||||||
termora.terminal-logger=终端日志
|
termora.terminal-logger=终端日志
|
||||||
termora.terminal-logger.start-recording=开始记录
|
termora.terminal-logger.start-recording=开始记录
|
||||||
|
termora.terminal-logger.plain-text=纯文本
|
||||||
|
termora.terminal-logger.styled-text=样式文本
|
||||||
termora.terminal-logger.stop-recording=停止记录
|
termora.terminal-logger.stop-recording=停止记录
|
||||||
termora.terminal-logger.open-log-viewer=打开日志浏览器
|
termora.terminal-logger.open-log-viewer=打开日志浏览器
|
||||||
termora.terminal-logger.open-in-folder=在 {0} 中打开
|
termora.terminal-logger.open-in-folder=在 {0} 中打开
|
||||||
|
|||||||
@@ -253,6 +253,8 @@ termora.tabbed.tab.close-prompt=你確定要關閉這個分頁嗎?
|
|||||||
# Terminal logger
|
# Terminal logger
|
||||||
termora.terminal-logger=終端日誌
|
termora.terminal-logger=終端日誌
|
||||||
termora.terminal-logger.start-recording=開始記錄
|
termora.terminal-logger.start-recording=開始記錄
|
||||||
|
termora.terminal-logger.plain-text=純文字
|
||||||
|
termora.terminal-logger.styled-text=樣式文本
|
||||||
termora.terminal-logger.stop-recording=停止記錄
|
termora.terminal-logger.stop-recording=停止記錄
|
||||||
termora.terminal-logger.open-log-viewer=開啟日誌瀏覽器
|
termora.terminal-logger.open-log-viewer=開啟日誌瀏覽器
|
||||||
termora.terminal-logger.open-in-folder=在 {0} 中打開
|
termora.terminal-logger.open-in-folder=在 {0} 中打開
|
||||||
|
|||||||
Reference in New Issue
Block a user