diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/MuxService.qml')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/MuxService.qml | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/MuxService.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/MuxService.qml new file mode 100644 index 0000000..c2f941c --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/MuxService.qml @@ -0,0 +1,230 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Common + +Singleton { + id: root + + property var sessions: [] + property bool loading: false + + property bool tmuxAvailable: false + property bool zellijAvailable: false + readonly property bool currentMuxAvailable: muxType === "zellij" ? zellijAvailable : tmuxAvailable + + readonly property string muxType: SettingsData.muxType + readonly property string displayName: muxType === "zellij" ? "Zellij" : "Tmux" + + readonly property var terminalFlags: ({ + "ghostty": ["-e"], + "kitty": ["-e"], + "alacritty": ["-e"], + "foot": [], + "wezterm": ["start", "--"], + "gnome-terminal": ["--"], + "xterm": ["-e"], + "konsole": ["-e"], + "st": ["-e"], + "terminator": ["-e"], + "xfce4-terminal": ["-e"] + }) + + function getTerminalFlag(terminal) { + return terminalFlags[terminal] ?? ["-e"] + } + + readonly property string terminal: Quickshell.env("TERMINAL") || "ghostty" + + function _terminalPrefix() { + return [terminal].concat(getTerminalFlag(terminal)) + } + + Process { + id: tmuxCheckProcess + command: ["which", "tmux"] + running: false + onExited: (code) => { root.tmuxAvailable = (code === 0) } + } + + Process { + id: zellijCheckProcess + command: ["which", "zellij"] + running: false + onExited: (code) => { root.zellijAvailable = (code === 0) } + } + + function checkAvailability() { + tmuxCheckProcess.running = true + zellijCheckProcess.running = true + } + + Component.onCompleted: checkAvailability() + + Process { + id: listProcess + running: false + + stdout: StdioCollector { + onStreamFinished: { + try { + if (root.muxType === "zellij") + root._parseZellijSessions(text) + else + root._parseTmuxSessions(text) + } catch (e) { + console.error("[MuxService] Error parsing sessions:", e) + root.sessions = [] + } + root.loading = false + } + } + + stderr: SplitParser { + onRead: (line) => { + if (line.trim()) + console.error("[MuxService] stderr:", line) + } + } + + onExited: (code) => { + if (code !== 0 && code !== 1) { + console.warn("[MuxService] Process exited with code:", code) + root.sessions = [] + } + root.loading = false + } + } + + function refreshSessions() { + if (!root.currentMuxAvailable) { + root.sessions = [] + return + } + + root.loading = true + + if (listProcess.running) + listProcess.running = false + + if (root.muxType === "zellij") + listProcess.command = ["zellij", "list-sessions", "--no-formatting"] + else + listProcess.command = ["tmux", "list-sessions", "-F", "#{session_name}|#{session_windows}|#{session_attached}"] + + Qt.callLater(function () { + listProcess.running = true + }) + } + + function _isSessionExcluded(name) { + var filter = SettingsData.muxSessionFilter.trim() + if (filter.length === 0) + return false + var parts = filter.split(",") + for (var i = 0; i < parts.length; i++) { + var pattern = parts[i].trim() + if (pattern.length === 0) + continue + if (pattern.startsWith("/") && pattern.endsWith("/") && pattern.length > 2) { + try { + var re = new RegExp(pattern.slice(1, -1)) + if (re.test(name)) + return true + } catch (e) {} + } else { + if (name.toLowerCase() === pattern.toLowerCase()) + return true + } + } + return false + } + + function _parseTmuxSessions(output) { + var sessionList = [] + var lines = output.trim().split('\n') + + for (var i = 0; i < lines.length; i++) { + var line = lines[i].trim() + if (line.length === 0) + continue + + var parts = line.split('|') + if (parts.length >= 3 && !_isSessionExcluded(parts[0])) { + sessionList.push({ + name: parts[0], + windows: parts[1], + attached: parts[2] === "1" + }) + } + } + + root.sessions = sessionList + } + + function _parseZellijSessions(output) { + var sessionList = [] + var lines = output.trim().split('\n') + + for (var i = 0; i < lines.length; i++) { + var line = lines[i].trim() + if (line.length === 0) + continue + + var exited = line.includes("(EXITED") + var bracketIdx = line.indexOf(" [") + var name = (bracketIdx > 0 ? line.substring(0, bracketIdx) : line).trim() + + if (!_isSessionExcluded(name)) { + sessionList.push({ + name: name, + windows: "N/A", + attached: !exited + }) + } + } + + root.sessions = sessionList + } + + function attachToSession(name) { + if (SettingsData.muxUseCustomCommand && SettingsData.muxCustomCommand) { + Quickshell.execDetached([SettingsData.muxCustomCommand, name]) + } else if (root.muxType === "zellij") { + Quickshell.execDetached(_terminalPrefix().concat(["zellij", "attach", name])) + } else { + Quickshell.execDetached(_terminalPrefix().concat(["tmux", "attach", "-t", name])) + } + } + + function createSession(name) { + if (SettingsData.muxUseCustomCommand && SettingsData.muxCustomCommand) { + Quickshell.execDetached([SettingsData.muxCustomCommand, name]) + } else if (root.muxType === "zellij") { + Quickshell.execDetached(_terminalPrefix().concat(["zellij", "-s", name])) + } else { + Quickshell.execDetached(_terminalPrefix().concat(["tmux", "new-session", "-s", name])) + } + } + + readonly property bool supportsRename: muxType !== "zellij" + + function renameSession(oldName, newName) { + if (root.muxType === "zellij") + return + Quickshell.execDetached(["tmux", "rename-session", "-t", oldName, newName]) + Qt.callLater(refreshSessions) + } + + function killSession(name) { + if (root.muxType === "zellij") { + Quickshell.execDetached(["zellij", "kill-session", name]) + } else { + Quickshell.execDetached(["tmux", "kill-session", "-t", name]) + } + Qt.callLater(refreshSessions) + } +} |