From patchwork Tue Jun 4 22:34:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 33009 Received: (qmail 67431 invoked by alias); 4 Jun 2019 22:44:29 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 67420 invoked by uid 89); 4 Jun 2019 22:44:29 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=sk:custom, sk:custom- X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 04 Jun 2019 22:44:28 +0000 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 07CDAA6DEF for ; Tue, 4 Jun 2019 22:35:20 +0000 (UTC) Received: from localhost.localdomain (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8FFF319C69 for ; Tue, 4 Jun 2019 22:35:19 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH v3 19/24] Introduce complete_nested_command_line Date: Tue, 4 Jun 2019 23:34:39 +0100 Message-Id: <20190604223444.26472-20-palves@redhat.com> In-Reply-To: <20190604223444.26472-1-palves@redhat.com> References: <20190604223444.26472-1-palves@redhat.com> This adds a completion helper routine that makes it possible for a command that takes another command as argument, such as "frame apply all COMMAND" as "thread apply all COMMAND", to complete on COMMAND, and have the completion machinery recurse and complete COMMAND as if you tried to complete "(gdb) COMMAND". I.e., we'll be able to complete like this, for example: (gdb) thread apply all -[TAB] -c -ascending -q -s (gdb) thread apply all -ascending frame apply all -[TAB] -c -limit -past-entry -past-main -q -s (gdb) thread apply all -ascending frame apply all -past-main print -[TAB] -address -elements -pretty -symbol -array -null-stop -repeats -union -array-indexes -object -static-members -vtbl (gdb) thread apply all -ascending frame apply all -past-main print glo[TAB] global1 global2 Above, the completer function understands that "thread apply all" is a command, and then parses "-ascending" successfully and understand that the rest of the string is "thread apply all"'s operand. And then, the process repeats for the "frame apply" command, and on and on. gdb/ChangeLog: yyyy-mm-dd Pedro Alves * completer.c (complete_nested_command_line): New. (gdb_completion_word_break_characters_throw): Add assertion. * completer.h (complete_nested_command_line): Declare. --- gdb/completer.c | 36 ++++++++++++++++++++++++++++++++++++ gdb/completer.h | 12 ++++++++++++ 2 files changed, 48 insertions(+) diff --git a/gdb/completer.c b/gdb/completer.c index 0f4e7f9ca75..6892a62bb91 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -423,6 +423,39 @@ completion_tracker::completes_to_completion_word (const char *word) return false; } +/* See completer.h. */ + +void +complete_nested_command_line (completion_tracker &tracker, const char *text) +{ + /* Must be called from a custom-word-point completer. */ + gdb_assert (tracker.use_custom_word_point ()); + + /* Disable the custom word point temporarily, because we want to + probe whether the command we're completing itself uses a custom + word point. */ + tracker.set_use_custom_word_point (false); + size_t save_custom_word_point = tracker.custom_word_point (); + + int quote_char = '\0'; + const char *word = completion_find_completion_word (tracker, text, + "e_char); + + if (tracker.use_custom_word_point ()) + { + /* The command we're completing uses a custom word point, so the + tracker already contains the matches. We're done. */ + return; + } + + /* Restore the custom word point settings. */ + tracker.set_custom_word_point (save_custom_word_point); + tracker.set_use_custom_word_point (true); + + /* Run the handle_completions completer phase. */ + complete_line (tracker, word, text, strlen (text)); +} + /* Complete on linespecs, which might be of two possible forms: file:line @@ -1894,6 +1927,9 @@ gdb_completion_word_break_characters_throw () { gdb_assert (tracker.custom_word_point () > 0); rl_point = tracker.custom_word_point () - 1; + + gdb_assert (rl_point >= 0 && rl_point < strlen (rl_line_buffer)); + 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; diff --git a/gdb/completer.h b/gdb/completer.h index 58fe84f4fee..9f8ec47c9f1 100644 --- a/gdb/completer.h +++ b/gdb/completer.h @@ -611,6 +611,18 @@ extern completion_list complete_source_filenames (const char *text); extern void complete_expression (completion_tracker &tracker, const char *text, const char *word); +/* Called by custom word point completers that want to recurse into + the completion machinery to complete a command. Used to complete + COMMAND in "thread apply all COMMAND", for example. Note that + unlike command_completer, this fully recurses into the proper + completer for COMMAND, so that e.g., + + (gdb) thread apply all print -[TAB] + + does the right thing and show the print options. */ +extern void complete_nested_command_line (completion_tracker &tracker, + const char *text); + extern const char *skip_quoted_chars (const char *, const char *, const char *);