How to accessing s: variable and s: functions in another script?

828 views
Skip to first unread message

pansz

unread,
Nov 19, 2009, 1:15:14 AM11/19/09
to vim...@googlegroups.com
Hi everyone:

When I want to design "a plugin for a plugin", I may use such a feature.
i.e. a plugin which is a generic framework for a kind of engine plugins,
which could be implemented by another script:

plugin/framework.vim
engine_a.vim
engine_b.vim
engine_c.vim

there may be different engines, we can only enable one of them at each
vim session, the framework will call engine's initialization and some
interface functions, inside the engine.vim script it may need to set
some s:variables and access some s:functions inside framework.vim

This architecture requires the framework give the access right of some
variables and functions to the engine. If we define g: variables it will
be global, I want the engine to be the "friend" of the framework, i.e.
the particular script engine.vim can access all script-local stuffs of
framework.vim, is that possible?

Or is it possible for two scripts sharing the same script-local namespace?

Kana Natsuno

unread,
Nov 19, 2009, 3:19:35 AM11/19/09
to vim_use
> there may be different engines, we can only enable one of them at each
> vim session, the framework will call engine's initialization and some
> interface functions, inside the engine.vim script it may need to set
> some s:variables and access some s:functions inside framework.vim

callee.vim:
function SID()
return maparg('<SID>', 'n')
endfunction
nnoremap <SID> <SID>

function s:cript_local_function(...)
return string(a:000)
endfunction

caller.vim:
echo call(substitute('s:cript_local_function', '^s:', SID(), ''),
['Vim', 'is', 'forever'])
" ==> ['Vim', 'is', 'forever']

referencee.vim:
function Scope()
return s:
endfunction
let s:mile = 'XD'

referencer.vim:
let s = Scope()
echo s['mile']
" ==> 'XD'

Andy Wokula

unread,
Nov 19, 2009, 4:36:03 AM11/19/09
to vim...@googlegroups.com
Kana Natsuno schrieb:

>> there may be different engines, we can only enable one of them at each
>> vim session, the framework will call engine's initialization and some
>> interface functions, inside the engine.vim script it may need to set
>> some s:variables and access some s:functions inside framework.vim
>
> callee.vim:
> function SID()
> return maparg('<SID>', 'n')
> endfunction
> nnoremap <SID> <SID>
>
> function s:cript_local_function(...)
> return string(a:000)
> endfunction
>
> caller.vim:
> echo call(substitute('s:cript_local_function', '^s:', SID(), ''),
> ['Vim', 'is', 'forever'])
> " ==> ['Vim', 'is', 'forever']

--------------------------
" callee.vim:
com! -nargs=* -complete=command FrameworkLocal <args>

function s:cript_local_function(...)
return string(a:000)
endfunction

let s:mile = 'XD'

--------------------------
" caller.vim:
FrameworkLocal echo s:cript_local_function(['Vim', 'is', 'forever'])


" ==> ['Vim', 'is', 'forever']

FrameworkLocal echo s:mile
" ==> 'XD'

--
Andy

Kana Natsuno

unread,
Nov 19, 2009, 5:41:53 AM11/19/09
to vim...@googlegroups.com
On Thu, 19 Nov 2009 18:36:03 +0900, Andy Wokula <anw...@yahoo.de> wrote:
> " callee.vim:
> com! -nargs=* -complete=command FrameworkLocal <args>
>
> function s:cript_local_function(...)
> return string(a:000)
> endfunction
>
> let s:mile = 'XD'
>
> --------------------------
> " caller.vim:
> FrameworkLocal echo s:cript_local_function(['Vim', 'is', 'forever'])
> " ==> ['Vim', 'is', 'forever']
> FrameworkLocal echo s:mile
> " ==> 'XD'

It's not possible to interact with caller's script-local variables easily .
For example:

caller.vim:
let s:callers_variable = '...'
FrameworkLocal let s:callee_variable = s:caller_variable " ???

And user-defined Ex commands (= :FrameworkLocal) are usually
for interactive use, not for scripts. Defining Ex commands
may be annoying for users whenever they try to complete the names of
Ex commands in Command-line mode.


--
To Vim, or not to Vim.
http://whileimautomaton.net/

Kana Natsuno

unread,
Nov 19, 2009, 5:54:07 AM11/19/09
to vim...@googlegroups.com
On Thu, 19 Nov 2009 15:15:14 +0900, pansz <pans...@routon.com> wrote:
> plugin/framework.vim
> engine_a.vim
> engine_b.vim
> engine_c.vim
>
...

