diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-07-13 18:35:32 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-07-13 18:35:32 +0300 |
commit | fbab5e252f22de37d42cc6c2a014d690a9312565 (patch) | |
tree | 9552e56a343e5b9e273021ab53c376d773486447 /src | |
parent | 8c6de6cc718debf44f6056a4c34c4fbb13bc5020 (diff) | |
download | sciteco-fbab5e252f22de37d42cc6c2a014d690a9312565.tar.gz |
implemented <ER> command for reading a file into the current buffer
* This command exists in Video TECO.
In Video TECO it also supports reading multiple files with a glob pattern -- we do not support that
as I am not convinced of its usefulness.
* teco_view_load() has been extended, so it can read into dot without
discarding the existing document.
Diffstat (limited to 'src')
-rw-r--r-- | src/core-commands.c | 2 | ||||
-rw-r--r-- | src/qreg.c | 2 | ||||
-rw-r--r-- | src/ring.c | 36 | ||||
-rw-r--r-- | src/ring.h | 1 | ||||
-rw-r--r-- | src/view.c | 62 | ||||
-rw-r--r-- | src/view.h | 13 |
6 files changed, 89 insertions, 27 deletions
diff --git a/src/core-commands.c b/src/core-commands.c index 0ff2b81..8e31ae3 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -2686,6 +2686,8 @@ teco_state_ecommand_input(teco_machine_main_t *ctx, gunichar chr, GError **error .modifier_at = TRUE, .modifier_colon = 1}, ['W'] = {&teco_state_save_file, .modifier_at = TRUE}, + ['R'] = {&teco_state_read_file, + .modifier_at = TRUE}, /* * Commands @@ -337,7 +337,7 @@ teco_qreg_plain_load(teco_qreg_t *qreg, const gchar *filename, GError **error) * So if loading fails, teco_qreg_current will be * made the current document again. */ - if (!teco_view_load(teco_qreg_view, filename, error)) + if (!teco_view_load(teco_qreg_view, filename, TRUE, error)) return FALSE; if (teco_qreg_current) @@ -77,7 +77,7 @@ teco_buffer_undo_edit(teco_buffer_t *ctx) static gboolean teco_buffer_load(teco_buffer_t *ctx, const gchar *filename, GError **error) { - if (!teco_view_load(ctx->view, filename, error)) + if (!teco_view_load(ctx->view, filename, TRUE, error)) return FALSE; #if 0 /* NOTE: currently buffer cannot be dirty */ @@ -595,6 +595,40 @@ teco_state_save_file_done(teco_machine_main_t *ctx, const teco_string_t *str, GE */ TECO_DEFINE_STATE_EXPECTFILE(teco_state_save_file); +static teco_state_t * +teco_state_read_file_done(teco_machine_main_t *ctx, const teco_string_t *str, GError **error) +{ + if (ctx->flags.mode > TECO_MODE_NORMAL) + return &teco_state_start; + + sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); + + g_autofree gchar *filename = teco_file_expand_path(str->data); + /* FIXME: Add wrapper to interface.h? */ + if (!teco_view_load(teco_interface_current_view, filename, FALSE, error)) + return NULL; + + if (teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0) != pos) { + teco_ring_dirtify(); + + if (teco_current_doc_must_undo()) + undo__teco_interface_ssm(SCI_UNDO, 0, 0); + } + + return &teco_state_start; +} + +/*$ ER read + * ER<file>$ -- Read and insert file into current buffer + * + * Reads and inserts the given <file> into the current buffer or Q-Register at dot. + * Dot is left immediately after the given file. + */ +/* + * NOTE: Video TECO allows glob patterns as an argument. + */ +TECO_DEFINE_STATE_EXPECTFILE(teco_state_read_file); + /*$ EF close * [n]EF -- Remove buffer from ring * -EF @@ -99,6 +99,7 @@ void teco_ring_cleanup(void); TECO_DECLARE_STATE(teco_state_edit_file); TECO_DECLARE_STATE(teco_state_save_file); +TECO_DECLARE_STATE(teco_state_read_file); void teco_state_ecommand_close(teco_machine_main_t *ctx, GError **error); @@ -198,16 +198,22 @@ teco_view_set_representations(teco_view_t *ctx) * * @param ctx The view to load. * @param channel Channel to read from. + * @param clear Whether to completely replace document + * (leaving dot at the beginning of the document) or insert at dot + * (leaving dot at the end of the insertion). * @param error A GError. * @return FALSE in case of a GError. * * @memberof teco_view_t */ gboolean -teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **error) +teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, + gboolean clear, GError **error) { gboolean ret = TRUE; + unsigned int message = SCI_ADDTEXT; + g_auto(teco_eol_reader_t) reader; teco_eol_reader_init_gio(&reader, channel); @@ -225,22 +231,27 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **erro SC_LINECHARACTERINDEX_UTF32, 0); teco_view_ssm(ctx, SCI_BEGINUNDOACTION, 0, 0); - teco_view_ssm(ctx, SCI_CLEARALL, 0, 0); + if (clear) { + teco_view_ssm(ctx, SCI_CLEARALL, 0, 0); - /* - * Preallocate memory based on the file size. - * May waste a few bytes if file contains DOS EOLs - * and EOL translation is enabled, but is faster. - * NOTE: g_io_channel_unix_get_fd() should report the correct fd - * on Windows, too. - */ - struct stat stat_buf = {.st_size = 0}; - if (!fstat(g_io_channel_unix_get_fd(channel), &stat_buf) && - stat_buf.st_size > 0) { - ret = teco_memory_check(stat_buf.st_size, error); - if (!ret) - goto cleanup; - teco_view_ssm(ctx, SCI_ALLOCATE, stat_buf.st_size, 0); + /* + * Preallocate memory based on the file size. + * May waste a few bytes if file contains DOS EOLs + * and EOL translation is enabled, but is faster. + * NOTE: g_io_channel_unix_get_fd() should report the correct fd + * on Windows, too. + */ + struct stat stat_buf = {.st_size = 0}; + if (!fstat(g_io_channel_unix_get_fd(channel), &stat_buf) && + stat_buf.st_size > 0) { + ret = teco_memory_check(stat_buf.st_size, error); + if (!ret) + goto cleanup; + teco_view_ssm(ctx, SCI_ALLOCATE, stat_buf.st_size, 0); + } + + /* keep dot at beginning of document */ + message = SCI_APPENDTEXT; } for (;;) { @@ -258,7 +269,7 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **erro if (rc == G_IO_STATUS_EOF) break; - teco_view_ssm(ctx, SCI_APPENDTEXT, str.len, (sptr_t)str.data); + teco_view_ssm(ctx, message, str.len, (sptr_t)str.data); /* * Even if we checked initially, knowing the file size, @@ -285,7 +296,7 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **erro * If it is enabled but the stream does not contain any * EOL characters, the platform default is still assumed. */ - if (reader.eol_style >= 0) + if (clear && reader.eol_style >= 0) teco_view_ssm(ctx, SCI_SETEOLMODE, reader.eol_style, 0); if (reader.eol_style_inconsistent) @@ -303,12 +314,21 @@ cleanup: } /** - * Load view's document from file. + * Load file into view's document. + * + * @param ctx The view to load. + * @param filename File name to read + * @param clear Whether to completely replace document + * (leaving dot at the beginning of the document) or insert at dot + * (leaving dot at the end of the insertion). + * @param error A GError. + * @return FALSE in case of a GError. * * @memberof teco_view_t */ gboolean -teco_view_load_from_file(teco_view_t *ctx, const gchar *filename, GError **error) +teco_view_load_from_file(teco_view_t *ctx, const gchar *filename, + gboolean clear, GError **error) { g_autoptr(GIOChannel) channel = g_io_channel_new_file(filename, "r", error); if (!channel) @@ -322,7 +342,7 @@ teco_view_load_from_file(teco_view_t *ctx, const gchar *filename, GError **error g_io_channel_set_encoding(channel, NULL, NULL); g_io_channel_set_buffered(channel, FALSE); - if (!teco_view_load_from_channel(ctx, channel, error)) { + if (!teco_view_load_from_channel(ctx, channel, clear, error)) { g_prefix_error(error, "Error reading file \"%s\": ", filename); return FALSE; } @@ -52,13 +52,17 @@ teco_view_set_scintilla_undo(teco_view_t *ctx, gboolean state) teco_view_ssm(ctx, SCI_SETUNDOCOLLECTION, state, 0); } -gboolean teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, GError **error); -gboolean teco_view_load_from_file(teco_view_t *ctx, const gchar *filename, GError **error); +gboolean teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel, + gboolean clear, GError **error); +gboolean teco_view_load_from_file(teco_view_t *ctx, const gchar *filename, + gboolean clear, GError **error); /** @memberof teco_view_t */ -#define teco_view_load(CTX, FROM, ERROR) \ +#define teco_view_load(CTX, FROM, CLEAR, ERROR) \ (_Generic((FROM), GIOChannel * : teco_view_load_from_channel, \ - const gchar * : teco_view_load_from_file)((CTX), (FROM), (ERROR))) + gchar * : teco_view_load_from_file, \ + const gchar * : teco_view_load_from_file)((CTX), (FROM), \ + (CLEAR), (ERROR))) gboolean teco_view_save_to_channel(teco_view_t *ctx, GIOChannel *channel, GError **error); gboolean teco_view_save_to_file(teco_view_t *ctx, const gchar *filename, GError **error); @@ -66,6 +70,7 @@ gboolean teco_view_save_to_file(teco_view_t *ctx, const gchar *filename, GError /** @memberof teco_view_t */ #define teco_view_save(CTX, TO, ERROR) \ (_Generic((TO), GIOChannel * : teco_view_save_to_channel, \ + gchar * : teco_view_save_to_file, \ const gchar * : teco_view_save_to_file)((CTX), (TO), (ERROR))) /** @pure @memberof teco_view_t */ |