pmacs3/mode/shellmini.py

287 lines
9.4 KiB
Python

import code, os, re, string, StringIO, sys, traceback
import buffer, color, completer, lex, method, mode, window
from lex import Grammar, PatternRule
from mode.sh import ShGrammar
from point import Point
from method import Method
from subprocess import Popen, PIPE, STDOUT
#PAD = ' '
PAD = ''
LIMIT = 79
class ShellExec(Method):
sequences = {
'\x1b[01;32m': "[green:default]",
'\x1b[01;34m': "[blue:default]",
'\x1b[01;36m': "[cyan:default]",
'\x1b[0m': "[default:default]",
}
def _execute(self, w, **vargs):
a = w.application
if a.completion_window_is_open():
a.close_completion_buffer()
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
if not a.has_buffer_name('*Shell*'):
raise Exception, "No shell found!"
b = a.bufferlist.get_buffer_by_name('*Shell*')
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)
a.set_mini_buffer_prompt('sh$ ')
ok = True
args = ['sh', '-c', s]
env = {'COLUMNS': '80', 'LINES': '24', 'TERM': os.environ['TERM']}
p = Popen(args, bufsize=1024, stderr=STDOUT, stdout=PIPE,
close_fds=True, env=env)
output = p.stdout.read()
output2 = []
i = 0
escaped = []
for c in output:
if escaped:
escaped.append(c)
if c == 'm':
seq = ''.join(escaped)
if seq in self.sequences:
#output2.append(self.sequences[seq])
output2.append('{foo:bar}')
escaped = []
elif c == '\x1b':
escaped.append(c)
elif c == '\n':
output2.append(c)
i = 0
elif c == '\t':
j = i % 8
output2.append(' ' * (8 - j))
i += 8 - j
elif c == '\a':
pass
elif c == '\b':
if i > 0:
output2.pop(-1)
i -= 1
else:
output2.append(c)
i += 1
output = ''.join(output2)
limit = 1000
for w2 in b.windows:
limit = min(w.width, limit)
if limit == 1000:
limit = LIMIT
limit -= len(PAD)
if output:
newlines = []
for line in output.split('\n'):
line = line.replace('\x1b[01;32m', "[green:default]")
line = line.replace('\x1b[01;34m', "[blue:default]")
line = line.replace('\x1b[01;36m', "[cyan:default]")
line = line.replace('\x1b[0m', "[default:default]")
#line = repr(line)
i = 0
while i + limit < len(line):
j = limit
while j > 0 and line[i + j] != ' ':
j -= 1
if j == 0:
newlines.append(PAD + line[i:i + limit])
i += j
else:
newlines.append(PAD + line[i:i + j])
i += j + 1
newlines.append(PAD + line[i:])
#assert newlines[-1] == PAD
newlines[-1] = ''
#b.insert_lines(b.get_buffer_end(), newlines, force=True)
#b.set_lines(newlines, force=True)
b.set_data("\n".join(newlines))
for w2 in b.windows:
w2.goto_end(force=True)
class ShellCancel(Method):
def execute(self, w, **vargs):
w.application.close_mini_buffer()
if w.application.completion_window_is_open():
w.application.close_completion_buffer()
class ShellClear(Method):
def execute(self, w, **vargs):
a = w.application
if not a.has_buffer_name('*Shell*'):
raise Exception, "No shell found!"
b = a.bufferlist.get_buffer_by_name('*Shell*')
b.clear()
class ShellHistoryPrev(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 ShellHistoryNext(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])
#class ShellTab(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
#
# l = lex.Lexer(w.mode, ShGrammar)
# 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
#
# if not names:
# return
#
# obj = None
# g = globals()
# i = 0
# 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:
# 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)
class ShellBaseMethod(Method):
subcls = Method
subbuf = '*Shell*'
def __init__(self):
Method.__init__(self)
self.submethod = self.subcls()
def _execute(self, w, **vargs):
a = w.application
if not a.has_buffer_name(self.subbuf):
raise Exception, "No shell found!"
w2 = a.bufferlist.get_buffer_by_name(self.subbuf).windows[0]
self.submethod.execute(w2, **vargs)
class ShellPageUp(ShellBaseMethod):
subcls = method.move.PageUp
class ShellPageDown(ShellBaseMethod):
subcls = method.move.PageDown
class ShellGotoBeginning(ShellBaseMethod):
subcls = method.move.GotoBeginning
class ShellGotoEnd(ShellBaseMethod):
subcls = method.move.GotoEnd
class OpenShell(Method):
'''Evaluate sh expressions'''
def execute(self, w, **vargs):
a = w.application
if not a.has_buffer_name('*Shell*'):
b = buffer.ShellBuffer()
a.add_buffer(b)
window.Window(b, a)
b = a.bufferlist.get_buffer_by_name('*Shell*')
if a.window().buffer is not b:
a.switch_buffer(b)
f = lambda x: None
w.application.open_mini_buffer('sh$ ', f, self, None, 'shellmini')
class ShellMini(mode.Fundamental):
modename = 'ShellMini'
grammar = ShGrammar
actions = [ShellExec, ShellClear, ShellCancel, ShellHistoryPrev,
ShellHistoryNext, #ShellTab,
ShellPageUp, ShellPageDown, ShellGotoBeginning, ShellGotoEnd,
OpenShell]
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
self.add_bindings('shell-exec', ('RETURN',))
self.add_bindings('shell-clear', ('C-l',))
self.add_bindings('shell-cancel', ('C-]', 'C-g'))
self.add_bindings('shell-history-prev', ('C-p', 'UP'))
self.add_bindings('shell-history-next', ('C-n', 'DOWN'))
#self.add_bindings('shell-tab', ('TAB',))
self.add_bindings('shell-page-up', ('M-v',))
self.add_bindings('shell-page-down', ('C-v',))
self.add_bindings('shell-goto-beginning', ('M-<',))
self.add_bindings('shell-goto-end', ('M->',))
install = ShellMini.install