diff options
Diffstat (limited to 'stow/vim/dot-vim/plugin')
-rw-r--r-- | stow/vim/dot-vim/plugin/SWTC.vim | 339 | ||||
-rw-r--r-- | stow/vim/dot-vim/plugin/dragvisuals.vim | 345 | ||||
-rw-r--r-- | stow/vim/dot-vim/plugin/rng.vim | 83 |
3 files changed, 767 insertions, 0 deletions
diff --git a/stow/vim/dot-vim/plugin/SWTC.vim b/stow/vim/dot-vim/plugin/SWTC.vim new file mode 100644 index 0000000..9459e92 --- /dev/null +++ b/stow/vim/dot-vim/plugin/SWTC.vim @@ -0,0 +1,339 @@ +" Vim global plugin for Star Wars crawls +" Maintainer: Damian Conway +" License: This file is placed in the public domain. + +"###################################################################### +"## ## +"## To use: ## +"## ## +"## :SWTC <filename> ## +"## ## +"## See file 'intro.swtc' for the crawl-specification syntax ## +"## ## +"###################################################################### + + +" If already loaded, we're done... +if exists("loaded_SWcrawl") + finish +endif +let loaded_SWcrawl = 1 + +" Preserve external compatibility options, then enable full vim compatibility... +let s:save_cpo = &cpo +set cpo&vim + +" Set up the actual colon command... +command! -nargs=1 -complete=file SWTC call SWcrawl(<f-args>) + + +" Implementation.... + +let s:CRAWL_SPEED = 1 "(lines per second) +let s:STAR_DENSITY = 50 "(pixels per star, i.e. 1 star per STAR_DENSITY pixels) +let s:STARFIELD_HEIGHT = 2 "(screens deep) + +let s:LOGO_LINE1 = '^\s*\[\zs.*\ze\]\s*$' +let s:LOGO_LINE2 = '^\s*\[\[\zs.*\ze\]\]\s*$' +let s:LOGO_LINE3 = '^\s*\[\[\[\zs.*\ze\]\]\]\s*$' +let s:LOGO_LINE4 = '^\s*\[\[\[\[\zs.*\ze\]\]\]\]\s*$' +let s:CENTRED_CRAWL_LINE = '^\s*[>]\s*\zs.\{-}\ze\s*[<]\s*$' +let s:CRAWL_LINE = '^\s*[|]\s*\zs.\{-}\ze\s*[|]\s*$' +let s:PREFACE_LINE = '^\s*\zs.\{-}\ze\s*$' + +highlight SWC_PREFACE ctermfg=cyan +highlight SWC_FADE_LIGHT ctermfg=cyan +highlight SWC_FADE_DARK ctermfg=blue +highlight SWC_LOGO ctermfg=yellow cterm=bold +highlight SWC_CRAWL ctermfg=yellow +highlight SWC_STAR ctermfg=white +highlight SWC_BLACK ctermfg=black ctermbg=black + +let s:PREFACE_POS = { 'x': 10, 'y': 5 } + +function! SWcrawl (textsource) + " Load preface, logo, and text to be crawled... + let preface = [] + let logo1 = [] + let logo2 = [] + let logo3 = [] + let logo4 = [] + let crawl = [] + let centred = [] + let max_crawl_width = 0 + for nextline in readfile(a:textsource) + " Ignore blank lines... + if nextline =~ '^\s*$' + continue + + " Lines in [...] are logo components... + elseif nextline =~ s:LOGO_LINE4 + let logo4 += [ matchstr(nextline, s:LOGO_LINE4) ] + elseif nextline =~ s:LOGO_LINE3 + let logo3 += [ matchstr(nextline, s:LOGO_LINE3) ] + elseif nextline =~ s:LOGO_LINE2 + let logo2 += [ matchstr(nextline, s:LOGO_LINE2) ] + elseif nextline =~ s:LOGO_LINE1 + let logo1 += [ matchstr(nextline, s:LOGO_LINE1) ] + + " Lines in |...| are crawl components... + elseif nextline =~ s:CRAWL_LINE + let next_crawl = matchstr(nextline, s:CRAWL_LINE) + if strlen(next_crawl) > max_crawl_width + let max_crawl_width = strlen(substitute(next_crawl,'\s\+',' ','g')) + endif + let crawl += [ next_crawl ] + let centred += [ 0 ] + + " Lines in >...< are centred crawl components... + elseif nextline =~ s:CENTRED_CRAWL_LINE + let next_crawl = matchstr(nextline, s:CENTRED_CRAWL_LINE) + if strlen(next_crawl) > max_crawl_width + let max_crawl_width = strlen(substitute(next_crawl,'\s\+',' ','g')) + endif + let crawl += [ next_crawl ] + let centred += [ 1 ] + + " Anything else is preface... + else + let preface += [ substitute(matchstr(nextline, s:PREFACE_LINE), "^\s*", repeat(" ",s:PREFACE_POS.x), '') ] + + endif + endfor + + " Ensure all logos available... + let logo1 = len(logo1) ? logo1 : ["YOUR", "LOGO", "HERE"] + let logo2 = len(logo2) ? logo2 : copy(logo1) + let logo3 = len(logo3) ? logo3 : copy(logo2) + let logo4 = len(logo4) ? logo4 : copy(logo3) + + " Save current buffer for final transition effect... + let original_buffer = getline(1,'$') + + " Switch to a new buffer... + let prev_matches = getmatches() + enew! + let b:WIN = { 'x' : winwidth(0), 'y' : winheight(0) } + call setline(1, repeat([""], b:WIN.y + 1)) + + " And hide annoyances... + set lcs= + let old_rulerformat = &rulerformat + let &rulerformat="%#SWC_BLACK#%l" + echo "" + + " Generate starfield... + let stars = SWC_gen_stars() + + " Clear screen... + call setline(1, repeat([""], s:STARFIELD_HEIGHT * b:WIN.y) + original_buffer) + redraw + sleep 2 + + " Start with preface... + call matchadd('SWC_PREFACE', '.', 100) + call setline(s:PREFACE_POS.y, preface) + echo "" + redraw + sleep 5 + + " Clean up... + call clearmatches() + call setline(s:PREFACE_POS.y, repeat([""], len(preface))) + echo "" + redraw + sleep 1 + + " Then show logo receding at centre of screen... + call clearmatches() + call matchadd('SWC_BLACK', '*', 102) + call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) + call matchadd('SWC_LOGO', '.', 100) + call SWC_draw_logo(logo1) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 3 + + " Push it away... + call setline(1, repeat([""], b:WIN.y)) + call SWC_draw_logo(logo2) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 500m + + call setline(1, repeat([""], b:WIN.y)) + call SWC_draw_logo(logo3) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 500m + + call setline(1, repeat([""], b:WIN.y)) + call SWC_draw_logo(logo4) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 500m + + + " Clean up... + call clearmatches() + call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) + call setline(1, repeat([""], b:WIN.y)) + call SWC_paint_stars(stars) + echo "" + redraw + sleep 2 + + " Run crawl... + call clearmatches() + call matchadd('SWC_CRAWL', '.', 100) + call matchadd('SWC_STAR', '\s\zs[.]\ze\s', 101) + for offset_from_bottom in range(1, len(crawl) + b:WIN.y) + let crawl_line = offset_from_bottom < b:WIN.y ? 0 : offset_from_bottom - b:WIN.y + 1 + for screen_line in range(1, b:WIN.y) + if screen_line >= b:WIN.y - offset_from_bottom && crawl_line < len(crawl) + let padded_line = SWC_pad(crawl[crawl_line], screen_line, centred[crawl_line], max_crawl_width) + call setline(screen_line, padded_line) + let crawl_line += 1 + else + call setline(screen_line, "") + endif + endfor + call SWC_paint_stars(stars) + echo "" + redraw + exec 'sleep ' . s:trunc(1000/s:CRAWL_SPEED) . 'm' + if getchar(0) || offset_from_bottom > len(crawl) && padded_line !~ '\S' + break + endif + endfor + + " Pan starfield down... + call matchadd('SWC_FADE_DARK', '[^.]', 200) + sleep 200m + for offset_from_top in range(1, s:STARFIELD_HEIGHT * b:WIN.y) + 1delete + redraw + exec 'sleep ' . (200 - 2 * offset_from_top) . 'm' + endfor + sleep 200m + + + " Switch back to previous buffer and restore normal highlighting... + edit! # + call setmatches(prev_matches) + let &rulerformat = old_rulerformat + redraw + +endfunction + +function s:trunc (n) + return str2nr(string( a:n )) +endfunction + +function! SWC_draw_logo (logo) + let logo = copy(a:logo) + + " Find centre for logo... + let logo_width = 0 + for line in logo + if strlen(line) > logo_width + let logo_width = strlen(line) + endif + endfor + let logo_pos_x = (b:WIN.x - logo_width) / 2 + let logo_pos_y = (b:WIN.y - len(logo)) / 2 + + " Move logo to centre... + call map(logo, "repeat(' ', logo_pos_x) . v:val") + + " Draw logo + call setline(logo_pos_y, logo) + +endfunction + +function! SWC_pad (text, y_pos, centred, max_text_width) + + " Does this need padding??? + let words = split(a:text, '\s\+') + if len(words) < 1 + return a:text + endif + + " How many unpadded characters are there??? + let unpadded_width = 0 + for word in words + let unpadded_width += strlen(word) + endfor + + " How much padding is needed??? + let rel_y = (2.0 * a:y_pos / b:WIN.y) - 1.0 + let stretched_width = s:trunc( a:max_text_width + rel_y * (b:WIN.x - a:max_text_width) ) + let required_padding = max([ 0, stretched_width - unpadded_width ]) + let indent = (b:WIN.x - stretched_width) / 2 + let gap_count = len(words) - 1 + + " Is this a last line??? + let tight = a:centred || strlen(a:text) < 0.9 * a:max_text_width + + " Insert padding... + if a:y_pos >= b:WIN.y/2 + let min_padding_needed_for = gap_count + if tight + let min_pad_per_gap = max([ 1, s:trunc(rel_y * 6.0) ]) + else + let min_pad_per_gap = max([ 1, required_padding / gap_count ]) + let leftover_padding = required_padding - gap_count * min_pad_per_gap + let min_padding_needed_for = min([ gap_count, gap_count - leftover_padding ]) + endif + let padded_text = join(words[0 : min_padding_needed_for], repeat(" ", min_pad_per_gap)) + \ . repeat(" ", min_pad_per_gap+1) + \ . join(words[min_padding_needed_for+1 : -1], repeat(" ", min_pad_per_gap+1)) + let padded_text = substitute(padded_text, '\s*$', '', '') + + " Or remove chars (in the distance)... + elseif a:text =~ '\S' +" let delta = s:trunc( 8.0 * (b:WIN.y/2 - a:y_pos) ) +" let greeked_len = max([ 0, strlen(substitute(a:text, '^\s*\|\s*$', '', 'g')) - delta ]) + let greeked_len = tight ? stretched_width * (unpadded_width + gap_count) / a:max_text_width : stretched_width + let padded_text = repeat('~', greeked_len) + + " Or ignore it... + else + let padded_text = "" + + endif + + " Indent to centre... + let padded_text = substitute(padded_text, '\s*$', '', '') + let max_ever_padding = b:WIN.x - a:max_text_width + let indent = a:centred ? (b:WIN.x - strlen(padded_text))/2 + \ : indent + return repeat(" ", indent) . padded_text +endfunction + +function! SWC_gen_stars () + let star_count = b:WIN.x * s:STARFIELD_HEIGHT * b:WIN.y / s:STAR_DENSITY + let stars = [] + for n in range(star_count) + let x = RandomNumber(b:WIN.x) + 1 + let y = RandomNumber(s:STARFIELD_HEIGHT * b:WIN.y) + 1 + let stars += [{'y':y,'x':x}] + endfor + return stars +endfunction + +function! SWC_paint_stars (stars) + let max_x = b:WIN.x + for star in a:stars + let line = strpart(getline(star.y) . repeat(" ", max_x), 0, max_x) + let line = substitute(line, '\s\zs\%'.(star.x-1).'c\s\ze\s', '.', '') + call setline(star.y, line) + endfor +endfunction + +" Restore previous external compatibility options +let &cpo = s:save_cpo diff --git a/stow/vim/dot-vim/plugin/dragvisuals.vim b/stow/vim/dot-vim/plugin/dragvisuals.vim new file mode 100644 index 0000000..12c4f5d --- /dev/null +++ b/stow/vim/dot-vim/plugin/dragvisuals.vim @@ -0,0 +1,345 @@ +" Vim global plugin for dragging virtual blocks +" Last change: Tue Jul 24 07:19:35 EST 2012 +" Maintainer: Damian Conway +" License: This file is placed in the public domain. + +"######################################################################### +"## ## +"## Add the following (uncommented) to your .vimrc... ## +"## ## +"## runtime plugin/dragvisuals.vim ## +"## ## +"## vmap <expr> <LEFT> DVB_Drag('left') ## +"## vmap <expr> <RIGHT> DVB_Drag('right') ## +"## vmap <expr> <DOWN> DVB_Drag('down') ## +"## vmap <expr> <UP> DVB_Drag('up') ## +"## vmap <expr> D DVB_Duplicate() ## +"## ## +"## " Remove any introduced trailing whitespace after moving... ## +"## let g:DVB_TrimWS = 1 ## +"## ## +"## Or, if you use the arrow keys for normal motions, choose ## +"## four other keys for block dragging. For example: ## +"## ## +"## vmap <expr> h DVB_Drag('left') ## +"## vmap <expr> l DVB_Drag('right') ## +"## vmap <expr> j DVB_Drag('down') ## +"## vmap <expr> k DVB_Drag('up') ## +"## ## +"## Or: ## +"## ## +"## vmap <expr> <S-LEFT> DVB_Drag('left') ## +"## vmap <expr> <S-RIGHT> DVB_Drag('right') ## +"## vmap <expr> <S-DOWN> DVB_Drag('down') ## +"## vmap <expr> <S-UP> DVB_Drag('up') ## +"## ## +"## Or even: ## +"## ## +"## vmap <expr> <LEFT><LEFT> DVB_Drag('left') ## +"## vmap <expr> <RIGHT><RIGHT> DVB_Drag('right') ## +"## vmap <expr> <DOWN><DOWN> DVB_Drag('down') ## +"## vmap <expr> <UP><UP> DVB_Drag('up') ## +"## ## +"######################################################################### + + +" If already loaded, we're done... +if exists("loaded_dragvirtualblocks") + finish +endif +let loaded_dragvirtualblocks = 1 + +" Preserve external compatibility options, then enable full vim compatibility... +let s:save_cpo = &cpo +set cpo&vim + +"====[ Implementation ]==================================== + +" Toggle this to stop trimming on drags... +if !exists('g:DVB_TrimWS') + let g:DVB_TrimWS = 1 +endif + +function! DVB_Drag (dir) + " No-op in Visual mode... + if mode() ==# 'v' + return "\<ESC>gv" + + " Do Visual Line drag indirectly via temporary nmap + " (to ensure we have access to block position data)... + elseif mode() ==# 'V' + " Set up a temporary convenience... + exec "nnoremap <silent><expr><buffer> M \<SID>Drag_Lines('".a:dir."')" + + " Return instructions to implement the move and reset selection... + return '"vyM' + + " Otherwise do Visual Block drag indirectly via temporary nmap + " (to ensure we have access to block position data)... + else + " Set up a temporary convenience... + exec "nnoremap <silent><expr><buffer> M \<SID>Drag_Block('".a:dir."')" + + " Return instructions to implement the move and reset selection... + return '"vyM' + endif +endfunction + +" Duplicate selected block and place to the right... +function! DVB_Duplicate () + exec "nnoremap <silent><expr><buffer> M \<SID>DuplicateBlock()" + return '"vyM' +endfunction + +function! s:DuplicateBlock () + nunmap <buffer> M + " Locate block boundaries... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Identify special '$' blocks... + let dollar_block = 0 + let start_col = min([col_left+offset_left, col_right+offset_right]) + let end_col = max([col_left+offset_left, col_right+offset_right]) + let visual_width = end_col - start_col + 1 + for visual_line in split(getreg("v"),"\n") + if strlen(visual_line) > visual_width + let dollar_block = 1 + let visual_width = strlen(visual_line) + endif + endfor + let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') + + set virtualedit=all + return 'gv'.square_up.'yPgv' + \. (visual_width-dollar_block) . 'lo' . (visual_width-dollar_block) . 'l' + \. "y:set virtualedit=block\<CR>gv" + \. (dollar_block ? 'o$' : '') +endfunction + + +" Kludge to hide change reporting inside implementation... +let s:NO_REPORT = ":let b:DVB_report=&report\<CR>:let &report=1000000000\<CR>" +let s:PREV_REPORT = ":let &report = b:DVB_report\<CR>" + + +" Drag in specified direction in Visual Line mode... +function! s:Drag_Lines (dir) + " Clean up the temporary convenience... + nunmap <buffer> M + + " Locate block being shifted... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Drag entire lines left if possible... + if a:dir == 'left' + " Are all lines indented at least one space??? + let lines = getline(line_left, line_right) + let all_indented = match(lines, '^[^ ]') == -1 + nohlsearch + + " If can't trim one space from start of each line, be a no-op... + if !all_indented + return 'gv' + + " Otherwise drag left by removing one space from start of each line... + else + return s:NO_REPORT + \ . "gv:s/^ //\<CR>" + \ . s:PREV_REPORT + \ . "gv" + endif + + " To drag entire lines right, add a space in column 1... + elseif a:dir == 'right' + return s:NO_REPORT + \ . "gv:s/^/ /\<CR>:nohlsearch\<CR>" + \ . s:PREV_REPORT + \ . "gv" + + " To drag entire lines upwards... + elseif a:dir == 'up' + let EOF = line('$') + + " Can't drag up if at first line... + if line_left == 1 || line_right == 1 + return 'gv' + + " Needs special handling at EOF (because cursor moves up on delete)... + elseif line_left == EOF || line_right == EOF + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + return s:NO_REPORT + \ . 'gvxP' + \ . s:PREV_REPORT + \ . 'V' . select_extra + + " Otherwise just cut-move-paste-reselect... + else + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + return s:NO_REPORT + \ . 'gvxkP' + \ . s:PREV_REPORT + \ . 'V' . select_extra + endif + + " To drag entire lines downwards... + elseif a:dir == 'down' + let EOF = line('$') + + " This is how much extra we're going to have to reselect... + let height = line_right - line_left + let select_extra = height ? height . 'j' : "" + + " Needs special handling at EOF (to push selection down into new space)... + if line_left == EOF || line_right == EOF + return "O\<ESC>gv" + + " Otherwise, just cut-move-paste-reselect... + else + return s:NO_REPORT + \ . 'gvxp' + \ . s:PREV_REPORT + \ . 'V' . select_extra + endif + + endif +endfunction + +" Drag in specified direction in Visual Block mode... +function! s:Drag_Block (dir) + " Clean up the temporary convenience... + nunmap <buffer> M + + " Locate block being shifted... + let [buf_left, line_left, col_left, offset_left ] = getpos("'<") + let [buf_right, line_right, col_right, offset_right] = getpos("'>") + + " Identify special '$' blocks... + let dollar_block = 0 + let start_col = min([col_left+offset_left, col_right+offset_right]) + let end_col = max([col_left+offset_left, col_right+offset_right]) + let visual_width = end_col - start_col + 1 + for visual_line in split(getreg("v"),"\n") + if strlen(visual_line) > visual_width + let dollar_block = 1 + let visual_width = strlen(visual_line) + endif + endfor + let square_up = (dollar_block ? (start_col+visual_width-2).'|' : '') + + " Drag left... + if a:dir == 'left' + "Can't drag left at left margin... + if col_left == 1 || col_right == 1 + return 'gv' + + " Otherwise reposition one column left (and optionally trim any whitespace)... + elseif g:DVB_TrimWS + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " Are we moving past other text??? + let square_up_final = "" + if dollar_block + let lines = getline(line_left, line_right) + if match(lines, '^.\{'.(start_col-2).'}\S') >= 0 + let dollar_block = 0 + let square_up_final = (start_col+visual_width-3).'|' + endif + endif + + let vcol = start_col - 2 + return 'gv'.square_up.'xhP' + \ . s:NO_REPORT + \ . "gvhoho:s/\\s*$//\<CR>gv\<ESC>" + \ . ':set virtualedit=' . prev_ve . "\<CR>" + \ . s:PREV_REPORT + \ . ":nohlsearch\<CR>gv" + \ . (dollar_block ? '$' : square_up_final ) + else + return 'gv'.square_up.'xhPgvhoho' + endif + + " Drag right... + elseif a:dir == 'right' + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " Reposition block one column to the right... + if g:DVB_TrimWS + let vcol = start_col + return 'gv'.square_up.'xp' + \ . s:NO_REPORT + \ . "gvlolo" + \ . ":s/\\s*$//\<CR>gv\<ESC>" + \ . ':set virtualedit=' . prev_ve . "\<CR>" + \ . s:PREV_REPORT + \ . (dollar_block ? 'gv$' : 'gv') + else + return 'gv'.square_up.'xp:set virtualedit=' . prev_ve . "\<CR>gvlolo" + endif + + " Drag upwards... + elseif a:dir == 'up' + " Can't drag upwards at top margin... + if line_left == 1 || line_right == 1 + return 'gv' + endif + + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " If trimming whitespace, jump to just below block to do it... + if g:DVB_TrimWS + let height = line_right - line_left + 1 + return 'gv'.square_up.'xkPgvkoko"vy' + \ . height + \ . 'j:s/\s*$//' + \ . "\<CR>:nohlsearch\<CR>:set virtualedit=" + \ . prev_ve + \ . "\<CR>gv" + \ . (dollar_block ? '$' : '') + + " Otherwise just move and reselect... + else + return 'gv'.square_up.'xkPgvkoko"vy:set virtualedit=' + \ . prev_ve + \ . "\<CR>gv" + \ . (dollar_block ? '$' : '') + endif + + " Drag downwards... + elseif a:dir == 'down' + " May need to be able to temporarily step past EOL... + let prev_ve = &virtualedit + set virtualedit=all + + " If trimming whitespace, move to just above block to do it... + if g:DVB_TrimWS + return 'gv'.square_up.'xjPgvjojo"vyk:s/\s*$//' + \ . "\<CR>:nohlsearch\<CR>:set virtualedit=" + \ . prev_ve + \ . "\<CR>gv" + \ . (dollar_block ? '$' : '') + + " Otherwise just move and reselect... + else + return 'gv'.square_up.'xjPgvjojo"vy' + \ . "\<CR>:set virtualedit=" + \ . prev_ve + \ . "\<CR>gv" + \ . (dollar_block ? '$' : '') + endif + endif +endfunction + + +" Restore previous external compatibility options +let &cpo = s:save_cpo + diff --git a/stow/vim/dot-vim/plugin/rng.vim b/stow/vim/dot-vim/plugin/rng.vim new file mode 100644 index 0000000..51c9991 --- /dev/null +++ b/stow/vim/dot-vim/plugin/rng.vim @@ -0,0 +1,83 @@ +" George Marsaglia's Multiply-with-carry Random Number Generator {{{ +" Modified to work within Vim's semantics +let s:m_w = 1 + getpid() +let s:m_z = localtime() + +" not sure of the wisdom of generating a full 32-bit RN here +" and then using abs() on the sucker. Feedback welcome. +function! RandomNumber(...) + if a:0 == 0 + let s:m_z = (36969 * and(s:m_z, 0xffff)) + (s:m_z / 65536) + let s:m_w = (18000 * and(s:m_w, 0xffff)) + (s:m_w / 65536) + return (s:m_z * 65536) + s:m_w " 32-bit result + elseif a:0 == 1 " We return a number in [0, a:1] or [a:1, 0] + return a:1 < 0 ? RandomNumber(a:1,0) : RandomNumber(0,a:1) + else " if a:2 >= 2 + return abs(RandomNumber()) % (abs(a:2 - a:1) + 1) + a:1 + endif +endfunction +" end RNG }}} + +" RandomChar(base, cap) +" base : the lowest char number desired +" cap : the highest char number desired +" Defaults to ASCII characters in the range +" 33-126 (!-~) +" But it's capable of much wider character tables +function! RandomChar(...) + let base = 33 + let cap = 126 + if a:0 > 0 + let base = a:1 + endif + if a:0 > 1 + let cap = a:2 + endif + return nr2char(RandomNumber(base, cap)) +endfunction + +function! RandomCharsInSet(length, set) + let from = join(map(range(len(a:set)), 'nr2char(char2nr("a")+v:val)'), '') + let to = join(a:set, '') + return map(RandomChars(a:length, 97, 96+len(a:set)), 'tr(v:val, from, to)') +endfunction + +function! RandomChars(length, ...) + let args = [] + if a:0 > 0 + if type(a:1) == type([]) + let args = a:1 + else + let args = a:000 + endif + endif + return map(repeat([0], a:length), 'call("RandomChar", args)') +endfunction + +function! RandomString(length, ...) + let args = [] + if a:0 > 0 + if type(a:1) == type([]) + let args = a:1 + else + let args = a:000 + endif + endif + return join(call('RandomChars', [a:length, args]), '') +endfunction + +let s:chars = '! " # $ % & '' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~' +let s:charlist = split(s:chars, ' ') + +function! RandomCharFromRegex(regex, ...) + let charlist = a:0 ? split(a:1, '\zs') : copy(s:charlist) + call filter(charlist, 'v:val =~ a:regex') + return charlist[RandomNumber(0, len(charlist) - 1)] +endfunction + +function! RandomStringFromRegex(regex, lenght, ...) + let charlist = a:0 ? split(a:1, '\zs') : copy(s:charlist) + call filter(charlist, 'v:val =~ a:regex') + let len = len(charlist) - 1 + return join(map(range(a:lenght), 'charlist[RandomNumber(0, len)]'), '') +endfunction |