shell buffer

--HG--
branch : pmacs2
This commit is contained in:
moculus 2008-09-12 13:31:48 +00:00
parent a6fb81d077
commit 57b5f38c80
5 changed files with 303 additions and 3 deletions

View File

@ -129,6 +129,7 @@ class Application(object):
'latex', 'insertmini', 'conf', 'haskell', 'erlang', 'latex', 'insertmini', 'conf', 'haskell', 'erlang',
'iperl', 'iperlmini', 'ipython', 'ipythonmini', 'iperl', 'iperlmini', 'ipython', 'ipythonmini',
'bds', #XYZ 'bds', #XYZ
'shell', 'shellmini',
) )
for name in names: for name in names:
exec("import mode.%s; mode.%s.install(self)" % (name, name)) exec("import mode.%s; mode.%s.install(self)" % (name, name))

View File

@ -395,6 +395,24 @@ class ConsoleBuffer(Buffer):
def readonly(self): def readonly(self):
return True return True
class ConsoleBuffer(Buffer):
btype = 'shell'
modename = 'shell'
def __init__(self):
Buffer.__init__(self)
self.clear()
def clear(self):
lines = ['Shell\n']
self.set_data(''.join(lines), force=True)
def name(self):
return '*Shell*'
def changed(self):
return False
def close(self):
pass
def readonly(self):
return True
class InterpreterPipeError(Exception): class InterpreterPipeError(Exception):
pass pass

View File

@ -138,10 +138,11 @@ class Sh(mode.Fundamental):
grammar = ShGrammar grammar = ShGrammar
tabbercls = ShTabber tabbercls = ShTabber
opentokens = ('delimiter', 'sh_reserved', 'case.start') opentokens = ('delimiter', 'sh_reserved', 'case.start')
opentags = {'(': ')', '[': ']', '{': '}', 'do': 'done', 'then': 'fi', 'case': 'esac'} opentags = {'(': ')', '[': ']', '{': '}', 'do': 'done', 'then': 'fi',
'case': 'esac'}
closetokens = ('delimiter', 'sh_reserved', 'case.end') closetokens = ('delimiter', 'sh_reserved', 'case.end')
closetags = {')': '(', ']': '[', '}': '{', closetags = {')': '(', ']': '[', '}': '{', 'done': 'do', 'fi': 'then',
'done': 'do', 'fi': 'then', 'esac': 'case'} 'esac': 'case'}
colors = { colors = {
'sh_builtin': ('cyan', 'default', 'bold'), 'sh_builtin': ('cyan', 'default', 'bold'),
'sh_function': ('magenta', 'default', 'bold'), 'sh_function': ('magenta', 'default', 'bold'),

18
mode/shell.py Normal file
View File

@ -0,0 +1,18 @@
import color, mode
from lex import Grammar, PatternRule, RegionRule
from mode.sh import ShGrammar
class ShellGrammar(Grammar):
rules = [
#RegionRule(r'shell_input', r'^(?:sh$|sh>)', ShGrammar, '\n$'),
#PatternRule(r'shell_mesg', r'^[A-Za-z].*$'),
]
class Shell(mode.Fundamental):
modename = 'Shell'
#grammar = ShellGrammar()
colors = {
#'shell_mesg': ('red', 'default', 'bold'),
#'shell_input.start': ('red', 'default', 'bold'),
}
install = Shell.install

262
mode/shellmini.py Normal file
View File

@ -0,0 +1,262 @@
import code, os, re, string, StringIO, sys, traceback
import color, completer, lex, method, mode
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):
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
for c in output:
if 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'):
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)
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