forked from vim-test/vim-test
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbase.vim
More file actions
95 lines (83 loc) · 3 KB
/
Copy pathbase.vim
File metadata and controls
95 lines (83 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
function! test#base#test_file(runner, file) abort
return test#{a:runner}#test_file(a:file)
endfunction
function! test#base#build_position(runner, type, position) abort
return test#{a:runner}#build_position(a:type, a:position)
endfunction
function! test#base#options(runner, ...) abort
let options = get(g:, 'test#'.a:runner.'#options')
if empty(a:000) && type(options) == type('')
return split(options)
elseif !empty(a:000) && type(options) == type({})
return split(get(options, a:000[0], ''))
else
return []
endif
endfunction
function! test#base#executable(runner) abort
return get(g:, 'test#'.a:runner.'#executable', test#{a:runner}#executable())
endfunction
function! test#base#build_args(runner, args) abort
return test#{a:runner}#build_args(a:args)
endfunction
function! test#base#file_exists(file) abort
return !empty(glob(a:file)) || bufexists(a:file)
endfunction
function! test#base#escape_regex(string) abort
return escape(a:string, '?+*\^$.|{}[]()')
endfunction
function! test#base#no_colors() abort
let strategy = get(g:, 'test#strategy', 'basic')
return has('gui_running') && strategy == 'basic'
endfunction
" Takes a position and a dictionary of patterns, and returns list of strings
" that were matched in the file by the patterns from the given position
" upwards. It can be used when a runner doesn't support running nearest tests
" with line numbers, but supports regexes.
"
" The "position" argument is a dictionary created by this plugin:
"
" {
" 'file': 'test/foo_test.rb',
" 'line': 11,
" 'col': 2,
" }
"
" The "patterns" argument is a dictionary where keys are either "test" or
" "namespace", and values are lists of regexes:
"
" {
" 'test': ['\v^\s*def (test_\w+)'],
" 'namespace': ['\v^\s*%(class|module) (\S+)'],
" }
"
" If a line is matched, the substring corresponding to the 1st match group will
" be returned. So for the above patterns this function might return something
" like this:
"
" {
" 'test': ['test_calculates_time'],
" 'namespace': ['CalculatorTest'],
" }
function! test#base#nearest_test(position, patterns) abort
let test = []
let namespace = []
let last_indent = -1
for line in reverse(getbufline(a:position['file'], 1, a:position['line']))
let test_match = s:find_match(line, a:patterns['test'])
let namespace_match = s:find_match(line, a:patterns['namespace'])
let indent = len(matchstr(line, '^\s*'))
if !empty(test_match) && last_indent == -1
call add(test, filter(test_match[1:], '!empty(v:val)')[0])
let last_indent = indent
elseif !empty(namespace_match) && (indent < last_indent || last_indent == -1)
call add(namespace, filter(namespace_match[1:], '!empty(v:val)')[0])
let last_indent = indent
endif
endfor
return {'test': test, 'namespace': reverse(namespace)}
endfunction
function! s:find_match(line, patterns) abort
let matches = map(copy(a:patterns), 'matchlist(a:line, v:val)')
return get(filter(matches, '!empty(v:val)'), 0, [])
endfunction