From a3ef5723a95edf153095f512417c402202ac3270 Mon Sep 17 00:00:00 2001 From: Scott Prager Date: Tue, 16 Sep 2014 19:14:20 -0400 Subject: [PATCH 1/4] mch_write -> term_write Switch from POSIX's write() to fwrite(stdout,...) and disable buffering since vim buffers output explicitly and flushes when needed, like when a key is typed. --- src/nvim/os_unix.c | 30 ++++++------------------------ src/nvim/term.c | 26 +++++++++++++++++++++++++- src/nvim/ui.c | 2 +- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 3bf1198b46..bcb35e297b 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -82,30 +82,6 @@ static int did_set_title = FALSE; static char_u *oldicon = NULL; static int did_set_icon = FALSE; - - -/* - * Write s[len] to the screen. - */ -void mch_write(char_u *s, int len) -{ - if (embedded_mode) { - // TODO(tarruda): This is a temporary hack to stop Neovim from writing - // messages to stdout in embedded mode. In the future, embedded mode will - // be the only possibility(GUIs will always start neovim with a msgpack-rpc - // over stdio) and this function won't exist. - // - // The reason for this is because before Neovim fully migrates to a - // msgpack-rpc-driven architecture, we must have a fully functional - // UI working - return; - } - - ignored = (int)write(1, (char *)s, len); - if (p_wd) /* Unix is too fast, slow down a bit more */ - os_microdelay(p_wd, false); -} - /* * If the machine has job control, use it to suspend the program, * otherwise fake it by starting a new shell. @@ -159,6 +135,12 @@ void mch_init(void) Columns = 80; Rows = 24; + // Prevent buffering output. + // Output gets explicitly buffered and flushed by out_flush() at times like, + // for example, when the user presses a key. Without this line, vim will not + // render the screen correctly. + setbuf(stdout, NULL); + out_flush(); #ifdef MACOS_CONVERT diff --git a/src/nvim/term.c b/src/nvim/term.c index 3d1053bd2f..18620ea766 100644 --- a/src/nvim/term.c +++ b/src/nvim/term.c @@ -1822,11 +1822,35 @@ void termcapinit(char_u *name) set_termname(T_NAME != NULL ? T_NAME : term); } +/// Write s[len] to the screen. +void term_write(char_u *s, size_t len) +{ + if (embedded_mode) { + // TODO(tarruda): This is a temporary hack to stop Neovim from writing + // messages to stdout in embedded mode. In the future, embedded mode will + // be the only possibility(GUIs will always start neovim with a msgpack-rpc + // over stdio) and this function won't exist. + // + // The reason for this is because before Neovim fully migrates to a + // msgpack-rpc-driven architecture, we must have a fully functional + // UI working + return; + } + + (void) fwrite(s, len, 1, stdout); + +#ifdef UNIX + if (p_wd) { // Unix is too fast, slow down a bit more + os_microdelay(p_wd, false); + } +#endif +} + /* * the number of calls to ui_write is reduced by using the buffer "out_buf" */ # define OUT_SIZE 2047 -/* Add one to allow mch_write() in os_win32.c to append a NUL */ +// Add one to allow term_write() in os_win32.c to append a NUL static char_u out_buf[OUT_SIZE + 1]; static int out_pos = 0; /* number of chars in out_buf */ diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 803e7fab50..0b68eb3051 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -55,7 +55,7 @@ void ui_write(char_u *s, int len) s = tofree; } - mch_write(s, len); + term_write(s, len); if (output_conv.vc_type != CONV_NONE) free(tofree); From 8d271bb57bdf6e7718da91f58f98cf0da0fe0e71 Mon Sep 17 00:00:00 2001 From: Scott Prager Date: Wed, 17 Sep 2014 19:17:22 -0400 Subject: [PATCH 2/4] mch_init -> term_init --- src/nvim/main.c | 11 +++++------ src/nvim/os_unix.c | 20 -------------------- src/nvim/term.c | 24 ++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/nvim/main.c b/src/nvim/main.c index 68ae000c35..ca9b4184bc 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -60,6 +60,7 @@ #include "nvim/os/time.h" #include "nvim/os/input.h" #include "nvim/os/os.h" +#include "nvim/os/event.h" #include "nvim/os/signal.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/api/private/defs.h" @@ -252,14 +253,12 @@ int main(int argc, char **argv) */ - /* - * mch_init() sets up the terminal (window) for use. This must be - * done after resetting full_screen, otherwise it may move the cursor - * Note that we may use mch_exit() before mch_init()! - */ - mch_init(); + // term_init() sets up the terminal (window) for use. This must be + // done after resetting full_screen, otherwise it may move the cursor + term_init(); TIME_MSG("shell init"); + event_init(); if (!embedded_mode) { // Print a warning if stdout is not a terminal. diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index bcb35e297b..2595e2e5a2 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -130,26 +130,6 @@ void mch_suspend(void) #endif } -void mch_init(void) -{ - Columns = 80; - Rows = 24; - - // Prevent buffering output. - // Output gets explicitly buffered and flushed by out_flush() at times like, - // for example, when the user presses a key. Without this line, vim will not - // render the screen correctly. - setbuf(stdout, NULL); - - out_flush(); - -#ifdef MACOS_CONVERT - mac_conv_init(); -#endif - - event_init(); -} - static int get_x11_title(int test_only) { return FALSE; diff --git a/src/nvim/term.c b/src/nvim/term.c index 18620ea766..fd2988c850 100644 --- a/src/nvim/term.c +++ b/src/nvim/term.c @@ -1010,6 +1010,30 @@ static struct builtin_term builtin_termcaps[] = # define DEFAULT_TERM (char_u *)"dumb" #endif +/// Sets up the terminal window for use. +/// +/// This must be done after resetting full_screen, otherwise it may move the +/// cursor. +/// +/// @remark We may call mch_exit() before calling this. +void term_init(void) +{ + Columns = 80; + Rows = 24; + + // Prevent buffering output. + // Output gets explicitly buffered and flushed by out_flush() at times like, + // for example, when the user presses a key. Without this line, vim will not + // render the screen correctly. + setbuf(stdout, NULL); + + out_flush(); + +#ifdef MACOS_CONVERT + mac_conv_init(); +#endif +} + /* * Term_strings contains currently used terminal output strings. * It is initialized with the default values by parse_builtin_tcap(). From d5ea1836333f7a139cab46833feb9d35ede46d6c Mon Sep 17 00:00:00 2001 From: Scott Prager Date: Wed, 17 Sep 2014 22:24:39 -0400 Subject: [PATCH 3/4] update mch_suspend Use the portable uv_kill. Don't bother with archaic BeOS. --- src/nvim/os_unix.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 2595e2e5a2..21c8065642 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -88,17 +88,16 @@ static int did_set_icon = FALSE; */ void mch_suspend(void) { - /* BeOS does have SIGTSTP, but it doesn't work. */ -#if defined(SIGTSTP) && !defined(__BEOS__) +#if defined(SIGTSTP) out_flush(); /* needed to make cursor visible on some systems */ settmode(TMODE_COOK); out_flush(); /* needed to disable mouse on some systems */ - + // Note: compiler defines _REENTRANT when given -pthread flag. # if defined(_REENTRANT) && defined(SIGCONT) sigcont_received = FALSE; # endif - kill(0, SIGTSTP); /* send ourselves a STOP signal */ + uv_kill(0, SIGTSTP); // send ourselves a STOP signal # if defined(_REENTRANT) && defined(SIGCONT) /* * Wait for the SIGCONT signal to be handled. It generally happens From 275f6e3a6b5132f814ee947da49b8899f557f0a3 Mon Sep 17 00:00:00 2001 From: Scott Prager Date: Fri, 19 Sep 2014 03:49:37 -0400 Subject: [PATCH 4/4] mch_early_init() -> early_init(). Move general initialization functions to early_init, which simplifies test/unit/helpers.lua, which requires all these functions. --- src/nvim/main.c | 96 +++++++++++++++++++++++-------------------- src/nvim/os_unix.c | 6 --- test/unit/helpers.lua | 24 ++--------- 3 files changed, 55 insertions(+), 71 deletions(-) diff --git a/src/nvim/main.c b/src/nvim/main.c index ca9b4184bc..54077acfe3 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -60,11 +60,13 @@ #include "nvim/os/time.h" #include "nvim/os/input.h" #include "nvim/os/os.h" +#include "nvim/os/time.h" #include "nvim/os/event.h" #include "nvim/os/signal.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/api/private/handle.h" /* Maximum number of commands from + or -c arguments. */ #define MAX_ARG_CMDS 10 @@ -143,13 +145,60 @@ static char *(main_errors[]) = #define ME_INVALID_ARG 5 }; +/// Performs early initialization. +/// +/// Needed for unit tests. Must be called after `time_init()`. +void early_init(void) +{ + handle_init(); + + (void)mb_init(); // init mb_bytelen_tab[] to ones + eval_init(); // init global variables + +#ifdef __QNXNTO__ + qnx_init(); // PhAttach() for clipboard, (and gui) +#endif + + // Init the table of Normal mode commands. + init_normal_cmds(); + +#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) + // Setup to use the current locale (for ctype() and many other things). + // NOTE: Translated messages with encodings other than latin1 will not + // work until set_init_1() has been called! + init_locale(); +#endif + + // Allocate the first window and buffer. + // Can't do anything without it, exit when it fails. + if (!win_alloc_first()) { + mch_exit(0); + } + + init_yank(); // init yank buffers + + alist_init(&global_alist); // Init the argument list to empty. + global_alist.id = 0; + + // Set the default values for the options. + // NOTE: Non-latin1 translated messages are working only after this, + // because this is where "has_mbyte" will be set, which is used by + // msg_outtrans_len_attr(). + // First find out the home directory, needed to expand "~" in options. + init_homedir(); // find real value of $HOME + set_init_1(); + TIME_MSG("inits 1"); + + set_lang_var(); // set v:lang and v:ctype +} + #ifndef NO_VIM_MAIN /* skip this for unittests */ int main(int argc, char **argv) { char_u *fname = NULL; /* file name from command line */ mparm_T params; /* various parameters passed between * main() and other functions. */ - mch_early_init(); + time_init(); /* Many variables are in "params" so that we can pass them to invoked * functions without a lot of arguments. "argc" and "argv" are also @@ -158,24 +207,7 @@ int main(int argc, char **argv) init_startuptime(¶ms); - (void)mb_init(); /* init mb_bytelen_tab[] to ones */ - eval_init(); /* init global variables */ - -#ifdef __QNXNTO__ - qnx_init(); /* PhAttach() for clipboard, (and gui) */ -#endif - - /* Init the table of Normal mode commands. */ - init_normal_cmds(); - -#if defined(HAVE_LOCALE_H) || defined(X_LOCALE) - /* - * Setup to use the current locale (for ctype() and many other things). - * NOTE: Translated messages with encodings other than latin1 will not - * work until set_init_1() has been called! - */ - init_locale(); -#endif + early_init(); /* * Check if we have an interactive window. @@ -185,32 +217,6 @@ int main(int argc, char **argv) */ check_and_set_isatty(¶ms); - /* - * Allocate the first window and buffer. - * Can't do anything without it, exit when it fails. - */ - if (win_alloc_first() == FAIL) - mch_exit(0); - - init_yank(); /* init yank buffers */ - - alist_init(&global_alist); /* Init the argument list to empty. */ - global_alist.id = 0; - - /* - * Set the default values for the options. - * NOTE: Non-latin1 translated messages are working only after this, - * because this is where "has_mbyte" will be set, which is used by - * msg_outtrans_len_attr(). - * First find out the home directory, needed to expand "~" in options. - */ - init_homedir(); /* find real value of $HOME */ - set_init_1(); - TIME_MSG("inits 1"); - - set_lang_var(); /* set v:lang and v:ctype */ - - /* * Figure out the way to work from the command name argv[0]. * "vimdiff" starts diff mode, "rvim" sets "restricted", etc. diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 21c8065642..e761145f6f 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -439,12 +439,6 @@ int mch_nodetype(char_u *name) return NODE_WRITABLE; } -void mch_early_init(void) -{ - handle_init(); - time_init(); -} - #if defined(EXITFREE) || defined(PROTO) void mch_free_mem(void) { diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua index 544a53fa10..1b97a2f15a 100644 --- a/test/unit/helpers.lua +++ b/test/unit/helpers.lua @@ -139,26 +139,10 @@ local function vim_init() if vim_init_called ~= nil then return end - -- import os_unix.h for mch_early_init(), which initializes some globals - local all = cimport('./src/nvim/os_unix.h', - './src/nvim/misc1.h', - './src/nvim/eval.h', - './src/nvim/os_unix.h', - './src/nvim/option.h', - './src/nvim/ex_cmds2.h', - './src/nvim/window.h', - './src/nvim/ops.h', - './src/nvim/normal.h', - './src/nvim/mbyte.h') - all.mch_early_init() - all.mb_init() - all.eval_init() - all.init_normal_cmds() - all.win_alloc_first() - all.init_yank() - all.init_homedir() - all.set_init_1() - all.set_lang_var() + local main = cimport('./src/nvim/main.h') + local time = cimport('./src/nvim/os/time.h') + time.time_init() + main.early_init() vim_init_called = true end