0

I want to build an include path from a environment variable on vim. I want to keep only the instances which ends as /share/bin on this variable, and change them to include. I want to do this on .vimrc, for this reason I used the vim substitute() function.

As a test, I will use this variable:

export TEST=/afs/test/share/bin:/afs/test2/share/bin:/afs/test/bin:/afs/test3/share/bin:/cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

The desired result for this example is:

TEST=/afs/test/include /afs/test2/include /afs/test3/include

While trying to achieve this result, I got stuck with the following two questions:


Question1

As I was having trouble to use the vim substitute() method (explained below), I opened a file, say lala, with the same text from the $TEST environment variable:

/afs/test/share/bin:/afs/test2/share/bin:/afs/test/bin:/afs/test3/share/bin:/cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

And used the command s/share\/bin:/include /g to get:

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include /cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

afterwards, I used the command %s#\(/.*include\)\(.*\)#\1#g, resulting:

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include

But when I do on vim

:echo substitute(substitute($TEST,"share/bin:","include ","g"),"\(/.*include\)\(.*\)","\1","g")

I get:

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include /cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin

so, my first question is:

Why does not substitute() give the same result when using substitute?


Question2

And finally, I want to remove all instances similar to /afs/test/bin: from:

/afs/test/include /afs/test2/include /afs/test/bin:/afs/test3/include

, that is, that do not have include on it. I was trying:

%s#\(/.\{-}include\)\@<=\(/| \)\{-}.\{-}:# #

But it is matching /afs/test2/include /afs/test/bin: and giving as result:

/afs/test/include /afs/test3/include

How can I remove those text instances that did not have /share/bin?

1
  • 1
    One problem you're having (it may not be the only problem) is you're using backslashes inside double quotes (e.g. "\(/.*include\) which won't work as you seem to expect. This will be a literal ( character rather than using the \( search feature. Either use single quotes or escape the backslash to keep it in the string. I'm not going to try deciphering the rest since the list functions in the current answer are so much nicer. :-)
    – Ben
    Nov 16, 2014 at 19:32

1 Answer 1

2

Your code isn't easy to follow, and in general, substitute() should behave like :s, so I can't tell you the exact problem. However, your whole approach depends solely on text substitutions, and that makes it so complex. Since version 7, Vim has (Python-inspired) functions to work on Lists, and this is what I would use here. I show you this step by step:

" Setup
let $TEST='/afs/test/share/bin:/afs/test2/share/bin:/afs/test/bin:/afs/test3/share/bin:/cvmfs/x86_64-slc6-gcc47-opt/share:/cvmfs/x86_64-slc6-gcc47-opt/bin'

" Turn into List.
let dirs = split($TEST, ':')

" Remove unwanted dirs, then substitute the rest.
call filter(dirs, 'v:val =~# "/share/bin$"')
call map(dirs, 'substitute(v:val, "/share/bin$", "/include", "")')

" Combine back into String.
let result = join(dirs, ' ')
echo result

Output:

/afs/test/include /afs/test2/include /afs/test3/include
1
  • 1
    I needed just one more minute to format and proofread my answer ;-)
    – romainl
    Nov 14, 2014 at 14:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .