Hi, lists
I'm recognizing that some people reported "echo-backing problem"(see below) at
start-up time on some UNIX terminals.
https://cloud.githubusercontent.com/assets/1162739/6369447/d0fba520-bd29-11e4-9e9f-49b850953db3.png
related issue: https://github.com/saitoha/mouseterm-plus/issues/3
This is easily reproduced by the following command on XTerm:
$ vim -u NONE --noplugin -c "set nocompatible | autocmd VimEnter * call
system('sleep 3')"
or
$ vim -u NONE --noplugin -c "set nocompatible | autocmd Termresponse * call
system('sleep 3')"
I discussed about it with Yukihiro Nakadaira, then propose the following
solution for this problem:
- VIM should use new terminal mode "cbreak"(fig.2) during calling system()
function on UNIX terminals.
- The vim function system() should always be done in non-echo mode without
prepending ":silent", at least on UNIX terminals.
- To keep the program simply, drop "sleep" mode and replace it with
"cbreak" mode.
Now VIM uses 3 terminal modes "raw"(TMODE_RAW), "cooked"(TMODE_COOK), and
"sleep"(TMODE_SLEEP) on UNIX terminals(fig.1).
As same as almost other TUI applications, VIM works with "raw" terminal mode
basically.
But in the following cases, VIM switches the terminal to "cooked" mode
exceptionally.
case 1. when entering shell with ":shell" command
case 2. during running other processes by such as system() function
(required for stopping the child process with <C-c>)
I think it is appropriate to use "cooked" mode in case 1.
But in case 2, "cooked" mode sometimes causes "echo-backing problem" with
coming into contact with "termresponse" feature.
Another mode "sleep"(TMODE_SLEEP) is used in ":sleep" command and the internal
function mch_delay().
Attached patch drops "sleep" mode and introduce new terminal mode
"cbreak"(fig.2).
I found "sleep" mode in current VIM can be replaced with "cbreak" mode.
Additionaly this patch uses "cbreak" mode instead of "cooked" mode in system()
function.
I tested it in OSX10.10 and Linux(Debian sid/CentOS 6.5).
Note:
With this patch, the default behavior of system() is slightly changed.
It comes to be same as the behavior of one always prefixed with ":silent".
But I believe it is no needs to run system() with non-silent(echo on) mode.
Remind that stdin/stdout of the process launched by system() is always
redirected.
fig.1 existing Vim terminal modes
| get input immediately? | signal with ^C | input echo-backing
--------+------------------------+----------------+--------------------
raw | yes | no | no
--------+------------------------+----------------+--------------------
cooked | no | yes | yes
--------+------------------------+----------------+--------------------
sleep | no | yes | no
--------+------------------------+----------------+--------------------
fig.2 new terminal mode "cbreak"
| get input immediately? | signal with ^C | input echo-backing
--------+------------------------+----------------+-------------------
cbreak | yes | yes | no
--------+------------------------+----------------+-------------------
Best regards,
-- Hayaki Saito
--
--
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.
diff -r cf5d9c1e4c8a runtime/doc/eval.txt
--- a/runtime/doc/eval.txt Fri Apr 17 22:08:16 2015 +0200
+++ b/runtime/doc/eval.txt Sat Apr 18 18:00:32 2015 +0900
@@ -6132,11 +6132,8 @@
list items converted to NULs).
Pipes are not used.
- When prepended by |:silent| the shell will not be set to
- cooked mode. This is meant to be used for commands that do
- not need the user to type. It avoids stray characters showing
- up on the screen which require |CTRL-L| to remove. >
- :silent let f = system('ls *.vim')
+ The shell will be set to cbreak mode during execution of the
+ command. It avoids stray characters showing up on the screen.
<
Note: Use |shellescape()| or |::S| with |expand()| or
|fnamemodify()| to escape special characters in a command
diff -r cf5d9c1e4c8a src/diff.c
--- a/src/diff.c Fri Apr 17 22:08:16 2015 +0200
+++ b/src/diff.c Sat Apr 18 18:00:32 2015 +0900
@@ -986,7 +986,7 @@
#ifdef FEAT_AUTOCMD
block_autocmds(); /* Avoid ShellCmdPost stuff */
#endif
- (void)call_shell(buf, SHELL_FILTER | SHELL_COOKED);
+ (void)call_shell(buf, SHELL_FILTER | SHELL_CBREAK);
#ifdef FEAT_AUTOCMD
unblock_autocmds();
#endif
diff -r cf5d9c1e4c8a src/eval.c
--- a/src/eval.c Fri Apr 17 22:08:16 2015 +0200
+++ b/src/eval.c Sat Apr 18 18:00:32 2015 +0900
@@ -18850,10 +18850,9 @@
}
}
- /* Omit SHELL_COOKED when invoked with ":silent". Avoids that the shell
- * echoes typeahead, that messes up the display. */
- if (!msg_silent)
- flags += SHELL_COOKED;
+ /* Set term to cbreak mode to avoid that the shell echoes typeahead,
+ * that messes up the display. */
+ flags |= SHELL_CBREAK;
if (retlist)
{
diff -r cf5d9c1e4c8a src/os_unix.c
--- a/src/os_unix.c Fri Apr 17 22:08:16 2015 +0200
+++ b/src/os_unix.c Sat Apr 18 18:00:32 2015 +0900
@@ -622,7 +622,7 @@
in_mch_delay = TRUE;
old_tmode = curr_tmode;
if (curr_tmode == TMODE_RAW)
- settmode(TMODE_SLEEP);
+ settmode(TMODE_CBREAK);
/*
* Everybody sleeps in a different way...
@@ -3443,8 +3443,12 @@
tnew.c_cc[VMIN] = 1; /* return after 1 char */
tnew.c_cc[VTIME] = 0; /* don't wait */
}
- else if (tmode == TMODE_SLEEP)
- tnew.c_lflag &= ~(ECHO);
+ else if (tmode == TMODE_CBREAK)
+ {
+ tnew.c_lflag &= ~(ICANON | ECHO);
+ tnew.c_cc[VMIN] = 1; /* return after 1 char */
+ tnew.c_cc[VTIME] = 0; /* don't wait */
+ }
# if defined(HAVE_TERMIOS_H)
{
@@ -3483,7 +3487,7 @@
ttybnew.sg_flags &= ~(CRMOD | ECHO);
ttybnew.sg_flags |= RAW;
}
- else if (tmode == TMODE_SLEEP)
+ else if (tmode == TMODE_CBREAK)
ttybnew.sg_flags &= ~(ECHO);
ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
#endif
@@ -4059,7 +4063,9 @@
out_flush();
- if (options & SHELL_COOKED)
+ if (options & SHELL_CBREAK)
+ settmode(TMODE_CBREAK); /* set to normal mode without echo */
+ else if (options & SHELL_COOKED)
settmode(TMODE_COOK); /* set to normal mode */
# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
@@ -4184,7 +4190,9 @@
goto error;
out_flush();
- if (options & SHELL_COOKED)
+ if (options & SHELL_CBREAK)
+ settmode(TMODE_CBREAK); /* set to normal mode without echo */
+ else if (options & SHELL_COOKED)
settmode(TMODE_COOK); /* set to normal mode */
/*
diff -r cf5d9c1e4c8a src/term.h
--- a/src/term.h Fri Apr 17 22:08:16 2015 +0200
+++ b/src/term.h Sat Apr 18 18:00:32 2015 +0900
@@ -165,6 +165,6 @@
#define T_OP (term_str(KS_OP)) /* original color pair */
#define T_U7 (term_str(KS_U7)) /* request cursor position */
-#define TMODE_COOK 0 /* terminal mode for external cmds and Ex mode */
-#define TMODE_SLEEP 1 /* terminal mode for sleeping (cooked but no echo) */
-#define TMODE_RAW 2 /* terminal mode for Normal and Insert mode */
+#define TMODE_COOK 0 /* terminal mode for :shell, ! and Ex mode */
+#define TMODE_CBREAK 1 /* terminal mode for system() and sleeping */
+#define TMODE_RAW 2 /* terminal mode for Normal and Insert mode */
diff -r cf5d9c1e4c8a src/vim.h
--- a/src/vim.h Fri Apr 17 22:08:16 2015 +0200
+++ b/src/vim.h Sat Apr 18 18:00:32 2015 +0900
@@ -975,6 +975,7 @@
#define SHELL_SILENT 16 /* don't print error returned by command */
#define SHELL_READ 32 /* read lines and insert into buffer */
#define SHELL_WRITE 64 /* write lines from buffer */
+#define SHELL_CBREAK 128 /* set term to cbreak mode */
/* Values returned by mch_nodetype() */
#define NODE_NORMAL 0 /* file or directory, check with mch_isdir()*/