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;
Related
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.
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'm trying to learn VIM editor , and I'm going to test some small code
for ruby
here is question..
When I compile and launch my small ruby code,
Command-mode,
:!ruby %
Or Open another terminal,
$ruby filename.rb
I did ,
but.. its really stressful and I cannot focus....
Is there any magical things?? ,
config .vimrc file then make a hot-key
or... make some script by rubyself...??
You can use :!! to repeat the last :!{cmd}.
You can type :!ruby % once, and then run :!!, which can of course be mapped to a key like:
nnoremap <F8> :!!<CR>
Or to write and run it (saves typing :w):
nnoremap <F8> :w<CR>:!!<CR>
This is a flexible solution, since you can replace :!ruby % with anything else (e.g. :!coffee -c %, :!python %, etc.).
If your vim distribution has ruby support, can be confirmed using vim --version |grep ruby, Then
nnoremap <F9> :rubyfile %<CR>
This is will be more faster as this does not invoke an external command using !ruby and hence no shell launch. More details at :help ruby.
Another way to complete the work irrespective of ruby support.
Your vim distribution will come with $VIMRUNTIME/compiler/ruby.vim for compiler setting. If so, you can set it :compiler ruby for ruby files in your vimrc.
This will allow you to just do make to accomplish what you are doing. But output looks somewhat clumsy.
Hence, Having a some keybinding will help
nnoremap <f9> :make<CR> :copen<CR>
This will open a quickfix for error. You can just press F9 or any other key that you have mapped.
You might also like to review quickfix commands at :help quickfix
You can try doing this to your .vimrc. It's not exactly sophisticated, but may be good enough for your needs:
" Run current file as Ruby program
nnoremap <C-r> :!ruby %<CR>
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 found an awesome tip here. You can "[r]apidly invoke an editor to write a long, complex, or tricky command". However, when I press the key combination above, I get Emacs open. I would like to switch it to Vim. How can I invoke Vim with C-X e?
[1. Problem SOLVED by Brian Cambell]
export EDITOR=vim
Add to your .bashrc or appropriate shell rc file
[2. Problem SOLVED thanks to Pax]
I was unable to get the tricky command back to Bash. The errors were:
> Error detected while processing BufRead Auto commands for "*":
> E117: Unknown function: JumpToLastPosition
Quotes in .vimrc solved the second problem. I am still unsure about the part in my .vimrc:
" augroup misc
" autocmd!
" autocmd BufReadPost * call JumpToLastPosition()
" autocmd FileChangedShell * call WarningMsg("File changed outside of vim")
" augroup end
[3. Problem]
What do the above part in .vimrc do?
On most Linux installs (all the ones I tested), bash recognizes both the Emacs and Vi command history keys (or you can use "set -o vi" to force it).
So, you can just use the vi-mode "<ESC>v" to to enter visual mode, this will start editing in a Vim session.
To run the command, you just save and exit from Vim ("ZZ" or ":wq"). To cancel the command, you need to delete the contents, save and exit ("1GdGZZ").
In addition to running it by exiting, you can also save it while in the editor to another location (":w /tmp/myscript").
Keep in mind that visual mode will work with the currently selected line so you don't have to start with a blank command ("<ESC>v"). You can use the normal vi-mode tools to select a line from the history first and then enter visual mode ("<ESC>kv" for last command, "<ESC>/grep<ENTER>nnv" for third-last grep command and so on).
Using this method has the advantage of not changing the "EDITOR" variable which may be used for other things (unless you want Vim for everything, which is a very sensible position to take IMNSHO).
Update:
Regarding your error, posted after the question:
JumpToLastPosition() is the function called by Vim for all files to put the cursor where it was when you last edited the file. I'm going to assume you're actually getting this error when the editing starts, not when you exit, since this is the auto function following a buffer read.
Can you start a "normal" vim session ("vim xx.txt" and then "vim xx") without this error occurring? You may find you get the same problem (and possibly only on the last one).
If you do have the same problem, you need to look at your startup files. It's possible the autocmd for BufRead is broken somehow. Have a look inside your vimrc and you filetype.vim files to see where that function is called and/or defined (I suspect it's called but not defined and that may be a mismatch between the two files or one of them has been damaged).
export EDITOR=vim
Add to your .bashrc or appropriate shell rc file
The link that you provided contains the answer:
Next time you are using your shell, try typing ctrl-x e (that is holding control key press x and then e). The shell will take what you've written on the command line thus far and paste it into the editor specified by $EDITOR.
You need to set the EDITOR environment variable (like #Brian Campbell)