pmacs3/mode/shellmini.py

287 lines
9.4 KiB
Python
Raw Normal View History

2008-09-12 09:31:48 -04:00
import code, os, re, string, StringIO, sys, traceback
2008-09-12 10:43:15 -04:00
import buffer, color, completer, lex, method, mode, window
2008-09-12 09:31:48 -04:00
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):
2008-09-12 10:43:15 -04:00
sequences = {
'\x1b[01;32m': "[green:default]",
'\x1b[01;34m': "[blue:default]",
'\x1b[01;36m': "[cyan:default]",
'\x1b[0m': "[default:default]",
}
2008-09-12 09:31:48 -04:00
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
2008-09-12 10:43:15 -04:00
escaped = []
2008-09-12 09:31:48 -04:00
for c in output:
2008-09-12 10:43:15 -04:00
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':
2008-09-12 09:31:48 -04:00
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'):
2008-09-12 10:43:15 -04:00
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)
2008-09-12 09:31:48 -04:00
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:])
2008-09-12 10:43:15 -04:00
#assert newlines[-1] == PAD
2008-09-12 09:31:48 -04:00
newlines[-1] = ''
2008-09-12 10:43:15 -04:00
#b.insert_lines(b.get_buffer_end(), newlines, force=True)
#b.set_lines(newlines, force=True)
b.set_data("\n".join(newlines))
2008-09-12 09:31:48 -04:00
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