Show result instead of X with incomplete mapping in vim - vim

In my file at ~/.vim/ftplugin/tex/insert.vim I have the following mappings
; <Nul> is ctrl-space
imap <Nul> \,
imap <Nul><Nul> ~
imap <Nul><Nul><Nul> \enspace
imap <Nul><Nul><Nul><Nul> \quad
imap <Nul><Nul><Nul><Nul><Nul> \qquad
This allows me to insert spaces of different width by pressing ctrl-space, with each press making the whitespace longer. When I type the first ctrl-space, I get an X and it waits for me to see if I wanted to input more ctrl-spaces or if I'm done.
I would like to know if there's a way to show what the space will be, either input it directly to the buffer and change it if it's pressed again, or put it in the status bar until I'm done.
A way I think this could be possible was to check if the chars before the cursor are \, and if they are replace it with the next space, and if it's not, check the rest of the spaces I can input and finally input a \, if none of the spaces are there. I just don't know how to accomplish such a keymap.

Your current map solution is based on the mapping timeout. Until that happens, Vim is waiting for more input, and nothing has been inserted yet. In order to later revise what got inserted, you need to completely replace the approach.
This could be implemented with :map <expr> <Nul>, checking what's before the cursor, and then returning <BS> characters to wipe that followed by the replacing text.
With the mjbrownie/swapit plugin, you'll get that "toggling through alternatives" functionality (using <C-a> / <C-x>) for free: Just put the following into ~/.vim/ftplugin/tex/swapit.vim:
SwapList spaces \, ~ \enspace \quad \qqad
You can keep your original <Nul> mappings to quickly insert when you know what you want (or for the initial insert), and use swapit only to revise later on.

Related

Using placeholders in vim

