vim conditional keymap when a tex file is open - vim

I am trying to make a keymap that will call latexmk when .tex is available (it would be better if .tex is the currently open and active buffer)
I tried :
:nnoremap <Leader>lw :if filereadable('*.tex')<cr>up!<cr>:!latexmk -pdf<cr>endif<cr>
when trying to make latexmk -pdf run, but unfortunately, its just prompting those line in the window, and doing nothing like:
~
:if filereadable('*.tex')
: up!
: :call Tex_RunLaTeX()
: endif
Press ENTER or type command to continue
kindly help.
(it will be great, as told, if this can be done when .tex is the currently open and active buffer.)
NB: this question and its variant has been asked here several time here eg this and this, hence sorry for the repetation. I have failed to solve my problem with those.

You need to do 3 things:
fix your mapping to run the command properly
create a mapping local to a specific buffer by using the <buffer> option for nnoremap.
load the mappings for just a specific filetype.
First fix the mapping by using executing the command as single ex command by using <bar> and removing :'s & <cr>'s. We also remove the filereadable portion because we just wrote the file.
nnoremap <buffer> :up!<bar>!latexmk -pdf<cr>
or you can use an expressing mapping like FDinoff suggested.
Note the <buffer> option on the mapping. This makes the mapping only available to the current buffer not every buffer.
Now we need to make sure this mapping only works for tex filetypes. This can be done via an autocommand in your .vimrc like so:
autocmd FileType tex nnoremap <buffer> :up!<bar>!latexmk -pdf<cr>
The other way option is by creating a filetype plugin. (see :h ftplugin for more details)
A simple example is do create a file named, ~/.vim/ftplugin/text.vim and place your mappings inside like so:
nnoremap <buffer> :up!<bar>!latexmk -pdf<cr>
I personally lean more towards the ftplugin approach but having a everything in your .vimrc file can be nice.

I feel like this could be done with an autocmd.
The autocmd only loads the mapping when the file is a tex file.
autocmd FileType tex nnoremap <leader>lw :up! \| !latexmk -pdf<CR>
If you want to do this filereadable('*.tex') which just checks to see if a file in the directory is a tex file. You could use the expr mapping from the first link. In the else part of the expression we just put an empty string so the mapping will do nothing.
nnoremap <expr> <leader>lw filereadable('*.txt') ? ':up! \| !latexmk -pdf<CR>' : ''

Related

Why disabling mapping doesn't work in my vim editor?

In my vim editor, I can find two mappings of through following commands:
:imap <CR>
and it outputs:
i <CR> &#<SNR>60_AutoPairsOldCRWrapper73<SNR>60_AutoPairsReturn
i <CR> <CR><Plug>DiscretionaryEnd
I want to disable the first one, so I add it into my .vimrc file:
iunmap <buffer> <CR>
but vim shows error no such mapping error when I open my editor, but actually I can disable the mapping by typing command in editor:
:iunmap <buffer> <CR>
I want to know why I cann't make it work in my .vimrc configuration file.
Plugins are sourced after your vimrc so the mapping you want to disable is not defined when that comand is executed.
That said, the plugin's README tells you how to replace the default mappings. So… read it and experiment.

Vimrc autocmd runs command instead of mapping

