parent
f3cac461cd
commit
6efcf5ca2d
|
@ -128,7 +128,9 @@ class Application(object):
|
|||
'lisp', 'make', 'mini', 'mutt', 'nasm', 'ocaml', 'perl',
|
||||
'python', 'replace', 'rst', 'scheme', 'search', 'sh', 'sql',
|
||||
'tt', 'text', 'text2', 'which', 'xml', 'cheetah', 'colortext',
|
||||
'latex', 'insertmini', 'conf', 'haskell', 'erlang')
|
||||
'latex', 'insertmini', 'conf', 'haskell', 'erlang',
|
||||
'iperl', 'iperlmini',
|
||||
)
|
||||
for name in names:
|
||||
exec("import mode.%s; mode.%s.install(self)" % (name, name))
|
||||
|
||||
|
|
25
buffer.py
25
buffer.py
|
@ -398,6 +398,31 @@ class ConsoleBuffer(Buffer):
|
|||
def readonly(self):
|
||||
return True
|
||||
|
||||
# console is another singleton
|
||||
iperl = None
|
||||
class IperlBuffer(Buffer):
|
||||
btype = 'iperl'
|
||||
modename = 'iperl'
|
||||
def __new__(cls, *args, **kwargs):
|
||||
global iperl
|
||||
if iperl is None:
|
||||
iperl = object.__new__(IperlBuffer, *args, **kwargs)
|
||||
return iperl
|
||||
def __init__(self):
|
||||
Buffer.__init__(self)
|
||||
self.clear()
|
||||
def clear(self):
|
||||
iperl.set_data('', force=True)
|
||||
def name(self):
|
||||
return '*IPerl*'
|
||||
def changed(self):
|
||||
return False
|
||||
def close(self):
|
||||
global iperl
|
||||
iperl = None
|
||||
def readonly(self):
|
||||
return True
|
||||
|
||||
class BinaryDataException(Exception):
|
||||
pass
|
||||
|
||||
|
|
|
@ -186,14 +186,15 @@ class ConsoleTab(method.Method):
|
|||
|
||||
class ConsoleBaseMethod(method.Method):
|
||||
subcls = method.Method
|
||||
subbuf = '*Console*'
|
||||
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*'):
|
||||
if not a.has_buffer_name(self.subbuf):
|
||||
raise Exception, "No console found!"
|
||||
w2 = a.bufferlist.get_buffer_by_name('*Console*').windows[0]
|
||||
w2 = a.bufferlist.get_buffer_by_name(self.subbuf).windows[0]
|
||||
self.submethod.execute(w2, **vargs)
|
||||
|
||||
class ConsolePageUp(ConsoleBaseMethod):
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import color, mode
|
||||
#from lex import Grammar, PatternRule, RegionRule
|
||||
#from mode.python import StringGrammar, PythonGrammar
|
||||
|
||||
#class ReprGrammar(Grammar):
|
||||
# rules = [
|
||||
# RegionRule(r'string', r'"', StringGrammar, r'"'),
|
||||
# RegionRule(r'string', r"'", StringGrammar, r"'"),
|
||||
# ]
|
||||
#class ConsoleGrammar(Grammar):
|
||||
# rules = [
|
||||
# PatternRule(r'console_mesg', r'^[A-Za-z].*$'),
|
||||
# PatternRule(r'console_input', r'^>>>.*$'),
|
||||
# PatternRule(r'console_input', r'^-->.*$'),
|
||||
# RegionRule(r'string', r'"', StringGrammar, r'"'),
|
||||
# RegionRule(r'string', r"'", StringGrammar, r"'"),
|
||||
# #RegionRule(r'console_repr', r"<", ReprGrammar, r">"),
|
||||
# PatternRule(r'console_reserved', r'True|False|None'),
|
||||
# PatternRule(r'console_bareword', r'[a-zA-Z_][a-zA-Z0-9_]*'),
|
||||
# ]
|
||||
class Console(mode.Fundamental):
|
||||
modename = 'IPerl'
|
||||
# grammar = ConsoleGrammar()
|
||||
# colors = {
|
||||
# 'console_mesg': ('magenta', 'default', 'bold'),
|
||||
# 'console_input': ('cyan', 'default', 'bold'),
|
||||
# 'console_reserved': ('magenta', 'default', 'bold'),
|
||||
# 'console_bareword': ('default', 'default', 'bold'),
|
||||
# 'console_repr.start': ('default', 'default', 'bold'),
|
||||
# 'console_repr.null': ('blue', 'default', 'bold'),
|
||||
# 'console_repr.string.start': ('cyan', 'default', 'bold'),
|
||||
# 'console_repr.string.null': ('cyan', 'default', 'bold'),
|
||||
# 'console_repr.string.end': ('cyan', 'default', 'bold'),
|
||||
# 'console_repr.end': ('default', 'default', 'bold'),
|
||||
# }
|
||||
|
||||
install = Console.install
|
|
@ -0,0 +1,167 @@
|
|||
import code, re, string, StringIO, sys, traceback
|
||||
import buffer, color, completer, lex, method, mode, mode.mini, mode.consolemini, window
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
#from lex import Grammar, PatternRule
|
||||
from mode.perl import PerlGrammar
|
||||
from point import Point
|
||||
|
||||
PAD = ' '
|
||||
LIMIT = 79
|
||||
|
||||
class IperlExec(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('*IPerl*'):
|
||||
raise Exception, "No iperl found!"
|
||||
b = a.bufferlist.get_buffer_by_name('*IPerl*')
|
||||
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)
|
||||
|
||||
w.mode.pipe.stdin.write("ENTER:%s\n" % s)
|
||||
w.mode.pipe.stdin.flush()
|
||||
output = w.mode._read()
|
||||
b.insert_string(b.get_buffer_end(), output, force=True)
|
||||
|
||||
class IperlTab(method.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, PerlGrammar)
|
||||
tokens = list(l.lex([s]))
|
||||
|
||||
t = None
|
||||
for t2 in tokens:
|
||||
if t2.x < x and t2.end_x() >= x:
|
||||
t = t2
|
||||
break
|
||||
if t is None:
|
||||
return
|
||||
|
||||
s = t.string
|
||||
w.mode.pipe.stdin.write("COMPLETE:%s\n" % s)
|
||||
w.mode.pipe.stdin.flush()
|
||||
(typ_, value) = w.mode._readline()
|
||||
assert typ_ == 'COMPLETIONS'
|
||||
|
||||
candidates = [x for x in value.split('|') if x]
|
||||
w.mode._read()
|
||||
|
||||
if candidates:
|
||||
s = completer.find_common_string(candidates)
|
||||
w.buffer.delete(Point(t.x, 0), Point(t.end_x(), 0), force=True)
|
||||
w.insert_string_at_cursor(s)
|
||||
mode.mini.use_completion_window(a, s, candidates)
|
||||
|
||||
class IperlStart(method.Method):
|
||||
'''Evaluate python expressions (for advanced use and debugging only)'''
|
||||
def execute(self, w, **vargs):
|
||||
a = w.application
|
||||
if not a.has_buffer_name('*IPerl*'):
|
||||
b = buffer.IperlBuffer()
|
||||
a.add_buffer(b)
|
||||
window.Window(b, a)
|
||||
b = a.bufferlist.get_buffer_by_name('*IPerl*')
|
||||
if a.window().buffer is not b:
|
||||
a.switch_buffer(b)
|
||||
f = lambda x: None
|
||||
w.application.open_mini_buffer('*** ', f, self, None, 'iperlmini')
|
||||
|
||||
class IperlPageUp(mode.consolemini.ConsolePageUp):
|
||||
subbuf = '*IPerl*'
|
||||
class IperlPageDown(mode.consolemini.ConsolePageDown):
|
||||
subbuf = '*IPerl*'
|
||||
class IperlGotoBeginning(mode.consolemini.ConsoleGotoBeginning):
|
||||
subbuf = '*IPerl*'
|
||||
class IperlGotoEnd(mode.consolemini.ConsoleGotoEnd):
|
||||
subbuf = '*IPerl*'
|
||||
|
||||
class IperlMini(mode.Fundamental):
|
||||
modename = 'IperlMini'
|
||||
actions = [IperlExec, IperlTab, IperlStart,
|
||||
IperlPageUp, IperlPageDown, IperlGotoBeginning, IperlGotoEnd]
|
||||
readre = re.compile('^([A-Z]+):(.*)\n$')
|
||||
def _readline(self):
|
||||
line = self.pipe.stdout.readline()
|
||||
m = self.readre.match(line)
|
||||
if m:
|
||||
return (m.group(1), m.group(2))
|
||||
else:
|
||||
return ('RAW', line.rstrip())
|
||||
def _read(self):
|
||||
output = []
|
||||
while True:
|
||||
(type_, value) = self._readline()
|
||||
if type_ == 'PROMPT':
|
||||
self.window.application.set_mini_buffer_prompt(value + ' ')
|
||||
break
|
||||
elif type_ in ('ERROR', 'RESULT'):
|
||||
output.append(value.replace('\\n', '\n').replace('\\\\', '\\'))
|
||||
elif type_ == 'RAW':
|
||||
output.append(value)
|
||||
return '\n'.join(output) + '\n'
|
||||
|
||||
def __init__(self, w):
|
||||
mode.Fundamental.__init__(self, w)
|
||||
self.bindings = {}
|
||||
self.history = ['']
|
||||
self.hindex = 0
|
||||
|
||||
cmd = ('iperl', '-p')
|
||||
self.pipe = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
|
||||
(type_, value) = self._readline()
|
||||
assert type_ == 'PROMPT', type_
|
||||
w.application.set_mini_buffer_prompt('%s ' % value.strip())
|
||||
|
||||
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('iperl-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('iperl-tab', ('TAB',))
|
||||
self.add_bindings('iperl-page-up', ('M-v',))
|
||||
self.add_bindings('iperl-page-down', ('C-v',))
|
||||
self.add_bindings('iperl-goto-beginning', ('M-<',))
|
||||
self.add_bindings('iperl-goto-end', ('M->',))
|
||||
for c in string.letters + string.digits + string.punctuation:
|
||||
self.add_binding('insert-string-%s' % c, c)
|
||||
|
||||
install = IperlMini.install
|
32
mode/mini.py
32
mode/mini.py
|
@ -1,6 +1,21 @@
|
|||
import string
|
||||
import buffer, method, mode, window
|
||||
|
||||
def use_completion_window(app, s, candidates):
|
||||
if app.completion_window_is_open():
|
||||
w = app.get_completion_window()
|
||||
if w.buffer._completion != s:
|
||||
app.close_completion_buffer()
|
||||
|
||||
if app.completion_window_is_open():
|
||||
w = app.get_completion_window()
|
||||
if w.last_is_visible():
|
||||
w.goto_beginning()
|
||||
else:
|
||||
w.page_down()
|
||||
elif len(candidates) > 1:
|
||||
app.open_completion_buffer(s, sorted(candidates))
|
||||
|
||||
class MiniCallback(method.Method):
|
||||
def execute(self, w, **vargs):
|
||||
app = w.application
|
||||
|
@ -19,21 +34,8 @@ class MiniTabComplete(method.Method):
|
|||
s2, exists, complete = b.tabber.tab_string(s1, w)
|
||||
b.set_data(s2)
|
||||
|
||||
if app.completion_window_is_open():
|
||||
w2 = app.get_completion_window()
|
||||
if w2.buffer._completion != s2:
|
||||
app.close_completion_buffer()
|
||||
|
||||
if app.completion_window_is_open():
|
||||
w2 = app.get_completion_window()
|
||||
if w2.last_is_visible():
|
||||
w2.goto_beginning()
|
||||
else:
|
||||
w2.page_down()
|
||||
else:
|
||||
candidates = sorted(b.tabber.get_candidates(s1, w))
|
||||
if len(candidates) > 1:
|
||||
app.open_completion_buffer(s2, candidates)
|
||||
candidates = b.tabber.get_candidates(s1, w)
|
||||
use_completion_window(app, s2, candidates)
|
||||
|
||||
class Mini(mode.Fundamental):
|
||||
modename = 'Mini'
|
||||
|
|
|
@ -0,0 +1,273 @@
|
|||
#!/usr/bin/perl
|
||||
#
|
||||
# by Erik Osheim
|
||||
#
|
||||
# licensed under the GNU GPL version 2
|
||||
|
||||
use Data::Dumper;
|
||||
use File::Basename;
|
||||
use Getopt::Long;
|
||||
use Perl6::Slurp;
|
||||
use Scalar::Util;
|
||||
use Term::ReadLine;
|
||||
|
||||
Getopt::Long::Configure('bundling');
|
||||
|
||||
$| = 1;
|
||||
$Data::Dumper::Terse = 1;
|
||||
$Data::Dumper::Indent = 1;
|
||||
|
||||
sub usage {
|
||||
my($status) = @_;
|
||||
my $prog = basename($0);
|
||||
print <<EOT;
|
||||
usage: $prog [options]
|
||||
-h,--help show this message
|
||||
-e,--eval STR eval STR before interaction
|
||||
-p,--pipe run in pipe mode (as a subprocess)
|
||||
-q,--quiet do not output eval results
|
||||
-r,--run PATH run PATH before interaction
|
||||
-v,--verbose output eval results (default)
|
||||
|
||||
perl needs a good interpreter.
|
||||
EOT
|
||||
exit($status);
|
||||
}
|
||||
|
||||
my @OLDARGV = @ARGV;
|
||||
my $verbose = 'yes';
|
||||
my $pipe;
|
||||
my @preload;
|
||||
GetOptions(
|
||||
'help|h' => sub { usage(0); },
|
||||
'eval|e=s' => sub { push(@preload, ['eval', $_[1]]); },
|
||||
'pipe|p' => sub { $pipe = 'line' },
|
||||
'quiet|q' => sub { $verbose = 0 },
|
||||
'run|r=s' => sub { push(@preload, ['run', $_[1]]); },
|
||||
'use|u=s' => sub { push(@preload, ['use', $_[1]]); },
|
||||
'verbose|v' => sub { $verbose = 'please'; },
|
||||
) || usage(1);
|
||||
|
||||
my ($prompt, $input) = (">>>", "");
|
||||
unless($pipe) {
|
||||
print "Welcome to Erik's Perl Interpreter\n";
|
||||
print "(Type \"help\", \"exit\", or something else)\n";
|
||||
}
|
||||
|
||||
my $pkgregex = qr/^(?:[a-zA-Z_][a-zA-Z0-9_]*::)+$/;
|
||||
my $nameregex = qr/^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
||||
sub sigilfind {
|
||||
my ($pkg, $sigil, $base, $proc) = @_;
|
||||
$base = "" unless $base;
|
||||
$proc = {$pkg => 1} unless $proc;
|
||||
$pkg = $base if $base;
|
||||
my @results;
|
||||
foreach my $item (eval("keys(\%${pkg})")) {
|
||||
my $item2 = $base . $item;
|
||||
next if $proc->{$item2};
|
||||
if($item =~ m/$nameregex/) {
|
||||
push(@results, $item2) if eval("defined(${sigil}::${base}${item})");
|
||||
} elsif($item =~ m/$pkgregex/) {
|
||||
$proc->{$item2} = 1;
|
||||
push(@results, sigilfind($item2, $sigil, $item2, $proc));
|
||||
}
|
||||
}
|
||||
return @results;
|
||||
}
|
||||
|
||||
sub _repr {
|
||||
my ($item) = @_;
|
||||
if(!defined($item)) {
|
||||
return 'undef';
|
||||
} elsif(Scalar::Util::blessed($item)) {
|
||||
return "$item";
|
||||
} elsif(ref($item) eq 'CODE') {
|
||||
return "$item";
|
||||
} else {
|
||||
my $s = Dumper($item);
|
||||
$s =~ s/\n+$//;
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
sub repr {
|
||||
my @output;
|
||||
foreach my $item (@_) {
|
||||
push(@output, _repr($item));
|
||||
}
|
||||
return join("\n", @output);
|
||||
}
|
||||
|
||||
sub escape {
|
||||
my($s) = @_;
|
||||
$s =~ s/\\/\\\\/g;
|
||||
$s =~ s/\n/\\n/g;
|
||||
return $s;
|
||||
}
|
||||
|
||||
sub _draw {
|
||||
my ($s, $prefix, $suffix) = @_;
|
||||
if($pipe) {
|
||||
print "$prefix:" . escape($s) . "\n";
|
||||
} else {
|
||||
print $s . ($suffix ? $suffix : '');
|
||||
}
|
||||
}
|
||||
|
||||
sub draw_prompt {
|
||||
my($p) = @_;
|
||||
_draw($p, "PROMPT", " ");
|
||||
}
|
||||
sub draw_result {
|
||||
my ($result) = @_;
|
||||
$result = 'undef' unless defined($result);
|
||||
_draw($result, "RESULT", "\n");
|
||||
}
|
||||
sub draw_error {
|
||||
my ($err) = @_;
|
||||
_draw($err, "ERROR");
|
||||
}
|
||||
sub draw_completions {
|
||||
my (@items) = @_;
|
||||
if($pipe) {
|
||||
print 'COMPLETIONS:' . join('|', @items) . "\n";
|
||||
} else {
|
||||
print join("\n", @items) . "\n";
|
||||
}
|
||||
}
|
||||
sub draw_message {
|
||||
my ($mesg) = @_;
|
||||
_draw($mesg, "MESSAGE");
|
||||
}
|
||||
sub draw_exit {
|
||||
_draw("Bye.", "EXIT", "\n");
|
||||
}
|
||||
|
||||
sub complete {
|
||||
my ($word) = @_;
|
||||
$word =~ m/^([&\$%@\*]?)(.*)$/;
|
||||
my $sigil = $1 ? $1 : '&';
|
||||
my $name = $2;
|
||||
my @candidates = grep {
|
||||
$_ =~ m/^$name/
|
||||
} sigilfind('main::', $sigil);
|
||||
return map { "${1}$_" } sort(@candidates);
|
||||
}
|
||||
|
||||
my $HELP = <<EOT;
|
||||
Greetings!
|
||||
|
||||
I'm program is designed to help you write Perl. Like the "perl" command,
|
||||
I can parse and execute Perl code. Unlike it, I can execute perl code
|
||||
interactively, allowing you to call functions, save their results, inspect
|
||||
the results, and repeat.
|
||||
|
||||
I contain a lot of tricky functionality.
|
||||
|
||||
One side-note: I can't be run under the "strict" pragma; thus, you don't
|
||||
need to use my() or our() to declare variables. The reaon for this has to
|
||||
do with the way I evaluate blocks you enter. Sorry.
|
||||
EOT
|
||||
|
||||
my $term;
|
||||
|
||||
sub main {
|
||||
foreach my $pair (@preload) {
|
||||
if($pair->[0] eq 'eval') {
|
||||
eval $pair->[1];
|
||||
die "failed to eval '$pair->[1]': $@" if $@;
|
||||
} elsif($pair->[0] eq 'run') {
|
||||
die "no path named $pair->[1] found" unless -e $pair->[1];
|
||||
my $data = slurp($pair->[1]);
|
||||
eval $data;
|
||||
die "failed to run $pair->[1]: $@" if $@;
|
||||
} elsif($pair->[0] eq 'use') {
|
||||
eval "use $pair->[1]";
|
||||
die "failed to use $pair->[1]: $@" if $@;
|
||||
}
|
||||
}
|
||||
|
||||
unless($pipe) {
|
||||
$term = Term::ReadLine->new('IPERL');
|
||||
my $attribs = $term->Attribs();
|
||||
$attribs->{special_prefixes} = '$@%*&';
|
||||
$attribs->{completion_function} = sub {
|
||||
my ($word, $line, $x) = @_;
|
||||
return complete($word);
|
||||
};
|
||||
}
|
||||
|
||||
while(1) {
|
||||
my $line;
|
||||
if($pipe) {
|
||||
draw_prompt($prompt);
|
||||
$line = <STDIN>;
|
||||
} else {
|
||||
$line = $term->readline("$prompt ");
|
||||
}
|
||||
last unless defined($line);
|
||||
chomp($line);
|
||||
|
||||
if($pipe) {
|
||||
if($line =~ m/ENTER:(.*)$/) {
|
||||
$line = $1;
|
||||
} else {
|
||||
if($line =~ m/COMPLETE:(.*)$/) {
|
||||
draw_completions(complete($1));
|
||||
} else {
|
||||
draw_error("malformed pipe input line");
|
||||
}
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
if($line eq '') {
|
||||
} elsif($line eq 'exit') {
|
||||
last;
|
||||
} elsif($line eq 'help') {
|
||||
($input, $prompt) = ("", ">>>");
|
||||
draw_message($HELP);
|
||||
} elsif($line eq 'reload') {
|
||||
($input, $prompt) = ("", ">>>");
|
||||
draw_message("reloading...\n");
|
||||
exec($0, @OLDARGV);
|
||||
} elsif($line eq 'sh') {
|
||||
($input, $prompt) = ("", ">>>");
|
||||
system("bash") unless $pipe;
|
||||
} elsif($line =~ m/^sh (.+)$/) {
|
||||
($input, $prompt) = ("", ">>>");
|
||||
system($1) unless $pipe;
|
||||
} elsif($line =~ m/^:tab *(.*)$/) {
|
||||
} elsif($line eq ':code') {
|
||||
draw_completions(sigilfind('main::', '&'));
|
||||
} elsif($line eq ':scalar') {
|
||||
draw_completions(sigilfind('main::', '$'));
|
||||
} elsif($line eq ':hash') {
|
||||
draw_completions(sigilfind('main::', '%'));
|
||||
} elsif($line eq ':array') {
|
||||
draw_completions(sigilfind('main::', '@'));
|
||||
} elsif($line eq ':glob') {
|
||||
draw_completions(sigilfind('main::', '*'));
|
||||
} elsif($line =~ m/^[\t ]/ || $line =~ m/\{ *$/) {
|
||||
$input .= $line;
|
||||
$prompt = "..>";
|
||||
} elsif($line =~ m/\\ *$/) {
|
||||
$line =~ s/\\ *$//;
|
||||
$input .= $line;
|
||||
$prompt = "..>";
|
||||
} else {
|
||||
$input .= $line;
|
||||
my @results = map { chomp($_); repr($_); } eval($input);
|
||||
if($@) {
|
||||
draw_error($@);
|
||||
} elsif(scalar(@results) < 2) {
|
||||
draw_result($results[0]);
|
||||
} else {
|
||||
draw_result(join(", ", @results));
|
||||
}
|
||||
($input, $prompt) = ("", ">>>");
|
||||
}
|
||||
}
|
||||
draw_exit();
|
||||
}
|
||||
main();
|
Loading…
Reference in New Issue