Skip to content

Commit

Permalink
feat: support snippet (#321)
Browse files Browse the repository at this point in the history
  • Loading branch information
hstyi authored Feb 27, 2025
1 parent dcc9635 commit 483a777
Show file tree
Hide file tree
Showing 43 changed files with 1,482 additions and 373 deletions.
38 changes: 23 additions & 15 deletions src/main/kotlin/app/termora/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import app.termora.highlight.KeywordHighlight
import app.termora.keymap.Keymap
import app.termora.keymgr.OhKeyPair
import app.termora.macro.Macro
import app.termora.snippet.Snippet
import app.termora.sync.SyncType
import app.termora.terminal.CursorStyle
import jetbrains.exodus.bindings.StringBinding
import jetbrains.exodus.env.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.serialization.encodeToString
import org.apache.commons.io.IOUtils
import org.apache.commons.lang3.StringUtils
import org.slf4j.LoggerFactory
Expand All @@ -26,6 +26,7 @@ class Database private constructor(private val env: Environment) : Disposable {
companion object {
private const val KEYMAP_STORE = "Keymap"
private const val HOST_STORE = "Host"
private const val SNIPPET_STORE = "Snippet"
private const val KEYWORD_HIGHLIGHT_STORE = "KeywordHighlight"
private const val MACRO_STORE = "Macro"
private const val KEY_PAIR_STORE = "KeyPair"
Expand Down Expand Up @@ -105,17 +106,6 @@ class Database private constructor(private val env: Environment) : Disposable {
}
}

fun removeAllHost() {
env.executeInTransaction { tx ->
val store = env.openStore(HOST_STORE, StoreConfig.WITHOUT_DUPLICATES_WITH_PREFIXING, tx)
store.openCursor(tx).use {
while (it.next) {
it.deleteCurrent()
}
}
}
}

fun removeAllKeyPair() {
env.executeInTransaction { tx ->
val store = env.openStore(KEY_PAIR_STORE, StoreConfig.WITHOUT_DUPLICATES_WITH_PREFIXING, tx)
Expand Down Expand Up @@ -152,15 +142,32 @@ class Database private constructor(private val env: Environment) : Disposable {
}
}

fun removeHost(id: String) {
fun addSnippet(snippet: Snippet) {
var text = ohMyJson.encodeToString(snippet)
if (doorman.isWorking()) {
text = doorman.encrypt(text)
}
env.executeInTransaction {
delete(it, HOST_STORE, id)
put(it, SNIPPET_STORE, snippet.id, text)
if (log.isDebugEnabled) {
log.debug("Removed Host: $id")
log.debug("Added Snippet: ${snippet.id} , ${snippet.name}")
}
}
}


fun getSnippets(): Collection<Snippet> {
val isWorking = doorman.isWorking()
return env.computeInTransaction { tx ->
openCursor<Snippet>(tx, SNIPPET_STORE) { _, value ->
if (isWorking)
ohMyJson.decodeFromString(doorman.decrypt(value))
else
ohMyJson.decodeFromString(value)
}.values
}
}

fun getKeywordHighlights(): Collection<KeywordHighlight> {
return env.computeInTransaction { tx ->
openCursor<KeywordHighlight>(tx, KEYWORD_HIGHLIGHT_STORE) { _, value ->
Expand Down Expand Up @@ -621,6 +628,7 @@ class Database private constructor(private val env: Environment) : Disposable {
*/
var rangeHosts by BooleanPropertyDelegate(true)
var rangeKeyPairs by BooleanPropertyDelegate(true)
var rangeSnippets by BooleanPropertyDelegate(true)
var rangeKeywordHighlights by BooleanPropertyDelegate(true)
var rangeMacros by BooleanPropertyDelegate(true)
var rangeKeymap by BooleanPropertyDelegate(true)
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/app/termora/FilterableHostTreeModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class FilterableHostTreeModel(
continue
}

if (c.host.protocol != Protocol.Folder) {
if (c.data.protocol != Protocol.Folder) {
if (filters.isNotEmpty() && filters.none { it.apply(c) }) {
continue
}
Expand Down
49 changes: 31 additions & 18 deletions src/main/kotlin/app/termora/HostTreeNode.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
package app.termora

import javax.swing.tree.DefaultMutableTreeNode
import com.formdev.flatlaf.icons.FlatTreeClosedIcon
import com.formdev.flatlaf.icons.FlatTreeOpenIcon
import javax.swing.Icon
import javax.swing.tree.TreeNode

class HostTreeNode(host: Host) : DefaultMutableTreeNode(host) {
class HostTreeNode(host: Host) : SimpleTreeNode<Host>(host) {
companion object {
private val hostManager get() = HostManager.getInstance()
}

var host: Host
get() = data
set(value) = setUserObject(value)

override val isFolder: Boolean
get() = data.protocol == Protocol.Folder

override val id: String
get() = data.id

/**
* 如果要重新赋值,记得修改 [Host.updateDate] 否则下次取出时可能时缓存的
*/
var host: Host
override var data: Host
get() {
val cacheHost = hostManager.getHost((userObject as Host).id)
val myHost = userObject as Host
Expand All @@ -22,22 +34,23 @@ class HostTreeNode(host: Host) : DefaultMutableTreeNode(host) {
}
set(value) = setUserObject(value)

val folderCount
get() = children().toList().count { if (it is HostTreeNode) it.host.protocol == Protocol.Folder else false }
override val folderCount
get() = children().toList().count { if (it is HostTreeNode) it.data.protocol == Protocol.Folder else false }

override fun getParent(): HostTreeNode? {
return super.getParent() as HostTreeNode?
}

fun getAllChildren(): List<HostTreeNode> {
val children = mutableListOf<HostTreeNode>()
for (child in children()) {
if (child is HostTreeNode) {
children.add(child)
children.addAll(child.getAllChildren())
}
override fun getAllChildren(): List<HostTreeNode> {
return super.getAllChildren().filterIsInstance<HostTreeNode>()
}

override fun getIcon(selected: Boolean, expanded: Boolean, hasFocus: Boolean): Icon {
return when (host.protocol) {
Protocol.Folder -> if (expanded) FlatTreeOpenIcon() else FlatTreeClosedIcon()
Protocol.Serial -> if (selected && hasFocus) Icons.plugin.dark else Icons.plugin
else -> if (selected && hasFocus) Icons.terminal.dark else Icons.terminal
}
return children
}

fun childrenNode(): List<HostTreeNode> {
Expand All @@ -57,15 +70,15 @@ class HostTreeNode(host: Host) : DefaultMutableTreeNode(host) {

private fun deepClone(newNode: HostTreeNode, oldNode: HostTreeNode, scopes: Set<Protocol> = emptySet()) {
for (child in oldNode.childrenNode()) {
if (scopes.isNotEmpty() && !scopes.contains(child.host.protocol)) continue
if (scopes.isNotEmpty() && !scopes.contains(child.data.protocol)) continue
val newChildNode = child.clone() as HostTreeNode
deepClone(newChildNode, child, scopes)
newNode.add(newChildNode)
}
}

override fun clone(): Any {
val newNode = HostTreeNode(host)
val newNode = HostTreeNode(data)
newNode.children = null
newNode.parent = null
return newNode
Expand All @@ -74,7 +87,7 @@ class HostTreeNode(host: Host) : DefaultMutableTreeNode(host) {
override fun isNodeChild(aNode: TreeNode?): Boolean {
if (aNode is HostTreeNode) {
for (node in childrenNode()) {
if (node.host == aNode.host) {
if (node.data == aNode.data) {
return true
}
}
Expand All @@ -88,10 +101,10 @@ class HostTreeNode(host: Host) : DefaultMutableTreeNode(host) {

other as HostTreeNode

return host == other.host
return data == other.data
}

override fun hashCode(): Int {
return host.hashCode()
return data.hashCode()
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/app/termora/Icons.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ object Icons {
val left by lazy { DynamicIcon("icons/left.svg", "icons/left_dark.svg") }
val right by lazy { DynamicIcon("icons/right.svg", "icons/right_dark.svg") }
val dotListFiles by lazy { DynamicIcon("icons/dotListFiles.svg", "icons/dotListFiles_dark.svg") }
val anyType by lazy { DynamicIcon("icons/anyType.svg", "icons/anyType_dark.svg") }
val toolWindowJsonPath by lazy { DynamicIcon("icons/toolWindowJsonPath.svg", "icons/toolWindowJsonPath_dark.svg") }
val codeSpan by lazy { DynamicIcon("icons/codeSpan.svg", "icons/codeSpan_dark.svg") }
val fileTransfer by lazy { DynamicIcon("icons/fileTransfer.svg", "icons/fileTransfer_dark.svg") }
val help by lazy { DynamicIcon("icons/help.svg", "icons/help_dark.svg") }
val applyNotConflictsLeft by lazy {
Expand Down
Loading

0 comments on commit 483a777

Please sign in to comment.