forked from jpalardy/vim-slime
-
Notifications
You must be signed in to change notification settings - Fork 0
/
slime.vim
129 lines (108 loc) · 3.62 KB
/
slime.vim
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
" GHC before 8.0.1 does not support top-level bindings
let g:slime_config_defaults["haskell_ghci_add_let"] = 1
" Remove '>' on line beginning in literate haskell
function! s:Remove_initial_gt(lines)
return map(copy(a:lines), "substitute(v:val, '^>[ \t]*', '', 'g')")
endfunction
function! s:Is_type_declaration(line)
let l:isNewType = a:line =~ "newtype"
let l:isTypeAlias = a:line =~ "type"
let l:isData = a:line =~ "data"
return l:isNewType || l:isTypeAlias || l:isData
endfunction
" Prepend certain statements with 'let'
function! s:Perhaps_prepend_let(lines)
if len(a:lines) > 0
let l:lines = a:lines
let l:line = l:lines[0]
" Prepend let if the line is an assignment
if (l:line =~ "=[^>]" || l:line =~ "::") && !s:Is_type_declaration(l:line)
let l:lines[0] = "let " . l:lines[0]
endif
return l:lines
else
return a:lines
endif
endfunction
" indent lines except for first one.
" lines are indented equally, so indentation is preserved.
function! s:Indent_lines(lines)
let l:lines = a:lines
let l:indent = slime#common#get_indent_string()
let l:i = 1
let l:len = len(l:lines)
while l:i < l:len
let l:lines[l:i] = l:indent . l:lines[l:i]
let l:i += 1
endwhile
return l:lines
endfunction
" Check if line is commented out
function! s:Is_comment(line)
return (match(a:line, "^[ \t]*--.*") >= 0)
endfunction
" Remove commented out lines
function! s:Remove_line_comments(lines)
return filter(copy(a:lines), "!s:Is_comment(v:val)")
endfunction
" remove block comments
function! s:Remove_block_comments(text)
return substitute(a:text, "{-.*-}", "", "g")
endfunction
" remove line comments
" todo: fix this! it only removes one occurence whilst it should remove all.
" function! s:Remove_line_comments(text)
" return substitute(a:text, "^[ \t]*--[^\n]*\n", "", "g")
" endfunction
" Wrap in :{ :} if there's more than one line
function! Wrap_if_multi(lines)
if len(a:lines) > 1
return [":{"] + a:lines + [":}"]
else
return a:lines
endif
endfunction
function! s:FilterImportLines(lines)
let l:matches = []
let l:noMatches = []
for l:line in a:lines
if l:line =~ "^import"
call add(l:matches, l:line)
else
call add(l:noMatches, l:line)
endif
endfor
return [l:matches, l:noMatches]
endfunction
" vim slime handler
function! _EscapeText_lhaskell(text)
let l:text = s:Remove_block_comments(a:text)
let l:lines = slime#common#lines(slime#common#tab_to_spaces(l:text))
let l:lines = s:Remove_initial_gt(l:lines)
let [l:imports, l:nonImports] = s:FilterImportLines(l:lines)
let l:lines = s:Remove_line_comments(l:nonImports)
if slime#config#resolve("haskell_ghci_add_let")
let l:lines = s:Perhaps_prepend_let(l:lines)
let l:lines = s:Indent_lines(l:lines)
endif
let l:lines = Wrap_if_multi(l:lines)
return slime#common#unlines(l:imports + l:lines)
endfunction
function! _EscapeText_haskell(text)
let l:text = s:Remove_block_comments(a:text)
let l:lines = slime#common#lines(slime#common#tab_to_spaces(l:text))
let [l:imports, l:nonImports] = s:FilterImportLines(l:lines)
let l:lines = s:Remove_line_comments(l:nonImports)
if slime#config#resolve("haskell_ghci_add_let")
let l:lines = s:Perhaps_prepend_let(l:lines)
let l:lines = s:Indent_lines(l:lines)
endif
let l:lines = Wrap_if_multi(l:lines)
return slime#common#unlines(l:imports + l:lines)
endfunction
function! _EscapeText_haskell_script(text)
let l:text = s:Remove_block_comments(a:text)
let l:lines = slime#common#lines(slime#common#tab_to_spaces(l:text))
let l:lines = s:Remove_line_comments(l:lines)
return slime#common#unlines(l:lines)
endfunction