2008-05-04 02:40:30 -04:00
|
|
|
import code, re, string, StringIO, sys, traceback
|
2008-03-16 18:12:29 -04:00
|
|
|
import color, completer, lex, method, mode
|
2007-10-21 20:52:48 -04:00
|
|
|
from lex import Grammar, PatternRule
|
2008-03-16 18:12:29 -04:00
|
|
|
from mode.python import PythonGrammar
|
2007-10-21 20:50:11 -04:00
|
|
|
from point import Point
|
2007-07-21 11:40:53 -04:00
|
|
|
|
2008-05-11 23:37:57 -04:00
|
|
|
PAD = ' '
|
2008-05-04 13:55:08 -04:00
|
|
|
LIMIT = 79
|
|
|
|
|
2007-07-21 11:40:53 -04:00
|
|
|
class ConsoleExec(method.Method):
|
|
|
|
def _execute(self, w, **vargs):
|
|
|
|
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()
|
|
|
|
b.insert_string(b.get_buffer_end(), p + s + '\n', force=True)
|
|
|
|
|
|
|
|
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()
|
|
|
|
except (SyntaxError, OverflowError, ValueError), e:
|
|
|
|
a.set_mini_buffer_prompt('>>> ')
|
|
|
|
t = sys.exc_traceback
|
|
|
|
output = str(e) + traceback.format_exc()
|
|
|
|
|
2008-05-11 23:37:57 -04:00
|
|
|
limit = 1000
|
|
|
|
for w2 in b.windows:
|
|
|
|
limit = min(w.width, limit)
|
|
|
|
if limit == 1000:
|
|
|
|
limit = LIMIT
|
|
|
|
limit -= len(PAD)
|
|
|
|
|
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'):
|
2008-05-04 13:55:08 -04:00
|
|
|
i = 0
|
2008-05-11 23:37:57 -04:00
|
|
|
while i + limit < len(line):
|
|
|
|
j = limit
|
2008-05-04 13:55:08 -04:00
|
|
|
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])
|
2008-05-04 13:55:08 -04:00
|
|
|
i += j
|
|
|
|
else:
|
2008-05-11 23:37:57 -04:00
|
|
|
newlines.append(PAD + line[i:i + j])
|
2008-05-04 13:55:08 -04:00
|
|
|
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
|
|
|
|
|
|
|
class ConsoleCancel(method.Method):
|
|
|
|
def execute(self, w, **vargs):
|
|
|
|
w.application.close_mini_buffer()
|
|
|
|
class ConsoleClear(method.Method):
|
|
|
|
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()
|
|
|
|
|
|
|
|
class ConsoleHistoryPrev(method.Method):
|
|
|
|
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])
|
|
|
|
class ConsoleHistoryNext(method.Method):
|
|
|
|
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])
|
|
|
|
|
2008-03-16 18:12:29 -04:00
|
|
|
class ConsoleTab(method.Method):
|
|
|
|
def execute(self, w, **vargs):
|
|
|
|
a = w.application
|
|
|
|
s = w.buffer.make_string()
|
|
|
|
|
|
|
|
x = w.logical_cursor().x
|
2008-04-14 14:27:23 -04:00
|
|
|
if not s or s[:x].isspace():
|
|
|
|
w.insert_string_at_cursor(' ' * w.mode.tabwidth)
|
|
|
|
return
|
|
|
|
|
|
|
|
l = lex.Lexer(w.mode, PythonGrammar)
|
|
|
|
tokens = list(l.lex([s]))
|
2008-03-16 18:12:29 -04:00
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
names = [curr_t.string]
|
|
|
|
name_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
|
|
|
|
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
|
|
|
|
|
|
|
|
obj = None
|
|
|
|
g = globals()
|
|
|
|
i = 0
|
|
|
|
name = None
|
|
|
|
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:
|
|
|
|
if hasattr(obj, name):
|
|
|
|
obj = getattr(obj, name)
|
|
|
|
else:
|
|
|
|
break
|
|
|
|
i += 1
|
2008-04-14 14:27:23 -04:00
|
|
|
|
|
|
|
if i == len(names) - 1:
|
|
|
|
if obj is not None:
|
|
|
|
newnames = dir(obj)
|
|
|
|
else:
|
2008-05-04 02:40:30 -04:00
|
|
|
newnames = set()
|
2008-04-14 14:27:23 -04:00
|
|
|
newnames.update(__builtins__)
|
|
|
|
newnames.update(w.mode.locals)
|
|
|
|
newnames.update(w.mode.globals)
|
2008-03-16 18:12:29 -04:00
|
|
|
candidates = [x for x in newnames if x.startswith(name)]
|
|
|
|
if len(candidates) > 1:
|
|
|
|
s = completer.find_common_string(candidates)[len(name):]
|
|
|
|
w.insert_string_at_cursor(s)
|
|
|
|
elif len(candidates) == 1:
|
|
|
|
s = candidates[0][len(name):]
|
|
|
|
w.insert_string_at_cursor(s)
|
|
|
|
|
2008-05-11 23:37:57 -04:00
|
|
|
class ConsoleBaseMethod(method.Method):
|
|
|
|
subcls = method.Method
|
|
|
|
def __init__(self):
|
|
|
|
method.Method.__init__(self)
|
|
|
|
self.submethod = self.subcls()
|
|
|
|
def _execute(self, w, **vargs):
|
|
|
|
a = w.application
|
|
|
|
if not a.has_buffer_name('*Console*'):
|
|
|
|
raise Exception, "No console found!"
|
|
|
|
w2 = a.bufferlist.get_buffer_by_name('*Console*').windows[0]
|
|
|
|
self.submethod.execute(w2, **vargs)
|
|
|
|
|
|
|
|
class ConsolePageUp(ConsoleBaseMethod):
|
|
|
|
subcls = method.move.PageUp
|
|
|
|
class ConsolePageDown(ConsoleBaseMethod):
|
|
|
|
subcls = method.move.PageDown
|
|
|
|
class ConsoleGotoBeginning(ConsoleBaseMethod):
|
|
|
|
subcls = method.move.GotoBeginning
|
|
|
|
class ConsoleGotoEnd(ConsoleBaseMethod):
|
|
|
|
subcls = method.move.GotoEnd
|
|
|
|
|
2008-04-18 23:32:08 -04:00
|
|
|
class ConsoleMini(mode.Fundamental):
|
|
|
|
modename = 'ConsoleMini'
|
|
|
|
grammar = PythonGrammar
|
|
|
|
actions = [ConsoleExec, ConsoleClear, ConsoleCancel, ConsoleHistoryPrev,
|
2008-05-11 23:37:57 -04:00
|
|
|
ConsoleHistoryNext, ConsoleTab,
|
|
|
|
ConsolePageUp, ConsolePageDown, ConsoleGotoBeginning, ConsoleGotoEnd]
|
2008-04-18 23:32:08 -04:00
|
|
|
def __init__(self, w):
|
|
|
|
mode.Fundamental.__init__(self, w)
|
|
|
|
self.bindings = {}
|
|
|
|
self.globals = dict(w.application.globals())
|
|
|
|
self.locals = dict(w.application.locals())
|
|
|
|
self.saved_input = ""
|
|
|
|
|
|
|
|
self.history = ['']
|
|
|
|
self.hindex = 0
|
|
|
|
|
|
|
|
self.add_bindings('start-of-line', ('C-a', 'HOME',))
|
|
|
|
self.add_bindings('end-of-line', ('C-e', 'END',))
|
|
|
|
self.add_bindings('backward', ('C-b', 'L_ARROW',))
|
|
|
|
self.add_bindings('forward', ('C-f', 'R_ARROW',))
|
|
|
|
self.add_bindings('delete-left', ('DELETE', 'BACKSPACE',))
|
|
|
|
self.add_bindings('delete-left-word', ('M-DELETE', 'M-BACKSPACE',))
|
|
|
|
self.add_bindings('delete-right', ('C-d',))
|
|
|
|
self.add_bindings('delete-right-word', ('M-d',))
|
|
|
|
self.add_bindings('kill-region', ('C-w',))
|
|
|
|
self.add_bindings('copy-region', ('M-w',))
|
|
|
|
self.add_bindings('kill', ('C-k',))
|
|
|
|
self.add_bindings('copy', ('M-k',))
|
|
|
|
self.add_bindings('yank', ('C-y',))
|
|
|
|
self.add_bindings('pop-kill', ('M-y',))
|
|
|
|
self.add_bindings('right-word', ('M-f',))
|
|
|
|
self.add_bindings('left-word', ('M-b',))
|
|
|
|
self.add_bindings('set-mark', ('C-@',))
|
|
|
|
self.add_bindings('switch-mark', ('C-x C-x',))
|
|
|
|
self.add_bindings('undo', ('C-/', 'C-x u',))
|
|
|
|
self.add_bindings('redo', ('M-/', 'M-_', 'C-x r',))
|
|
|
|
self.add_bindings('toggle-margins', ('M-m',))
|
|
|
|
self.add_bindings('transpose-words', ('M-t',))
|
|
|
|
self.add_bindings('delete-left-whitespace', ('C-c DELETE', 'C-c BACKSPACE',))
|
|
|
|
self.add_bindings('delete-right-whitespace', ('C-c d',))
|
|
|
|
self.add_bindings('insert-space', ('SPACE',))
|
|
|
|
self.add_bindings('insert-tab', ('TAB',))
|
|
|
|
self.add_bindings('console-exec', ('RETURN',))
|
|
|
|
self.add_bindings('console-clear', ('C-l',))
|
|
|
|
self.add_bindings('console-cancel', ('C-]',))
|
|
|
|
self.add_bindings('console-history-prev', ('C-p',))
|
|
|
|
self.add_bindings('console-history-next', ('C-n',))
|
|
|
|
self.add_bindings('console-tab', ('TAB',))
|
2008-05-11 23:37:57 -04:00
|
|
|
self.add_bindings('console-page-up', ('M-v',))
|
|
|
|
self.add_bindings('console-page-down', ('C-v',))
|
|
|
|
self.add_bindings('console-goto-beginning', ('M-<',))
|
|
|
|
self.add_bindings('console-goto-end', ('M->',))
|
2008-04-18 23:32:08 -04:00
|
|
|
for c in string.letters + string.digits + string.punctuation:
|
|
|
|
self.add_binding('insert-string-%s' % c, c)
|
|
|
|
|
2007-10-19 02:41:33 -04:00
|
|
|
install = ConsoleMini.install
|