5 Sepia - Simple Emacs-Perl Interface
11 M-x load-library RET sepia RET
14 At the prompt in the C<*perl-interaction*> buffer:
26 use Scalar
::Util
'looks_like_number';
32 use vars
qw($PS1 $dies $STOPDIE $STOPWARN %REPL %RK %REPL_DOC
33 $PACKAGE $WANTARRAY $PRINTER $STRICT $PRINT_PRETTY);
36 eval { require PadWalker; import PadWalker qw(peek_my) };
38 *peek_my
= sub { +{ } };
40 eval { require Lexical
::Persistence
; import Lexical
::Persistence
};
43 print STDERR
"Strict mode requires Lexical::Persistence.\n";
48 my $x = as_boolean
(shift, $STRICT);
50 $STRICT = new Lexical
::Persistence
;
61 Sepia is a set of features to make Emacs a better tool for Perl
62 development. This package contains the Perl side of the
63 implementation, including all user-serviceable parts (for the
64 cross-referencing facility see L<Sepia::Xref>).
66 Though not intended to be used independent of the Emacs interface, the
67 Sepia module's functionality can be used through a rough procedural
70 =head2 C<@compls = completions($string [, $type])>
72 Find a list of completions for C<$string> with glob type $type.
73 Completion operates on word subparts separated by [:_], so
74 e.g. "S:m_w" completes to "Sepia::my_walksymtable".
80 # Do that crazy multi-word identifier completion thing:
82 return qr/.*/ if $re eq '';
85 s/(?:^|(?<=[A-Za-z\d]))(([^A-Za-z\d])\2*)/[A-Za-z\\d]*$2+/g;
87 } split /:+/, $re, -1;
89 if ($re !~ /[^\w\d_^:]/) {
90 $re =~ s/(?<=[A-Za-z\d])(([^A-Za-z\d])\2*)/[A-Za-z\\d]*$2+/g;
100 my $re = shift || '';
102 if (@_ == 0 || !defined $_[0]) {
103 map "$stash$_", grep /$re/, keys %$stash;
106 _completions1
("$stash$_", @_);
107 } grep /$re.*::$/, keys %$stash;
113 _completions1
'::', _apropos_re
($_[0]);
118 %sigil = qw(ARRAY @ SCALAR $ HASH %);
124 my ($str, $type, $infunc) = @_;
129 defined *{$_}{CODE
} || defined *{$_}{IO
}
130 || (/::$/ && defined *{$_}{HASH
});
134 $type eq 'SCALAR' ?
defined ${$_} : defined *{$_}{$type}
136 if (defined $infunc && defined *{$infunc}{CODE
}) {
137 my ($apre) = _apropos_re
($str);
138 my $st = $sigil{$type};
140 (my $tmp = $_) =~ s/^\Q$st//;
146 ## Complete "simple" sequences as abbreviations, e.g.:
147 ## wtci -> Want_To_Complete_It, NOT
149 if (!@ret && $str !~ /[^\w\d]/) {
150 my $broad = join '.*', map "\\b$_", split '', $str;
153 defined *{$_}{CODE
} || defined *{$_}{IO
}
154 || (/::$/ && defined *{$_}{HASH
});
155 } _completions1
'::', qr/$broad/;
158 $type eq 'SCALAR' ?
defined ${$_} : defined *{$_}{$type}
159 } _completions1
'::', qr/$broad/;
161 if (defined $infunc && defined *{$infunc}{CODE
}) {
162 my $st = $sigil{$type};
164 (my $tmp = $_) =~ s/^\Q$st//;
169 ## XXX: Control characters, $", and $1, etc. confuse Emacs, so
172 !looks_like_number
$_ && !/^[^\w\d_]$/ && !/^_</ && !/^[[:cntrl:]]/
173 } map { s/^:://; $_ } @ret;
176 =head2 C<@locs = location(@names)>
178 Return a list of [file, line, name] triples, one for each function
188 if (my ($pfx, $name) = $str =~ /^([\%\$\@]?)(.+)/) {
190 warn "Sorry -- can't lookup variables.";
193 # XXX: svref_2object only seems to work with a package
194 # tacked on, but that should probably be done
196 $name = 'main::'.$name unless $name =~ /::/;
197 my $cv = B
::svref_2object
(\
&{$name});
198 if ($cv && defined($cv = $cv->START) && !$cv->isa('B::NULL')) {
199 my ($file, $line) = ($cv->file, $cv->line);
200 if ($file !~ /^\//) {
208 my ($shortname) = $name =~ /^(?:.*::)([^:]+)$/;
209 [Cwd
::abs_path
($file), $line, $shortname || $name]
211 # warn "Bad CV for $name: $cv";
222 =head2 C<@matches = apropos($name [, $is_regex])>
224 Search for function C<$name>, either in all packages or, if C<$name>
225 is qualified, only in one package. If C<$is_regex> is true, the
226 non-package part of C<$name> is a regular expression.
230 sub my_walksymtable
(&*)
236 &$f for keys %$stash;
237 _walk
("$stash$_") for grep /(?<!main)::$/, keys %$stash;
244 my ($it, $re, @types) = @_;
247 $stashp = grep /STASH/, @types;
248 @types = grep !/STASH/, @types;
253 if ($it =~ /^(.*::)([^:]+)$/) {
254 my ($stash, $name) = ($1, $2);
255 if (!defined %$stash) {
259 my $name = qr/^$name/;
264 my $stashnm = "$stash$_";
267 || scalar grep { defined *{$stashnm}{$_} } @types)
270 defined &$it ?
$it : ();
274 my $findre = $re ?
qr/$it/ : qr/^\Q$it\E$/;
276 push @ret, "$stash$_" if /$findre/;
278 map { s/^:*(?:main:+)*//;$_ } @ret;
282 =head2 C<@names = mod_subs($pack)>
284 Find subs in package C<$pack>.
292 my $stash = \
%{"$p\::"};
293 if (defined $stash) {
294 grep { defined &{"$p\::$_"} } keys %$stash;
298 =head2 C<@decls = mod_decls($pack)>
300 Generate a list of declarations for all subroutines in package
311 my $proto = prototype(\
&{"$pack\::$sn"});
312 $proto = defined($proto) ?
"($proto)" : '';
315 return wantarray ?
@ret : join '', @ret;
318 =head2 C<$info = module_info($module, $type)>
320 Emacs-called function to get module information.
329 $info = Module
::Info
->new_from_file($m);
331 (my $file = $m) =~ s
|::|/|g
;
333 if (exists $INC{$file}) {
334 $info = Module
::Info
->new_from_loaded($m);
336 $info = Module
::Info
->new_from_module($m);
344 =head2 C<$file = mod_file($mod)>
346 Find the likely file owner for module C<$mod>.
354 while ($m && !exists $INC{"$m.pm"}) {
355 $m =~ s
#(?:^|/)[^/]+$##;
357 $m ?
$INC{"$m.pm"} : undef;
360 =head2 C<@mods = package_list>
362 Gather a list of all distributions on the system. XXX UNUSED
370 eval 'require ExtUtils::Installed';
371 $INST = new ExtUtils
::Installed
;
378 sort { $a cmp $b } inst
()->modules;
381 =head2 C<@mods = module_list>
383 Gather a list of all packages (.pm files, really) installed on the
384 system, grouped by distribution. XXX UNUSED
390 @_ = package_list
unless @_;
391 my $incre = join '|', map quotemeta, @INC;
392 $incre = qr
|(?
:$incre)/|;
396 s/$incre//; s
|/|::|g
;$_
397 } grep /\.pm$/, $inst->files($_)]
401 =head2 C<@mods = doc_list>
403 Gather a list of all documented packages (.?pm files, really)
404 installed on the system, grouped by distribution. XXX UNUSED
410 @_ = package_list
unless @_;
414 s/.*man.\///; s|/|::|g
;s/\..?pm//; $_
415 } grep /\..pm$/, $inst->files($_)]
419 =head2 C<lexicals($subname)>
421 Return a list of C<$subname>'s lexical variables. Note that this
422 includes all nested scopes -- I don't know if or how Perl
423 distinguishes inner blocks.
429 my $cv = B
::svref_2object
(\
&{+shift});
430 return unless $cv && ($cv = $cv->PADLIST);
431 my ($names, $vals) = $cv->ARRAY;
433 my $name = $_->PV; $name =~ s/\0.*$//; $name
434 } grep B
::class($_) ne 'SPECIAL', $names->ARRAY;
437 =head2 C<$lisp = tolisp($perl)>
439 Convert a Perl scalar to some ELisp equivalent.
445 my $thing = @_ == 1 ?
shift : \
@_;
448 if (!defined $thing) {
450 } elsif (looks_like_number
$thing) {
455 } elsif ($t eq 'GLOB') {
456 (my $name = $$thing) =~ s/\*main:://;
458 } elsif ($t eq 'ARRAY') {
459 '(' . join(' ', map { tolisp
($_) } @
$thing).')'
460 } elsif ($t eq 'HASH') {
461 '(' . join(' ', map {
462 '(' . tolisp
($_) . " . " . tolisp
($thing->{$_}) . ')'
464 } elsif ($t eq 'Regexp') {
465 "'(regexp . \"" . quotemeta($thing) . '")';
466 # } elsif ($t eq 'IO') {
472 =head2 C<printer(\@res [, $iseval])>
474 Print C<@res> appropriately on the current filehandle. If C<$iseval>
475 is true, use terse format. Otherwise, use human-readable format,
476 which can use either L<Data::Dumper>, L<YAML>, or L<Data::Dump>.
482 local $Data::Dumper
::Deparse
= 1;
483 local $Data::Dumper
::Indent
= 0;
486 local $_ = Data
::Dumper
::Dumper
(@res > 1 ? \
@res : $res[0]);
502 eval { require YAML
};
513 eval { require Data
::Dump
};
525 my ($iseval, $wantarray) = @_;
527 $::__
= @res == 1 ?
$res[0] : [@res];
531 } elsif (@res == 1 && (ref $res[0]) =~ /^PDL/) {
533 } elsif (!$iseval && $PRINT_PRETTY && @res > 1 && grep !ref $_, @res) {
534 $res = columnate
(@res);
541 print ';;;', length $res, "\n$::__\n";
549 Execute a command interpreter on FH. The prompt has a few bells and
552 * Obviously-incomplete lines are treated as multiline input (press
553 'return' twice or 'C-c' to discard).
555 * C<die> is overridden to enter a recursive interpreter at the point
556 C<die> is called. From within this interpreter, you can examine a
557 backtrace by calling "bt", return from C<die> with "r EXPR", or
558 go ahead and die by pressing Control-c.
560 Behavior is controlled in part through the following package-globals:
564 =item C<$PACKAGE> -- evaluation package
566 =item C<$PRINTER> -- result printer (default: print_dumper)
568 =item C<$PS1> -- the default prompt
570 =item C<$STOPDIE> -- true to enter the inspector on C<die()>
572 =item C<$STOPWARN> -- true to enter the inspector on C<warn()>
574 =item C<$STRICT> -- whether 'use strict' is applied to input
576 =item C<$WANTARRAY> -- evaluation context
578 =item C<$PRINT_PRETTY> -- format some output nicely (default = 0)
580 Format some values nicely, independent of $PRINTER. Currently, this
581 displays arrays of scalars as columns.
583 =item C<%REPL> -- maps shortcut names to handlers
585 =item C<%REPL_DOC> -- maps shortcut names to documentation
599 $PRINTER = \
&Sepia
::print_dumper
;
601 %REPL = (help
=> \
&Sepia
::repl_help
,
602 cd
=> \
&Sepia
::repl_chdir
,
603 methods
=> \
&Sepia
::repl_methods
,
604 package => \
&Sepia
::repl_package
,
605 who
=> \
&Sepia
::repl_who
,
606 wantarray => \
&Sepia
::repl_wantarray
,
607 format
=> \
&Sepia
::repl_format
,
608 strict
=> \
&Sepia
::repl_strict
,
609 quit
=> \
&Sepia
::repl_quit
,
613 'cd DIR Change directory to DIR',
615 'format [dumper|dump|yaml|plain]
616 Set output formatter (default: dumper)',
618 'help Display this message',
620 'methods X [RE] List methods for reference or package X,
621 matching optional pattern RE.
624 'package PACKAGE Set evaluation package to PACKAGE',
626 'quit Quit the REPL',
628 'strict [0|1] Turn \'use strict\' mode on or off',
630 'wantarray [0|1] Set or toggle evaluation context',
632 who PACKAGE [RE] List variables and subs in PACKAGE matching optional
636 %RK = abbrev
keys %REPL;
641 "$PACKAGE ".($WANTARRAY ?
'@' : '$').$PS1
646 Data
::Dumper
->Dump([$_[0]], [$_[1]]);
652 my ($expr, $env) = @_;
656 next unless /^([\$\@%])(.+)/;
657 $str .= "local *$2 = \$::ENV->{'$_'}; ";
659 eval "do { no strict; $str $expr }";
664 my ($lev, $exp) = $_[0] =~ /^\s*(\d+)\s+(.*)/;
666 (0, eval_in_env
($exp, peek_my
(0+$lev)));
673 my $sub = (caller $i)[3];
676 print "[$i] $sub:\n";
678 for (sort keys %$h) {
679 local @res = $h->{$_};
680 print "\t$_ = ", $PRINTER->(), "\n";
688 print "REPL commands (prefixed with ','):\n";
689 for (sort keys %REPL) {
691 exists $REPL_DOC{$_} ?
"$REPL_DOC{$_}\n": "$_ (undocumented)\n";
700 $t = 'dumper' if $t eq '';
701 my %formats = abbrev
qw(dumper dump yaml plain);
702 if (exists $formats{$t}) {
704 $PRINTER = \
&{'print_'.$formats{$t}};
706 warn "No such format '$t' (dumper, dump, yaml, plain).\n";
713 chomp(my $dir = shift);
714 $dir =~ s/^~\//$ENV{HOME
}\
//;
715 $dir =~ s/\$HOME/$ENV{HOME}/;
719 my $ecmd = '(cd "'.Cwd
::getcwd
().'")';
720 print ";;;###".length($ecmd)."\n$ecmd\n";
722 warn "Can't chdir\n";
729 my ($pack, $re) = @_;
733 sort grep /$re/, map {
734 (defined %{$pack.'::'.$_} ?
'%'.$_ : (),
735 defined ${$pack.'::'.$_} ?
'$'.$_ : (), # ?
736 defined @
{$pack.'::'.$_} ?
'@'.$_ : (),
737 defined &{$pack.'::'.$_} ?
$_ : (),
739 } grep !/::$/ && !/^(?:_<|[^\w])/, keys %{$pack.'::'};
746 my $width = $ENV{COLUMNS
} || 80;
748 $len = length if $len < length;
750 my $nc = int($width / ($len+1)) || 1;
751 my $nr = int(@_ / $nc) + (@_ % $nc ?
1 : 0);
752 my $fmt = ('%-'.($len+1).'s') x
($nc-1) . "%s\n";
753 my @incs = map { $_ * $nr } 0..$nc-1;
755 for my $r (0..$nr-1) {
756 $str .= sprintf $fmt, map { $_ || '' } @_[map { $r + $_ } @incs];
764 my ($pkg, $re) = split ' ', shift;
765 print columnate who
($pkg || $PACKAGE, $re);
773 (grep(defined *{"$pack\::$_"}{CODE
}, keys %{$pack.'::'}),
774 defined @
{$pack.'::ISA'} ?
(map methods
($_), @
{$pack.'::ISA'}) : ());
779 my ($x, $re) = split ' ', shift;
783 $x = repl_eval
("ref $x");
788 print columnate
sort { $a cmp $b } grep /$re/, methods
$x;
794 my ($val, $cur) = @_;
796 length($val) ?
$val : !$cur;
801 $WANTARRAY = as_boolean
shift, $WANTARRAY;
807 chomp(my $p = shift);
809 if (defined %{$p.'::'}) {
811 # my $ecmd = '(setq sepia-eval-package "'.$p.'")';
812 # print ";;;###".length($ecmd)."\n$ecmd\n";
814 warn "Can't go to package $p -- doesn't exist!\n";
827 Inspector commands (prefixed with ','):
828 \\C-c Pop one debugger level
829 backtrace show backtrace
830 inspect N ... inspect lexicals in frame(s) N ...
831 eval N EXPR evaluate EXPR in lexical environment of frame N
832 return EXPR return EXPR
833 die/warn keep on dying/warning
850 my ($buf, $wantarray, $pkg) = @_;
852 local $PACKAGE = $pkg || $PACKAGE;
855 $buf = 'scalar($buf)';
857 my $ctx = join(',', keys %{$STRICT->get_context('_')});
858 $ctx = $ctx ?
"my ($ctx);" : '';
859 $buf = eval "sub { package $PACKAGE; use strict; $ctx $buf }";
861 print STDERR
"ERROR\n$@\n";
866 $buf = "do { package $PACKAGE; no strict; $buf }";
877 my ($fh, $level) = @_;
878 select((select($fh), $|=1)[0]);
883 my $nextrepl = sub { $sigged = 1; };
886 my $MSG = "('\\C-c' to exit, ',h' for help)";
888 backtrace
=> \
&Sepia
::debug_backtrace
,
889 inspect
=> \
&Sepia
::debug_inspect
,
890 eval => \
&Sepia
::debug_upeval
,
891 return => \
&Sepia
::debug_return
,
892 help
=> \
&Sepia
::debug_help
,
894 local *CORE
::GLOBAL
::die = sub {
897 local $dies = $dies+1;
898 local $PS1 = "*$dies*> ";
900 local %Sepia::REPL
= (
901 %dhooks, die => sub { local $Sepia::STOPDIE
=0; die @dieargs });
902 local %Sepia::RK
= abbrev
keys %Sepia::REPL
;
903 print "@_\nDied $MSG\n";
904 return Sepia
::repl
($fh, 1);
909 local *CORE
::GLOBAL
::warn = sub {
911 local $dies = $dies+1;
912 local $PS1 = "*$dies*> ";
914 local %Sepia::REPL
= (
915 %dhooks, warn => sub { local $Sepia::STOPWARN
=0; warn @dieargs });
916 local %Sepia::RK
= abbrev
keys %Sepia::REPL
;
917 print "@_\nWarned $MSG\n";
918 return Sepia
::repl
($fh, 1);
923 Sepia version $Sepia::VERSION.
924 Press ",h" for help, or "^D" or ",q" to exit.
927 my @sigs = qw(INT TERM PIPE ALRM);
929 $SIG{$_} = $nextrepl for @sigs;
930 repl
: while (my $in = <$fh>) {
939 if ($buf =~ /^<<(\d+)\n(.*)/) {
944 while ($len && defined($tmp = read $fh, $buf, $len, length $buf)) {
949 local $SIG{__WARN__
} = sub {
952 if ($buf =~ /^,(\S+)\s*(.*)/s) {
953 ## Inspector shortcuts
955 if (exists $Sepia::RK
{$short}) {
959 ($ret, @res) = $Sepia::REPL
{$Sepia::RK
{$short}}->($arg, wantarray);
961 return wantarray ?
@res : $res[0];
964 if (grep /^$short/, keys %Sepia::REPL
) {
965 print "Ambiguous shortcut '$short': ",
966 join(', ', sort grep /^$short/, keys %Sepia::REPL
),
969 print "Unrecognized shortcut '$short'\n";
977 @res = repl_eval
$buf, wantarray;
980 if ($@
=~ /at EOF$/m) {
981 ## Possibly-incomplete line
983 print "Error:\n$@\n*** cancel ***\n", prompt
;
992 Sepia
::printer \
@res, $iseval, wantarray if $iseval;
996 if ($buf !~ /;$/ && $buf !~ /^,/) {
997 ## Be quiet if it ends with a semicolon, or if we
998 ## executed a shortcut.
999 Sepia
::printer \
@res, $iseval, wantarray;
1005 print ';;;'.length($tmp)."\n$tmp\n";
1016 tolisp
(repl_eval
(shift));
1019 =head2 C<$status = html_module_list($file [, $prefix])>
1021 Generate an HTML list of installed modules, looking inside of
1022 packages. If C<$prefix> is missing, uses "about://perldoc/".
1024 =head2 C<$status = html_package_list($file [, $prefix])>
1026 Generate an HTML list of installed top-level modules, without looking
1027 inside of packages. If C<$prefix> is missing, uses
1032 sub html_module_list
1034 my ($file, $base) = @_;
1035 $base ||= 'about://perldoc/';
1037 return unless $inst;
1038 return unless open OUT
, ">$file";
1039 print "<html><body><ul>";
1042 for (package_list
) {
1043 push @
{$ns{$1}}, $_ if /^([^:]+)/;
1045 for (sort keys %ns) {
1046 print qq{<li
><b
>$_</b
><ul
>} if @
{$ns{$_}} > 1;
1047 for (sort @
{$ns{$_}}) {
1049 s/.*man.\///; s|/|::|g
; s/\..?pm//; $_
1050 } grep /\.\dpm$/, sort $inst->files($_);
1052 print qq{<li
><a href
="$base$fs[0]">$fs[0]</a
>};
1054 print qq{<li
>$_<ul
>};
1056 print qq{<li
><a href
="$base$_">$_</a
>};
1061 print qq{</ul
>} if @
{$ns{$_}} > 1;
1063 print "</ul></body></html>\n";
1068 sub html_package_list
1070 my ($file, $base) = @_;
1071 return unless inst
();
1072 $base ||= 'about://perldoc/';
1073 return unless open OUT
, ">$file";
1074 print OUT
"<html><body><ul>";
1077 for (package_list
) {
1078 push @
{$ns{$1}}, $_ if /^([^:]+)/;
1080 for (sort keys %ns) {
1081 if (@
{$ns{$_}} == 1) {
1083 qq{<li
><a href
="$base$ns{$_}[0]">$ns{$_}[0]</a
>};
1085 print OUT
qq{<li
><b
>$_</b
><ul
>};
1086 print OUT
qq{<li
><a href
="$base$_">$_</a
>}
1087 for sort @
{$ns{$_}};
1088 print OUT
qq{</ul
>};
1091 print OUT
"</ul></body></html>\n";
1101 See the README file included with the distribution.
1105 Sean O'Rourke, E<lt>seano@cpan.orgE<gt>
1107 Bug reports welcome, patches even more welcome.
1111 Copyright (C) 2005-2007 Sean O'Rourke. All rights reserved, some
1112 wrongs reversed. This module is distributed under the same terms as