>
> This architecture requires the framework give the access right of some
> variables and functions to the engine. If we define g: variables it will
> be global, I want the engine to be the "friend" of the framework, i.e.
> the particular script engine.vim can access all script-local stuffs of
> framework.vim, is that possible?

It's possible as I replied before. But IMHO, you should not do so
unless you REALLY need it, for example, testing script-local stuffs.

There is another way which is to provide API of framework.vim to
interact with engine_x.vim. For example:

autoload/framework.vim:
function! framework#get_parameter_x()
return s:parameter_x
endfunction

function! framework#set_parameter_x(value)
let s:parameter_x = a:value
endfunction

function! framework#_call_internal_stuff()
return s:zap()
endfunction

function! s:zap()
return '...'
endfunction

plugin/engine_x.vim:
call framework#set_parameter_x('...')
call framework#_call_internal_stuff()

Did you consider about this way? If so, why do you reject it?

Andy Wokula

unread,
Nov 19, 2009, 7:25:49 AM11/19/09
to vim...@googlegroups.com
Kana Natsuno schrieb:

> On Thu, 19 Nov 2009 18:36:03 +0900, Andy Wokula <anw...@yahoo.de> wrote:
>> " callee.vim:
>> com! -nargs=* -complete=command FrameworkLocal <args>
>>
>> function s:cript_local_function(...)
>> return string(a:000)
>> endfunction
>>
>> let s:mile = 'XD'
>>
>> --------------------------
>> " caller.vim:
>> FrameworkLocal echo s:cript_local_function(['Vim', 'is', 'forever'])
>> " ==> ['Vim', 'is', 'forever']
>> FrameworkLocal echo s:mile
>> " ==> 'XD'
>
> It's not possible to interact with caller's script-local variables easily.
> For example:
>
> caller.vim:
> let s:callers_variable = '...'
> FrameworkLocal let s:callee_variable = s:caller_variable " ???

Within a function, you can pass a local copy of the s:callers_variable:
func CallerFunc()
let var = s:callers_variable
FrameworkLocal let s:callee_variable = var
endfunc

I agree that your
:let s['callee_variable'] = s:caller_variable
works better here.

> And user-defined Ex commands (= :FrameworkLocal) are usually for
> interactive use, not for scripts.

Really? What are your reasons for this statement?

> Defining Ex commands may be annoying for users whenever they try to
> complete the names of Ex commands in Command-line mode.

Not if the name is :ZFrameworkLocal ...

And yes, :FrameworkLocal is mainly for interactive use and debugging and
should not be used in the final version of a framework "architecture".
It gives the caller too much power to manipulate the framework during
session. But it's very simple and lets you keep most of the normal
command syntax.

--
Andy

pansz

unread,
Nov 20, 2009, 1:46:10 AM11/20/09
to vim...@googlegroups.com
Kana Natsuno 写道:

>
> autoload/framework.vim:
> function! framework#get_parameter_x()
> return s:parameter_x
> endfunction
>
> plugin/engine_x.vim:
> call framework#set_parameter_x('...')
> call framework#_call_internal_stuff()
>
> Did you consider about this way? If so, why do you reject it?

This does work, But it considered tedious.

Consider: if all you want is to split an already too long script into
two, how much "s:" do you need to change? isn't there some similiar
feature like "include foobar.vim"? i.e. source some script completely
inside my own script-local namespace?


Tony Mechelynck

unread,
Dec 6, 2009, 4:09:17 AM12/6/09
to vim...@googlegroups.com, pansz
No, there isn't. ":source foobar.vim" is considered adequate for most
purposes, and when it isn't, ":call foobar#somefunc()" comes to the rescue.

Changing the "s:"-es is not a problem with

:%s/s:\|<SID>/foobar#/gc


Best regards,
Tony.
--
hundred-and-one symptoms of being an internet addict:
220. Your wife asks for sex and you tell her where to find you on IRC.

pansz

unread,
Dec 7, 2009, 8:16:42 PM12/7/09
to vim...@googlegroups.com
Tony Mechelynck 写道:
>> Consider: if all you want is to split an already too long script into
>> two, how much "s:" do you need to change? isn't there some similiar
>> feature like "include foobar.vim"? i.e. source some script completely
>> inside my own script-local namespace?
>
> No, there isn't. ":source foobar.vim" is considered adequate for most
> purposes, and when it isn't, ":call foobar#somefunc()" comes to the rescue.
>
> Changing the "s:"-es is not a problem with
>
> :%s/s:\|<SID>/foobar#/gc

;-(

So it seems that I'd better keep a long script as is.

Reply all
Reply to author
Forward
0 new messages