" @Author: Tom Link (micathom AT gmail com?subject=[vim]) " @Website: http://www.vim.org/account/profile.php?user_id=4037 " @License: GPL (see http://www.gnu.org/licenses/gpl.txt) " @Revision: 127 " :filedoc: " Provides a prototype plus some OO-like methods. let s:id_counter = 0 let s:prototype = {'_class': ['object'], '_super': [], '_id': 0} "{{{2 " :def: function! tlib#Object#New(?fields={}) " This function creates a prototype that provides some kind of " inheritance mechanism and a way to call parent/super methods. " " The usage demonstrated in the following example works best when every " class/prototype is defined in a file of its own. " " The reason for why there is a dedicated constructor function is that " this layout facilitates the use of templates and that methods are " hidden from the user. Other solutions are possible. " " EXAMPLES: > " let s:prototype = tlib#Object#New({ " \ '_class': ['FooBar'], " \ 'foo': 1, " \ 'bar': 2, " \ }) " " Constructor " function! FooBar(...) " let object = s:prototype.New(a:0 >= 1 ? a:1 : {}) " return object " endf " function! s:prototype.babble() { " echo "I think, therefore I am ". (self.foo * self.bar) ." months old." " } " " < This could now be used like this: > " let myfoo = FooBar({'foo': 3}) " call myfoo.babble() " => I think, therefore I am 6 months old. " echo myfoo.IsA('FooBar') " => 1 " echo myfoo.IsA('object') " => 1 " echo myfoo.IsA('Foo') " => 0 " echo myfoo.RespondTo('babble') " => 1 " echo myfoo.RespondTo('speak') " => 0 function! tlib#Object#New(...) "{{{3 return s:prototype.New(a:0 >= 1 ? a:1 : {}) endf function! s:prototype.New(...) dict "{{{3 let object = deepcopy(self) let s:id_counter += 1 let object._id = s:id_counter if a:0 >= 1 && !empty(a:1) " call object.Extend(deepcopy(a:1)) call object.Extend(a:1) endif return object endf function! s:prototype.Inherit(object) dict "{{{3 let class = copy(self._class) " TLogVAR class let objid = self._id for c in get(a:object, '_class', []) " TLogVAR c if index(class, c) == -1 call add(class, c) endif endfor call extend(self, a:object, 'keep') let self._class = class " TLogVAR self._class let self._id = objid " let self._super = [super] + self._super call insert(self._super, a:object) return self endf function! s:prototype.Extend(dictionary) dict "{{{3 let super = copy(self) let class = copy(self._class) " TLogVAR class let objid = self._id let thisclass = get(a:dictionary, '_class', []) for c in type(thisclass) == 3 ? thisclass : [thisclass] " TLogVAR c if index(class, c) == -1 call add(class, c) endif endfor call extend(self, a:dictionary) let self._class = class " TLogVAR self._class let self._id = objid " let self._super = [super] + self._super call insert(self._super, super) return self endf function! s:prototype.IsA(class) dict "{{{3 return index(self._class, a:class) != -1 endf function! s:prototype.IsRelated(object) dict "{{{3 return len(filter(a:object._class, 'self.IsA(v:val)')) > 1 endf function! s:prototype.RespondTo(name) dict "{{{3 " return has_key(self, a:name) && type(self[a:name]) == 2 return has_key(self, a:name) endf function! s:prototype.Super(method, arglist) dict "{{{3 for o in self._super " TLogVAR o if o.RespondTo(a:method) " let self._tmp_method = o[a:method] " TLogVAR self._tmp_method " return call(self._tmp_method, a:arglist, self) return call(o[a:method], a:arglist, self) endif endfor echoerr 'tlib#Object: Does not respond to '. a:method .': '. string(self) endf function! tlib#Object#Methods(object, ...) "{{{3 TVarArg ['pattern', '\d\+'] let o = items(a:object) call filter(o, 'type(v:val[1]) == 2 && string(v:val[1]) =~ "^function(''\\d\\+'')"') let acc = {} for e in o let id = matchstr(string(e[1]), pattern) if !empty(id) let acc[id] = e[0] endif endfor return acc endf