diff --git a/lib/readline/bind.c b/lib/readline/bind.c --- a/lib/readline/bind.c +++ b/lib/readline/bind.c @@ -1428,6 +1428,7 @@ static const struct { { "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 }, { "disable-completion", &rl_inhibit_completion, 0 }, { "echo-control-characters", &_rl_echo_control_chars, 0 }, + { "enable-bracketed-paste", &_rl_enable_bracketed_paste, 0 }, { "enable-keypad", &_rl_enable_keypad, 0 }, { "enable-meta-key", &_rl_enable_meta, 0 }, { "expand-tilde", &rl_complete_with_tilde_expansion, 0 }, diff --git a/lib/readline/funmap.c b/lib/readline/funmap.c --- a/lib/readline/funmap.c +++ b/lib/readline/funmap.c @@ -68,6 +68,7 @@ static const FUNMAP default_funmap[] = { { "backward-word", rl_backward_word }, { "beginning-of-history", rl_beginning_of_history }, { "beginning-of-line", rl_beg_of_line }, + { "bracketed-paste-begin", rl_bracketed_paste_begin }, { "call-last-kbd-macro", rl_call_last_kbd_macro }, { "capitalize-word", rl_capitalize_word }, { "character-search", rl_char_search }, diff --git a/lib/readline/kill.c b/lib/readline/kill.c --- a/lib/readline/kill.c +++ b/lib/readline/kill.c @@ -656,6 +656,55 @@ rl_yank_last_arg (count, key) return retval; } +/* Having read the special escape sequence denoting the beginning of a + `bracketed paste' sequence, read the rest of the pasted input until the + closing sequence and insert the pasted text as a single unit without + interpretation. */ +int +rl_bracketed_paste_begin (int count, int key) +{ + int retval, c; + size_t len, cap; + char *buf; + + retval = 1; + len = 0; + buf = xmalloc (cap = 64); + + RL_SETSTATE (RL_STATE_MOREINPUT); + while ((c = rl_read_key ()) >= 0) + { + if (RL_ISSTATE (RL_STATE_MACRODEF)) + _rl_add_macro_char (c); + + if (c == '\r') /* XXX */ + c = '\n'; + + if (len == cap) + buf = xrealloc (buf, cap *= 2); + + buf[len++] = c; + if (len >= BRACK_PASTE_SLEN && c == BRACK_PASTE_LAST && + STREQN (buf + len - BRACK_PASTE_SLEN, BRACK_PASTE_SUFF, BRACK_PASTE_SLEN)) + { + len -= BRACK_PASTE_SLEN; + break; + } + } + RL_UNSETSTATE (RL_STATE_MOREINPUT); + + if (c >= 0) + { + if (len == cap) + buf = xrealloc (buf, cap + 1); + buf[len] = '\0'; + retval = rl_insert_text (buf); + } + + xfree (buf); + return (retval); +} + /* A special paste command for users of Cygnus's cygwin32. */ #if defined (__CYGWIN__) #include diff --git a/lib/readline/readline.c b/lib/readline/readline.c --- a/lib/readline/readline.c +++ b/lib/readline/readline.c @@ -95,6 +95,8 @@ static void readline_initialize_everything PARAMS((void)); static void bind_arrow_keys_internal PARAMS((Keymap)); static void bind_arrow_keys PARAMS((void)); +static void bind_bracketed_paste_prefix PARAMS((void)); + static void readline_default_bindings PARAMS((void)); static void reset_default_bindings PARAMS((void)); @@ -285,6 +287,11 @@ int _rl_revert_all_at_newline = 0; characters corresponding to keyboard-generated signals. */ int _rl_echo_control_chars = 1; +/* Non-zero means to attempt to put the terminal in `bracketed paste mode', + where it will prefix pasted text with an escape sequence and send + another to mark the end of the paste. */ +int _rl_enable_bracketed_paste = 0; + /* **************************************************************** */ /* */ /* Top Level Functions */ @@ -1143,6 +1150,10 @@ readline_initialize_everything () /* Try to bind a common arrow key prefix, if not already bound. */ bind_arrow_keys (); + /* Bind the bracketed paste prefix assuming that the user will enable + it on terminals that support it. */ + bind_bracketed_paste_prefix (); + /* Enable the meta key, if this terminal has one. */ if (_rl_enable_meta) _rl_enable_meta_key (); @@ -1234,6 +1245,22 @@ bind_arrow_keys () #endif } +static void +bind_bracketed_paste_prefix (void) +{ + Keymap xkeymap; + + xkeymap = _rl_keymap; + + _rl_keymap = emacs_standard_keymap; + rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin); + + _rl_keymap = vi_insertion_keymap; + rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin); + + _rl_keymap = xkeymap; +} + /* **************************************************************** */ /* */ /* Saving and Restoring Readline's state */ diff --git a/lib/readline/readline.h b/lib/readline/readline.h --- a/lib/readline/readline.h +++ b/lib/readline/readline.h @@ -172,6 +172,7 @@ extern int rl_yank PARAMS((int, int)); extern int rl_yank_pop PARAMS((int, int)); extern int rl_yank_nth_arg PARAMS((int, int)); extern int rl_yank_last_arg PARAMS((int, int)); +extern int rl_bracketed_paste_begin PARAMS((int, int)); /* Not available unless __CYGWIN__ is defined. */ #ifdef __CYGWIN__ extern int rl_paste_from_clipboard PARAMS((int, int)); diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h --- a/lib/readline/rlprivate.h +++ b/lib/readline/rlprivate.h @@ -195,6 +195,14 @@ extern int rl_blink_matching_paren; /* kill.c */ extern int rl_set_retained_kills PARAMS((int)); +#define BRACK_PASTE_PREF "\033[200~" +#define BRACK_PASTE_SUFF "\033[201~" + +#define BRACK_PASTE_LAST '~' +#define BRACK_PASTE_SLEN 6 + +#define BRACK_PASTE_INIT "\033[?2004h" +#define BRACK_PASTE_FINI "\033[?2004l\r" /* terminal.c */ extern void _rl_set_screen_size PARAMS((int, int)); @@ -452,6 +460,7 @@ extern int _rl_output_meta_chars; extern int _rl_bind_stty_chars; extern int _rl_revert_all_at_newline; extern int _rl_echo_control_chars; +extern int _rl_enable_bracketed_paste; extern char *_rl_comment_begin; extern unsigned char _rl_parsing_conditionalized_out; extern Keymap _rl_keymap; diff --git a/lib/readline/rltty.c b/lib/readline/rltty.c --- a/lib/readline/rltty.c +++ b/lib/readline/rltty.c @@ -60,6 +60,12 @@ static void set_winsize PARAMS((int)); /* */ /* **************************************************************** */ +/* Non-zero means that the terminal is in a prepped state. There are several + flags that are OR'd in to denote whether or not we have sent various + init strings to the terminal. */ +#define TPX_PREPPED 0x01 +#define TPX_BRACKPASTE 0x02 + /* Non-zero means that the terminal is in a prepped state. */ static int terminal_prepped; @@ -595,7 +601,7 @@ void rl_prep_terminal (meta_flag) int meta_flag; { - int tty; + int tty, nprep; TIOTYPE tio; if (terminal_prepped) @@ -659,8 +665,16 @@ rl_prep_terminal (meta_flag) if (_rl_enable_keypad) _rl_control_keypad (1); + nprep = TPX_PREPPED; + + if (_rl_enable_bracketed_paste) + { + fprintf (rl_outstream, BRACK_PASTE_INIT); + nprep |= TPX_BRACKPASTE; + } + fflush (rl_outstream); - terminal_prepped = 1; + terminal_prepped = nprep; RL_SETSTATE(RL_STATE_TERMPREPPED); _rl_release_sigint (); @@ -680,6 +694,9 @@ rl_deprep_terminal () tty = rl_instream ? fileno (rl_instream) : fileno (stdout); + if (terminal_prepped & TPX_BRACKPASTE) + fprintf (rl_outstream, BRACK_PASTE_FINI); + if (_rl_enable_keypad) _rl_control_keypad (0);