I'm trying to get some pressed keys control a piece of software.
And I'm using ANSI escapes to control terminal screen output.
Both works nicely in separate tests, but assembled the former
seems to affect the latter. So I am looking for hints/caveats on
what I am possibly doing wrong.
The "poll pressed key" function is basically derived from Steven's
APUE book (tty_cbreak). The main functional parts are the following >settings...
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
and
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
I'm trying to get some pressed keys control a piece of software.
And I'm using ANSI escapes to control terminal screen output.
Both works nicely in separate tests, but assembled the former
seems to affect the latter. So I am looking for hints/caveats on
what I am possibly doing wrong.
The "poll pressed key" function is basically derived from Steven's
APUE book (tty_cbreak). The main functional parts are the following >settings...
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
and
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
On Tue, 19 Dec 2023 10:46:02 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
I'm trying to get some pressed keys control a piece of software.
And I'm using ANSI escapes to control terminal screen output.
Make sure your terminal is 100% ANSI compatible. Not all are - some codes will
work, others won't and others can cause odd behaviour.
Both works nicely in separate tests, but assembled the former
seems to affect the latter. So I am looking for hints/caveats on
what I am possibly doing wrong.
The "poll pressed key" function is basically derived from Steven's
APUE book (tty_cbreak). The main functional parts are the following
settings...
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
I've never had to use that, try removing it to see if it helps.
and
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
Instead of TCSAFLUSH try TCSANOW and make sure you check the return code
for -1.
Also are you sure fd is stdin? Perhaps use STDIN_FILENO.
I'm trying to get some pressed keys control a piece of software.
And I'm using ANSI escapes to control terminal screen output.
Both works nicely in separate tests, but assembled the former
seems to affect the latter. So I am looking for hints/caveats on
what I am possibly doing wrong.
The "poll pressed key" function is basically derived from Steven's
APUE book (tty_cbreak). The main functional parts are the following settings...
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
and
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
Given that there are bazillions of flags to set or clear; is
there anything I should add or omit? (Or something else I should
have an eye on?)
I'm trying to get some pressed keys control a piece of software.
And I'm using ANSI escapes to control terminal screen output.
Both works nicely in separate tests, but assembled the former
seems to affect the latter. So I am looking for hints/caveats on
what I am possibly doing wrong.
The "poll pressed key" function is basically derived from Steven's
APUE book (tty_cbreak). The main functional parts are the following >settings...
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
and
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
Given that there are bazillions of flags to set or clear; is
there anything I should add or omit? (Or something else I should
have an eye on?)
Scott Lurndal, dans le message <92kgN.11545$5Hnd.7072@fx03.iad>, a
écrit :
Use poll(2) instead of read(2). IIRC, O_NONBLOCK doesn't necessarily
apply to PTYs.
O_NONBLOCK applies to ptys, and if it did not then poll() would not either.
diag = ::tcgetattr
What is this ugly horror?
On Tue, 19 Dec 2023 10:46:02 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
I've never had to use that, try removing it to see if it helps.
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
Instead of TCSAFLUSH try TCSANOW [...]
Use poll(2) instead of read(2). IIRC, O_NONBLOCK doesn't necessarily
apply to PTYs.
diag = ::tcgetattr
Use poll(2) instead of read(2). [...]
diag = ::tcgetattr(u_ttyfd, &u_term_attr_orig);
if (diag == -1) {
u_logger->log("%s: Unable to get attributes for '%s': %s\n",
u_appname, devname, strerror(errno));
goto leave;
}
u_term_attr_cur = u_term_attr_orig;
::cfmakeraw(&u_term_attr_cur);
u_term_attr_cur.c_lflag = 0;
u_term_attr_cur.c_oflag |= OPOST|ONLCR;
diag = ::tcsetattr(u_ttyfd, TCSANOW, &u_term_attr_cur);
if (diag == -1) {
u_logger->log("%s: Unable to set attributes for '%s': %s\n",
u_appname, devname, strerror(errno));
goto leave;
}
u_term_attr_set = true;
Also are you sure fd is stdin? Perhaps use STDIN_FILENO.
On 19.12.2023 18:04, Scott Lurndal wrote:
Use poll(2) instead of read(2). [...]
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
It isn't explicitly mentioned in the man-page, but I assume a
timeout value of 0 will actually do the non-blocking behavior
with poll(2).
diag = ::tcgetattr(u_ttyfd, &u_term_attr_orig);
if (diag == -1) {
u_logger->log("%s: Unable to get attributes for '%s': %s\n",
u_appname, devname, strerror(errno));
goto leave;
}
u_term_attr_cur = u_term_attr_orig;
::cfmakeraw(&u_term_attr_cur);
u_term_attr_cur.c_lflag = 0;
u_term_attr_cur.c_oflag |= OPOST|ONLCR;
diag = ::tcsetattr(u_ttyfd, TCSANOW, &u_term_attr_cur);
if (diag == -1) {
u_logger->log("%s: Unable to set attributes for '%s': %s\n",
u_appname, devname, strerror(errno));
goto leave;
}
u_term_attr_set = true;
At the moment I don't understand what this code does; I suppose
I'll have to look up all those flags first.
Scott Lurndal, dans le message <92kgN.11545$5Hnd.7072@fx03.iad>, a
écrit :
Use poll(2) instead of read(2). IIRC, O_NONBLOCK doesn't necessarily
apply to PTYs.
O_NONBLOCK applies to ptys, and if it did not then poll() would not either.
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
[...]
(You can ignore the leading :: on system calls, that's a C++-ism).
Den 2023-12-19 skrev Kaz Kylheku <433-929-6894@kylheku.com>:
On 2023-12-19, Nicolas George <nicolas$george@salle-s.org> wrote:
Scott Lurndal, dans le message <92kgN.11545$5Hnd.7072@fx03.iad>, aI don't believe that true. There is no requirement that non-blocking
écrit :
Use poll(2) instead of read(2). IIRC, O_NONBLOCK doesn't necessarily
apply to PTYs.
O_NONBLOCK applies to ptys, and if it did not then poll() would not either. >>
objects be used with poll, at least if you are only reading.
When a descriptor polls positive for input, then a subsequent input
operation will not block. There is no requirement to use O_NONBLOCK, or
for the device to support it.
You're right that O_NONBLOCK is not needed for polling since polling
consists of the polling process asking the driver if it has data
available and if the device doesn't, the process is put to sleep until
data is available or the timeout is hit.
On the other hand, I can't really imagine a scenario where it would
make sense for a device to be pollable, but not support non-blocking
reads. If you can tell whether data is ready, you should be able to
support non-blocking reads.
On 2023-12-19, Nicolas George <nicolas$george@salle-s.org> wrote:
Scott Lurndal, dans le message <92kgN.11545$5Hnd.7072@fx03.iad>, a
écrit :
Use poll(2) instead of read(2). IIRC, O_NONBLOCK doesn't necessarily
apply to PTYs.
O_NONBLOCK applies to ptys, and if it did not then poll() would not either.
I don't believe that true. There is no requirement that non-blocking
objects be used with poll, at least if you are only reading.
When a descriptor polls positive for input, then a subsequent input
operation will not block. There is no requirement to use O_NONBLOCK, or
for the device to support it.
You need O_NONBLOCK if you're polling for writing, because a positive
write poll only tells you that there is some buffer space available,
without indicating how much. If the device is blocking and the
subsequent write is too large, it can still block.
However, I think, logically, one byte must be guaranteed: if a blocking device polls positive for writing, we can be confident we can do a one
byte write without blocking, provided the device isn't shared with
any other process that could stuff it behind our back.
Den 2023-12-19 skrev Kaz Kylheku <433-929-6894@kylheku.com>:
O_NONBLOCK applies to ptys, and if it did not then poll() would not either.I don't believe that true. There is no requirement that non-blocking
objects be used with poll, at least if you are only reading.
When a descriptor polls positive for input, then a subsequent input
operation will not block. There is no requirement to use O_NONBLOCK, or
for the device to support it.
int diag = ioctl(tty_fd, FIONREAD, &num_to_read);
On 19.12.2023 11:04, Muttley@dastardlyhq.com wrote:
On Tue, 19 Dec 2023 10:46:02 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
I've never had to use that, try removing it to see if it helps.
I am confused. - I removed that fcntl() call completely and the output
wasn't affected any more in the observed negative way. - Why that?
Don't I need to use non-blocking I/O for a poll?
(Or is maybe buf.c_cc[VMIN] = 1 serving the same purpose?)
But why has a non-blocking input definition an effect on _output_?
You see me puzzled.
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
Instead of TCSAFLUSH try TCSANOW [...]
I tried this change, but it had no visible effect (neither to the good
nor to the bad).
On Tue, 19 Dec 2023 20:02:46 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
On 19.12.2023 11:04, Muttley@dastardlyhq.com wrote:
On Tue, 19 Dec 2023 10:46:02 +0100
Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
fcntl (STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
I've never had to use that, try removing it to see if it helps.
I am confused. - I removed that fcntl() call completely and the output
wasn't affected any more in the observed negative way. - Why that?
Don't I need to use non-blocking I/O for a poll?
(Or is maybe buf.c_cc[VMIN] = 1 serving the same purpose?)
But why has a non-blocking input definition an effect on _output_?
You see me puzzled.
struct termios buf;
buf.c_lflag &= ~(ECHO | ICANON);
buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;
tcsetattr(fd, TCSAFLUSH, &buf);
Instead of TCSAFLUSH try TCSANOW [...]
I tried this change, but it had no visible effect (neither to the good
nor to the bad).
Sorry I can't help any more. The above code has always worked for me.
Your proposal also works with TCSAFLUSH, so TCSANOW at least doesn't
seem necessary. Since you said I should "try" TCSANOW - which seemed
to imply no strict reason to use it - I also wanted to give feedback
on that part.
So thanks again. I don't know *why* it works (or rather, why it didn't
work before), but now [without the fcntl()] it does. :-)
[*] It would certainly have been good if I'd understand why the fcntl()
on stdin was in the way, and why it affected output. - But okay, that's
just my honest desire to try to understand what I'm doing. ;-)
TCSAFLUSH is evil; if your user is a fast typist who can enter keyboard
input before your program has initialized, they will find that their
buffered keystrokes were lost. You won't easily see it in a small
program whose executable and libraries are cache hot, and which doesn't
read a lot of startup files and such.
[...]
If you only care about changing input parameters, you want TCSANOW.
If any of your options affect output, you may want any previously
written, buffered output (not just by your program but anything that
came before!) to be drained before the changes take effect, for
which there is TCSADRAIN.
On 2023-12-20, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
So thanks again. I don't know *why* it works (or rather, why it didn't
work before), but now [without the fcntl()] it does. :-)
Are you using C stdio after setting STDIN_FILENO to nonblocking?
If so, you will be constantly getting errors on stdin whenever the
underlying descriptor returns EWOULDBLOCK. Every time that happens
you have to call clearerr(stdin).
The only reason you'd want the descriptor nonblocking is that your
program has some busy calculation to do during which it needs to
periodically check for TTY input.
As soon as your program has nothing to do but wait for input,
you'd need to use poll() or select(), or else switch the descriptor
to blocking again. So as not to sit in a tight loop calling the
nonblocking read.
[*] It would certainly have been good if I'd understand why the fcntl()
on stdin was in the way, and why it affected output. - But okay, that's
just my honest desire to try to understand what I'm doing. ;-)
Probably because your program blows through the non-blocking reads,
which affects its behavior. Output that would not have been produced
until a keystroke is read is now produced immediately, or whatever.
On 2023-12-20, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
Your proposal also works with TCSAFLUSH, so TCSANOW at least doesn't
seem necessary. Since you said I should "try" TCSANOW - which seemed
to imply no strict reason to use it - I also wanted to give feedback
on that part.
TCSAFLUSH is evil; if your user is a fast typist who can enter keyboard
input before your program has initialized, they will find that their
buffered keystrokes were lost. You won't easily see it in a small
program whose executable and libraries are cache hot, and which doesn't
read a lot of startup files and such.
(Vim does this annoying flush thing. I posted about it to the mailing
list many years ago and was rudely dismissed.)
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2023-12-20, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
Your proposal also works with TCSAFLUSH, so TCSANOW at least doesn't
seem necessary. Since you said I should "try" TCSANOW - which seemed
to imply no strict reason to use it - I also wanted to give feedback
on that part.
TCSAFLUSH is evil; if your user is a fast typist who can enter keyboard
input before your program has initialized, they will find that their
buffered keystrokes were lost. You won't easily see it in a small
program whose executable and libraries are cache hot, and which doesn't
read a lot of startup files and such.
(Vim does this annoying flush thing. I posted about it to the mailing
list many years ago and was rudely dismissed.)
Lol. Do you have a message-id or something? I'd love to have a look.
On 2023-12-21, Julieta Shem <jshem@yaxenu.org> wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
On 2023-12-20, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote: >>>> Your proposal also works with TCSAFLUSH, so TCSANOW at least doesn't
seem necessary. Since you said I should "try" TCSANOW - which seemed
to imply no strict reason to use it - I also wanted to give feedback
on that part.
TCSAFLUSH is evil; if your user is a fast typist who can enter keyboard
input before your program has initialized, they will find that their
buffered keystrokes were lost. You won't easily see it in a small
program whose executable and libraries are cache hot, and which doesn't
read a lot of startup files and such.
(Vim does this annoying flush thing. I posted about it to the mailing
list many years ago and was rudely dismissed.)
Lol. Do you have a message-id or something? I'd love to have a look.
According to my own mail archives, I first posted about it to the
vim@vim.org mailing list on 2012-03-27 with the subject
"Typeahead character loss when running Vim.".
I think I got no reply, so I pinged the topic, sme subject line with Re: prepended, on 2014-02-18, almost two years later.
I don't see any of the replies in my archives, though I subscribed
to the list at the time. I might have looked at the archive for
the reply.
I'm using Vim 7.3 on Ubuntu 11.x.
When I run $ vim file.txt from the shell, and start typing a command
like /quicksort,
some of the characters end up missing. It might end up /quickt.
I type very fast and can queue up quite a bunch of keystrokes, which I
expect to be executed properly.
This is especially annoying when the character loss turns a harmless positioning
command into an edit which then has to be undone.
Looks like Vim may be discarding some characters (or telling the TTY
driver to do that).
Hello?
I asked this nearly two years ago; doesn't anyone else have this problem?
Is it fixed in newer versions of Vim?
On an Ubuntu 11.04 which has a dated version of Vim, if I do this:
$ vim some_file
and upon hitting enter, immediately type, "io", sometimes Vim ends up in command mode as if nothing was typed, then sometimes it ends up in an
insert on the same line, and the character o has been entered, as expected. Most of the time, though, one of the other four possibilities happens,
based on which of the two characters is dropped, or both: it's in command mode, insert mode on the same line, or insert mdoe with a new line having been o)pened.
Kaz Kylheku <433-929-6894@kylheku.com> writes:[...]
On 2023-12-21, Julieta Shem <jshem@yaxenu.org> wrote:
Kaz Kylheku <433-929-6894@kylheku.com> writes:
TCSAFLUSH is evil; if your user is a fast typist who can enter keyboard >>>> input before your program has initialized, they will find that their
buffered keystrokes were lost. You won't easily see it in a small
program whose executable and libraries are cache hot, and which doesn't >>>> read a lot of startup files and such.
(Vim does this annoying flush thing. I posted about it to the mailing
list many years ago and was rudely dismissed.)
Lol. Do you have a message-id or something? I'd love to have a look.
According to my own mail archives, I first posted about it to the
vim@vim.org mailing list on 2012-03-27 with the subject
"Typeahead character loss when running Vim.".
I think I got no reply, so I pinged the topic, sme subject line with Re:
prepended, on 2014-02-18, almost two years later.
I don't see any of the replies in my archives, though I subscribed
to the list at the time. I might have looked at the archive for
the reply.
You got two replies in 2014. Have a look at
https://groups.google.com/g/vim_use/c/XX6SoxHAzhI
[ from the archives; character loss on Vim startup ]
On 27.03.2012 14:33, Kaz Kylheku wrote:
When I run $ vim file.txt from the shell, and start typing a command
like /quicksort,
some of the characters end up missing. It might end up /quickt.
On 22.12.2023 06:33, Julieta Shem wrote:
[ from the archives; character loss on Vim startup ]
On 27.03.2012 14:33, Kaz Kylheku wrote:
When I run $ vim file.txt from the shell, and start typing a command
like /quicksort,
some of the characters end up missing. It might end up /quickt.
For this specific but not uncommon usecase - to start and immediately
locate the desired place - you could work around the issue by starting
$ vim +/quicksort file.txt
instead of
$ vim file.txt
/quicksort
Doesn't address the Vim issue directly but may result in a better user experience of the interface for fast typers.
(It certainly will be difficult to change habits, though, to relocate
the first command to the vim call. Myself I also first start the tool.)
On 19.12.2023 18:04, Scott Lurndal wrote:
Use poll(2) instead of read(2). [...]
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
It isn't explicitly mentioned in the man-page, but I assume a
timeout value of 0 will actually do the non-blocking behavior
with poll(2).
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 299 |
Nodes: | 16 (2 / 14) |
Uptime: | 81:13:29 |
Calls: | 6,696 |
Calls today: | 1 |
Files: | 12,229 |
Messages: | 5,347,754 |