Skip to content

Instantly share code, notes, and snippets.

@lambdalisue
Last active March 27, 2016 08:25
Show Gist options
  • Save lambdalisue/bb408da1b3fb100d6c1a to your computer and use it in GitHub Desktop.
Save lambdalisue/bb408da1b3fb100d6c1a to your computer and use it in GitHub Desktop.
Benchmark of s:test1
| Total: 11.059016 s
| Mean: 1.105902 s
Benchmark of s:test2
| Total: 10.36895 s
| Mean: 1.036895 s
Benchmark of s:test3
| Total: 10.090889 s
| Mean: 1.009089 s
diff --git a/autoload/vital/__latest__/Data/String.vim b/autoload/vital/__latest__/Data/String.vim
index 6d28383..7915ba9 100644
--- a/autoload/vital/__latest__/Data/String.vim
+++ b/autoload/vital/__latest__/Data/String.vim
@@ -455,6 +455,50 @@ function! s:truncate(str, width) abort
return ret
endfunction
+function! s:truncate_mattn(str, width) abort
+ " Original function is from mattn.
+ " http://github.com/mattn/googlereader-vim/tree/master
+
+ if a:str =~# '^[\x00-\x7f]*$'
+ return len(a:str) < a:width ?
+ \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width)
+ endif
+
+ let ret = a:str
+ let width = s:wcswidth(a:str)
+ if width > a:width
+ let ret = s:strwidthpart_mattn(ret, a:width)
+ let width = s:wcswidth(ret)
+ endif
+
+ if width < a:width
+ let ret .= repeat(' ', a:width - width)
+ endif
+
+ return ret
+endfunction
+function! s:truncate_lambdalisue(str, width) abort
+ " Original function is from mattn.
+ " http://github.com/mattn/googlereader-vim/tree/master
+
+ if a:str =~# '^[\x00-\x7f]*$'
+ return len(a:str) < a:width ?
+ \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width)
+ endif
+
+ let ret = a:str
+ let width = s:wcswidth(a:str)
+ if width > a:width
+ let ret = s:strwidthpart_lambdalisue(ret, a:width)
+ let width = s:wcswidth(ret)
+ endif
+
+ if width < a:width
+ let ret .= repeat(' ', a:width - width)
+ endif
+
+ return ret
+endfunction
function! s:truncate_skipping(str, max, footer_width, separator) abort
let width = s:wcswidth(a:str)
@@ -467,6 +511,28 @@ function! s:truncate_skipping(str, max, footer_width, separator) abort
endif
return s:truncate(ret, a:max)
endfunction
+function! s:truncate_skipping_mattn(str, max, footer_width, separator) abort
+ let width = s:wcswidth(a:str)
+ if width <= a:max
+ let ret = a:str
+ else
+ let header_width = a:max - s:wcswidth(a:separator) - a:footer_width
+ let ret = s:strwidthpart_mattn(a:str, header_width) . a:separator
+ \ . s:strwidthpart_reverse_mattn(a:str, a:footer_width)
+ endif
+ return s:truncate_mattn(ret, a:max)
+endfunction
+function! s:truncate_skipping_lambdalisue(str, max, footer_width, separator) abort
+ let width = s:wcswidth(a:str)
+ if width <= a:max
+ let ret = a:str
+ else
+ let header_width = a:max - s:wcswidth(a:separator) - a:footer_width
+ let ret = s:strwidthpart_lambdalisue(a:str, header_width) . a:separator
+ \ . s:strwidthpart_reverse_lambdalisue(a:str, a:footer_width)
+ endif
+ return s:truncate_lambdalisue(ret, a:max)
+endfunction
function! s:strwidthpart(str, width) abort
if a:width <= 0
@@ -491,6 +557,32 @@ function! s:strwidthpart(str, width) abort
return index ? join(strarr[:index - 1], '') : ''
endfunction
+function! s:strwidthpart_mattn(str, width) abort
+ if a:width <= 0
+ return ''
+ endif
+ let s = ''
+ let w = 0
+ for cw in map(split(a:str, '\zs'), '[v:val, s:wcswidth(v:val)]')
+ if w + cw[1] > a:width
+ break
+ endif
+ let w += cw[1]
+ let s .= cw[0]
+ endfor
+ return s
+endfunction
+function! s:strwidthpart_lambdalisue(str, width) abort
+ if a:width <= 0
+ return ''
+ endif
+ let index = strlen(a:str)
+ while index > 0 && s:wcswidth(strpart(a:str, 0, index)) > a:width
+ let index -= 1
+ endwhile
+ return strpart(a:str, 0, index)
+endfunction
+
function! s:strwidthpart_reverse(str, width) abort
if a:width <= 0
return ''
@@ -514,12 +606,27 @@ function! s:strwidthpart_reverse(str, width) abort
endwhile
return index < strlen ? join(strarr[(index + 1):], '') : ''
endfunction
+function! s:strwidthpart_reverse_mattn(str, width) abort
+ return join(reverse(split(s:strwidthpart_mattn(join(reverse(split(a:str, '\zs')), ''), a:width), '\zs')), '')
+endfunction
+function! s:strwidthpart_reverse_lambdalisue(str, width) abort
+ if a:width <= 0
+ return ''
+ endif
+ let index = 0
+ let max = strlen(a:str)
+ while index <= max && s:wcswidth(strpart(a:str, index)) > a:width
+ let index += 1
+ endwhile
+ return strpart(a:str, index)
+endfunction
if v:version >= 703
" Use builtin function.
- function! s:wcswidth(str) abort
- return strwidth(a:str)
- endfunction
+ "function! s:wcswidth(str) abort
+ " return strwidth(a:str)
+ "endfunction
+ let s:wcswidth = function('strwidth')
else
function! s:wcswidth(str) abort
if a:str =~# '^[\x00-\x7f]*$'
let s:save_cpo = &cpo
set cpo&vim
let s:V = vital#of('vital')
let s:Math = s:V.import('Math')
let s:String = s:V.import('Data.String')
function! s:benchmark(fname, ...) abort
let nrepeat = get(a:000, 0, 10)
let timespans = []
let F = function(a:fname)
for n in range(1, nrepeat)
"redraw
"echohl Error
"echo printf('Processing %d/%d ...', n, nrepeat)
"echohl None
let start = reltime()
call call(F, [])
call add(timespans, str2float(reltimestr(reltime(start))))
endfor
let total = s:Math.sum(timespans)
let mean = total / len(timespans)
echomsg
echomsg 'Benchmark of ' . a:fname
echomsg '| Total: ' . string(total) . ' s'
echomsg '| Mean: ' . string(mean) . ' s'
endfunction
function! s:test1() abort
for i in range(300)
call s:String.truncate_skipping('this is a pen', 10, 1, '/')
call s:String.truncate_skipping('this is a pen', 10, 3, '...')
call s:String.truncate_skipping('this is a pen', 20, 3, '...')
call s:String.truncate_skipping('this is a pen', 10, 3, '...................')
call s:String.truncate_skipping('あいうえおかきくけこ.', 10, 1, '/')
call s:String.truncate_skipping('あいうえおかきくけこ', 10, 2, ' .. ')
call s:String.truncate_skipping('あいうえおかきくけこ', 15, 2, ' .. ')
call s:String.truncate_skipping('あいうえおかきくけこ', 20, 2, ' .. ')
endfor
endfunction
function! s:test2() abort
for i in range(300)
call s:String.truncate_skipping_mattn('this is a pen', 10, 1, '/')
call s:String.truncate_skipping_mattn('this is a pen', 10, 3, '...')
call s:String.truncate_skipping_mattn('this is a pen', 20, 3, '...')
call s:String.truncate_skipping_mattn('this is a pen', 10, 3, '...................')
call s:String.truncate_skipping_mattn('あいうえおかきくけこ.', 10, 1, '/')
call s:String.truncate_skipping_mattn('あいうえおかきくけこ', 10, 2, ' .. ')
call s:String.truncate_skipping_mattn('あいうえおかきくけこ', 15, 2, ' .. ')
call s:String.truncate_skipping_mattn('あいうえおかきくけこ', 20, 2, ' .. ')
endfor
endfunction
function! s:test3() abort
for i in range(300)
call s:String.truncate_skipping_lambdalisue('this is a pen', 10, 1, '/')
call s:String.truncate_skipping_lambdalisue('this is a pen', 10, 3, '...')
call s:String.truncate_skipping_lambdalisue('this is a pen', 20, 3, '...')
call s:String.truncate_skipping_lambdalisue('this is a pen', 10, 3, '...................')
call s:String.truncate_skipping_lambdalisue('あいうえおかきくけこ.', 10, 1, '/')
call s:String.truncate_skipping_lambdalisue('あいうえおかきくけこ', 10, 2, ' .. ')
call s:String.truncate_skipping_lambdalisue('あいうえおかきくけこ', 15, 2, ' .. ')
call s:String.truncate_skipping_lambdalisue('あいうえおかきくけこ', 20, 2, ' .. ')
endfor
endfunction
command! Test1 call s:benchmark('s:test1')
command! Test2 call s:benchmark('s:test2')
command! Test3 call s:benchmark('s:test3')
function! s:test() abort
call s:benchmark('s:test1')
call s:benchmark('s:test2')
call s:benchmark('s:test3')
endfunction
command! Test call s:test()
let &cpo = s:save_cpo
unlet! s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment