How to eliminate the delay in message redirection to a file in Vim? - 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.

Related

How can I find what VimL functions hook into inserting characters in normal mode?

I want to get the set of all VimL functions that are called when I type any character in insert mode.
The reason I want this is to find out which is causing Vim to use high CPU when it's trying to complete variables in some cases.
The 'verbose' option controls the logging. With a value of 15 or higher, any executed Vim command is logged. As functions can now run asynchronously in the background, or triggered periodically, this gets messy fast, and the hit-enter prompts can prevent you from doing any work. Therefore, it's recommended to redirect the logging into a file by setting 'verbosefile' as well.

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.

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

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.

How can I use vim in a pipeline to colorize text?

I'd like to have a command I can insert into a command pipeline that adds color escapes to its input according to vim's syntax highlighting capabilities.
For example:
cat somefile.js | vim - <???> | less
The resulting text would be that of somefile.js, but colorized according to how the current vim configuration would do it in-editor.
It occurs to me that this must be possible. I agree that the example up there isn't what a sane man might call exactly useful, but that doesn't mean the idea never is.
I think your idea has one basic flaw: that nobody ever thought about allowing such a thing.
Clearly vim is capable of doing syntax highlighting. But I'll bet you an ice cream cone that if you can manage to get vim to stream text through and process it, that you won't like the results.
Consider what happens when you pipe text through more (or less if you prefer). When it goes to the terminal, these programs display one screenful and wait for you to hit the space bar. But if you redirect stdout to some other place than the terminal, these programs notice this and simply copy their input to their output unchanged.
If vim doesn't notice that you are piping text through, it is likely to send cursor-movement commands that you probably don't want in your output. If vim does notice, it is likely to just pass the text, and not syntax-color it. Only if vim does do the syntax-coloring but does not inject cursor-movement stuff will your idea work.
You could try it. Here's an answer that discusses piping stuff through vim:
Execute a command within Vim from the command line
But I say why not pipe your text through a program that was designed and intended to have text piped through it? Pygments can colorize every major programming language and markup format.
http://pygments.org/
The major advantage I see for your idea: you can customize the way vim does syntax coloring, get it the way you want it, and then also use vim to process your text. But it's probably not that hard to customize Pygments, and it might even be satisfactory out of the box, in which case it would definitely be the easiest way to go. And Pygments not only has ANSI sequence output, it also has HTML output, RTF, LaTeX, etc. So if you get Pygments working the way you want it to, it should be able to output whatever output format you need; vim will only have the ANSI sequence one.
There's a Perl module called Text::VimColor that I've heard will do kinda what you're looking for.
http://search.cpan.org/dist/Text-VimColor/
But let me ask this: Why do want it to go through less? Why not use vim as a perfectly good file viewer? view - will read from standard input in read-only mode.
https://gist.github.com/echristopherson/4090959
Via https://superuser.com/a/554531/7198.
Tried on /etc/passwd and it works surprisingly well!
This might be what you're after
cat filename.sh | vim - -c 'syntax on; syn=bash'
This is ugly, but you could alias this:
alias vim.sh="vim -c 'syntax on; syn=bash'"
Then use like this:
cat filename.sh | vim.sh -
Use vimcat !
wget -O /usr/local/bin/vimcat "https://www.vim.org/scripts/download_script.php?src_id=23422"
chmod 755 /usr/local/bin/vimcat
vimcat /etc/passwd
See also: https://www.vim.org/scripts/script.php?script_id=4325

Resources