From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id GMV2BrbOxGZv+A0AWB0awg (envelope-from ) for ; Tue, 20 Aug 2024 13:13:26 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=IJQSUbxg; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 1356C1E0D0; Tue, 20 Aug 2024 13:13:26 -0400 (EDT) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id EB6471E08C for ; Tue, 20 Aug 2024 13:13:23 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 81E68387086C for ; Tue, 20 Aug 2024 17:13:23 +0000 (GMT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id EA870386D622 for ; Tue, 20 Aug 2024 17:11:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EA870386D622 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org EA870386D622 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1724173868; cv=none; b=K68KMqBJbABNLS+RAz2fSRzeIxIJH1S+G0Yi0fG+qxIWRVOizlXlNw0dl0Y801XNW1Pq6vedmZtbDGWnr9Dif0+e7ZzBnZvu41shYHlcTD9mQJA2GQc4E9HIv5On2JPTF7hiZQVMfYUXUdpSSKlVghERtLC+qPAle4bVhvSzafc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1724173868; c=relaxed/simple; bh=nFxpyuMfB17zFgF8ol1z05O1rx4ukW7DAIiUGJerwa0=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=pnc/aztuOtBH3HxenelHtmF1eJvjasS7D+kDTUwumBF80R+35krqLidrKOMGXPu16ynYJdo+9C/pJAOMgygjYe5VYnPA1aQsDpSrSNbnC3e5BFJQGnYu1d3XFU2mgwJAX8XzWpUAGpWaYTMvdwxRBI+/y/ShmT95lyyTdFWRvDc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1724173865; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=IXI7VwVTHwoAEfXwK6Z00UpL3aAM7DLEEwJ88bCciuo=; b=IJQSUbxgdp7tHZ4nTmlh+t4jLb+h14fE3P2KcYMHy+sQ5cgMZltnxOq4dBDiC62IBJNi73 yqlPjz3dYnjKPk1UDmKgWtF6lurFSUIYEaT47/cIeH3BnlNjERKn5hUVNGQ0mu51opQugN wMsrHVB3mlgVtdgdba1PVyTHQORpcE0= Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-161-ttLNKnH8NNufoq9tWy7ATA-1; Tue, 20 Aug 2024 13:11:04 -0400 X-MC-Unique: ttLNKnH8NNufoq9tWy7ATA-1 Received: by mail-wm1-f70.google.com with SMTP id 5b1f17b1804b1-42820c29a76so50073685e9.2 for ; Tue, 20 Aug 2024 10:11:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724173862; x=1724778662; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=IXI7VwVTHwoAEfXwK6Z00UpL3aAM7DLEEwJ88bCciuo=; b=wSD8WAb76vu0+1+SpKk/68ZQMYTPNLaaInDY8GLHUwXu9+xVGGP34L1APKroWfg8Qn tqTU4n+O+ouXhbhP0xFJMtdBSE4qLDIYSCPO55u13sbMrR4YAOZRRbL7fukzfxEW3jRW NKsWHHOfg2N6aj2xZbhRICSqDYhIPWjADA5S7aemV3BmWjxkAIwK2Jx12uzF+NHVq2lH Zq5AzzkWY4XFtjLcpvXO2Iy2UJBaOHY1XqdVs05E7R9+apWIQhUNQWIyGzacySF2Va7m tGtoY71GZ59bLY77ywWLWV/PKoTk0Z0GQttyNbaApuJStiy2I6kdpFbFElQSnvrpZ1v/ YM1Q== X-Gm-Message-State: AOJu0Yx7ghPgclQY2St3jVmUvh4MS71vR7t8ReSQMEe9VvVa+zrEDGzS dlzePGP59vQLu9bQq5ulP7u3CLz5/Y1EgI7nI6LfQm2uBiQn6RLzpUftYvd41mTBdToQ1g/piOF h+SxaQOP3XPPRdrrU+RAqCWPLLpRjf8etNphDM9SBT4Lmm2dQkiddQKdxBeuok2U7dMcnlAkdEk e98zhbZWqMkYDDqnnP2tM2Q1YTXH0c359BW9vzHPHB5Hc= X-Received: by 2002:a05:600c:1c90:b0:426:647b:1bfc with SMTP id 5b1f17b1804b1-42abd244b11mr225205e9.30.1724173862028; Tue, 20 Aug 2024 10:11:02 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHCKqmXsHMu1KT8pPCdz/+lM6n09euusGOIzWWJRp5pMWAq2hMJqq3dnrLG8fcKGDvGR7FbFg== X-Received: by 2002:a05:600c:1c90:b0:426:647b:1bfc with SMTP id 5b1f17b1804b1-42abd244b11mr224825e9.30.1724173860876; Tue, 20 Aug 2024 10:11:00 -0700 (PDT) Received: from localhost (178.126.90.146.dyn.plus.net. [146.90.126.178]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-429ed650e21sm148489415e9.20.2024.08.20.10.11.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Aug 2024 10:11:00 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCHv5 11/14] gdb: extend completion of quoted filenames to work in brkchars phase Date: Tue, 20 Aug 2024 18:10:41 +0100 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Up to this point filename completion for possibly quoted filenames has always been handled during the second (non-brkchars) phase of completion. This works fine for commands that only want to complete on a single filename argument. In a later commit though I need to perform completion of a quoted filename argument during the first (brkchars) phase of completion. This will allow me to add a custom completer that completes both command options and arguments for a command (remove-symbol-file) that takes a possibly quoted filename argument. This commit doesn't add the remove-symbol-file completer, this commit is just about putting support for that in place. To achieve this I've added the new function advance_to_filename_maybe_quoted_complete_word_point, which is unused in this commit. I've then had to extend some other functions in order to extract the quoting state during the brkchars phase. As this commit doesn't use the new functionality, the important thing at this point is that I've not regressed the existing filename completion (or any of the other completion). The next commit in this series will make use of the new functionality, and will include tests. There should be no user visible changes after this commit. --- gdb/completer.c | 98 +++++++++++++++++++++++++++++++++++++++++-------- gdb/completer.h | 8 ++++ 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/gdb/completer.c b/gdb/completer.c index b80649c5260..e8f5e7bb577 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -730,13 +730,23 @@ gdb_rl_find_completion_word (struct gdb_rl_completion_word_info *info, /* Find the completion word point for TEXT, emulating the algorithm readline uses to find the word point, using WORD_BREAK_CHARACTERS - as word break characters. */ + as word break characters. + + The output argument *FOUND_ANY_QUOTING is set to true if the completion + word found either has an opening quote, or contains backslash escaping + within it. Otherwise *FOUND_ANY_QUOTING is set to false. + + The output argument *QC is set to the opening quote character for the + completion word that is found, or to the null character if there is no + opening quote. */ static const char * advance_to_completion_word (completion_tracker &tracker, const char *word_break_characters, const char *quote_characters, - const char *text) + const char *text, + bool *found_any_quoting, + int *qc) { gdb_rl_completion_word_info info; @@ -746,7 +756,8 @@ advance_to_completion_word (completion_tracker &tracker, int delimiter; const char *start - = gdb_rl_find_completion_word (&info, nullptr, &delimiter, nullptr, text); + = gdb_rl_find_completion_word (&info, qc, &delimiter, found_any_quoting, + text); tracker.advance_custom_word_point_by (start - text); @@ -767,18 +778,54 @@ advance_to_expression_complete_word_point (completion_tracker &tracker, { const char *brk_chars = current_language->word_break_characters (); const char *quote_chars = gdb_completer_expression_quote_characters; - return advance_to_completion_word (tracker, brk_chars, quote_chars, text); + return advance_to_completion_word (tracker, brk_chars, quote_chars, + text, nullptr, nullptr); } /* See completer.h. */ const char * -advance_to_deprecated_filename_complete_word_point +advance_to_filename_maybe_quoted_complete_word_point (completion_tracker &tracker, const char *text) +{ + const char *brk_chars = gdb_completer_file_name_break_characters; + const char *quote_chars = gdb_completer_file_name_quote_characters; + rl_char_is_quoted_p = gdb_completer_file_name_char_is_quoted; + bool found_any_quoting = false; + int qc; + const char *result + = advance_to_completion_word (tracker, brk_chars, quote_chars, + text, &found_any_quoting, &qc); + rl_completion_found_quote = found_any_quoting ? 1 : 0; + if (qc != '\0') + { + tracker.set_quote_char (qc); + /* If we're completing for readline (not the 'complete' command) then + we want readline to correctly detect the opening quote. The set + of quote characters will have been set during the brkchars phase, + so now we move the word point back by one (so it's pointing at + the quote character) and now readline will correctly spot the + opening quote. For the 'complete' command setting the quote + character in the tracker is enough, so there's no need to move + the word point back here. */ + if (tracker.from_readline ()) + tracker.advance_custom_word_point_by (-1); + } + return result; +} + +/* See completer.h. */ + +const char * +advance_to_deprecated_filename_complete_word_point (completion_tracker &tracker, + const char *text) { const char *brk_chars = gdb_completer_path_break_characters; const char *quote_chars = nullptr; - return advance_to_completion_word (tracker, brk_chars, quote_chars, text); + rl_filename_quoting_desired = 0; + + return advance_to_completion_word (tracker, brk_chars, quote_chars, + text, nullptr, nullptr); } /* See completer.h. */ @@ -2283,7 +2330,21 @@ gdb_completion_word_break_characters_throw () gdb_custom_word_point_brkchars[0] = rl_line_buffer[rl_point]; rl_completer_word_break_characters = gdb_custom_word_point_brkchars; - rl_completer_quote_characters = NULL; + + /* When performing filename completion we have two options, unquoted + filename completion, in which case the quote characters will have + already been set to nullptr, or quoted filename completion in + which case the quote characters will be set to a string of + characters. In this second case we need readline to perform the + check for a quoted string so that it sets its internal notion of + the quote character correctly, this allows readline to correctly + add the trailing quote (if necessary) after completing a + filename. + + For non-filename completion we manually add a trailing quote if + needed, so we clear the quote characters set here. */ + if (!rl_filename_completion_desired) + rl_completer_quote_characters = NULL; /* Clear this too, so that if we're completing a quoted string, readline doesn't consider the quote character a delimiter. @@ -2330,7 +2391,12 @@ gdb_completion_word_break_characters () noexcept handle_brkchars phase (using TRACKER) to figure out the right work break characters for the command in TEXT. QUOTE_CHAR, if non-null, is set to the opening quote character if we found an unclosed quoted substring, - '\0' otherwise. */ + '\0' otherwise. + + The argument *FOUND_ANY_QUOTING is set to true if the completion word is + either surrounded by quotes, or contains any backslash escapes, but is + only set if TRACKER.use_custom_word_point() is false, otherwise + *FOUND_ANY_QUOTING is just set to false. */ static const char * completion_find_completion_word (completion_tracker &tracker, const char *text, @@ -2344,13 +2410,12 @@ completion_find_completion_word (completion_tracker &tracker, const char *text, { gdb_assert (tracker.custom_word_point () > 0); *quote_char = tracker.quote_char (); - /* This isn't really correct, we're ignoring the case where we found - a backslash escaping a character. However, this isn't an issue - right now as we only rely on *FOUND_ANY_QUOTING being set when - performing filename completion, which doesn't go through this - path. */ + /* If use_custom_word_point is set then the completions have already + been calculated, in which case we don't need to have this flag + set correctly, which is lucky as we don't currently have any way + to know if the completion word included any backslash escapes. */ if (found_any_quoting != nullptr) - *found_any_quoting = *quote_char != '\0'; + *found_any_quoting = false; return text + tracker.custom_word_point (); } @@ -2527,7 +2592,10 @@ completion_tracker::build_completion_result (const char *text, { bool completion_suppress_append; - if (from_readline ()) + /* For filename completion we rely on readline to append the closing + quote. While for other types of completion we append the closing + quote here. */ + if (from_readline () && !rl_filename_completion_desired) { /* We don't rely on readline appending the quote char as delimiter as then readline wouldn't append the ' ' after the diff --git a/gdb/completer.h b/gdb/completer.h index c18bd16ad26..44eafc487f7 100644 --- a/gdb/completer.h +++ b/gdb/completer.h @@ -618,6 +618,14 @@ const char *advance_to_expression_complete_word_point extern const char *advance_to_deprecated_filename_complete_word_point (completion_tracker &tracker, const char *text); +/* Assuming TEXT is a filename, find the completion word point for TEXT, + emulating the algorithm readline uses to find the word point. The + filenames that are located by this function assume that filenames + can be quoted, this function should be paired with + filename_maybe_quoted_completer. */ +extern const char *advance_to_filename_maybe_quoted_complete_word_point + (completion_tracker &tracker, const char *text); + extern void noop_completer (struct cmd_list_element *, completion_tracker &tracker, const char *, const char *); -- 2.25.4