From d18995e91f00d0137c74176c2dda2738f8ebb875 Mon Sep 17 00:00:00 2001
From: Sigurd Tullander
Date: Thu, 17 Aug 2023 12:01:26 +0200
Subject: [PATCH] Re-implement smart copy from #3873
---
.github/workflows/upload_asset.sh | 2 +-
README.md | 34 +++++++++++++++++++++++++++++++
alacritty/src/config/bindings.rs | 5 +++++
alacritty/src/input/keyboard.rs | 5 +++++
alacritty/src/input/mod.rs | 6 ++++++
5 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/upload_asset.sh b/.github/workflows/upload_asset.sh
index 9e1f40e5684..15c2c5001e6 100755
--- a/.github/workflows/upload_asset.sh
+++ b/.github/workflows/upload_asset.sh
@@ -6,7 +6,7 @@ if [ $# -lt 2 ]; then
exit 1
fi
-repo="alacritty/alacritty"
+repo="sigurdo/alacritty-smart-copy"
file_path=$1
bearer=$2
diff --git a/README.md b/README.md
index af678ff8868..6dec30f9b73 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,40 @@
src="extra/promo/alacritty-readme.png">
+## About this fork
+
+This fork of Alacritty lets you copy and paste with `ctrl+c` and `ctrl+v`, like in most modern Windows and Linux software. If no text is selected, `ctrl+c` sends `SIGINT` like usual. The selection is cleared when you copy with `ctrl+c`. In this way, pressing `ctrl+c` twice will always send minimum one `SIGINT`. Copying without clearing the selection can still be achieved with `ctrl+shift+c`.
+
+Precompiled binaries are available from the [GitHub releases page](https://github.com/sigurdo/alacritty-smart-copy/releases).
+
+On the technical side, a `CopyDynamic` action is added. It copies the selected text and clears the selection. When no text is selected, the keystroke is passed through, thus causing a `SIGINT`.
+
+"Smart copy" was first propsed and rejected already [back in 2018](https://github.com/alacritty/alacritty/issues/1919) for reasons I do not agree with. In 2020, dtheodor provided a [fantastic explanation](https://github.com/alacritty/alacritty/issues/1919#issuecomment-588188924) of why smart copy is such a brilliant solution. A [pull request implementing this feature](https://github.com/alacritty/alacritty/pull/3873) was proposed by ambiso later in 2020, which was also rejected. [Their fork](https://github.com/ambiso/alacritty/tree/master) is sadly outdated now. Therefore, I created this updated fork with the same approach. I plan to keep the fork up to date for as long as I use Alacritty as my daily driver terminal emulator.
+
+The following key bindings are provided by default for Windows, Linux and BSD:
+
+```toml
+[[keyboard.bindings]]
+key = "V"
+mods = "Control"
+mode = "~Vi"
+action = "Paste"
+
+[[keyboard.bindings]]
+key = "C"
+mods = "Control"
+mode = "~Vi"
+action = "CopyDynamic"
+```
+
+and in YAML (for Alacritty v0.12 or older),
+
+```yaml
+key_bindings:
+ - { key: V, mods: Control, mode: ~Vi, action: Paste }
+ - { key: C, mods: Control, mode: ~Vi, action: CopyDynamic }
+```
+
## About
Alacritty is a modern terminal emulator that comes with sensible defaults, but
diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs
index 62ca03a0b7f..a15106e4b7e 100644
--- a/alacritty/src/config/bindings.rs
+++ b/alacritty/src/config/bindings.rs
@@ -120,6 +120,9 @@ pub enum Action {
/// Store current selection into clipboard.
Copy,
+ /// Copy selection and clear it, or forward the keybinding to the program if there is no selection.
+ CopyDynamic,
+
/// Store current selection into selection buffer.
CopySelection,
@@ -535,11 +538,13 @@ fn common_keybindings() -> Vec {
KeyBinding;
"v", ModifiersState::CONTROL | ModifiersState::SHIFT, ~BindingMode::VI; Action::Paste;
"v", ModifiersState::CONTROL | ModifiersState::SHIFT, +BindingMode::VI, +BindingMode::SEARCH; Action::Paste;
+ "v", ModifiersState::CONTROL, ~BindingMode::VI; Action::Paste;
"f", ModifiersState::CONTROL | ModifiersState::SHIFT, ~BindingMode::SEARCH; Action::SearchForward;
"b", ModifiersState::CONTROL | ModifiersState::SHIFT, ~BindingMode::SEARCH; Action::SearchBackward;
Insert, ModifiersState::SHIFT, ~BindingMode::VI; Action::PasteSelection;
"c", ModifiersState::CONTROL | ModifiersState::SHIFT; Action::Copy;
"c", ModifiersState::CONTROL | ModifiersState::SHIFT, +BindingMode::VI, ~BindingMode::SEARCH; Action::ClearSelection;
+ "c", ModifiersState::CONTROL, ~BindingMode::VI; Action::CopyDynamic;
"0", ModifiersState::CONTROL; Action::ResetFontSize;
"=", ModifiersState::CONTROL; Action::IncreaseFontSize;
"+", ModifiersState::CONTROL; Action::IncreaseFontSize;
diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs
index afb23eb5053..418ac63015b 100644
--- a/alacritty/src/input/keyboard.rs
+++ b/alacritty/src/input/keyboard.rs
@@ -201,6 +201,11 @@ impl> Processor {
// Pass through the key if any of the bindings has the `ReceiveChar` action.
*suppress_chars.get_or_insert(true) &= binding.action != Action::ReceiveChar;
+ // Pass through the key if any of the bindings has the `CopyDynamic` action and the selection is empty.
+ if binding.action == Action::CopyDynamic && self.ctx.selection_is_empty() {
+ suppress_chars = Some(false);
+ }
+
// Binding was triggered; run the action.
binding.action.clone().execute(&mut self.ctx);
}
diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs
index 9a96b45bda4..f55c2c14504 100644
--- a/alacritty/src/input/mod.rs
+++ b/alacritty/src/input/mod.rs
@@ -301,6 +301,12 @@ impl Execute for Action {
Action::Copy => ctx.copy_selection(ClipboardType::Clipboard),
#[cfg(not(any(target_os = "macos", windows)))]
Action::CopySelection => ctx.copy_selection(ClipboardType::Selection),
+ Action::CopyDynamic => {
+ if !ctx.selection_is_empty() {
+ ctx.copy_selection(ClipboardType::Clipboard);
+ ctx.clear_selection();
+ }
+ },
Action::ClearSelection => ctx.clear_selection(),
Action::Paste => {
let text = ctx.clipboard_mut().load(ClipboardType::Clipboard);