From db63be790984c20ba3a399e233d33b51c73cf4a1 Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Sat, 25 Feb 2017 14:42:52 +0100 Subject: [PATCH] Add support for bracketed paste This is a terminal feature where pastes will be "bracketed" in \e\[200~ and \e\[201~. It is more of a "security" measure (since particularly copying from a browser can copy text different from what the user sees, which might be malicious) than a performance optimization. Work towards #967. --- CHANGELOG.md | 1 + .../functions/__fish_config_interactive.fish | 17 +++++++++ .../functions/__fish_shared_key_bindings.fish | 37 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fca7fda3..6ec5a33bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - The `export` command now supports colon-separated `PATH`, `CDPATH` and `MANPATH`. - The `read` command now has a default limit of 10 MiB. If a line is longer than that it will fail with $status set to 122 and the var will be empty. You can set a different limit by setting the FISH_READ_BYTE_LIMIT variable. - The \cl binding no longer deletes the scrollback buffer with ncurses >= 6.0 (#2855). +- fish now supports "bracketed paste". Note that this is more of a security measure, the `fish_clipboard_paste` function (bound to \cv by default) still has a few advantages. --- diff --git a/share/functions/__fish_config_interactive.fish b/share/functions/__fish_config_interactive.fish index 2716a3a27..53902b156 100644 --- a/share/functions/__fish_config_interactive.fish +++ b/share/functions/__fish_config_interactive.fish @@ -232,6 +232,23 @@ function __fish_config_interactive -d "Initializations that should be performed # Load key bindings __fish_reload_key_bindings + if not set -q FISH_UNIT_TESTS_RUNNING + # Enable bracketed paste before every prompt (see __fish_shared_bindings for the bindings). + # Disable it for unit tests so we don't have to add the sequences to bind.expect + function __fish_enable_bracketed_paste --on-event fish_prompt + printf "\e[?2004h" + end + + # Disable BP before every command because that might not support it. + function __fish_disable_bracketed_paste --on-event fish_preexec + printf "\e[?2004l" + end + + # Tell the terminal we support BP. Since we are in __f_c_i, the first fish_prompt + # has already fired. + __fish_enable_bracketed_paste + end + function __fish_winch_handler --on-signal WINCH -d "Repaint screen when window changes size" commandline -f repaint end diff --git a/share/functions/__fish_shared_key_bindings.fish b/share/functions/__fish_shared_key_bindings.fish index 4a137fbfa..32ce5eee2 100644 --- a/share/functions/__fish_shared_key_bindings.fish +++ b/share/functions/__fish_shared_key_bindings.fish @@ -105,4 +105,41 @@ function __fish_shared_key_bindings -d "Bindings shared between emacs and vi mod # The [meta-e] and [meta-v] keystrokes invoke an external editor on the command buffer. bind \ee edit_command_buffer bind \ev edit_command_buffer + + # Support for "bracketed paste" + # The way it works is that we acknowledge our support by printing + # \e\[?2004h + # then the terminal will "bracket" every paste in + # \e\[200~ and \e\[201~ + # Every character in between those two will be part of the paste and should not cause a binding to execute (like \n executing commands). + # + # We enable it after every command and disable it before (in __fish_config_interactive.fish) + # + # Support for this seems to be ubiquitous - emacs enables it unconditionally (!) since 25.1 (though it only supports it since then, + # it seems to be the last term to gain support). + # TODO: Should we disable this in older emacsen? + # + # NOTE: This is more of a "security" measure than a proper feature. + # The better way to paste remains the `fish_clipboard_paste` function (bound to \cv by default). + # We don't disable highlighting here, so it will be redone after every character (which can be slow), + # and it doesn't handle "paste-stop" sequences in the paste (which the terminal needs to strip, but KDE konsole doesn't). + # + # See http://thejh.net/misc/website-terminal-copy-paste. The second case will not be caught in KDE konsole. + # Bind the starting sequence in every bind mode, even user-defined ones. + # HACK: We introspect `bind` here to list all modes. + # Re-running `bind` multiple times per mode is still faster than trying to make the list unique, + # even without calling `sort -u` or `uniq`, for the vi-bindings. + # TODO: This can be solved better once #3872 is implemented. + set -l allmodes default + set allmodes $allmodes (bind -a | string match -r -- '-M \w+' | string replace -- '-M ' '') + for mode in $allmodes + bind -M $mode -m paste \e\[200~ 'set -g __fish_last_bind_mode $fish_bind_mode' + end + # This sequence ends paste-mode and returns to the previous mode we have saved before. + bind -M paste \e\[201~ 'set fish_bind_mode $__fish_last_bind_mode; commandline -f force-repaint' + # In paste-mode, everything self-inserts except for the sequence to get out of it + bind -M paste "" self-insert + # Without this, a \r will overwrite the other text, rendering it invisible - which makes the exercise kinda pointless. + # TODO: Test this in windows (\r\n line endings) + bind -M paste \r "commandline -i \n" end