Autocmd bufnewfile causing "Trailing characters" error on relative paths - vim

I am having issue with my .vimrc file. I have completed an autocommand for all python and sh files. I have included both below. All works as expected when using a direct path ie:
gvim test.py
If I use a path relative to the cwd, however, such as:
gvim ../test.py
I receive the following error:
Error detected while processing BufNewFile Auto commands for "*.{py,sh}"
E488: Trailing characters
Any ideas on how to fix this problem?
autocmd bufnewfile *.{py,sh}
\ let path = expand("~/bin/Templates/")|
\ let extension = expand("%:e")|
\ let template = path . extension|
\ let name = "John Doe" |
\ if filereadable(template)|
\ execute "silent! 0r" . template|
\ execute "1," . 10 . "g/# File Name:.*/s//# File Name: " .expand("%")|
\ execute "1," . 10 . "g/# Creation Date:.*/s//# Creation Date: " .strftime("%b-%d-%Y")|
\ execute "1," . 10 . "g/Created By:.*/s//Created By: " . name|
\ execute "normal Gdd/CURSOR\<CR>dw"|
\ endif|
\ startinsert!
autocmd bufwritepre,filewritepre *.{py,sh}
\ execute "normal ma"|
\ execute "1," . 10 . "g/# Last Modified:.*/s/# Last Modified:.*/# Last Modified: "
\ .strftime("%b-%d-%Y")
autocmd bufwritepost,filewritepost *.{py,sh}
\ execute "normal 'a"
The template for python files is as follows:
#!/usr/bin/python
# File Name: <filename>
# Creation Date: <date>
# Last Modified: <N/A>
# Created By: <Name>
# Description: CURSOR

First of all, let's have a look at :help 10.2:
The general form of the `:substitute` command is as follows:
:[range]substitute/from/to/[flags]
Please keep /[flags] in mind. Now when you enter gvim test.py in the command line, the following command is executed in Vim:
:s//# File Name: test.py
But when you enter gvim ../test.py Vim executes:
:s//# File Name: ../test.py
so Vim uses test.py as :substitute's flags and that's not the desired behavior.
What you need is to replace expand("%") with expand("%:t") to get only the file name. See :help expand() for details.

Related

How to remove the space in front of the matched content that transfered to sink Vim FZF?

Fzf seems to automatically add spaces in front of the matched content, And then transfer it to sink.
let g:vimspector_json_path=$HOME . "/.config/vimspector_template/"
command! -bang -nargs=* LoadVimSpectorJson call fzf#run({
\ 'source': 'ls ' . vimspector_json_path,
\ 'sink': 'e .vimspector.json | 0r' . vimspector_json_path,
\ 'down': '25%',
\ 'options': '--preview-window=hidden'
\ })
Vim(read):E484: Can't open file /home/lee/.config/vimspector_template/ python.json
Error because of the space before the filename python.json .
Is there any way to remove this space?
You can create an additional user-command to load a template by name and do the directory concatenation in that command.
For example:
command! -bar -nargs=1 LoadVimSpectorTemplate
\ execute "0r ".g:vimspector_json_path.<q-args>
So :LoadVimSpectorTemplate python.json will load that template file from the vimspector template directory.
In your fzf#run() call, you can then use:
'sink': 'e .vimspector.json | LoadVimSpectorTemplate'

.vimrc variables are not evaluated

I am trying to create installation script for https://github.com/junegunn/vim-plug/wiki/tips
if empty(glob('~/.vim/autoload/plug.vim'))
let s:downloadurl = "https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim"
let s:destinedirectory = $HOME . "/.vim/autoload/"
let s:destinefile = s:destinedirectory . "plug.vim"
if !isdirectory(s:destinedirectory)
call mkdir(s:destinedirectory, "p")
echo "Created directory: " . s:destinedirectory
endif
if executable("curl")
silent !curl --location --fail --output s:destinefile --create-dirs s:downloadurl
else
silent !wget -o s:destinefile --force-directories s:downloadurl
endif
autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif
But vim is not evaluating my variables, i.e., instead of running the command
wget -o /home/user/.vim/plug.vim --force-directories https://raw.githubusercontent...
It is running:
wget -o s:destinefile --force-directories s:downloadurl
You could use execute to evaluate the variables in commands. For your case:
silent execute '!wget -o '.s:destinefile.' --force-directories '.s:downloadurl
Here the dot is the string concatenation operator documented in :help expr-..

how to auto update file path in file header with autocmd in vi/vim?

