forked from python-mode/python-mode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun.vim
More file actions
126 lines (95 loc) · 4.01 KB
/
run.vim
File metadata and controls
126 lines (95 loc) · 4.01 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
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
" The following lines set Vim's errorformat variable, to allow the
" quickfix window to show Python tracebacks properly. It is much
" easier to use let than set, because set requires many more
" characters to be escaped. This is much easier to read and
" maintain. % escapes are still needed however before any regex meta
" characters. Hence \S (non-whitespace) becomes %\S etc. Note that
" * becomes %#, so .* (match any character) becomes %.%# Commas must
" also be escaped, with a backslash (\,). See the Vim help on
" quickfix for details.
"
" Python errors are multi-lined. They often start with 'Traceback', so
" we want to capture that (with +G) and show it in the quickfix window
" because it explains the order of error messages.
let s:efm = '%+GTraceback%.%#,'
" The error message itself starts with a line with 'File' in it. There
" are a couple of variations, and we need to process a line beginning
" with whitespace followed by File, the filename in "", a line number,
" and optional further text. %E here indicates the start of a multi-line
" error message. The %\C at the end means that a case-sensitive search is
" required.
let s:efm .= '%E File "%f"\, line %l\,%m%\C,'
let s:efm .= '%E File "%f"\, line %l%\C,'
" The possible continutation lines are idenitifed to Vim by %C. We deal
" with these in order of most to least specific to ensure a proper
" match. A pointer (^) identifies the column in which the error occurs
" (but will not be entirely accurate due to indention of Python code).
let s:efm .= '%C%p^,'
" Any text, indented by more than two spaces contain useful information.
" We want this to appear in the quickfix window, hence %+.
let s:efm .= '%+C %.%#,'
let s:efm .= '%+C %.%#,'
" The last line (%Z) does not begin with any whitespace. We use a zero
" width lookahead (\&) to check this. The line contains the error
" message itself (%m)
let s:efm .= '%Z%\S%\&%m,'
" We can ignore any other lines (%-G)
let s:efm .= '%-G%.%#'
" DESC: Save file if it modified and run python code
fun! pymode#run#Run(line1, line2) "{{{
let l:code = getline(a:line1, a:line2)
let l:traceback = []
call setqflist([])
call pymode#WideMessage("Code running.")
try
Python << EOF
import StringIO, json
_input = lambda s: vim.eval('input("%s")' % s)
context = dict(__name__='__main__', input=_input, raw_input=_input)
out, errors = "", []
sys.stdout, stdout_ = StringIO.StringIO(), sys.stdout
sys.stderr, stderr_ = StringIO.StringIO(), sys.stderr
lines = [l.rstrip() for l in vim.eval('l:code')]
indent = 0
for line in lines:
if line:
indent = len(line) - len(line.lstrip())
break
lines = [l[indent:] for l in lines]
try:
code = compile('\n'.join(lines) + '\n', vim.current.buffer.name, 'exec')
exec(code, context)
except SystemExit as e:
errors.append('test')
if e.code:
# A non-false code indicates abnormal termination. A false code will be treated as a
# successful run, and the error will be hidden from Vim
vim.command('echohl Error | echo "Script exited with code {0}" | echohl none'.format(e.code))
vim.command('return')
except Exception as e:
import traceback
err = traceback.format_exc()
else:
err = sys.stderr.getvalue()
out = sys.stdout.getvalue().strip()
errors += [e for e in err.splitlines() if e and "<string>" not in e]
sys.stdout, sys.stderr = stdout_, stderr_
for e in errors:
vim.command("call add(l:traceback, %s)" % json.dumps(e))
if out:
vim.command("call pymode#TempBuffer()")
vim.current.buffer.append([x.decode("utf-8").encode(vim.eval('&enc')) for x in out.split('\n')], 0)
vim.command("wincmd p")
else:
vim.command('call pymode#WideMessage("No output.")')
EOF
cexpr ""
let l:_efm = &efm
let &efm = s:efm
cgetexpr(l:traceback)
call pymode#QuickfixOpen(0, g:pymode_lint_hold, g:pymode_lint_maxheight, g:pymode_lint_minheight, 0)
let &efm = l:_efm
catch /E234/
echohl Error | echo "Run-time error." | echohl none
endtry
endfunction "}}}