From patchwork Mon Sep 22 18:00:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 390 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758564116; bh=+DCbGlA9EZRqIhDuhnii+ZA7CNCZRXxZqCr507nxogM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iwTkc/qUyUx8zqdTImVVdWbg4Hgs6XlHAvhrRFz8hUeKbJhprLpliBpshUcSwkSqO X6ZiJbLS1pTRCPUL0PX/2uuCfkZuPJQuKAGSKBmy7kpCFA6wSKGsgN75zai4lza2ga tXYQBrps3EimMwVlzqwtwTDWbgnDSi6XYVsKQq/6kA04C7Ye7msRnl0d8MobRMm74w eJbnTDGe7PGBSXqVeOXkzcFL2h2VY1MlvGO4cEsXa1bpkwP32gg//+nQMMk0Q7ddCe TfbqRE8xx1DLjPmYNXIlhcWV5DurpO6EwSOCkSDxM9d4c4jE33qGLlr10dB79sfltC xGiJI8yC/VhZA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 2D1F867C65 for ; Mon, 22 Sep 2025 12:01:56 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id AquCIukwkRd1 for ; Mon, 22 Sep 2025 12:01:56 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758564116; bh=+DCbGlA9EZRqIhDuhnii+ZA7CNCZRXxZqCr507nxogM=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=iwTkc/qUyUx8zqdTImVVdWbg4Hgs6XlHAvhrRFz8hUeKbJhprLpliBpshUcSwkSqO X6ZiJbLS1pTRCPUL0PX/2uuCfkZuPJQuKAGSKBmy7kpCFA6wSKGsgN75zai4lza2ga tXYQBrps3EimMwVlzqwtwTDWbgnDSi6XYVsKQq/6kA04C7Ye7msRnl0d8MobRMm74w eJbnTDGe7PGBSXqVeOXkzcFL2h2VY1MlvGO4cEsXa1bpkwP32gg//+nQMMk0Q7ddCe TfbqRE8xx1DLjPmYNXIlhcWV5DurpO6EwSOCkSDxM9d4c4jE33qGLlr10dB79sfltC xGiJI8yC/VhZA== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 1B2B467C55 for ; Mon, 22 Sep 2025 12:01:56 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758564114; bh=RUAsu/EBlmHOpGxHFenUTzPKhqlP7BF35aGgdwqwRfQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J9tnMjPE8dfctDprzh1QSibMcsDAZ3QyDvBhSOxEJLL0l+SAnUiEAziT2bsUpFCQ/ uyuM0jhAt9vg/nGxWJxh3370Ft7RgA9LaldTVI1h24WvV1ABhthfCXxprMLOIKLn6V pib36Jisi5sKWjRG8OlT+L+wfY3yOe+qFCC94lD8qehYKgNFfE8RcJXbNGpuT+MO17 gdthG6LPuAl++x3Q8jCltqZg3ud1WuQTYqXXKPkOvVl3R1h3VLEQsv9dGnYNcT/jAm LMEaXYaYo03+gHPENKZbxP5Kht/UEK6Gjh3T2CBOIR4VKs9rol+KtMjJcduOcFqy1s NdFCz8lGkxT+Q== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 334DB67C52; Mon, 22 Sep 2025 12:01:54 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id 8wPIhR2ReEhn; Mon, 22 Sep 2025 12:01:54 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1758564110; bh=YpfR/4IkCxfR5qdFYzpIo7GgTvuv3uJsMVmM/+6r2ho=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=e1bMaxKyhUb8UD/BGuReBBG0TIaENg+ACA42VbBy4h4/UP6PPcwjtnDGTCDRgbqY7 WpQ3LL9wAzMqeudgKBDX/gdhmsli8p3AsnUCQgIpzdxkKQ+LPmv+I9pW81NZNMac6K vhYybsau/mX5dSj/tH965DAIhNXOtz8i7jbHTfLcPEoX+ya+Op51N5ORvej36pUk/M uH7ruqX/dUL9mdvxF3WjyZuPj56tWqH7r2FcKrNW66VUvS1C256slDUIIozwHOXJe9 iTtxDTYWBy4cQXpRhHY4DWzE71kPGjmMFPXa5OlicxC9dv2h3S7MmnOuuuyAdUPJ7X 48CJ+ESp4fJCg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id D069B67B38; Mon, 22 Sep 2025 12:01:49 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Mon, 22 Sep 2025 12:00:50 -0600 Message-ID: <20250922180116.3088502-7-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250922180116.3088502-1-sjg@u-boot.org> References: <20250922180116.3088502-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: 3OPCYJA6MFQRBDRM7XR35PNHWL6NB2JX X-Message-ID-Hash: 3OPCYJA6MFQRBDRM7XR35PNHWL6NB2JX X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 06/24] console: Add a way to quit pager with no further output List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass Add support for pressing 'q' to throw away any further output until the prompt is reached. Signed-off-by: Simon Glass --- common/cli_readline.c | 1 + common/pager.c | 19 +++++++++++++++++ doc/usage/console.rst | 3 ++- include/pager.h | 20 +++++++++++++++++- test/common/pager.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/common/cli_readline.c b/common/cli_readline.c index dc27a962e9d..244a287b435 100644 --- a/common/cli_readline.c +++ b/common/cli_readline.c @@ -654,6 +654,7 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer, static int initted; bool old_bypass; + pager_clear_quit(gd_pager()); old_bypass = pager_set_bypass(gd_pager(), true); /* diff --git a/common/pager.c b/common/pager.c index c0a55b738b9..60b1adc8571 100644 --- a/common/pager.c +++ b/common/pager.c @@ -24,6 +24,9 @@ const char *pager_post(struct pager *pag, bool use_pager, const char *s) pag->state == PAGERST_BYPASS) return s; + if (pag->state == PAGERST_QUIT_SUPPRESS) + return NULL; + len = strlen(s); if (!len) return NULL; @@ -75,6 +78,10 @@ const char *pager_next(struct pager *pag, bool use_pager, int key) pag->state = PAGERST_BYPASS; return PAGER_BLANK; } + if (key == 'q') { + pag->state = PAGERST_QUIT_SUPPRESS; + return "\r \r"; + } if (key != ' ') return PAGER_WAITING; pag->state = PAGERST_CLEAR_PROMPT; @@ -84,6 +91,9 @@ const char *pager_next(struct pager *pag, bool use_pager, int key) break; case PAGERST_BYPASS: break; + case PAGERST_QUIT_SUPPRESS: + membuf_purge(&pag->mb); + return NULL; } ret = membuf_getraw(&pag->mb, pag->buf.size - 1, false, &str); @@ -176,6 +186,15 @@ void pager_reset(struct pager *pag) pag->line_count = 0; } +void pager_clear_quit(struct pager *pag) +{ + if (!pag) + return; + + if (pag->state == PAGERST_QUIT_SUPPRESS) + pag->state = PAGERST_OK; +} + static int on_pager(const char *name, const char *value, enum env_op op, int flags) { diff --git a/doc/usage/console.rst b/doc/usage/console.rst index 880a5b7b605..088760c6f86 100644 --- a/doc/usage/console.rst +++ b/doc/usage/console.rst @@ -70,7 +70,8 @@ only available if `CONFIG_CONSOLE_MUX` is also enabled. When activated, the pager pauses at the end of each 'page' (screenful) of output, shows a prompt ": Press SPACE to continue" and lets the user read the -output. To continue to the next page, press the SPACE key. +output. To continue to the next page, press the SPACE key. To quit paging +without seeing further output from the current command, press 'q'. The pager can be bypassed by pressing 'Q' at the prompt. This disables the pager until the 'pager' environment variable is given a new value. diff --git a/include/pager.h b/include/pager.h index 887f5d1f639..3f13f82885d 100644 --- a/include/pager.h +++ b/include/pager.h @@ -33,6 +33,7 @@ * @PAGERST_WAIT_USER: Waiting for the user to press a key * @PAGERST_CLEAR_PROMPT: Clearing the prompt ready for more output * @PAGERST_BYPASS: Pager is being bypassed + * @PAGERST_QUIT_SUPPRESS: Output is being suppressed after 'q' keypress */ enum pager_state { PAGERST_OK, @@ -40,6 +41,7 @@ enum pager_state { PAGERST_WAIT_USER, PAGERST_CLEAR_PROMPT, PAGERST_BYPASS, + PAGERST_QUIT_SUPPRESS, }; /** @@ -112,7 +114,8 @@ const char *pager_post(struct pager *pag, bool use_pager, const char *s); * * When the pager prompts for user input, pressing SPACE continues to the next * page, while pressing capital 'Q' puts the pager into bypass mode and - * disables further paging. + * disables further paging. Pressing 'q' quits and suppresses all output until + * the next command prompt. * * @pag: Pager to use * @use_pager: Whether or not to use the pager functionality @@ -157,6 +160,17 @@ bool pager_set_test_bypass(struct pager *pag, bool bypass); */ void pager_reset(struct pager *pag); +/** + * pager_clear_quit() - Clear quit suppression mode + * + * If the pager is in PAGERST_QUIT_SUPPRESS state, this resets it to normal + * operation (PAGERST_OK). This is typically called at the start of + * cli_readline_into_buffer() to allow new commands to display output normally. + * + * @pag: Pager to update, may be NULL in which case this function does nothing + */ +void pager_clear_quit(struct pager *pag); + /** * pager_uninit() - Uninit the pager * @@ -188,6 +202,10 @@ static inline bool pager_set_test_bypass(struct pager *pag, bool bypass) return true; } +static inline void pager_clear_quit(struct pager *pag) +{ +} + static inline void pager_reset(struct pager *pag) { } diff --git a/test/common/pager.c b/test/common/pager.c index 636069d5b37..ccd5230f3a4 100644 --- a/test/common/pager.c +++ b/test/common/pager.c @@ -618,3 +618,50 @@ static int pager_test_bypass_keypress(struct unit_test_state *uts) return 0; } COMMON_TEST(pager_test_bypass_keypress, 0); + +/* Test quit keypress ('q') functionality */ +static int pager_test_quit_keypress(struct unit_test_state *uts) +{ + struct pager *pag; + const char *out; + int ret; + + ret = pager_init(&pag, 3, SZ_1K); + ut_assertok(ret); + + /* Post text that will trigger paging */ + out = pager_post(pag, true, "line1\nline2\nline3\nline4\n"); + ut_assertnonnull(out); + ut_asserteq_str("line1\nline2", out); + + /* Should be waiting for user input */ + out = pager_next(pag, true, 0); + ut_asserteq_str(PAGER_PROMPT, out); + + /* Press 'q' to quit and suppress */ + out = pager_next(pag, true, 'q'); + ut_asserteq_str("\r \r", out); + + /* Verify pager is now in quit suppress mode */ + ut_asserteq(PAGERST_QUIT_SUPPRESS, pag->state); + + /* Next call should return NULL (suppressed) */ + out = pager_next(pag, true, 0); + ut_asserteq_ptr(NULL, out); + + /* Posting new text should also return NULL (suppressed) */ + out = pager_post(pag, true, "new text\n"); + ut_asserteq_ptr(NULL, out); + + /* Test that pager_clear_quit() restores normal operation */ + pager_clear_quit(pag); + ut_asserteq(PAGERST_OK, pag->state); + + /* and that any new test appears */ + out = pager_post(pag, true, "more new text\n"); + ut_asserteq_str("more new text\n", out); + + pager_uninit(pag); + return 0; +} +COMMON_TEST(pager_test_quit_keypress, 0);