I'm working on a vim script and want to see the value of a variable that is generated in the script for debugging purposes.
I use something like:
echomsg 'My variable = ' . b:variable
reload the source with
:source %
and then look the message history list with
:messages
But there's nothing there and I'm pretty sure that the command would be executed.
What am I doing wrong here?
EDIT:
I'm trying to make a change to vim-cucumber and so I wanted to see the value of a variable. In the ftplugin/cucumber.vim file, I have the following:
let b:cucumber_root = expand('%:p:h:s?.*[\/]\%(features\|stories\)/step_definitions/mobile_website\zs[\/].*??')
echomsg 'cucumber_root = ' . b:cucumber_root
If you look at the top of file you will find
if (exists("b:did_ftplugin"))
finish
endif
Which stops the file from being sourced again after the first time. You need to unlet b:did_ftplugin before sourcing the file again.
Other options would be to use another tpope plugin to do this for you called scripttease with the :Runtime command.
Related
I've tried all the solutionshttps://stackoverflow.com/questions/4976776/how-to-get-path-to-the-current-vimscript-being-executed/53274039#53274039 which was posted 7 years ago and none are working for me in the current (2018) MacVim (8.1) or neovim (0.3.1). Since my question there keeps being deleted, I decided to ask in a new question.
Has something changed in Vim since the last answer 7 years ago? All of these solutions are giving me the current file's location and not the location of the script. Is SpaceVim effecting how these functions work?
This is the code I'm trying to fix:
function! TeaCodeExpand()
<<some code>>
echom fnamemodify(resolve(expand('<sfile>:p')), ':h')
<<other code>>
endfunction
I have an echom to show the path that should be the current script file, but it always returns the currently edited file. The next line is to execute an AppleScript in the directory above the vimscript file. I can hard code the path and everything works fine. But, I can't get it to work as is. The full code is here: github.com/raguay/TeaCode-Vim-Extension
To have the <sfile> expand to the plugin's filespec, the expansion has to happen when the script is sourced. See :help :<sfile>:
<sfile> When executing a ":source" command, is replaced with the
file name of the sourced file.
When executing a function, is replaced with:
"function {function-name}[{lnum}]"
If you need the filespec later in a function, you need to store it in a (script-local) variable, and reference that from the function:
let s:scriptPath = fnamemodify(resolve(expand('<sfile>:p')), ':h')
function! TeaCodeExpand()
<<some code>>
echom s:scriptPath
<<other code>>
endfunction
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'
i want to set the tags variable to the set of all gotags files i generated in specific folder(s) using exuberant Ctags. (gotags is nothing but the tags file renamed).
i put following lines in my .vimrc file.
set tags+=/usr/local/go/src/gotags
set tags+=`find /home/vimal/gowork/src -name gotags`
but it doesnt work and i get the following error
$ vi ~/.vimrc
Error detected while processing /home/vimal/.vimrc:
line 157:
E518: Unknown option: /home/vimal/gowork/src
Press ENTER or type command to continue
how can i fix the error and set the tags variable with the value: list of all the gotags files under one directory tree.
Inventing new syntax tends not to work that well in practice. Use system() to run external commands from Vim, not backticks. Also set in Vim is weird, it doesn't evaluate RHS the way you expect. Most of the time it's a lot simpler to use let &option = ... instead of set option=....
Anyway, to answer your question, you don't need to run find(1) for that, plain Vim functions are enough for what you want:
let &tags = join(extend([&tags, '/usr/local/go/src/gotags'],
\ findfile('gotags', '/home/vimal/gowork/src', -1)), ',')
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
For example:
If my current directory is /temp/src/com. And the file edited in vim is from /java/test.And now i want to add the path of the file to path environment. So if there is a cmd like set path+=$(filepath) in vim?
case 2:
Run make in terminal will start to compile a project, and it will out put logs about this compile. And now i want to read the outputed logs into vim using some command like r !make.
1) Pull the path into the current Vim buffer:
:r !echo \%PATH\%
Append to the path:
:let $PATH="C:\Test" . $PATH
2) This question is ambiguous, because it depends on your makefile behavior.
If your Makefile simply print to the console, then, :r make should do the trick.
If your make file actually writes to files explicitly, then there is no automatic way.
You'll have to write a custom vimscript function to pull in the logs.
1) Part 2
I do not know of what a way to do it in one line, but here's one way to achieve the functionality you want.
:redir #a "redirect output to register a
:pwd
:redir END "stop redirecting
:let #a = substitute(#a, '\n', '', 'g') "remove the newlines
:let $PATH=#a .":". $PATH
You should be able to wrap this in a function if you need to use it often.
You may reference environment variables using $MYVAR syntax. To set system environment variables use
let $MYVAR=foo
e.g.
let $PATH = "/foo" . $PATH
See http://vim.wikia.com/wiki/Environment_variables or :help :let-environment
Then you may use filename-modifiers to get directory name of a file in a current buffer:
let $PATH = expand("%:p:h") . $PATH
To read and parse compilation output in vim you might be interested to check quickfix mode
Use :make instead of :!make