How to execute a command in a buffer with a specific name in the background? - vim

I'm currently doing the following, but it makes the current window switch to the buffer in question, which is disruptive:
let current_buffer = bufname("%")
buffer NERD_tree_1
normal R
exec "buffer" current_buffer
Is there a way to execute a command in a buffer with a specific name (in this case NERD_tree_1) in the background?

No, there's no such mechanism, especially not for :normal, which executes commands in the current window.
I see two options:
Since you're already relying on plugin internals (the NERD_tree_1 buffer name), you could further delve into the plugin and directly modify it / its data structures to achieve your goal. Note that this is a brittle solution that is susceptible to future plugin updates, and therefore not recommended.
Completely rely on the plugin's external interface (i.e. replace the :buffer commands with :NERDTreeToggle), and live with the side effects of the plugin briefly activating.

Related

Pasting text to a new buffer

I've found questions that are similar, but don't really address what I'm trying to learn. I want to yank or delete text and append it to a new (or existing) buffer without changing buffers. I want to basically redirect the pasted text to its destination at the end of a separate buffer without leaving the original one, similar to what you might do with shell file redirection. I have a hard time believing vim/nvim can't do this, but haven't found an appropriate answer anywhere as of yet.
:'a, 'bw ~/path/to/file.txt
This will copy the text between the two marks 'a and 'b, and write it to a file in the filesystem. This is good, but the file can't be appended to... and it doesn't get opened in a buffer.
There is a :w >> {file} variant that lets you append to a file (:help :write_a).
As #Matt already commented, the usual way would involve switching buffers. Vimscript usage is closely aligned with (mostly Ex-) commands that the user would interactively use. With recent Vim versions, you can alternatively call the low-level appendbufline() function, though. This would bypass any autocmds, buffer setttings, etc. Depending on your use case, this can be desirable or not.
If the target buffer is already visible or can be kept visible as a side effect, temporarily switching to it is easy (mostly involving :sbuffer). My ingo-library plugin has a function ingo#buffer#visible#Execute() that also handles hidden buffers transparently.

Preventing vim script from being applied to itself

I have a vim script with substitutions:
:%s/|I\(cc\|ee\|CC\|EE\)|/|$I_{\1}$|/
:%s/|UOmax\([+-]\)|/|$U_{Omax\1}$|/
:%s/|KcmR|/|$K_{cmR}$|/
:%s/|KsvR|/|$K_{svR}$|/
:%s/Uoffset/$U_{offset}$/
..............
Sometimes I forget that this script is currently edited, so I execute so ~/.vim/macros/script.vim and it is modifying itself. How to make script know that it is currently edited?
You could check that expand('%:p') != expand('<sfile>:p') before continuing.
Honestly, I'm not sure I'd bother with that as undo will quickly fix the issue, and moreover as I often open many buffers, I'm likely make the mistake on any buffer.
BTW, another approach would be to define a tex ftplugin, where you'd define a fucntion that does the substitutions, and a buffer-local mapping that executes the function on the current buffer. This way, you won't have the possibility to run the substitution on buffers that are not LaTeX ones.
Try to install vim-quickrun and type <leader>r. vim-quickrun run the script from buffer instead of file if it's modified.

Save Changes to a Vim Buffer Without Switching to That Buffer

How can I save the changes to a modified Vim buffer without switching to that buffer? I am trying to write a function that saves and closes all the buffers in a project.
Apart from the :wqall command, there's no command that writes a buffer other than the current one.
So you do have to switch to the buffer in order to write it. You could use :noautocmd to avoid the associated events (but that may have adverse side effects!).
The only alternative would be to use low-level functions like getbufline() and writefile(), but then you would have to deal with encoding conversions, fileformat, etc. on your own.
You can use :wqa[ll] to write and close all changed buffers. :wa will write without closing.
You can use the argument list, see :help argument-list.
Supposing you are working with three files foo, bar, baz, and want to only write foo and baz:
:args foo baz
:argdo w
You'll obviously need additional logic to determine which buffers to put in the arglist in the first place but it sounds like you already have that.

How to eliminate the delay in message redirection to a file in Vim?

I have this line in my vimrc:
redir! >/Users/seanmackesey/.vim/.vimmessages
But messages do not show up in this file immediately after they are generated-- when I run tail -f .vimmessages in the shell, messages show up slowly and somewhat erratically. I get a big dump of messages to it sometimes when I run the :messages command, but I can't figure out exactly what the pattern is. Is there a way to simply append each message as it occurs, immediately, to the end of a file?
The problem with a global :redir is that it doesn't nest, so it'll cause errors with mappings and functions that use :redir, too. Rather, use
:set verbosefile=/Users/seanmackesey/.vim/.vimmessages
to capture all messages. Because Vim's implementation uses buffered output, you'd still experience some amount of chunking, though.
You didn't mention where you intend to use this output, so it's hard to give a better recommendation. If you really need immediate output to an external file, you'd have to use writefile() or use an embedded scripting language to write and flush a file.
This seemed more likely to be simple data buffering, not any specific time delay.
I grepped through the Vim 7.3 source, and it looks like the redir is done with fopen, puts, and putc, and fclose (i.e. stdio). There did not appear to be any calls to fflush, setbuf, setbuffer, setlinebuf, or setvbuf so the redirection will always use the default buffering provided by your system’s stdio (probably “block buffering” of some convenient size).
You could periodically stop and restart the redirection to effectively flush the data:
redir END | redir! >>~/.vim/.vimmessages
Short of that, there does not seem to be a nice way to do what you want with redir to a file.

Use Vim to "colourize" files or input streams

This may be an odd question, but still. I use cat to display a file in bash (KDE Konsole),
cat foobar.rb
Now, I would like to use Vim to colourize that foobar.rb file according to what you would get when you start foobar.rb in Vim. Edit: But only for display purpose, on the terminal.
I am not sure this is possible, but I thought it would be neat if I could use Vim for that.
I really just want colourized keywords, and Vim has the perfect colour definitions.
So I thought combining this would be great.
Is this possible in Vim out of the box though?
One approach would be to use a library such as Pygments, which is a general purpose syntax highlighter. You could write a wrapper called ccat or something that would apply syntax highlighting to an input file and write to stdout.
If you want to page up and down in a highlighted file, you can use less with the -R switch, which passes control characters through to the terminal directly, preserving colours. So:
ccat file.rb | less -R
But at that point, you're pretty much at the capabilities of view.
I'm not sure if I understand your question correctly, but if you are only looking for a command that will give you a read-only view of the input file (like cat) but with coloured keywords, use view. view is an alternative way to start vim in read-only mode, so you have all syntax highlighting possibilities. From the vim man page:
view Start in read-only mode. You will be protected from writing
the files. Can also be done with the "-R" argument.
gvim gview
The GUI version. Starts a new window. Can also be done with
the "-g" argument.
evim eview
The GUI version in easy mode. Starts a new window. Can also
be done with the "-y" argument.
rvim rview rgvim rgview
Like the above, but with restrictions. It will not be possi-
ble to start shell commands, or suspend Vim. Can also be
done with the "-Z" argument.
I have always seen view on systems that have vim installed.
Closest is the less script that comes with vim:
cat myfile | vim -u /usr/share/vim/vim72/macros/less.vim -
Note the - argument to vim. You may need to change the vim72 to your version (and the whole path if you have it installed elsewhere)
Now, this isn't exactly what you want, because its behaviour is less-like, in that you have to press keys to make it scroll down or complete. However, they are briefer than usual vim. For example, space to scroll down; and q to quit (not :q).
You want a cat-like version; me too. But there doesn't seem to be one.
EDIT uh, there's also a vimpager project, that includes vimcat - exactly what you want. But it doesn't come with vim, and I haven't tried it yet.
vim.org: http://www.vim.org/scripts/script.php?script_id=1723
github: https://github.com/rkitover/vimpager

Resources