1
votes

I often use gf in vim to open files under cursor. Often these file paths use environment variables but when in .tcl script files vim is unable to use the environment variable.

This works for gf:

$tcl_lib/myfile.tcl

These do NOT work for gf:

$env(tcl_lib)/myfile.tcl
$::env(tcl_lib)/myfile.tcl

These are some of the things I have tried:

:set isfname=@,48-57,/,.,-,_,+,,,#,$,%,~,=,{,},(,)
:set isfname=@,48-57,/,.,-,_,+,,,#,$,%,~,=,{,},40-41

:set includeexpr=substitute(v:fname,'\$env(\([^)]\+\))','\$\1','')

Is there a way to make vim understand the syntax for environment variables in tcl scripts (specifically for the 'gf' command)?

3
Can you just add $tcl_lib to your 'path'? e.g. setlocal path=.,$tcl_lib,,Peter Rincker
@PeterRincker I would need to remove the '$env(tcl_lib)/' in the source and then the source would be broken.stephenmm
In theory you can leave 'isfname' alone and just add $tcl_lib to 'path'. If you change 'isfname' then you are correct you will need to remove or read $env(..) like structures.Peter Rincker
@PeterRincker I did revert the isfname but then still sees the begining '/' and looks in the root dir instead of 'path'.stephenmm

3 Answers

2
votes

There are a few techniques:

Set 'path' & 'includeexpr'

In theory you can just add $tcl_lib to path. e.g. set path=.,$tcl_lib,,. However, any filename starting with / will fail. This can be remedied by removing the starting /.

Add to ~/.vim/after/ftplugin/tcl.vim:

set path=.,$tcl_lib,,
let &l:includeexpr="substitute(v:fname, '^/', '', 'g')"

Reading Environmental variables via 'includeexpr'

Can use a substitution to expand environment variables

let l:includeexpr = "substitute(v:fname, '$\\%(::\\)\\=env(\\([^)]*\\))', '\\=expand(\"$\".submatch(1))', 'g')"

This uses a sub-replace-expression (See :h sub-replace-expression) to use expand() to get the environmental variable.

This might require you to change 'isfname' to allow more characters tto be a part of a filename looking string.

Just map gf and friends

Make buffer-local mappings for gf, <c-w>f, etc which are specific to your language and check certain paths. This completely side-steps many of Vim's built in methods so it should be used as a last resort.

0
votes

Finally got back to this and was able to solve it in a pretty good way. Add the following tcl.vim file to your ~/.vim/ftplugin and your "gf" should work!

https://github.com/stephenmm/dotfiles/blob/master/vim/ftplugin/tcl.vim

" Add charecters to possible filename types so vim will recognize:
"    $::env(THIS)/as/a/file.tcl
set isfname+={,},(,),:

" Turn the string into something vim knows as a filename:
"    $::env(THIS)/as/a/file.tcl => ${THIS}/as/a/file.tcl
function! TclGfIncludeExpr(fname)
  if a:fname =~? '\$\(::\)\?env([^)]\+)'
    return substitute(a:fname, '\$\(::\)\?env(\([^)]\+\))', '${\2}', 'g')
  endif
  return a:fname
endfunction

" Tie the function to includeexpr
set includeexpr=TclGfIncludeExpr(v:fname)    
0
votes

Adding below 2 lines in ~/.vimrc will work for me.

set isfname+={,},(,),:
let &l:includeexpr = "substitute(v:fname,'$\\%(::\\)\\=env(\\([^)]*\\))','\\=expand(\"$\".submatch(1))', 'g')"