vimlrs 0.1.3

Faithful Rust port of the Vimscript (VimL) interpreter, from the Neovim C eval engine
Documentation
" regex_zs.vim — \zs / \ze match-bound atoms and zero-width split() (regexp).
" \zs sets where the matched text starts, \ze where it ends, so matchstr() and
" substitute() report only the bracketed part. split() on a zero-width pattern
" (the \zs "split into characters" idiom, or any pattern that can match empty)
" advances one character at a time. Self-test: asserts into v:errors.

" --- \zs / \ze in matchstr(): only the text after \zs / before \ze is returned
call assert_equal('l', matchstr('hello', 'l\zs.'))
call assert_equal('foo', matchstr('foobar', 'foo\zebar'))
call assert_equal('123', matchstr('abc123', '\d\+'))

" --- \zs in substitute(): the replaced span starts at \zs
call assert_equal('Xbc', substitute('abc', '\zs.', 'X', ''))
call assert_equal('heXo', substitute('hello', 'l\zsl', 'X', ''))

" --- split() on \zs splits into characters
call assert_equal(['h', 'e', 'l', 'l', 'o'], split('hello', '\zs'))

" --- split() on any zero-width-capable pattern advances one char per item
call assert_equal(['a', 'b'], split('ab', 'x*'))

" --- regular (non-zero-width) split still works, internal empties kept
call assert_equal(['a', 'b', 'c'], split('a1b2c', '\d'))
call assert_equal(['a', '', 'b'], split('a,,b', ','))

if len(v:errors) > 0
  for err in v:errors
    echo err
  endfor
  throw 'regex_zs.vim: ' . len(v:errors) . ' assertion(s) failed'
endif
echo 'regex_zs.vim: all assertions passed'