I have a function in my .vimrc that automatically updates the file I'm currently editing with the timestamp (Modified) of the last 'save' (:w).
I would like to also update the Filename and Filepath. I have an autocmd that updates the filename (through expand("%"). As for the Filepath, from what I read in the documentation, using expand("%:p:h") should permit me to insert the path (excluding the filename), but it does not work.
Anybody can tell me how insert the Filepath in my header ?
Example of file header that I wish to update:
Modified: November 13 2016
Filename: myfile
Filepath: /home/me/path/tomyfile/
Code I have at the moment :
autocmd BufWritePre * call UpdHeader()
function! UpdHeader()
" update path <<<<<< DOES NOT WORK >>>>>>>
silent! execute "1," . 10 . "g/Filepath:.*/s//Filepath: " .expand("%:p:h")
" update filename <<WORKS>>
silent! execute "1," . 10 . "g/Filename:.*/s//Filename: " . expand("%")
" update last mod date <<WORKS>>
silent! execute "1," . 10 . "g/Modified:.*/s//Modified: " . strftime("%d %B %Y%t%t%T (%z)%tBy : ") . $USER
...
endf
thx!
M
You need to perform proper escaping on the filepath, as you use / both as a separator in :substitute, and the (Unix-style) replacement path also has / separators in it. :substitute would have alerted your via E488: Trailing characters, but you've :silent! it.
A quick fix would be switching of :substitute separators, hoping that # will never appear in a file path:
silent! execute "1," . 10 . "g/Filepath:.*/s##Filepath: " .expand("%:p:h")
Better do proper escaping:
silent! execute "1," . 10 . "g/Filepath:.*/s//Filepath: " .escape(expand("%:p:h"), '/\'. (&magic ? '&~' : ''))
Alternatively, you can replace with an expression:
silent! execute "1," . 10 . "g/Filepath:.*/s//\\='Filepath: ' .expand('%:p:h')"
Your filename expansion would benefit from that as well.

Using Uncrustify with VIM

In my vimrc I call Uncrustify by this command:
%!uncrustify -l CPP -c D:\uncrustify\default.cfg
After that on some code I get a Windows Fatal error:
But when I call uncrustify on the same code in the console using the -f option, there is no error.
How can I change my vimrc to avoid such errors in the future? What can invoke this error?
In order to integrate Uncrustify with Vim properly, add the following to your .vimrc:
" Restore cursor position, window position, and last search after running a
" command.
function! Preserve(command)
" Save the last search.
let search = #/
" Save the current cursor position.
let cursor_position = getpos('.')
" Save the current window position.
normal! H
let window_position = getpos('.')
call setpos('.', cursor_position)
" Execute the command.
execute a:command
" Restore the last search.
let #/ = search
" Restore the previous window position.
call setpos('.', window_position)
normal! zt
" Restore the previous cursor position.
call setpos('.', cursor_position)
endfunction
" Specify path to your Uncrustify configuration file.
let g:uncrustify_cfg_file_path =
\ shellescape(fnamemodify('~/.uncrustify.cfg', ':p'))
" Don't forget to add Uncrustify executable to $PATH (on Unix) or
" %PATH% (on Windows) for this command to work.
function! Uncrustify(language)
call Preserve(':silent %!uncrustify'
\ . ' -q '
\ . ' -l ' . a:language
\ . ' -c ' . g:uncrustify_cfg_file_path)
endfunction
Now you can either map this function (Uncrustify) to a combination of keys or you could do the convenient trick that I use. Create a file ~/.vim/after/ftplugin/cpp.vim where you can override any Vim settings particularly for C++ and add the following line there:
autocmd BufWritePre <buffer> :call Uncrustify('cpp')
This basically adds a pre-save hook. Now when you save the file with C++ code it will be automatically formatted by Uncrustify utilizing the configuration file you supplied earlier.
For example, the same could be done for Java: in ~/.vim/after/ftplugin/java.vim add:
autocmd BufWritePre <buffer> :call Uncrustify('java')
You got the point.
NOTE: Everything presented here is well-tested and used every day by me.
I have found the placing the following code into your .vimrc to be sufficient:
let g:uncrustifyCfgFile = '~/.uncrustify.cfg'
function! UncrustifyFunc(options) range
exec a:firstline.','.a:lastline.'!uncrustify '.a:options
\.' -c '.g:uncrustifyCfgFile.' -q -l '.&filetype
endfunction
command! -range=% UncrustifyRange <line1>,<line2>call UncrustifyFunc('--frag')
command! Uncrustify let s:save_cursor = getcurpos()
\| %call UncrustifyFunc('')
\| call setpos('.', s:save_cursor)
Note this does assume that you have "uncrustify" binary in your $PATH.
It also assumes your configure file is ~/.uncrustify.cfg however you can change that by modifiying the g:uncrustifyCfgFile variable.
To call run
:Uncrustify
It also works on ranges (which was what promoted me to make this function). Visual selection example:
:'<,'>UncrustifyRange
I have only tired it with C, CPP and JAVA (I assume others will work as well)
In addition to #Alexander Shukaev's answer, adding the following will perform a check for uncrustify config correctness and not auto format if error is detected:
let output = system('uncrustify -q -c ' . a:cfgfile)
if v:shell_error != 0
echo output
endif
return v:shell_error
endfunction
" Don't forget to add Uncrustify executable to $PATH (on Unix) or
" %PATH% (on Windows) for this command to work.
function! Uncrustify(language)
if CheckUncrustifyCfg(g:uncrustify_cfg_file_path)
echo "Config file" g:uncrustify_cfg_file_path "has errors"
echo "No formatting will be performed"
return
endif
call Preserve(':silent %!uncrustify'
\ . ' -q '
\ . ' -l ' . a:language
\ . ' -c ' . g:uncrustify_cfg_file_path)
endfunction

To insert mode from autocmd in Vim

I am trying to create an autocommand that will create boiler plate comments and code for new Java source files. As a simple start, I have added the following two lines (only a new line after the first line below in the actual file) to my .vim/ftplugin/java.vim:
autocmd BufNewFile *.java
\ exe "normal O/*\r" . expand('%:t') . "\t" . strftime("%B %d %Y") .
"\r/\r\rpublic class " . expand('%:t:r') . " {\r\t\<Esc>i"
With the last part, \t\<Esc>i, I am trying to insert a tab and shift to insert mode automatically. I can't make the switch to insert mode work and have tried different permutations of two or more of \<Esc>, \<Insert>, "insert" , i and \t. What am I missing ?
I am using VIM 7.2 on Linux.
You could use the :startinsert command. Just execute it after the :normal command:
autocmd! BufNewFile *.java
\ exe "normal O/*\r" . expand('%:t') . "\t" . strftime("%B %d %Y") .
\ "\r/\r\rpublic class " . expand('%:t:r') . " {\r\t" |
\ startinsert!
Here's some more information on that: http://vimdoc.sourceforge.net/htmldoc/insert.html#:startinsert.

Resources