Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically applying change commands in multiple windows in Vim

Tags:

vim

Can Vim automatically apply change/insert commands such as dd, O, and u to all open windows? I am composing a LaTeX document in one window and would like to use a second window for my margin notes, TODOs, etc. (similar to Cornell notes). My Vim tab looks like

|1 \documentclass{article}       |1 
|2 \begin{document}              |2 
|3 Lorem ipsum dolor sit amet,   |3 TODO: reword this.
|  …consectetur adipisicing elit.|  
|4 Ut enim ad minim veniam, quis |4 Could use some more examples.
|  …nostrud exercitation ullamco.|  
|5                               |5 Put bibliography here.
|6 \end{document}                |6 

I need to keep wrap (and preferably showbreak) toggled as my sentences are often fairly long.

So far I am successfully using scrollbind and cursorbind to navigate the two files in parallel. When I insert or delete lines in one file, though, the alignment breaks. For example, I might insert a line (using o) in the lefthand window to load a package, producing

|1 \documentclass{article}       |1 
|2 \usepackage{hyperref}         |2 
|3 \begin{document}              |3 TODO: reword this. 
|4 Lorem ipsum dolor sit amet,   |4 Could use some more examples.
|  …consectetur adipisicing elit.|  
|5 Ut enim ad minim veniam, quis |5 Put bibliography here.
|  …nostrud exercitation ullamco.|  
|6                               |6
|7 \end{document}                |~ 

Now all the comments in the righthand window are on the wrong lines. If my edit in the lefthand window also inserted a new line after line 1 in the righthand window, the alignment would be preserved. I have had some success using the windo command (e.g. windo normal dd to delete a line in both files); should I map dd to window normal dd and similarly for every command I might use? How would this work for commands like o that leave you in insert mode?

To complicate the problem, I would ideally like any action that created or deleted a newline character to be replicated in both files. For example, carriage returns in insert mode should be caught and repeated in the other window.

Is there some better way of doing this (I will stick to Vim but would be interested in hearing about other editors that have this functionality), or should I just keep my comments inside the document file?

like image 579
Ben Whitney Avatar asked Dec 11 '13 18:12

Ben Whitney


2 Answers

Nice, I've never heard of the Cornell notes but I doubt it's possible to synchronize two buffers the way you want without any hickups (I'd love to be proven wrong though).

But what if we step back a bit and instead of trying to synchronize two buffers we try using just one buffer by creating a gutter at column 120?

Workflow

  • Create a new document
  • :set virtualedit=all
  • In normal mode, type 80@='120|i|^M^[' to create a gutter at position 120 over 80 lines.
  • Write the document and notes
  • Save the document

^M is entered as ctrl-venter
^[ is entered as ctrl-vesc

Advantages

  • Navigating and deleting the document and notes is simplified. After all, you are just working in one buffer.
  • You'll just have to open one file to have both document and notes.
  • If you spend most of the time navigating and altering an existing document, this could be a viable solution.

Disadvantages

  • Writing the notes will be more complicated because you'll have to use R (replace) a lot instead of i (insert) to not mess up the gutter we've created.
  • Resizing two buffers is easier than 'resizing' the fixed gutter.
  • If you spend most of the time creating new documents, well, it's going to be painfull.
like image 105
Lieven Keersmaekers Avatar answered Nov 09 '22 05:11

Lieven Keersmaekers


Within Vim, you won't be able to implement a perfect system that is 100% complete and consistent.

While commands like dd can be applied straightforwardly to the other buffer, insert mode already requires that you wait for the end of the text entry. A command like u cannot be directly applied at all; you need to watch for what changed, and apply that to the other buffer. Same for most Ex commands like :global, :substitute.

Instead of re-mapping most commands, I'd rather define :autocmds on events like CursorHold,InsertLeave, which compare the total number of lines with the previously stored value, and then adapt the other buffer at the current line accordingly. If you're willing to accept that certain edits will fall through that scheme, and you either avoid those or manually correct them, this can be a workable solution.

like image 22
Ingo Karkat Avatar answered Nov 09 '22 07:11

Ingo Karkat