digitalmars.D.learn - Get single keystroke?
- Sean Eskapp (2/2) Mar 21 2011 Is there a way to get a single keystroke in D2? Any method I've tried re...
- Lars Holowko (34/36) Mar 21 2011 Hi Sean,
- bearophile (4/5) Mar 21 2011 But the need to get a keystroke is simple and not so uncommon, so I thin...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (9/14) Mar 21 2011 think Phobos needs a function to do that that works on both
- Jonathan M Davis (14/20) Mar 21 2011 Assuming that it could be done cleanly, it would be a good function to a...
- Andrej Mitrovic (13/13) Mar 21 2011 Here's something simpler:
- Sean Eskapp (2/15) Mar 21 2011 What extra linker dependencies does this add?
- Andrej Mitrovic (2/17) Mar 21 2011 snn.lib
- Sean Eskapp (3/22) Mar 21 2011 What about on Linux?
- Andrej Mitrovic (8/9) Mar 21 2011 I'm not sure. Both DMD and GDC can run the example on Windows. Perhaps
- Andrej Mitrovic (1/1) Mar 21 2011 It looks like its not available on Linux, I've just tried with DMD.
- Andrej Mitrovic (19/19) Mar 21 2011 I believe I've found you a solution:
- Sean Eskapp (3/22) Mar 21 2011 Great, thanks!
- Andrej Mitrovic (20/20) Mar 21 2011 Woops forgot to add import std.stdio, here's a fixed version:
- teo (5/31) Mar 21 2011 It looks like this can be dangerous, because the terminal can be left in...
- Andrej Mitrovic (5/36) Mar 21 2011 H mentions using tcgetattr to save old state and restoring it with
- =?ISO-8859-1?Q?Ali_=C7ehreli?= (8/47) Mar 21 2011 Thanks for posting this.
- Andrej Mitrovic (3/3) Mar 21 2011 Replace that writefln with this:
Is there a way to get a single keystroke in D2? Any method I've tried requires pushing Enter before the stroke is registered.
Mar 21 2011
On Mon, Mar 21, 2011 at 1:33 PM, Sean Eskapp <eatingstaples gmail.com> wrote:Is there a way to get a single keystroke in D2? Any method I've tried requires pushing Enter before the stroke is registered.Hi Sean, what you want to do is OS dependent. I needed something similar ('press key to continue') e.g.: for Windows import core.sys.windows.windows; bool kbHit() { // inspired by http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1045691686&id=1043284392 HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE); DWORD saveMode; GetConsoleMode(stdIn, &saveMode); SetConsoleMode(stdIn, ENABLE_PROCESSED_INPUT); bool ret = false; if (WaitForSingleObject(stdIn, INFINITE) == WAIT_OBJECT_0) { uint num; char ch; ReadConsoleA(stdIn, &ch, 1, &num, cast(void *) 0L); ret = true; } SetConsoleMode(stdIn, saveMode); return ret; } void wait_for_key() { writeln("\nPress any key to continue"); while (!kbHit()) {} } for Linux/Unix something like http://www.linuxquestions.org/questions/programming-9/kbhit-34027/ should work. Hope that helps, Lars
Mar 21 2011
Lars Holowko:what you want to do is OS dependent.But the need to get a keystroke is simple and not so uncommon, so I think Phobos needs a function to do that that works on both Windows/Linux (and Mac too). Bye, bearophile
Mar 21 2011
On 03/21/2011 02:42 PM, bearophile wrote:Lars Holowko:think Phobos needs a function to do that that works on both Windows/Linux (and Mac too). If D sticks to the C (and C++) heritage, there is no guarantee that there is a keyboard around. The interface is stdin, stdout, and stderr; which are just character streams. But I agree: some subset of ncurses would be nice when a keyboard is available.what you want to do is OS dependent.But the need to get a keystroke is simple and not so uncommon, so IBye, bearophileAli
Mar 21 2011
Lars Holowko:Assuming that it could be done cleanly, it would be a good function to add, but honestly, I dispute that it's a common need in this day and age. If all you need is something like "press any key to continue," you can easily do that with the current functions by having "press enter to continue," and if you need to do something other than that, odds are you need something more powerful like ncurses anyway. Not to mention, I don't think that interactive console apps are all that common these days. They definitely exist, but most console apps essentially run a single command for you and then quit. Most of the types of applications which would have have been interactive console apps in the past are now GUI apps. So, while it certainly wouldn't hurt to add a function like this to Phobos (assuming that it could be done cleanly), I really don't think that it's a common need anymore. - Jonathan M Daviswhat you want to do is OS dependent.But the need to get a keystroke is simple and not so uncommon, so I think Phobos needs a function to do that that works on both Windows/Linux (and Mac too).
Mar 21 2011
Here's something simpler: import std.stdio : writefln; extern(C) int kbhit(); extern(C) int getch(); void main() { while(!kbhit()) { // keep polling // might use thread.sleep here. } writefln("Key hit was %s.", getch()); }
Mar 21 2011
== Quote from Andrej Mitrovic (andrej.mitrovich gmail.com)'s articleHere's something simpler: import std.stdio : writefln; extern(C) int kbhit(); extern(C) int getch(); void main() { while(!kbhit()) { // keep polling // might use thread.sleep here. } writefln("Key hit was %s.", getch()); }What extra linker dependencies does this add?
Mar 21 2011
On 3/21/11, Sean Eskapp <eatingstaples gmail.com> wrote:== Quote from Andrej Mitrovic (andrej.mitrovich gmail.com)'s articlesnn.libHere's something simpler: import std.stdio : writefln; extern(C) int kbhit(); extern(C) int getch(); void main() { while(!kbhit()) { // keep polling // might use thread.sleep here. } writefln("Key hit was %s.", getch()); }What extra linker dependencies does this add?
Mar 21 2011
== Quote from Andrej Mitrovic (andrej.mitrovich gmail.com)'s articleOn 3/21/11, Sean Eskapp <eatingstaples gmail.com> wrote:article== Quote from Andrej Mitrovic (andrej.mitrovich gmail.com)'sWhat about on Linux?snn.libHere's something simpler: import std.stdio : writefln; extern(C) int kbhit(); extern(C) int getch(); void main() { while(!kbhit()) { // keep polling // might use thread.sleep here. } writefln("Key hit was %s.", getch()); }What extra linker dependencies does this add?
Mar 21 2011
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?
Mar 21 2011
It looks like its not available on Linux, I've just tried with DMD.
Mar 21 2011
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.
Mar 21 2011
== Quote from Andrej Mitrovic (andrej.mitrovich gmail.com)'s articleI 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 newstate */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!
Mar 21 2011
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 }
Mar 21 2011
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
Mar 21 2011
On 3/21/11, teo <teo.ubuntu yahoo.com> wrote:On Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote: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.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
Mar 21 2011
On 03/21/2011 03:37 PM, Andrej Mitrovic wrote:On 3/21/11, teo<teo.ubuntu yahoo.com> wrote: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); AliOn Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote: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.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
Mar 21 2011
Replace that writefln with this: writefln("Key hit was %s.", cast(char)getch()); You should get the right key displayed then.
Mar 21 2011