diff --git a/Doc/cmus.txt b/Doc/cmus.txt index 1bd5bc3be..47636d3a7 100644 --- a/Doc/cmus.txt +++ b/Doc/cmus.txt @@ -888,6 +888,10 @@ altformat_trackwin [`Format String`] Note: if empty, *format_trackwin* is used instead. +block_key_paste (true) + Prevent accidental input by only accepting pasted text in the command line. + Only works on terminals which support bracketed paste. + buffer_seconds (10) [1-300] Size of the player buffer in seconds. diff --git a/options.c b/options.c index 703729a7e..1fe4e6641 100644 --- a/options.c +++ b/options.c @@ -93,6 +93,7 @@ int stop_after_queue = 0; int tree_width_percent = 33; int tree_width_max = 0; int pause_on_output_change = 0; +int block_key_paste = 1; int colors[NR_COLORS] = { -1, @@ -1318,6 +1319,21 @@ static void toggle_pause_on_output_change(void *data) pause_on_output_change ^= 1; } +static void get_block_key_paste(void *data, char *buf, size_t size) +{ + strscpy(buf, bool_names[block_key_paste], size); +} + +static void set_block_key_paste(void *data, const char *buf) +{ + parse_bool(buf, &pause_on_output_change); +} + +static void toggle_block_key_paste(void *data) +{ + pause_on_output_change ^= 1; +} + /* }}} */ /* special callbacks (id set) {{{ */ @@ -1581,6 +1597,7 @@ static const struct { DN(tree_width_max) DT(pause_on_output_change) DN(pl_env_vars) + DT(block_key_paste) { NULL, NULL, NULL, NULL, 0 } }; diff --git a/options.h b/options.h index 521970778..4b6dd136c 100644 --- a/options.h +++ b/options.h @@ -163,6 +163,7 @@ extern int stop_after_queue; extern int tree_width_percent; extern int tree_width_max; extern int pause_on_output_change; +extern int block_key_paste; extern const char * const aaa_mode_names[]; extern const char * const view_names[NR_VIEWS + 1]; diff --git a/ui_curses.c b/ui_curses.c index 676ffbaff..8780e3f82 100644 --- a/ui_curses.c +++ b/ui_curses.c @@ -149,6 +149,8 @@ static const int default_esc_delay = 25; static char *title_buf = NULL; +static int in_bracketed_paste = 0; + enum { CURSED_WIN, CURSED_WIN_CUR, @@ -1988,7 +1990,9 @@ static void handle_ch(uchar ch) { clear_error(); if (input_mode == NORMAL_MODE) { - normal_mode_ch(ch); + if (!block_key_paste || !in_bracketed_paste) { + normal_mode_ch(ch); + } } else if (input_mode == COMMAND_MODE) { command_mode_ch(ch); update_commandline(); @@ -2024,6 +2028,15 @@ static void handle_csi(void) { if (!done) { return; // overflow } + + if (buf_n == 4) { + // bracketed paste + // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ + if (buf[0] == '2' && buf[1] == '0' && (buf[2] == '0' || buf[2] == '1') && buf[3] == '~') { + in_bracketed_paste = buf[2] == '0'; + return; + } + } } static void handle_escape(int c) @@ -2044,7 +2057,9 @@ static void handle_key(int key) { clear_error(); if (input_mode == NORMAL_MODE) { - normal_mode_key(key); + if (!block_key_paste || !in_bracketed_paste) { + normal_mode_key(key); + } } else if (input_mode == COMMAND_MODE) { command_mode_key(key); update_commandline(); @@ -2418,6 +2433,10 @@ static void init_all(void) init_curses(); + // enable bracketed paste (will be ignored if not supported) + printf("\033[?2004h"); + fflush(stdout); + if (resume_cmus) { resume_load(); cmus_add(play_queue_append, play_queue_autosave_filename, @@ -2436,6 +2455,10 @@ static void exit_all(void) { endwin(); + // disable bracketed paste + printf("\033[?2004l"); + fflush(stdout); + if (resume_cmus) resume_exit(); options_exit();