vimscript - catching keystrokes with autocommands - vim

Say, if I need to process an :ex command I can use getcmdline() tied with CmdWinLeave, for example. This way I can, for example, automatically catch when a window is closed.
But I cannot catch, for example, a :h CTRL-W_q in that way.
I would like to know how could I catch this kind of keystrokes being pressed (not necessarily in relation to windows). Thank you!

Related

Vim detect what kind of buffer the current buffer is

I'm making a plugin where the idea is that if the buffer is empty then you'll enter insert mode, otherwise you'll stay in normal mode.
Of course this is all nice and well but you come across some problems, what if you just opened Vim and you're in the default empty buffer and you don't want to do anything in that buffer? You gotta first go to normal mode and then do your :e magic. Which is undesirable as it takes more work.
So my question is, how does one detect if the current buffer is a real file whether it exists in the file system or not.
For example, I'd like to detect if the buffer is a JS file, whether new or pre-existing. Or if the buffer is a NERDTree buffer or a plugin buffer, that kind of stuff.
Thank you. Any help is appreciated. :)
P.S.: For those interested, this is the plugin: https://github.com/Greduan/vim-empty-insert
if expand('%:p') != ''
" do stuff
endif
See :h %:p and :h expand().
BTW, sorry if this sounds rude, but I'd guess many long-time Vim users would automatically press a/i when they enter a buffer, without thinking whether it exists on the drive or not. So you might want to consider keeping the functionality more consistent.

Run vim commands on errors?

Ok so this question is vaguely related to one of my previous questions:
I want Vim to be able to save and close similarly to Photoshop in regards to buffers?
Basically the solution I found (or gets really close to what I want), is a plugin called BufOnly which basically closes all buffers that have not been modified. So when I have a lot of buffers open and I want to close, I just run this, and then just care of everything that I haven't already. It works well.
But I'm greedy. I want this to execute automatically when I need it to. Basically I would like it so that if I run qa, if qa runs into -->
E73: No write since list change (add ! to override)
Then I want to run
:BufOnly<CR>:bd <cr>
Is there a way to do that?
you can write a function with vim's try-catch mechanism. example:
function! Funk()
try
execute "qa"
let yes = 1
catch /^Vim\%((\a\+)\)\=:E37/
execute "BufOnly"
execute "bd"
endtry
endfunction
this will catch the error :E37 and do the command you want. I don't have that plugin installed, I therefore didn't test with BufOnly. I tested with "h gg", it shows the help page of gg
to call the command, type :call Funk(), of course you could create mapping for that function call.

Return focus to vim when using screens plugin after ScreenShellFocus?

The screens plugin turns vim into a kind of dreampie, only its a whole lot better because you have more control over what gets send even when you have multiple buffers and specific text within those buffers.
To follow my environment setup, merely install screens with vim, and then at the command line, do screen, reach the shell, then type vim in. Edit a shell script of some kind with it, then do :ScreenShell *shell type here, eg python/bash/irb* which spawns a shell below. You can use :ScreenShellSend to send the visually selected text to the shell or all of the file if none is selected.
My problem is, say I want to restart the shell that I'm running using this plugin and sending it some text. I need to do :ScreenShellFocus, call exit, and then start it up again. But then I need to be able to return to the same vim session that is directly above the shell that I'm affecting. I realize that I can use screen to just reach the vim session, but the only way I can do that now is to select it with ^a 1, which really only replaces the lower portion, the one that supposed to be the shell, with the vim buffer being edited. This is stupid because now you have vim buffer on top of vim buffer.
So my question is, how do I return the cursor to the vim session above after doing :ScreenShellFocus?
(yes I know my example of killing and restarting a shell may be circumvented by other logic, but I'm not that acquainted with the GNU screen util, and I think there's a way to do it like this, which I think preserves the workflow of the programmer)
<C-a><Tab>
is the mapping used in screen to cycle through "regions". Since you have only two, it moves the focus to the other region.
Since you are effectively using screen, you should learn how to use it to make this plugin really useful.
$ man screen

A Stop button in VIM

Often I test a function or click too often on an key on my keyboard.
I can't stop the output of the function... I can't stop VIM doing what it is asked to do.
Is there a way to Stop all processes in VIM?
I have asked a similar question recently.
CTRL+C works most of the time to interrupt a long process.
To add a button, see :help toolbar-icon.
It should be something like :amenu icon=[icon-path] Toolbar.Stop <C-C>
You could use ctrl-break on Windows. I do not think it would work well as a button since if Vim is kicking out a lot of output it may not be able to service the GUI functionality fast enough.
On Windows (with mswin.vim) ctrl-break, everywhere else ctrl-c.

How can I make VIM play typewriter sound when I write a letter?

After a lot of writing in Q10 on Windows, I got used to the typewriter sound it makes every time you press a key. At least for me it feels great to have this sort of sound feedback.
On Linux on the other hand, I love writing it VIM, because of it's editing features. How could I add this functionality to VIM?
Simply said, I want to play a sound every time I press a key in the insert mode.
Alright, this kinda crazy, but it appears to work. First, grab yourself a typewriter sound in aiff format. Then put that typewriter sound in ~/.vim/support/my_typewriter_sound.aiff. Then add the following to your ~/.vimrc.
function! PlaySound()
silent! exec '!afplay ~/.vim/support/my_typewriter_sound.aiff &'
endfunction
autocmd CursorMovedI * call PlaySound()
Note that the above function calls out to afplay, which I know works on a Mac and needs to be replaced with play on Linux. On Windows, I have no idea.
So you know what's happening above, we're first creating a function called PlaySound that shells out to afplay. We then setup an autocommand that gets fired anytime the cursor moves in insert mode. When it fires, it calls PlaySound.
The plugin does exist. You can find it here: https://github.com/osyo-manga/vim-sound
However, you need to add sound effects files yourself, which you can find here:
http://www.soundjay.com/typewriter-sounds.html
If you're on Solaris, you can DTrace the kernel keyboard driver with this set of scripts: http://www.brendangregg.com/DTrace/typewriter-0.75.tar.gz
You should try Qweritckle
It's a typewriter sound emulator for Linux.
Fun idea, and thanks for the answer Trotter. However, using your answer I found with my system (Ubuntu 14.04) that Vim went blank at each keypress with the message:
Press ENTER or type command to continue
Based on discussion on the topic of executing commands silently in Vim at https://vi.stackexchange.com/questions/1942/how-to-execute-shell-commands-silently I tried:
function! PlaySound()
silent! exec '!play ~/.vim/support/my_typewriter_sound.wav &' | :redraw!
endfunction
autocmd CursorMovedI * call PlaySound()
which cleared the blank screen automatically, but I could see the flicker after each keypress and the sounds were only produced after the last keypress was finished, making for quite an unnatural and epileptic experience. In the same question OliverUv gave the important explanation that Vim executes synchronously, meaning it waits to continue until the execution is completed. He suggests vim-dispatch or Neomake for asynchronous execution, but in the end I went with Do for Vim as it is more geared towards executing arbitrary shell commands rather than specific compilation tasks. Do for Vim utilizes built-in Python support in Vim to run each command on a separate thread (asyncronously). I am very pleased with the results using this plugin as follows:
function! PlaySound()
:DoQuietly play ~/.vim/support/my_typewriter_sound.wav
endfunction
autocmd CursorMovedI * call PlaySound()
There is no flickering of the screen and the individual keypress sounds overlap for an authentic clattering cascade of clicking.

Resources