diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/interface.c | 7 | ||||
-rw-r--r-- | src/interface.h | 2 | ||||
-rw-r--r-- | src/main.c | 41 | ||||
-rw-r--r-- | src/view.c | 63 | ||||
-rw-r--r-- | src/view.h | 2 |
5 files changed, 114 insertions, 1 deletions
diff --git a/src/interface.c b/src/interface.c index c3103fd..cfc8279 100644 --- a/src/interface.c +++ b/src/interface.c @@ -36,6 +36,9 @@ //#define DEBUG +/** minimum level of messages to print to stdout/stderr */ +teco_msg_t teco_interface_msg_level = TECO_MSG_USER; + teco_view_t *teco_interface_current_view = NULL; TECO_DEFINE_UNDO_CALL(teco_interface_show_view, teco_view_t *); @@ -114,6 +117,10 @@ teco_interface_msg(teco_msg_t type, const gchar *fmt, ...) void teco_interface_stdio_msg(teco_msg_t type, const gchar *str, gsize len) { + /* "user"-level messages are always printed */ + if (type != TECO_MSG_USER && type < teco_interface_msg_level) + return; + switch (type) { case TECO_MSG_USER: fwrite(str, 1, len, stdout); diff --git a/src/interface.h b/src/interface.h index 02af8a2..c0c41bd 100644 --- a/src/interface.h +++ b/src/interface.h @@ -66,6 +66,8 @@ typedef enum { TECO_MSG_ERROR } teco_msg_t; +extern teco_msg_t teco_interface_msg_level; + /** @pure */ void teco_interface_msg_literal(teco_msg_t type, const gchar *str, gsize len); @@ -42,6 +42,7 @@ #include "parser.h" #include "goto.h" #include "qreg.h" +#include "view.h" #include "ring.h" #include "undo.h" #include "error.h" @@ -109,6 +110,9 @@ teco_get_default_config_path(void) #endif static gboolean teco_show_version = FALSE; +static gboolean teco_quiet = FALSE; +static gboolean teco_stdin = FALSE; +static gboolean teco_stdout = FALSE; static gchar *teco_eval_macro = NULL; static gboolean teco_mung_file = FALSE; static gboolean teco_mung_profile = TRUE; @@ -122,6 +126,12 @@ teco_process_options(gchar ***argv) static const GOptionEntry option_entries[] = { {"version", 'v', 0, G_OPTION_ARG_NONE, &teco_show_version, "Show version"}, + {"quiet", 'q', 0, G_OPTION_ARG_NONE, &teco_quiet, + "Don't print any non-user-level messages to stdout"}, + {"stdin", 'i', 0, G_OPTION_ARG_NONE, &teco_stdin, + "Read stdin into the unnamed buffer"}, + {"stdout", 'o', 0, G_OPTION_ARG_NONE, &teco_stdout, + "Print current buffer to stdout before program termination"}, {"eval", 'e', 0, G_OPTION_ARG_STRING, &teco_eval_macro, "Evaluate macro", "macro"}, {"mung", 'm', 0, G_OPTION_ARG_NONE, &teco_mung_file, @@ -195,6 +205,10 @@ teco_process_options(gchar ***argv) exit(EXIT_SUCCESS); } + if (teco_quiet) + /* warnings and errors will still be printed to stderr */ + teco_interface_msg_level = TECO_MSG_WARNING; + if ((*argv)[0] && !g_strcmp0((*argv)[1], "-S")) { /* translate -S to --, this is always passed down */ (*argv)[1][1] = '-'; @@ -453,17 +467,39 @@ main(int argc, char **argv) } /* + * Load stdin into the unnamed buffer. + * This will also perform EOL normalization. + * This is not done automatically when isatty(0) == 0 + * since you might want to read from stdin manually (^T). + * Loading stdin also won't work if the stream is infinite. + * + * NOTE: The profile hasn't run yet, so it cannot guess the + * documents encoding. This should therefore be done by the profile + * for any preexisting unnamed buffer. + * + * FIXME: The unnamed buffer is also currently used for + * command-line parameters. + * Therefore you practically cannot pipe into SciTECO + * while using opener.tes. + */ + if (teco_stdin && !teco_view_load_from_stdin(teco_ring_current->view, TRUE, &error)) + goto cleanup; + + /* * Add remaining arguments to unnamed buffer. * * FIXME: This is not really robust since filenames may contain linefeeds. * Also, the Unnamed Buffer should be kept empty for piping. - * Therefore, it would be best to store the arguments in Q-Regs, e.g. $0,$1,$2... + * Therefore, it would be best to store the arguments in Q-Regs, e.g. ^A0,^A1,^A2... */ for (gint i = 1; argv_utf8[i]; i++) { teco_interface_ssm(SCI_APPENDTEXT, strlen(argv_utf8[i]), (sptr_t)argv_utf8[i]); teco_interface_ssm(SCI_APPENDTEXT, 1, (sptr_t)"\n"); } + if (teco_interface_ssm(SCI_GETLENGTH, 0, 0) > 0) + teco_ring_dirtify(); + /* * Execute macro or mung file */ @@ -571,6 +607,9 @@ main(int argc, char **argv) goto cleanup; cleanup: + if (!error && teco_stdout) + teco_view_save_to_stdout(teco_ring_current->view, &error); + if (error != NULL) { teco_error_display_full(error); ret = EXIT_FAILURE; @@ -350,6 +350,44 @@ teco_view_load_from_file(teco_view_t *ctx, const gchar *filename, return TRUE; } +/** + * Load stdin until EOF into view's document. + * + * @param ctx The view to load. + * @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_stdin(teco_view_t *ctx, gboolean clear, GError **error) +{ +#ifdef G_OS_WIN32 + g_autoptr(GIOChannel) channel = g_io_channel_win32_new_fd(0); +#else + g_autoptr(GIOChannel) channel = g_io_channel_unix_new(0); +#endif + g_assert(channel != NULL); + + /* + * The file loading algorithm does not need buffered + * streams, so disabling buffering should increase + * performance (slightly). + */ + g_io_channel_set_encoding(channel, NULL, NULL); + g_io_channel_set_buffered(channel, FALSE); + + if (!teco_view_load_from_channel(ctx, channel, clear, error)) { + g_prefix_error_literal(error, "Error reading stdin: "); + return FALSE; + } + + return TRUE; +} + #if 0 /* @@ -554,6 +592,31 @@ teco_view_save_to_file(teco_view_t *ctx, const gchar *filename, GError **error) return TRUE; } +/** @memberof teco_view_t */ +gboolean +teco_view_save_to_stdout(teco_view_t *ctx, GError **error) +{ +#ifdef G_OS_WIN32 + g_autoptr(GIOChannel) channel = g_io_channel_win32_new_fd(1); +#else + g_autoptr(GIOChannel) channel = g_io_channel_unix_new(1); +#endif + g_assert(channel != NULL); + + /* + * teco_view_save_to_channel() expects a buffered and blocking channel + */ + g_io_channel_set_encoding(channel, NULL, NULL); + g_io_channel_set_buffered(channel, TRUE); + + if (!teco_view_save_to_channel(ctx, channel, error)) { + g_prefix_error_literal(error, "Error writing to stdout: "); + return FALSE; + } + + return TRUE; +} + /** * Convert a glyph index to a byte offset as used by Scintilla. * @@ -56,6 +56,7 @@ 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); +gboolean teco_view_load_from_stdin(teco_view_t *ctx, gboolean clear, GError **error); /** @memberof teco_view_t */ #define teco_view_load(CTX, FROM, CLEAR, ERROR) \ @@ -66,6 +67,7 @@ gboolean teco_view_load_from_file(teco_view_t *ctx, const gchar *filename, 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); +gboolean teco_view_save_to_stdout(teco_view_t *ctx, GError **error); /** @memberof teco_view_t */ #define teco_view_save(CTX, TO, ERROR) \ |