diff options
Diffstat (limited to 'src/main.c')
| -rw-r--r-- | src/main.c | 119 |
1 files changed, 99 insertions, 20 deletions
@@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2025 Robin Haberkorn + * Copyright (C) 2012-2026 Robin Haberkorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,17 +30,24 @@ #include <glib/gprintf.h> #include <glib/gstdio.h> +#ifdef G_OS_WIN32 +#include <fcntl.h> +#include <io.h> +#endif + #ifdef HAVE_SYS_CAPSICUM_H #include <sys/capsicum.h> #endif #include "sciteco.h" +#include "expressions.h" #include "file-utils.h" #include "cmdline.h" #include "interface.h" #include "parser.h" #include "goto.h" #include "qreg.h" +#include "view.h" #include "ring.h" #include "undo.h" #include "error.h" @@ -107,6 +114,10 @@ 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; @@ -118,6 +129,14 @@ static gchar * 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, @@ -150,7 +169,7 @@ teco_process_options(gchar ***argv) g_option_context_set_description( options, "Bug reports should go to <" PACKAGE_BUGREPORT "> or " - "<" PACKAGE_URL ">." + "<rhaberkorn@fmsbw.de>." ); g_option_context_add_main_entries(options, option_entries, NULL); @@ -186,6 +205,15 @@ teco_process_options(gchar ***argv) exit(EXIT_FAILURE); } + if (teco_show_version) { + puts(PACKAGE_VERSION); + 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] = '-'; @@ -337,6 +365,21 @@ main(int argc, char **argv) #endif { g_autoptr(GError) error = NULL; + teco_int_t ret = EXIT_SUCCESS; + +#ifdef G_OS_WIN32 + /* + * Windows might by default perform EOL translations, especially + * when writing to stdout, i.e. translate LF to CRLF. + * This would break at the very least --stdout, where you are + * expected to get the linebreaks configured on the current buffer via EL. + * It would also break binary filters on Windows. + * Since printing LF to the console is safe nowadays, we just do that + * globally. + */ + for (gint fd = 0; fd <= 2; fd++) + _setmode(fd, _O_BINARY); +#endif #ifdef DEBUG_PAUSE /* Windows debugging hack (see above) */ @@ -417,15 +460,20 @@ main(int argc, char **argv) * DEC TECO has them in the global table, though. */ /* search string and status register */ - teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_plain_new("_", 1)); + teco_qreg_table_insert_unique(&teco_qreg_table_globals, + teco_qreg_plain_new("_", 1)); /* replacement string register */ - teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_plain_new("-", 1)); + teco_qreg_table_insert_unique(&teco_qreg_table_globals, + teco_qreg_plain_new("-", 1)); /* current document's dot (":") */ - teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_dot_new()); + teco_qreg_table_insert_unique(&teco_qreg_table_globals, + teco_qreg_dot_new()); /* current buffer name and number ("*") */ - teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_bufferinfo_new()); + teco_qreg_table_insert_unique(&teco_qreg_table_globals, + teco_qreg_bufferinfo_new()); /* current working directory ("$") */ - teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_workingdir_new()); + teco_qreg_table_insert_unique(&teco_qreg_table_globals, + teco_qreg_workingdir_new()); /* environment defaults and registers */ teco_initialize_environment(); @@ -438,15 +486,37 @@ main(int argc, char **argv) } /* - * Add remaining arguments to unnamed buffer. + * 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. * - * 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... + * 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. + */ + if (teco_stdin) { + if (!teco_view_load_from_stdin(teco_ring_current->view, TRUE, &error)) + goto cleanup; + + if (teco_interface_ssm(SCI_GETLENGTH, 0, 0) > 0) + teco_ring_dirtify(); + } + + /* + * Initialize the commandline-argument Q-registers (^Ax). */ - 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"); + for (guint i = 0; argv_utf8[i]; i++) { + gchar buf[32+1]; + gint len = g_snprintf(buf, sizeof(buf), "\1%u", i); + g_assert(len < sizeof(buf)); + + teco_qreg_t *qreg = teco_qreg_plain_new(buf, len); + teco_qreg_table_insert_unique(&teco_qreg_table_globals, qreg); + if (!qreg->vtable->set_string(qreg, argv_utf8[i], strlen(argv_utf8[i]), + teco_default_codepage(), &error)) + goto cleanup; } /* @@ -461,7 +531,8 @@ main(int argc, char **argv) } g_clear_error(&error); - if (!teco_ed_hook(TECO_ED_HOOK_QUIT, &error)) + if (!teco_expressions_pop_num_calc(&ret, EXIT_SUCCESS, &error) || + !teco_ed_hook(TECO_ED_HOOK_QUIT, &error)) goto cleanup; goto cleanup; } @@ -498,8 +569,10 @@ main(int argc, char **argv) goto cleanup; g_clear_error(&error); - if (teco_quit_requested) { - if (!teco_ed_hook(TECO_ED_HOOK_QUIT, &error)) + if (teco_ed & TECO_ED_EXIT) { + /* exit was requested using the EX command */ + if (!teco_expressions_pop_num_calc(&ret, EXIT_SUCCESS, &error) || + !teco_ed_hook(TECO_ED_HOOK_QUIT, &error)) goto cleanup; goto cleanup; } @@ -509,7 +582,7 @@ main(int argc, char **argv) * If munged file didn't quit, switch into interactive mode */ /* commandline replacement string register */ - teco_qreg_table_insert(&teco_qreg_table_globals, teco_qreg_plain_new("\e", 1)); + teco_qreg_table_replace(&teco_qreg_table_globals, teco_qreg_plain_new("\e", 1)); teco_undo_enabled = TRUE; teco_ring_set_scintilla_undo(TRUE); @@ -553,8 +626,13 @@ main(int argc, char **argv) goto cleanup; cleanup: - if (error != NULL) + 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; + } #ifndef NDEBUG teco_ring_cleanup(); @@ -562,8 +640,9 @@ cleanup: teco_qreg_table_clear(&teco_qreg_table_globals); teco_qreg_stack_clear(); teco_view_free(teco_qreg_view); + teco_cmdline_cleanup(); #endif teco_interface_cleanup(); - return error ? EXIT_FAILURE : EXIT_SUCCESS; + return ret; } |