Given a vim document with multiple occurrences of a specific placeholder, say <%%>, I want to be able to jump to the next placeholder from the beginning of the document: More explicitly, if the document is given by
$\frac{<%%>}{<%%>}$
I want to press a key such that the first placeholder gets removed, i.e. we have
$\frac{}{<%%>}$
where the cursor is at the position of the placeholder and vim is in insert mode.
I'm aware of the vim-latex plugin which implements such a behaviour but only need this one feature. I tried to use the /-search of vim but didnt get the cursor position right.
Thanks in advance for any advice.
lh-brackets provides this feature -- actually vim-latex placeholder system has been inspired by lh-brackets one.
The idea to implement this feature, is:
to look for the pattern of the placeholder -- prefer search() to know whether something has been found: no selection shall be done otherwise
Actually doing it correctly may require a couple of calls to searchpair() to handle the case where the cursor is in the middle of the placeholder, see lh-brackets code as search(..., 'c') is not enough;
select this pattern -- v + movement 3<right> for instance
and finally either go into SELECT-mode (gh <c-g>) or remove the placeholder and go into insert mode (s)
If your placeholder pattern is exactly <%%>, it'll be quite simple to implement.
" I factorize common code without introducing the exact keybinding
" NB: we have to use the ancestor of map-<expr> as the later doesn't
" permit to move the cursor -> we execute the expression register: :h #=
" NB: As said earlier a correct implementation would require to call searchpair()
" twice in case the cursor is within a placeholder, see lh-brackets code
nnoremap <silent> <Plug>(jump-next) #=(search('<%%>') > 0 ? "v3l<c-g>" : '')<cr>
vmap <silent> <Plug>(jump-next) <c-\><c-n><Plug>(jump-next)
imap <silent> <Plug>(jump-next) <c-\><c-n><Plug>(jump-next)
" Tests shall be done in a real plugin before binding to the chosen shortcut: µ, <f3>, <c-j>, <tab>...
nmap <silent> µ <Plug>(jump-next)
vmap <silent> µ <Plug>(jump-next)
imap <silent> µ <Plug>(jump-next)
If sometimes it could become <%somestring%>, then I would definitively recommend using lh-brackets or any snippet engine that already takes care of this -- for instance, mu-template would permit to use your exact snippets/templates by changing locally the default placeholder characters with VimL: let s:marker_open = '<%' +
VimL: let s:marker_close = '%>' (I'm also maintaining mu-template which depends on lh-brackets).
NB: lh-brackets also provides surrounding (non intrusive), and bracket pairs insertion (can be deactivated: add :let g:cb_no_default_brackets = 1 in your .vimrc)
Using a macro might help.
In your example, use /<%%> to search for your placeholder. Then gg will take you at the beginning of the document.
Then start the macro with qa for instance. Go to the next occurrence of your placeholder with n. Then, ca< will remove the placeholder. C-o q will stop recording, while keeping you in insertion mode.
To go to and replace the next placeholder, just do #a (execute the macro stored in register a)
Does this mapping help?
:nmap %% /<%%><cr>ni
It executes a search (/<%%><cr>), repeats the search with n to skip the 1st placeholder and goes to the second. Then it switches (i) to Insert Mode.

extra space added when going into insert mode in an abbreviation

I'm trying to create an abbreviation which replace typed text by what I want but also move the cursor and enters insert mode.
the ab is as following:
:abbreviate MSG `MSG(("")); <Esc>F"i
everything works fine except when entering insert mode, I have to extra spaces before the cursor.
I've tried then to add <BS><BS> but it's leading to delete the first quote. Same thing if I'm putting only one <BS> (which is really strange, it seems the second <BS> has no effect at all...)
I guess I'm missing something but I can't figure out what...
Thanks for your help !
A citation from Vim help system (:help abbreviations):
An abbreviation is only recognized when you type a non-keyword
character. This can also be the <Esc> that ends insert mode or the
<CR> that ends a command. The non-keyword character which ends the
abbreviation is inserted after the expanded abbreviation. An
exception to this is the character <C-]>, which is used to expand an
abbreviation without inserting any extra characters.
Example:
:ab hh hello
"hh<Space>" is expanded to "hello<Space>"
"hh<C-]>" is expanded to "hello"
So if you press <Space> after entering MSG a space is inserted after expanding your abbreviation.
To avoid adding a needless space you can invoke the abbreviation with pressing <C-]> after entering MSG or you can try elaborate a mapping like this:
:inoremap MSG `MSG(("")); <C-O>F"
But IMHO such a mapping is very inconvenient.
Another option may be to use use one of the many abbreviation plugins like this (first shown by Google).

Opposite of newline in vim

In vim, is there a command to delete the newline, and all empty space behind the cursor?
Say I stand in the middle of a text in insert mode and press Enter, what command would the reverse what I just did?
A) An example:
"some code{ in here }"
B) After pressing Enter:
"some code{
in here }"
Now pressing backspace will delete one space of the indentation. I would rather have it delete all indentation, and jump back to A.
Can this be done in a command or by doing some remapping to the backspace key?
It's tragic how unknown the J command is. It joins lines in normal mode.
In insert mode, you can press <C-U> twice; first, it'll delete the indent before the cursor, then it'll join with the previous line. Note that this requires
:set backspace=indent,eol,start
did you try J (uppercase) ? it will give exactly what you want.
"some code{ cursor on this line, pressJ
in here }"
You can do ᴇꜱᴄ, K, Shift+J.
K jumps up to the previous line and Shift+J joins the two lines.
However, with properly configured indentation and syntax, a backspace doesn’t just delete a space, it deletes the full previous indentation block.
One easy way is up one line, to end of that line and just delete. As long as you still are in insert mode it will do the same thing as J when deleting at the last position - like most other editors. For me that is the quickest alternative because I'm used to it from other editors.
That is: ↑, End, Delete (when still in insert mode)
One quick alternative (the VIM-way) is (when still in insert mode):
↑, Ctrl+o, J (when still in insert mode)
(Ctrl+o is used in insert mode to enter one normal mode command.)
It's also possible to use a remapping of the backspace key:
inoremap <expr> <bs> getline('.')[:col('.')-2]=~'^\s\+$' ? "<c-u><c-u>" : "<bs>"
Note that this mapping completely overrides the normal behavior the backspace key. This will only be useful when you don't intend to use its normal behavior. This is not recommended if you can easily access the other options (c-u or J)
However, (as far as I know) there's no way to distinguish between manually added leading white spaces and auto indent. If you use noexpandtab, you can edit the regex to only match tabs.
This also does not work in some modes of auto-indent (for example, in block comment in C, vim automatically start a new line starts with *)

VIM: Mappable (unused) shortcut letters?

