Skip to content

Commit 2105e00

Browse files
committed
Merge with lawrenceakka
2 parents ec56898 + a064c3c commit 2105e00

File tree

1 file changed

+98
-30
lines changed

1 file changed

+98
-30
lines changed

autoload/pymode/run.vim

Lines changed: 98 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,116 @@
1+
" The following lines set Vim's errorformat variable, to allow the
2+
" quickfix window to show Python tracebacks properly. It is much
3+
" easier to use let than set, because set requires many more
4+
" characters to be escaped. This is much easier to read and
5+
" maintain. % escapes are still needed however before any regex meta
6+
" characters. Hence \S (non-whitespace) becomes %\S etc. Note that
7+
" * becomes %#, so .* (match any character) becomes %.%# Commas must
8+
" also be escaped, with a backslash (\,). See the Vim help on
9+
" quickfix for details.
10+
"
11+
" Python errors are multi-lined. They often start with 'Traceback', so
12+
" we want to capture that (with +G) and show it in the quickfix window
13+
" because it explains the order of error messages.
14+
let s:efm = '%+GTraceback%.%#,'
15+
16+
" The error message itself starts with a line with 'File' in it. There
17+
" are a couple of variations, and we need to process a line beginning
18+
" with whitespace followed by File, the filename in "", a line number,
19+
" and optional further text. %E here indicates the start of a multi-line
20+
" error message. The %\C at the end means that a case-sensitive search is
21+
" required.
22+
let s:efm .= '%E File "%f"\, line %l\,%m%\C,'
23+
let s:efm .= '%E File "%f"\, line %l%\C,'
24+
25+
" The possible continutation lines are idenitifed to Vim by %C. We deal
26+
" with these in order of most to least specific to ensure a proper
27+
" match. A pointer (^) identifies the column in which the error occurs
28+
" (but will not be entirely accurate due to indention of Python code).
29+
let s:efm .= '%C%p^,'
30+
" Any text, indented by more than two spaces contain useful information.
31+
" We want this to appear in the quickfix window, hence %+.
32+
let s:efm .= '%+C %.%#,'
33+
let s:efm .= '%+C %.%#,'
34+
35+
" The last line (%Z) does not begin with any whitespace. We use a zero
36+
" width lookahead (\&) to check this. The line contains the error
37+
" message itself (%m)
38+
let s:efm .= '%Z%\S%\&%m,'
39+
40+
" We can ignore any other lines (%-G)
41+
let s:efm .= '%-G%.%#'
42+
43+
144
" DESC: Save file if it modified and run python code
245
fun! pymode#run#Run(line1, line2) "{{{
3-
if &modifiable && &modified
4-
try
5-
noautocmd write
6-
catch /E212/
7-
echohl Error | echo "File modified and I can't save it. Cancel code checking." | echohl None
8-
return 0
9-
endtry
10-
endif
11-
call pymode#Execute("import StringIO")
12-
call pymode#Execute("sys.stdout, stdout_ = StringIO.StringIO(), sys.stdout")
13-
call pymode#Execute("sys.stderr, stderr_ = StringIO.StringIO(), sys.stderr")
14-
call pymode#Execute("enc = vim.eval('&enc')")
46+
let l:code = getline(a:line1, a:line2)
47+
let l:traceback = []
48+
1549
call setqflist([])
1650
call pymode#WideMessage("Code running.")
51+
1752
try
18-
call pymode#Execute("context = globals()")
19-
call pymode#Execute("context['raw_input'] = context['input'] = lambda s: vim.eval('input(\"{0}\")'.format(s))")
20-
call pymode#Execute("execfile(vim.eval('expand(\"%:p\")'), context)")
21-
call pymode#Execute("out, err = sys.stdout.getvalue().strip(), sys.stderr.getvalue()")
22-
call pymode#Execute("sys.stdout, sys.stderr = stdout_, stderr_")
2353

24-
cexpr ""
25-
python << EOF
26-
for x in err.strip().split('\n'):
27-
vim.command('caddexpr "' + x.replace('"', r'\"') + '"')
28-
EOF
29-
let l:oldefm = &efm
30-
set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m
31-
call pymode#QuickfixOpen(0, g:pymode_lint_hold, g:pymode_lint_maxheight, g:pymode_lint_minheight, 0)
32-
let &efm = l:oldefm
54+
Python << EOF
55+
56+
import StringIO, json
57+
58+
_input = lambda s: vim.eval('input("%s")' % s)
59+
context = dict(__name__='__main__', input=_input, raw_input=_input)
60+
out, errors = "", []
61+
sys.stdout, stdout_ = StringIO.StringIO(), sys.stdout
62+
sys.stderr, stderr_ = StringIO.StringIO(), sys.stderr
63+
try:
64+
code = compile('\n'.join(vim.eval('l:code')) + '\n', vim.current.buffer.name, 'exec')
65+
exec(code, context)
66+
67+
except SystemExit as e:
68+
errors.append('test')
69+
if e.code:
70+
# A non-false code indicates abnormal termination. A false code will be treated as a
71+
# successful run, and the error will be hidden from Vim
72+
vim.command('echohl Error | echo "Script exited with code {0}" | echohl none'.format(e.code))
73+
vim.command('return')
74+
75+
except Exception as e:
76+
import traceback
77+
err = traceback.format_exc()
78+
79+
else:
80+
err = sys.stderr.getvalue()
81+
82+
out = sys.stdout.getvalue().strip()
83+
errors += [e for e in err.splitlines() if e and "<string>" not in e]
84+
85+
sys.stdout, sys.stderr = stdout_, stderr_
86+
87+
for e in errors:
88+
vim.command("call add(l:traceback, %s)" % json.dumps(e))
3389

34-
python << EOF
3590
if out:
3691
vim.command("call pymode#TempBuffer()")
37-
vim.current.buffer.append([x.decode("utf-8").encode(enc) for x in out.split('\n')], 0)
92+
vim.current.buffer.append([x.decode("utf-8").encode(vim.eval('&enc')) for x in out.split('\n')], 0)
3893
vim.command("wincmd p")
3994
else:
4095
vim.command('call pymode#WideMessage("No output.")')
96+
4197
EOF
4298

43-
catch /.*/
99+
cexpr ""
100+
101+
let l:_efm = &efm
102+
103+
let &efm = s:efm
104+
105+
cgetexpr(l:traceback)
106+
107+
call pymode#QuickfixOpen(0, g:pymode_lint_hold, g:pymode_lint_maxheight, g:pymode_lint_minheight, 0)
108+
let &efm = l:_efm
109+
110+
catch /E234/
44111

45112
echohl Error | echo "Run-time error." | echohl none
46-
113+
47114
endtry
115+
48116
endfunction "}}}

0 commit comments

Comments
 (0)