How to make Syntastic search for javac config file in project - vim

I'm using Syntastic with vim and I've added external libraries to its classpath (using SyntasticJavacEditClasspath). This creates a file in the current working directory (which was my project folder). This is all fine. However, whenever I restart vim, Syntastic seems to search for the .syntastic_javac_config file in the current working directory only, and the cwd is, of course, randomly whereever I left it in my last operation. So it doesn't find the file and I get a bunch of incorrect import errors. Can Syntastic be told to search the file's parents for the config file? If not, is there a way of using vim where this typically works? (I've only been using vim for a couple of months so I might be clueless.)

According to the official manual, the snippet should solve the problem. Put it in your .vimrc, change the javascript, jscs, etc. to required values
function! FindConfig(prefix, what, where)
let cfg = findfile(a:what, escape(a:where, ' ') . ';')
return cfg !=# '' ? ' ' . a:prefix . ' ' . shellescape(cfg) : ''
endfunction
autocmd FileType javascript let b:syntastic_javascript_jscs_args =
\ get(g:, 'syntastic_javascript_jscs_args', '') .
\ FindConfig('-c', '.jscs', expand('<afile>:p:h', 1))

Related

Cannot write to backup file

Since I have upgraded to Catalina, I cannot edit my dotfiles but get a message saying "Cannot write to backup file...".
I have checked the permissions on the file and my user account is the owner and has read and write permissions. If I edit the files with BBedit, I can save the files so the issue just seems to be editing within neovim.
I can also edit files using neovim in other directories but not within my dotfile directory.
Additional information added:
I have noticed that the files that I can't edit have the following permission structure:
.rwxrwxrwx# 1.4k pdd 30 Aug 2017 plugin_manager.vim
I have now removed the # attribute using xattr but that has not made any difference.
Additional Information Update
I have narrowed it down to something in my vimrc file. If I start neovim without my vimrc, I can save files in my vimrc directory.
I have the following code in my vimrc relating to backup files:
if exists('$SUDO_USER')
set nobackup " don't create root-owned files
set nowritebackup " don't create root-owned files
else
set backupdir=~/local/.config/nvim/tmp/backup
set backupdir+=~/.config/nvim/tmp/backup " keep backup files out of the way
set backupdir+=.
endif
If I comment these lines out, I can then save files in my vimrc directory. I am a little confused as I have had these in my vimrc for some time and have not had a problem.
I am probably missing something simple. Does anyone have any suggestions?
The original backup I used for vim was found here: https://vim.fandom.com/wiki/Incremental_backup_in_central_backup_directory created July 22, 2005 author Sylvain Lafleur
It doesn't work in neovim, but I was able to get it working:
I'm using KDE Neon. The original looks like it might work on windows, but I have not tested it.
A few things to note:
You will need to manually edit the g:backupdir and
g:this_root_backkup_dir (This may be reduced, but I didn't mess with it.)
I was unable to make $HOME work, so use /home/username on linux.
This is not my actual directory structure, but should suffice as an
example, in that /home/neon/vim existed before I used this code.
This is very redundant backup. Every time the file is saved it will
create a backup of the filename with date/time stamp.
In the .vimrc put your vim specific code in if !has('nvim')
and endif blocks. I put the following code in my init.vim file.
set backup
set backupcopy=yes
function Write_backup()
let g:backupdir='/home/neon/vim/vim_backups'
let &backupdir=g:backupdir
let g:backupext = strftime("_%Y-%m-%d_%H-%M-%S")
let &backupext=g:backupext
let g:this_root_backup_dir = '/home/neon/vim/vim_backups'
let g:this_dir = substitute(expand("%:p:h")," ","_","g")
let g:this_filename = substitute(expand("%")," ","_","g")
let g:this_drive = strpart(g:this_dir, 0, 1)
let g:this_backup_dir_drive = g:this_root_backup_dir . g:this_drive
let g:this_backup_dir = g:this_backup_dir_drive . strpart(g:this_dir, 1)
"--make DRIVE directory if it doesn't exist
if !filewritable(g:this_backup_dir_drive)
silent! execute expand('!mkdir -p ' . g:this_backup_dir_drive)
endif
"--make directory under DRIVE if it doesn't exist
if !filewritable(g:this_backup_dir)
silent! execute expand('!mkdir -p ' . g:this_backup_dir)
endif
"--set new backup dir
let g:backupdir = g:this_backup_dir
let &backupdir=g:backupdir
endfunction
call Write_backup()
inoremap <ESC> <ESC>:call Write_backup()<CR><C-l>
" note the <C-l> clears the output so remove if testing with echo

How can I source files relative to file?

I'm trying to split my vimrc up into multiple files - init.vim, keybindings.vim, ui.vim, etc. - but I can't get Vim to source files relative to init.vim (it instead sources relative to where I launch Vim from.
This is what I've got at the top of init.vim:
source keybindings.vim
source ui.vim
If I run vim from the same directory as those files, it works fine; if I run it from any other directory, I get the following errors:
Error detected while processing /path/to/vimrc:
line 1:
E484: Can't open file keybindings.vim
line 2:
E484: Can't open file ui.vim
Press ENTER or type command to continue
Edit: It's worth noting that I'm using NixOS, so I don't know what the absolute paths will be, nor if they would be constant if I found out.
I think you can use
runtime keybindings.vim
Source needs the full path, you can however simplify it using something like this :
let path = expand('%:p:h')
exec 'source' path . '/keybindings.vim'
You can have a look at mine here - https://github.com/dhruvasagar/dotfiles/blob/master/vim/vimrc for reference.
If the order is not important, you can just put your scripts into ~/.vim/plugin/, and they will be sourced after ~/.vimrc. You can check :scriptnames output to see what gets sourced when.
You can influence the ordering somewhat via the plugin filenames. For example, I have a ~/.vim/plugin/00plugin-configuration.vim that configures Vim plugins; the 00... ensures this is sourced first.
To get finer control, I would instead put the scripts into ~/.vim/. Vim will ignore them there, but they can easily be addressed via :runtime, which looks in all runtimepaths, and ~/.vim/ typically is included in 'runtimepath':
# .vimrc
runtime init.vim
runtime keybindings.vim
...
Relevant help pages: :help .vimrc and :help load-plugins.
Building on Dhruva's answer, you can make a function to help out with this
function! SourceLocal(relativePath)
let root = expand('%:p:h')
let fullPath = root . '/'. a:relativePath
exec 'source ' . fullPath
endfunction
You then use it like
call SourceLocal ("yourScript.vim")
I have met exactly the same issue with you in Neovim. I split my large init.vim file into several small vim scripts and I want to source them inside init.vim.
This is what I get finally based on #Dhruva Sagar's links:
let g:nvim_config_root = stdpath('config')
let g:config_file_list = ['variables.vim',
\ 'options.vim',
\ 'autocommands.vim',
\ 'mappings.vim',
\ 'plugins.vim',
\ 'ui.vim'
\ ]
for f in g:config_file_list
execute 'source ' . g:nvim_config_root . '/' . f
endfor
As none of the solutions works as a real substitute for source working globally (on any script, even sourced from vimrc), I ended up with this solution and decided to share here, which can be used as a substitute for source with relative support, as simple as:
Rsource /home/me/.vim/your/file/path
Rsource $HOME/.vim/your/file/path
Rsource your/file/path
Rsource ../your/file/path
To use it, this must be defined on your vimrc or any file sourced by it before you can use Rsource:
if !exists('g:RelativeSource')
function! g:RelativeSource(file)
let file = expand(a:file)
" if file is a root path, just source it
if stridx(file, '/') == 0
exec 'source ' . file
return
endif
let sfile = expand('<sfile>:p:h')
" If this is called outside this script, it will contains this script
" name, this function name, a script_marker then the executing script name
" In this case we extract just the last part, the script name which called
" the this function
let script_marker = '..script '
let path_index = strridx(sfile, script_marker)
if path_index == -1
let path_index = 0
else
let path_index += len(script_marker)
endif
let path = strpart(sfile,path_index)
let absolute_path = resolve(path . '/'. file)
exec 'source ' . absolute_path
endfunction
command! -nargs=1 Rsource :call g:RelativeSource(<q-args>)
endif
This is safe to be used in any script or plugin.
These are all great solutions, and this is what I ended up using.
let home = expand('~')
exec 'source' home . '/.config/nvim/prettierConfig.vim'

vimscript augment rtp with directory above result of system command

I'm trying to modify my vimrc to include a directory
let g:mydir = system('which someExecutable')
execute "set rtp+=" . g:mydir
The problem is that which someExecutable returns something like
/aDir/a/b.
I need g:mydir set to /aDir/, so two dirs above b.
Is there an easy way to do this in vimscript?
You're looking for fnamemodify(path, ":h")
If you version of vim is recent enough, you can even use exepath('someExecutable') instead of system('which someexecutable'). Which gives:
fnamemodify(exepath('someExecutable'), ":h")
PS: don't forget to escape what must be escaped if you use exe "set rtp+=....

Automatically append current date to file name when saving in Vim

I'm using vim to take notes while reading academic articles. I prefer to have a new text file for each note I've taken, but organizing them becomes tedious.
What I would like to do is set an autocommand to detect if I'm in a certain directory, writing to a newfile and then appened the current date and time to whatever filename I write.
So if I have:
:pwd
/path/to/projects
When I type
:w Notes
I would like vim instead to save the file as
"Notes - <CURRENT DATE - TIME >.txt"
I believe it involves declaring something like the following in my vimrc:
autocmd BufNewFile,BufWrite "/path/to/projects/*" <command involving strftime("%Y-%m-%d_%H-%M")>
But I can't figure out what. Any Ideas? I'm using Vim 7.3 on Debian Linux.
You're very close. I think it's best to rename the file as it is created; messing with the file name during writes makes this more difficult (e.g. what if you re-open an existing note, or just write the buffer again?)
The :file command can be used to rename the current file; the current filename is in the % special identifier. Triggered when a new file is created, this does the job:
autocmd BufNewFile /path/to/projects/* execute 'file' fnameescape(expand('%') . strftime(" - %Y-%m-%d_%H-%M.txt"))
If you don't want to consider the original filename, this becomes even easier:
autocmd BufNewFile /path/to/projects/* execute 'file' fnameescape(strftime("Notes - %Y-%m-%d_%H-%M.txt"))
You may be looking for something along the lines of:
function! SaveWithTS(filename) range
execute "save '" . a:filename . strftime(" - %Y-%m-%d_%H-%M.txt'")
endfunction
command! -nargs=1 SWT call SaveWithTS( <q-args> )
With the above in your .vimrc, executing :SWT Note will save your file as Note - YYYY-MM-DD_HH-MM.txt. This has the disadvantage of not happening automatically, so you have to remember to use :SWT instead of :w the first time your write your file, but it does let you wait until you are ready to save to decide what your filename should be (i.e. you aren't stuck with Note every time).
Edit: The above version of SaveWithTS actually saves to the filename with single quotes around it (bad testing on my part). Below is a version that should fix that and also lets you specify an extension to your file (but will default to .txt)
function! SaveWithTS(filename) range
let l:extension = '.' . fnamemodify( a:filename, ':e' )
if len(l:extension) == 1
let l:extension = '.txt'
endif
let l:filename = escape( fnamemodify(a:filename, ':r') . strftime(" - %Y-%m-%d_%H-%M") . l:extension, ' ' )
execute "write " . l:filename
endfunction

gvim open dialog file type filter

I like using the file browser in gvim sometimes, however what I don't like is that the file filter is always set to the current file type being edited.
For example, if I have a .cpp file open in the current buffer and go to the file open dialog the file filter is set to "C++ source files (*.cpp *.c++)". I would prefer that headers are displayed too by default (say).
Is there a way to change this default behavior?
Thanks to #benjifisher, I found the help for :browse which shows how to do what I wanted.
More specifically, the default filetype plugin for C/C++ contains these lines:
let b:browsefilter = "C++ Source Files (*.cpp *.c++)\t*.cpp;*.c++\n" .
\ "C Header Files (*.h)\t*.h\n" .
\ "C Source Files (*.c)\t*.c\n" .
\ "All Files (*.*)\t*.*\n"
I copied the file into my local vim ftplugin directory and modified to my liking which now takes precedence over the system version.
If anyone, like me, wants a quick and simple way to disable this behaviour altogether in vimrc:
autocmd FileType * let b:browsefilter = ''
From first reply in this thread
I had a similar issue that I solved without having to copy the c.vim file to ~/.vim/ftplugin. To support *.cc as a C++ extension, in GVim on Ubuntu I edited the /usr/share/vim/vim74/ftplugin/c.vim file to add the extension:
let b:browsefilter = "C++ Source Files (*.cpp *.c++ *cc)\t*.cpp;*.c++;*.cc\n" .
\ "C Header Files (*.h)\t*.h\n" .
\ "C Source Files (*.c)\t*.c\n" .
\ "All Files (*.*)\t*.*\n"
Then restarted GVim and it worked without copying c.vim.

Resources