I'm trying to create two mappings which are efficient for myself:
map X ddp
Which I'd use to delete and paste in one go.
map X "_dw
Which would delete a word without yanking into a register.
However I don't want to break any existing, useful shortcuts so I'm wondering what keys I could use - any suggestions? Am I being too uptidy?
vim help has a section :he map-which-keys
1.7 WHAT KEYS TO MAP *map-which-keys*
If you are going to map something, you will need to choose which key(s) to use
for the {lhs}. You will have to avoid keys that are used for Vim commands,
otherwise you would not be able to use those commands anymore. Here are a few
suggestions:
- Function keys <F2>, <F3>, etc.. Also the shifted function keys <S-F1>,
<S-F2>, etc. Note that <F1> is already used for the help command.
- Meta-keys (with the ALT key pressed). |:map-alt-keys|
- Use the '_' or ',' character and then any other character. The "_" and ","
commands do exist in Vim (see |_| and |,|), but you probably never use them.
- Use a key that is a synonym for another command. For example: CTRL-P and
CTRL-N. Use an extra character to allow more mappings.
See the file "index" for keys that are not used and thus can be mapped without
losing any builtin function. You can also use ":help {key}^D" to find out if
a key is used for some command. ({key} is the specific key you want to find
out about, ^D is CTRL-D).
Many Vim plugins use an initial <Leader> to start their key sequences; this is an (otherwise normally) unused key that is configurable by the user.
*<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.
Every single ASCII character, upper and lower case, is used for something in Vim. So you're going to wind up overwriting something--just pick something that you don't use. It may help to use a common idiom for your own extensions. I use a leading comma, for example:
map ,w :w!<CR>
map ,e :e #<CR>
imap ,, <ESC>
(The last is particularly useful for me, since I pretty much never need to write two consecutive commas in insert mode, and it's nice not to have to go all the way to the Esc key.)
Typically I use control + [letter] or alt + [letter] for most mappings and it's safe, but watch out for 'w' since that's needed for window commands. You might also be interested in arpeggio.vim which lets you create mappings to simultaneously pressed groups of keys - it will massively expand the possibilities for your mappings with no danger of over-mapping something. For example, you could map "dp" (pressed simultaneously) to execute "ddp" to delete and paste in one command.
Uhmm, no, don't. When creating your mappings try not to overwrite anything ... not so much because you don't use the command you're overmapping, but because some plugin which you have/or will have maybe using it.
And then you overmap it, and then you have to worry.
Personally, for commands such as you gave as an example, I like Ctrl+some key combinations. There are a lot of free ones in vim, and the letters on the left side near Ctrl make a nice pair then.
Btw, what are you trying to do with those mappings ... I understand the second one (delete word by word), but the first doesn't make sense to me. What is it supposed to do ? Transpose lines ?

How to jump to the next tag in vim help file

I want to learn the vim documentation given in the standard help file. But I am stuck on a navigating issue - I just cannot go to the next tag without having to position the cursor manually. I think you would agree that it is more productive to:
go to the next tag with some
keystroke
press Ctrl-] to read corresponding
topic
press Ctrl-o to return
continue reading initial text
PS. while I was writing this question, I tried some ideas on how to resolve this. I found that searching pipe character with /| is pretty close to what I want. But the tag is surrounded with two pipe '|' characters, so it's still not really optimized to use.
Use the :tn and :tp sequences to navigate between tags.
If you want to look for the next tag on the same help page, try this search:
/|.\{-}|
This means to search for:
The character |
Any characters up to the next |, matching as few as possible (that's what \{-} does).
Another character |
This identifies the tags in the VIM help file.
If you want to browse tags occasionally only, without mapping the search string to keyboard,
/|.*|
also does the trick, which is slightly easier to type in than the suggested
/|.\{-}|
For the case, that the "|" signs for the links in the help file are not visible, you can enable them with
:set conceallevel=0
To establish this setting permanently, please refer to Defining the settings for the vim help file
Well, I don't really see the point. When I want to read everything, I simply use <pagedown> (or <c-f> with some terminals)
" .vim/ftplugin/help/navigate.vim
nnoremap <buffer> <tab> /\*\S\+\*/<cr>zt
?
Or do you mean:
nnoremap <buffer> <tab> /\|\zs\S\{-}\|/<cr><c-]>
?
You could simply remap something like:
nmap ^\ /<Bar><Bslash>zs<Bslash>k<Bslash>+<Bar><CR>
where ^\ is entered as (on my keyboard) Ctrl-V Ctrl-#: choose whatever shortcut you want.
This does a single key search for a | followed by one or more keyword characters and then a |. It puts the cursor on the first keyword character. The and bits are there due to the way map works, see
:help :map-special-chars
As an aside, I imagine that ctrl-t would make more sense than ctrl-o as it's a more direct opposite of ctrl-], but it's up to you. Having said that, ctrl-o will allow you to go back to before the search as well.

Resources