Gautam
Gautam

Reputation: 375

possibility of using a function to calculate sum in vim

I have some parameters in a text file which goes as follows

parameter1  =5
parameter2=4
----------
---------
parameter(n-1) = 6
parameter(n)=11

My requirement is that the values of the parameters should sum upto 100 and there can be number of parameters. I was wondering if I could write a function in Vim , which could calculate the sum and display it somewhere? I have no idea how to pass arguement to such a function,I was thinking it could somehow be done by block selecting the lines with parameter values.

Upvotes: 1

Views: 955

Answers (2)

Luc Hermitte
Luc Hermitte

Reputation: 32966

This can also be done with a (pseudo) one-liner as well:

:let s=0
:g/parameter\d\+\s*=\s*\d\+/let s+=matchstr(getline('.'), '\d\+\s*$')
:echo s

It you want a function you fall back to Birei's solution

EDIT: BTW, we can also echo it directly with:

echo eval(join(map(filter(getline(1,'$'), 'v:val =~ "=\\s*\\d"'), 'matchstr(v:val, "=\\s*\\zs\\d\\+")'), '+'))

or if you prefer a command:

command! -nargs=0 -range=% Sum echo eval(join(map(filter(getline(<line1>,<line2>), 'v:val =~ "=\\s*\\d"'), 'matchstr(v:val, "=\\s*\\zs\\d\\+")'), '+'))

Upvotes: 0

Birei
Birei

Reputation: 36282

Add following function to your vimrc file:

function! CustomSum()
        let sum = 0
        for l in range( 1, line('$') )
                let fields = split( getline(l), '\s*=\s*' )
                if ( len( fields ) != 2 || fields[1] =~? '\D' )
                        continue
                endif
                let sum = sum + fields[1]
        endfor
        return sum
endfunction

And run it:

:echo CustomSum()

That with your input data yields:

26

EDIT to add a range to previous function. Now accepts a range as input parameters named a:firstline and a:lastline. I increment them with 0 to convert them to integers, otherwise the range function complains. Last line echoes the result for debugging but would be better idea to handle the result in a return call (only uncomment it).

function! CustomSum() range
        let sum = 0
        for l in range( a:firstline + 0, a:lastline + 0 )
                let fields = split( getline(l), '\s*=\s*' )
                if ( len( fields ) != 2 || fields[1] =~? '\D' )
                        continue
                endif
                let sum = sum + fields[1]
        endfor
        echo sum
        "" return sum
endfunction

Now you can do visually selection or normal ranges, like:

:'<,'>call CustomSum()

or

:1,5call CustomSum()

Both should work.

Upvotes: 2

Related Questions