Arrow keys in insert mode in vim - macos

When I'm in insert mode in vim and I use the arrow keys, it sends what seems like a letter and a carriage return. For example, pressing ↑ it sends:
A
It looks like A\n but I'm not sure exactly what characters/codes it's sending. Why does this occur, and is there a way to disable this?

The usual sequence sent by a terminal for the Up arrow is <Esc>OA or ^[OA (the ^[ sequence represents the <Esc> key, also equivalent to Ctrl+[.)
If your Vim fails to recognize this sequence as the Up arrow, it will end up executing this sequence: <Esc> which will leave Insert mode and go to Normal mode, then O to insert a new line above the current one and go to Insert mode, then insert a literal A since you'd be in Insert mode again.
You can confirm that this is indeed the sequence your terminal is sending Vim by typing Ctrl+V followed by the Up arrow in Insert mode. (Ctrl+V in Insert mode inserts the next character literally.) I'd expect you'd see the ^[OA sequence inserted.
Then you can check what your Vim thinks the sequence for the Up arrow is with the :set <Up> command. I'd expect you'd see something like:
t_ku <Up> ^[OA
(t_ku is the internal name for the setting corresponding to this Up arrow key. You can also use :set termcap to see all Vim settings related to the terminal, including the special key codes.)
If either of these don't match the expectations, that would explain why your Vim is not recognizing the Up arrow key. (One alternative explanation is that 'ttimeoutlen' is set too short, but I'd say that's highly unlikely.)
These settings are usually managed by the 'term' setting. By default, it's set based on whatever you have for $TERM on your shell outside of Vim.
You can start by looking at what Vim thinks 'term' is, and where it's set from:
:verbose set term?
term=screen-256color
Last set from ~/.vimrc line 100
The :verbose part asks Vim to tell you where it's set from, so you'll see if your vimrc or one of your plug-ins is overwriting it. If Vim shows none of that, it means it's coming from the $TERM variable in your shell.
So look at what $TERM is set to outside of Vim and see if that seems to be correct or not. Are you setting that explicitly somewhere? Be it one of the shell's initialization files or perhaps from your terminal emulator itself?
Also possibly relevant whether you're using tmux or screen, in which case you should double check that $TERM is also set correctly both inside tmux or screen, but also outside it.
Hopefully all these hints should lead you in the right direction fixing this. If you can't figure out, post your findings as comments on this answer and I'll update it with more specific fixes you can try.

You're probably in vi compatibility mode. try :set nocompatible
If that makes it function as you would like, put set nocompatible at the top of your vimrc file to get it to default to this behavior.

Related

How curses differs Enter from Ctrl+Enter and other key strokes with overlapping escape sequences?

As far as I can see, in Konsole both CTRL+ENTER and ENTER look like byte 13 in the stdin of the running app. But when I run mc which obviously uses ncurses lib, pressing CTRL+ENTER inserts the name of the file into the command line while ENTER opens the file. How is it implemented? I tried to look into sources, but they are totally unreadable for me.
mc (midnight commander) doesn't use ncurses for input, but may use it for output. Essentially it is looking for specific character sequences.
mc makes little use of the terminfo database, essentially only to check on the xterm mouse- and alternate-screen features.
In principle, it could read the user-defined capabilities from the ncurses terminfo database (see for example ncurses trapping extended keys (Control-left, Shift-Function etc)), but it does not.
Since you are looking at sources, see the source of mc, in lib/tty/key.c, which contains tables which mc uses as a set of predefined keys. Doing it that way "works" when mc is configured to use slang, for instance, though it has the drawback that it's hardcoded and may not actually match your terminal.
However - as I said, mc does its own input. Further down in key.c, you may see a chunk in get_modifier() ifdef'd with HAVE_TEXTMODE_X11_SUPPORT. Inside that is a call which ultimately goes to XQueryPointer, which mc uses to find the current state of the modifier keys — if it happens to be running in an X display, and if the feature is enabled. You are probably seeing that.

Searching for a character in the bash prompt

In vim, to find a character you can use 'f' to find the next matching character in the line that your cursor is on, and 'F' to find the previous matching character in the line that your cursor is on.
Is there a way to move around like that on the bash command line?
I know that you can set bash to be in vim mode, by saying set -o vim, and this works great for my local machine, but I administer a lot of machines where I can't change that setting.
Ignoring for a moment the security issues associated with everybody in your office sharing the same user, you could add a key binding to the readline command character-search:
# ~/.inputrc
C-]: character-search
To use the search, type Ctrl-] followed by the character you want to search for. You can bind the command to any key sequence, not just Ctrl-], but for obvious reasons you probably don't want to emulate vi mode by binding it to the letter f.
This would be less invasive than turning on vi mode so most users would probably not even notice the change. However, somebody could easily stumble upon your key sequence by accident and become very confused. You would also have to use three keystrokes instead of the two you're accustomed to with vi.

Mapping alt keys in Vim on Windows

I have a function that I'd like to map to Alt+o in gVim on Windows (7.3.46 32 bit Bram#KIBAALE Big version on Win7-x64) and it's... not working.
My .vimrc has a line that reads:
nnoremap <A-o> :call SplitRelatedFile()<CR>
Then I fire up gVim, load up a file, hit Alt+o and get a beep. I tried with a capital O in the mapping, I tried with and without shift in gVim, and it's just not working, I just get beeps. (I've also tried <M-o>.)
If I load up Vim in the terminal, it works as expected. If I manually execute the above line in a new instance of gVim, it also works as expected. It's only not working when it appears in the .vimrc. Actually, it appears in another file but my _vimrc just has one line that reads source x:/path/to/my.vimrc.
When I look at the output of :map I don't get alt keys listed as alt keys anyway, presumably due to the 8th bit interpretation crossing something up. However what I do see is...
n <ef> * :call SplitRelatedFile()<CR>
and after I manually run the :nnoremap in gVim I see this (the first line shows i-umlaut as the key if there are any character translation issues with this post):
n ï * :call SplitRelatedFile()<CR>
n <ef> * :call SplitRelatedFile()<CR>
So it seems that the 8th bit is getting interpreted differently at different points in Vim's (GUI) startup? For what it's worth, when I run :map in console Vim I get the i-umlaut as well and not the <ef> line (o is 0x6F in ASCII so would be 0xEF if the high bit is set, so this makes perfect sense; i-umlaut seems to be 0x8B).
I've tried a few different Alt key combinations and none of them have survived into gVim so I'm curious if anyone's got any tips. Maybe I can stuff these somehow into a "delayed load" module of some sort, like a local plugin or something?
I could move away from Alt keys but I'm out of function keys and don't want to stomp on the obvious Ctrl keys for this functionality... I just discovered that I could replace the <A-o> with the result of Ctrl+v,Alt+o and that does work (as I get the i-umlaut in my vimrc) but that's not very nice! Any thoughts on this madness? (Oh and this doesn't work for console Vim, I need to keep the Alt versions for when has("gui") returns false.)
I've now noticed that both gVim and console Vim report the i-umlaut as 0xEF so ... I don't know what I need to do to make this less kludgey. Help me please!
Thanks for any advice.
Mappings (especially combinations with Alt that have the 8th bit set) are susceptible to changes of 'encoding', and may break when you later modify it.
As a general rule, if you want to :set encoding=..., it should be one of the first things in your .vimrc file.

