Script syntax - return value

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Script syntax - return value

Jean-Rene David-2
I have two functions defined as follows:

function! Foo() range
   return 5
endfunction

function! Bar()
   1,5call Foo()
endfunction

What is the syntax to put the return value of
Foo() in a local variable when calling Foo() with
a range from within Bar()?

I tried:

let l:return_value_of_Foo = 1,5call Foo()
let l:return_value_of_Foo = execute 1,5call Foo()
let l:return_value_of_Foo = execute "1,5call Foo()"

None of them work.

--
JR
Reply | Threaded
Open this post in threaded view
|

Re: Script syntax - return value

Gerald Lai-2
On Fri, 25 Nov 2005, Jean-Rene David wrote:

> I have two functions defined as follows:
>
> function! Foo() range
>   return 5
> endfunction
>
> function! Bar()
>   1,5call Foo()
> endfunction
>
> What is the syntax to put the return value of
> Foo() in a local variable when calling Foo() with
> a range from within Bar()?
>
> I tried:
>
> let l:return_value_of_Foo = 1,5call Foo()
> let l:return_value_of_Foo = execute 1,5call Foo()
> let l:return_value_of_Foo = execute "1,5call Foo()"
>
> None of them work.
>
> --
> JR

I don't think there's a way of capturing the return value of functions
that act on a {range}.  A shortcoming? Perhaps not. I don't think it's
suppose to work that way.

One way to look at it is that you're calling that function multiple times,
each time for every line in the {range}. But you're trying to assign those
multiple return values to a scalar variable. Many-to-one assignments won't
work.

In your case, you would have to code Foo() to accept the {range}
as parameter arguments to the function. Maybe something like this:

   function! Foo(...) range
     if a:0 == 2
       let begin = a:1
       let end = a:2
       "code for range as argument
     else
       let begin = a:firstline
       let end = a:lastline
       "code for range as Vim induced {range}
     endif
   endfunction

-Gerald
Reply | Threaded
Open this post in threaded view
|

Re: Script syntax - return value

Jean-Rene David-2
* Gerald Lai <[hidden email]>:

> > function! Foo() range
> >   return 5
> > endfunction
> >
> > function! Bar()
> >   1,5call Foo()
> > endfunction
>
> One way to look at it is that you're calling
> that function multiple times, each time for
> every line in the {range}.

That's only true if the function is defined
without the "range" keyword after the name of the
function. In my case, I included it to make sure
the function was only called once.

> But you're trying to assign those multiple
> return values to a scalar variable. Many-to-one
> assignments won't work.

There is no many-to-one assignment in this case,
though I agree that if there were, it wouldn't
make sense.

> In your case, you would have to code Foo() to
> accept the {range} as parameter arguments to the
> function.

That's an idea, of course. If it turns out that
it's the only way, I'll do it.

I was trying to find a way to use the "range"
functionality, just because it's there...
Reply | Threaded
Open this post in threaded view
|

Re: Script syntax - return value

Charles E Campbell Jr
In reply to this post by Jean-Rene David-2
Jean-Rene David wrote:

>...
>What is the syntax to put the return value of
>Foo() in a local variable when calling Foo() with
>a range from within Bar()?
>  
>
...

Hello!

I suggest putting the function's output in a suitably accessable
variable (ie.  let b:FooOutput= 5).  Then you can follow the
[range]call Foo()  with the assignment to the local variable
using the accessable variable.

Regards,
Chip Campbell

Reply | Threaded
Open this post in threaded view
|

Re: Script syntax - return value

Jean-Rene David-2
* Charles E. Campbell, Jr. <[hidden email]>:

> Jean-Rene David wrote:
>
> >...
> >What is the syntax to put the return value of
> >Foo() in a local variable when calling Foo() with
> >a range from within Bar()?
> >...
>
> I suggest putting the function's output in a
> suitably accessable variable (ie.  let
> b:FooOutput= 5).

That's a good idea. However in my specific
situation, the call is recursive, so the buffer
variable would get overwritten at each level.

