Vim: multi-file editing - having different makes in different splits - vim

I'm a recent vim convert (from fancy IDEs like eclipse.)
I love the :make command in vim and use it extensively; however I also like to edit multiple projects (with separate makefiles.)
So usually to edit more than one project I will do
pushd project1
vim project1.cpp
[suspend signal]
pushd ../project2
vim project2.cpp
and now I can switch between the two projects with ctrl+z i.e. suspend signal, and fg.
When this becomes an issue is when I want to open one project in the context of another so I can do copy/pasting. So if instead in the above I do
pushd project1
vim project1.cpp
:vsp ../project2/project2.cpp
I can edit both concurrently in the same vim process, however I can't effectively build one or the other with the :make command, it will only build project 1.
Does anyone have some kind of scheme that gives them the best of both worlds: being able to edit concurrently while still being able to build multiple projects with the :make command all from the same vim process?

Are the make commands you want to execute the same for each? So the problem is just the current directory? You can use :lcd to change the directory only for the current window, so that it will run in the appropriate directory for each. To make this more automatic, you could set up an autocommand (on BufWinEnter, I think) for when you create that split window to run :lcd expand('%:h'), or just map a key to that if you don't want to always do it.
(You could also map a key/create a custom command for a combination of the lcd and make, probably saving keystrokes but then unnecessarily cd'ing before each make. Not that that takes long.)
P.S. The reason I asked if the make commands were the same is that you can actually set makeprg and other associated options locally (use :setlocal instead of :set).

vim's :make command really just executes the program configured as makeprg in the current directory (make by default).
By starting every vim process inside a project directory, you indirectly set the current directory for that vim session, but of course you can change the current directory inside a running session, e.g. when you started in project1/ you can simple cd to project2/ and build it inside vim with
:cd project2
:make
or like if you only what to change the directory for the current window, do what Jefromi suggests
:lcd project2
:make
There are plugins that say they makes this easier (this one seems to be popular), but I never needed to use them.

Related

Opening a file via Vim on GIT

I'm following a tutorial on Uniswap forking (just to learn how this works) and I'm stuck a particular step.
How does one go from:
vim migrations/2_deploy_contracts.js
to
I'm only able to see:
How do I see the folders and directories ?
The user in that particular video is using the NERDTree plugin for Vim. Vim is very powerful and extensible, and it's possible to load a variety of extensions written in Vimscript to customize the interface, add editor features (such as LSP support), or various other functionality.
They're also using a custom colorscheme which is probably based on the Solarized palette. You can also load a custom colorscheme with the :colorscheme ex command.
There is another thing to notice, besides mentioned NerdTree plugin.
I think you are running your command from the wrong place.
vim migrations/2_deploy_contracts.js
This command tries to open the file set by relative path, or creates a new file, if that does not exist. As we see from your screenshots - the file exists in the tutorial, but it does not exist on your machine (the [+] mark after the filename on the second screenshot shows that).
My guess you need to cd to the right directory first (tutorial project root) and then only run your vim command to open the file.
As for your question about seeing the files and directories, you can do it without NerdTree plugin, using built-in netrw. Just type :Ex in vim normal mode.

Vim script to browse for a directory and retrieve the directory name

I'm attempting to write a plugin to ease my personal workflow. I'd like to be able to configure/reconfigure the plugin to refer to different directories (containing program outputs) - but without changing the vim working directory. In order to do I'd like that whenever I need to point my plugin at a different directory, e.g. by calling the a "reconfigure" function, a convenient interface pops up which allow me to browse through the filesystem and pick the directory using some shortcuts.
My first thought was to use netrw, configured to hide non-directories, but once I'm inside a directory how can I then obtain the current netrw directory path for use in my script? Is there a better way of doing this?
What if I want to pick a file instead of a directory? Is there an easy way to change the Enter key in netrw so that it changes into directories but when the selected item is a file it will call my custom callback function (for example).
Is there a better way of prompting the user for a file directory?
Without knowing the exact background, I would recommend triggering your Vim script via a custom command, and pass the file / directory as a command argument. If you define the command like this:
:command -nargs=1 -complete=file MyCommand call MyFunction(<q-args>)
you'll get Vim's file / directory (cp. :help :command-complete) completion in the command line for free.
There's :browse built-in, but it only works for file-related commands like :edit or :write; you cannot put the value into a variable.
There's inputdialog(), which allows you to query for any string; unfortunately, without (file-) completion.
It would be possible to hook into plugins like netrw, overriding the plugin's mappings for file selection (e.g. :nnoremap <buffer> <CR> ..., but this will entangle your plugin deeply with it.
Summary
Don't forget, Vim is a text editor, so excessive passing of filenames / directories should not be necessary. Depending on your use case, this might be better handled by an external tool (invoked by Vim).
The current netrw directory path is in the variable
b:netrw_curdir
Note that it will track vim's current directory if g:netrw_keepdir is zero.

Best way to view multiple logs at once?

I am currently running zookeeper processes and multiple internal processes and they all print out to their own log files as text. I am pretty green to linux but I was wondering if viewing multiple log file in a single screen without switching between emacs windows or vim windows is an issue for other. What is the best way to view say 3, four or more log files at once? Would it involve the CAT or | commands?
If you are viewing live logs you can use tail with multiple files, or just tail an entire directory using the wildcard operator.
If you are digging though logs you can use Terminator, it is in the Debian repos, to open multiple terminal sessions in one window.
If you are feeling more adventurous your can use tmux to split your terminal window, the great thing about tmux is that is works in textmode, so you can do it over ssh. Here is a pretty decent tmux split pane tutorial http://lukaszwrobel.pl/blog/tmux-tutorial-split-terminal-windows-easily
i like multitail as an optional but nice way to monitor multiple files whithout a lot of hacking around. After installing (e.g. apt-get install multitail) run multitail file1.log file2.log file3.log. the 'f1' key gives you inline help which keys to press.
But, if you want to stay in vim you can use this answer:
One can run this oneliner from ex (whithin vim) when needed (or put each command in vimrc, for when log-files are opened.)
:set autoread | au CursorHold * checktime | call feedkeys("lh")
Explanation:
- autoread: reads the file when changed from the outside (but it doesnt work on its own, there is no internal timer or something like that. It will only read the file when vim does an action, like a command in ex :!
- CursorHold * checktime: when the cursor isn't moved by the user for the time specified in 'updatetime' (which is 4000 miliseconds by default) checktime is executed, which checks for changes from outside the file
- call feedkeys("lh"): the cursor is moved once, right and back left. and then nothing happens (... which means, that CursorHold is triggered, which means we have a loop)
It hit me out of nowhere... I should just import the log folder directory into an empty project in eclipse, then I can swiftly explore and inspect logs and split the screens as needed across multiple monitors. All of Leon's answer is good stuff too, but since I am already using Eclipse heavily I might as well take advantage of that locality.

vim run make through screen

Due to some complicated environmental variables required, I have chosen to run Make through GNU screen. Using the screen vim plugin, I have the following setup in my .vimrc:
map <Leader>mm :call ScreenShellSend("cd ".expand("%:p:h")." && make 2>&1 | tee /path/to/errorfile") <CR>
Roughly translated, this will run make in the current working directory through an existing screen session with all of the required environment variables preset. I can then see the output of that command in a separate terminal window.
My question is, assuming I output the results of make to a text file, how do I tell automate the vim make process to:
A.) set make to use a vimscript function, i.e. call SreenShellSend() instead of an external program.
B.) set errorfile to /path/to/errorfile
Unfortunately, you cannot set 'makeprg' to a Vim function or command, it has to be a shell program. (I wish for an enhancement that treats commands starting with a colon as Vim commands, similar to the :help exception in 'keywordprg', but haven't come around to implementing this.)
There are workarounds, though. One is to use vim --remote-send as 'makeprg' and use this other temporary Vim instance to call back into the original Vim. What I do though is overriding the :make command through the cmdalias.vim plugin for those buffers. That alias then simply :calls my function.
Once you're able to invoke a Vim function, setting the 'errorfile' is just a matter of putting a function wrapper around ScreenShellSend() and setting it in there.

VIM: Overwriting system vimrc

I work on multiple MAC OS X systems, which do not save changes after log out. As you know VIM is on every new mac, just type in vim in the terminal. I always bring my vimrc file with me, and the problem is that every single time I start vim i have to load it with :so command.
I want to use the fact that vim is available on every unix, but I also want to take advantage of the nifty integration with the terminal for doing quick tests, I just switch back to the terminal, but for that I need to close vim. When I reopen it, I again have to load the vimrc. And I am a newb, I don't even have plugins yet...
I want to keep the integration with the terminal and only develop a super quick way of introducing my changes to vim. Think of the conditions as if though you are sitting on newly installed operating system.
Thanks !
Not directly to your question, but you can always invoke vim with -u, which will let you specify your vimrc file instead of launching vim and then running :so.
The default location for your .vimrc file is ~/.vimrc (on the mac, ~ is /Users/_you_, eg /Users/matt). If you can write your file there, it will be loaded when vim starts up every time.
The system vimrc file on the mac is at /usr/share/vim/vimrc, but it sounds like these systems are not under your control, so you won't be able to write that file. Have a look at: How can I override ~/.vim and ~/.vimrc paths (but no others) in vim?, which uses the -u option to change the path vim looks for plugins under. But, in all cases, you must either be able to write your .vimrc into your home directory (which it sounds like your system does not permit) or specify the path to it at runtime (as with the command-line option I mention above, or with the normal command :so which you're currently using).
Depending on the kind of testing you need to do, you can always run shell commands within vim, by using the ! in normal mode. For instance, I frequently make changes to a python file in a buffer, and then (in normal mode) run !nosetests within vim—that writes terminal output into a temporary buffer at the bottom, and doesn't require me to leave or suspend vim. I can review the output, and any key-press takes me back to my buffer.
I don't have any experience with Mac-Os terminal. However I think if you could cp your .vimrc file to your home directory. everytime you start vim, vim will load the .vimrc file from your home directory.
If you want to swtich back to terminal from vim to do some testing/execute some commands and back to vim. you could consider to:
open multiple terminal windows
try something like screen or tmux. personaly I am using tmux, and it's very nice.
try Conque Shell plugin: http://www.vim.org/scripts/script.php?script_id=2771 I have this plugin installed too.
type Ctrl-z in vim to back to terminal
If you want to sync your .vimrc on different machines, you could put your .vimrc file in
a scm repository like gitHub, bitbucket... (I perfer this option, since you could have different branches for different settings)
dropbox
I hope this helps.
How is it possible that your changes are not saved after you log out? What would be the point of such a machine? An internet kiosk in an airport? Do you log as a user without a "home" directory?
If you have a "home" directory, just create a blank ~/.vimrc and put your settings there.
If you don't have a "home" directory but you are able to write somewhere else, create a blank vimrc file where you can, write your settings there and learn this command by heart:
$ vim -u /path/to/your/vimrc
If you don't have a "home" directory and you are really sure that you can't save anything on these machines, put your settings in a file somewhere online, preferably a place under your control, and learn this command by heart:
$ vim -u http://domain.name/yourvimrc
If you are lucky, the command you use will be remembered by your shell for you and it will be easy to issue it again without much typing.
For running your tests, you can either:
Hit <C-z> to suspend Vim. You are back at the prompt from where you started Vim and you can do your thing. Type $ fg to go back to Vim.
Type :sh to launch a new shell from the current directory. To go back to Vim, type $ exit.

Resources