Reputation: 70277
I am trying to create a basic REPL. If my program is run in a terminal that can support it, I use the termios getchar
to read input character-by-character and respond to special keys, such as the arrow keys. However, if run in a terminal for which that does not make sense, I'd like to switch to good old-fashioned cin.getline
.
The trouble is in detecting whether the terminal has the capabilities I'm looking for. Initially, I was thinking isatty
would do the trick.
#include <cstdio>
#include <iostream>
#include <unistd.h>
int main() {
bool tty = isatty(fileno(stdin));
std::cout << "You are using a TTY: " << std::boolalpha << tty << std::endl;
return 0;
}
This will correctly identify cases where stdin is a pipe or something like that. However, if I'm running a subshell inside Emacs (M-x shell
, specifically), it still identifies as a TTY, even though Emacs captures arrow keys and other special characters and does its own thing with them. What C++ or POSIX functionality can I use that would correctly distinguish between a subshell being run within Emacs and a shell being run with full control inside an "ordinary" terminal?
I'm primarily looking for POSIX solutions here, but Windows-only answers are useful for posterity as well.
Footnote: Yes, I am aware of things like ncurses that handle all of this for me. I would like to do this without using such libraries, to improve my understanding of the terminal environment.
Upvotes: 2
Views: 138
Reputation: 39838
This is the purpose of the TERM
environment variable. You use (low-level) libraries like terminfo to understand (the implications of) the value of TERM
, although recognizing Emacs’ value of “dumb” is easy enough.
Upvotes: 1