Calling a function, and then sending a key in neovim - vim

map z. <Cmd>call repeat(VSCodeNotify('editor.action.commentLine')j, v:count1)<CR>
The idea is to call the vscode command for commenting, and then the down key. With that, if I pass 5z., the next 5 lines get commented out
This code doesn't work. Does work if I remove j (but with that, I don't get the wanted behavior)
The repeat command also doesn't work. you'd expect the comment function to cancel out if you call it twice (it's a "toggle comment" function), but it only executes once, no matter what number I input

Related

How do I check if nothing was typed in the previous Zsh prompt

In the zsh prompt, I have a custom script to display the amount of time the last command ran for.
I've got this working, but how do I check if the user entered nothing and just pressed "Enter" or "Ctrl + C", in the previous prompt?
In this case, I do not want to show the amount of time the user spent idle, as this is not useful information for me.
$history[$((HISTCMD-1))] doesn't appear to work in this case. If the user typed nothing and just hit enter, it will just show the last command that was run, and not be an empty string.
If you define a function with the name zshaddhistory, it will be invoked every time enter has been pressed. $1 is the command being entered, and this can also be an empty command. You could set a global variable to indicate that an empty line has been entered, and use this variable later on.
Be careful with the return value from this function: If it returns 0, the command is saved into the history; otherwise it is not. You find more on this in the zshparam man-page, where _HISTORY_IGNORE_ is described, because the main use of this function is to control whether or not a command should be added into the history. Hence, an alternative would be to add empty lines to the history too and use your original approach with $history to access it. This has the disadvantage that seeing empty history entries is not really user-friendly.

Vim function normal mode then execute

I have the following code:
function CSVTableFunc(command)
let cursor = getpos('.')
let l:winview = winsaveview()
normal(ggVG)
execute a:command
call setpos('.', cursor)
call winrestview(l:winview)
endfunction
Basically, what it does is it selects all lines from top to bottom, then executes the command that's passed in the function.
However, before the command is executed, the lines selected before hand are deselected.
What's the thing that I've missed?
Cheers!
A couple problems here.
First, you attempted to use normal(...) as if it's a function. It's not (and if it was, you used it wrong anyway, you'd be missing a call command).
What you actually told Vim was to run the following normal-mode commands:
( - back a sentence
ggVG - roughly, select all text in the buffer
) - forward a sentence
Some experimentation shows this probably actually doesn't cause any problems, but it's wrong, and it could cause problems in other circumstances.
Your bigger problem is that commands don't actually operate on a range unless you tell them to. In visual mode (i.e. when you've selected a range of lines), when you press : you automatically get '<,'> inserted on the command line. This text says "run the command on the visual selection".
Using execute does not automatically insert this range. You'd need to manually put the range at the beginning of the command, if the command supports a range. Since you did not do this, your command only runs with its default range, which is usually the current line. In your case, since you did ggVG before running your command, you probably see the command run on the last line only.
Anyway, you don't need the visual selection. Just use the special range % instead of selecting anything. % means "on every line".
The problem is, some commands may not support a range. For those commands, you will probably need to use a loop, or a :g command, to run the command on each line of interest one by one.

vim script exec pastes unformated text

In all honesty the title is bad. Consider the following 5 lines:
function Example()
let ## = "-_-"
execute "normal! ]P"
call cursor(line('.'), col('.')-1)
endfunction
When this function is called, I expect to get -_- as output and the cursor should be moved to the left, meaning that it is at the third character, so if I press a key, like I for example I will get -_i-
What happens in reality is quite different (and to some degree interesting)
The output the first time this is called is - _- and after that it's _--
I assume that "cursor" shifts the position of the word under the cursor.
Basically: Why is it happening? How can I get the desired effect ?
Very important edit:
Apperantly the problem isn't in the plugins. When I go for:
call Example()
It works flawlessly. Thing is it is supposed to be triggered by a key. I have currently bound it like so:
inoremap ' <C-O>: call Example()<CR>
So now I am thinking that something in the mapping is broken...
I cannot reproduce your strange behavior. I get ----_-_-_-_- on repeated invocations, as expected. I again suspect there are plugins at work. Try with vim -N -u NONE. As this is a paste, there's little that could influence this function, though. You could try to workaround via :noautocmd call Example(), but I'd rather try to find the root cause of this disconcerting strangeness.
The "-_-" is not a full line, so the ]P (paste with adapted indent) has no effect here. You could just as well have used P.
To move the cursor one left, rather use :normal! h. The subtraction from col('.') again only works for single-byte ASCII characters.

The `:bar` in vim doesn't work as expected

