From d8fb966c083bfa2aabd1a58cc81e0291d4235bee Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 1 Jan 2025 11:38:33 +0100 Subject: [PATCH 1/6] [contour] Adds configuration documentation for action `SwitchToPreviousTab` Signed-off-by: Christian Parpart --- src/contour/ConfigDocumentation.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/contour/ConfigDocumentation.h b/src/contour/ConfigDocumentation.h index 4a743206ac..2e36bb5d12 100644 --- a/src/contour/ConfigDocumentation.h +++ b/src/contour/ConfigDocumentation.h @@ -783,6 +783,7 @@ constexpr StringLiteral InputMappingsConfig { "{comment} - SendChars Writes given characters in `chars` member to the applications input.\n" "{comment} - SwitchToTab Switches to the tab position, given by extra parameter \"position\".\n" "{comment} The positions start at number 1.\n" + "{comment} - SwitchToPreviousTab Switches to the previously active tab.\n" "{comment} - SwitchToTabLeft Switches to the tab left of the current tab.\n" "{comment} - SwitchToTabRight Switches to the tab right of the current tab.\n" "{comment} - CreateNewTab Creates a new tab.\n" From 8cd304230111244985455a0bb3f5e9986e498dd3 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 1 Jan 2025 11:43:08 +0100 Subject: [PATCH 2/6] [contour] Terminal.qml: fix indentation Signed-off-by: Christian Parpart --- src/contour/ui.template/Terminal.qml.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/contour/ui.template/Terminal.qml.in b/src/contour/ui.template/Terminal.qml.in index c5995e1be8..15d3aebfc0 100644 --- a/src/contour/ui.template/Terminal.qml.in +++ b/src/contour/ui.template/Terminal.qml.in @@ -241,9 +241,10 @@ ContourTerminal } function delay(duration) { // In milliseconds - var timeStart = new Date().getTime(); + var timeStart = new Date().getTime(); while (new Date().getTime() - timeStart < duration) { - } + // Do nothing + } } From a5f8dd39d592c352bd98cb8422c91a1aa4a47ab0 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 1 Jan 2025 12:03:24 +0100 Subject: [PATCH 3/6] [contour] Initial work on implementing moving terminal session tabs to the left/right Signed-off-by: Christian Parpart --- metainfo.xml | 1 + src/contour/Actions.cpp | 2 ++ src/contour/Actions.h | 12 ++++++++++ src/contour/ConfigDocumentation.h | 2 ++ src/contour/TerminalSession.cpp | 18 ++++++++++++++- src/contour/TerminalSession.h | 6 ++++- src/contour/TerminalSessionManager.cpp | 32 +++++++++++++++++++++++++- src/contour/TerminalSessionManager.h | 2 ++ 8 files changed, 72 insertions(+), 3 deletions(-) diff --git a/metainfo.xml b/metainfo.xml index 99db4827d8..7d9d997dda 100644 --- a/metainfo.xml +++ b/metainfo.xml @@ -107,6 +107,7 @@
    +
  • Adds `MoveTabToLeft` and `MoveTabToRight` actions to move tabs around (#1695)
diff --git a/src/contour/Actions.cpp b/src/contour/Actions.cpp index 320403fa73..f6512e906b 100644 --- a/src/contour/Actions.cpp +++ b/src/contour/Actions.cpp @@ -81,6 +81,8 @@ optional fromString(string const& name) mapAction("WriteScreen"), mapAction("CreateNewTab"), mapAction("CloseTab"), + mapAction("MoveTabToLeft"), + mapAction("MoveTabToRight"), mapAction("SwitchToTab"), mapAction("SwitchToPreviousTab"), mapAction("SwitchToTabLeft"), diff --git a/src/contour/Actions.h b/src/contour/Actions.h index a6713cce1e..793e7879b3 100644 --- a/src/contour/Actions.h +++ b/src/contour/Actions.h @@ -81,6 +81,8 @@ struct ViNormalMode{}; struct WriteScreen{ std::string chars; }; // "\033[2J\033[3J" struct CreateNewTab{}; struct CloseTab{}; +struct MoveTabToLeft{}; +struct MoveTabToRight{}; struct SwitchToTab{ int position; }; struct SwitchToPreviousTab{}; struct SwitchToTabLeft{}; @@ -140,6 +142,8 @@ using Action = std::variant: std::formatter HANDLE_ACTION(ViNormalMode); HANDLE_ACTION(CreateNewTab); HANDLE_ACTION(CloseTab); + HANDLE_ACTION(MoveTabToLeft); + HANDLE_ACTION(MoveTabToRight); HANDLE_ACTION(SwitchToPreviousTab); HANDLE_ACTION(SwitchToTabLeft); HANDLE_ACTION(SwitchToTabRight); diff --git a/src/contour/ConfigDocumentation.h b/src/contour/ConfigDocumentation.h index 2e36bb5d12..c6e2a2a535 100644 --- a/src/contour/ConfigDocumentation.h +++ b/src/contour/ConfigDocumentation.h @@ -741,6 +741,8 @@ constexpr StringLiteral InputMappingsConfig { "position.\n" "{comment} - IncreaseFontSize Increases the font size by 1 pixel.\n" "{comment} - IncreaseOpacity Increases the default-background opacity by 5%.\n" + "{comment} - MoveTabToLeft Moves the current tab to the left.\n" + "{comment} - MoveTabToRight Moves the current tab to the right.\n" "{comment} - NewTerminal Spawns a new terminal at the current terminals current working " "directory.\n" "{comment} - NoSearchHighlight Disables current search highlighting, if anything is still " diff --git a/src/contour/TerminalSession.cpp b/src/contour/TerminalSession.cpp index b29ae8445e..f67b35d26f 100644 --- a/src/contour/TerminalSession.cpp +++ b/src/contour/TerminalSession.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -185,7 +186,10 @@ namespace } // namespace -TerminalSession::TerminalSession(unique_ptr pty, ContourGuiApp& app): +TerminalSession::TerminalSession(TerminalSessionManager* manager, + unique_ptr pty, + ContourGuiApp& app): + _manager { manager }, _id { createSessionId() }, _startTime { steady_clock::now() }, _config { app.config() }, @@ -1440,6 +1444,18 @@ bool TerminalSession::operator()(actions::CloseTab) return true; } +bool TerminalSession::operator()(actions::MoveTabToLeft) +{ + _manager->moveTabToLeft(this); + return true; +} + +bool TerminalSession::operator()(actions::MoveTabToRight) +{ + _manager->moveTabToRight(this); + return true; +} + bool TerminalSession::operator()(actions::SwitchToTab const& event) { emit switchToTab(event.position); diff --git a/src/contour/TerminalSession.h b/src/contour/TerminalSession.h index f54e0b3029..60b4601bef 100644 --- a/src/contour/TerminalSession.h +++ b/src/contour/TerminalSession.h @@ -32,6 +32,7 @@ namespace display } class ContourGuiApp; +class TerminalSessionManager; /** * A set of user-facing activities that are guarded behind a permission-check wall. @@ -215,7 +216,7 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev * @param pty a PTY object (can be process, networked, mockup, ...) * @param display fronend display to render the terminal. */ - TerminalSession(std::unique_ptr pty, ContourGuiApp& app); + TerminalSession(TerminalSessionManager* manager, std::unique_ptr pty, ContourGuiApp& app); ~TerminalSession() override; int id() const noexcept { return _id; } @@ -356,6 +357,8 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev bool operator()(actions::WriteScreen const& event); bool operator()(actions::CreateNewTab); bool operator()(actions::CloseTab); + bool operator()(actions::MoveTabToLeft); + bool operator()(actions::MoveTabToRight); bool operator()(actions::SwitchToTab const& event); bool operator()(actions::SwitchToPreviousTab); bool operator()(actions::SwitchToTabLeft); @@ -437,6 +440,7 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev // private data // + TerminalSessionManager* _manager; int _id; std::chrono::steady_clock::time_point _startTime; config::Config _config; diff --git a/src/contour/TerminalSessionManager.cpp b/src/contour/TerminalSessionManager.cpp index c427f542b6..f4c58bdbe3 100644 --- a/src/contour/TerminalSessionManager.cpp +++ b/src/contour/TerminalSessionManager.cpp @@ -76,7 +76,7 @@ TerminalSession* TerminalSessionManager::createSessionInBackground() } #endif - auto* session = new TerminalSession(createPty(ptyPath), _app); + auto* session = new TerminalSession(this, createPty(ptyPath), _app); managerLog()("Create new session with ID {} at index {}", session->id(), _sessions.size()); _sessions.push_back(session); @@ -216,6 +216,36 @@ void TerminalSessionManager::closeTab() removeSession(*_activeSession); } +void TerminalSessionManager::moveTabToLeft(TerminalSession* session) +{ + auto const maybeIndex = getSessionIndexOf(session); + if (!maybeIndex) + return; + + auto const index = maybeIndex.value(); + + if (index > 0) + { + std::swap(_sessions[index], _sessions[index - 1]); + updateStatusLine(); + } +} + +void TerminalSessionManager::moveTabToRight(TerminalSession* session) +{ + auto const maybeIndex = getSessionIndexOf(session); + if (!maybeIndex) + return; + + auto const index = maybeIndex.value(); + + if (index + 1 < _sessions.size()) + { + std::swap(_sessions[index], _sessions[index + 1]); + updateStatusLine(); + } +} + void TerminalSessionManager::removeSession(TerminalSession& thatSession) { managerLog()("REMOVE SESSION: session: {}, _sessions.size(): {}", (void*) &thatSession, _sessions.size()); diff --git a/src/contour/TerminalSessionManager.h b/src/contour/TerminalSessionManager.h index 288e325b0c..b7c37e77a2 100644 --- a/src/contour/TerminalSessionManager.h +++ b/src/contour/TerminalSessionManager.h @@ -38,6 +38,8 @@ class TerminalSessionManager: public QAbstractListModel Q_INVOKABLE void switchToTabRight(); Q_INVOKABLE void switchToTab(int position); Q_INVOKABLE void closeTab(); + Q_INVOKABLE void moveTabToLeft(TerminalSession* session); + Q_INVOKABLE void moveTabToRight(TerminalSession* session); void setSession(size_t index); From 9f3ec38ee8e2d02f394d6bd2c93e93a36b7f53c6 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 1 Jan 2025 21:05:04 +0100 Subject: [PATCH 4/6] [contour] Ensure inserting happens right next to the currently active tab Signed-off-by: Christian Parpart --- metainfo.xml | 2 ++ src/contour/TerminalSession.cpp | 2 +- src/contour/TerminalSessionManager.cpp | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/metainfo.xml b/metainfo.xml index 7d9d997dda..3d2119e609 100644 --- a/metainfo.xml +++ b/metainfo.xml @@ -107,7 +107,9 @@
    +
  • Fixes `CreateTab` to sometimes spawn more than one tab (#1695)
  • Adds `MoveTabToLeft` and `MoveTabToRight` actions to move tabs around (#1695)
  • +
  • Ensure inserting new tabs happens right next to the currently active tab (#1695)
diff --git a/src/contour/TerminalSession.cpp b/src/contour/TerminalSession.cpp index f67b35d26f..9a028bcdea 100644 --- a/src/contour/TerminalSession.cpp +++ b/src/contour/TerminalSession.cpp @@ -1434,7 +1434,7 @@ bool TerminalSession::operator()(actions::WriteScreen const& event) bool TerminalSession::operator()(actions::CreateNewTab) { - emit createNewTab(); + _manager->createSession(); return true; } diff --git a/src/contour/TerminalSessionManager.cpp b/src/contour/TerminalSessionManager.cpp index f4c58bdbe3..6ab1fa1079 100644 --- a/src/contour/TerminalSessionManager.cpp +++ b/src/contour/TerminalSessionManager.cpp @@ -79,7 +79,11 @@ TerminalSession* TerminalSessionManager::createSessionInBackground() auto* session = new TerminalSession(this, createPty(ptyPath), _app); managerLog()("Create new session with ID {} at index {}", session->id(), _sessions.size()); - _sessions.push_back(session); + auto const currentSessionIterator = std::ranges::find(_sessions, _activeSession); + auto const insertPoint = currentSessionIterator != _sessions.end() ? std::next(currentSessionIterator) + : currentSessionIterator; + + _sessions.insert(insertPoint, session); connect(session, &TerminalSession::sessionClosed, [this, session]() { removeSession(*session); }); From def62b32c1ab31100930492138faaa2bc5894086 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 1 Jan 2025 21:48:36 +0100 Subject: [PATCH 5/6] Adds `MoveTabTo` action to move tabs to a specific position (#1695) Signed-off-by: Christian Parpart --- metainfo.xml | 1 + src/contour/Actions.cpp | 1 + src/contour/Actions.h | 20 ++++++++++++++++++++ src/contour/Config.cpp | 8 ++++++++ src/contour/TerminalSession.cpp | 6 ++++++ src/contour/TerminalSession.h | 1 + src/contour/TerminalSessionManager.cpp | 15 +++++++++++++++ src/contour/TerminalSessionManager.h | 1 + 8 files changed, 53 insertions(+) diff --git a/metainfo.xml b/metainfo.xml index 3d2119e609..e4d6b91136 100644 --- a/metainfo.xml +++ b/metainfo.xml @@ -109,6 +109,7 @@
  • Fixes `CreateTab` to sometimes spawn more than one tab (#1695)
  • Adds `MoveTabToLeft` and `MoveTabToRight` actions to move tabs around (#1695)
  • +
  • Adds `MoveTabTo` action to move tabs to a specific position (#1695)
  • Ensure inserting new tabs happens right next to the currently active tab (#1695)
diff --git a/src/contour/Actions.cpp b/src/contour/Actions.cpp index f6512e906b..7fb44a673e 100644 --- a/src/contour/Actions.cpp +++ b/src/contour/Actions.cpp @@ -81,6 +81,7 @@ optional fromString(string const& name) mapAction("WriteScreen"), mapAction("CreateNewTab"), mapAction("CloseTab"), + mapAction("MoveTabTo"), mapAction("MoveTabToLeft"), mapAction("MoveTabToRight"), mapAction("SwitchToTab"), diff --git a/src/contour/Actions.h b/src/contour/Actions.h index 793e7879b3..14ccf1c397 100644 --- a/src/contour/Actions.h +++ b/src/contour/Actions.h @@ -81,6 +81,7 @@ struct ViNormalMode{}; struct WriteScreen{ std::string chars; }; // "\033[2J\033[3J" struct CreateNewTab{}; struct CloseTab{}; +struct MoveTabTo{ int position; }; struct MoveTabToLeft{}; struct MoveTabToRight{}; struct SwitchToTab{ int position; }; @@ -142,6 +143,7 @@ using Action = std::variant +struct std::formatter: std::formatter +{ + auto format(contour::actions::MoveTabTo const& value, auto& ctx) const + { + return formatter::format(std::format("MoveTabTo {{ position: {} }}", value.position), ctx); + } +}; + template <> struct std::formatter: std::formatter { @@ -491,6 +506,11 @@ struct std::formatter: std::formatter HANDLE_ACTION(SwitchToPreviousTab); HANDLE_ACTION(SwitchToTabLeft); HANDLE_ACTION(SwitchToTabRight); + if (std::holds_alternative(_action)) + { + const auto action = std::get(_action); + name = std::format("MoveTabTo, position: {}", action.position); + } if (std::holds_alternative(_action)) { const auto action = std::get(_action); diff --git a/src/contour/Config.cpp b/src/contour/Config.cpp index 515572d7f8..bd117276df 100644 --- a/src/contour/Config.cpp +++ b/src/contour/Config.cpp @@ -1827,6 +1827,14 @@ std::optional YAMLConfigReader::parseAction(YAML::Node const& n return std::nullopt; } + if (holds_alternative(action)) + { + if (auto position = node["position"]; position.IsScalar()) + return actions::MoveTabTo { position.as() }; + else + return std::nullopt; + } + if (holds_alternative(action)) { if (auto position = node["position"]; position.IsScalar()) diff --git a/src/contour/TerminalSession.cpp b/src/contour/TerminalSession.cpp index 9a028bcdea..27de7de8c0 100644 --- a/src/contour/TerminalSession.cpp +++ b/src/contour/TerminalSession.cpp @@ -1444,6 +1444,12 @@ bool TerminalSession::operator()(actions::CloseTab) return true; } +bool TerminalSession::operator()(actions::MoveTabTo event) +{ + _manager->moveTabTo(event.position); + return true; +} + bool TerminalSession::operator()(actions::MoveTabToLeft) { _manager->moveTabToLeft(this); diff --git a/src/contour/TerminalSession.h b/src/contour/TerminalSession.h index 60b4601bef..ddc808a5fd 100644 --- a/src/contour/TerminalSession.h +++ b/src/contour/TerminalSession.h @@ -357,6 +357,7 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev bool operator()(actions::WriteScreen const& event); bool operator()(actions::CreateNewTab); bool operator()(actions::CloseTab); + bool operator()(actions::MoveTabTo); bool operator()(actions::MoveTabToLeft); bool operator()(actions::MoveTabToRight); bool operator()(actions::SwitchToTab const& event); diff --git a/src/contour/TerminalSessionManager.cpp b/src/contour/TerminalSessionManager.cpp index 6ab1fa1079..88988927a4 100644 --- a/src/contour/TerminalSessionManager.cpp +++ b/src/contour/TerminalSessionManager.cpp @@ -220,6 +220,21 @@ void TerminalSessionManager::closeTab() removeSession(*_activeSession); } +void TerminalSessionManager::moveTabTo(int position) +{ + auto const currentIndexOpt = getSessionIndexOf(_activeSession); + if (!currentIndexOpt) + return; + + if (position < 1 || position > static_cast(_sessions.size())) + return; + + auto const index = static_cast(position - 1); + + std::swap(_sessions[currentIndexOpt.value()], _sessions[index]); + updateStatusLine(); +} + void TerminalSessionManager::moveTabToLeft(TerminalSession* session) { auto const maybeIndex = getSessionIndexOf(session); diff --git a/src/contour/TerminalSessionManager.h b/src/contour/TerminalSessionManager.h index b7c37e77a2..42c690d563 100644 --- a/src/contour/TerminalSessionManager.h +++ b/src/contour/TerminalSessionManager.h @@ -38,6 +38,7 @@ class TerminalSessionManager: public QAbstractListModel Q_INVOKABLE void switchToTabRight(); Q_INVOKABLE void switchToTab(int position); Q_INVOKABLE void closeTab(); + Q_INVOKABLE void moveTabTo(int position); Q_INVOKABLE void moveTabToLeft(TerminalSession* session); Q_INVOKABLE void moveTabToRight(TerminalSession* session); From 8f56df6faea2cce7f4283d67c2cadb44cbfddcc5 Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Wed, 1 Jan 2025 22:03:40 +0100 Subject: [PATCH 6/6] [contour] TerminalSessionManager: Don't crash when switching to previous tab when only one tab is present :) Signed-off-by: Christian Parpart --- src/contour/TerminalSessionManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/contour/TerminalSessionManager.cpp b/src/contour/TerminalSessionManager.cpp index 88988927a4..7a5c92aaaf 100644 --- a/src/contour/TerminalSessionManager.cpp +++ b/src/contour/TerminalSessionManager.cpp @@ -112,6 +112,9 @@ void TerminalSessionManager::setSession(size_t index) TerminalSession* TerminalSessionManager::activateSession(TerminalSession* session, bool isNewSession) { + if (!session) + return nullptr; + managerLog()( "Activating session ID {} at index {}", session->id(), getSessionIndexOf(session).value_or(-1));