parent
a6fb81d077
commit
57b5f38c80
|
@ -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))
|
||||||
|
|
18
buffer.py
18
buffer.py
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue