Save Changes to a Vim Buffer Without Switching to That Buffer - vim

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.

Related

How to save buffer (preferably if changed) and then close the buffer but not VIM?

So, I just realized I could use marks with capital letters to go to different files. That's great! However, I'm trying to find a way to close the buffer and return to the previous one. Say I go to my header file to change or add the declaration of the function I'm writing, and then I'd like to save the file, but only if there's changes to it, to go back to working on the contents of the function. How can I do this?
There's :x, but it also quits VIM
There's :bd!, but it doesnt save the changes
There's :bw, but that's even worse (unfortunately that's w[ipeout], not w[rite]...)
There's ctrl+O, but it doesnt seem to work when I edit the file (also, it doesnt actually close the buffer)
There's :up followed by :bd, but that's two commands and VIM's about efficiency, so I'd prefer a single command if it exists
There's a few other options and variants, but none that do what I wanted, afaik
It feels like this should be simple enough to do with one command, preferably without macros/plugins/functions/snippets/etc; as close to vanilla as possible. I get the feeling I'm missing something obvious.
You could concatenate commands like so:
:w|bd
I'd like to save the file, but only if there's changes to it
:up[date]
to go back to working on the contents of the function
Press Ctrl^, or enter the command :e[dit] #
I'd prefer a single command if it exists
Set an option :set autowrite and then Vim will save the current buffer on pressing Ctrl^ automatically.

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.

Syntax of Greplace

I want to change some words in several files using VIM. To do this, I found out about Greplace, which appears to be made to do just that. However, in the documentation there is no sample of the syntax of Greplace (there is a sample of Gsearch, but I need the replace function).
Say I want to change "foo" for "bar" in all ".asp" files, how could that be achieved with Greplace (or any other method). I do not care about confirmation (it's fine if it requires confirmation; it's also fine if it does not).
It's trivial to do without a dedicated plugin.
$ vim *.asp
:bufdo %s/foo/bar/ge | update
:q
:bufdo runs the following commands on all buffers.
%s/foo/bar/ge replaces foo with bar on all lines and all occurrences in each line. The e flag makes sure :s doesn't emit an error if it doesn't find foo, since foo may not exist in all the files.
| is Vim's way of separating multiple commands to run. See :help :bar
update saves the file back to disk, only if any changes were actually made.

Lock some text in vim to prevent modifications

I'm looking for a way to prevent the modification of a part of a vim buffer. I know it is possible to lock buffer to prevent all modifications inside, but I would like to do the same for just a few lines, or a paragraph.
Any idea if this is possible ?
Cheers,
V
Well, as I know, vim can not do that. The text in vim buffer is just a "string" without any property can be attached to them. So "readonly" can be only to whole buffer, but not specific characters, although emacs is able to add text properties to let some characters in buffer readonly.
On the other handle, if you really want to edit something and make it not affect the other buffer content. There should be an alternate way, although is not elegant.
1.create a temp buffer with "setlocal buftype=nofile", insert the text you want to edit into that buffer.
2.show that buffer on other window(need split firstly)
3.edit the temp buffer.
4.when you close that buffer, "merge" the result in the real buffer, and replace the text you want to edit.
So, you need to do that via some key binding and vim scripting, not an easy way.
If the "protected" region of text is readily defined (i.e. by its position in the file, or a regular expression) you could try writing a BufWritePre function that checks this region and throws an error if it has been modified. I resorted to this when I wanted to prevent saving a file with an invalid fold structure.
Presumably this would involve saving the original text in a variable when the file is loaded, and this may have performance implications.
Hope this helps.
There is a plugin called narrow region that edits selected text leaving intact the rest

Resources