Note: this isn't completely finished, but wanted to send it out now.
Add the "!" flag to 'guioptions' to try it out. Try:
:!cat testdir/color_ramp.txt
Report problems if you see them (or send a patch! :-).
Patch 8.0.1609
Problem: Shell commands in the GUI use a dumb terminal.
Solution: Add the "!" flag to 'guioptions' to execute system commands in a
special terminal window. Only for Unix now.
Files: src/os_unix.c, src/option.h, src/evalfunc.c, src/terminal.c,
src/proto/terminal.pro, src/channel.c, src/proto/channel.pro,
src/vim.h, runtime/doc/options.txt
*** ../vim-8.0.1608/src/os_unix.c 2018-03-05 21:59:33.214889934 +0100
--- src/os_unix.c 2018-03-16 20:42:01.367637679 +0100
***************
*** 4154,4163 ****
return wait_pid;
}
! #if defined(FEAT_JOB_CHANNEL) || !defined(USE_SYSTEM) || defined(PROTO)
/*
* Parse "cmd" and put the white-separated parts in "argv".
! * "argv" is an allocated array with "argc" entries.
* Returns FAIL when out of memory.
*/
int
--- 4154,4166 ----
return wait_pid;
}
! #if defined(FEAT_JOB_CHANNEL) \
! || !defined(USE_SYSTEM) \
! || (defined(FEAT_GUI) && defined(FEAT_TERMINAL)) \
! || defined(PROTO)
/*
* Parse "cmd" and put the white-separated parts in "argv".
! * "argv" is an allocated array with "argc" entries and room for 4 more.
* Returns FAIL when out of memory.
*/
int
***************
*** 4359,4366 ****
# endif
}
! int
! mch_call_shell(
char_u *cmd,
int options) /* SHELL_*, see vim.h */
{
--- 4362,4482 ----
# endif
}
! #if !defined(USE_SYSTEM) || (defined(FEAT_GUI) && defined(FEAT_TERMINAL))
!
! static int
! build_argv(
! char_u *cmd,
! char ***argvp,
! char_u **sh_tofree,
! char_u **shcf_tofree)
! {
! char **argv = NULL;
! int argc;
!
! *sh_tofree = vim_strsave(p_sh);
! if (*sh_tofree == NULL) /* out of memory */
! return FAIL;
!
! if (mch_parse_cmd(*sh_tofree, TRUE, &argv, &argc) == FAIL)
! return FAIL;
! *argvp = argv;
!
! if (cmd != NULL)
! {
! char_u *s;
! char_u *p;
!
! if (extra_shell_arg != NULL)
! argv[argc++] = (char *)extra_shell_arg;
!
! /* Break 'shellcmdflag' into white separated parts. This doesn't
! * handle quoted strings, they are very unlikely to appear. */
! *shcf_tofree = alloc((unsigned)STRLEN(p_shcf) + 1);
! if (*shcf_tofree == NULL) /* out of memory */
! return FAIL;
! s = *shcf_tofree;
! p = p_shcf;
! while (*p != NUL)
! {
! argv[argc++] = (char *)s;
! while (*p && *p != ' ' && *p != TAB)
! *s++ = *p++;
! *s++ = NUL;
! p = skipwhite(p);
! }
!
! argv[argc++] = (char *)cmd;
! }
! argv[argc] = NULL;
! return OK;
! }
! #endif
!
! #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
! /*
! * Use a terminal window to run a shell command in.
! */
! static int
! mch_call_shell_terminal(
! char_u *cmd,
! int options UNUSED) /* SHELL_*, see vim.h */
! {
! jobopt_T opt;
! char **argv = NULL;
! char_u *tofree1 = NULL;
! char_u *tofree2 = NULL;
! int retval = -1;
! buf_T *buf;
! aco_save_T aco;
! oparg_T oa; /* operator arguments */
!
! if (build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
! goto theend;
!
! init_job_options(&opt);
! ch_log(NULL, "starting terminal for system command '%s'", cmd);
! buf = term_start(NULL, argv, &opt, TERM_START_SYSTEM);
!
! /* Find a window to make "buf" curbuf. */
! aucmd_prepbuf(&aco, buf);
!
! clear_oparg(&oa);
! while (term_use_loop())
! {
! if (oa.op_type == OP_NOP && oa.regname == NUL && !VIsual_active)
! {
! /* If terminal_loop() returns OK we got a key that is handled
! * in Normal model. We don't do redrawing anyway. */
! if (terminal_loop(TRUE) == OK)
! normal_cmd(&oa, TRUE);
! }
! else
! normal_cmd(&oa, TRUE);
! }
! retval = 0;
! ch_log(NULL, "system command finished");
!
! /* restore curwin/curbuf and a few other things */
! aucmd_restbuf(&aco);
!
! wait_return(TRUE);
! do_buffer(DOBUF_WIPE, DOBUF_FIRST, FORWARD, buf->b_fnum, TRUE);
!
! theend:
! vim_free(argv);
! vim_free(tofree1);
! vim_free(tofree2);
! return retval;
! }
! #endif
!
! #ifdef USE_SYSTEM
! /*
! * Use system() to start the shell: simple but slow.
! */
! static int
! mch_call_shell_system(
char_u *cmd,
int options) /* SHELL_*, see vim.h */
{
***************
*** 4369,4375 ****
char *ofn = NULL;
#endif
int tmode = cur_tmode;
- #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
char_u *newcmd; /* only needed for unix */
int x;
--- 4485,4490 ----
***************
*** 4443,4456 ****
restore_clipboard();
# endif
return x;
! #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
127, some shells use that already */
# define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
! char_u *newcmd;
pid_t pid;
pid_t wpid = 0;
pid_t wait_pid = 0;
--- 4558,4580 ----
restore_clipboard();
# endif
return x;
+ }
! #else /* USE_SYSTEM */
# define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
127, some shells use that already */
# define OPEN_NULL_FAILED 123 /* Exit code if /dev/null can't be opened */
! /*
! * Don't use system(), use fork()/exec().
! */
! static int
! mch_call_shell_fork(
! char_u *cmd,
! int options) /* SHELL_*, see vim.h */
! {
! int tmode = cur_tmode;
pid_t pid;
pid_t wpid = 0;
pid_t wait_pid = 0;
***************
*** 4461,4468 ****
# endif
int retval = -1;
char **argv = NULL;
! int argc;
! char_u *p_shcf_copy = NULL;
int i;
char_u *p;
int pty_master_fd = -1; /* for pty's */
--- 4585,4592 ----
# endif
int retval = -1;
char **argv = NULL;
! char_u *tofree1 = NULL;
! char_u *tofree2 = NULL;
int i;
char_u *p;
int pty_master_fd = -1; /* for pty's */
***************
*** 4474,4517 ****
int pipe_error = FALSE;
int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
- newcmd = vim_strsave(p_sh);
- if (newcmd == NULL) /* out of memory */
- goto error;
-
out_flush();
if (options & SHELL_COOKED)
settmode(TMODE_COOK); /* set to normal mode */
! if (mch_parse_cmd(newcmd, TRUE, &argv, &argc) == FAIL)
goto error;
- if (cmd != NULL)
- {
- char_u *s;
-
- if (extra_shell_arg != NULL)
- argv[argc++] = (char *)extra_shell_arg;
-
- /* Break 'shellcmdflag' into white separated parts. This doesn't
- * handle quoted strings, they are very unlikely to appear. */
- p_shcf_copy = alloc((unsigned)STRLEN(p_shcf) + 1);
- if (p_shcf_copy == NULL) /* out of memory */
- goto error;
- s = p_shcf_copy;
- p = p_shcf;
- while (*p != NUL)
- {
- argv[argc++] = (char *)s;
- while (*p && *p != ' ' && *p != TAB)
- *s++ = *p++;
- *s++ = NUL;
- p = skipwhite(p);
- }
-
- argv[argc++] = (char *)cmd;
- }
- argv[argc] = NULL;
-
/*
* For the GUI, when writing the output into the buffer and when reading
* input from the buffer: Try using a pseudo-tty to get the stdin/stdout
--- 4598,4610 ----
int pipe_error = FALSE;
int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
out_flush();
if (options & SHELL_COOKED)
settmode(TMODE_COOK); /* set to normal mode */
! if (build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
goto error;
/*
* For the GUI, when writing the output into the buffer and when reading
* input from the buffer: Try using a pseudo-tty to get the stdin/stdout
***************
*** 5319,5326 ****
MSG_PUTS(_("\nCommand terminated\n"));
}
}
- vim_free(argv);
- vim_free(p_shcf_copy);
error:
if (!did_settmode)
--- 5412,5417 ----
***************
*** 5329,5339 ****
# ifdef FEAT_TITLE
resettitle();
# endif
! vim_free(newcmd);
return retval;
!
#endif /* USE_SYSTEM */
}
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
--- 5420,5447 ----
# ifdef FEAT_TITLE
resettitle();
# endif
! vim_free(argv);
! vim_free(tofree1);
! vim_free(tofree2);
return retval;
! }
#endif /* USE_SYSTEM */
+
+ int
+ mch_call_shell(
+ char_u *cmd,
+ int options) /* SHELL_*, see vim.h */
+ {
+ #if defined(FEAT_GUI) && defined(FEAT_TERMINAL)
+ if (gui.in_use && vim_strchr(p_go, GO_TERMINAL) != NULL)
+ return mch_call_shell_terminal(cmd, options);
+ #endif
+ #ifdef USE_SYSTEM
+ return mch_call_shell_system(cmd, options);
+ #else
+ return mch_call_shell_fork(cmd, options);
+ #endif
}
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
*** ../vim-8.0.1608/src/option.h 2018-03-09 21:33:29.244607400 +0100
--- src/option.h 2018-03-13 21:25:36.660819811 +0100
***************
*** 214,219 ****
--- 214,220 ----
#define SHM_ALL "rmfixlnwaWtToOsAIcqF" /* all possible flags
for 'shm' */
/* characters for p_go: */
+ #define GO_TERMINAL '!' /* use terminal for system commands */
#define GO_ASEL 'a' /* autoselect */
#define GO_ASELML 'A' /* autoselect modeless selection */
#define GO_BOT 'b' /* use bottom scrollbar */
***************
*** 236,242 ****
#define GO_FOOTER 'F' /* add footer */
#define GO_VERTICAL 'v' /* arrange dialog buttons vertically */
#define GO_KEEPWINSIZE 'k' /* keep GUI window size */
! #define GO_ALL "aAbcefFghilmMprtTvk" /* all possible flags for
'go' */
/* flags for 'comments' option */
#define COM_NEST 'n' /* comments strings nest */
--- 237,243 ----
#define GO_FOOTER 'F' /* add footer */
#define GO_VERTICAL 'v' /* arrange dialog buttons vertically */
#define GO_KEEPWINSIZE 'k' /* keep GUI window size */
! #define GO_ALL "!aAbcefFghilmMprtTvk" /* all possible flags
for 'go' */
/* flags for 'comments' option */
#define COM_NEST 'n' /* comments strings nest */
*** ../vim-8.0.1608/src/evalfunc.c 2018-03-12 22:16:33.261746681 +0100
--- src/evalfunc.c 2018-03-13 21:44:12.065740473 +0100
***************
*** 7032,7038 ****
rettv->v_type = VAR_JOB;
if (check_restricted() || check_secure())
return;
! rettv->vval.v_job = job_start(argvars, NULL);
}
/*
--- 7032,7038 ----
rettv->v_type = VAR_JOB;
if (check_restricted() || check_secure())
return;
! rettv->vval.v_job = job_start(argvars, NULL, NULL);
}
/*
*** ../vim-8.0.1608/src/terminal.c 2018-03-13 13:13:56.715070346 +0100
--- src/terminal.c 2018-03-16 20:40:09.108192020 +0100
***************
*** 38,47 ****
* in tl_scrollback are no longer used.
*
* TODO:
! * - When using 'termguicolors' still use the 16 ANSI colors as-is. Helps for
! * - In the GUI use a terminal emulator for :!cmd. Make the height the same
as
! * the window and position it higher up when it gets filled, so it looks
like
! * the text scrolls up.
* - implement term_setsize()
* - Copy text in the vterm to the Vim buffer once in a while, so that
* completion works.
--- 38,51 ----
* in tl_scrollback are no longer used.
*
* TODO:
! * - Make terminal close by default when started without a command. Add
! * ++noclose argument.
! * - Win32: In the GUI use a terminal emulator for :!cmd.
! * - Add a way to set the 16 ANSI colors, to be used for 'termguicolors' and
in
! * the GUI.
! * - Some way for the job running in the terminal to send a :drop command back
! * to the Vim running the terminal. Should be usable by a simple shell or
! * python script.
* - implement term_setsize()
* - Copy text in the vterm to the Vim buffer once in a while, so that
* completion works.
***************
*** 104,109 ****
--- 108,117 ----
VTerm *tl_vterm;
job_T *tl_job;
buf_T *tl_buffer;
+ #if defined(FEAT_GUI)
+ int tl_system; /* when non-zero used for :!cmd output
*/
+ int tl_toprow; /* row with first line of system
terminal */
+ #endif
/* Set when setting the size of a vterm, reset after redrawing. */
int tl_vterm_size_changed;
***************
*** 175,184 ****
/*
* Functions with separate implementation for MS-Windows and Unix-like
systems.
*/
! static int term_and_job_init(term_T *term, typval_T *argvar, jobopt_T *opt);
static int create_pty_only(term_T *term, jobopt_T *opt);
static void term_report_winsize(term_T *term, int rows, int cols);
static void term_free_vterm(term_T *term);
/* The character that we know (or assume) that the terminal expects for the
* backspace key. */
--- 183,195 ----
/*
* Functions with separate implementation for MS-Windows and Unix-like
systems.
*/
! static int term_and_job_init(term_T *term, typval_T *argvar, char **argv,
jobopt_T *opt);
static int create_pty_only(term_T *term, jobopt_T *opt);
static void term_report_winsize(term_T *term, int rows, int cols);
static void term_free_vterm(term_T *term);
+ #ifdef FEAT_GUI
+ static void update_system_term(term_T *term);
+ #endif
/* The character that we know (or assume) that the terminal expects for the
* backspace key. */
***************
*** 209,214 ****
--- 220,235 ----
static void
set_term_and_win_size(term_T *term)
{
+ #ifdef FEAT_GUI
+ if (term->tl_system)
+ {
+ /* Use the whole screen for the system command. However, it will start
+ * at the command line and scroll up as needed, using tl_toprow. */
+ term->tl_rows = Rows;
+ term->tl_cols = Columns;
+ }
+ else
+ #endif
if (*curwin->w_p_tms != NUL)
{
char_u *p = vim_strchr(curwin->w_p_tms, 'x') + 1;
***************
*** 236,242 ****
* Initialize job options for a terminal job.
* Caller may overrule some of them.
*/
! static void
init_job_options(jobopt_T *opt)
{
clear_job_options(opt);
--- 257,263 ----
* Initialize job options for a terminal job.
* Caller may overrule some of them.
*/
! void
init_job_options(jobopt_T *opt)
{
clear_job_options(opt);
***************
*** 301,312 ****
/*
* Start a terminal window and return its buffer.
! * When "without_job" is TRUE only create the buffer, b_term and open the
! * window.
* Returns NULL when failed.
*/
! static buf_T *
! term_start(typval_T *argvar, jobopt_T *opt, int without_job, int forceit)
{
exarg_T split_ea;
win_T *old_curwin = curwin;
--- 322,338 ----
/*
* Start a terminal window and return its buffer.
! * Use either "argvar" or "argv", the other must be NULL.
! * When "flags" has TERM_START_NOJOB only create the buffer, b_term and open
! * the window.
* Returns NULL when failed.
*/
! buf_T *
! term_start(
! typval_T *argvar,
! char **argv,
! jobopt_T *opt,
! int flags)
{
exarg_T split_ea;
win_T *old_curwin = curwin;
***************
*** 334,359 ****
term->tl_cursor_visible = TRUE;
term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
term->tl_finish = opt->jo_term_finish;
ga_init2(&term->tl_scrollback, sizeof(sb_line_T), 300);
vim_memset(&split_ea, 0, sizeof(split_ea));
if (opt->jo_curwin)
{
/* Create a new buffer in the current window. */
! if (!can_abandon(curbuf, forceit))
{
no_write_message();
vim_free(term);
return NULL;
}
if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
! ECMD_HIDE + (forceit ? ECMD_FORCEIT : 0), curwin) == FAIL)
{
vim_free(term);
return NULL;
}
}
! else if (opt->jo_hidden)
{
buf_T *buf;
--- 360,390 ----
term->tl_cursor_visible = TRUE;
term->tl_cursor_shape = VTERM_PROP_CURSORSHAPE_BLOCK;
term->tl_finish = opt->jo_term_finish;
+ #ifdef FEAT_GUI
+ term->tl_system = (flags & TERM_START_SYSTEM);
+ #endif
ga_init2(&term->tl_scrollback, sizeof(sb_line_T), 300);
vim_memset(&split_ea, 0, sizeof(split_ea));
if (opt->jo_curwin)
{
/* Create a new buffer in the current window. */
! if (!can_abandon(curbuf, flags & TERM_START_FORCEIT))
{
no_write_message();
vim_free(term);
return NULL;
}
if (do_ecmd(0, NULL, NULL, &split_ea, ECMD_ONE,
! ECMD_HIDE
! + ((flags & TERM_START_FORCEIT) ? ECMD_FORCEIT : 0),
! curwin) == FAIL)
{
vim_free(term);
return NULL;
}
}
! else if (opt->jo_hidden || (flags & TERM_START_SYSTEM))
{
buf_T *buf;
***************
*** 418,423 ****
--- 449,456 ----
if (opt->jo_term_name != NULL)
curbuf->b_ffname = vim_strsave(opt->jo_term_name);
+ else if (argv != NULL)
+ curbuf->b_ffname = vim_strsave((char_u *)"!system");
else
{
int i;
***************
*** 476,487 ****
set_term_and_win_size(term);
setup_job_options(opt, term->tl_rows, term->tl_cols);
! if (without_job)
return curbuf;
#if defined(FEAT_SESSION)
/* Remember the command for the session file. */
! if (opt->jo_term_norestore)
{
term->tl_command = vim_strsave((char_u *)"NONE");
}
--- 509,520 ----
set_term_and_win_size(term);
setup_job_options(opt, term->tl_rows, term->tl_cols);
! if (flags & TERM_START_NOJOB)
return curbuf;
#if defined(FEAT_SESSION)
/* Remember the command for the session file. */
! if (opt->jo_term_norestore || argv != NULL)
{
term->tl_command = vim_strsave((char_u *)"NONE");
}
***************
*** 533,544 ****
}
/* System dependent: setup the vterm and maybe start the job in it. */
! if (argvar->v_type == VAR_STRING
&& argvar->vval.v_string != NULL
&& STRCMP(argvar->vval.v_string, "NONE") == 0)
res = create_pty_only(term, opt);
else
! res = term_and_job_init(term, argvar, opt);
newbuf = curbuf;
if (res == OK)
--- 566,578 ----
}
/* System dependent: setup the vterm and maybe start the job in it. */
! if (argv == NULL
! && argvar->v_type == VAR_STRING
&& argvar->vval.v_string != NULL
&& STRCMP(argvar->vval.v_string, "NONE") == 0)
res = create_pty_only(term, opt);
else
! res = term_and_job_init(term, argvar, argv, opt);
newbuf = curbuf;
if (res == OK)
***************
*** 546,564 ****
/* Get and remember the size we ended up with. Update the pty. */
vterm_get_size(term->tl_vterm, &term->tl_rows, &term->tl_cols);
term_report_winsize(term, term->tl_rows, term->tl_cols);
/* Make sure we don't get stuck on sending keys to the job, it leads to
* a deadlock if the job is waiting for Vim to read. */
channel_set_nonblock(term->tl_job->jv_channel, PART_IN);
! if (!opt->jo_hidden)
{
++curbuf->b_locked;
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
--curbuf->b_locked;
}
!
! if (old_curbuf != NULL)
{
--curbuf->b_nwindows;
curbuf = old_curbuf;
--- 580,605 ----
/* Get and remember the size we ended up with. Update the pty. */
vterm_get_size(term->tl_vterm, &term->tl_rows, &term->tl_cols);
term_report_winsize(term, term->tl_rows, term->tl_cols);
+ #ifdef FEAT_GUI
+ if (term->tl_system)
+ {
+ /* display first line below typed command */
+ term->tl_toprow = msg_row + 1;
+ term->tl_dirty_row_end = 0;
+ }
+ #endif
/* Make sure we don't get stuck on sending keys to the job, it leads to
* a deadlock if the job is waiting for Vim to read. */
channel_set_nonblock(term->tl_job->jv_channel, PART_IN);
! if (old_curbuf == NULL)
{
++curbuf->b_locked;
apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
--curbuf->b_locked;
}
! else
{
--curbuf->b_nwindows;
curbuf = old_curbuf;
***************
*** 572,578 ****
return NULL;
}
! apply_autocmds(EVENT_TERMINALOPEN, NULL, NULL, FALSE, curbuf);
return newbuf;
}
--- 613,619 ----
return NULL;
}
! apply_autocmds(EVENT_TERMINALOPEN, NULL, NULL, FALSE, newbuf);
return newbuf;
}
***************
*** 671,677 ****
argvar[0].v_type = VAR_STRING;
argvar[0].vval.v_string = cmd;
argvar[1].v_type = VAR_UNKNOWN;
! term_start(argvar, &opt, FALSE, eap->forceit);
vim_free(tofree);
theend:
--- 712,718 ----
argvar[0].v_type = VAR_STRING;
argvar[0].vval.v_string = cmd;
argvar[1].v_type = VAR_UNKNOWN;
! term_start(argvar, NULL, &opt, eap->forceit ? TERM_START_FORCEIT : 0);
vim_free(tofree);
theend:
***************
*** 833,839 ****
{
if (term->tl_normal_mode)
return;
! setcursor();
if (redraw)
{
if (term->tl_buffer == curbuf && term->tl_cursor_visible)
--- 874,886 ----
{
if (term->tl_normal_mode)
return;
! #ifdef FEAT_GUI
! if (term->tl_system)
! windgoto(term->tl_cursor_pos.row + term->tl_toprow,
! term->tl_cursor_pos.col);
! else
! #endif
! setcursor();
if (redraw)
{
if (term->tl_buffer == curbuf && term->tl_cursor_visible)
***************
*** 867,872 ****
--- 914,928 ----
ch_log(channel, "writing %d bytes to terminal", (int)len);
term_write_job_output(term, msg, len);
+ #ifdef FEAT_GUI
+ if (term->tl_system)
+ {
+ /* show system output, scrolling up the screen as needed */
+ update_system_term(term);
+ update_cursor(term, TRUE);
+ }
+ else
+ #endif
/* In Terminal-Normal mode we are displaying the buffer, not the terminal
* contents, thus no screen update is needed. */
if (!term->tl_normal_mode)
***************
*** 1905,1915 ****
while (blocking || vpeekc_nomap() != NUL)
{
! /* TODO: skip screen update when handling a sequence of keys. */
! /* Repeat redrawing in case a message is received while redrawing. */
! while (must_redraw != 0)
! if (update_screen(0) == FAIL)
! break;
update_cursor(curbuf->b_term, FALSE);
restore_cursor = TRUE;
--- 1961,1975 ----
while (blocking || vpeekc_nomap() != NUL)
{
! #ifdef FEAT_GUI
! if (!curbuf->b_term->tl_system)
! #endif
! /* TODO: skip screen update when handling a sequence of keys. */
! /* Repeat redrawing in case a message is received while redrawing.
! */
! while (must_redraw != 0)
! if (update_screen(0) == FAIL)
! break;
update_cursor(curbuf->b_term, FALSE);
restore_cursor = TRUE;
***************
*** 2586,2591 ****
--- 2646,2784 ----
}
/*
+ * Fill one screen line from a line of the terminal.
+ * Advances "pos" to past the last column.
+ */
+ static void
+ term_line2screenline(VTermScreen *screen, VTermPos *pos, int max_col)
+ {
+ int off = screen_get_current_line_off();
+
+ for (pos->col = 0; pos->col < max_col; )
+ {
+ VTermScreenCell cell;
+ int c;
+
+ if (vterm_screen_get_cell(screen, *pos, &cell) == 0)
+ vim_memset(&cell, 0, sizeof(cell));
+
+ c = cell.chars[0];
+ if (c == NUL)
+ {
+ ScreenLines[off] = ' ';
+ if (enc_utf8)
+ ScreenLinesUC[off] = NUL;
+ }
+ else
+ {
+ if (enc_utf8)
+ {
+ int i;
+
+ /* composing chars */
+ for (i = 0; i < Screen_mco
+ && i + 1 < VTERM_MAX_CHARS_PER_CELL; ++i)
+ {
+ ScreenLinesC[i][off] = cell.chars[i + 1];
+ if (cell.chars[i + 1] == 0)
+ break;
+ }
+ if (c >= 0x80 || (Screen_mco > 0
+ && ScreenLinesC[0][off] != 0))
+ {
+ ScreenLines[off] = ' ';
+ ScreenLinesUC[off] = c;
+ }
+ else
+ {
+ ScreenLines[off] = c;
+ ScreenLinesUC[off] = NUL;
+ }
+ }
+ #ifdef WIN3264
+ else if (has_mbyte && c >= 0x80)
+ {
+ char_u mb[MB_MAXBYTES+1];
+ WCHAR wc = c;
+
+ if (WideCharToMultiByte(GetACP(), 0, &wc, 1,
+ (char*)mb, 2, 0, 0) > 1)
+ {
+ ScreenLines[off] = mb[0];
+ ScreenLines[off + 1] = mb[1];
+ cell.width = mb_ptr2cells(mb);
+ }
+ else
+ ScreenLines[off] = c;
+ }
+ #endif
+ else
+ ScreenLines[off] = c;
+ }
+ ScreenAttrs[off] = cell2attr(cell.attrs, cell.fg, cell.bg);
+
+ ++pos->col;
+ ++off;
+ if (cell.width == 2)
+ {
+ if (enc_utf8)
+ ScreenLinesUC[off] = NUL;
+
+ /* don't set the second byte to NUL for a DBCS encoding, it
+ * has been set above */
+ if (enc_utf8 || !has_mbyte)
+ ScreenLines[off] = NUL;
+
+ ++pos->col;
+ ++off;
+ }
+ }
+ }
+
+ static void
+ update_system_term(term_T *term)
+ {
+ VTermPos pos;
+ VTermScreen *screen;
+
+ if (term->tl_vterm == NULL)
+ return;
+ screen = vterm_obtain_screen(term->tl_vterm);
+
+ /* Scroll up to make more room for terminal lines if needed. */
+ while (term->tl_toprow > 0
+ && (Rows - term->tl_toprow) < term->tl_dirty_row_end)
+ {
+ int save_p_more = p_more;
+
+ p_more = FALSE;
+ msg_row = Rows - 1;
+ msg_puts((char_u *)"\n");
+ p_more = save_p_more;
+ --term->tl_toprow;
+ }
+
+ for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
+ && pos.row < Rows; ++pos.row)
+ {
+ if (pos.row < term->tl_rows)
+ {
+ int max_col = MIN(Columns, term->tl_cols);
+
+ term_line2screenline(screen, &pos, max_col);
+ }
+ else
+ pos.col = 0;
+
+ screen_line(term->tl_toprow + pos.row, 0, pos.col, Columns, FALSE);
+ }
+
+ term->tl_dirty_row_start = MAX_ROW;
+ term->tl_dirty_row_end = 0;
+ update_cursor(term, TRUE);
+ }
+
+ /*
* Called to update a window that contains an active terminal.
* Returns FAIL when there is no terminal running in this window or in
* Terminal-Normal mode.
***************
*** 2650,2739 ****
for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
&& pos.row < wp->w_height; ++pos.row)
{
- int off = screen_get_current_line_off();
- int max_col = MIN(wp->w_width, term->tl_cols);
-
if (pos.row < term->tl_rows)
{
! for (pos.col = 0; pos.col < max_col; )
! {
! VTermScreenCell cell;
! int c;
!
! if (vterm_screen_get_cell(screen, pos, &cell) == 0)
! vim_memset(&cell, 0, sizeof(cell));
!
! c = cell.chars[0];
! if (c == NUL)
! {
! ScreenLines[off] = ' ';
! if (enc_utf8)
! ScreenLinesUC[off] = NUL;
! }
! else
! {
! if (enc_utf8)
! {
! int i;
!
! /* composing chars */
! for (i = 0; i < Screen_mco
! && i + 1 < VTERM_MAX_CHARS_PER_CELL; ++i)
! {
! ScreenLinesC[i][off] = cell.chars[i + 1];
! if (cell.chars[i + 1] == 0)
! break;
! }
! if (c >= 0x80 || (Screen_mco > 0
! && ScreenLinesC[0][off] != 0))
! {
! ScreenLines[off] = ' ';
! ScreenLinesUC[off] = c;
! }
! else
! {
! ScreenLines[off] = c;
! ScreenLinesUC[off] = NUL;
! }
! }
! #ifdef WIN3264
! else if (has_mbyte && c >= 0x80)
! {
! char_u mb[MB_MAXBYTES+1];
! WCHAR wc = c;
! if (WideCharToMultiByte(GetACP(), 0, &wc, 1,
! (char*)mb, 2, 0, 0) > 1)
! {
! ScreenLines[off] = mb[0];
! ScreenLines[off + 1] = mb[1];
! cell.width = mb_ptr2cells(mb);
! }
! else
! ScreenLines[off] = c;
! }
! #endif
! else
! ScreenLines[off] = c;
! }
! ScreenAttrs[off] = cell2attr(cell.attrs, cell.fg, cell.bg);
!
! ++pos.col;
! ++off;
! if (cell.width == 2)
! {
! if (enc_utf8)
! ScreenLinesUC[off] = NUL;
!
! /* don't set the second byte to NUL for a DBCS encoding, it
! * has been set above */
! if (enc_utf8 || !has_mbyte)
! ScreenLines[off] = NUL;
!
! ++pos.col;
! ++off;
! }
! }
}
else
pos.col = 0;
--- 2843,2853 ----
for (pos.row = term->tl_dirty_row_start; pos.row < term->tl_dirty_row_end
&& pos.row < wp->w_height; ++pos.row)
{
if (pos.row < term->tl_rows)
{
! int max_col = MIN(wp->w_width, term->tl_cols);
! term_line2screenline(screen, &pos, max_col);
}
else
pos.col = 0;
***************
*** 3623,3629 ****
/* TODO: use the file name arguments for the buffer name */
opt.jo_term_name = (char_u *)"dump diff";
! buf = term_start(&argvars[0], &opt, TRUE, FALSE);
if (buf != NULL && buf->b_term != NULL)
{
int i;
--- 3737,3743 ----
/* TODO: use the file name arguments for the buffer name */
opt.jo_term_name = (char_u *)"dump diff";
! buf = term_start(&argvars[0], NULL, &opt, TERM_START_NOJOB);
if (buf != NULL && buf->b_term != NULL)
{
int i;
***************
*** 4396,4402 ****
if (opt.jo_vertical)
cmdmod.split = WSP_VERT;
! buf = term_start(&argvars[0], &opt, FALSE, FALSE);
if (buf != NULL && buf->b_term != NULL)
rettv->vval.v_number = buf->b_fnum;
--- 4510,4516 ----
if (opt.jo_vertical)
cmdmod.split = WSP_VERT;
! buf = term_start(&argvars[0], NULL, &opt, 0);
if (buf != NULL && buf->b_term != NULL)
rettv->vval.v_number = buf->b_fnum;
***************
*** 4592,4597 ****
--- 4706,4712 ----
term_and_job_init(
term_T *term,
typval_T *argvar,
+ char **argv UNUSED,
jobopt_T *opt)
{
WCHAR *cmd_wchar = NULL;
***************
*** 4880,4897 ****
* Create a new terminal of "rows" by "cols" cells.
* Start job for "cmd".
* Store the pointers in "term".
* Return OK or FAIL.
*/
static int
term_and_job_init(
term_T *term,
typval_T *argvar,
jobopt_T *opt)
{
create_vterm(term, term->tl_rows, term->tl_cols);
! /* This will change a string in "argvar". */
! term->tl_job = job_start(argvar, opt);
if (term->tl_job != NULL)
++term->tl_job->jv_refcount;
--- 4995,5014 ----
* Create a new terminal of "rows" by "cols" cells.
* Start job for "cmd".
* Store the pointers in "term".
+ * When "argv" is not NULL then "argvar" is not used.
* Return OK or FAIL.
*/
static int
term_and_job_init(
term_T *term,
typval_T *argvar,
+ char **argv,
jobopt_T *opt)
{
create_vterm(term, term->tl_rows, term->tl_cols);
! /* This may change a string in "argvar". */
! term->tl_job = job_start(argvar, argv, opt);
if (term->tl_job != NULL)
++term->tl_job->jv_refcount;
*** ../vim-8.0.1608/src/proto/terminal.pro 2018-03-11 19:30:40.128142740
+0100
--- src/proto/terminal.pro 2018-03-14 22:48:26.777762521 +0100
***************
*** 1,4 ****
--- 1,6 ----
/* terminal.c */
+ void init_job_options(jobopt_T *opt);
+ buf_T *term_start(typval_T *argvar, char **argv, jobopt_T *opt, int flags);
void ex_terminal(exarg_T *eap);
int term_write_session(FILE *fd, win_T *wp);
int term_should_restore(buf_T *buf);
*** ../vim-8.0.1608/src/channel.c 2018-03-10 20:27:32.071757661 +0100
--- src/channel.c 2018-03-13 21:43:30.738004891 +0100
***************
*** 5383,5393 ****
/*
* Create a job and return it. Implements job_start().
* The returned job has a refcount of one.
* Returns NULL when out of memory.
*/
job_T *
! job_start(typval_T *argvars, jobopt_T *opt_arg)
{
job_T *job;
char_u *cmd = NULL;
--- 5383,5395 ----
/*
* Create a job and return it. Implements job_start().
+ * "argv_arg" is only for Unix.
+ * When "argv_arg" is NULL then "argvars" is used.
* The returned job has a refcount of one.
* Returns NULL when out of memory.
*/
job_T *
! job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg)
{
job_T *job;
char_u *cmd = NULL;
***************
*** 5474,5479 ****
--- 5476,5488 ----
job_set_options(job, &opt);
+ #ifdef USE_ARGV
+ if (argv_arg != NULL)
+ {
+ argv = argv_arg;
+ }
+ else
+ #endif
if (argvars[0].v_type == VAR_STRING)
{
/* Command is a string. */
***************
*** 5551,5557 ****
theend:
#ifdef USE_ARGV
! vim_free(argv);
#else
vim_free(ga.ga_data);
#endif
--- 5560,5567 ----
theend:
#ifdef USE_ARGV
! if (argv != argv_arg)
! vim_free(argv);
#else
vim_free(ga.ga_data);
#endif
*** ../vim-8.0.1608/src/proto/channel.pro 2017-12-09 19:13:08.579678220
+0100
--- src/proto/channel.pro 2018-03-13 22:27:20.877173011 +0100
***************
*** 66,72 ****
void job_stop_on_exit(void);
int has_pending_job(void);
void job_check_ended(void);
! job_T *job_start(typval_T *argvars, jobopt_T *opt_arg);
char *job_status(job_T *job);
void job_info(job_T *job, dict_T *dict);
int job_stop(job_T *job, typval_T *argvars, char *type);
--- 66,72 ----
void job_stop_on_exit(void);
int has_pending_job(void);
void job_check_ended(void);
! job_T *job_start(typval_T *argvars, char **argv_arg, jobopt_T *opt_arg);
char *job_status(job_T *job);
void job_info(job_T *job, dict_T *dict);
int job_stop(job_T *job, typval_T *argvars, char *type);
*** ../vim-8.0.1608/src/vim.h 2018-03-11 17:02:07.310194396 +0100
--- src/vim.h 2018-03-13 22:18:13.232722972 +0100
***************
*** 2543,2546 ****
--- 2543,2551 ----
#define REPLACE_CR_NCHAR -1
#define REPLACE_NL_NCHAR -2
+ /* flags for term_start() */
+ #define TERM_START_NOJOB 1
+ #define TERM_START_FORCEIT 2
+ #define TERM_START_SYSTEM 4
+
#endif /* VIM__H */
*** ../vim-8.0.1608/runtime/doc/options.txt 2018-02-22 21:06:44.550819285
+0100
--- runtime/doc/options.txt 2018-03-13 21:22:21.450057261 +0100
***************
*** 3760,3766 ****
To avoid problems with flags that are added in the future, use the
"+=" and "-=" feature of ":set" |add-option-flags|.
! Valid letters are as follows:
*guioptions_a* *'go-a'*
'a' Autoselect: If present, then whenever VISUAL mode is started,
or the Visual area extended, Vim tries to become the owner of
--- 3845,3858 ----
To avoid problems with flags that are added in the future, use the
"+=" and "-=" feature of ":set" |add-option-flags|.
! Valid characters are as follows:
! *'go-!'*
! '!' External commands are executed in a terminal window. Without
! this flag the MS-Windows GUI will open a console window to
! execute the command. The Unix GUI will simulate a dumb
! terminal to list the command output.
! The terminal window will be positioned at the bottom, and grow
! upwards as needed.
*guioptions_a* *'go-a'*
'a' Autoselect: If present, then whenever VISUAL mode is started,
or the Visual area extended, Vim tries to become the owner of
*** ../vim-8.0.1608/src/version.c 2018-03-14 21:38:57.912996023 +0100
--- src/version.c 2018-03-16 20:44:10.622996708 +0100
***************
*** 768,769 ****
--- 768,771 ----
{ /* Add new patch number below this line */
+ /**/
+ 1609,
/**/
--
Don't Panic!
-- The Hitchhiker's Guide to the Galaxy
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.