March 21, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Sean Eskapp | On 3/21/11, Sean Eskapp <eatingstaples@gmail.com> wrote: > What about on Linux? > I'm not sure. Both DMD and GDC can run the example on Windows. Perhaps they've got these functions implemented for Linux as well. But according to this: https://secure.wikimedia.org/wikipedia/en/wiki/Conio.h it seems these functions are usually only available for compilers targeting Windows. Have you tried compiling it on Linux, or does it fail to link? | |||
March 21, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
It looks like its not available on Linux, I've just tried with DMD. | ||||
March 21, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
I believe I've found you a solution:
import std.c.stdio;
import std.c.linux.termios;
extern(C) void cfmakeraw(termios *termios_p);
void main() {
termios ostate; /* saved tty state */
termios nstate; /* values for editor mode */
// Open stdin in raw mode
/* Adjust output channel */
tcgetattr(1, &ostate); /* save old state */
tcgetattr(1, &nstate); /* get base of new state */
cfmakeraw(&nstate);
tcsetattr(1, TCSADRAIN, &nstate); /* set mode */
// Read characters in raw mode
writefln("The key hit is %s", cast(char)fgetc(stdin));
// Close
tcsetattr(1, TCSADRAIN, &ostate); // return to original mode
}
I've tested this under Ubuntu and DMD 2.052 and it works.
| ||||
March 21, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
Woops forgot to add import std.stdio, here's a fixed version:
import std.stdio : writefln;
import std.c.stdio;
import std.c.linux.termios;
extern(C) void cfmakeraw(termios *termios_p);
void main()
{
termios ostate; /* saved tty state */
termios nstate; /* values for editor mode */
// Open stdin in raw mode
/* Adjust output channel */
tcgetattr(1, &ostate); /* save old state */
tcgetattr(1, &nstate); /* get base of new state */
cfmakeraw(&nstate);
tcsetattr(1, TCSADRAIN, &nstate); /* set mode */
// Read characters in raw mode
writefln("The key hit is %s", cast(char)fgetc(stdin));
// Close
tcsetattr(1, TCSADRAIN, &ostate); // return to original mode
}
| ||||
March 21, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | == Quote from Andrej Mitrovic (andrej.mitrovich@gmail.com)'s article > I believe I've found you a solution: > import std.c.stdio; > import std.c.linux.termios; > extern(C) void cfmakeraw(termios *termios_p); > void main() { > termios ostate; /* saved tty state */ > termios nstate; /* values for editor mode */ > // Open stdin in raw mode > /* Adjust output channel */ > tcgetattr(1, &ostate); /* save old state */ > tcgetattr(1, &nstate); /* get base of new state */ > cfmakeraw(&nstate); > tcsetattr(1, TCSADRAIN, &nstate); /* set mode */ > // Read characters in raw mode > writefln("The key hit is %s", cast(char)fgetc(stdin)); > // Close > tcsetattr(1, TCSADRAIN, &ostate); // return to original mode > } > I've tested this under Ubuntu and DMD 2.052 and it works. Great, thanks! | |||
March 21, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote: > Woops forgot to add import std.stdio, here's a fixed version: > > import std.stdio : writefln; > import std.c.stdio; > import std.c.linux.termios; > > extern(C) void cfmakeraw(termios *termios_p); > > void main() > { > termios ostate; /* saved tty state */ termios > nstate; /* values for editor mode */ > > // Open stdin in raw mode > /* Adjust output channel */ > tcgetattr(1, &ostate); /* save old state */ > tcgetattr(1, &nstate); /* get base of new > state */ cfmakeraw(&nstate); > tcsetattr(1, TCSADRAIN, &nstate); /* set mode */ > > // Read characters in raw mode > writefln("The key hit is %s", cast(char)fgetc(stdin)); > > // Close > tcsetattr(1, TCSADRAIN, &ostate); // return to original mode > } It looks like this can be dangerous, because the terminal can be left in an unusable state. Please read this: http://groups.google.com/group/comp.os.linux.development.apps/ browse_thread/thread/0667d16089e2b6fc | |||
March 21, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to teo | On 3/21/11, teo <teo.ubuntu@yahoo.com> wrote:
> On Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote:
>
>> Woops forgot to add import std.stdio, here's a fixed version:
>>
>> import std.stdio : writefln;
>> import std.c.stdio;
>> import std.c.linux.termios;
>>
>> extern(C) void cfmakeraw(termios *termios_p);
>>
>> void main()
>> {
>> termios ostate; /* saved tty state */ termios
>> nstate; /* values for editor mode */
>>
>> // Open stdin in raw mode
>> /* Adjust output channel */
>> tcgetattr(1, &ostate); /* save old state */
>> tcgetattr(1, &nstate); /* get base of new
>> state */ cfmakeraw(&nstate);
>> tcsetattr(1, TCSADRAIN, &nstate); /* set mode */
>>
>> // Read characters in raw mode
>> writefln("The key hit is %s", cast(char)fgetc(stdin));
>>
>> // Close
>> tcsetattr(1, TCSADRAIN, &ostate); // return to original mode
>> }
>
> It looks like this can be dangerous, because the terminal can be left in an unusable state. Please read this: http://groups.google.com/group/comp.os.linux.development.apps/ browse_thread/thread/0667d16089e2b6fc
>
H mentions using tcgetattr to save old state and restoring it with tcsetattr. This is what this code does. Btw this code is not mine, Walter posted it and I just added the cfmakeraw prototype. So kudos goes to him.
| |||
March 22, 2011 Re: Get single keystroke? | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On 03/21/2011 03:37 PM, Andrej Mitrovic wrote:
> On 3/21/11, teo<teo.ubuntu@yahoo.com> wrote:
>> On Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote:
>>
>>> Woops forgot to add import std.stdio, here's a fixed version:
>>>
>>> import std.stdio : writefln;
>>> import std.c.stdio;
>>> import std.c.linux.termios;
>>>
>>> extern(C) void cfmakeraw(termios *termios_p);
>>>
>>> void main()
>>> {
>>> termios ostate; /* saved tty state */ termios
>>> nstate; /* values for editor mode */
>>>
>>> // Open stdin in raw mode
>>> /* Adjust output channel */
>>> tcgetattr(1,&ostate); /* save old state */
>>> tcgetattr(1,&nstate); /* get base of new
>>> state */ cfmakeraw(&nstate);
>>> tcsetattr(1, TCSADRAIN,&nstate); /* set mode */
>>>
>>> // Read characters in raw mode
>>> writefln("The key hit is %s", cast(char)fgetc(stdin));
>>>
>>> // Close
>>> tcsetattr(1, TCSADRAIN,&ostate); // return to original mode
>>> }
>>
>> It looks like this can be dangerous, because the terminal can be left in
>> an unusable state. Please read this:
>> http://groups.google.com/group/comp.os.linux.development.apps/
>> browse_thread/thread/0667d16089e2b6fc
>>
>
> H mentions using tcgetattr to save old state and restoring it with
> tcsetattr. This is what this code does. Btw this code is not mine,
> Walter posted it and I just added the cfmakeraw prototype. So kudos
> goes to him.
Thanks for posting this.
It can be improved by moving the last tcsetattr to an earlier scope(exit) statement:
termios ostate;
tcgetattr(1, &ostate);
scope (exit) tcsetattr(1, TCSADRAIN, &ostate);
Ali
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply