How to call function without leaving insert mode? - vim

I am trying to create a plugin for vim like ctrlp and I need some help. First of all I want to place input field at the top of the screen so
Is there a function similar to input() but which can place input field at the top?
Friendly speaking, I have already started to realize my own input field and there is an issue while editing text. I have found a backspace option very useful to prevent deleting prompt text ("Files> "). I just put this text to the buffer and then start insert mode. To my regret I cannot use this option because I have complex logic to control buffer and I always need exit insert mode to call functions. Instead of backspace I need remap <BS> to something like this <C-o>:call backspace()<CR>
function backspace()
" checks if deletion is possible
x
endfunction
This works but there is a cursor flashing which disturbs me. Insert mode makes buffer modified and there is a mark * in tabline. It can be hidden call setbufvar(bufnr('%'), '&mod', 0) but it works quite slow and the symbol appears from time to time. I use TextChangedI event for this.
Is there an option to disable monitoring buffer change?
The most important question is how can I get more freedom in insert mode? Is there a way to calling function without leaving this mode?

Is there a function similar to input() but which can place input field at the top?
No. The command-line is at the bottom and there's nothing you can do about it.
Is there an option to disable monitoring buffer change?
Yes. See the last paragraph of :help 'modified'.

Related

Insert a specific string instead of tabs or spaces in gVim

Since I'm working with LaTeX documents in vim, I want to be able to insert \quad instead of a tab space whenever I press tab (instead of having to replace/insert them manually). Is there any setting that could do this? If not, are there any plugins that work like this?
While you can use inoremap to change Tab to \quad in insert mode, that means
that you lose the original Tab functionality...
This might be worth it if you're sure that you'll never want to use Tab, but
what will you do when you face a similar problem of wanting some
latex-specific text? You could try and find a second key to map... but each
addition will take up a new key that already had some function.
The way I would handle this would be to use iabbrev to map some unlikely
sequence of keys like ;q to \quad:
iabbrev ;q \quad
This has the advantage that you can build up a whole set of insert mode
abbreviations, all consistently starting with ; followed by a letter or two
that you can choose to be easily remembered. And you get to keep all the
original functionality.

How to use vim autowrap correctly?

I am trying to use the vim autowrap functionality to automatically wrap my paragraph into lines no longer than 80 letters in real time as I type. This can be done by set textwidth=80 and set fo+=a. The a option of the vim formatoptions or fo basically tells vim to wrap the entire paragraph while typing.
However, there is a very annoying side-effect, that I can no longer break a line by simply pressing enter.
This is a sample sentence.
Say for the above sentence, if I want to make it into:
This is
a sample sentence.
Usually I can just move the cursor to "a" and enter insert mode and then press enter. But after set fo+=a, nothing will happen when I press enter in the insert mode at "a". One thing I do notice is that if there is no space between "is" and "a", pressing enter will insert a space. But nothing else will happen after that.
So what do I miss here? How do I stop this annoying behavior?
You can run :help fo-table to see explanations of the options:
a Automatic formatting of paragraphs. Every time text is inserted or
deleted the paragraph will be reformatted. See |auto-format|.
When the 'c' flag is present this only happens for recognized
comments.
This means that every time you insert a character, vim will try and autoformat the paragraph. This will cause it to move everything back onto the same line.
I don't think you need to add a at all. I use neovim, but the behavior here should be the same. The default values are, according to the help pages:
(default: "tcqj", Vi default: "vt")
Try removing set fo+=a entirely from your .vimrc. Keep set textwidth=80. That should fix your issue.
EDIT: Once you have set textwidth=80, if you want to format an existing paragraph, you can highlight it in visual selection and press gq.
The following allows me to use the enter key to start a new line while setting the text width to be 79 characters:
set tw=79 "width of document
set fo=cqt
set wm=0 "# margin from right window border
After some exploration, I find a workaround that can solve the problem to some extent, though not perfect.
The basic idea is that when entering a line break, disable the auto-wrapping temporarily when sending <CR> and resume auto-wrapping after that. There are multiple ways of doing that. And the best one as far as I know is using the paste mode, since you don't have to exit insert mode when entering paste mode. So just make the following commands into any key binding you like in insert mode. The one I am using right now is inoremap <C-N> <F2><CR><F2>
The reason why I think this one is not optimal is that for some reason I cannot bind <Enter> in this way, but have to use another key.
If <Enter> or <CR> can be configured in this way then the problem is 100% solved.

Perform operation on entire buffer, without changing the cursor position

Consider a scenario, when you are editing a C file in vim. & you have used a mix of spaces & tabss. & you need to convert all of them to spaces.
There is a utility, called expand, which performs this task intelligently & it's a preferred way than s/\t/<4 spaces>/g. We can use this command in vim using :%!expand -t4. Typically, I map a function key, say F11 for this.
Similarly, we can use any other command in vim.
The problem is when you run any such operation on entire buffer, the cursor position changes & can be irritating at times.
Hence, the question is, how to perform an operation on entire buffer, without changing cursor position?
The cursor position can be restored by using the latest jump mark:
``
If you also want to maintain the exact window view, use winsaveview() / winrestview().
The anwolib - Yet another vim library has a handy :KeepView command for that:
:KeepView %!expand -t4
For such a case, we can use marks (e.g. mA). The mapping would be:
:nmap <F11> mZ:%!expand -t4<CR>`Z
However, there is still a catch. The screen scroll position may change, when operating on entire buffer.
This can be handled by using 2 marks as below:
:nmap <F11> mZHmY:%!expand -t4<CR>'Yzt`Z
Explanation:
Mark current position. (mZ)
Go to top of screen. (H)
Mark this line. (mY)
Run your filter. (:%!expand -t4)
Go to line Y. ('Y)
Make it top of screen. (zt)
Go to your mark. (`Z)
Now, when you press the mapped key, F11, the filter runs on the buffer & the cursor remains at its proper location.
you can just:
:your expand cmd|norm! ``
you can map it to <F11> if you like. but better use nnoremap
I just saw you mentioned in your question:
Similarly, we can use any other command in vim
If you want to do that, the reliable solution would be wrap the "any other command" in a function, and before/after the main logic, save/restore the cursor position. Because "any other command" could change the (back tick) mark, even the marks you defined.

mapping shortcut in vim without hanging the cursor

I would like to have vim fill a short sequence of characters into a longer string in insert mode. Example, say I write the word "sub" and it writes "subroutine" as soon as I press space. The problem I find is that when I use :imap sub subroutine, every time I start typing sub, the cursor does not continue moving, but hangs in the same position waiting for more keystrokes in order to decide what to do. I find this behavior annoying, although not wrong (it does what I need).
Is there a way to have vim continue typing single characters, and eventually replace ?
Just try to use abbreviate :ab sub subroutine
Search the web for "vim completion" (or the help for "completion"). The feature is in v7.x, but you may want to change the keystrokes with ìmap.

Multiple selections in VIM

Is it possible to select multiple non-consecutive lines (or sections) in VIM's visual mode? If so, how?
No, this is not possible without plugins.
But you can copy multiple lines into the same buffer, if that solves your problem.
To start the 'Accumulation Buffer':
mark a section to copy in visual mode,
press "a to operate on the buffer a with the next command and
yank it as usual (y).
To add to that buffer:
mark the next section and
press "A (capitalizing the buffer name means "do not overwrite the buffer, append to it instead")
and yank again using y.
You can then paste the accumulated buffer a at any time using "ap.
You have to install the multiselect plugin to get this capability. Find it here: http://www.vim.org/scripts/script.php?script_id=953
A more up-to-date answer is this plugin.
(disclaimer: I personally don't actually use it, it interferes too much with the rest of my vim setup. If your vim is relatively clean and you are moving over from sublime, this may certainly be your cup of tea.)
I would also like to point out the record/replay functionality of vim (the q key). Quite often recording is also unnecessary, I can do the tasks normally done with sublime's multi-select by doing it iteratively (e.g. search for something, perform the fix on the first instance of it, and then subsequent repeats are achieved by hitting n and N to move around and . to repeat the edit operation).
I do have my , comma key nnoremap'd to #q, this repeats the sequence that is recorded by pressing qq (record into q register).

Resources