From 9f177ebb2be58e07a4e437e4b885411ae2017114 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 26 Jun 2023 17:19:00 -0400 Subject: [PATCH] new rl_full_quoting_desired application-settable variable; repeated invocations of vi-yank-pop now cycle through the kill ring; fix some uninitialized variable problems; fix some small memory leaks; better deallocation when completion is interrupted; don't print signal chars in callback mode by default; don't compile in obsolete typedefs by default --- complete.c | 118 +++++++++++++++++++++++++++++++---------------- doc/rltech.texi | 10 ++++ doc/rluser.texi | 4 ++ doc/version.texi | 6 +-- input.c | 1 + kill.c | 6 +-- readline.h | 6 +++ rltypedefs.h | 6 +-- signals.c | 3 ++ util.c | 2 +- 10 files changed, 111 insertions(+), 51 deletions(-) diff --git a/complete.c b/complete.c index bf7cc85..349c87a 100644 --- a/complete.c +++ b/complete.c @@ -336,6 +336,15 @@ int rl_filename_completion_desired = 0; entry finder function. */ int rl_filename_quoting_desired = 1; +/* Non-zero means we should apply filename-type quoting to all completions + even if we are not otherwise treating the matches as filenames. This is + ALWAYS zero on entry, and can only be changed within a completion entry + finder function. */ +int rl_full_quoting_desired = 0; + +#define QUOTING_DESIRED() \ + (rl_full_quoting_desired || (rl_filename_completion_desired && rl_filename_quoting_desired)) + /* This function, if defined, is called by the completer when real filename completion is done, after all the matching names have been generated. It is passed a (char**) known as matches in the code below. @@ -480,6 +489,32 @@ rl_completion_mode (rl_command_func_t *cfunc) return TAB; } +/********************************************/ +/* */ +/* Completion signal handling and cleanup */ +/* */ +/********************************************/ + +/* State to clean up and free if completion is interrupted by a signal. */ +typedef struct { + char **matches; + char *saved_line; +} complete_sigcleanarg_t; + +static void +_rl_complete_sigcleanup (int sig, void *ptr) +{ + complete_sigcleanarg_t *arg; + + if (sig == SIGINT) /* XXX - for now */ + { + arg = ptr; + _rl_free_match_list (arg->matches); + FREE (arg->saved_line); + _rl_complete_display_matches_interrupt = 1; + } +} + /************************************/ /* */ /* Completion utility functions */ @@ -494,16 +529,6 @@ _rl_reset_completion_state (void) rl_completion_quote_character = 0; } -static void -_rl_complete_sigcleanup (int sig, void *ptr) -{ - if (sig == SIGINT) /* XXX - for now */ - { - _rl_free_match_list ((char **)ptr); - _rl_complete_display_matches_interrupt = 1; - } -} - /* Set default values for readline word completion. These are the variables that application completion functions can change or inspect. */ static void @@ -512,6 +537,7 @@ set_completion_defaults (int what_to_do) /* Only the completion entry function can change these. */ rl_filename_completion_desired = 0; rl_filename_quoting_desired = 1; + rl_full_quoting_desired = 0; rl_completion_type = what_to_do; rl_completion_suppress_append = rl_completion_suppress_quote = 0; rl_completion_append_character = ' '; @@ -1408,10 +1434,8 @@ compute_lcd_of_matches (char **match_list, int matches, const char *text) check against the list of matches FI */ dtext = (char *)NULL; - if (rl_filename_completion_desired && - rl_filename_dequoting_function && - rl_completion_found_quote && - rl_filename_quoting_desired) + if (QUOTING_DESIRED() && rl_completion_found_quote && + rl_filename_dequoting_function) { dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character); text = dtext; @@ -1766,9 +1790,7 @@ make_quoted_replacement (char *match, int mtype, char *qc) matches don't require a quoted substring. */ replacement = match; - should_quote = match && rl_completer_quote_characters && - rl_filename_completion_desired && - rl_filename_quoting_desired; + should_quote = match && rl_completer_quote_characters && QUOTING_DESIRED(); if (should_quote) should_quote = should_quote && (!qc || !*qc || @@ -1980,8 +2002,7 @@ compare_match (char *text, const char *match) char *temp; int r; - if (rl_filename_completion_desired && rl_filename_quoting_desired && - rl_completion_found_quote && rl_filename_dequoting_function) + if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function) { temp = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); r = strcmp (temp, match); @@ -2005,10 +2026,11 @@ rl_complete_internal (int what_to_do) { char **matches; rl_compentry_func_t *our_func; - int start, end, delimiter, found_quote, i, nontrivial_lcd; + int start, end, delimiter, found_quote, i, nontrivial_lcd, do_display; char *text, *saved_line_buffer; char quote_char; int tlen, mlen, saved_last_completion_failed; + complete_sigcleanarg_t cleanarg; /* state to clean up on signal */ RL_SETSTATE(RL_STATE_COMPLETING); @@ -2043,8 +2065,7 @@ rl_complete_internal (int what_to_do) strcmp directly. */ /* nontrivial_lcd is set if the common prefix adds something to the word being completed. */ - if (rl_filename_completion_desired && rl_filename_quoting_desired && - rl_completion_found_quote && rl_filename_dequoting_function) + if (QUOTING_DESIRED() && rl_completion_found_quote && rl_filename_dequoting_function) { char *t; t = (*rl_filename_dequoting_function) (text, rl_completion_quote_character); @@ -2088,6 +2109,8 @@ rl_complete_internal (int what_to_do) if (matches && matches[0] && *matches[0]) last_completion_failed = 0; + do_display = 0; + switch (what_to_do) { case TAB: @@ -2121,13 +2144,13 @@ rl_complete_internal (int what_to_do) { if (what_to_do == '!') { - display_matches (matches); + do_display = 1; break; } else if (what_to_do == '@') { if (nontrivial_lcd == 0) - display_matches (matches); + do_display = 1; break; } else if (rl_editing_mode != vi_mode) @@ -2152,22 +2175,7 @@ rl_complete_internal (int what_to_do) break; } - if (rl_completion_display_matches_hook == 0) - { - _rl_sigcleanup = _rl_complete_sigcleanup; - _rl_sigcleanarg = matches; - _rl_complete_display_matches_interrupt = 0; - } - display_matches (matches); - if (_rl_complete_display_matches_interrupt) - { - matches = 0; /* already freed by rl_complete_sigcleanup */ - _rl_complete_display_matches_interrupt = 0; - if (rl_signal_event_hook) - (*rl_signal_event_hook) (); /* XXX */ - } - _rl_sigcleanup = 0; - _rl_sigcleanarg = 0; + do_display = 1; break; default: @@ -2180,6 +2188,34 @@ rl_complete_internal (int what_to_do) return 1; } + /* If we need to display the match list, set up to clean it up on receipt of + a signal and do it here. If the application has registered a function to + display the matches, let it do the work. */ + if (do_display) + { + if (rl_completion_display_matches_hook == 0) + { + _rl_sigcleanup = _rl_complete_sigcleanup; + cleanarg.matches = matches; + cleanarg.saved_line = saved_line_buffer; + _rl_sigcleanarg = &cleanarg; + _rl_complete_display_matches_interrupt = 0; + } + + display_matches (matches); + + if (_rl_complete_display_matches_interrupt) + { + matches = 0; /* Both already freed by _rl_complete_sigcleanup */ + saved_line_buffer = 0; + _rl_complete_display_matches_interrupt = 0; + if (rl_signal_event_hook) + (*rl_signal_event_hook) (); + } + _rl_sigcleanup = 0; + _rl_sigcleanarg = 0; + } + _rl_free_match_list (matches); /* Check to see if the line has changed through all of this manipulation. */ @@ -2864,7 +2900,7 @@ rl_menu_complete (int count, int ignore) if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items) { rl_ding (); - FREE (matches); + _rl_free_match_list (matches); matches = (char **)0; full_completion = 1; return (0); diff --git a/doc/rltech.texi b/doc/rltech.texi index 5aa0453..4d3f3cc 100644 --- a/doc/rltech.texi +++ b/doc/rltech.texi @@ -2300,6 +2300,16 @@ The quoting is effected via a call to the function pointed to by @code{rl_filename_quoting_function}. @end deftypevar +@deftypevar int rl_full_quoting_desired +Non-zero means that Readline should apply filename-style quoting, +including any application-specified quoting mechanism, +to all completion matches even if we are not otherwise treating the +matches as filenames. +This is @emph{always} zero when completion is attempted, and can only +be changed within an application-specific completion function. +The quoting is effected via a call to the function pointed to +by @code{rl_filename_quoting_function}. + @deftypevar int rl_attempted_completion_over If an application-specific completion function assigned to @code{rl_attempted_completion_function} sets this variable to a non-zero diff --git a/doc/rluser.texi b/doc/rluser.texi index 36e8a38..5e8a36a 100644 --- a/doc/rluser.texi +++ b/doc/rluser.texi @@ -2206,6 +2206,10 @@ quoting special characters, or suppressing trailing spaces). This option is intended to be used with shell functions specified with @option{-F}. +@item fullquote +Tell Readline to quote all the completed words even if they are not +filenames. + @item noquote Tell Readline not to quote the completed words if they are filenames (quoting filenames is the default). diff --git a/doc/version.texi b/doc/version.texi index 865a715..e117043 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -5,7 +5,7 @@ Copyright (C) 1988-2023 Free Software Foundation, Inc. @set EDITION 8.2 @set VERSION 8.2 -@set UPDATED 27 March 2023 -@set UPDATED-MONTH March 2023 +@set UPDATED 15 June 2023 +@set UPDATED-MONTH June 2023 -@set LASTCHANGE Mon Mar 27 11:41:20 EDT 2023 +@set LASTCHANGE Thu Jun 15 14:37:40 EDT 2023 diff --git a/input.c b/input.c index 229474f..9807453 100644 --- a/input.c +++ b/input.c @@ -249,6 +249,7 @@ rl_gather_tyi (void) struct timeval timeout; #endif + result = -1; chars_avail = 0; input = 0; tty = fileno (rl_instream); diff --git a/kill.c b/kill.c index 1dfe3c5..972c7d9 100644 --- a/kill.c +++ b/kill.c @@ -569,7 +569,7 @@ rl_vi_yank_pop (int count, int key) } l = strlen (rl_kill_ring[rl_kill_index]); -#if 0 /* TAG:readline-8.3 8/29/2022 matteopaolini1995@gmail.com */ +#if 1 origpoint = rl_point; n = rl_point - l + 1; #else @@ -577,7 +577,7 @@ rl_vi_yank_pop (int count, int key) #endif if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l)) { -#if 0 /* TAG:readline-8.3 */ +#if 1 rl_delete_text (n, n + l); /* remember vi cursor positioning */ rl_point = origpoint - l; #else @@ -779,7 +779,7 @@ _rl_read_bracketed_paste_prefix (int c) pbpref = BRACK_PASTE_PREF; /* XXX - debugging */ if (c != pbpref[0]) return (0); - pbuf[ind = 0] = c; + pbuf[ind = 0] = key = c; while (ind < BRACK_PASTE_SLEN-1 && (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) && _rl_pushed_input_available () == 0 && diff --git a/readline.h b/readline.h index 48f1210..5b83d29 100644 --- a/readline.h +++ b/readline.h @@ -790,6 +790,12 @@ extern int rl_filename_completion_desired; entry finder function. */ extern int rl_filename_quoting_desired; +/* Non-zero means we should apply filename-type quoting to all completions + even if we are not otherwise treating the matches as filenames. This is + ALWAYS zero on entry, and can only be changed within a completion entry + finder function. */ +extern int rl_full_quoting_desired; + /* Set to a function to quote a filename in an application-specific fashion. Called with the text to quote, the type of match found (single or multiple) and a pointer to the quoting character to be used, which the function can diff --git a/rltypedefs.h b/rltypedefs.h index b1ffeb0..d179e85 100644 --- a/rltypedefs.h +++ b/rltypedefs.h @@ -1,6 +1,6 @@ /* rltypedefs.h -- Type declarations for readline functions. */ -/* Copyright (C) 2000-2021 Free Software Foundation, Inc. +/* Copyright (C) 2000-2023 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. @@ -28,7 +28,7 @@ extern "C" { /* Old-style, attempt to mark as deprecated in some way people will notice. */ -#if !defined (_FUNCTION_DEF) +#if !defined (_FUNCTION_DEF) && defined (WANT_OBSOLETE_TYPEDEFS) # define _FUNCTION_DEF typedef int Function () __attribute__((deprecated)); @@ -36,7 +36,7 @@ typedef void VFunction () __attribute__((deprecated)); typedef char *CPFunction () __attribute__((deprecated)); typedef char **CPPFunction () __attribute__((deprecated)); -#endif /* _FUNCTION_DEF */ +#endif /* _FUNCTION_DEF && WANT_OBSOLETE_TYPEDEFS */ /* New style. */ diff --git a/signals.c b/signals.c index ec835e5..51d7468 100644 --- a/signals.c +++ b/signals.c @@ -267,6 +267,9 @@ _rl_handle_signal (int sig) sigprocmask (SIG_BLOCK, &set, &oset); #endif +#if defined (READLINE_CALLBACKS) + if (RL_ISSTATE (RL_STATE_CALLBACK) == 0 || rl_persistent_signal_handlers) +#endif rl_echo_signal_char (sig); rl_cleanup_after_signal (); diff --git a/util.c b/util.c index f909daa..2a24703 100644 --- a/util.c +++ b/util.c @@ -43,8 +43,8 @@ #include /* System-specific feature definitions and include files. */ -#include "rldefs.h" #include "rlmbutil.h" +#include "rldefs.h" #if defined (TIOCSTAT_IN_SYS_IOCTL) # include -- 2.47.2