From 89b22ba984e32ee84f5c8d01cdddd8c42d59ba66 Mon Sep 17 00:00:00 2001 From: hstyi Date: Mon, 14 Jul 2025 16:36:15 +0800 Subject: [PATCH] feat: support modifying log format --- gradle/libs.versions.toml | 2 +- .../kotlin/app/termora/MyTermoraToolbar.kt | 1 + .../app/termora/actions/ActionManager.kt | 2 +- .../app/termora/terminal/TextProcessor.kt | 10 ++++- .../app/termora/tlog/LogViewerTerminal.kt | 3 ++ .../app/termora/tlog/TerminalLoggerAction.kt | 37 +++++++++++++++++-- .../tlog/TerminalLoggerDataListener.kt | 33 +++++++++++------ src/main/resources/i18n/messages.properties | 2 + .../resources/i18n/messages_ru_RU.properties | 2 + .../resources/i18n/messages_zh_CN.properties | 2 + .../resources/i18n/messages_zh_TW.properties | 2 + 11 files changed, 77 insertions(+), 19 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1807bfe..4a501e1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ slf4j = "2.0.17" pty4j = "0.13.6" tinylog = "2.7.0" kotlinx-coroutines = "1.10.2" -flatlaf = "3.6.1-SNAPSHOT" +flatlaf = "3.6.1" kotlinx-serialization-json = "1.9.0" commons-codec = "1.18.0" commons-lang3 = "3.18.0" diff --git a/src/main/kotlin/app/termora/MyTermoraToolbar.kt b/src/main/kotlin/app/termora/MyTermoraToolbar.kt index 6aeb444..beead1d 100644 --- a/src/main/kotlin/app/termora/MyTermoraToolbar.kt +++ b/src/main/kotlin/app/termora/MyTermoraToolbar.kt @@ -166,6 +166,7 @@ internal class MyTermoraToolbar(private val windowScope: WindowScope, private va if (action is StateAction) { button.isSelected = action.isSelected(windowScope) } + button.icon = action.getValue(Action.SMALL_ICON) as? Icon } override fun dispose() { diff --git a/src/main/kotlin/app/termora/actions/ActionManager.kt b/src/main/kotlin/app/termora/actions/ActionManager.kt index 9c72e4a..f0f7125 100644 --- a/src/main/kotlin/app/termora/actions/ActionManager.kt +++ b/src/main/kotlin/app/termora/actions/ActionManager.kt @@ -31,7 +31,7 @@ class ActionManager : org.jdesktop.swingx.action.ActionManager() { addAction(QuickConnectAction.QUICK_CONNECT, QuickConnectAction.instance) addAction(Actions.KEYWORD_HIGHLIGHT, KeywordHighlightAction()) - addAction(Actions.TERMINAL_LOGGER, TerminalLoggerAction()) + addAction(Actions.TERMINAL_LOGGER, TerminalLoggerAction.getInstance()) addAction(Actions.SFTP, TransferAnAction()) addAction(SFTPCommandAction.SFTP_COMMAND, SFTPCommandAction()) addAction(MultipleAction.MULTIPLE, MultipleAction.getInstance()) diff --git a/src/main/kotlin/app/termora/terminal/TextProcessor.kt b/src/main/kotlin/app/termora/terminal/TextProcessor.kt index 02252b8..87abda9 100644 --- a/src/main/kotlin/app/termora/terminal/TextProcessor.kt +++ b/src/main/kotlin/app/termora/terminal/TextProcessor.kt @@ -1,6 +1,10 @@ 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 terminals = setOf( 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() { - terminal.getDocument().write(sb.toString()) + val text = sb.toString() + terminal.getDocument().write(text) + terminal.getTerminalModel().setData(Written, text) sb.clear() } } \ No newline at end of file diff --git a/src/main/kotlin/app/termora/tlog/LogViewerTerminal.kt b/src/main/kotlin/app/termora/tlog/LogViewerTerminal.kt index 163eb36..bd7bb02 100644 --- a/src/main/kotlin/app/termora/tlog/LogViewerTerminal.kt +++ b/src/main/kotlin/app/termora/tlog/LogViewerTerminal.kt @@ -2,6 +2,7 @@ package app.termora.tlog import app.termora.TerminalFactory import app.termora.terminal.* +import app.termora.terminal.panel.TerminalPanel import org.slf4j.LoggerFactory class LogViewerTerminal : TerminalFactory.MyVisualTerminal() { @@ -50,6 +51,8 @@ class LogViewerTerminal : TerminalFactory.MyVisualTerminal() { override fun getData(key: DataKey, defaultValue: T): T { if (key == DataKey.ShowCursor) { return false as T + } else if (key == TerminalPanel.FocusMode) { + return false as T } return super.getData(key, defaultValue) } diff --git a/src/main/kotlin/app/termora/tlog/TerminalLoggerAction.kt b/src/main/kotlin/app/termora/tlog/TerminalLoggerAction.kt index f62265a..4a61a0e 100644 --- a/src/main/kotlin/app/termora/tlog/TerminalLoggerAction.kt +++ b/src/main/kotlin/app/termora/tlog/TerminalLoggerAction.kt @@ -7,14 +7,24 @@ import app.termora.database.DatabaseManager import com.formdev.flatlaf.extras.components.FlatPopupMenu import com.formdev.flatlaf.util.SystemInfo import org.apache.commons.io.FileUtils +import org.slf4j.LoggerFactory import java.awt.Window import java.io.File import java.time.LocalDate -import javax.swing.JComponent -import javax.swing.JFileChooser -import javax.swing.SwingUtilities +import javax.swing.* + +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 /** @@ -28,6 +38,12 @@ class TerminalLoggerAction : AnAction(I18n.getString("termora.terminal-logger"), 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 { 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() // 打开日志浏览 diff --git a/src/main/kotlin/app/termora/tlog/TerminalLoggerDataListener.kt b/src/main/kotlin/app/termora/tlog/TerminalLoggerDataListener.kt index df0335a..ed2b008 100644 --- a/src/main/kotlin/app/termora/tlog/TerminalLoggerDataListener.kt +++ b/src/main/kotlin/app/termora/tlog/TerminalLoggerDataListener.kt @@ -1,7 +1,9 @@ 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 kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel @@ -9,7 +11,6 @@ import kotlinx.coroutines.channels.onFailure import kotlinx.coroutines.channels.onSuccess import org.apache.commons.io.IOUtils import org.apache.commons.lang3.time.DateFormatUtils -import org.jdesktop.swingx.action.ActionManager import org.slf4j.LoggerFactory import java.beans.PropertyChangeListener import java.io.BufferedWriter @@ -73,7 +74,7 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener } override fun onChanged(key: DataKey<*>, data: Any) { - if (key != VisualTerminal.Written || isClosed.get()) { + if (isClosed.get()) { return } @@ -82,14 +83,24 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener return } - val host = this.host ?: return - val action = ActionManager.getInstance().getAction(Actions.TERMINAL_LOGGER) - if (action !is TerminalLoggerAction || !action.isRecording) { + if (key != VisualTerminal.Written && key != TextProcessor.Written) { return } - try {// 尝试记录 - tryRecord(data as String, host, action) + val host = this.host ?: return + 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) { if (log.isErrorEnabled) { log.error(e.message, e) @@ -160,8 +171,8 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener } // 移除监听 - ActionManager.getInstance().getAction(Actions.TERMINAL_LOGGER) - ?.removePropertyChangeListener(terminalLoggerActionPropertyChangeListener) + TerminalLoggerAction.getInstance() + .removePropertyChangeListener(terminalLoggerActionPropertyChangeListener) this.channel?.close() diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index bb82afb..c3f8f0c 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -261,6 +261,8 @@ termora.tabbed.tab.close-prompt=Are you sure you want to close this tab? # Terminal logger termora.terminal-logger=Terminal Logger 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.open-log-viewer=Open Log Viewer termora.terminal-logger.open-in-folder=Open in {0} diff --git a/src/main/resources/i18n/messages_ru_RU.properties b/src/main/resources/i18n/messages_ru_RU.properties index 472895f..7d0ff74 100644 --- a/src/main/resources/i18n/messages_ru_RU.properties +++ b/src/main/resources/i18n/messages_ru_RU.properties @@ -221,6 +221,8 @@ termora.tabbed.tab.close-prompt=Вы уверены, что хотите зак # Terminal logger termora.terminal-logger=Журнал Терминала termora.terminal-logger.start-recording=Начать Запись +termora.terminal-logger.plain-text=Обычный текст +termora.terminal-logger.styled-text=Стилизованный текст termora.terminal-logger.stop-recording=Остановить Запись termora.terminal-logger.open-log-viewer=Открыть Журнал termora.terminal-logger.open-in-folder=Открыть в {0} diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties index 779765f..25fc040 100644 --- a/src/main/resources/i18n/messages_zh_CN.properties +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -258,6 +258,8 @@ termora.tabbed.tab.close-prompt=你确定要关闭这个标签页吗? # Terminal logger termora.terminal-logger=终端日志 termora.terminal-logger.start-recording=开始记录 +termora.terminal-logger.plain-text=纯文本 +termora.terminal-logger.styled-text=样式文本 termora.terminal-logger.stop-recording=停止记录 termora.terminal-logger.open-log-viewer=打开日志浏览器 termora.terminal-logger.open-in-folder=在 {0} 中打开 diff --git a/src/main/resources/i18n/messages_zh_TW.properties b/src/main/resources/i18n/messages_zh_TW.properties index 6698c04..54a60b0 100644 --- a/src/main/resources/i18n/messages_zh_TW.properties +++ b/src/main/resources/i18n/messages_zh_TW.properties @@ -253,6 +253,8 @@ termora.tabbed.tab.close-prompt=你確定要關閉這個分頁嗎? # Terminal logger termora.terminal-logger=終端日誌 termora.terminal-logger.start-recording=開始記錄 +termora.terminal-logger.plain-text=純文字 +termora.terminal-logger.styled-text=樣式文本 termora.terminal-logger.stop-recording=停止記錄 termora.terminal-logger.open-log-viewer=開啟日誌瀏覽器 termora.terminal-logger.open-in-folder=在 {0} 中打開