aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Luke <chrisy@flirble.org>2016-05-14 10:13:34 -0400
committerFlorin Coras <florin.coras@gmail.com>2016-05-16 21:37:00 +0000
commit862623da6eb3dfb211f5ed03ce063137d3f2242e (patch)
tree29b157792690407c37cb51ed7c726e0a7dcc1719
parente7a40e86b1f7f2325ebcff1d2506ef6a81536955 (diff)
VPP-23 Re-work pager line collationv16.09-rc0
To better handle lines longer than the terminal width, re-work how the pager collates lines. We still store each output line in a vector or lines; additionally we index the start and end of displayable lines. The index then becomes the data to work out what to display. If the terminal is resized this index is rebuilt and the current page redisplayed and an attempt made to keep the current top-of-screen line in place. Change-Id: Icc6f4f72dabad89682cd82be88adb03eadb7811d Signed-off-by: Chris Luke <chrisy@flirble.org>
-rw-r--r--vlib/vlib/unix/cli.c452
1 files changed, 364 insertions, 88 deletions
diff --git a/vlib/vlib/unix/cli.c b/vlib/vlib/unix/cli.c
index 70ffdec74b9..c34ae219297 100644
--- a/vlib/vlib/unix/cli.c
+++ b/vlib/vlib/unix/cli.c
@@ -116,6 +116,18 @@ _("\n")
};
#undef _
+/** Pager line index */
+typedef struct {
+ /** Index into pager_vector */
+ u32 line;
+
+ /** Offset of the string in the line */
+ u32 offset;
+
+ /** Length of the string in the line */
+ u32 length;
+} unix_cli_pager_index_t;
+
/** Unix CLI session. */
typedef struct {
@@ -164,8 +176,8 @@ typedef struct {
/** Pager buffer */
u8 ** pager_vector;
- /** Lines currently displayed */
- u32 pager_lines;
+ /** Index of line fragments in the pager buffer */
+ unix_cli_pager_index_t * pager_index;
/** Line number of top of page */
u32 pager_start;
@@ -188,12 +200,16 @@ unix_cli_pager_reset (unix_cli_file_t *f)
{
u8 ** p;
- f->pager_lines = f->pager_start = 0;
+ f->pager_start = 0;
+
+ vec_free (f->pager_index);
+ f->pager_index = 0;
+
vec_foreach (p, f->pager_vector)
{
- vec_free(*p);
+ vec_free (*p);
}
- vec_free(f->pager_vector);
+ vec_free (f->pager_vector);
f->pager_vector = 0;
}
@@ -205,7 +221,7 @@ unix_cli_file_free (unix_cli_file_t * f)
{
vec_free (f->output_vector);
vec_free (f->input_vector);
- unix_cli_pager_reset(f);
+ unix_cli_pager_reset (f);
}
/** CLI actions */
@@ -240,6 +256,7 @@ typedef enum {
UNIX_CLI_PARSE_ACTION_PAGER_BOTTOM,
UNIX_CLI_PARSE_ACTION_PAGER_PGDN,
UNIX_CLI_PARSE_ACTION_PAGER_PGUP,
+ UNIX_CLI_PARSE_ACTION_PAGER_REDRAW,
UNIX_CLI_PARSE_ACTION_PAGER_SEARCH,
UNIX_CLI_PARSE_ACTION_PARTIALMATCH,
@@ -344,6 +361,8 @@ static unix_cli_parse_actions_t unix_cli_parse_pager[] = {
/* Pager commands */
_( " ", UNIX_CLI_PARSE_ACTION_PAGER_NEXT ),
_( "q", UNIX_CLI_PARSE_ACTION_PAGER_QUIT ),
+ _( CTL('L'), UNIX_CLI_PARSE_ACTION_PAGER_REDRAW ),
+ _( CTL('R'), UNIX_CLI_PARSE_ACTION_PAGER_REDRAW ),
_( "/", UNIX_CLI_PARSE_ACTION_PAGER_SEARCH ),
/* VT100 */
@@ -615,7 +634,7 @@ static void unix_cli_pager_prompt(unix_cli_file_t * cf, unix_file_t * uf)
cf->ansi_capable ? ANSI_BOLD : "",
cf->pager_start + 1,
cf->pager_start + cf->height,
- cf->pager_lines,
+ vec_len (cf->pager_index),
cf->ansi_capable ? ANSI_RESET: "");
unix_vlib_cli_output_cooked(cf, uf, prompt, vec_len(prompt));
@@ -673,7 +692,205 @@ static void unix_cli_ansi_cursor(unix_cli_file_t * cf, unix_file_t * uf,
vec_free(str);
}
-/** \brief VLIB CLI output function. */
+/** Redraw the currently displayed page of text.
+ * @param cf CLI session to redraw the pager buffer of.
+ * @param uf Unix file of the CLI session.
+ */
+static void unix_cli_pager_redraw(unix_cli_file_t * cf, unix_file_t * uf)
+{
+ unix_cli_pager_index_t * pi = NULL;
+ u8 * line = NULL;
+ word i;
+
+ /* No active pager? Do nothing. */
+ if (!vec_len (cf->pager_index))
+ return;
+
+ if (cf->ansi_capable)
+ {
+ /* If we have ANSI, send the clear screen sequence */
+ unix_vlib_cli_output_cooked (cf, uf,
+ (u8 *)ANSI_CLEAR, sizeof(ANSI_CLEAR) - 1);
+ }
+ else
+ {
+ /* Otherwise make sure we're on a blank line */
+ unix_cli_pager_prompt_erase (cf, uf);
+ }
+
+ /* (Re-)send the current page of content */
+ for (i = 0; i < cf->height - 1 &&
+ i + cf->pager_start < vec_len (cf->pager_index);
+ i ++)
+ {
+ pi = &cf->pager_index[cf->pager_start + i];
+ line = cf->pager_vector[pi->line] + pi->offset;
+
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
+ }
+ /* if the last line didn't end in newline, add a newline */
+ if (pi && line[pi->length - 1] != '\n')
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
+
+ unix_cli_pager_prompt (cf, uf);
+}
+
+/** @brief Process and add a line to the pager index.
+ * In normal operation this function will take the given character string
+ * found in @c line and with length @c len_or_index and iterates the over the
+ * contents, adding each line of text discovered within it to the
+ * pager index. Lines are identified by newlines ("<code>\\n</code>") and by
+ * strings longer than the width of the terminal.
+ *
+ * If instead @c line is @c NULL then @c len_or_index is taken to mean the
+ * index of an existing line in the pager buffer; this simply means that the
+ * input line does not need to be cloned since we alreayd have it. This is
+ * typical if we are reindexing the pager buffer.
+ *
+ * @param cf The CLI session whose pager we are adding to.
+ * @param line The string of text to be indexed into the pager buffer.
+ * If @c line is @c NULL then the mode of operation
+ * changes slightly; see the description above.
+ * @param len_or_index If @c line is a pointer to a string then this parameter
+ * indicates the length of that string; Otherwise this
+ * value provides the index in the pager buffer of an
+ * existing string to be indexed.
+ */
+static void unix_cli_pager_add_line (unix_cli_file_t * cf,
+ u8 * line,
+ word len_or_index)
+{
+ u8 * p;
+ word i, j, k;
+ word line_index, len;
+ u32 width = cf->width;
+ unix_cli_pager_index_t * pi;
+
+ if (line == NULL)
+ {
+ /* Use a line already in the pager buffer */
+ line_index = len_or_index;
+ p = cf->pager_vector[line_index];
+ len = vec_len (p);
+ }
+ else
+ {
+ len = len_or_index;
+ /* Add a copy of the raw string to the pager buffer */
+ p = vec_new (u8, len);
+ clib_memcpy (p, line, len);
+
+ /* store in pager buffer */
+ line_index = vec_len (cf->pager_vector);
+ vec_add1 (cf->pager_vector, p);
+ }
+
+ i = 0;
+ while (i < len)
+ {
+ /* Find the next line, or run to terminal width, or run to EOL */
+ int l = len - i;
+ j = unix_vlib_findchr((u8)'\n', p, l < width ? l : width);
+
+ if (j < l && p[j] == '\n') /* incl \n */
+ j ++;
+
+ /* Add the line to the index */
+ k = vec_len (cf->pager_index);
+ vec_validate (cf->pager_index, k);
+ pi = &cf->pager_index[k];
+
+ pi->line = line_index;
+ pi->offset = i;
+ pi->length = j;
+
+ i += j;
+ p += j;
+ }
+}
+
+/** @brief Reindex entire pager buffer.
+ * Resets the current pager index and then re-adds the lines in the pager
+ * buffer to the index.
+ *
+ * Additionally this function attempts to retain the current page start
+ * line offset by searching for the same top-of-screen line in the new index.
+ *
+ * @param cf The CLI session whose pager buffer should be reindexed.
+ */
+static void unix_cli_pager_reindex (unix_cli_file_t * cf)
+{
+ word i, old_line, old_offset;
+ unix_cli_pager_index_t * pi;
+
+ /* If there is nothing in the pager buffer then make sure the index
+ * is empty and move on.
+ */
+ if (cf->pager_vector == 0)
+ {
+ vec_reset_length (cf->pager_index);
+ return;
+ }
+
+ /* Retain a pointer to the current page start line so we can
+ * find it later
+ */
+ pi = &cf->pager_index[cf->pager_start];
+ old_line = pi->line;
+ old_offset = pi->offset;
+
+ /* Re-add the buffered lines to the index */
+ vec_reset_length (cf->pager_index);
+ vec_foreach_index(i, cf->pager_vector)
+ {
+ unix_cli_pager_add_line(cf, NULL, i);
+ }
+
+ /* Attempt to re-locate the previously stored page start line */
+ vec_foreach_index(i, cf->pager_index)
+ {
+ pi = &cf->pager_index[i];
+
+ if (pi->line == old_line &&
+ (pi->offset <= old_offset ||
+ pi->offset + pi->length > old_offset))
+ {
+ /* Found it! */
+ cf->pager_start = i;
+ break;
+ }
+ }
+
+ /* In case the start line was not found (rare), ensure the pager start
+ * index is within bounds
+ */
+ if (cf->pager_start >= vec_len (cf->pager_index))
+ {
+ cf->pager_start = vec_len (cf->pager_index) - cf->height + 1;
+
+ if (cf->pager_start < 0)
+ cf->pager_start = 0;
+ }
+}
+
+/** VLIB CLI output function.
+ *
+ * If the terminal has a pager configured then this function takes care
+ * of collating output into the pager buffer; ensuring only the first page
+ * is displayed and any lines in excess of the first page are buffered.
+ *
+ * If the maximum number of index lines in the buffer is exceeded then the
+ * pager is cancelled and the contents of the current buffer are sent to the
+ * terminal.
+ *
+ * If there is no pager configured then the output is sent directly to the
+ * terminal.
+ *
+ * @param cli_file_index Index of the CLI session where this output is
+ * directed.
+ * @param buffer String of printabe bytes to be output.
+ * @param buffer_bytes The number of bytes in @c buffer to be output.
+ */
static void unix_vlib_cli_output (uword cli_file_index,
u8 * buffer,
uword buffer_bytes)
@@ -688,75 +905,80 @@ static void unix_vlib_cli_output (uword cli_file_index,
if (cf->no_pager || um->cli_pager_buffer_limit == 0 || cf->height == 0)
{
- unix_vlib_cli_output_cooked(cf, uf, buffer, buffer_bytes);
+ unix_vlib_cli_output_cooked (cf, uf, buffer, buffer_bytes);
}
else
{
- /* At each \n add the line to the pager buffer.
- * If we've not yet displayed a whole page in this command then
- * also output the line.
- * If we have displayed a whole page then display a pager prompt
- * and count the lines we've buffered.
- */
- u8 * p = buffer;
+ word row = vec_len (cf->pager_index);
u8 * line;
- uword i, len = buffer_bytes;
-
- while (len)
- {
- i = unix_vlib_findchr('\n', p, len);
- if (i < len)
- i ++; /* include the '\n' */
-
- /* make a vec out of this substring */
- line = vec_new(u8, i);
- memcpy(line, p, i);
+ unix_cli_pager_index_t * pi;
- /* store in pager buffer */
- vec_add1(cf->pager_vector, line);
- cf->pager_lines ++;
+ /* Index and add the output lines to the pager buffer. */
+ unix_cli_pager_add_line (cf, buffer, buffer_bytes);
- if (cf->pager_lines < cf->height)
+ /* Now iterate what was added to display the lines.
+ * If we reach the bottom of the page, display a prompt.
+ */
+ while (row < vec_len (cf->pager_index))
+ {
+ if (row < cf->height - 1)
{
/* output this line */
- unix_vlib_cli_output_cooked(cf, uf, p, i);
- /* TODO: stop if line longer than cf->width and would
- * overflow cf->height */
+ pi = &cf->pager_index[row];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
+
+ /* if the last line didn't end in newline, and we're at the
+ * bottom of the page, add a newline */
+ if (line[pi->length - 1] != '\n' && row == cf->height - 2)
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
}
else
{
/* Display the pager prompt every 10 lines */
- if (!(cf->pager_lines % 10))
+ if (!(row % 10))
unix_cli_pager_prompt(cf, uf);
}
-
- p += i;
- len -= i;
+ row ++;
}
- /* Check if we went over the pager buffer limit */
- if (cf->pager_lines > um->cli_pager_buffer_limit)
- {
- /* Stop using the pager for the remainder of this CLI command */
- cf->no_pager = 2;
+ /* Check if we went over the pager buffer limit */
+ if (vec_len (cf->pager_index) > um->cli_pager_buffer_limit)
+ {
+ /* Stop using the pager for the remainder of this CLI command */
+ cf->no_pager = 2;
- /* If we likely printed the prompt, erase it */
- if (cf->pager_lines > cf->height - 1)
- unix_cli_pager_prompt_erase (cf, uf);
+ /* If we likely printed the prompt, erase it */
+ if (vec_len (cf->pager_index) > cf->height - 1)
+ unix_cli_pager_prompt_erase (cf, uf);
- /* Dump out the contents of the buffer */
- for (i = cf->pager_start + (cf->height - 1);
- i < cf->pager_lines; i ++)
- unix_vlib_cli_output_cooked (cf, uf,
- cf->pager_vector[i],
- vec_len(cf->pager_vector[i]));
+ /* Dump out the contents of the buffer */
+ for (row = cf->pager_start + (cf->height - 1);
+ row < vec_len (cf->pager_index); row ++)
+ {
+ pi = &cf->pager_index[row];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
+ }
- unix_cli_pager_reset (cf);
- }
+ unix_cli_pager_reset (cf);
+ }
}
}
-/** \brief Identify whether a terminal type is ANSI capable. */
+/** Identify whether a terminal type is ANSI capable.
+ *
+ * Compares the string given in @term with a list of terminal types known
+ * to support ANSI escape sequences.
+ *
+ * This list contains, for example, @c xterm, @c screen and @c ansi.
+ *
+ * @param term A string with a terminal type in it.
+ * @param len The length of the string in @term.
+ *
+ * @return @c 1 if the terminal type is recognized as supporting ANSI
+ * terminal sequences; @c 0 otherwise.
+ */
static u8 unix_cli_terminal_type(u8 * term, uword len)
{
/* This may later be better done as a hash of some sort. */
@@ -906,6 +1128,10 @@ static i32 unix_cli_process_telnet(unix_main_t * um,
break;
cf->width = clib_net_to_host_u16(*((u16 *)(input_vector + 3)));
cf->height = clib_net_to_host_u16(*((u16 *)(input_vector + 5)));
+ /* reindex pager buffer */
+ unix_cli_pager_reindex (cf);
+ /* redraw page */
+ unix_cli_pager_redraw (cf, uf);
break;
default:
@@ -1308,18 +1534,24 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
case UNIX_CLI_PARSE_ACTION_PAGER_NEXT:
case UNIX_CLI_PARSE_ACTION_PAGER_PGDN:
/* show next page of the buffer */
- if (cf->height + cf->pager_start < cf->pager_lines)
+ if (cf->height + cf->pager_start < vec_len (cf->pager_index))
{
- u8 * line;
+ u8 * line = NULL;
+ unix_cli_pager_index_t * pi = NULL;
+
int m = cf->pager_start + (cf->height - 1);
unix_cli_pager_prompt_erase (cf, uf);
for (j = m;
- j < cf->pager_lines && cf->pager_start < m;
+ j < vec_len (cf->pager_index) && cf->pager_start < m;
j ++, cf->pager_start ++)
{
- line = cf->pager_vector[j];
- unix_vlib_cli_output_cooked (cf, uf, line, vec_len(line));
+ pi = &cf->pager_index[j];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
}
+ /* if the last line didn't end in newline, add a newline */
+ if (pi && line[pi->length - 1] != '\n')
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
unix_cli_pager_prompt (cf, uf);
}
else
@@ -1333,13 +1565,19 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
case UNIX_CLI_PARSE_ACTION_PAGER_DN:
case UNIX_CLI_PARSE_ACTION_PAGER_CRLF:
/* display the next line of the buffer */
- if (cf->pager_start < cf->pager_lines - (cf->height - 1))
+ if (cf->pager_start < vec_len (cf->pager_index) - (cf->height - 1))
{
u8 * line;
+ unix_cli_pager_index_t * pi;
+
unix_cli_pager_prompt_erase (cf, uf);
- line = cf->pager_vector[cf->pager_start + (cf->height - 1)];
- unix_vlib_cli_output_cooked (cf, uf, line, vec_len(line));
+ pi = &cf->pager_index[cf->pager_start + (cf->height - 1)];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
cf->pager_start ++;
+ /* if the last line didn't end in newline, add a newline */
+ if (line[pi->length - 1] != '\n')
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
unix_cli_pager_prompt (cf, uf);
}
else
@@ -1355,16 +1593,20 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
/* scroll the page back one line */
if (cf->pager_start > 0)
{
- u8 * line;
+ u8 * line = NULL;
+ unix_cli_pager_index_t * pi = NULL;
+
cf->pager_start --;
if (cf->ansi_capable)
{
+ pi = &cf->pager_index[cf->pager_start];
+ line = cf->pager_vector[pi->line] + pi->offset;
unix_cli_pager_prompt_erase (cf, uf);
unix_vlib_cli_output_cooked (cf, uf, (u8 *)ANSI_SCROLLDN, sizeof(ANSI_SCROLLDN) - 1);
unix_vlib_cli_output_cooked (cf, uf, (u8 *)ANSI_SAVECURSOR, sizeof(ANSI_SAVECURSOR) - 1);
unix_cli_ansi_cursor(cf, uf, 1, 1);
unix_vlib_cli_output_cooked (cf, uf, (u8 *)ANSI_CLEARLINE, sizeof(ANSI_CLEARLINE) - 1);
- unix_vlib_cli_output_cooked (cf, uf, cf->pager_vector[cf->pager_start], vec_len(cf->pager_vector[cf->pager_start]));
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
unix_vlib_cli_output_cooked (cf, uf, (u8 *)ANSI_RESTCURSOR, sizeof(ANSI_RESTCURSOR) - 1);
unix_cli_pager_prompt_erase (cf, uf);
unix_cli_pager_prompt (cf, uf);
@@ -1373,11 +1615,15 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
{
int m = cf->pager_start + (cf->height - 1);
unix_cli_pager_prompt_erase (cf, uf);
- for (j = cf->pager_start; j < cf->pager_lines && j < m; j ++)
+ for (j = cf->pager_start; j < vec_len (cf->pager_index) && j < m; j ++)
{
- line = cf->pager_vector[j];
- unix_vlib_cli_output_cooked (cf, uf, line, vec_len(line));
+ pi = &cf->pager_index[j];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
}
+ /* if the last line didn't end in newline, add a newline */
+ if (pi && line[pi->length - 1] != '\n')
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
unix_cli_pager_prompt (cf, uf);
}
}
@@ -1387,32 +1633,44 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
/* back to the first page of the buffer */
if (cf->pager_start > 0)
{
- u8 * line;
+ u8 * line = NULL;
+ unix_cli_pager_index_t * pi = NULL;
+
cf->pager_start = 0;
int m = cf->pager_start + (cf->height - 1);
unix_cli_pager_prompt_erase (cf, uf);
- for (j = cf->pager_start; j < cf->pager_lines && j < m; j ++)
+ for (j = cf->pager_start; j < vec_len (cf->pager_index) && j < m; j ++)
{
- line = cf->pager_vector[j];
- unix_vlib_cli_output_cooked (cf, uf, line, vec_len(line));
+ pi = &cf->pager_index[j];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
}
+ /* if the last line didn't end in newline, add a newline */
+ if (pi && line[pi->length - 1] != '\n')
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
unix_cli_pager_prompt (cf, uf);
}
break;
case UNIX_CLI_PARSE_ACTION_PAGER_BOTTOM:
/* skip to the last page of the buffer */
- if (cf->pager_start < cf->pager_lines - (cf->height - 1))
+ if (cf->pager_start < vec_len (cf->pager_index) - (cf->height - 1))
{
- u8 * line;
- cf->pager_start = cf->pager_lines - (cf->height - 1);
+ u8 * line = NULL;
+ unix_cli_pager_index_t * pi = NULL;
+
+ cf->pager_start = vec_len (cf->pager_index) - (cf->height - 1);
unix_cli_pager_prompt_erase (cf, uf);
unix_cli_pager_message (cf, uf, "skipping", "\n");
- for (j = cf->pager_start; j < cf->pager_lines; j ++)
+ for (j = cf->pager_start; j < vec_len (cf->pager_index); j ++)
{
- line = cf->pager_vector[j];
- unix_vlib_cli_output_cooked (cf, uf, line, vec_len(line));
+ pi = &cf->pager_index[j];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
}
+ /* if the last line didn't end in newline, add a newline */
+ if (pi && line[pi->length - 1] != '\n')
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
unix_cli_pager_prompt (cf, uf);
}
break;
@@ -1421,23 +1679,34 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
/* wander back one page in the buffer */
if (cf->pager_start > 0)
{
- u8 * line;
+ u8 * line = NULL;
+ unix_cli_pager_index_t * pi = NULL;
int m;
+
if (cf->pager_start >= cf->height)
cf->pager_start -= cf->height - 1;
else
- cf->pager_start = 1;
+ cf->pager_start = 0;
m = cf->pager_start + cf->height - 1;
unix_cli_pager_prompt_erase (cf, uf);
- for (j = cf->pager_start; j < cf->pager_lines && j < m; j ++)
+ for (j = cf->pager_start; j < vec_len (cf->pager_index) && j < m; j ++)
{
- line = cf->pager_vector[j];
- unix_vlib_cli_output_cooked (cf, uf, line, vec_len(line));
+ pi = &cf->pager_index[j];
+ line = cf->pager_vector[pi->line] + pi->offset;
+ unix_vlib_cli_output_cooked (cf, uf, line, pi->length);
}
+ /* if the last line didn't end in newline, add a newline */
+ if (pi && line[pi->length - 1] != '\n')
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *)"\n", 1);
unix_cli_pager_prompt (cf, uf);
}
break;
+ case UNIX_CLI_PARSE_ACTION_PAGER_REDRAW:
+ /* Redraw the current pager screen */
+ unix_cli_pager_redraw (cf, uf);
+ break;
+
case UNIX_CLI_PARSE_ACTION_PAGER_SEARCH:
/* search forwards in the buffer */
break;
@@ -1482,7 +1751,7 @@ static int unix_cli_line_process_one(unix_cli_main_t * cm,
case UNIX_CLI_PARSE_ACTION_PARTIALMATCH:
case UNIX_CLI_PARSE_ACTION_NOMATCH:
- if (cf->pager_lines)
+ if (vec_len (cf->pager_index))
{
/* no-op for now */
}
@@ -1605,7 +1874,7 @@ static int unix_cli_line_edit (unix_cli_main_t * cm,
unix_cli_parse_actions_t *a;
/* If we're in the pager mode, search the pager actions */
- a = cf->pager_lines ? unix_cli_parse_pager : unix_cli_parse_strings;
+ a = vec_len (cf->pager_index) ? unix_cli_parse_pager : unix_cli_parse_strings;
/* See if the input buffer is some sort of control code */
action = unix_cli_match_action(a, &cf->input_vector[i],
@@ -1714,8 +1983,7 @@ more:
(void) unformat (&input, "");
cm->current_input_file_index = cli_file_index;
- cf->pager_lines = 0; /* start a new pager session */
- cf->pager_start = 0;
+ cf->pager_start = 0; /* start a new pager session */
if (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
vlib_cli_input (um->vlib_main, &input, unix_vlib_cli_output, cli_file_index);
@@ -1743,7 +2011,7 @@ done:
cf->no_pager = um->cli_no_pager;
}
- if (cf->pager_lines == 0 || cf->pager_lines < cf->height)
+ if (vec_len (cf->pager_index) == 0 || vec_len (cf->pager_index) < cf->height)
{
/* There was no need for the pager */
unix_cli_pager_reset (cf);
@@ -2034,9 +2302,11 @@ static clib_error_t * unix_cli_listen_read_ready (unix_file_t * uf)
static void
unix_cli_resize_interrupt (int signum)
{
+ unix_main_t * um = &unix_main;
unix_cli_main_t * cm = &unix_cli_main;
unix_cli_file_t * cf = pool_elt_at_index (cm->cli_file_pool,
cm->stdin_cli_file_index);
+ unix_file_t * uf = pool_elt_at_index (um->file_pool, cf->unix_file_index);
struct winsize ws;
(void)signum;
@@ -2044,6 +2314,12 @@ unix_cli_resize_interrupt (int signum)
ioctl(UNIX_CLI_STDIN_FD, TIOCGWINSZ, &ws);
cf->width = ws.ws_col;
cf->height = ws.ws_row;
+
+ /* Reindex the pager buffer */
+ unix_cli_pager_reindex (cf);
+
+ /* Redraw the page */
+ unix_cli_pager_redraw (cf, uf);
}
/** Handle configuration directives in the @em unix section. */