I want to add a hotkey to my vim to run my python files, so I have added the following line to my vimrc:
autocmd FileType python map <F5> :w|!python3 %
But on opening the file instead of running autocmd, it runs python with my file.
For me this seems no different from what many tutorials suggest on using autocmd and map, so I'd like to know what exactly is happening here instead of the behavior I expect.
Your :map command ends at the command separator |; the remainder is already executed when the :autocmd runs. You need to escape it (\|), or better use the special <Bar> character:
autocmd FileType python nnoremap <buffer> <F5> :w<Bar>!python3 %<CR>
Cp. :help map_bar. Also, you should use :noremap; it makes the mapping immune to remapping and recursion. And (as #PeterRincker suggested), make the mapping buffer-local, so that it only applies to Python buffers).
Your :autocmd FileType approach is fine for a few mappings, but it doesn't scale well. If you have :filetype plugin on in your ~/.vimrc, you can factor our your mappings into a separate script ~/.vim/ftplugin/python_mappings.vim.

Vim per file mappings

I tried to put the following in my file header:
#!/bin/sh
# vim:set ts=2 sts=2 sw=2 expandtab:
# vim:map <leader>t :w\|:!./script.sh <cr>:
But Vim always complains about the map, saying that it's invalid. I also tried nnoremap with no success. What should I do to fix this (I want it in this file only)?
Modelines are only for options.
If you want this mapping only for that file, add this snippet to your ~/.vimrc:
augroup ThisFile
autocmd!
autocmd BufRead,BufNew /path/to/file nnoremap <buffer> <leader>t :w\|:!./script.sh <cr>:
augroup END
edit
It looks like you want a mapping for executing the current file. If so, you are really chasing the wrong rabbit, here, and also crashing real hard in the XY Problem wall.
You can use % as a synonym for "the file associated with the current buffer" so, assuming your script is executable, this command would execute it:
:w|!./%<CR>
Therefore, you could simply put this generic mapping in your ~/.vimrc:
nnoremap <leader>t :w\|!./%<CR>
Note 1: See :help c_% for the meaning of % and in that context.
Note 2: The bar needs to be escaped when used in a mapping, see :help map_bar.

How to open pdf files under cursor (using 'gf') with external PDF readers in vim

The current gf command will open *.pdf files as ascii text. I want the pdf file opened with external tools (like okular, foxitreader, etc.). I tried to use autocmd to achieve it like this:
au BufReadCmd *.pdf silent !FoxitReader % & "open file under cursor with FoxitReader
au BufEnter *.pdf <Ctrl-O> "since we do not really open the file, go back to the previous buffer
However, the second autocmd failed to work as expected. I could not figure out a way to execute <Ctrl-o> command in a autocmd way.
Could anyone give me a hint on how to <Ctrl-O> in autocmd, or just directly suggest a better way to open pdf files with gf?
Thanks.
That's because what follows an autocmd is an ex command (the ones beginning
with a colon). To simulate the execution of a normal mode command, use the
:normal command. The problem is that you can't pass a <C-O> (and not
<Ctrl-O>) directly to :normal, it will be taken as literal characters (<,
then C, then r) which is not a very meaningful normal command. You have two
options:
1.Insert a literal ^O Character
Use controlvcontrolo to get one:
au BufEnter *.pdf normal! ^O
2.Use :execute to Build Your Command
This way you can get a more readable result with the escaped sequence:
au BufEnter *.pdf exe "normal! \<c-o>"
Anyway, this is not the most appropriate command. <C-O> just jumps to the
previous location in the jump list, so your buffer remains opened. I would do
something like:
au BufEnter *.pdf bdelete
Instead. Still I have another solution for you.
Create another command with a map, say gO. Then use your PDF reader
directly, or a utility like open if you're in MacOS X or Darwin (not sure if
other Unix systems have it, and how it's called). It's just like double clicking
the icon of the file passed as argument, so it will open your default PDF reader
or any other application configured to open any file by default, like images or
so.
:nnoremap gO :!open <cfile><CR>
This <cfile> will be expanded to the file under the cursor. So if you want to
open the file in Vim, use gf. If you want to open it with the default
application, use gO.
If you don't have this command or prefer a PDF-only solution, create a map to
your preferred command:
:nnoremap gO :!FoxitReader <cfile> &<CR>
If the default app is acceptable, then simply using :!open % in command mode works. You can always map this to a suitable leader combination in your vim config file etc.
If you want something that works with normal mode, then you could try something like the following (i use this too for opening HTML files), and modify to your own needs:
if has('win32') || has ('win64')
autocmd FileType html nmap <Leader>g :silent ! start firefox "%"<cr>
elseif has('mac')
autocmd FileType html nmap <Leader>g :!open "%"<cr><cr>
endif

Can you have file type-specific key bindings in Vim?

In my .vimrc file, I have a key binding for commenting out that inserts double slashes (//) at the start of a line:
" the mappings below are for commenting blocks of text
:map <C-G> :s/^/\/\//<Esc><Esc>
:map <C-T> :s/\/\/// <Esc><Esc>
However, when I’m editing Python scripts, I want to change that to a # sign for comments
I have a Python.vim file in my .vim/ftdetect folder that also has settings for tab widths, etc.
What is the code to override the keybindings if possible, so that I have Python use:
" the mappings below are for commenting blocks of text
:map <C-G> :s/^/#/<Esc><Esc>
:map <C-T> :s/#/ <Esc><Esc>
You can use :map <buffer> ... to make a local mapping just for the active buffer. This requires that your Vim was compiled with +localmap.
So you can do something like
autocmd FileType python map <buffer> <C-G> ...
The ftdetect folder is for scripts of filetype detection. Filetype plugins must be inside the ftplugin folder. The filetype must be included in the file name in one of the following three forms:
.../ftplugin/<filetype>.vim
.../ftplugin/<filetype>_foo.vim
.../ftplugin/<filetype>/foo.vim
For instance, you can map comments for the cpp filetype putting the following inside the .../ftplugin/cpp_mine.vim:
:map <buffer> <C-G> :s/^/\/\//<Esc><Esc>
:map <buffer> <C-T> :s/\/\/// <Esc><Esc>
I prefer to have my configuration in a single file so I use the autocmd approach.
augroup pscbindings
autocmd! pscbindings
autocmd Filetype purescript nmap <buffer> <silent> K :Ptype<CR>
autocmd Filetype purescript nmap <buffer> <silent> <leader>pr :Prebuild!<CR>
augroup end
Vim doesn't clear set autocmds when you source your vimrc, so starting vim, changing something in your vimrc and running :so ~/.vimrc would define autocmds twice. That's why the bindings are grouped and cleared with autocmd! group_name. You can read more here.
Since mappings are applied to every buffer by default, and you want to change them for buffers matching the filetype only, the <buffer> modifier is in there, limiting the mappings to the local buffer.
Btw... if your primary problem is about commenting... you should check out 'nerdcommenter' plugin, its the fastest way to comment/uncomment your code in java/c/c++/python/dos_batch_file/etc etc.
This is only a partial answer for people coming here having difficulties getting any ftplugin scripts working, but remember that your .vimrc (or a file that it sources) should contain
filetype plugin on
or
:filetype plugin on
for filetype-plugins to be executed when a file of a given type is loaded.
I recommend the .../ftplugin/<filetype>.vim approach that freitass suggests, but in your specific case Vim Commentary will solve all of this for you.

Resources