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
Related
I'm writing markdown in Vim and using this shortcut to set correct markdown image syntax:
nnoremap <leader>p :s/.*/![](\0)/ <CR>
when pressing ,p, /path/to/image/img.jpg (in my vim text file) becomes
![](/path/to/image/img.jpg)
But I want to add after that this { width = *variable*% }, like this
![](img.jpg){ width = *variable*% }
I made this little bash script (img.sh) that gives me the variable according to the image size:
#!/bin/bash
VAR=$(identify -format '%h' $1)
echo "scale=3; 300 * (100/$VAR)" | bc
If I do this in vim :r !img.sh /path/to/image/img.jpg I get a number in this case 32
I would want to launch this script with the shortcut above, I tried this:
nnoremap <leader>p :s/.*/![](\0){ width=/ <CR> :r !img.sh /path/to/image/img.jpg <CR> % }
I want you to help me to find a way to not type path to image to execute the script. Path to image is already written in the text if i could find a way to indicate to vim to place it in the shortcut after img.sh it would be great !
You can use a Vimscript expression on the replacement side of your :s command, that way you can refer to the text in the match (which is the path to the image) using submatch(0). You can use an expression on the replacement of a :s by beginning it with \=, see :help sub-replace-expression for more details.
Using a replacement expression, you can also use the system() function to call the external command, instead of using a separate :r !... command to read its output into the current buffer.
Putting it all together:
:s/.*/\='![]('.submatch(0).']{ width='.trim(system('img.sh '.submatch(0))).' }'/
Or to add a mapping to it:
nnoremap <leader>p :s/.*/\='![]('.submatch(0).']{ width='.trim(system('img.sh '.submatch(0))).' }'/<CR>
(NOTE: You might also want to add a :noh command to the end of your mapping, otherwise it will keep highlighting the search for .* which matches everything.)
nnoremap <leader>p :s/.*/\='![]('.submatch(0).']{ width='.trim(system('img.sh '.submatch(0))).' }'/\|noh<CR>
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
1.Env
vim7.3+zsh+iTerm2 on mavericks
2. Mapping Problem
Here are my problem list:
My vim could not get some shortcuts: <C-q>,<C-s>,<A-Left|Right|..>,<D-char>.
I could not map some special keys such as <A-char> , <A-S-char> , <C-A-char>in mac.
<C-q> and <C-s>
In iTerm2, <C-q> will delete whole line, (and <C-s> will launch Fwd-i-search).
It doesn't behave like start/stop character , so that I thought this problem is nothing to do with stty start and stty stop.
But after I add this into ~/.zshrc, I surprised to see that the map for <C-q> and <C-s> works well in Vim. At the same time it doesn't change the behavior of <C-q> and <C-s> in iTerm2(I don't know why).
stty start undef
stty stop undef
<A-char> problem in mac
In mac, mappings for <A-char> won't directly work in mac.
:inoremap <A-u> type some string A-u
:inoremap <A-p> type some string A-p
:inoremap
i õ * type some string A-u
i ð * type some string A-p
As far as I know about <A-char> in mac, hit <A-u> will print nothing but with a sound alert. hit <A-p> will print π. I found that map for π works well.
:inoremap π type some string A-p
Is it possible to map <A-u> in vim?
Another complex question, is it possible for <A-S-char>, <C-A-char>
:map <A-S-p> not work
:map ∏ works well(A-S-p will print `∏`)
:map <C-A-p> not work
:map <C-π> still not work
:map <C-S-p> do work
Another complex question related above, is it possible mapping <C-A-char>?
<A-Left|Right|UP|Down
In iTerm2 , hitting <A-Left|... will result in(iTerm2 doesn't bind any shortcut for them.):
<A-Up> print 'A' with a sound alert.
<A-Down> print 'B' with a sound alert.
<A-Left> print 'D' with a sound alert.
<A-Down> print 'C' with a sound alert.
In vim, <A-Left|... is same as <Left><Right><Up><Down> in insert mode , normal mode, visual mdoe and Ex Mode, etc.
<D-char>
Some keys about <D-char> are iTerms's own hotkeys, such as :
1. <D-q> will quit iTerm2
1. <D-w> will close current tab in iTerm2
On the other hand, the other keys such as <D-s> are not hotkey, and do not print any char in vim and terminal. Is it possible to map them in vim?
Map <C-1>
Vim doesn't provide keycode <C-1>, but you can use other unused vim keycodes instead
Potentially unused Vim keycodes that can be used include:
<F13> to <F37>
<S-F13> to <S-F37>
<xF1> to <xF4>
<S-xF1> to <S-xF4>
Type :set termcap to see which vim keycodes are unused.
If you want to use hotkey Ctrl+1, map it to Esc Sequence (such as ^[C-1) in terminal preference first, then bind this terminal keycode with an unused vim keycode such as <F13>, <xF1>, <t_bc>, etc.
"bind vim keycode `<F13>` to terminal keycode `^[C-1`
:set <F13>=^[C-1
:imap <F13> Input some characters
For more details, refer to fastcodes in vim
Map <A-char>
By default, <A-char> will print special character in mac. In generally, you can map this special character. Or you can remap <Alt> as Meta in your terminal.
Map <C-A-char> and <D-char>
Same with <C-1>, if you use termainal vim you could use fastcodes instead of.
Bind <C-A-char> with terminal any keycodes, for example : ^[C-A-a
Set vim fastkeycodes and do mapping:
Mapping:
:set <C-A-a>=^[C-A-a
:map <C-A-a> Input some characters
I've remapped the following keys in Bash:
bind '"a" "b"'
bind '"b" "c"'
If I press a or b both times a c will be printed.
How can I map the keys so that by pressing a and b will be printed and only by pressing a and c will be printed (like with Vims **nore**-map)?
You can make a char in the right part a literal with a preceeding "^V":
bind '"x":"^Vx "'
The key sequence to enter the text after colon is:
" Ctrl-v Ctrl-v x space "
In bash "Ctrl-v x" results in a literal x, without key-mapping interpretation .
You may find it useful to build your own keymapping file which maps the numeric signal you get from the keyboard to a character. This is done with the loadkeys command i.e. if you're switching to the dvorak layout you can do (this is a verbose way to show you the location of the map files:
loadkeys /usr/share/keymaps/i386/dvorak/dvorak.map.gz
You could copy the map file for the layout you use and change the relavent chars, and load your modified mapping. I think loadkeys only affects the command line, though there are similar methods for changing the behaviour in X I believe.
How do you prettify / align / format code in vi? What is the command?
I have pasted in a hunk of code and I need to have it all formatted/aligned... obviously I am a vi neophyte.
x
These commands in my answer work in vim. Most people who think they're using vi are using vim. To find out if your 'vi' is really 'vim', open vi and type :version -- if it's vim, it will say so. Otherwise you might just see a version number without the name of the program. Also, when you open vim for the first time you will usually see a splash screen of some sort that says "VIM - VI iMproved"...
Automatic Indentation
To turn auto-indentation on, make sure vim knows the file type you're editing (it usually automatically detects this from the file name extension, but might not figure it out with some file types). You can tell it the filetype using the menus for syntax highlighting. Then, do this:
:filetype indent on
You can disable auto-indentation with
:filetype indent off
Automatically adjusting/correcting indentation
In general, ={motion} will align code to an indentation level.
== align the current line
=i{ align the inner block
=% align to the matching parenthesis/bracket under the cursor
=14j or 14== align the next 14 lines
=G align to the end of the file
vG= same thing, align to the end of the
file (but using visual mode)
vjjj= align four lines (using visual mode)
Manual indentation
If vim is not guessing the indentation level correctly, there are two ways to change it:
If you are in normal mode (where everything is a command), do << to shift a line left, or >> to shift it right by one tab. You can do this with several lines by using the same movement commands I showed above (eg, >i{ indents the current inner code block).
If you are in insert mode, you can indent the line further (without moving the cursor) by doing a Ctrl-T, or un-indent one tab with Ctrl-D
Aligning equals signs, etc
If you want to align equals signs in a list of declarations, you should consider using this vim script: http://www.vim.org/scripts/script.php?script_id=294
Adjusting indentation/tab sizes
If you want vim to use spaces instead of tabs when it indents, run this command (or consider adding it to your vimrc file)
:set expandtab
To set how many spaces equal a tab, I usually do this:
:set expandtab softtabstop=3 tabstop=3 shiftwidth=3
tabstop - how many columns a tab counts for (affects display of existing tab characters)
shiftwidth - controls reindentation size with << and >>, among other commands.
softtabstop - how much space to insert when you press the tab key
expandtab - expand tab keys to spaces
But if you have to work with different amounts of tabs a lot, you could also use this function and keybinding:
function! Ktabs(tabsize)
execute "set softtabstop=" . a:tabsize . " tabstop=" . a:tabsize . " expandtab shiftwidth=" . a:tabsize
"set softtabstop=a:tabsize tabstop=a:tabsize expandtab shiftwidth=a:tabsize
endfunction
noremap <leader><Tab> :call Ktabs(3)<Left>
If you are editing a file with a mix of tabs and spaces, you may want to use this command after setting tab size:
:retab
={motion}
:h =
P.S. You shouldn't use vi if vim is available.
If manually adjusting indents I will open a visual block with V on the first or last line I want to re-indent, move to the brace containing the block, goto the other brace with % then shift the line with > or <
If indents are off by a lot I will shift everything all the way left with < and repeat it with . and then re-indent everything.
Another solution is to use the unix fmt command as described in Your problem with Vim is that you don't grok vi., {!}fmt