pmacs3/mode/consolemini.py

247 lines
8.1 KiB
Python
Raw Normal View History

2009-03-29 20:50:27 -04:00
import code
import re
import StringIO
import sys
import traceback
import completer
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!"
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 = StringIO.StringIO()
sys.stderr = code_err = StringIO.StringIO()
ok = True
try:
exec code_obj in w.mode.globals, w.mode.locals
except Exception, e:
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, e:
2007-07-21 11:40:53 -04:00
a.set_mini_buffer_prompt('>>> ')
t = sys.exc_traceback
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:
2008-05-11 23:37:57 -04:00
newlines = []
for line in output.split('\n'):
i = 0
2008-05-11 23:37:57 -04:00
while i + limit < len(line):
j = limit
while j > 0 and line[i + j] != ' ':
j -= 1
if j == 0:
2008-05-11 23:37:57 -04:00
newlines.append(PAD + line[i:i + limit])
i += j
else:
2008-05-11 23:37:57 -04:00
newlines.append(PAD + line[i:i + j])
i += j + 1
2008-05-11 23:37:57 -04:00
newlines.append(PAD + line[i:])
assert newlines[-1] == PAD
newlines[-1] = ''
b.insert_lines(b.get_buffer_end(), newlines, 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):
2008-05-11 23:37:57 -04:00
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