ncurses function keys only returns escape - putty

I'm testing an ncurses program that was running under ncurses5 but recently compiled under curses6 in a new environment (putty/xterm/virtualbox) and can't get it to recognize any function keys. The arrow keys work fine but only those that use an escape sequence appear to fail.
chtype c;
initscr();
start_color();
noecho();
cbreak();
intrflush(stdscr, TRUE);
keypad(stdscr, TRUE);
c=getch();
printf("c=%d\n", (int)c);
Pressing F1 returns "c=27". I'm using putty and tried various settings with TERM set to xterm. Outside of curses, F1 returns \EOP as expected, and I'm using TERM=xterm which appears to define the function key properly in termcap. I understand the keypad() routine is suppose to cause the getch/wgetch routines to return the numeric key equivalent of 265 KEY_F(1), but I can't get anything but 27 with various combos of break, raw, notimeout, etc.

Both putty and xterm have several options for their function-keys. The default configurations for each differ, which you can see using
infocmp putty xterm
and it seems that kf1 (F1) is one of many differences, e.g., (putty on the left, xterm on the right):
kent: NULL, '\EOM'.
kf1: '\E[11~', '\EOP'.
kf13: '\E[25~', '\E[1;2P'.
kf14: '\E[26~', '\E[1;2Q'.
kf15: '\E[28~', '\E[1;2R'.
kf16: '\E[29~', '\E[1;2S'.
kf17: '\E[31~', '\E[15;2~'.
kf18: '\E[32~', '\E[17;2~'.
kf19: '\E[33~', '\E[18;2~'.
kf2: '\E[12~', '\EOQ'.
kf20: '\E[34~', '\E[19;2~'.
kf21: NULL, '\E[20;2~'.
kf22: NULL, '\E[21;2~'.
kf23: NULL, '\E[23;2~'.
kf24: NULL, '\E[24;2~'.
(Some copies of ncurses' terminal database are minimal, but there's a full database which includes the putty description).
If the terminal database doesn't show the key as you're configured, ncurses will not recognize it, and you will see the escape character.

Doh! I finally found there was an alias "alias cmd='TERM=Linux cmd'" in an old .bashrc file, so my TERM was set to linux only for the duration of the command. Stupid simple issue that took hours of debugging to figure out. Lesson learned.

At least on my copy of putty (0.76) the default TERM is set to xterm. As others have explained putty does not use the same escape codes as xterm, so this is definitely an unfortunate default. Set the term option (available in the putty menus before you open the connection) to putty and everything will work right, unless your .bashrc file also overrides the TERM (which would be highly unfortunate).
you can check what your current TERM is: echo $TERM

Related

Vim Command Mapping "Copy to Clipboard" Not Working

