From d67de797b64a9fcad5b69bc2da56ac85c95509dd Mon Sep 17 00:00:00 2001 From: Matan Ziv-Av Date: Mon, 20 Jun 2022 16:20:09 +0300 Subject: [PATCH] Allow filtered copy to clipboard This adds three copy actions: - Copy only user input - Copy only command output - Copy both (filter out shell prompts). --- desktop/sessionui.rc | 3 ++ src/Screen.cpp | 27 ++++++++++++++++- src/session/SessionController.cpp | 40 +++++++++++++++++++++++++ src/session/SessionController.h | 3 ++ src/terminalDisplay/TerminalDisplay.cpp | 4 +-- src/terminalDisplay/TerminalDisplay.h | 2 +- 6 files changed, 75 insertions(+), 4 deletions(-) diff --git a/desktop/sessionui.rc b/desktop/sessionui.rc index 2c03d658..4679e9e2 100644 --- a/desktop/sessionui.rc +++ b/desktop/sessionui.rc @@ -49,6 +49,9 @@ + + + diff --git a/src/Screen.cpp b/src/Screen.cpp index 1e0f3bde..968e1642 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -1784,9 +1784,34 @@ int Screen::copyLineToStream(int line, count -= spacesCount; } + // Filter CharacterBuffer + Character *newBuffer; + bool todel = false; + if ((options & (ExcludePrompt | ExcludeInput | ExcludeOutput)) != 0) { + newBuffer = new Character[count]; + todel = true; + int p = 0; + for (int i = 0; i < count; i++) { + Character c = characterBuffer[spacesCount + i]; + // fprintf(stderr, "copy %i %i %i\n", i, c.character, c.flags); + if (((options & ExcludePrompt) != 0 && (c.flags & EF_REPL) == EF_REPL_PROMPT) + || ((options & ExcludeInput) != 0 && (c.flags & EF_REPL) == EF_REPL_INPUT) + || ((options & ExcludeOutput) != 0 && (c.flags & EF_REPL) == EF_REPL_OUTPUT)) { + continue; + } + newBuffer[p++] = c; + } + count = p; + } else { + newBuffer = characterBuffer + spacesCount; + } // decode line and write to text stream - decoder->decodeLine(characterBuffer + spacesCount, count, currentLineProperties); + decoder->decodeLine(newBuffer, count, currentLineProperties); + + if (todel) { + delete newBuffer; + } return count; } diff --git a/src/session/SessionController.cpp b/src/session/SessionController.cpp index c2ebd57d..1eac485f 100644 --- a/src/session/SessionController.cpp +++ b/src/session/SessionController.cpp @@ -457,6 +457,13 @@ void SessionController::updateCopyAction(const bool selectionEmpty) // copy action is meaningful only when some text is selected. copyAction->setEnabled(!selectionEmpty); copyContextMenu->setVisible(!selectionEmpty); + QAction *Action = actionCollection()->action(QStringLiteral("edit_copy_contextmenu_in")); + bool hasRepl = view() && view()->screenWindow() && view()->screenWindow()->screen() && view()->screenWindow()->screen()->hasRepl(); + Action->setVisible(!selectionEmpty && hasRepl); + Action = actionCollection()->action(QStringLiteral("edit_copy_contextmenu_out")); + Action->setVisible(!selectionEmpty && hasRepl); + Action = actionCollection()->action(QStringLiteral("edit_copy_contextmenu_in_out")); + Action->setVisible(!selectionEmpty && hasRepl); } void SessionController::updateWebSearchMenu() @@ -639,6 +646,24 @@ void SessionController::setupCommonActions() action->setVisible(false); connect(action, &QAction::triggered, this, &SessionController::copy); + action = collection->addAction(QStringLiteral("edit_copy_contextmenu_in_out")); + action->setText(i18n("Copy except propmts")); + action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); + action->setVisible(false); + connect(action, &QAction::triggered, this, &SessionController::copyInputOutput); + + action = collection->addAction(QStringLiteral("edit_copy_contextmenu_in")); + action->setText(i18n("Copy user input")); + action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); + action->setVisible(false); + connect(action, &QAction::triggered, this, &SessionController::copyInput); + + action = collection->addAction(QStringLiteral("edit_copy_contextmenu_out")); + action->setText(i18n("Copy command output")); + action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); + action->setVisible(false); + connect(action, &QAction::triggered, this, &SessionController::copyOutput); + action = KStandardAction::paste(this, &SessionController::paste, collection); QList pasteShortcut; pasteShortcut.append(QKeySequence(Konsole::ACCEL | Qt::Key_V)); @@ -1122,6 +1147,21 @@ void SessionController::copy() view()->copyToClipboard(); } +void SessionController::copyInput() +{ + view()->copyToClipboard(Screen::ExcludePrompt | Screen::ExcludeOutput); +} + +void SessionController::copyOutput() +{ + view()->copyToClipboard(Screen::ExcludePrompt | Screen::ExcludeInput); +} + +void SessionController::copyInputOutput() +{ + view()->copyToClipboard(Screen::ExcludePrompt); +} + void SessionController::paste() { view()->pasteFromClipboard(); diff --git a/src/session/SessionController.h b/src/session/SessionController.h index d7813acc..bb3ceb36 100644 --- a/src/session/SessionController.h +++ b/src/session/SessionController.h @@ -227,6 +227,9 @@ private Q_SLOTS: // menu item handlers void openBrowser(); void copy(); + void copyInput(); + void copyOutput(); + void copyInputOutput(); void paste(); void selectAll(); void selectLine(); diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp index 3586c9cc..42303fac 100644 --- a/src/terminalDisplay/TerminalDisplay.cpp +++ b/src/terminalDisplay/TerminalDisplay.cpp @@ -2267,13 +2267,13 @@ void TerminalDisplay::copyToX11Selection() } } -void TerminalDisplay::copyToClipboard() +void TerminalDisplay::copyToClipboard(Screen::DecodingOptions options) { if (_screenWindow.isNull()) { return; } - const QString &text = _screenWindow->selectedText(currentDecodingOptions()); + const QString &text = _screenWindow->selectedText(currentDecodingOptions() | options); if (text.isEmpty()) { return; } diff --git a/src/terminalDisplay/TerminalDisplay.h b/src/terminalDisplay/TerminalDisplay.h index 0f50b348..73c0251f 100644 --- a/src/terminalDisplay/TerminalDisplay.h +++ b/src/terminalDisplay/TerminalDisplay.h @@ -399,7 +399,7 @@ public Q_SLOTS: void copyToX11Selection(); /** Copies the selected text to the system clipboard. */ - void copyToClipboard(); + void copyToClipboard(Screen::DecodingOptions options = Screen::PlainText); /** * Pastes the content of the clipboard into the display.