console: Provide a way to output without the pager

Sometimes output should be sent ignoring the pager, such as when it is
a message related to paging. Add a parameter to support this.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-08-21 18:06:07 -06:00
parent 4a74dee5ce
commit 984b363d02
3 changed files with 113 additions and 38 deletions

View File

@@ -14,12 +14,12 @@
DECLARE_GLOBAL_DATA_PTR;
const char *pager_post(struct pager *pag, const char *s)
const char *pager_post(struct pager *pag, bool use_pager, const char *s)
{
struct membuf old;
int ret, len;
if (!pag)
if (!pag || !use_pager)
return s;
len = strlen(s);
@@ -44,14 +44,17 @@ const char *pager_post(struct pager *pag, const char *s)
pag->mb = old;
}
return pager_next(pag, 0);
return pager_next(pag, true, 0);
}
const char *pager_next(struct pager *pag, int key)
const char *pager_next(struct pager *pag, bool use_pager, int key)
{
char *str, *p, *end;
int ret;
if (!use_pager)
return NULL;
/* replace the real character we overwrite with nul, if needed */
if (pag->nulch) {
*pag->nulch = pag->oldch;

View File

@@ -81,7 +81,7 @@ struct pager {
/**
* pager_post() - Add text to the input buffer for later handling
*
* The text is added to the pager buffer and fed out a screenful
* If @use_pager the text is added to the pager buffer and fed out a screenful
* at a time. This function calls pager_post() after storing the text.
*
* After calling pager_post(), if it returns anything other than NULL, you must
@@ -91,10 +91,12 @@ struct pager {
* If @pag is NULL, this does nothing but return @s
*
* @pag: Pager to use, may be NULL
* @use_pager: Whether or not to use the pager functionality
* @s: Text to add
* Return: text which should be sent to output, or NULL if there is no more.
* If !@use_pager this just returns @s and does not affect the pager state
*/
const char *pager_post(struct pager *pag, const char *s);
const char *pager_post(struct pager *pag, bool use_pager, const char *s);
/**
* pager_next() - Returns the next screenful of text to show
@@ -105,12 +107,14 @@ const char *pager_post(struct pager *pag, const char *s);
* return PAGER_WAITING until @ch is non-zero.
*
* @pag: Pager to use
* @use_pager: Whether or not to use the pager functionality
* @ch: Key that the user has pressed, or 0 if none
*
* Return: text which should be sent to output, or PAGER_WAITING if waiting for
* the user to press a key, or NULL if there is no more text.
* If !@use_pager this just returns NULL and does not affect the pager state
*/
const char *pager_next(struct pager *pag, int ch);
const char *pager_next(struct pager *pag, bool use_pager, int ch);
/**
* pager_uninit() - Uninit the pager
@@ -122,12 +126,13 @@ const char *pager_next(struct pager *pag, int ch);
void pager_uninit(struct pager *pag);
#else
static inline const char *pager_post(struct pager *pag, const char *s)
static inline const char *pager_post(struct pager *pag, bool use_pager,
const char *s)
{
return s;
}
static inline const char *pager_next(struct pager *pag, int ch)
static inline const char *pager_next(struct pager *pag, bool use_pager, int ch)
{
return NULL;
}

View File

@@ -50,12 +50,12 @@ static int pager_test_simple_text(struct unit_test_state *uts)
ut_assertok(pager_init(&pag, 20, 1024));
/* Post some text and get it back */
result = pager_post(pag, text);
result = pager_post(pag, true, text);
ut_assertnonnull(result);
ut_asserteq_str(text, result);
/* Should be no more text */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnull(result);
pager_uninit(pag);
@@ -79,28 +79,28 @@ static int pager_test_multiline(struct unit_test_state *uts)
ut_assertok(pager_init(&pag, 20, 1024));
/* Post multiple pieces of text */
result = pager_post(pag, text1);
result = pager_post(pag, true, text1);
ut_assertnonnull(result);
ut_asserteq_str(text1, result);
/* Should be no more text after first post */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnull(result);
result = pager_post(pag, text2);
result = pager_post(pag, true, text2);
ut_assertnonnull(result);
ut_asserteq_str(text2, result);
/* Should be no more text after second post */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnull(result);
result = pager_post(pag, text3);
result = pager_post(pag, true, text3);
ut_assertnonnull(result);
ut_asserteq_str(text3, result);
/* Should be no more text after third post */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnull(result);
pager_uninit(pag);
@@ -121,10 +121,10 @@ static int pager_test_large_text(struct unit_test_state *uts)
ut_assertok(pager_init(&pag, 20, 16)); /* Small buffer */
/* Post large text - should fit in buffer */
result = pager_post(pag, "this is 16 chars");
result = pager_post(pag, true, "this is 16 chars");
ut_assertnonnull(result);
ut_asserteq_str("this is 16 chars", result);
ut_assertnull(pager_next(pag, 0));
ut_assertnull(pager_next(pag, true, 0));
pager_uninit(pag);
@@ -141,12 +141,12 @@ static int pager_test_overflow(struct unit_test_state *uts)
ut_assertok(pager_init(&pag, 20, 4)); /* Small buffer */
/* send some text which is too long for the buffer */
result = pager_post(pag, "test1");
result = pager_post(pag, true, "test1");
ut_assertnonnull(result);
/* overflow handling should return the text */
ut_asserteq_str("test1", result);
ut_assertnull(pager_next(pag, 0));
ut_assertnull(pager_next(pag, true, 0));
pager_uninit(pag);
@@ -160,7 +160,7 @@ static int pager_test_null_input(struct unit_test_state *uts)
const char *result;
/* Test pager_post with NULL pager */
result = pager_post(NULL, "test");
result = pager_post(NULL, true, "test");
ut_asserteq_str("test", result);
return 0;
@@ -176,11 +176,11 @@ static int pager_test_empty_strings(struct unit_test_state *uts)
ut_assertok(pager_init(&pag, 20, 1024));
/* Post empty string */
result = pager_post(pag, "");
result = pager_post(pag, true, "");
ut_assertnull(result);
/* Should be no more text */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnull(result);
pager_uninit(pag);
@@ -203,7 +203,7 @@ static int pager_test_buffer_management(struct unit_test_state *uts)
ut_asserteq(1024, pag->buf.size);
/* Post text and verify buffer state */
result = pager_post(pag, text);
result = pager_post(pag, true, text);
ut_assertnonnull(result);
/* Verify the buffer contains our text */
@@ -229,7 +229,7 @@ static int pager_test_long_single_line(struct unit_test_state *uts)
long_line[sizeof(long_line) - 1] = '\0';
/* Post the long line */
result = pager_post(pag, long_line);
result = pager_post(pag, true, long_line);
ut_assertnonnull(result);
/* Should get our text back */
@@ -252,7 +252,7 @@ static int pager_test_line_counting(struct unit_test_state *uts)
ut_assertok(pager_init(&pag, 4, 1024));
/* Post multiline text */
result = pager_post(pag, multiline_text);
result = pager_post(pag, true, multiline_text);
ut_assertnonnull(result);
/* Should get first 3 lines (excluding the 3rd newline) */
@@ -261,22 +261,22 @@ static int pager_test_line_counting(struct unit_test_state *uts)
ut_asserteq(0, pag->line_count);
/* Next call should return pager prompt */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnonnull(result);
ut_asserteq_str(PAGER_PROMPT, result);
/* Press space to continue */
result = pager_next(pag, ' ');
result = pager_next(pag, true, ' ');
ut_assertnonnull(result);
ut_asserteq_str(PAGER_BLANK, result);
/* Get remaining lines */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnonnull(result);
ut_asserteq_str("Line 4\nLine 5\n", result);
/* Should be no more text */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnull(result);
pager_uninit(pag);
@@ -295,30 +295,30 @@ static int pager_test_pager_waiting(struct unit_test_state *uts)
ut_assertok(pager_init(&pag, 3, 1024));
/* Post text that fills exactly the page limit */
result = pager_post(pag, "Line 1\nLine 2\n");
result = pager_post(pag, true, "Line 1\nLine 2\n");
ut_assertnonnull(result);
ut_asserteq_str("Line 1\nLine 2", result);
/* Next call should return the prompt */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnonnull(result);
ut_asserteq_str(PAGER_PROMPT, result);
/* Next call without space key should return PAGER_WAITING */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_asserteq_ptr(PAGER_WAITING, result);
/* Another call without space should still return PAGER_WAITING */
result = pager_next(pag, 'x'); /* Wrong key */
result = pager_next(pag, true, 'x'); /* Wrong key */
ut_asserteq_ptr(PAGER_WAITING, result);
/* Pressing space should clear the prompt */
result = pager_next(pag, ' ');
result = pager_next(pag, true, ' ');
ut_assertnonnull(result);
ut_asserteq_str("\r \r", result);
ut_asserteq_str(PAGER_BLANK, result);
/* Now should return NULL (no more content) */
result = pager_next(pag, 0);
result = pager_next(pag, true, 0);
ut_assertnull(result);
pager_uninit(pag);
@@ -326,3 +326,70 @@ static int pager_test_pager_waiting(struct unit_test_state *uts)
return 0;
}
COMMON_TEST(pager_test_pager_waiting, 0);
/* Test use_pager parameter - output text directly, while buffer is non-empty */
static int pager_test_use_pager_param(struct unit_test_state *uts)
{
struct pager *pag;
const char *buffered_text = "Line 1\nLine 2\nLine 3\nLine 4\nLine 5\n";
const char *direct_text = "This should be written immediately";
const char *result;
/* Init with small page length to ensure paging occurs */
ut_assertok(pager_init(&pag, 3, 1024));
/* Post text with use_pager=true - should trigger paging */
result = pager_post(pag, true, buffered_text);
ut_assertnonnull(result);
/* Should get first 2 lines */
ut_asserteq_str("Line 1\nLine 2", result);
/* Now call pager_post with use_pager=false while text is still buffered */
result = pager_post(pag, false, direct_text);
/* Should get the text immediately, not from buffer */
ut_asserteq_ptr(direct_text, result);
/* Call pager_next with use_pager=false - should return NULL */
result = pager_next(pag, false, 0);
ut_assertnull(result);
/* Now continue with use_pager=true to get buffered text */
result = pager_next(pag, true, 0);
ut_assertnonnull(result);
/* Should get the pager prompt */
ut_asserteq_str(PAGER_PROMPT, result);
/* Press space to continue */
result = pager_next(pag, true, ' ');
ut_assertnonnull(result);
ut_asserteq_str(PAGER_BLANK, result);
/* Get remaining buffered lines - should be next 2 lines due to page limit */
result = pager_next(pag, true, 0);
ut_assertnonnull(result);
ut_asserteq_str("Line 3\nLine 4", result);
/* Should get pager prompt again */
result = pager_next(pag, true, 0);
ut_assertnonnull(result);
ut_asserteq_str(PAGER_PROMPT, result);
/* Press space to continue */
result = pager_next(pag, true, ' ');
ut_assertnonnull(result);
ut_asserteq_str(PAGER_BLANK, result);
/* Get final line */
result = pager_next(pag, true, 0);
ut_assertnonnull(result);
ut_asserteq_str("Line 5\n", result);
/* Should be no more text */
result = pager_next(pag, true, 0);
ut_assertnull(result);
pager_uninit(pag);
return 0;
}
COMMON_TEST(pager_test_use_pager_param, 0);