After reading the vim doc about *:bar* *:\bar*:
'|' can be used to separate commands, so you can give multiple commands in one line.
I tried to clear history via this command:
:set history=0 | set history=20
I expect that, these two commands should be executed one by one, and the history should be cleared.
But it didn't. The history still there, and a new history was added.
Then I tried:
:set history=0
:set history=20
It works.
Why?
When you execute a command line that is what happens:
History is initialized (truncation happens here) (init_hist() function call in getcmdline()).
String to be executed is obtained (in getcmdline()).
It is added to history (add_to_history() call in getcmdline()).
It is executed (do_one_cmd() in do_cmdline(), happens after getcmdline() call (called by getexline() passed as fgetline argument to do_cmdline())).
Setting the option itself does nothing, it only changes p_hi variable. Actual modification of history is done at step 1.
Now let’s see what happens in both cases (assuming that you typed second or third additional command):
History is first initialized when p_hi has old value, then it is changed two times and then when you do next command it is already set to 20.
History is first initialized when p_hi has old value, then it is changed once and initialized for the second time, being effectively truncated at this step and only then the value changes again. By the time you start typing third command it is already wiped out.
Thus your assumption (commands are executed one by one) is true, but you have mistaken at which point history modification happens. I would rather suggest using histdel() as #Michael advised because, at first, it clears history by itself and, at second, it does not have hardcoded 'history' value. I can’t say how you live with just 20 lines long history (I’ve set it to 65535 and am always sure I won’t lose anything small, but useful), but hardcoding this value will make changing history size to something else more painful.

Vim: How to handle newlines when storing multiple commands in registers?

I have a file where I store snippets of vim commands. When I need a snippet, I yank it and then execute it with #". The snippets are stored as a script, one line per command, like this:
:s/foo/bar/g
:echo "hello"
:s/1/2/g
Edit: I removed normal mode commands from the example, as they were not part of the problem.
Now this procedure doesn't work anymore: when executing the snippet, it just stops at the first line as if waiting for a newline.
Is there an option somewhere affecting how # is executed? I'm pretty sure it was working some time ago...
Substituting the newline with a ^M character works but makes the file more difficult to handle.
Additional information:
Here's another symptom: when I yank a snippet, if I execute it with #" it stops at the first line as I just explained. But if I execute it with :# it works. But the help file doesn't seem to imply any difference in how the two commands treat the register's content...
I don't think the problem is ^M vs. ^J. Vim macros will treat either one as a valid end-of-line character for recorded macros. I think the problem is extra newlines.
In your example, there's at least one spurious newline after 2j, and unless you're particularly careful when copying the snippet, there's probably another one after 10k as well. These extra newlines are like pressing <Enter> in Normal mode -- they move the cursor down one line.
Here's what I think you want the snippet to look like:
:s/foo/bar/g
2j:s/1/2/g
10k
(Even that's a little misleading -- you'd still have to be careful not to copy the newline after the 10k.)
Why do these extra newlines make such a big difference? Well, for one thing, they cause you to be at least one line away from where you expect to be, which throws off anything you want to do on a particular line (like execute the :s// command).
More importantly, however -- and this is what I think is happening in your example -- is that Vim stops macro playback if the macro attempts to use <Enter> on the last line of a buffer. (I'm guessing Vim considers it an error, and any error causes a macro to stop running.)
Here's an example. Suppose you've got this snippet stored in register x:
4j
:echo "Done"
(Notice the newline after 4j.)
Furthermore, suppose you have the following five lines (and only these five lines) in a buffer:
line 1
line 2
line 3
line 4
line 5
If you now press #x on line 1, the :echo "Done" never executes. Vim moves the cursor down 4 lines to line 5, then attempts to move down one more line because of the extra newline, but it can't. The macro stops executing at that point, before the :echo command gets a chance to run.
However, it works if you change the x register to this:
4j:echo "Done"
So to return to your original example, I'll bet what's happening is that the extra newline after 2j is attempting to move your cursor somewhere it can't go, and that causes the macro to stop. The bottom line of the screen contains the last command executed (:s/foo/bar/g), which makes it look like Vim is waiting for you to press Return.
Finally, I'd strongly recommend using another method to store and execute Vim command sequences. The technique you're using is tolerable for simple cases, but it's fragile and doesn't scale well. Vim has a full scripting language that includes functions and custom commands, and it can be used to do all the things you're doing now, but in a much more robust fashion. Vim scripting is a big topic, but I'd start here:
:help script
Be sure to read about the :normal command, which lets you execute Normal-mode commands (like 2j and 10k) within scripts.
Good luck!
I finally found the culprit. Somehow I had a command mapping on <C-J> in my .vimrc file. When read with the default cpoptions, this turned into a mapping on <NL>.
How I found out: I noticed that when starting vim with -u ~/.vimrc, it would indeed execute yanked snippets. I generated a session file with and without that commandline option and compared them. This way I found out that a different set of cpoptions where used to read the same .vimrc file, so that in one case the mapping was indeed on <C-J>, in the other it was converted into a mapping on <NL>!
If someone has a similar problem, I suggest to look carefully at the currently set command mappings, with :cmap.

Resources