Files
bshell/bshell.runtime/line-editor/display.c
T
wash ad8b284869 runtime: implement an extensible line editor
the line editor supports custom keybinds and data storage, allowing for
a wide range of functionality to be implemented via plugins.

included plugins include:
* core: basic input and cursor movement.
* history: input history storage and retrieval (unfinished)
* highlight: support for colour-highlighting the line buffer (unfinished)
* syntax: parses the line buffer and uses `highlight` to apply syntax highlighting (unfinished).
* shell-integration:
  - allows a `prompt` function to be defined, which will be called to get the text to
    be used for the prompt
  - exposes key properties of the line editor to the shell environment, allowing line editor
    functionality to be extended via shell scripts.
2026-06-20 15:13:34 +01:00

99 lines
2.7 KiB
C

#include "line-editor.h"
void line_ed_hide(struct bshell_line_ed_p *ed)
{
if (!ed->ed_render.r_vlines) {
return;
}
#if 0
fprintf(stderr, "--- hide ---\n");
fprintf(stderr,
"vlines=%lu, cursor=%lu->(%ld,%ld)\n",
ed->ed_render.r_vlines,
ed->ed_cursor,
ed->ed_render.ed_points.c_cursor_x,
ed->ed_render.ed_points.c_cursor_y);
#endif
if (ed->ed_render.ed_points.c_cursor_y > 0) {
fx_tty_move_cursor_y(
ed->ed_tty,
FX_TTY_POS_CURSOR,
-ed->ed_render.ed_points.c_cursor_y);
}
fx_tty_move_cursor_x(ed->ed_tty, FX_TTY_POS_START, 0);
fx_tty_clear(
ed->ed_tty,
FX_TTY_CLEAR_SCREEN | FX_TTY_CLEAR_FROM_CURSOR);
memset(&ed->ed_render, 0x0, sizeof ed->ed_render);
}
static void render_prompt(struct bshell_line_ed_p *ed)
{
if (ed->ed_render_prompt) {
bshell_line_ed_plugin_class *renderer = fx_object_get_interface(
ed->ed_render_prompt,
BSHELL_TYPE_LINE_EDITOR_PLUGIN);
renderer->p_render_prompt(ed->ed_render_prompt, ed->ed_self);
}
}
static void render_buffer(struct bshell_line_ed_p *ed)
{
if (ed->ed_render_buffer) {
bshell_line_ed_plugin_class *renderer = fx_object_get_interface(
ed->ed_render_buffer,
BSHELL_TYPE_LINE_EDITOR_PLUGIN);
renderer->p_render_buffer(ed->ed_render_buffer, ed->ed_self);
}
}
void line_ed_show(struct bshell_line_ed_p *ed)
{
render_prompt(ed);
render_buffer(ed);
line_ed_get_points(ed, &ed->ed_render.ed_points);
bool cursor_limit_newline
= ed->ed_render.ed_points.c_cursor_limit_x == 0
&& ed->ed_render.ed_points.c_cursor_limit_y > 0;
if (cursor_limit_newline) {
fx_tty_putc(ed->ed_tty, 0, '\r');
fx_tty_putc(ed->ed_tty, 0, '\n');
}
long shift_x = 0, shift_y = 0;
shift_x = (long)ed->ed_render.ed_points.c_cursor_x
- (long)ed->ed_render.ed_points.c_cursor_limit_x;
shift_y = (long)ed->ed_render.ed_points.c_cursor_y
- (long)ed->ed_render.ed_points.c_cursor_limit_y;
fx_tty_move_cursor_x(ed->ed_tty, FX_TTY_POS_CURSOR, shift_x);
fx_tty_move_cursor_y(ed->ed_tty, FX_TTY_POS_CURSOR, shift_y);
#if 0
fprintf(stderr, "--- show ---\n");
fprintf(stderr,
"cursor=%lu->(%lu,%lu)\n",
ed->ed_cursor,
ed->ed_render.ed_points.c_cursor_x,
ed->ed_render.ed_points.c_cursor_y);
fprintf(stderr,
"cursor_limit=(%lu,%lu)\n",
ed->ed_render.ed_points.c_cursor_limit_x,
ed->ed_render.ed_points.c_cursor_limit_y);
fprintf(stderr,
"render_limit=(%lu,%lu)\n",
ed->ed_render.ed_points.c_render_limit_x,
ed->ed_render.ed_points.c_render_limit_y);
#endif
ed->ed_render.r_vlines = ed->ed_render.ed_points.c_render_limit_y + 1;
}
int line_ed_get_char_width(fx_wchar c)
{
/* TODO support double-width and zero-width characters */
return fx_wchar_is_graph(c) ? 1 : 0;
}