Stepping back a little from the original question
(for which the answer as far as I can see is
still: it can't be done), what I'm trying to do is
to hierarchically number text. So for example from
this:

todo
        do this
        do that
to buy
        buy this
        buy that

I would like to get:

1. todo
        1.1. do this
        1.2. do that
2. to buy
        2.1. buy this
        2.2. buy that

Each level is indented with a literal tab. For
each indentation level, I want to add a level of
numbering, up to 10 levels.

This is for use with vimoutliner, by the way, so
the syntax of the original text is rigidly
determined. This makes the problem much easier to
solve.

It's pretty elegantly done recursively, if I can
only get the syntax right. I'm sure there's other
ways to do it, so if anybody has ideas -- or
ready-made scripts! -- that would be nice.

At the moment what I think I will do is pass the
range as parameters. That way I can access the
return value with just:

let l:FooOutput = Foo(firstline, lastline)

--
JR
Reply | Threaded
Open this post in threaded view
|

Re: Script syntax - return value

A.J.Mechelynck
Jean-Rene David wrote:

> * Charles E. Campbell, Jr. <[hidden email]>:
>> Jean-Rene David wrote:
>>
>>> ...
>>> What is the syntax to put the return value of
>>> Foo() in a local variable when calling Foo() with
>>> a range from within Bar()?
>>> ...
>> I suggest putting the function's output in a
>> suitably accessable variable (ie.  let
>> b:FooOutput= 5).
>
> That's a good idea. However in my specific
> situation, the call is recursive, so the buffer
> variable would get overwritten at each level.

Maybe you can save/restore it in a function-local variable around the
recursion call; and if function-local variables are clobbered by a
recursive call, then pass the recursion level as an argument to the
call, and use |curly-braces-names| (q.v.).

>
> Stepping back a little from the original question
> (for which the answer as far as I can see is
> still: it can't be done), what I'm trying to do is
> to hierarchically number text. So for example from
> this:
>
> todo
> do this
> do that
> to buy
> buy this
> buy that
>
> I would like to get:
>
> 1. todo
> 1.1. do this
> 1.2. do that
> 2. to buy
> 2.1. buy this
> 2.2. buy that
>
> Each level is indented with a literal tab. For
> each indentation level, I want to add a level of
> numbering, up to 10 levels.
>
> This is for use with vimoutliner, by the way, so
> the syntax of the original text is rigidly
> determined. This makes the problem much easier to
> solve.
>
> It's pretty elegantly done recursively, if I can
> only get the syntax right. I'm sure there's other
> ways to do it, so if anybody has ideas -- or
> ready-made scripts! -- that would be nice.
>
> At the moment what I think I will do is pass the
> range as parameters. That way I can access the
> return value with just:
>
> let l:FooOutput = Foo(firstline, lastline)
>

Best regards,
Tony.

Reply | Threaded
Open this post in threaded view
|

Re: Script syntax - return value

Antony Scriven
In reply to this post by Jean-Rene David-2
Hello

On Nov 28, Jean-Rene David wrote:

 > [...]
 >
 > Stepping back a little from the original question
 > (for which the answer as far as I can see is
 > still: it can't be done), what I'm trying to do is
 > to hierarchically number text. So for example from
 > this:
 >
 > todo
 > do this
 > do that
 > to buy
 > buy this
 > buy that
 >
 > I would like to get:
 >
 > 1. todo
 > 1.1. do this
 > 1.2. do that
 > 2. to buy
 > 2.1. buy this
 > 2.2. buy that
 >
 > Each level is indented with a literal tab. For
 > each indentation level, I want to add a level of
 > numbering, up to 10 levels.
 >
 > This is for use with vimoutliner, by the way, so
 > the syntax of the original text is rigidly
 > determined. This makes the problem much easier to
 > solve.
 >
 > It's pretty elegantly done recursively, if I can
 > only get the syntax right. I'm sure there's other
 > ways to do it, so if anybody has ideas -- or
 > ready-made scripts! -- that would be nice.

Hmm, I can't see what recursion buys you here. Maybe it's
just the fog of another late night. What is your intended
approach? Here's an iterative solution. Note that I've only
tested it on your sample text above, so it probably needs a
lot of work. It just looks at the indent of the current
line, sets the appropriate counters, then uses these to
number the current line.

---otlnum.vim---
let s:maxlevel = 10

fun! s:ResetSubHeadings(level)
        let i = a:level + 1
        while i <= s:maxlevel
                let s:num{i} = 0
                let i = i + 1
        endwhile
endfun

fun! s:NumberCurrentLine(level)
        if a:level > s:maxlevel | return | endif
        call s:ResetSubHeadings(a:level)
        let s:num{a:level} = s:num{a:level} + 1
        let n = '' | let i = 1
        while i <= a:level
                let n = n . s:num{i} . '.'
                let i = i + 1
        endwhile
        exe 's/\ze\S/' . n . ' '
endfun

fun! OTLNumberHeadings(start,end)
        call s:ResetSubHeadings(0)
        exe a:start','a:end'g/^/ let lev = indent(line("."))/&ts+1'
        \                      .'| call s:NumberCurrentLine(lev)'
endfun

---end otlnum.vim---
:source otlnum.vim
:call OTLNumberHeadings(1, line('$'))

Antony
Reply | Threaded
Open this post in threaded view
|

Re: Script syntax - return value

Jean-Rene David-2
* Antony Scriven <[hidden email]>:
> Here's an iterative solution.

Why thanks. That will probably be just fine.

I was wondering how to create an array variable to
keep the count of each level but couldn't find
one.  What I was missing was the {} notation for
variable names.

After years of use, I am just now starting to do a
little vim scripting and, honestly, I find the
language a little unwieldy...