+
+ /* Use the last character to determine the last direction of the cursor. */
+ if (buffer_bytes > 0)
+ cf->cursor_direction = (buffer[buffer_bytes - 1] == (u8) '\b');
+}
+
+/** @brief Moves the terminal cursor one character to the left, with
+ * special handling when it reaches the left edge of the terminal window.
+ *
+ * Ordinarily we can simply send a '\b' to move the cursor left, however
+ * most terminals will not reverse-wrap to the end of the previous line
+ * if the cursor is in the left-most column. To counter this we must
+ * check the cursor position + prompt length modulo terminal width and
+ * if available use some other means, such as ANSI terminal escape
+ * sequences, to move the cursor.
+ *
+ * @param cf Unix CLI session of the desired stream to write to.
+ * @param uf The Unix file structure of the desired stream to write to.
+ */
+static void
+unix_vlib_cli_output_cursor_left (unix_cli_file_t * cf, clib_file_t * uf)
+{
+ unix_cli_main_t *cm = &unix_cli_main;
+ static u8 *ansi = 0; /* assumes no reentry */
+ u32 position;
+
+ if (!cf->is_interactive || !cf->ansi_capable || !cf->width)
+ {
+ /* No special handling for dumb terminals */
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
+ return;
+ }
+
+ position = ((u32) vec_len (cm->cli_prompt) + cf->cursor) % cf->width;
+
+ if (position != 0)
+ {
+ /* No special handling required if we're not at the left edge */
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\b", 1);
+ return;
+ }
+
+ if (!cf->cursor_direction)
+ {
+ /* Special handling for when we are at the left edge but
+ * the cursor was going left-to-right, but in this situation
+ * xterm-like terminals actually hide the cursor off the right
+ * edge. A \b here seems to jump one char too many, so let's
+ * force the cursor onto the next line instead.
+ */
+ if (cf->cursor < vec_len (cf->current_command))
+ unix_vlib_cli_output_cooked (cf, uf, &cf->current_command[cf->cursor],
+ 1);
+ else
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *) " ", 1);
+ unix_vlib_cli_output_cooked (cf, uf, (u8 *) "\r", 1);
+ }
+
+ /* Relocate the cursor at the right hand edge one line above */
+ ansi = format (ansi, CSI "A" CSI "%dC", cf->width - 1);
+ unix_vlib_cli_output_cooked (cf, uf, ansi, vec_len (ansi));
+ vec_reset_length (ansi); /* keep the vec around for next time */
+ cf->cursor_direction = 1; /* going backwards now */