5 Sepia - Simple Emacs-Perl Interface
15 use Scalar
::Util
'looks_like_number';
17 use PadWalker
qw(peek_my peek_our peek_sub closed_over);
23 =item C<@compls = completions($string [, $type])>
25 Find a list of completions for C<$string> with glob type $type.
26 Completion operates on word subparts separated by [:_], so
27 e.g. "S:m_w" completes to "Sepia::my_walksymtable".
33 # Do that crazy multi-word identifier completion thing:
37 s/(?:^|(?<=[A-Za-z\d]))(([^A-Za-z\d])\2*)/[A-Za-z\\d]*$2+/g;
39 } split /:+/, $re, -1;
41 if ($re !~ /[^\w\d_^:]/) {
42 $re =~ s/(?<=[A-Za-z\d])(([^A-Za-z\d])\2*)/[A-Za-z\\d]*$2+/g;
55 } grep /$_[0]/, keys %$stash;
59 _completions1
("$stash$_", @_);
60 } grep /$re.*::$/, keys %$stash;
66 _completions1
'::', _apropos_re
($_[0]);
71 %sigil = qw(ARRAY @ SCALAR $ HASH %);
77 my ($str, $type, $infunc) = @_;
78 map { s/^:://; $_ } ($type ?
do {
79 (grep { defined *{$_}{$type} } _completions
$str),
80 (defined $infunc && defined *{$infunc}{CODE
}) ?
do {
81 my ($apre) = _apropos_re
($str);
82 my $st = $sigil{$type};
84 (my $tmp = $_) =~ s/^\Q$st//;
90 defined *{$_}{CODE
} || defined *{$_}{IO
}
91 || (/::$/ && defined *{$_}{HASH
});
96 =item C<@locs = location(@names)>
98 Return a list of [file, line, name] triples, one for each function
108 if (my ($pfx, $name) = $str =~ /^([\%\$\@]?)(.+)/) {
110 warn "Sorry -- can't lookup variables.";
113 # XXX: svref_2object only seems to work with a package
114 # tacked on, but that should probably be done
116 $name = 'main::'.$name unless $name =~ /::/;
117 my $cv = B
::svref_2object
(\
&{$name});
118 if ($cv && defined($cv = $cv->START) && !$cv->isa('B::NULL')) {
119 my ($file, $line) = ($cv->file, $cv->line);
120 if ($file !~ /^\//) {
128 my ($shortname) = $name =~ /^(?:.*::)([^:]+)$/;
129 [Cwd
::abs_path
($file), $line, $shortname || $name]
131 # warn "Bad CV for $name: $cv";
142 =item C<@matches = apropos($name [, $is_regex])>
144 Search for function C<$name>, either in all packages or, if C<$name>
145 is qualified, only in one package. If C<$is_regex> is true, the
146 non-package part of C<$name> is a regular expression.
150 sub my_walksymtable
(&*)
156 &$f for keys %$stash;
157 _walk
("$stash$_") for grep /(?<!main)::$/, keys %$stash;
164 my ($it, $re, @types) = @_;
167 $stashp = grep /STASH/, @types;
168 @types = grep !/STASH/, @types;
173 if ($it =~ /^(.*::)([^:]+)$/) {
174 my ($stash, $name) = ($1, $2);
176 my $name = qr/^$name/;
181 my $stashnm = "$stash$_";
184 || scalar grep { defined *{$stashnm}{$_} } @types)
187 defined &$it ?
$it : ();
191 my $findre = $re ?
qr/$it/ : qr/^\Q$it\E$/;
193 push @ret, "$stash$_" if /$findre/;
195 map { s/^:*(?:main:+)*//;$_ } @ret;
199 =item C<@names = mod_subs($pack)>
201 Find subs in package C<$pack>.
209 my $stash = \
%{"$p\::"};
210 if (defined $stash) {
211 grep { defined &{"$p\::$_"} } keys %$stash;
215 =item C<@decls = mod_decls($pack)>
217 Generate a list of declarations for all subroutines in package
228 my $proto = prototype(\
&{"$pack\::$sn"});
229 $proto = defined($proto) ?
"($proto)" : '';
232 return wantarray ?
@ret : join '', @ret;
235 =item C<$info = module_info($module, $type)>
237 Emacs-called function to get module information.
246 $info = Module
::Info
->new_from_file($m);
248 (my $file = $m) =~ s
|::|/|g
;
250 if (exists $INC{$file}) {
251 $info = Module
::Info
->new_from_loaded($m);
253 $info = Module
::Info
->new_from_module($m);
261 =item C<$file = mod_file($mod)>
263 Find the likely file owner for module C<$mod>.
271 while ($m && !exists $INC{"$m.pm"}) {
272 $m =~ s
#(?:^|/)[^/]+$##;
274 $m ?
$INC{"$m.pm"} : undef;
277 =item C<lexicals($subname)>
279 Return a list of C<$subname>'s lexical variables. Note that this
280 includes all nested scopes -- I don't know if or how Perl
281 distinguishes inner blocks.
287 my $cv = B
::svref_2object
(\
&{+shift});
288 return unless $cv && ($cv = $cv->PADLIST);
289 my ($names, $vals) = $cv->ARRAY;
291 my $name = $_->PV; $name =~ s/\0.*$//; $name
292 } grep B
::class($_) ne 'SPECIAL', $names->ARRAY;
295 =item C<$lisp = tolisp($perl)>
297 Convert a Perl scalar to some ELisp equivalent.
303 my $thing = @_ == 1 ?
shift : \
@_;
306 if (looks_like_number
$thing) {
311 } elsif ($t eq 'GLOB') {
312 (my $name = $$thing) =~ s/\*main:://;
314 } elsif ($t eq 'ARRAY') {
315 '(' . join(' ', map { tolisp
($_) } @
$thing).')'
316 } elsif ($t eq 'HASH') {
317 '(' . join(' ', map {
318 '(' . tolisp
($_) . " . " . tolisp
($thing->{$_}) . ')'
320 } elsif ($t eq 'Regexp') {
321 "'(regexp . \"" . quotemeta($thing) . '")';
322 # } elsif ($t eq 'IO') {
328 =item C<printer(\@res [, $iseval])>
330 Print C<@res> appropriately on the current filehandle. If C<$iseval>
331 is true, use terse format. Otherwise, use human-readable format.
339 my ($iseval, $wantarray) = @_;
345 local $Data::Dumper
::Deparse
= 1;
346 local $Data::Dumper
::Indent
= 0;
347 $__ = Data
::Dumper
::Dumper
(@res > 1 ? \
@res : $res[0]);
348 $__ =~ s/^\$VAR1 = //;
354 print ';;;', length $__, "\n$__\n";
362 Execute a command interpreter on FH. The prompt has a few bells and
365 * Obviously-incomplete lines are treated as multiline input.
367 * C<die> is overridden to enter a recursive interpreter at the point
368 C<die> is called. From within this interpreter, you can examine a
369 backtrace by calling "bt", return from C<die> with "r EXPR", or
370 go ahead and die by pressing Control-c.
372 Behavior is controlled in part through the following package-globals:
376 =item C<$PS1> -- the default prompt
378 =item C<$stopdie> -- true to enter the inspector on C<die()>
380 =item C<$stopwarn> -- true to enter the inspector on C<warn()>
382 =item C<$fancy> -- true for pretty-printing via L<Data::Dumper>
384 =item C<%REPL> -- maps shortcut names to handlers
388 use vars
qw($PS1 $dies $stopdie $stopwarn $fancy %REPL %RK $PACKAGE);
397 %REPL = (help => \&Sepia::repl_help,
398 cd => \&Sepia::repl_chdir,
399 package => \&Sepia::repl_package);
400 %RK = abbrev keys %REPL;
409 Data::Dumper->Dump([$_[0]], [$_[1]]);
416 my ($fn, @args) = @_;
418 uplevel $FRAMES, $fn, @args
424 my ($expr, $env) = @_;
428 next unless /^([\$\@%])(.+)/;
429 $str .= "local *$2 = \$::ENV->{'$_'}; ";
431 eval "do { no strict; $str $expr }";
436 my ($lev, $exp) = $_[0] =~ /^\s*(\d+)\s+(.*)/;
438 (0, eval_in_env($exp, PadWalker::peek_my(0+$lev)));
445 my $sub = (caller $i)[3];
447 my $h = PadWalker::peek_my($i);
448 print "[$i] $sub:\n";
449 for (sort keys %$h) {
450 print "\t", Sepia::Dump($h->{$_}, $_);
459 REPL commands (prefixed with ','):
460 cd DIR Change directory to DIR
461 package PACKAGE Set evaluation package to PACKAGE
468 chomp(my $dir = shift);
471 my $ecmd = '(cd "'.Cwd
::getcwd
().'")';
472 print ";;;###".length($ecmd)."\n$ecmd\n";
474 warn "Can't chdir\n";
481 chomp(my $p = shift);
483 if (defined %{$p.'::'}) {
485 # my $ecmd = '(setq sepia-eval-package "'.$p.'")';
486 # print ";;;###".length($ecmd)."\n$ecmd\n";
488 warn "Can't go to package $p -- doesn't exist!\n";
496 Inspector commands (prefixed with ','):
497 \\C-c Pop one debugger level
498 backtrace show backtrace
499 inspect N ... inspect lexicals in frame(s) N ...
500 eval N EXPR evaluate EXPR in lexical environment of frame N
501 return EXPR return EXPR
502 die/warn keep on dying/warning
519 my ($buf, $wantarray, $pkg) = @_;
521 local $PACKAGE = $pkg || $PACKAGE;
522 $buf = "do { package $PACKAGE; no strict; $buf }";
523 # open O, ">>/tmp/blah";
524 # print O "##############################\n$buf";
526 if ($wantarray || !defined($wantarray)) {
535 my ($fh, $level) = @_;
536 select((select($fh), $|=1)[0]);
541 my $nextrepl = sub { $sigged = 1; };
544 my $MSG = "('\\C-c' to exit, ',h' for help)";
546 backtrace
=> \
&Sepia
::debug_backtrace
,
547 inspect
=> \
&Sepia
::debug_inspect
,
548 eval => \
&Sepia
::debug_upeval
,
549 return => \
&Sepia
::debug_return
,
550 help
=> \
&Sepia
::debug_help
,
552 local *CORE
::GLOBAL
::die = sub {
555 local $dies = $dies+1;
556 local $PS1 = "*$dies*> ";
558 local %Sepia::REPL
= (
559 %dhooks, die => sub { local $Sepia::stopdie
=0; die @dieargs });
560 local %Sepia::RK
= abbrev
keys %Sepia::REPL
;
561 print "@_\nDied $MSG\n";
562 return Sepia
::repl
($fh, 1);
567 local *CORE
::GLOBAL
::warn = sub {
569 local $dies = $dies+1;
570 local $PS1 = "*$dies*> ";
572 local %Sepia::REPL
= (
573 %dhooks, warn => sub { local $Sepia::stopwarn
=0; warn @dieargs });
574 local %Sepia::RK
= abbrev
keys %Sepia::REPL
;
575 print "@_\nWarned $MSG\n";
576 return Sepia
::repl
($fh, 1);
582 my @sigs = qw(INT TERM PIPE ALRM);
584 $SIG{$_} = $nextrepl for @sigs;
585 repl
: while (my $in = <$fh>) {
594 if ($buf =~ /^<<(\d+)\n(.*)/) {
599 while ($len && defined($tmp = read $fh, $buf, $len, length $buf)) {
604 local $SIG{__WARN__
} = sub {
607 if ($buf =~ /^,(\S+)\s*(.*)/s) {
608 ## Inspector shortcuts
609 if (exists $Sepia::RK
{$1}) {
611 ($ret, @res) = $Sepia::REPL
{$Sepia::RK
{$1}}->($2, wantarray);
613 return wantarray ?
@res : $res[0];
616 print "Unrecignized shortcut '$1'\n";
623 @res = repl_eval
$buf, wantarray;
626 if ($@
=~ /at EOF$/m) {
627 ## Possibly-incomplete line
629 print "*** cancel ***\n", prompt
;
638 Sepia
::printer \
@res, $iseval, wantarray if $iseval;
643 ## Be quiet if it ends with a semicolon.
644 Sepia
::printer \
@res, $iseval, wantarray;
650 print ';;;'.length($tmp)."\n$tmp\n";
661 tolisp
(repl_eval
(shift));