I'm trying to do something very simple:
I have two buffers in Vim, one with source code (B1), another one with a text file a.txt (B2). The source code in B1 is run with a custom shortcut in Vim, filling a.txt with text. I want Vim to automatically scroll B2 every time it updates, even if my cursor is in B1. So, I just want that the buffer B2 to behave the way tail -f does.
Doing this with ConqueTerm is not an option, since buffer B2 can be a preview buffer from other plugin.
In general, vim events fire in response to user input. They don't just run continuously in the background.
This post details some tricks you could repurpose to write some customization code to reload your "tail -f" buffer and scroll to the bottom periodically.
Rather than trying to do this all in vim, here is a different proposal that would achieve a similar effect using GNU Screen (one terminal area with vim editing a file file1, another running tail -f against a different file file2):
download/install GNU Screen (perhaps apt-get install screen)
run screen
run vim file1
type Ctrl-A S to split the terminal down the middle horizontally (or, in recent versions of screen, Ctrl-A | to split it down the middle vertically)
type Ctrl-A Tab to switch to the other side of the split
type Ctrl-A c to start a new terminal on this side
run tail -f file2
Now one side of the split shows vim file1 and the other side shows tail -f file2. Here's an image of the result.
This command moves to the window containing a.txt, reloads it (edit), moves to the end (+$) and then jumps back to the previous window. You can add it to the shortcut that runs your source code to get a.txt to update whenever the code is run.
:exe bufwinnr("a.txt") . "wincmd w" | edit +$ | exe winnr("#") . "wincmd w"
Remember to escape the bars (\|) and add a <CR> at the end if you use this in a mapping.
This will require your shortcut to run the code in foreground, and Vim will be unresponsive till it is done (unless you press Ctrl-C). If you want Vim to reload a.txt automatically whenever it is changed (thus bypassing the need for running the code in foreground), you will need an external mechanism for file change detection (such as inotifywait on Linux). As far as I know, Vim only checks for external changes (with autoread) when you move the cursor to that window.
Related
I use Putty to connect to a server and I use 2 sessions, because I want to compare 2 .sh files and I find it easier to have both files on different windows.
I am using VIM as a text editor and want to yank a line from the file of the first session to the file of the second session.
I am using V"+y to yank and then p to paste, but it only works if I close the file in the current session and open the other file in the same session.
Is it even possible to yank text from one session and paste it in another?
You can have two windows in one single Vim "session":
# two windows stacked vertically
$ vim -o file1 file2
# two windows stacked horizontally
$ vim -O file1 file2
And you can even diff them:
$ vim -d file1 file2
So it seems to me that your initial goal, as described, doesn't warrant the use of two separate Vim "sessions" at all.
See :help -o, :help -O, :help diff.
To yank between two concurrent Vim "sessions" or one Vim "session" and another program, the bare minimum you need is a clipboard-enabled Vim but it is not clear what you call "session" (is it a Vim session or a shell session?) so I doubt that it will be enough in your case.
It turned out that I had mouse mode enabled and when I turn it off I can simply Ctrl + C the needed section and add it to the other session. Didn't know the mouse mode makes such a difference.
I need to document all commands that I used to modify text using Vim editor. When I am in the terminal and need to save all my input in a file I usually write:
history > ~/some_file.txt
However, I am not sure how to do it while using vim. Can you tell me?
Any output can be redirected with :redir. So
redir >~/vim.history|silent history|redir END
Will redirect the output of :history to the file ~/vim.history. Here silent is used to prevent a -- More -- prompt.
You could also put the history into the current buffer with
:put =execute(':history')
Note that Vims history is limited to 50 entries by default (see :help 'history).
Use startup option -w. From the docs:
All the characters that you type are recorded in the file "scriptout", until you exit Vim. This is useful if you want to create a script file to be used with "vim -s" or ":source!".
Press qx, which causes Vim to start recording your keystrokes.
Press q to finish recording.
Move your cursor to wherever you would like Vim to paste the record it has just made.
Press "xp to paste the record.
The x identifies a buffer. Buffers y, z and so on also exist, so you can use a different letter than x if you wish.
Nothing requires you to paste the record into the file you were editing when the record was made, incidentally. To paste into a different file, give the command :tabedit name-of-different-file, press [Enter], and then press "xp to paste. (Since :tabedit opens the second files in another tab, you can then press gt to toggle between the two if you wish.)
I'm trying to map a command or function that splits a new window vertically, switches the cursor to the new window, and runs an external command on the <cWORD>.
When I do:
:vsplit|wincmd w|execute '!perldoc <cWORD>'
Vim seems to run the the external command first in the current window and then when the command exits, Vim creates a new window and switches focus to it.
If I break these commands up into separate lines in a function and call the function, the same thing happens. Is there a way to have Vim do what I want it to do?
My coworker Tye showed me how to do it:
let w=expand("<cWORD>") | vnew | execute "read !perldoc " . w|1
Save <cWORD> as variable w
vnew opens a new empty window
execute read !perldoc passing w as the variable. The output is read into the new window
Jump to the first line of the buffer in the new window
If you don't tell Vim otherwise, new vertical windows open on the left by default, leaving the cursor in the new window.
If that's not what you experience you should definitely investigate why.
After :vsplit, further commands are executed before the new window is rendered, in what you can imagine as a "virtual window".
This means that, however unsettling it can be, you won't see the new window before the next command. That's how Vim works and there's nothing you can do about it.
In the example below…
I have two perl files in the same directory,
in perl.pl there's a sample perl script I found online,
in warnings.pl there's a single word, warnings,
perl.pl is open in Vim with the cursor on strict,
I run :vsplit|!perldoc <cWORD>,
I expect to see the documentation on strict in my pager and the same buffer displayed in two vertical windows when I come back to Vim,
I close the left window,
I run :vsplit warnings.pl|!perldoc <cWORD>,
I expect to see the documentation on warnings in my pager and two different buffers displayed in two vertical windows when I come back to Vim.
Let's see:
Looks like everything worked as expected.
I don't see any but you probably have a good reason for opening that new window. I will suggest :help K and :help 'keywordprg anyway:
set keywordprg=perldoc
The opposite question seems to be asked a lot: how to move a window into a new tab in an existing window. What I'm hoping is that a tab that I have open in gvim can be moved out into its own window or into another existing window.
Is this possible?
Thanks!
Same Vim instance
If that tab shows just a single window, you just have to note its buffer number (e.g. via :ls or :echo bufnr(''), or by including it in the statusline), and then close the tab via :close (:set hidden helps with modified buffers), then going to the target tab / window, and re-opening the buffer there via :buf N or :sbuf N.
If you need to support multiple windows in a tab page, you'd have to write a custom command / mapping that first remembers the buffers, and then applies the above steps for all of them.
Different Vim instances
Edit: The above is for movement within a single Vim instance. If you want to move a buffer to another GVIM instance, you first have to :bdelete it in the current Vim, to avoid swap file messages. Launching in new instances is easy:
:execute 'bdelete | !start gvim' shellescape(expand('%:p'), 1)
This passes the (full absolute) path of the current file to a fresh GVIM.
To move a file to an existing GVIM (you need to know its v:servername), you need to use the remote client-server communication (:help remote.txt), e.g. by sending a similar :drop command via remote_send(), like this:
:execute 'bdelete | call remote_send("GVIM1", ":drop " . ' . string(fnameescape(expand('%:p'))) . '. "\<CR>")'
Here is how you can "move" the current buffer to a second GVim instance:
:!gvim --remote %
:bw
Note that Vim must be built with the +clientserver option.
No, it is not possible.
You cannot move a vim tab into a window, no matter new or existing. Because a vim tab page is a collection of windows. You cannot move a collection of windows into one single window.
There got to be a way to open a newtab in background, without leaving the current tab, but i just can't find it in the docmentation.
Scenario: User Bob works on file: foo.txt. An external program updates periodically a file bar.txt. It then opens a new tab in the background of Bob's vim-session without forcing Bob to switch away from his current editing of foo.txt in his foreground tab.
All tab* commands doesn't seem to do the job. What am i missing?
You could say im looking for an equivalent to :tabnew_in_background_leave_edit_mode_as_is().
You can use
$ vim --servername BOB --remote-tab +":tabprevious" filename
edit
Vim has no command for opening a tab in the background. That's why we need the :tabprevious trick to open the new tab and go back to the previous one immediately. The drawback is that we are not in insert mode anymore.
Fortunately, we have gi, the normal mode mapping used to return to insert mode where it was last exited. This command works, here:
$ vim --servername BOB --remote-tab +":tabprevious" filename && vim --servername BOB --remote-send "gi"
Including and generalizing it in a shell script doesn't sound complicated.
Here is a second way, using the same ingredients but combined differently:
$ vim --servername BOB --remote-send "<Esc>:tabe filename | tabprevious<CR>gi"
Basically, we exit insert mode, do our "tab" business and get back to where we were. And we have another drawback: this method is tied to insert mode so we would end up in insert mode even if we were not there before.
Unfortunately I don't see a way to do that cleanly that doesn't involve writing a function.
did you check --remote-tab? or I misunderstood your question?
in vim, type :h remote-tab
--remote-tab Like --remote but open each file in a new
tabpage.
so you could try: (assume you had already a vim "server" named "SVR"):
vim --servername SVR --remote-tab foo.txt
the foo.txt will be opened in tab of SVR vim instance
Pressing SHIFT + t when the cursor is over a filename in a directory listing opens the file in a background tab.