Is it possible to set up Konsole so that CTRL-C functions as copy when text is selected and as interrupt when no text is selected?
if you don’t want to use the clipboard then simply highlighting text loads it into the paste buffer, and you can paste it with the middle mouse button.
i’ve setup copy and paste to be just F4 and F5, respectively and don’t use ctrl-c at all in konsole.
i have the same clipboard options in kate.
Standard shortcuts is CTRL+SHIFT+C, i.e. the normal GUI shortcut with additional SHIFT modifier.
Which for paste incidentally is the same as “paste without formatting” in GUI apps, so that fits nicely in a terminal
I wanted to see if I could make the behaviour exactly the same as a cmd prompt in Windows, but sounds like it isn’t possible (at least for copy).
There are several terminal apps around, maybe some other implements this
I decided to use CTRL-PAUSE (ie. break) for interrupt. My ~/.local/share/kxmlgui5/konsole/sessionui.rc has these shortcuts:
<ActionProperties scheme="Default">
<Action name="sigint-signal" shortcut="Ctrl+Pause; Ctrl+Shift+C"/>
<Action name="edit_paste" shortcut="Ctrl+V; Shift+Ins"/>
<Action name="edit_copy" shortcut="Ctrl+C"/>
</ActionProperties>
I took a different root to a solution.
I use intr = ^Y; lnext = ^B then configure konsole to use ^C for copy and ^V for paste.
Historic detail: Ctrl-Y was the interrupt key for DEC’s VAX.
I just vibecoded the following patch to Konsole. With it, create a new profile and tick the new option in the Mouse section. Then, rebind CTRL+C to copy and CTRL+V to paste.
diff --git a/src/profile/Profile.cpp b/src/profile/Profile.cpp
index df80c84d9..916c1ed69 100644
--- a/src/profile/Profile.cpp
+++ b/src/profile/Profile.cpp
@@ -173,6 +173,7 @@ const std::vector<Profile::PropertyInfo> Profile::DefaultProperties = {
{AllowEscapedLinks, "AllowEscapedLinks", INTERACTION_GROUP, false},
{EscapedLinksSchema, "EscapedLinksSchema", INTERACTION_GROUP, QLatin1String("http://;https://;file://")},
{ColorFilterEnabled, "ColorFilterEnabled", INTERACTION_GROUP, true},
+ {InterruptIfNothingSelected, "InterruptIfNothingSelected", INTERACTION_GROUP, false},
// Encoding
{DefaultEncoding, "DefaultEncoding", ENCODING_GROUP, DEFAULT_ENCODING},
diff --git a/src/profile/Profile.h b/src/profile/Profile.h
index d89a262b5..f5d8b577a 100644
--- a/src/profile/Profile.h
+++ b/src/profile/Profile.h
@@ -430,6 +430,9 @@ public:
/** (int) Milliseconds interval between autosave activations
*/
AutoSaveInterval,
+ /** (bool) If true, send an interrupt signal when copy shortcut is used with no selection
+ */
+ InterruptIfNothingSelected,
};
Q_ENUM(Property)
@@ -796,6 +799,11 @@ public:
return property<bool>(Profile::AutoCopySelectedText);
}
+ bool interruptIfNothingSelected() const
+ {
+ return property<bool>(Profile::InterruptIfNothingSelected);
+ }
+
/** Convenience method for property<QString>(Profile::DefaultEncoding) */
QString defaultEncoding() const
{
diff --git a/src/session/SessionController.cpp b/src/session/SessionController.cpp
index dba344fd1..4e9688199 100644
--- a/src/session/SessionController.cpp
+++ b/src/session/SessionController.cpp
@@ -130,6 +130,7 @@ SessionController::SessionController(Session *sessionParam, TerminalDisplay *vie
, _monitorProcessFinish(false)
, _monitorOnce(false)
, _escapedUrlFilter(nullptr)
+ , _interruptIfNothingSelected(false)
{
Q_ASSERT(sessionParam);
Q_ASSERT(viewParam);
@@ -473,9 +474,12 @@ void SessionController::updateCopyAction(const bool selectionEmpty)
{
QAction *copyAction = actionCollection()->action(QStringLiteral("edit_copy"));
QAction *copyContextMenu = actionCollection()->action(QStringLiteral("edit_copy_contextmenu"));
- // copy action is meaningful only when some text is selected.
+
+ // copy action is meaningful only when some text is selected;
+ // or if the profile is configured to send interrupt on copy with no selection.
bool hasRepl = view() && view()->screenWindow() && view()->screenWindow()->screen() && view()->screenWindow()->screen()->hasRepl();
- copyAction->setEnabled(!selectionEmpty);
+ copyAction->setEnabled(_interruptIfNothingSelected || !selectionEmpty);
+
copyContextMenu->setVisible(!selectionEmpty || hasRepl);
QAction *Action = actionCollection()->action(QStringLiteral("edit_copy_contextmenu_in"));
Action->setVisible(!selectionEmpty && hasRepl);
@@ -1233,6 +1237,10 @@ void SessionController::openBrowser()
void SessionController::copy()
{
+ if (_selectionEmpty && _interruptIfNothingSelected) {
+ session()->sendTextToTerminal(QChar(0x03), QChar());
+ return;
+ }
view()->copyToClipboard();
}
@@ -1496,6 +1504,9 @@ void SessionController::updateFilterList(const Profile::Ptr &profile)
_colorFilter = new ColorFilter();
filterChain->addFilter(_colorFilter);
}
+
+ _interruptIfNothingSelected = profile->interruptIfNothingSelected();
+ updateCopyAction(_selectionEmpty);
}
void SessionController::setSearchStartToWindowCurrentLine()
diff --git a/src/session/SessionController.h b/src/session/SessionController.h
index 09b23e3d8..3024040f1 100644
--- a/src/session/SessionController.h
+++ b/src/session/SessionController.h
@@ -415,6 +415,7 @@ private:
bool _monitorProcessFinish;
bool _monitorOnce;
EscapeSequenceUrlFilter *_escapedUrlFilter;
+ bool _interruptIfNothingSelected;
std::unique_ptr<KXMLGUIBuilder> _clientBuilder;
diff --git a/src/widgets/EditProfileMousePage.ui b/src/widgets/EditProfileMousePage.ui
index 5d13a3a40..474c2c6c8 100644
--- a/src/widgets/EditProfileMousePage.ui
+++ b/src/widgets/EditProfileMousePage.ui
@@ -230,6 +230,16 @@
</property>
</widget>
</item>
+ <item row="12" column="1">
+ <widget class="QCheckBox" name="interruptIfNothingSelectedButton">
+ <property name="toolTip">
+ <string>Send a SIGINT signal if copy is triggered while nothing is selected.</string>
+ </property>
+ <property name="text">
+ <string>Interrupt if nothing selected</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
(included the whole patch because I can’t link to my github fork)