6

I have enjoyed coding not too large projects in one single file. This way I can press * on an identifier and find it without having to hop across buffers.

But naturally this doesn't scale and at some point I need to isolate code into multiple files.

Here is a dream use-case for which I wonder what is the best way to accomplish:

Edit one buffer with multiple sections, each titled with the name of a file. Upon saving, each section is saved into the appropriate file. Upon loading/reading files, each file is incorporated into the buffer into a section titled with its name.

By "section" I do not mean any special construct. Just some convention, perhaps file name underlined by ===== to denote a boundary in text.

Here's an example:

main.py
=======

import util

print(util.rnd())

util.py
=======

def rnd ():
    return 7

PS: please excuse the diminished entropy of the random generator in this example

2
  • 1
    You can't do this with buffers; but you can use multiple windows. See :help windows-intro. Commented Nov 6, 2018 at 5:18
  • Tags (à la ctags, e.g.) would be a possible solution to the real problem, if someone who knows how to really set them up easily cares to explain
    – D. Ben Knoble
    Commented Nov 6, 2018 at 13:22

3 Answers 3

1

I don't thinks it's doable in pure Vim, or easly doable, but you can write a little script, in Python for example. Let's call it split.py. You can have a file, let's call it code.py, which will be the one that you edit. You can then call your script:

./split.py code.py

You can then also automate it in Vim with:

autocmd BufWritePost code.py !./split.py %

This will call your split.py whenever you will save a file called code.py.

Or have it in $PATH somewhere, and call it without ./

To merge files, you could write another script - merge.py - and call it manually or try to use BufReadPre autocommand in similar way as above with BufWritePost.


On the other hand, since you're using Python in the example, why not try Python-mode plugin, which provides really nice experience while working with Python code (you will need also some kind of completion plugin, like neocomplete, YouCompleteMe, deoplete, etc..). I'm using this setup at work as a Python developer. It contains refactoring tools, go to definition, linters, checkers

3
  • i'd upvote if i had enough reputation, so this thank you comment instead. i figured it would not be available out of the box and your autocmd BufWritePost is exactly what i would need to know to implement it as you have suggested. I guess there could be a autocmd BufWritePost *.py that invokes merge.py whereas the split would be as suggested. One would typically only edit code.py but in the off case somebody edited a file directly then the merge would take care of it. Thanks for the VIDE recommendation -- so far I get by with plain vim but a good refactoring tool would be great! thx. Commented Nov 6, 2018 at 9:46
  • I'm glad that this helped you. You should be able, as a question author, to accept/mark eventual answer as a good one? Can't tell exactly, since I never asked a question ;)
    – grodzik
    Commented Nov 6, 2018 at 12:30
  • yes, the only thing I can do is accept but I tend to wait for a few more responses just in case there is some magic command that we both didn't know about Commented Nov 7, 2018 at 12:27
2

You can achieve the functionality you're looking for through the use of multiple windows. This allows for search and highlighting across windows. To save all files :wa to save and close :wqa.

Open new windows using :split/<C-w>S for horizontal splitting or :vsplit/<C-w>v for vertical splitting. You can then navigate between using <C-w>[h/j/k/l] or <C-w>w to cycle through windows. To open the desired files use :e /path/to/file (relative to directory you opened vim from)

BTW didn't know you could push * to highlight all occurrences of an identifier, its a neat trick. A fine addition to my collection ;)

2
  • I'm gladd * helps you; # is the opposite. I assume you konw f and t, and if so ]), ]} and ]] might be new and useful. Back on point, your suggestion doesn't really help because if I press * and then n I cycle through just one window and my cursor does not go to other windows. It is hardly equivalent to a single file mode where I can find globally not to mention page down and up between files. It seems it isn't possible without hook scripts as the previous answer shows. thx for your suggestion happy viming "ayy, "ap, "Ayy, ma, 'a, `a, '', ```' ..... Commented Nov 6, 2018 at 9:50
  • Ah right, gotcha. Depending on how much effort you want to put in and how perfect you want your solution to be it's fairly damn close. Every time you hot the bottom you cycle windows once with <C-w>w and continue next-ing till you hit bottom etc. But from the functionality you're looking for I do concede it doesn't seem to answer your question. Maybe further clarification in your question in future would be good? Be specific in what functionality you would like or what you're trying to achieve.
    – ljden
    Commented Nov 6, 2018 at 11:08
0

I think you're approaching that from the wrong direction: Instead of artificially joining and splitting multiple files into a single buffer, you should instead adjust your searching to cover multiple buffers (or windows, if you :sbuffer them). That means that you can't simply use * and n/N to go through all matches, but:

  • use :vimgrep and the quickfix list and corresponding commands (e.g. :cnext) to iterate over matches
  • :set nowrapscan and switch to the next window (<C-w><C-w>) before continuing searching with n
  • use a combination of :bufdo and :global to show matches
  • ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.