I’ve been using the following script in my vimrc file for compiling and running C programs;
autocmd filetype c nnoremap <F8> :w <bar> exec '!gcc '.shellescape('%').' -o '.shellescape('%:r').' && .\'.shellescape('%:r')<CR>
The issue is, if the program has an input function, when I run it, it doesn’t ask for inputs, it simply finishes and it shows
Press ENTER to continue
Note: This is on Windows 10—I know, but it’s my only option at the moment.
So if I'm seeing it right, your keybinding executes the line immediately, after pressing <F8> due to the <CR> at the end of the line which represents your enter-key.
So you can remove it and use that:
autocmd filetype c nnoremap <F8> :w <bar> exec '!gcc '.shellescape('%').' -o '.shellescape('%:r').' && .\'.shellescape('%:r')
Everytime when you press <F8> you should be prompted in the commandline and enter your arguments just as you'd do in the commandline.
Related
There's some clunky behavior I'd like to resolve:
In vim I can use :terminal to bring up a shell window. But if I type something into it, I can't edit it like a normal shell: I'm stuck either in a useless normal mode, or I'm in an insert mode where I can only write new letters or delete them at the end of the line. I can't move the cursor to the middle and change, say,
cd ~/Picturs/MyLovelyHusbandAndChildren2017/VacationPhotos/Aruba
into
cd ~/Pictures/MyLovelyHusbandAndChildren2017/VacationPhotos/Aruba
without simply deleting everything from ~/Pictur to the end and rewriting it. Is there any way at all around this or is it a basic limitation of how vim works? This is frustrating to me because I'd like to use ghci in the shell window but this makes it much less responsive.
There are some specific configs you can do both on vim or neovim to tacle this issue, in my case, neovim, I have these lines on my init file:
augroup neovim_terminal
autocmd!
" Enter Terminal-mode (insert) automatically
autocmd TermOpen * startinsert
" Disables number lines on terminal buffers
autocmd TermOpen * :set nonumber norelativenumber
" allows you to use Ctrl-c on terminal window
autocmd TermOpen * nnoremap <buffer> <C-c> i<C-c>
augroup END
Note the autocmd TermOpen * startinsert, that line makes sure, as soon as I enter a new terminal on neovim it will be in inert mode.
I am new to vim and I'm using it to type up my latex documents. I work on Windows, and have defined this map in my vimrc file:
autocmd FileType tex inoremap ,lc <Esc>:w! \| !latexmk -pdf -pv %<CR>
When latexmk is ran, it opens up a cmd window and then the PDF viewer window. However, it doesn't close the cmd window, which I then have to close by pressing any key. Is there any way to define my map such that it closes the command line and opens up my PDF? I thought something like
autocmd FileType tex inoremap ,lc <Esc>:w! \| !latexmk -pdf %<CR> \| !latexmk -pv %<CR>
could work, but turns out it doesn't.
You can try:
autocmd FileType tex inoremap ,lc <Esc>:w! \| !latexmk -pdf -pv %<CR> \| call feedkeys(' ')<CR>
The feedkeys() simulates the press of the given key(s), in occurence the space key, which should close the command message for you.
Additional advices
As you are new to Vim, you may be interested by some additional advices I want to share to improve your above code:
You can add the <buffer> argument to your mapping:
autocmd FileType tex inoremap <buffer> ,lc ...
It will map your shortkey only for latex buffers. Without it, once a latex file is loaded, every buffer and window will interpret your mapping, which is not what you want I guess.
You can create a dedicated function in order to perform the job you want: it will improve readability and make it easier to modify. Indeed, your autocommand line is becoming quite long to read, and it might be still longer if you wanted to add more features.
So you could transform your code into something like this:
autocmd FileType tex inoremap <buffer> ,lc <Esc>:call MakeLatex()<CR>
function MakeLatex()
w!
!latexmk -pdf -pv %
call feedkeys(' ')
endf
Depending of what exact behaviour you want for your mapping, you could replace <esc> by <c-o> in your mapping.
This way, you can stay in Insert mode after having typed your shortcut:
autocmd FileType tex inoremap <buffer> ,lc <C-O>:call MakeLatex()<CR>
The last thing to improve (imho) would be to put all of this into a separate ftplugin file. This way you can separate features that you only want for Latex files, and make it easier to add even more filetype-based features.
In order to do this, go to your vim home directory (it should be something like ~/.vim or ~/vimfiles on Windows) and create the file <YOUR_VIM_DIR>/ftplugin/tex.vim; this file will be loaded each time you will want to edit a latex file, without the need of any autocmd FileType tex. Then put the following code into this file:
inoremap <buffer> ,lc <c-o>:MakeLatex<cr>
command! -buffer MakeLatex call s:make_latex()
function s:make_latex()
w!
!latexmk -pdf -pv %
call feedkeys(' ')
endf
It is a slightly improved version compared to the above one, because now, everything is local to the buffer or to the script. In the previous version, the MakeLatex() function scope was global to Vim, while it was not needed outside of Latex files. With this version, s:make_latex() is local to the script, and the MakeLatex command is local to the buffer, so the scope of commands/functions is really limited to Latex files only.
Hope this can be useful, happy vimming;
I have configured <F5> to use the Windows start command, but trying to use the command line option "/wait" confuses VIM so that the command is not found anymore.
Here my old mapping:
noremap <F5> :w<CR>:!start "%:p"<CR>
I changed the mapping to:
nnoremap <F5> :w<CR>:!start /wait "%:p"<CR>
Using the later cause the following error:
E371: command not found
But why "command not found", the command is still "start", isn't it?
Thanks in advance!
Vim implement :!start command it-self since Vim must handle background command correctly. And it doesn't have /wait option. See :help :!start.
Using "start" stops Vim switching to another screen, opening a new console,
or waiting for the program to complete; it indicates that you are running a
program that does not affect the files you are editing. Programs begun
with :!start do not get passed Vim's open file handles, which means they do
not have to be closed before Vim.
To avoid this special treatment, use ":! start".
:nnoremap <F5> :w<CR>:! start /wait %:p<CR>
FYI: original start command doesn't require double-quote for argument.
I'm somewhat new to VIM and am playing with ways to open files (OS X).
Upon returning to VIM after temporarily exiting into shell (ctrl+z, followed by fg), I think it would be convenient if VIM set its current working directory to wherever I was when I returned.
Is this possible? I do know how to change the working directory manually from within VIM.
thank you,
Check if your version of Vim has support for client-server functionality: :echo has('clientserver')
If so, you can write an alias to tell Vim to change its cwd:
In your .bashrc:
alias fg="$VIM --remote-send ':cd $PWD<CR>'; fg"
Where $VIM is vim or gvim or macvim.
You need the colon and the <CR> because you're sending Vim keystrokes rather than commands (<CR> is a special notation for "Enter")
I'm not sure whether --remote-send works when Vim is suspended - this approach might be better if you use something like screen or tmux to run vim and your shell at the same time.
Otherwise, it's a bit trickier.
There's a :shell command that is similar to suspending and resuming, but I'm assuming it forks a child process instead of returning you to Vim's parent process. If you're ok with that, there's a ShellCmdPost autocmd you can attach to to load information. You can use that in association with an alias that writes the $CWD to a file to load the required directory and change to it.
In your .bashrc:
alias fgv="echo $PWD > ~/.cwd; exit"
In your .vimrc:
autocmd ShellCmdPost * call LoadCWD()
function! LoadCWD()
let lines = readfile('~/.cwd')
if len(lines) > 0
let cwd = lines[0]
execute 'cd' cwd
endif
endfunction
Looking through the list of autocommands, I was not able to find any that detect when Vim has been suspended and has just been resumed. You could remap ctrl-z to first set a flag variable then do an unmapped ctrl-z. Then write a shell script like before that writes its $CWD to a specific file. Then you can set up an autocmd to watch that file for modification and in the handler, check the flag variable, and if it's set, reset it, read the file, and change to that directory. A bit complex, but it would work.
That would look like this. You'll have to load the file when you start Vim so that it can monitor it for changes. You may want to set hidden so that you can keep the buffer open but hide it.
In your .bashrc:
alias fg="echo $PWD > ~/.cwd; fg"
In your .vimrc:
set hidden
edit ~/.cwd
enew
nnoremap <C-Z> :let g:load_cwd = 1<CR><C-Z>
autocmd FileChangedShell ~/.cwd call LoadCWD()
function! LoadCWD()
if g:load_cwd
let g:load_cwd = 0
let lines = readfile('~/.cwd')
if len(lines) > 0
let cwd = lines[0]
execute 'cd' cwd
endif
endif
endfunction
I need to write lot of code and compile very often. I hate switching back and forth various windows just to compile the code. Is it possible to open a small window at bottom and run invoke shell and close that window when needed?
With GVim or MacVim, you can run external commands in the command-line: Gvim/MacVim comes with a (very) limited shell that will happily show you whatever the compiler outputs. The general usage pattern is:
:!command
:!command %
With CLI Vim, the same method will pause Vim and return to the shell to execute your command.
In both cases, you'll get a message asking you to press ENTER to come back to your normal editing.
Using :make | cw would be a slightly more sophisticated alternative, with the added bonus of showing the errors in the quickfix window.
An even more sophisticated approach would be to use Tim Pope's Dispatch plugin in combination with tmux or screen.
Sounds like a problem for Screen
http://www.gnu.org/software/screen/
Quick reference of commands
http://aperiodic.net/screen/quick_reference
I use tmux to achieve something like that. I have the following in my ~/.tmux.conf file:
bind s splitw -v -p 25 -c '#{pane_current_path}' '/bin/bash'
bind q kill-pane
On pressing Ctrl-b + s (prefix + s), a new pane containing a bash shell opens up at the bottom. I can run shell commands from there: find, grep, make, etc. When I'm done, I press Ctrl-b + q to close the shell.
To enable tmux on every bash session, add the following to your ~/.bashrc:
[[ -z "$TMUX" ]] && exec tmux
Maybe map a key to shell out to the compiler and run the program if compilation is successful:
:map F8 :!cc % && ./a.out
Or maybe just
:sh
make run
Ctrl-D
Another option is to suspend vi, using Ctrl-Z and do your stuff in the shell, then type fg to bring vim back to the foreground. Note that this is actually a feature of your shell, rather than vim but it produces the effect you seek.
Note this idea originates from the book "Efficient Linux at the Command Line" by Daniel Barrett. I forget the page number.