neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit cffdf102d4f01fe5675c389eb80bf55daa62697a
parent 1ad13e07d2d9a01fbadd59a84af601b2ab0d8c73
Author: Gregory Anders <8965202+gpanders@users.noreply.github.com>
Date:   Mon, 28 Aug 2023 07:22:19 -0500

feat(terminal): allow :terminal to take modifiers (#15427)

The following modifiers are all now supported:

    :tab term
    :vertical term
    :horizontal term
    :botright term
    :topleft term

Fixes: https://github.com/neovim/neovim/issues/11385
Diffstat:
Mruntime/doc/news.txt | 3+++
Mruntime/doc/windows.txt | 3++-
Msrc/nvim/ex_docmd.c | 30++++++++++++++++++++++++------
3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt @@ -158,6 +158,9 @@ The following new APIs and features were added. • Floating windows can now show footer with new `footer` and `footer_pos` config fields. Uses |hl-FloatFooter| by default. +• The |:terminal| command now accepts some |:command-modifiers| (specifically + |:horizontal| and those that affect splitting a window). + ============================================================================== CHANGED FEATURES *news-changed* diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt @@ -243,7 +243,8 @@ and 'winminwidth' are relevant. :hor[izontal] {cmd} Execute {cmd}. Currently only makes a difference for `horizontal wincmd =`, which will equalize windows only - horizontally. + horizontally, and |:terminal|, which will open a |terminal| + buffer in a split window. :lefta[bove] {cmd} *:lefta* *:leftabove* :abo[veleft] {cmd} *:abo* *:aboveleft* diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c @@ -7302,12 +7302,31 @@ void set_pressedreturn(bool val) static void ex_terminal(exarg_T *eap) { char ex_cmd[1024]; + size_t len = 0; + + if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) { + bool multi_mods = false; + + // ex_cmd must be a null terminated string before passing to add_win_cmd_modifiers + ex_cmd[0] = '\0'; + + len = add_win_cmd_modifiers(ex_cmd, &cmdmod, &multi_mods); + assert(len < sizeof(ex_cmd)); + int result = snprintf(ex_cmd + len, sizeof(ex_cmd) - len, " new"); + assert(result > 0); + len += (size_t)result; + } else { + int result = snprintf(ex_cmd, sizeof(ex_cmd), "enew%s", eap->forceit ? "!" : ""); + assert(result > 0); + len += (size_t)result; + } + + assert(len < sizeof(ex_cmd)); if (*eap->arg != NUL) { // Run {cmd} in 'shell'. char *name = vim_strsave_escaped(eap->arg, "\"\\"); - snprintf(ex_cmd, sizeof(ex_cmd), - ":enew%s | call termopen(\"%s\")", - eap->forceit ? "!" : "", name); + snprintf(ex_cmd + len, sizeof(ex_cmd) - len, + " | call termopen(\"%s\")", name); xfree(name); } else { // No {cmd}: run the job with tokenized 'shell'. if (*p_sh == NUL) { @@ -7327,9 +7346,8 @@ static void ex_terminal(exarg_T *eap) } shell_free_argv(argv); - snprintf(ex_cmd, sizeof(ex_cmd), - ":enew%s | call termopen([%s])", - eap->forceit ? "!" : "", shell_argv + 1); + snprintf(ex_cmd + len, sizeof(ex_cmd) - len, + " | call termopen([%s])", shell_argv + 1); } do_cmdline_cmd(ex_cmd);