From 438f11b5345258c4cfbf4b5ae3293d13980516c2 Mon Sep 17 00:00:00 2001 From: lymslive <403708621@qq.com> Date: Thu, 3 May 2018 10:38:25 +0800 Subject: [PATCH] example source --- example/autoload/delaytwice.vim | 11 ++ example/clet.vim | 46 ++++++++ example/closure.vim | 174 ++++++++++++++++++++++++++++ example/cmd.vim | 3 + example/delaytwice.vim | 29 +++++ example/fcommand.vim | 34 ++++++ example/frange.vim | 23 ++++ example/funcref.vim | 196 ++++++++++++++++++++++++++++++++ example/hello1.vim | 11 ++ example/hello2.vim | 4 + example/t_abort1.vim | 10 ++ example/vararg.vim | 50 ++++++++ readme.md | 4 + 13 files changed, 595 insertions(+) create mode 100644 example/autoload/delaytwice.vim create mode 100644 example/clet.vim create mode 100644 example/closure.vim create mode 100644 example/cmd.vim create mode 100644 example/delaytwice.vim create mode 100644 example/fcommand.vim create mode 100644 example/frange.vim create mode 100644 example/funcref.vim create mode 100644 example/hello1.vim create mode 100644 example/hello2.vim create mode 100644 example/t_abort1.vim create mode 100644 example/vararg.vim diff --git a/example/autoload/delaytwice.vim b/example/autoload/delaytwice.vim new file mode 100644 index 0000000..d3c76c0 --- /dev/null +++ b/example/autoload/delaytwice.vim @@ -0,0 +1,11 @@ +" foo: +function! delaytwice#Foo() abort "{{{ + echo 'in delaytwice#Foo()' +endfunction "}}} + +" bar: +function! delaytwice#Bar() abort "{{{ + echo 'in delaytwice#Bar()' +endfunction "}}} + +echo 'vimllearn/autoload/delaytwice.vim loaded' diff --git a/example/clet.vim b/example/clet.vim new file mode 100644 index 0000000..02f7b3b --- /dev/null +++ b/example/clet.vim @@ -0,0 +1,46 @@ +" File: ~/.vim/vimllearn/clet.vim +" custom VimL grammar command + +function! ParseLet(args) + let l:lsMatch = split(a:args, '\s*=\s*') + if len(l:lsMatch) < 2 + return '' + endif + let l:value = remove(l:lsMatch, -1) + let l:lsCmd = [] + for l:var in l:lsMatch + let l:cmd = 'let ' . l:var . ' = ' . l:value + call add(l:lsCmd, l:cmd) + endfor + return join(l:lsCmd, ' | ') +endfunction + +command! -nargs=+ LET execute ParseLet() + +function! TestLet() + LET l:x = y = z = 'abc' + echo 'l:x =' l:x 'x =' x + echo 'l:y =' l:y 'y =' y + echo 'l:z =' l:z 'z =' z +endfunction +call TestLet() +echo 'x =' x 'y =' y 'z =' z + +function! ParseBreak(args) + if empty(a:args) + return 'break' + endif + let l:cmd = 'if ' . a:args + let l:lsCmd = [l:cmd, 'break', 'endif'] + return join(l:lsCmd, ' | ') + " return join(l:lsCmd, "\n") +endfunction + +command! -nargs=+ BREAKIF execute ParseBreak() + +for i in range(10) + BREAKIF i >= 5 + if i >= 5 | break | endif + echo i +endfor +" break 用 execute 有问题 diff --git a/example/closure.vim b/example/closure.vim new file mode 100644 index 0000000..4013bfe --- /dev/null +++ b/example/closure.vim @@ -0,0 +1,174 @@ +function! Foo() + let x = 0 + function! Bar() closure + let x += 1 + return x + endfunction + return funcref('Bar') +endfunction + +function! Goo() + let x = 0 + function! Bar() closure + let x += 2 + return x + endfunction + return function('Bar') +endfunction + +" funcref 与 function 都有效 +" Bar() 也是全局函数 + +echo 'Fn = Foo()' +let Fn = Foo() +echo Fn() +echo Fn() +echo Bar() +echo Fn() + +" 交替使用有效 +echo 'Gn = Foo()' +let Gn = Goo() +echo Gn() +echo Gn() +echo Bar() +echo Gn() + +function! Bar() + return 'Bar() redefined' +endfunction + +echo Bar() +echo Fn() +echo Gn() + +" +" 重定义对 function() 有影响,对 funcref() 影响 + +" 对比 s: 变量与函数 +" +let s:x = 0 +function! s:Bar() " closure 不能放在顶层 E932 + let s:x += 1 + return s:x +endfunction + +echo 's:Bar()' +echo s:Bar() +echo s:Bar() +echo s:Bar() + +" 工厂函数 +" 闭包独立性 +" +function! FGoo(base) + let x = a:base + function! Bar1_cf() closure + let x += 1 + return x + endfunction + function! Bar2_cf() closure + let x += 2 + return x + endfunction + return [funcref('Bar1_cf'), funcref('Bar2_cf')] +endfunction + +echo 'FGoo(base)' +let [Fn, X_] = FGoo(10) +echo Fn() +echo Fn() +echo Fn() +let [X_, Gn] = FGoo(20) +echo Gn() +echo Gn() +echo Gn() +echo Fn() +echo Fn() + +" 偏包引用 +" +echo 'partial function reference' + +function! Full(x, y, z) + echo 'Full called:' a:x a:y a:z +endfunction + +let Part = function('Full', [3, 4]) +call Part(5) +echo Part +" call Part() +" call Part(3, 4, 5) + +function! FullPartial() + let x = 3 + let y = 4 + function! Part_cf(z) closure + let z = a:z + return Full(x, y, z) + endfunction + return funcref('Part_cf') +endfunction + +let Part = FullPartial() +call Part(5) +echo Part + +function! FuncPartial(fun, arg) + " let l:arg_closure = a:arg + function! Part_cf(...) closure + " let l:arg_passing = a:000 + " let l:arg_all = l:arg_closure + l:arg_passing + return call(a:fun, a:arg + a:000) + endfunction + return funcref('Part_cf') +endfunction + +let Part = FuncPartial('Full', [3, 4]) +call Part(5) +echo Part + +" lambda 表达式 +" +echo 'lambda expression' + +if 1 +function! Distance(point) abort + let x = a:point[0] + let y = a:point[1] + return x*x + y*y +endfunction +else + let Distance = {pt -> pt[0] * pt[0] + pt[1] * pt[1]} +endif + +" echo Distance +echo Distance([3,4]) + +function! MaxDistance(A, B, C) abort + let l:Distance = {pt -> pt[0] * pt[0] + pt[1] * pt[1]} + let [A, B, C] = [a:A, a:B, a:C] + let e1 = [A[0] - B[0], A[1] - B[1]] + let e2 = [A[0] - C[0], A[1] - C[1]] + let e3 = [B[0] - C[0], B[1] - C[1]] + let d1 = Distance(e1) + let d2 = l:Distance(e2) + let d3 = Distance(e3) + if d1 >= d2 && d1 >= d3 + return d1 + elseif d2 >= d1 && d2 >= d3 + return d2 + else + return d3 + endif +endfunction + +delfunction Distance +echo MaxDistance([2,8], [4,4], [5,10]) + +finish + +" +" 在 MaxDistance 中调用 Distance lambda 时,须定义为局部函数引用变量 +" 因 Distance() 调用只搜索 l:Distance 局部变量或全局函数,并不会搜索全局函数引 +" 用变量 diff --git a/example/cmd.vim b/example/cmd.vim new file mode 100644 index 0000000..ee95980 --- /dev/null +++ b/example/cmd.vim @@ -0,0 +1,3 @@ +: echomsg 'before error' +: echomsg error +: echomsg 'after error' diff --git a/example/delaytwice.vim b/example/delaytwice.vim new file mode 100644 index 0000000..f2c430a --- /dev/null +++ b/example/delaytwice.vim @@ -0,0 +1,29 @@ + +if !exists('s:load_first') + command -nargs=* MYcmd call DT_foo() + nnoremap :call DT_foo() + execute 'autocmd FuncUndefined DT_* source ' . expand('') + let s:load_first = 1 + finish +endif + +if exists('s:load_second') + finish +endif + +function! DT_foo() abort + " TODO: +endfunction +function! DT_bar() abort + " TODO: +endfunction + +let s:load_second = 1 + +execute 'autocmd FuncUndefined *#* call MyAutoFunc()' + +function! MyAutoFunc() abort + echo 'in MyAutoFunc()' + " TODO: + source ~/.vim/vimllearn/autoload/delaytwice.vim +endfunction diff --git a/example/fcommand.vim b/example/fcommand.vim new file mode 100644 index 0000000..c526016 --- /dev/null +++ b/example/fcommand.vim @@ -0,0 +1,34 @@ +" File: ~/.vim/vimllearn/fcommand.vim + +function! NumberLine() abort range + for l:line in range(a:firstline, a:lastline) + let l:sLine = getline(l:line) + let l:sLine = l:line . ' ' . l:sLine + call setline(l:line, l:sLine) + endfor +endfunction + +command! -range=% NumberLine call NumberLine() + +function! NumberRelate(count) abort + let l:cursor = line('.') + let l:eof = line('$') + for l:count in range(0, a:count) + let l:line = l:cursor + l:count + if l:line > l:eof + break + endif + let l:sLine = getline(l:line) + let l:sLine = l:count . ' ' . l:sLine + call setline(l:line, l:sLine) + endfor +endfunction + +command! -count NumberRelate call NumberRelate() +finish + +测试行 +测试行 +测试行 +测试行 +测试行 diff --git a/example/frange.vim b/example/frange.vim new file mode 100644 index 0000000..90380c1 --- /dev/null +++ b/example/frange.vim @@ -0,0 +1,23 @@ +" File: ~/.vim/vimllearn/frange.vim + +function! NumberLine() abort + let l:sLine = getline('.') + let l:sLine = line('.') . ' ' . l:sLine + call setline('.', l:sLine) +endfunction + +function! NumberLine2() abort range + for l:line in range(a:firstline, a:lastline) + let l:sLine = getline(l:line) + let l:sLine = l:line . ' ' . l:sLine + call setline(l:line, l:sLine) + endfor +endfunction + +finish + +测试行 +测试行 +测试行 +测试行 +测试行 diff --git a/example/funcref.vim b/example/funcref.vim new file mode 100644 index 0000000..8d15222 --- /dev/null +++ b/example/funcref.vim @@ -0,0 +1,196 @@ +function! Sum(x, y, ...) + let l:sum = a:x + a:y + for l:arg in a:000 + let l:sum += l:arg + endfor + return l:sum +endfunction + +function! Prod(x, y, ...) + let l:prod = a:x * a:y + for l:arg in a:000 + let l:prod = l:prod * l:arg + endfor + return l:prod +endfunction + +function! CalculateR(operator, ...) + if a:operator ==# '+' + let l:Fnr = function('Sum') + elseif a:operator ==# '*' + let l:Fnr = function('Prod') + endif + + let l:result = call(l:Fnr, a:000) + return l:result +endfunction + +let s:fnrSum = function('Sum') +let s:fnrProd = function('Prod') + +function! CalculateRs(operator, ...) + if a:operator ==# '+' + let l:Fnr = s:fnrSum + elseif a:operator ==# '*' + let l:Fnr = s:fnrProd + endif + + let l:result = call(l:Fnr, a:000) + return l:result +endfunction + +function! s:sum(...) + let l:sum = 0 + for l:arg in a:000 + let l:sum += l:arg + endfor + return l:sum +endfunction + +function! s:prod(...) + let l:prod = 1 + for l:arg in a:000 + let l:prod = l:prod * l:arg + endfor + return l:prod +endfunction + +let s:fnrSum = function('s:sum') +let s:fnrProd = function('s:prod') + +echo s:fnrSum(1,2,3,4) +echo s:fnrProd(1,2,3,4) + +" let s:sum = function('s:sum') +" let s:prod = function('s:prod') + +let s:sum = '1+2+3+4' +let s:prod = '1*2*3*4' + +echo s:sum(1,2,3,4) +echo s:prod(1,2,3,4) + +" 将函数引用保存在列表中 +let s:operator = [function('s:sum'), function('s:prod')] +function! CalculateA(...) + for l:Operator in s:operator + let l:result = call(l:Operator, a:000) + echo l:result + endfor +endfunction + +" 将函数引用保存在字典中 +let s:dOperator = {'desc': 'some function on varargins'} +let s:dOperator['+'] = function('s:sum') +let s:dOperator['*'] = function('s:prod') + +function! CalculateD(operator, ...) abort + let l:Fnr = s:dOperator[a:operator] + let l:result = call(l:Fnr, a:000) + return l:result +endfunction + +" 保存在成员键中 +let s:dOperator.sumFnr = s:dOperator['+'] +let s:dOperator.prodFnr = s:dOperator['*'] +echo s:dOperator.sumFnr(1, 2, 3, 4) +echo s:dOperator.prodFnr(1, 2, 3, 4) + +" 直接定义函数键 +function s:dOperator.sum(...) + let l:sum = 0 + for l:arg in a:000 + let l:sum += l:arg + endfor + return l:sum +endfunction + +function! s:dOperator.prod(...) + let l:prod = 1 + for l:arg in a:000 + let l:prod = l:prod * l:arg + endfor + return l:prod +endfunction + +echo s:dOperator.sum(1, 2, 3, 4) +echo s:dOperator.prod(1, 2, 3, 4) + +" 不能将字典函数引用赋值给普通函数引用 +" let g:Fnr = s:dOperator.sum +" echo g:Fnr(1,2,3,4) + +" 合法 +let g:Fnr = s:dOperator.sumFnr +echo g:Fnr(1,2,3,4) + +let s:dOperator.PI = 3.14 +function! s:dOperator.area(r) + return self.PI * a:r * a:r +endfunction + +echo s:dOperator.area(2) + +let s:Math = {} +let s:Math.PI = 3.14159 +let s:Math.Area = s:dOperator.area +echo s:Math.Area(2) + +" let g:Fnr = s:dOperator.area +" echo g:Fnr(2) + +function! s:area(width, height) dict + return a:width * a:height +endfunction + +" echo s:area(3, 4) |" 出错 +echo call('s:area', [5, 6], {}) +" echo call('s:area', [5, 6]) + +let s:Rect = {} +let s:Rect.area = function('s:area') +echo s:Rect.area(3, 4) |" 正确 + +function! s:area() dict + return self.width * self.height +endfunction + +let s:Rect.width = 3 +let s:Rect.height = 4 +echo s:Rect.area() + +echo call('s:area', [], s:Rect) +echo call(function('s:area'), [], s:Rect) + +" 调试信息观察 + +function! s:Rect.debug1() dict abort + echo expand('') + Hello Vim, 我在这里就是个错误 +endfunction + +function! s:debug2() abort + echo expand('') + Hello Vim, 我来这里也是个错误 +endfunction +let s:Rect.debug2 = function('s:debug2') + +function! s:Rect.test() dict " abort + echo expand('') + call self.debug1() + call self.debug2() +endfunction + +function! s:test() abort + echo expand('') + call s:Rect.test() +endfunction + +function! Test() abort + echo expand('') + call s:test() +endfunction + +echo expand('') + +" echo s: diff --git a/example/hello1.vim b/example/hello1.vim new file mode 100644 index 0000000..a7ed71f --- /dev/null +++ b/example/hello1.vim @@ -0,0 +1,11 @@ +" 文件:hello1.vim +" 用途:VimL hello world 示例 +" 作者:lymslive +" 时间:2017-08 + +echo 'Hello World!' + +finish + +脚本结束了,可以随便浪~~ +不管写些什么乱七八糟的都木有关系。 diff --git a/example/hello2.vim b/example/hello2.vim new file mode 100644 index 0000000..996da54 --- /dev/null +++ b/example/hello2.vim @@ -0,0 +1,4 @@ +let s:hello = 1 +let s:world = 2 +let s:hello_world = s:hello + s:world +echo s: diff --git a/example/t_abort1.vim b/example/t_abort1.vim new file mode 100644 index 0000000..7ff5983 --- /dev/null +++ b/example/t_abort1.vim @@ -0,0 +1,10 @@ +: function! Foo() abort +: echomsg 'before error' +: echomsg error +: echomsg 'after error' +: endfunction +: +: echomsg 'before call Foo()' +: call Foo() +: echomsg 'after call Foo()' + diff --git a/example/vararg.vim b/example/vararg.vim new file mode 100644 index 0000000..5c76e6d --- /dev/null +++ b/example/vararg.vim @@ -0,0 +1,50 @@ +function! UseVarargin(named, ...) + echo 'named argin: ' . string(a:named) + + if a:0 >= 1 + echo 'first varargin: ' . string(a:1) + endif + if a:0 >= 2 + echo 'second varargin: ' . string(a:2) + endif + + echo 'have varargin: ' . a:0 + for l:arg in a:000 + echo 'iterate varargin: ' . string(l:arg) + endfor +endfunction + +function! Join(list, ...) + if a:0 > 0 + let l:sep = a:1 + else + let l:sep = ',' + endif + return join(a:list, l:sep) +endfunction + +function! Calculate(operator, ...) + echo Join(a:000, a:operator) + if a:operator ==+ '+' + " let l:result = Sum(...) + elseif a:operator ==# '*' + " let l:result = Prod(...) + endif + return l:result +endfunction + +function! Calculate(operator, ...) + if a:0 < 2 + echoerr 'expect at leat 2 operand' + return + endif + + echo Join(a:000, a:operator) + if a:operator ==+ '+' + let l:result = call('Sum', a:000) + elseif a:operator ==# '*' + let l:result = call('Prod', a:000) + endif + + return l:result +endfunction diff --git a/readme.md b/readme.md index d4d3332..3eb0d35 100644 --- a/readme.md +++ b/readme.md @@ -4,3 +4,7 @@ 稿了,但高级应用尚未完成。 [进入目录](./content.md) + +初稿在本地我用自己的笔记插件 [vnote](https://github.com/lymslive/vnote) 写的, +保存在笔记本 [notebook](https://github.com/lymslive/notebook)。 +然后将这个较为系统化的教程独立出来,可能进行后续的修改与调整。