I recently dumped all ide's and decided to program solely with vim. So far it works good, but I have a minor annoyance. Everytime I want to run my recently compiled program, I have to write
:!./myProgramExecutable
I could do this in my .vimrc:
nmap <key> :!./myProgramExecutable<CR>
but that would only work for executables of that name. Is there a way to generalize this command for my current project in CMakeLists.txt for example? (or another way to find the correct name)
If the program name can be derived from the current buffer's path and/or name, you can use :help filename-modifiers in the command execution.
However, if it's okay for you to specify the program name once, a neat trick is that :!! repeats the last :! command with the same arguments. If you bind that to a key, you have a quick way to re-execute it.
Oh, and if you're working with Makefiles or similar, why not create a target (always with the same name) that executes the program; you can then do that from Vim via :make run, for instance.
Related
Is it possible to redirect an output of a command to the quick fix window?
The command I am running is
:!java %:r
and was hoping the output would go into the quickfix window
I would suggest one of two options: configure makeprg to run java like you want, or create a mapping or command to populate the quickfix list without changing anything else.
Option 1: Using makeprg and compiler plugins
I would generally set the makeprg option for this, as others have said. It's not a hack, that's exactly what the makeprg option is for.
The only problem is if you have another build script you want to run as well. A more general solution is to create a simple compiler plugin. For instance, somewhere on your runtimepath, you can create a file under compiler/java.vim and set it to something like this:
if exists("current_compiler")
finish
endif
let current_compiler = "java"
CompilerSet makeprg=java
Now when you're working with java, you can do :compiler java and then your makeprg will be set as desired in the current window. If you want to use it for all windows, use :compiler! java, with a bang. Not all compiler plugins set the makeprg option, but you can always reset it with :set makeprg&. Try :help write-compiler-plugin for more information.
Option 2: Create a command to do it
Alternatively, you can also use cexpr to populate the quickfix list. For instance:
:cexpr system('java ' . shellescape(expand('%:r')))
The expand is necessary to expand the '%:r' in an expression, and shellescape escapes it so it can be used as an argument to a shell command. Then the string 'java ' is prepended to the escaped path and the result is invoked as a shell command by system. The output from this command is used to load the quickfix list.
The nice thing about this is that it doesn't change makeprg or any other settings, but still lets you easily populate the quickfix list. Of course, you'll probably want to map this or define a custom command for it.
Please note that the quickfix window is for specific output (e.g. of compiler or syntax checker tools) which includes references (i.e. line and column numbers) to the current buffer. There's a lot of infrastructure around this: 'makeprg', 'errorformat', etc., usually bundled into a compiler plugin.
Though you can redirect arbitrary output into the quickfix window, it provides little benefit (and has the downside of clobbering 'makeprg') over reading the output of an external program into a new scratch buffer, e.g. like this:
:new|0read !java #:r
Try this:
set makeprg=java
make %:r
It's a bit of hack, and of course assumes you aren't already using makeprg for your actual build script.
I mapped leader + j + r to run my java code and display it in the quickfix window by doing
map <leader>jr :set makeprg=java <CR>:make %:r<CR>:copen<CR>
When coding, I like to check the code by running :! g++ %. I map the command to <F5>. sometimes it takes a while to compile and I want to see the errors without spending time recompiling. Also, sometimes I want to compare the new output to previous one.
Is there a way to see the previous output of :! ...?
Provided you have g++ configured with makeprg, you can use :copen to reopen the last list of errors from the :make command.
set makeprg=g++\ %
Then, to compile, use
:make
When the compile completes, any errors will be listed in the quickfix window, which can (assuming errorformat is correctly configured) be used to jump to the lines on which errors occur. This usually works out of the box for C/C++.
If you dismiss the quickfix window, retrieve the last error list with
:copen
Review :help quickfix and :help makeprg for full gory details on how this works.
If you are using Vim from the terminal just suspend vim with Ctrl+z.
This will send you back to your terminal. You should see the commands that you just ran via :!. To get back to vim issue the fg. Note: This maybe different depending upon your shell.
:sh starts you a shell within Vim. If you're using Vim in a terminal, this switches back to what's known as the "primary buffer", which means that you see the history from the terminal before you started Vim, as well as any of the :! commands you ran in Vim.
You can get back to your Vim session with Ctrl-d.
Michael gave you the right answer: :makeis the way to go. The old :!compilation-command is to be forgotten. Vi is, well, ... history.
Now to clarify : you'd almost never have to tweak &makeprg. The default value is the one you want to use, unless:
you're using something else to compile (ant, ...)
you want to compile a mono file program, and you don't want write a Makefile, and you're under mingw whose gnumake installation s*cks (all other installations of gnumake do permit to transform foo.c/cpp into foo(.exe) without having to write any single Makefile)
you want to play with the compilation directory, or with things that can't be injected through $CXXFLAGS, $LDFLAGS, $CFLAGS, etc.
R, Python, Scala etc. all come with REPL-environments, which I don't want to miss, however, most of the time editing text in them sucks, so I edit the code in vim, paste it and look at the output and edit the code in vim again.
I can run the current file with !python % and I can run the current line with even more vim magic, however, this will start a new process of the interpreter.
Is it possible to start a REPL and send lines of code to the running REPL (and get the results back, obviously)?
Maybe one of these two plugins is what you need:
slime is screen-based.
tslime is a tmux-based version of slime.
Try Conque:
"""
Conque is a Vim plugin which allows you to run interactive programs, such as bash on linux or powershell.exe on Windows, inside a Vim buffer.
"""
It can easily be configured to open a Python interpreter, and a key mapping can be used to transfer the current line to it to be executed (F9 for the current line, F10 for the current file etc.).
Not for plain-python alone, but if you're using IPython 0.11 or later, take a look at vim-ipython.
Using this plugin, you can send lines or whole files for IPython to execute, and also get back object introspection and word completions in Vim, like what you get with: object?<enter> and object.<tab> in IPython. Additionally, vim-ipython has a "shell" mode, where as you send lines to IPython, you get to see the results those lines produced back in the specialize buffer. See the second screencast on this post
I recently wrote a plugin for a very similar purpose: vim-notebook which allows the user to keep a background process alive and to make it evaluate part of the current document (and to write the output in the document). It is intended to be used on notebook-style documents containing pieces of code to be evaluated.
Maybe you can try my plugin vim-repl. It provides a convince repl environment for vim using the vim8 terminal feature.
here is the github homepage: https://github.com/sillybun/vim-repl.
To open the repl environment, just run :REPLToggle or you can even bind it witk key like:
nnoremap <leader>r :REPLToggle<Cr>
To interact with repl, you just select the code and press <leader>w. And the code will be transmitted to the repl environment.
Look into the github homepage for more details, it will worth your time.
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.
I have a one key mapping to build my project.
noremap <F5> :make<CR>
This works great. However I sometimes am building a only a piece of the project. In this case I use the command :make smaller_part to build just that piece. I'd also like a one key mapping for this use case as well.
noremap <S-F5> :make last_arguments()<CR>
Is this possible? A last_arguments() function isn't required. It's just how I imagine the solution would look. The important part is I hit one key and it runs :make with the arguments that I gave it last time.
I use
map <f2> :wa<cr>:Make <Up>
to run make with the last arguments
by the way
command -nargs=* Make write | make <args> | cwindow 6
is the Make.
I don't know whether you can programmatically retrieve the last line from the command history, or specific arguments on it. I expect you can, but I don't know how to do it offhand.
But what are the constraints here? If you'll allow your initial invocation of make to call a function you've defined, say :MyMake(smaller_part), then that can save the smaller_part in a variable and you can define a Remake() function that will call make on the target saved in that variable.
Is that solution acceptable to you? Or must the original invocation be of the form :make smaller_part?
What if you wrap the :make command in a couple commands of your own? One command runs make with whatever argument you supplied (possibly none). It also stores the argument in a variable. Then you map this command to <F5>. The other command runs make with the argument stored in your variable (again, if any). You map this command to <S-F5>. I think the vim command for defining your own commands like this is Command.