pmacs3/mode/consolemini.py

238 lines
7.7 KiB
Python
Raw Normal View History

2009-03-29 20:50:27 -04:00
import code
import re
import io
2009-03-29 20:50:27 -04:00
import sys
import traceback
2009-03-29 20:50:27 -04:00
import completer
import util
2009-03-29 20:50:27 -04:00
from method import Method
import method.move
import mode.mini
from lex import Lexer, Grammar, PatternRule
from mode.python import PythonGrammar
2007-07-21 11:40:53 -04:00
2008-05-11 23:37:57 -04:00
PAD = ' '
2009-03-29 20:50:27 -04:00
class ConsoleExec(Method):
2007-07-21 11:40:53 -04:00
def _execute(self, w, **vargs):
2008-05-26 23:57:09 -04:00
if w.application.completion_window_is_open():
w.application.close_completion_buffer()
2007-07-21 11:40:53 -04:00
s = w.buffer.make_string()
w.mode.history[-1] = s
w.mode.history.append('')
w.buffer.set_data('')
w.mode.hindex = len(w.mode.history) - 1
a = w.application
if not a.has_buffer_name('*Console*'):
raise Exception("No console found!")
2007-07-21 11:40:53 -04:00
b = a.bufferlist.get_buffer_by_name('*Console*')
if a.window().buffer is not b:
a.switch_buffer(b)
p = a.get_mini_buffer_prompt()
2009-03-10 10:43:04 -04:00
b.insert_string(b.get_buffer_end(), p + s + '\n', force=True)
2007-07-21 11:40:53 -04:00
if w.mode.saved_input:
s = w.mode.saved_input + '\n' + s
try:
code_obj = code.compile_command(s)
if code_obj is None:
w.mode.saved_input = s
a.set_mini_buffer_prompt('--> ')
output = None
else:
w.mode.saved_input = ''
a.set_mini_buffer_prompt('>>> ')
sys.stdout = code_out = io.StringIO()
sys.stderr = code_err = io.StringIO()
2007-07-21 11:40:53 -04:00
ok = True
try:
exec(code_obj, w.mode.globals, w.mode.locals)
except Exception as e:
2007-07-21 11:40:53 -04:00
ok = False
output = str(e) + '\n'
sys.stdout = sys.__stdout__
sys.stdout = sys.__stderr__
if ok:
output = code_out.getvalue()
code_out.close()
code_err.close()
2009-03-10 10:35:49 -04:00
#except (SyntaxError, OverflowError, ValueError), e:
except Exception as e:
2007-07-21 11:40:53 -04:00
a.set_mini_buffer_prompt('>>> ')
t = sys.exc_info()[2]
2007-07-21 11:40:53 -04:00
output = str(e) + traceback.format_exc()
2009-02-15 12:06:35 -05:00
limit = min([w.width for w in b.windows]) - len(PAD)
2008-05-11 23:37:57 -04:00
2007-07-21 11:40:53 -04:00
if output:
lines = []
2008-05-11 23:37:57 -04:00
for line in output.split('\n'):
lines.extend([PAD + l for l in util.wrap_lines(line, limit)])
if lines[-1] == PAD:
lines[-1] = ''
2010-05-18 23:43:01 -04:00
b.insert_lines(b.get_buffer_end(), lines + [''], force=True)
2007-07-21 11:40:53 -04:00
for w2 in b.windows:
2008-05-11 23:37:57 -04:00
w2.goto_end(force=True)
2007-07-21 11:40:53 -04:00
2009-03-29 20:50:27 -04:00
class ConsoleCancel(Method):
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
w.application.close_mini_buffer()
2008-05-26 23:57:09 -04:00
if w.application.completion_window_is_open():
w.application.close_completion_buffer()
2009-03-29 20:50:27 -04:00
class ConsoleClear(Method):
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
#a = w.application
#if not a.has_buffer_name('*Console*'):
# raise Exception, "No console found!"
#b = a.bufferlist.get_buffer_by_name('*Console*')
#b.clear()
w.buffer.parentw.buffer.clear()
2007-07-21 11:40:53 -04:00
2009-03-29 20:50:27 -04:00
class ConsoleHistoryPrev(Method):
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
if w.mode.hindex <= 0:
w.mode.hindex = 0
return
elif w.mode.hindex == len(w.mode.history) - 1:
w.mode.history[-1] = w.buffer.make_string()
w.mode.hindex -= 1
w.buffer.set_data(w.mode.history[w.mode.hindex])
2009-03-29 20:50:27 -04:00
class ConsoleHistoryNext(Method):
2007-07-21 11:40:53 -04:00
def execute(self, w, **vargs):
if w.mode.hindex == len(w.mode.history) - 1:
return
w.mode.hindex += 1
w.buffer.set_data(w.mode.history[w.mode.hindex])
2009-03-29 20:50:27 -04:00
class ConsoleTab(Method):
def execute(self, w, **vargs):
a = w.application
s = w.buffer.make_string()
x = w.logical_cursor().x
if not s or s[:x].isspace():
w.insert_string_at_cursor(' ' * w.mode.tabwidth)
return
2009-03-29 20:50:27 -04:00
l = Lexer(w.mode, PythonGrammar)
tokens = list(l.lex([s]))
curr_t = None
curr_i = None
for i in range(0, len(tokens)):
t = tokens[i]
if t.x < x and t.end_x() >= x:
curr_i = i
curr_t = t
if curr_t is None:
return
first_t = curr_t
j = curr_i
name_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
if name_re.match(curr_t.string):
names = [curr_t.string]
elif curr_t.string == '.':
names = ['']
else:
names = []
while j >= 1:
j -= 1
t = tokens[j]
if name_re.match(t.string):
names.insert(0, t.string)
elif t.string == '.':
pass
else:
break
2008-05-26 23:57:09 -04:00
if not names:
return
obj = None
g = globals()
i = 0
2008-05-26 23:57:09 -04:00
name = names[0]
if len(names) > 1:
while i < len(names):
name = names[i]
if obj is None:
if name in w.mode.locals:
obj = w.mode.locals[name]
elif name in w.mode.globals:
obj = w.mode.globals[name]
else:
break
else:
2008-05-26 23:57:09 -04:00
if hasattr(obj, name):
obj = getattr(obj, name)
else:
break
i += 1
if i == len(names) - 1:
if obj is not None:
newnames = dir(obj)
else:
newnames = set()
newnames.update(__builtins__)
newnames.update(w.mode.locals)
newnames.update(w.mode.globals)
candidates = [x for x in newnames if x.startswith(name)]
s = completer.find_common_string(candidates)[len(name):]
w.insert_string_at_cursor(s)
mode.mini.use_completion_window(a, name, candidates)
2009-03-29 20:50:27 -04:00
class ConsoleBase(Method):
subcls = Method
subbuf = '*Console*'
2008-05-11 23:37:57 -04:00
def __init__(self):
2009-03-29 20:50:27 -04:00
Method.__init__(self)
2008-05-11 23:37:57 -04:00
self.submethod = self.subcls()
def _execute(self, w, **vargs):
a = w.application
if not a.has_buffer_name(self.subbuf):
raise Exception("No console found!")
w2 = a.bufferlist.get_buffer_by_name(self.subbuf).windows[0]
2008-05-11 23:37:57 -04:00
self.submethod.execute(w2, **vargs)
2009-03-29 20:50:27 -04:00
class ConsolePageUp(ConsoleBase): subcls = method.move.PageUp
class ConsolePageDown(ConsoleBase): subcls = method.move.PageDown
class ConsoleGotoBeginning(ConsoleBase): subcls = method.move.GotoBeginning
class ConsoleGotoEnd(ConsoleBase): subcls = method.move.GotoEnd
2008-05-11 23:37:57 -04:00
2008-04-18 23:32:08 -04:00
class ConsoleMini(mode.Fundamental):
name = 'ConsoleMini'
grammar = PythonGrammar
actions = [ConsoleExec, ConsoleClear, ConsoleCancel, ConsoleHistoryPrev,
2009-03-29 20:50:27 -04:00
ConsoleHistoryNext, ConsoleTab,
ConsolePageUp, ConsolePageDown, ConsoleGotoBeginning,
ConsoleGotoEnd]
2009-02-15 12:06:35 -05:00
_bindings = {
2009-03-04 12:23:20 -05:00
'console-exec': ('RETURN',),
'console-clear': ('C-l',),
'console-cancel': ('C-]', 'C-g'),
'console-history-prev': ('C-p', 'UP'),
'console-history-next': ('C-n', 'DOWN'),
'console-tab': ('TAB',),
'console-page-up': ('M-v',),
'console-page-down': ('C-v',),
2009-02-15 12:06:35 -05:00
'console-goto-beginning': ('M-<',),
2009-03-04 12:23:20 -05:00
'console-goto-end': ('M->',),
2009-02-15 12:06:35 -05:00
}
2008-04-18 23:32:08 -04:00
def __init__(self, w):
mode.Fundamental.__init__(self, w)
self.globals = dict(w.application.globals())
self.locals = dict(w.application.locals())
self.saved_input = ""
self.history = ['']
self.hindex = 0
2008-04-18 23:32:08 -04:00
2007-10-19 02:41:33 -04:00
install = ConsoleMini.install