mirror of
https://github.com/ivuorinen/nvim-shellspec.git
synced 2026-01-26 03:24:00 +00:00
- Replace static test fixture files with dynamic test generation - Implement comprehensive test suite with unit, integration, and golden master tests - Add vim API mocking for standalone Lua test execution - Fix pre-commit hook interference by eliminating external fixture files - Add StyLua formatting for consistent Lua code style - Enhance ShellSpec formatting with improved HEREDOC and comment handling - Update documentation with new test architecture details This resolves issues where pre-commit hooks (shfmt, end-of-file-fixer) were modifying test fixture files and breaking golden master tests. The new dynamic approach generates test data programmatically, making tests immune to formatting tools while maintaining comprehensive coverage.
137 lines
3.9 KiB
VimL
137 lines
3.9 KiB
VimL
" ShellSpec DSL formatter functions with HEREDOC and comment support
|
|
|
|
function! shellspec#format_buffer() abort
|
|
let l:pos = getpos('.')
|
|
let l:lines = getline(1, '$')
|
|
let l:formatted = shellspec#format_lines(l:lines)
|
|
|
|
silent! %delete _
|
|
call setline(1, l:formatted)
|
|
call setpos('.', l:pos)
|
|
endfunction
|
|
|
|
" Detect HEREDOC start and return delimiter
|
|
function! s:detect_heredoc_start(line) abort
|
|
let l:trimmed = trim(a:line)
|
|
|
|
" Check for various HEREDOC patterns
|
|
let l:patterns = [
|
|
\ '<<\([A-Z_][A-Z0-9_]*\)',
|
|
\ "<<'\([^']*\)'",
|
|
\ '<<"\([^"]*\)"',
|
|
\ '<<-\([A-Z_][A-Z0-9_]*\)'
|
|
\ ]
|
|
|
|
for l:pattern in l:patterns
|
|
let l:match = matchlist(l:trimmed, l:pattern)
|
|
if !empty(l:match)
|
|
return l:match[1]
|
|
endif
|
|
endfor
|
|
|
|
return ''
|
|
endfunction
|
|
|
|
" Check if line ends a HEREDOC
|
|
function! s:is_heredoc_end(line, delimiter) abort
|
|
if empty(a:delimiter)
|
|
return 0
|
|
endif
|
|
return trim(a:line) ==# a:delimiter
|
|
endfunction
|
|
|
|
" Enhanced format_lines with HEREDOC and comment support
|
|
function! shellspec#format_lines(lines) abort
|
|
let l:result = []
|
|
let l:indent = 0
|
|
let l:state = 'normal' " States: normal, heredoc
|
|
let l:heredoc_delimiter = ''
|
|
let l:indent_comments = get(g:, 'shellspec_indent_comments', 1)
|
|
|
|
for l:line in a:lines
|
|
let l:trimmed = trim(l:line)
|
|
|
|
" Handle empty lines
|
|
if l:trimmed == ''
|
|
call add(l:result, l:line)
|
|
continue
|
|
endif
|
|
|
|
" State machine for HEREDOC handling
|
|
if l:state ==# 'normal'
|
|
" Check for HEREDOC start
|
|
let l:delimiter = s:detect_heredoc_start(l:line)
|
|
if !empty(l:delimiter)
|
|
let l:state = 'heredoc'
|
|
let l:heredoc_delimiter = l:delimiter
|
|
" Apply current indentation to HEREDOC start line
|
|
let l:formatted = repeat(' ', l:indent) . l:trimmed
|
|
call add(l:result, l:formatted)
|
|
continue
|
|
endif
|
|
|
|
" Handle End keyword (decrease indent first)
|
|
if l:trimmed =~ '^End\s*$'
|
|
let l:indent = max([0, l:indent - 1])
|
|
let l:formatted = repeat(' ', l:indent) . l:trimmed
|
|
call add(l:result, l:formatted)
|
|
continue
|
|
endif
|
|
|
|
" Handle comments
|
|
if l:trimmed =~ '^#'
|
|
if l:indent_comments
|
|
let l:formatted = repeat(' ', l:indent) . l:trimmed
|
|
call add(l:result, l:formatted)
|
|
else
|
|
" Preserve original comment formatting
|
|
call add(l:result, l:line)
|
|
endif
|
|
continue
|
|
endif
|
|
|
|
" Handle non-comment lines (ShellSpec commands, etc.)
|
|
let l:formatted = repeat(' ', l:indent) . l:trimmed
|
|
call add(l:result, l:formatted)
|
|
|
|
" Increase indent after block keywords
|
|
if l:trimmed =~ '^\(Describe\|Context\|ExampleGroup\|It\|Specify\|Example\)'
|
|
let l:indent += 1
|
|
elseif l:trimmed =~ '^\([xf]\)\(Describe\|Context\|ExampleGroup\|It\|Specify\|Example\)'
|
|
let l:indent += 1
|
|
elseif l:trimmed =~ '^\(Data\|Parameters\)\s*$'
|
|
let l:indent += 1
|
|
elseif l:trimmed =~ '^\(BeforeEach\|AfterEach\|BeforeAll\|AfterAll\|Before\|After\)'
|
|
let l:indent += 1
|
|
elseif l:trimmed =~ '^\(BeforeCall\|AfterCall\|BeforeRun\|AfterRun\)'
|
|
let l:indent += 1
|
|
endif
|
|
|
|
elseif l:state ==# 'heredoc'
|
|
" Check for HEREDOC end
|
|
if s:is_heredoc_end(l:line, l:heredoc_delimiter)
|
|
let l:state = 'normal'
|
|
let l:heredoc_delimiter = ''
|
|
" Apply current indentation to HEREDOC end line
|
|
let l:formatted = repeat(' ', l:indent) . l:trimmed
|
|
call add(l:result, l:formatted)
|
|
else
|
|
" Preserve original indentation within HEREDOC
|
|
call add(l:result, l:line)
|
|
endif
|
|
endif
|
|
endfor
|
|
|
|
return l:result
|
|
endfunction
|
|
|
|
function! shellspec#format_selection() abort
|
|
let l:start = line("'<")
|
|
let l:end = line("'>")
|
|
let l:lines = getline(l:start, l:end)
|
|
let l:formatted = shellspec#format_lines(l:lines)
|
|
|
|
call deletebufline('%', l:start, l:end)
|
|
call append(l:start - 1, l:formatted)
|
|
endfunction
|