bshell: add line-editor and file-based input support

This commit is contained in:
2026-05-07 10:52:00 +01:00
parent 3c15bb1609
commit 8b0295faf2
27 changed files with 1636 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
#include "file.h"
#include "line-source.h"
#include <errno.h>
#include <fx/collections/array.h>
#include <fx/string.h>
#include <stdlib.h>
#include <string.h>
static enum bshell_status get_name(
struct line_source *src,
char *buf,
size_t count,
size_t *nr_read)
{
struct file *f = (struct file *)src;
*nr_read = snprintf(buf, count, "%s", f->f_path);
return BSHELL_SUCCESS;
}
static enum bshell_status get_row(
struct line_source *src,
size_t row,
char *buf,
size_t count,
size_t *nr_read)
{
struct file *f = (struct file *)src;
size_t nr_rows = fx_array_size(f->f_lines);
if (row > nr_rows) {
return BSHELL_ERR_EOF;
}
fx_string *line = fx_array_at(f->f_lines, row - 1);
const char *line_str = fx_string_get_cstr(line);
size_t line_len = fx_string_get_size(line, FX_STRLEN_NORMAL);
size_t copy_len = fx_min(ulong, count, line_len);
memcpy(buf, line_str, copy_len);
buf[copy_len] = 0;
buf[strcspn(buf, "\n")] = 0;
*nr_read = copy_len;
return BSHELL_SUCCESS;
}
static enum bshell_status readline(
struct line_source *src,
fx_stringstream *out)
{
struct file *f = (struct file *)src;
fx_wchar c = FX_WCHAR_INVALID;
size_t nr_read = 0;
while (1) {
fx_status status = fx_stream_read_char(f->f_strp, &c);
if (!FX_OK(status)) {
break;
}
fx_stream_write_char(out, c);
nr_read++;
if (c == '\n') {
break;
}
}
if (nr_read == 0) {
return BSHELL_ERR_EOF;
}
return BSHELL_SUCCESS;
}
enum bshell_status file_open(const char *path, struct file **out)
{
FILE *fp = fopen(path, "r");
if (!fp) {
return bshell_status_from_errno(errno);
}
fx_stream *strp = fx_stream_open_fp(fp);
struct file *file = malloc(sizeof *file);
if (!file) {
fclose(fp);
return BSHELL_ERR_NO_MEMORY;
}
memset(file, 0x0, sizeof *file);
file->f_base.s_get_name = get_name;
file->f_base.s_get_row = get_row;
file->f_base.s_readline = readline;
file->f_fp = fp;
file->f_strp = strp;
file->f_path = fx_strdup(path);
file->f_lines = fx_array_create();
*out = file;
return BSHELL_SUCCESS;
}
void file_close(struct file *file)
{
fx_stream_unref(file->f_strp);
fx_array_unref(file->f_lines);
free(file->f_path);
fclose(file->f_fp);
free(file);
}