I’ve just ported Adventure Definition Language to Linux using WSL.
I’ve encountered a small problem with Terminal command history with ADLRun.
Instead of previous command some characters are displayed: ^[[A for cursor up.
I tried with TermCap and ANSI settings, without luck. I’m not quite sure what’s causing it. Windows and Amiga versions command-history work in Shell without problem.
P.S. If someone that works with Linux could test the ADLRun, I’ll be glad. Thanks.
I had also planned to make macOS version as well - on this basis. All this to spread the ADL games reachability.
Things like ^[[A are what Unix terminals (copying ye-olde hardware terminals) generate for special keys. So you need a library to handle that.
If you are controlling the whole screen, then the ncurses library is commonly used. If you just want to read a line of input, then readline is also commonly used. There are more light-weight equivalents to these libraries. e.g. my own one is called TweakLine.
^[[A are the raw key codes for the up arrow key. It’s up to the running program to interpret them appropriately. Generally programs use a termcap or terminfo library, or something higher level like readline.
In the case of ADL, it looks like it’ll use termcap (or termlib, an even older library) as long as you compile it with TERMCAP set to 1 in include/adltypes.h. Per the porting file, you need to update the makefile to link in the appropriate library by adding -ltermcap or -ltermlib to the cc -o adlrun step.
The ADLRun is reading the line with gets() function.
I know there should be fgets(), but it makes no difference.
It turns out, that the curses, termcap and termlib are only used with the printing, not with the input.
So I checked:
I tried to use readline() function, but I have problem with copying the result string to other string buffer. Anyway, the cursor up/down keys don’t display anything in this case.
I checked the standard shell sh instead of bash and there’s no history at all and the ^[[A is displayed also outside ADLRun.
It’s strange, because history works in Windows CMD and AmigaShell without any problems with very same gets() function.
It might be WSL problem as well. Maybe under real Linux bash history works correctly.
Thank you for help so far. I’m still not sure how I could fix this, because I even couldn’t handle stdin cursor up/down keys.to manage history by myself.
Superb. Thank you very much. I missed the headers <readline/readline.h> which are essential for readline() to work. Otherwise I got segmentation fault errors during execution, because some restrict were not defined.
Now it works as expected. Thanks also for the add_history().
So I just replace the gets() with readline() when there’s UNIX constant defined with #ifdef.
I probably need also to free() the memory allocated with readline().
I would like to share another solution to this problem:
I have found that on Windows there’s a <conio.h> header that gives such functions like getch() to handle raw key codes: arrow keys and function keys. It works great.
In Linux there are ncurses (by advice given by @andrewj and @plover) which works great as well, because it provides very same getch()function. Note: the raw codes bound to keys are different.
In ncurses the console screen is separate and allows to place text anywhere, which is even better.
It’s not available directly on Windows, but <conio.h> does the work.
The only drawback is a need to replace console I/O methods (gets, puts) with these raw ones (I mean those taken from library) - it’s not difficult to implement though.
I can implement command history common for both systems (which was a goal), and - with help of ncurses- even place fixed messages with text-adventure room name etc.
I would like to extend this topic a little, as I’ve written more advanced command history, that works in Windows terminal via mentioned<conio.h>functions.
My history has following properties:
It normally allows for traversal between previous and next commands in history using up/down arrow keys.
Once we exceed the boundary of the saved command list, the command field is cleared to allow entering of new ones,
It remembers history entries (upto some limit) and allows modification of them. This means that we can add, remove or modify some text in the command and it will be saved, so that if we browse the history and return again, the command will be restored with most recent contents.
If we execute the command taken from history, the next saved command will be set as initial value of new command.
We can hit esc key to clean history from the current entry from history to the latest one.
Code in C is quite short, and I can publish it. All normal entering of text as console commands is of course implemented as well.
If you have some thoughts about such history, I’d be glad to hear them. I think that it’s decent thing for any text-adventure system and I plan to add it to ADL.
Some behavior may require polishing, but it works OK overall.