vi, condition in vimrc - vim

I am trying to personalize my ~/.vimrc file.
Here is what I want: when the file name opened with vi is titi45.tex, and when I press <space> in normal mode, I want that the command make toto45
is executed. And if the file opened with vi is called titi65.tex, I want that
make toto65 is executed, and so on.
I tried to use a command
au FileType tex nmap <space> :w<CR>:!make<CR><CR>
in my .vimrc but I don't know how to match the file name and use the number.
Can you help me?
Mathieu

You are looking for :make %<. BTW why don't you compile within vim? Avoid :!make. Prefer :make, and check the help related to the quickfix mode (:h quickfix).
Your mapping would then be:
nnoremap <buffer> <silent> <space> :update<cr>:make %<<cr>
(the <buffer> part is very important, it makes sure your mapping won't leak to other filetypes; the other are not critical here, but good practices)
EDIT: Sorry I missed the exact requirement.
Then, you'll have to transform the target name. You'll to play with substitute() and :exe. But your substitution won't be a simple substitution. It looks like a rotating substitution. Solutions for this kind of substitution have been described over there: How do I substitute from a list of strings in VIM?
And IIIRC, there exist a plugin that does similar things.
In your case, I guess I would use a dictionary to define how names are substituted:
let k_subs = { 'toto': 'titi', 'titi': 'toto' }
nnoremap <buffer> <silent> <space> :update<cr>:exe 'make '.substitute(expand('%'), join(keys(k_subs), '\|'), '\=k_subs[submatch(0)]', '')cr>
NB: I haven't tested it.
If you want to get rid of the extension, it'd better be done in expand() argument.

Hum...
finally i use an additionnal script
#!/bin/bash
maRegex='source_(enonce|corrige)([0-9]+)$'
if [[ "${1}" =~ $maRegex ]]
then
commande="make enonce${BASH_REMATCH[2]}"
else
commande="make plouf"
fi
echo commande de compilation lancée: $commande
$commande
This script in launched by vimrc.

Related

vim keymap base on working directory

I use ack.vim, and have below keymap in my .vimrc,
nnoremap ;f :Ack! ^\"
to search for tags in my note files, which are lines that begin with double quote followed by non-space characters.
which works fine, since my note files lies in a common directory, say ~/notes.
Now, say at a git repo, eg, ~/code/some_repo, I want below keymap at that directory,
nnoremap ;f :Ack! ^\/\/\ *\"
I could manually set the keymap if work at given directory, but it soon become tedious.
So I wonder, how can I set keymap base on working directory when I start vim.
-- hopefully vimscript solution, with possible aid of bash command.
Have a look at https://stackoverflow.com/a/456889/15934
The solutions exposed can solve your question. Either by defining buffer specific mappings (:h :map-<buffer>, or by defining buffer variables that you could use in your mappings (:h b:var).
As #Luc suggested, I could use autocmd base on file name with BufEnter and BufCreate. Which works fine.
Then I ask myself, why stick to command only??
Just utilize vim builtin functions and simple vimscript statement!!
So, let's break my requirement to different parts.
get current working directory. -- getcwd().
pattern match on that. -- =~. What does =~ mean in VimScript?
do keymap base on match or not.
below is what's in my vimrc then,
"git, see also " grep
if getcwd() =~ "/code/repoA/"
nnoremap ;f :Ack! ^\/\/\ *\"
nnoremap ,a :!cd %:p:h && git add %<CR>
else
nnoremap ;f :Ack! ^\"
endif

VIM check for search pattern match in vim script

I just started with vim script and try make translation of opencart language files easier. I want to have a function that looks for a given search pattern and selects it. If there is no match left in the file, it shall open the next file for editing. What I have so far:
function! Nextmatch()
normal /\(= *'\)\#<=.\{-\}\('\)\#=/
normal v//e
endfunction
function! Nextfile()
if !exists("s:filecounter")
execute "!find -iname *.php > files.txt"
normal <CR>
let s:filecounter=0
endif
let s:lines= system("wc -l < files.txt")
if s:filecounter<s:lines
w
let s:filecounter += 1
let s:sedcommand="sed '".s:filecounter."!d' files.txt"
let s:selectedfile=system(s:sedcommand)
execute 'edit' s:selectedfile
else
wq
endif
endfunction
How can I achieve that Nextfile() is called in Nextmatch() if the search pattern is not found between the cursor and the end of the current file? And is there something that you consider to be bad style in my snippet?
Quickfix commands are powerful and well integrated with some external plugins, but if you really need to use your own script, and if you need to check a match in an if statement, just do:
if search("=\\s*'\\zs[^']*\\ze", 'W') == 0
echo 'No match until the end of the buffer'
endif
See :h search(), and please note :
the double backslashes, due to the double quotes
the 'W' flag which forbids wrapping around the end of file
I simplified the pattern you gave
You could simply use the :vim command to get rid of all your script.
I think the following should do quite what you're expecting:
:noremap <f8> <esc>:cn<cr>gn
/\(= *'\)\#<=.\{-\}\('\)\#=
:vim //g *.php
Then, to go to the next pattern in all files while selecting it,
you just have to press the F8 key.
In the noremap line, gn let you select the next actual search.
You may need to do:
:set nohidden
to let you navigate threw modified buffers (but don't forget to save
them with :wa, or list them with :ls)
About your script:
It's a good habit in scripts to always use :normal! instead of :normal (unless you deliberately need it) : thus, your personnal mappings won't interfer in your scripts.

vim conditional keymap when a tex file is open

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>' : ''

I want to update the file (if necessary) and run the system command on current file

I realize that I can :nmap <leader>rc :!cat %<CR> to provide an easy set of triggers, but I would like to do this instead.
nmap <leader>rc :up :!cat %<CR> but it complains about needing only one filename. How do I get vim to recognize both commands, in series?
You are missing a <CR> after :up. <CR> tells vim you want a carriage return here.
nmap <leader>rc :up<CR> :!cat %<CR>
The reason up is complaining about multiple file names is that it sees :!cat and %<CR> as two arguments to up.
So the new macro executes
:up
:!cat %
instead of
:up :!cat %
(Side Note: you should probably use nnoremap instead of nmap)
ZyX recommends using the following mapping instead.
nnoremap ,rc :up\|execute "!cat" shellescape(#%, 1)<CR>
This uses | to separate commands and escapes the %. Escaping the % leads to a more robust mapping just incase the filename contains special characters.
Help for :h execute and :h shellescape

How to write simple script in vim?

Here I got simple task for skilled vimmers. I need to reformat my css file. There are commands to do this:
%s/}/&\r/g
%s/ / /g
retab!
echo "You done did it!"
But I don't want to type these commands every time I need to format my css file (I get it after convert less file by WinLess program). Now I put these commands into cssformat.vim file, and put this file into vim runtime folder. In my vimrc I set:
autocmd Filetype css nmap :so $VIM/vim73/cssformat.vim
It's works, of course. But I wonder how can I do this task better? In the begginig I want to put these commands in my vimrc (to create a simple function), but I don't know how to do this correctly.
p.s. Sorry for my bad English.
Just put the commands from your script into a function:
function! ReformatCss()
" Place your commands here.
endfunction
And move the stuff into your .vimrc. Now you can invoke this via :call ReformatCss().
To top it off and make it even simpler, define your own command:
command! ReformatCss call ReformatCss()
Now you can invoke via :ReformatCss. Voila!
You can learn more at :help usr_40.txt and :help :command. For example, if you only need this for CSS files, you can turn this into a buffer-local command through command -buffer and moving the function and command definition to ~/.vim/ftplugin/css_reformat.vim

Resources