How to write simple script in vim? - 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

Related

Prevent Vim warning after autocommand changes file being edited

I run a command every time a save a file which, among other things, lints the current file. Vim does two annoying things which I wanted to avoid:
It asks me to press enter after the command was executed.
It notifies me that the current file has been modified outside of Vim.
How to get rid of this? I just want this to behave unobtrusively as ALE linters. This is my code:
autocmd BufWritePost *.prisma :execute '!npx prisma format'
#romainl's comment gave me an idea on how to do it:
autocmd BufWritePre *.prisma silent write | silent :execute '!npx prisma format' | edit! %
It's not the cleanest way to do it but it works. silent hides the command output and edit! forces Vim to open the modified file.

Define vim command to open current filename with another extension

I'm trying a simple way to compile pdfs in LaTeX and open them with zathura from a single autocmd inside vim, so far I tried:
command Latex !pdflatex %:t
command Za !zathura #%.pdf
autocmd FileType tex map <leader>pdf :w<CR>:Latex<CR>:Za <CR>
Obviously, #%.pdf is wrong, but I've had no luck in finding how to append an extension to the file name. I'm newbie in vim scripting so please point out any other errors.
Since no one bother to answer, I came up with a shell solution for it, a script called zatex:
tex=".tex"
pdf=".pdf"
cd $1;
texfile="$2$tex";
pdflatex $texfile;
pdffile="$2$pdf";
setsid zathura $pdffile;
And inside my .vimrc:
command Zatex !zatex %:p:h %:p:h:t
autocmd FileType tex map <leader>pdf :w<CR>:Zatex<CR>
Of course, after the first compiling it might be handy to have another mapping just to compile the pdf, since zathura is already open:
command Latex !pdflatex %:t
autocmd FileType tex map <leader>tex :w<CR>:Latex<CR>
I believe %:r is what you are looking for, without the # character. It will return the file name, without extension.
Also, have a look at this question.
EDIT: I just tested here (not with !zathura, but with !echo) and the following line should work for you (just append the correct extension after the file name expand):
command Za !zathura %:r.pdf

Run command from within vi / vim

As part of learning Haskell, for fun I'm attempting to use Raspberry PI. Having encountered a myriad of issues installing ghci on the PI I've resolved to using just ghc.
So to create, compile & run a new Haskell file :
vi first.hs
i
main = putStrLn "First"
Esc
:w
:q
ghc -o first first.hs
./first
Output is : "First"
I would like to automate the commands :
Esc
:w
:q
ghc -o first first.hs
./first
Can these be added as new command from within vi / vim, something like :
:mycustomcommands
And run from within the vi / vim editor ?
Maybe you could try adding something like this to your vimrc:
function! ExecuteHS()
w
!ghc -o first %
!./first
endfunction
And to use this function you just have to call it like that :call ExecuteHS(). Vim will be put on background during the execution of your file and will then come back on foreground at the end of the execution.
As a bonus you can add the folowing line to your vimrc
nnoremap <key> :call ExecuteHS()<CR>
Replacing <key> with your prefered key combination <Leader>e for example. This way you'll simply have to hit ,e (if you didn't changed your leader key) in normal mode to call the function.
That's probably not the cleanest way to do it but it should work for what you want.
Absolutely in vim, though not necessarily in other vi flavors. See this tutorial on defining custom commands. Put the custom command in your vimrc and it will always be available as :Customcmd or whatever you call it. For one-button access, you can use :remap to assign a hotkey to your custom command or the sequence of built-in commands you want to run. This is a tutorial on keymappings that will give you more information.
I second #statox's referral to https://vi.stackexchange.com :)
I use vim-haskell, which includes a couple nice things. In particular, it includes a file for setting up cabal-install as the compiler, which is a very nice way of working. Dump this in ~/.vim/compiler/cabal-build.vim:
CompilerSet makeprg=cabal\ build
CompilerSet errorformat=
\%W%f:%l:%c:\ Warning:%m,
\%W%f:%l:%c:\ Warning:,
\%E%f:%l:%c:%m,
\%E%f:%l:%c:,
\%C\ \ %#%m,
\%-G%.%#,
\%-G%.%#
And this in ~/.vim/ftplugin/haskell.vim:
compiler cabal-build
(The argument to compiler should match the name of the file you put in ~/.vim/compiler.) Then you can run :make in vim and it will save any changed buffers (assuming autowrite is set) and build your project. When there are errors, it will populate the quick-fix list, which lets you jump to the specific file and line numbers of each error or warning with a key. Read more about this feature with :help quickfix. Once everything is working, you can :!cabal run to run it.

Source more than one file with a keybind command in Vim

Here's my bind:
nnoremap <Leader>L :so $MYVIMRC<CR>:so ~/.vim/after/plugin/*.vim<CR>
It worked great right up until I added a second configuration file in the plugin folder. Now I get E77: too many file names from the :so[urce] command.
I found this which doesn't really make it obvious how to do it from an command string like in a keybind.
How do I write a loop in a keybind? Must a function be declared?
P.S. the reason I even have any scripts in .vim/after/plugin/ is because there are certain config commands for certain plugins that must be run after their initializations are run, and plugin load scripts run after vimrc. (so they cant just go in the vimrc).
:source takes only one argument but you can use the :runtime command:
runtime! after/plugin/*.vim
which is almost exactly the second example given under :help :runtime.
You can also chain the commands together, and it's not as nice as romainl's answer but you can break out into terminal and run source there.
nnoremap <Leader>L :so $MYVIMRC|:!source `find ~/.vim/after/plugin/ -name "*.vim"`<CR>

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

Resources