How to quickly scroll to the latest / end of command history in bash?

Lots of times I'll use Ctrl-R for reverse search and mistype some letter. Bash jumps up hundreds of lines and I'm in the middle of commands I was using a week ago.
Is there a shortcut for jumping back down to the lastest commands I had typed?
Edit: after testing it out on a CentOS server and Mac OS X, it looks like this only happening on OS X.
I've struggled with this same issue.
You can solve this by aborting with ctrl-c. Whether you're in the middle of a reverse search or scrolling through history with the arrows, aborting returns you to a prompt with the history scroll just after the last command.
UPDATE
Here's a nice trick I just learned. Bash and many other programs use Readline under the hood for command-line interpretation. Key bindings for Readline can be configured in a .inputrc file or with the bind command. The bindings can make use of a few functions provided by Readline. For example, I use Bash in vi mode but I still like to use Emacs-style ctrl-A so I have this line in my .bashrc file:
bind '\C-a:beginning-of-line'
To list all the available Readline functions:
bind -l
Among the functions is end-of-history. The function does like its name suggests. The difference between this approach and just using the abort command is that this keeps you on the same prompt.
If using libreadline, Alt-> (or Meta->). More info on Readline shortcuts or search for Commands for Manipulating the History in the man page.
On Mac, try command + .
It works for me.
I was trying alt+. and alt+shift+. , neither works for me. And then found command + . actually works
Maybe not exactly what you want, but you can fix your mistyped character(s) by using backspace when you're in the CTRL-r (reverse-i-search) mode.
You may wan to try "suggest box"-like history HSTR. It reads the bash history and allows quick navigation and filtering - you can see the context of similar history entries. Once you select a history entry it can be edited on the command line.
In Zsh with emacs binding set the actual default key sequence is ^[> binded to end-of-buffer-or-history command rather than command-. suggested above (or end-of-history depending on effect you want to achieve)
Cmd-. produces in Apple Terminal the similar or the same key sequence as Ctrl-C, which can be confirmed by running something useless and long, e.g. find . >/dev/null 2>&1 and pressing one and then other keys on keyboard.
Ctrl-C forces input to be ended and reset. and history scroll is just a side effect for it.

What setting in vim counteracts smartindent's refusal to indent # comments in shell scripts?

I recently started using vim 7 (previously vim 6) and the smartindent setting. For the most part, it works well, though I'm so used to typing a tab after an open brace that it is almost counter-productive.
However, there is one piece of maniacal behaviour. When editing a shell script, I try to create a comment at the current indent level, but smartindent will have nothing to do with it. It insists that the comment must be at level 0 (no indent). What's worse, it breaks shift-right ('>>' and friends) so that they do not work. This is outright insubordination, and I'd like to know what's the best way to fix it?
(I'm also not keen on smartindent's ideas about indenting then after if.)
Preferred solutions will save me manual bashing - I'm being lazy. One option would be 'turn off smartindent when editing shell scripts (leave it on for the rest)'. Another option would be guidelines on how to find the control script for smartindent and what to edit to change the characteristics I don't like. The final option (which I don't need advice on how to do - just the hint that it is the best, or only, way to restore sanity) is to leave smartindent unset.
I saw the vaguely related question on "(PHP and) annoying vim unindent rules"; it doesn't provide me with the direct answer, though maybe the cindent and related items mentioned in there are in fact part of the answer.
Find the indent file, (e.g. /usr/share/vim/vim71/indent/sh.vim on my system)
This line looks like the problem:
setlocal indentkeys-=:,0#
Perhaps you can fix this in your .vimrc or load a custom indent file manually.
edit: It looks more complicated than I thought, but maybe there is something specifically set in the indenting file that you would need to fix.
2nd edit: Looks like I was completely wrong, Check out:
Restoring indent after typing hash
or
howto-configure-vim-to-not-put-comments-at-the-beginning-of-lines-while-editing
Well, after exploring some options, including using ':set cindent' instead of ':set smartindent', I've ended up reverting to just using ':set autoindent'. There probably are ways to make this stuff work exactly as I want it to, but it is messy enough and fiddly enough that I can't be bothered. I've worked fine with autoindent for the previous 20-odd years, and the benefits from the extra bells and whistles provided by smartindent are outweighed by the what I regard as its misbehaviour.
Thank you, Juan, for your assistance. Believe it or not, it did help - quite a lot.
I also discovered a couple of other neat commands, though, while following up on this:
>i}
>a}
These right-shift the block of code you are in. The 'i' version indents the body and not the closing braces (my preferred style), and the 'a' version indents the closing braces to (the version that is required at work).
Also, you can apply qualifiers to '%' in commands executed at the shell:
:make %:r.o
This would run make on the 'root' of the current file name (that's '%:r') followed by '.o'. Or, in other words, if I'm editing somefile.c, this executes make somefile.o.
Add the line below in your .vimrc
filetype indent on
(it will set the right indent mode depending on the filetype)
I had this same issue for a long time, until I realized that autoindent and smartindent are both unnecessary if "filetype indent on" is set in your vimrc - 'filetype indent on' uses the indent/sh.vim (or whatever language) file in your vim directory to figure out the indentation rules, and autoindent and smartindent both can interfere with it.
I haven't tested this with sh, but perl suddenly started behaving properly when I switched.
Sidenote: Juan's redirect, "Restoring indent after typing hash", is not a good solution - while it does correct the problem in one situation (typing code in), it doesn't change how the editor thinks it should be indented, so a re-indent (visual =, or normal ==) will shove it back to the left.
The previous answer suggesting:
:inoremap # X^H#
is excellent. It is the answer suggested by the VIM documentation at ":help smartindent". Note that ^H is entered using CTRL-V CTRL-H. The relevant section from the documentation is below.
When typing '#' as the first character in a new line, the indent for
that line is removed, the '#' is put in the first column. The indent
is restored for the next line. If you don't want this, use this
mapping: ":inoremap # X^H#", where ^H is entered with CTRL-V CTRL-H.
When using the ">>" command, lines starting with '#' are not shifted
right.
I have the following lines in my .vimrc and I don't observe the problem.
set smartindent
inoremap # X^H#
I used to have set autoindent after these two lines but it seems that it has no effect.
Yes that is very annoying. smartindent is really only for C like languages.
See how I enable the appropriate indenting based on language at:
http://www.pixelbeat.org/settings/.vimrc

Resources