I recently began using Vim as my primary editor instead of programs like Atom/VSCode. I added a number of leader mappings to simplify tasks I do quite often but I'm having trouble with a few of them.
In Visual mode, I would like to be able to press <Space>y to copy the current selection to the clipboard (+ register). I've verified that I can do this manually by entering visual mode, selecting the text I want, and pressing "+y. However, my mapping doesn't seem to work:
vmap <Leader>y "+y
I set my leader the following way:
map <Space> <Leader>
I do it this way so that when showcmd is set, I get a visual indicator in operator-pending mode. By looking at that indicator, I can tell that when I press <Space>, I do enter operator pending mode on the \ key as expected. Then, when I press y, I am no longer in operator pending mode, but I am still in visual mode and haven't yanked the selection to the register.
To make sure there wasn't a plugin colliding with my mapping, I backed up my .vimrc and replaced it with one that only has the following contents:
set showcmd
map <Space> <Leader>
vmap <Leader>y "+y
Does one of these keys need to be escaped? Or am I doing something else wrong?
(I'm currently running Ubuntu Bash on Windows. Vim is version 7.4)
For reference, I got the idea from this article (And use the exact same command):
https://sheerun.net/2014/03/21/how-to-boost-your-vim-productivity/
Thankfully, the fix is pretty simple.
map <Space> <Leader>
is incorrect. The right way is
let mapleader=" "
From :help mapleader
*<Leader>* *mapleader*
To define a mapping which uses the "mapleader" variable, the special string
"<Leader>" can be used. It is replaced with the string value of "mapleader".
If "mapleader" is not set or empty, a backslash is used instead. Example: >
:map <Leader>A oanother line<Esc>
Works like: >
:map \A oanother line<Esc>
But after: >
:let mapleader = ","
It works like: >
:map ,A oanother line<Esc>
Note that the value of "mapleader" is used at the moment the mapping is
defined. Changing "mapleader" after that has no effect for already defined
mappings.
How to define the "leader" key is explained under :help mapleader. If you want to use <Space> as "leader" you are supposed to do:
let mapleader = "\<Space>"
Note that the "leader" key is not a special key at all. With <Space> as "leader", the two mappings below are strictly equivalent:
vmap <leader>y "+y
vmap <Space>y "+y

Shortening my prompt in Zsh

I'm having a lot of trouble getting zsh to shorten my prompt. I'm currently using zsh with the agnoster theme and oh-my-zsh package manager.
My prompt currently gets annoyingly long during work, usually around 110 characters, taking up the entire length of my terminal, which is just not very aesthetically pleasing.
I've looked at a few other people's .zshrc's and attempts to modify their prompt, but nothing seems to work in mine. I've tried copying many, many things into my .zshrc and have seen no effects.
My most recent attempt was to try to copy the prompt block from https://stackoverflow.com/a/171564/2416097
Nothing. Even when I disabled my theme while having this block included, the prompt is still at full length.
Additionally, I can't seem to find any simple or straightforward guides on how to format my prompt in the first place. Most of the results I found while searching only yielded long format strings without explanation or instruction on use.
Any help appreciated!
Old question, I know, but as an alternative solution I just discovered powerlevel9k, an extension of agnoster (they appear practically identical bar a fair few tweaks), which has this functionality built in.
Just set it as your zsh theme, then in .zshrc set
POWERLEVEL9K_SHORTEN_DIR_LENGTH=2
which ensures that only two directories are listed.
Alternate options are outlined in the readme.
First you would have to copy the theme into a different one in order to customize it to your liking.
Copy agnoster.zsh-theme to e.g. mytheme.zsh-theme and select it in your .zshrc
Then modify the theme to your liking
I looked at the agnoster theme and found a place where you could save space.
prompt_dir() {
prompt_segment blue $CURRENT_FG ' %~ '
}
could be changed to
prompt_dir() {
prompt_segment blue $CURRENT_FG ' %25<...<%~%<< '
}
This will truncate your path to 25 characters and replacing more with ...
How this works is described in the zsh manual (linked below).
Short explanation is:
%25<...< will truncate everything that is longer than 25 characters to ...
%<< will basically tell zsh that anything after this should not be truncated (limiting the truncation to the path part)
I leave it to you to find more places where you can save space by.
And for more customization needs take a look at zsh: 13 Prompt Expansion
add this to ~/.zshrc
prompt_dir() {
prompt_segment blue $CURRENT_FG '%2~'
}
Explanatory note: %<N>~ will limit the number of path segments leading up to the current directory to N. I.e. %2~ will show only two last segments: the current directory and its parent directory.
In case you stumbled upon this post coming from macOS' zsh like me and want to shorten the prefix/prompt there, I found this article helpful: https://www.makeuseof.com/customize-zsh-prompt-macos-terminal/.
I wanted to remove the name of my MacBook model from the prompt and was able to do so with the following steps:
vim .zshrc
append PROMPT="%n %1~ %# "
Verify with source .zshrc or simply open a new terminal
Before
chris#Christophers-MacBook-Pro ~ %
After
chris ~ %
In the Zsh themes folder you should search for this file agnoster.zsh-theme , open with an editor and change this piece of code :
prompt_dir() {
prompt_segment blue $CURRENT_FG ' %~ '
}
with this :
prompt_dir() {
prompt_segment blue $CURRENT_FG "%c"
}
This will prompt the current directory instead of the full path.

How to edit file content using zsh terminal?

I created an empty directory on zsh and added a file
called hello.rb by doing the following:
echo 'Hello, world.' >hello.rb
If I want to make changes in this file using the terminal
what's the proper way of doing it without opening the file
itself using let's say TextEditor?
I want to be able to make changes in the file hello.rb strictly
by using my zsh terminal, is this at all possible?
Zsh is not a terminal but a shell. The terminal is the window in which the shell executes. The shell is the text program prompting you commands and executing them.
If you want to edit the file within the terminal, then using vim, nano, emacs -nw or any other text-mode text editor will do it. They are not Zsh commands, but external commands that you can call from Zsh or from any other shell.
If you want to edit the file within Zsh, then use zed. You will need to run once (in ~/.zshrc)
autoload zed
and then you can edit hello.rb using:
zed hello.rb
(exit and save with Control-j)
You have already created and edited the file.
To edit it again, you can use the >> to append.
For example
echo "\nAnd you too!\n" >> hello.rb
This would edit the file by concatenating the additional string.
Edit, of course, by your use and definition of 'changing' a file, this is the simplest way to do so using the shell.
In a normal way, though you probably want to use a terminal editor.
Zed is a great answer, but to be even more stripped down - for a level of editing that even a script can do - zsh can hand all 256 characters/byte-values (including null) in variables. This means you can edit line by line or chunk by chunk almost any kind of file data directly from the command-line. This is approximately what zed/vared does. If you have a current version with all the standard modules included, it is a great benefit to have zsh/mapfile or zsh/system loaded so that you can capture any of the characters that are left out by command-expansion (zed uses $(<$file) to read a file to memory). Here is an example of a way you could use this variable manipulation method:
% typeset -T Buffer buffer $'\n'
% typeset -T Edit edit $'\n'
It is most common to use newline to divide a text file one wishes to edit.
This handy feature will make zsh give you full access to one line or a range of lines at a time without unintentionally messing with the data.
% zmodload zsh/mapfile
% Buffer=$mapfile[path/to/file]
Here, I use the handy mapfile module because I can load the contents of a file byte-for-byte. Alternately you can use % Buffer="$(<path/to/file)", like zed does, but you will always have the trailing newlines removed and other word splitting is possible with a typo or environment variation, so the simplicity of the module's method is best. When finished, you save the changes by simply assigning the $Buffer value back to the $mapfile[file] or use a more classic command like printf '%s' $Buffer >path/to/file (this is exact string writing, byte-for-byte, so any newlines or formatting you added back will be written).
You transfer the lines between Buffer and Edit using the mapped arrays as follows, however, remember that in its simplest form assigning one array to another drops elements that are completely empty (one \n \n two \n three becomes one \n two \n three). You can suppress this empty-element removal by quoting the input array and adding an '#' symbol to its index "$buffer[#]", if using the whole array; and adding the '#' symbol to the flags if using a range of the array "${(#)buffer[2,50]}". Preserving empty lines can be a bit troublesome for typing, but these multiple arrays should only be used in a script or function, since you can just edit one line at a time from the command line with buffer[54]="echo This is a newly written line."
% edit=($buffer[50,70])
...
% buffer[50,70]=($edit)
This is standard Zsh syntax, that means in the ... area you can edit and manipulate the $edit array of lines or the $Edit scalar block of text all you want, including adding more lines or taking some away. When you add the lines back into $buffer it will replace the specified block of lines (50-70) with the new lines, automatically expanding or reducing the other array elements to accommodate the reintegrated lines. -- Because of the dynamic array accommodations, you can also just insert whatever you need as a new line like this buffer[40]=("new string as new line" "$buffer[40]"). This inserts it before the index given, while swapping the order of the elements ("$buffer[40]" "new string as new line") inserts the new line after the index given. Either will adjust all following elements, including totally empty elements, to their current index plus one.
If you wanted to re-write the zed function to use this method in some complex way like: newzed /path/to/file [start-line] [end-line], that would be great and handy too.
Before I leave, I wanted to mention that using vared directly, once you have these commands typed on the interactive terminal, you may find it frustrating that you can't use "Enter" for inserting or appending new lines. I found that with my terminal and Zsh version using ESC-ENTER worked well, but I don't know about older versions (Mac usually comes stocked with a not-most-recent version, if my memory is right). If that doesn't work, you may have to do some documentation digging to learn how to set up your ZLE (Zsh Line Editor, a component of Zsh) or acquire a newer version of Zsh. Also, some other shells, when indexing a scalar variable may count by the byte because in ascii and C a byte is the same as a character, but Zsh supports UTF8 and will index a scalar string by the UTF8 character unless you turn off the shell option multibyte (on by default). This will help with manipulating each line if you need to use the old byte-character indexing. Also, if you have a version of Zsh that for whatever was not compiled with zsh/mapfile or zsh/system, then you can achieve a similar effect using number of options to the read builtin, like <path/to/file |read -u 0 -k $[5 * 2**20] -r -s Buffer ||(($#Buffer)). As you can see here, you have to make the read length big enough to accommodate the file's size or it will leave off part of the file, and the read return code will nearly always be an error because of not being able to read the full length of the string. We fix this with ||(($#Buffer)), but this builtin was simply not meant to handle large scale byte manipulation efficiently, so what you see is what you can get from it.

Is it possible to clear the screen within ghostscript?

I could not find the command to clear the screen within ghostscript under windows. Could you please help me?
Thanks.
So you want to clear the text window? How about:
28 { ()= } repeat % output 28 blank lines
[There are several short recipes to output a newline: ()=, ()==, <>=, <>==, / =, (\n)print]
In Linux, you can discover the appropriate terminal control string with infocmp -L|grep clear_screen.
Then you can emit a hex string. (Sadly, the PLRM does not provide (\E) to generate an escape.) For Konsole, it's:
<1b5b481b5b324a> print flush
or
(\033[H\033[2J) print flush
On windows, ghostscript implements its own terminal window; and while it probably has such a code, there is no infocmp to discover what it might be.
erasepage, or showpageif you want to start a new page.

Cygwin BASH and ANSI control sequences

Several things here:
Can anyone point me at C code to decode ANSI console escape sequences?
Is there a way to get Cygwin BASH to emulate a dumb old TTY?
Maybe this should be 2 questions.
Thanks.
It's a somewhat indirect answer, but the GNU ncurses library handles terminals of all sorts. One way of finding out which control sequences are applicable to ANSI terminals would be to decompile an ANSI terminal description:
infocmp ansi
This would give you the set of terminfo attributes that are used by curses programs to achieve effects on an ANSI terminal. Of course, you then have to know what those hieroglyphs mean.
On Cygwin, I got:
$ infocmp ansi
# Reconstructed via infocmp from file: /usr/share/terminfo/61/ansi
ansi|ansi/pc-term compatible with color,
am, mc5i, mir, msgr,
colors#8, cols#80, it#8, lines#24, ncv#3, pairs#64,
acsc=+\020\,\021\030.^Y0\333`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376,
bel=^G, blink=\E[5m, bold=\E[1m, cbt=\E[Z, clear=\E[H\E[J,
cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B,
cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH,
cuu=\E[%p1%dA, cuu1=\E[A, dch=\E[%p1%dP, dch1=\E[P,
dl=\E[%p1%dM, dl1=\E[M, ech=\E[%p1%dX, ed=\E[J, el=\E[K,
el1=\E[1K, home=\E[H, hpa=\E[%i%p1%dG, ht=\E[I, hts=\EH,
ich=\E[%p1%d#, il=\E[%p1%dL, il1=\E[L, ind=^J,
indn=\E[%p1%dS, invis=\E[8m, kbs=^H, kcbt=\E[Z, kcub1=\E[D,
kcud1=\E[B, kcuf1=\E[C, kcuu1=\E[A, khome=\E[H, kich1=\E[L,
mc4=\E[4i, mc5=\E[5i, nel=\r\E[S, op=\E[39;49m,
rep=%p1%c\E[%p2%{1}%-%db, rev=\E[7m, rin=\E[%p1%dT,
rmacs=\E[10m, rmpch=\E[10m, rmso=\E[m, rmul=\E[m,
s0ds=\E(B, s1ds=\E)B, s2ds=\E*B, s3ds=\E+B,
setab=\E[4%p1%dm, setaf=\E[3%p1%dm,
sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
sgr0=\E[0;10m, smacs=\E[11m, smpch=\E[11m, smso=\E[7m,
smul=\E[4m, tbc=\E[3g, u6=\E[%i%d;%dR, u7=\E[6n,
u8=\E[?%[;0123456789]c, u9=\E[c, vpa=\E[%i%p1%dd,
$
The '\E' notation refers to the ESC character.
Failing that, you could look up the standard itself.
Tweaking the TERM environment variable might make applications based on terminfo/termcap avoid using advanced escape sequences. (export TERM=dumb)
I am not sure that's what you want, though.

Resources