As far I researched, terminfo/termcap and ioctl don't allow to query character at (x,y) position on terminal's screen. This is rather unexpected, because:
one can read e.g. screen dimensions from terminal (e.g. tput co, tput li),
one can read input from terminal
– the two mean that communication with terminal is bidirectional. Is there really no way to query a character at given position, like with *inch*, *in_wch* curses functions (which work only for curses windows)?
That's expected (not "unexpected"):
tput gives values from a combination of the terminal database (fixed) and the operating system (changeable), but does not ask the terminal.
reading from the terminal is by an input stream from the device (what terminals are designed to do).
Some (not all) terminals support an escape sequence which asks the terminal where the cursor is. The resize program uses that to obtain the screensize. But keep in mind that it is known to be terminal-dependent, as mentioned in the manual page:
-s [rows columns]
This option indicates that Sun console escape sequences will be
used instead of the VT100-style xterm escape codes.
Very few terminals support an escape sequence which will simply read characters from the screen. Not everyone likes the notion of a program that can read their screen — perhaps without their knowledge.
Related
The standard xterm program has a Tek4014 emulation for some simple graphics output. This is however not implemented in most (all?) sucessors, like rxvt, gnome-terminal, or kterm.
However, almost all X11 terminals report xterm as (part of) the environment variable TERM, which makes it difficult for a program to determine whether the underlying terminal has graphics capabilities.
Is it possible to find that out programmatically? And, are there modern terminal windows (beside xterm) that implement Tek4014 graphics, maybe as an add-on?
Actually kterm provides Tek4014 emulation according to its menus. You are probably referring to KDE konsole, which does not. TeraTerm (a Windows application) reportedly also supports the feature.
Back to the point: there is no useful method for telling if a given terminal supports a given feature. Some terminals return status information which tells what type of terminal it is, and what optional features it may have (based on the device responses from DEC and similar terminals). The Tektronix terminal had no such status query/response (refer to XTerm Control Sequences).
Relying upon the status responses in any case doesn't give much assurance since some developers hard-code responses to match xterm.
Since the terminal will not tell you, the only way to verify that would be by actual inspection. Someone might construct a program that could do screendumps and verify that the terminal responds to the sequences, but there's still the pitfall that the switching between vt100(or similar) and tek4014 may not be done with the same escape sequence used in xterm. After all, that escape sequence is not in the standard repertoire of any hardware terminal.
If you have access to the X11 display on which the terminal runs you can do the following. Output the "enter Tektronix mode" escape sequence "\E[?38h" and watch for a new window to open. The WM_CLIENT_LEADER property should probably be the ID of the original terminal window, and the WM_CLASS property should probably contain "tektronix" (I have only checked with the actual xterm application).
If you need to do this from your text-mode application, you can try checking whether a switch to the Tek window actually does something. For example,
echo -en '\n\E[?38h' && echo -en 12345678 && echo -en '\E\003' && \
echo -en '\e[6n' && sleep 1 && echo -en '\n'
prints a newline, switches to the Tek window, prints some characters there, returns back to the VT window, and request the cursor position report. Since all the printing was in the Tek mode, the cursor should remain in column 1. However if the terminal doesn't support the Tek mode, the characters would be printed in the main window and the column would be >1.
The send device attributes sequence will cause the terminal to reply back with a cryptic string. Programs like vim use this to probe what version of xterm they are dealing with, but I don't know of specific documentation to interpret the results. Perhaps reading source?
See:
What is the ANSI escape code sequence "ESC[>c"?
Try it yourself:
printf "\E[c\n" ; sleep 1 ; echo
My non-xterm xterm compatible terminal says "\E[?1;2c" back.
One of my Emacs keybindings is C-', which works well in GUI. In terminal however, it is not being recognised. I understand that I need to figure out the actual characters sent to the terminal by C-' and map it in the emacs config.
Following the advice of https://unix.stackexchange.com/questions/76566/where-do-i-find-a-list-of-terminal-key-codes-to-remap-shortcuts-in-bash, sed -n l is returning back to me a an empty line, even without the ending $. Does Terminal not recognise the C-' sequence at all?
It depends on your terminal emulator. Emacs-the-GUI essentially is a terminal plus Emacs, so it is reading keystrokes directly from the keyboard (well, via the OS, but you can ignore that detail). As such, it can interpret any keystroke it receives. Your terminal emulator, however, is by default treating Control-' as a plain ', so you'll have to configure it to pass a different character (or character sequence) through to whatever process is running in the current terminal window.
Every now and then when using the ack-vim plugin the font in my window will change to all symbols. I've yet to see any pattern to when this happens. Any suggestions on the cause and possible remedy would be appreciated.
I've seen that happen when binary content got printed to the terminal. Do your Ack queries potentially include binary files?
A fix might be
:!echo -e '\ec\e(K\e[J'
These ANSI Escape sequences attempt to reset the terminal:
# "ESC c" - sends reset to the terminal.
# "ESC ( K" - reloads the screen output mapping table.
# "ESC [ J" - erases display.
This looks like the typical character set translation enabled by the Shift Out control character; you usually just need to send the Shift In control character to counteract it.
Basically, something is outputting a C-n character (Control-N, U+000E, named Shift Out) which tells your terminal to switch to a different display character set. You should be able to get your terminal to switch back to the normal display character set by sending a C-o (Control-O, U+000F, named Shift In) to it.
If you are in Vim, then you can probably send the C-o with a command like this:
:!printf \\017
You will have to type (or paste) this command “blindly” since (due to the alternate character set) you will probably not be able to read what you are typing. If you are typing it (not pasting), then you can also type C-v C-o (to insert a single, literal C-o) instead of the backslashed octal, if that is easier to remember.
If you find that this problem occurs only sporadically when you use the vim-ack plugin, then perhaps some bit of the text results contains the problematic Shift Out character. You might try searching for the file with a command like this:
grep -FRl $(printf \\016) .
Once you know the names of the files, then you should be able to use Vim to search for the character (start a search and type C-v C-n to insert a literal C-n). Maybe it is just some garbage that you can clean out, or maybe you can configure your ack-based searches to exclude the problematic files.
You also tagged the question with tmux. I can not tell for sure, but it looks like the top line might be a tmux status line. Since this line is also corrupted it indicates that it your external terminal emulator that has switched character sets, not just one of your tmux panes.
If you send Shift Out or Shift In directly to a tmux pane it will only affect that pane (each pane is emulated independently), so your status like could not have been munged just by a stray Shift Out hitting a single pane.
If you are running inside tmux, then the easiest way to reset the outside terminal is to suspend and resume your tmux client (or detach from and reattach to your session). tmux pretty much resets the outside terminal when it gives up control.
Depending on the situation, you may also have to reset the character set of the tmux pane by sending it a C-o, too (i.e. printf \\017 at a shell, or a :! prompt in Vim).
It is easy to see how a stray Shift Out could reconfigure a single tmux pane, but it is harder to see how it could have “leaked” out to reconfigure the external terminal (tmux is pretty good at isolating things like this). However, there is a control sequence that tmux recognizes that instructs it to pass data directly to the external terminal (thus “leaking out”), but it is much less likely that you would randomly encounter this sequence since it is much longer:
printf '\ePtmux;%s\e\\' 'stuff bound for the external terminal'
You could use it to send the restorative Shift In like this:
printf '\ePtmux;%s\e\\' $(printf \\017)
You will also want to tell tmux to redraw itself after this (by default, the refresh-client command is bound to C-b r).
It is probably easier to just suspend and resume (or detach and reattach), but this sequence is useful if that is not possible. It also provides a means toward understanding what kind of sequence might “leak” out of tmux to switch the character set of the external terminal.
It seems that we only use '\0'(null),'\a'(bell),'\b'(backspace),'\t'(horizontal tab),'\n'(line fee),'\r'(carriage return),'\v'(vertical tab),'\e'(escape).
Where are the other ASCII control characters?Whats the usage of other ASCII contorl characters?Do they still act as control command of printer?
thanks.
They are all here.
They were designed for control of terminals really, not just printers. It was pretty common back in the day on 80x24 character terminals to need to hit Ctrl-S (0x13 or XOFF) to pause output and Ctrl-Q (0x11 or XON) to unpause it again. Ctrl-G (0x07 or BEL) make the terminal beep. I suppose that could have worked on a printer too, but it would have to have been a really loud beep to be heard over those old chain printers.
Ctrl-S, Q, and G still work on most shells. The Windows shell doesn't do anything with G, but S and Q work.
CR and LF are of course still used in terminals, although they don't do quite what you'd expect from their printer definitions. On most OSes LF is used to terminate lines. Some old Macs just use CR, and Windows likes to use both.
I'm using curses to develop a small console application.
I have a main loop section which waits for user input, it uses the getstr function, of course this waits for the user to press enter.
I would like to capture the up and down and tab keypresses. I suppose this can't be done with getstr.
Anyone have any idea how to do this?
EDIT: I've tried using STDIN.getc wihch blocks the application from running, and getch doesn't catch the arrow keys.
EDIT #2: I'm trying this code on Windows. It seems that Curses.getch works for Linux, but on Windows I get no key sent for the up arrow.
You need to set the "cbreak" mode of the tty so that you get keypresses immediately. If you don't do this, the Unix terminal-handling system will buffer the input until a newline is received (i.e., the user hits ENTER), and the input will all be handed to the process at that point.
This isn't actually Ruby- or even curses-specific; this is the way all applications work that run through a Unix tty.
Try using the curses library cbreak() function to turn on this mode. Don't forget to call nocbreak() to turn it off before you exit!
For reading a single character, STDIN.getc will return a Fixnum of the ASCII code of the character. Quite possibly you'll find STDIN.read(1) to be more convenient, since it returns a one-character string of the next character.
However, you'll find that the "up/down" keys,if by that you mean the arrow keys, are actually a sequence of characters. On most ANSI-like terminal emulators these days (such as xterm), the up arrow will be "\e[A" (that \e is an escape character) for example. There are termcap (terminal capability) databases to deal with this sort of thing, and you can access them through curses, but intially you may find it easiest just to experiment with interpreting these directly; you're not very likely to run into a terminal using anything other than ANSI codes these days.
you want getch rather than getstr. also see curt sampson's comment about the arrow keys not being a single character.