How to get one keystroke in D2 (Phobos)?

Is there a simple cross-platform way to get one click of a D2 key using Phobos?

For example, the prompt "Press any key to continue ..." or the Brainfuck interpreter.

All the methods I tried require pressing the Enter key before passing the input (e.g. getchar ()).

+8
input keyboard d d2 phobos
source share
2 answers

I did some research on this, and I found that although the Phobos library under D 1.0 has exactly what you need in the form of std.c.stdio.getch() , D 2.0 does not have this function. None of the other standard input functions in Phobos have the desired behavior.

As I understand it, this is due to the fact that the desired behavior (that is, receiving one character without having to press the enter key) is rather non-standard and should be implemented in relatively ugly, platform-specific ways. (In its original form, the getch function existed in C <conio.h> , a DOS-specific header that became something like de facto, even though it is not part of the C standard library.) Obviously, the developers of the runtime library Phobos decided to exclude this particular bit of feedback-compatible functionality in the name of a cleaner library, but at the expense of that functionality.

Manual ad

It is reported that you can get around this missing function declaration by adding this to the source file:

 extern (C) int getch(); 

However, I found that this leads to a linker error, suggesting that the function was completely removed from the runtime library, and not just its declaration was removed from std.c.stdio . Of course it's worth a try - maybe it works on your system and compiler, I really don't know.

Edit 2: This actually works on Windows; this did not help me on the linux side. It seems that DMD under Windows first refers to the Phobos / D working environment (phobos.lib), then to C (snn.lib); however, on Linux, DMD links to a single runtime library that supplies both parts. This difference, apparently, causes a connection with undeclared functions ( getch among them) only for work in Windows. If Windows is the only platform you relate to, this solution is probably right. If you need more cross-platform compatibility, read on.

Ncurses

Another possibility is to use the ncurses . It implements a getch function that will definitely do what you want - provided that you find it cool to find D bindings for the library or just using the C interface. Keep in mind that this requires a more sophisticated smidgen setup than just calling the function which you want; this thread contains more information on this.

D 1.0

Now for some significantly more ugly solutions. Using D 1.0 will allow you to find what you need in the standard Phobos library, but this obviously means using an older, more rigid version of the language, and I personally do not think that the lack of one IO console function in the standard library is an excuse use the old version of D.

I believe that Tango also lost its getch declaration (under tango.stdc.stdio ) over the D 2.0 switch, but my knowledge of Tango is extremely limited, so I could be wrong.

Write it yourself

If you decide, you can simply write your own getch . I was unable to find a cross-platform implementation of C getch using Google Code Search , which leaves me pessimistic about the likelihood of a relatively simple, 10-line or so functional implementation that can simply be adapted to D.

Walter Bright, on the other hand - you know, the guy who developed the D language - provides an implementation of D of this kind here . However, even this seems a little dated because one of the cfmakeraw characters is undefined in the current version of the DMD2 compiler. However, it is really close to being a workable solution.

+5
source share

The simplest solution that works with D2 on Windows:

 import std.stdio : writefln; extern(C) int kbhit(); extern(C) int getch(); void main() { while(!kbhit()) { // keep polling // might use Thread.Sleep here to avoid taxing the cpu. } writefln("Key hit was %s.", cast(char)getch()); } 

It can work even with D1, but I have not tried it.

Here is the Linux version modified from Post Walter :

 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 } 
+5
source share

All Articles