Sepia is a set of Perl development tools for Emacs supporting code navigation and interactive evaluation.
Sepia is a set of tools for Perl development in Emacs. Its goal is to extend CPerl mode to support fast code navigation and interactive development. It is inspired by Emacs' current support for a number of other languages, including Lisp, Python, and Emacs Lisp.
To install Sepia, its Emacs Lisp files must be in Emacs'
load-path
, and the lib directory must be in Perl's
@INC
. Assuming that Sepia has been unpacked in
~/sepia, it can be installed by adding the following lines to
~/.emacs:
(add-to-list 'load-path "~/sepia") (setq sepia-perl5lib (list (expand-file-name "~/sepia/lib"))) (defalias 'perl-mode 'sepia-mode) (require 'sepia)
Then to bring up the interactive Perl prompt, type M-x sepia-repl.
A development environment should support three activities: code spelunking, interaction, and customization. Emacs as an environment for developing Emacs Lisp thoroughly supports all of them: It has commands to visit individual functions' code and documentation, commands to evaluate or step through expressions, and an architecture that encourages customization in Emacs Lisp. As an environment for Perl, however, it is lacking: there is limited interactivity with the Perl debugger, and reasonable documentation browsing, but no support for navigating, editing, and re-evaluating code. Sepia attempts to remedy the situation.
Modern IDEs also support these three activities, but do so awkwardly. Rather than having functions to visit definitions (find-function) and search for functions (apropos), they clutter the screen with class and file trees. Rather than supporting interactive evaluation of small pieces of code, they perform background semantic checking on whole projects and highlight errors. Rather than allowing minor customizations to grow organically into features, they support limited configuration files and baroque plug-in APIs. Sepia tries to adhere to the apparent Emacs philosophy that rich semantic information should be unobtrusive, and that the best way to build working code is to start by experimenting with small pieces.
Language support packages for Emacs vary widely in the degree to which they make use of or replace existing Emacs features. Minimal modes provide keyword-based syntax highlighting and an unadorned comint buffer as an interpreter. Others provide their own specialized equivalents of comint, eldoc, completion, and other Emacs features. Sepia takes a third approach by trying to do as much as possible with existing Emacs features, even when they are not optimal for Perl. For example, it uses comint to communicate with the subprocess, eldoc to display documentation, and grep to list source locations.
This approach has three advantages: First, it maximizes the number of features that can be supported with limited development time. Second, it respects users' settings. A seasoned Emacs user may have changed hundreds of settings, so a mode that reimplements features will have to support equivalent settings, and will force the user to re-specify them. Finally, this approach respects decades of development spent, as Neal Stephenson put it, “focused with maniacal intensity on the deceptively simple-seeming problem of editing text.” Many non-obvious choices go into making a polished interface, and while a reimplementation gets rid of accumulated cruft, it must rediscover these hidden trade-offs.
Anyways, I hope you enjoy using Sepia. Its development style is strange for someone used Perl's typical mix of one-liners and edit-save-run, but once you are accustomed to it, you may find it very effective.
Sepia's first contribution is a set of commands to explore a Perl codebase. These include commands to browse and display documentation, to find function definitions, and to query a cross-reference database of function and variable uses. Sepia also provides intelligent symbol completion.
Sepia implements partial-word completion that communicates with the inferior Perl process. For example, `%S:X:v_u' completes to `%Sepia::Xref::var_use' when Sepia is loaded. This completion only operates on functions and global variables known to the Perl interpreter, so it works best when code and interpreter are in sync.
More precisely, completion examines the text before point and tries each of the following in turn, using the first successful approach:
For each of the first three cases, completions candidates are first
generated by splitting the text on characters [:_]
and matching
the resulting word parts. For example, `X:a_b' will complete to
all symbols matching `^X[^:]*:+a[^:_]*_b' such as `Xref::a_bug'
and `X::always_bites_me'. If no matches result, the text is
treated as an acronym. For example, `dry' will complete to
`dont_repeat_yourself'.
Completion is performed by the following commands:
completion-ignore-case
.
sepia-indent-expand-abbrev
is nil
). If no abbrev is
expanded, then call sepia-complete-symbol
.
Sepia provides several commands for navigating program source. All of
them rely on information from the inferior Perl process, so it is
important both that it be running, and that its internal representation
of the program match the program source. The commands marked (Xref)
below also rely on a cross-reference database, which must be explicitly
rebuilt by calling xref-rebuild
when the program changes.
There are two basic kinds of navigation commands. The first kind jumps directly to the first matching location when possible, prompting only if no such location is found. These commands find only a single location.
sepia-dwim
automatically goes to
the first function definition or variable use found.
sepia-defs
,
and the two should probably be merged.
The second kind of navigation commands always prompts the user – though
usually with a sensible default value – and finds multiple locations.
When called with a prefix argument, these commands present their results
in a grep-mode
buffer. When called without a prefix
argument, they place all results on the found-location ring and jump
directly to the first. The remaining locations can be cycled through by
calls to sepia-next
.
Finally, there are several other navigation-related commands that do not fit into either of the above categories.
find-tag
command typically bound to <M-.>.
Sepia can be used to browse installed modules' documentation, to format and display the current buffer's POD, and to browse the list of modules installed on the system.
My::Stuff
also provides My::Stuff::Details
, it will not be displayed. When
Emacs-w3m is available, each module is linked to its documentation.
sepia-package-list
.
Sepia also integrates with eldoc (at least in GNU Emacs >= 22). Documentation for Perl operators and control structures is taken from CPerl mode. Sepia will also display documentation for user-defined functions if their POD is formatted in the standard way, with functions described in a “=head2” or “=item” entry. To load user documentation, visit the relevant file and type M-x sepia-doc-update.
If Module::CoreList
is available, Sepia's eldoc function will
also display the first version of Perl with which a module was shipped.
This is intended to give the programmer a sense of when he is creating
external dependencies.
Sepia's second main contribution is an interactive interface (REPL) to
an inferior Perl process. The interface is based on GUD mode, and
inherits many of its bindings; this chapter discusses only the Sepia
extensions. To start or switch to the repl, type M-x sepia-repl.
As in Sepia mode, <TAB> in the REPL performs partial-word completion
with sepia-complete-symbol
.
Sepia also provides a number of other ways to evaluate pieces of code in Perl, and commands to process buffer text using the inferior process.
“Shortcuts” are commands handled specially by the REPL rather than being evaluated as Perl code. They either communicate with the REPL function, or provide a convenient interface to variables in the Sepia package. Shortcuts are prefixed by a comma (<,>), and may be abbreviated to the shortest unique prefix.
Data::Dumper
), “dump” (Data::Dump
), “yaml”
(YAML
), or “plain” (stringification). Default: “dumper”.
ISA
-ancestors matching optional pattern regexp.
Sepia uses Perl's debugger hooks and GUD mode to support conditional
breakpoints and single-stepping, and overrides Perl's die()
to
invoke the debugger rather than unwinding the stack. This makes it
possible to produce a backtrace, inspect and modify global variables,
and even continue execution when a program tries to kill itself. If the
PadWalker module is available, Sepia also provides functions to inspect
and modify lexical variables.
The debugger has its own set of shortcuts, also prefixed by a comma.
die()
.
die()
had returned the value of
expr, which is evaluated in the global environment.
When interactive Perl is running, Sepia can evaluate regions of code in
the inferior Perl process. The following commands assume that this
process has already been started by calling sepia-repl
.
Sepia contains several functions to operate on regions of text using the interactive Perl process. These functions can be used like standard one-liners (e.g. `perl -pe ...'), with the advantage that all of the functions and variables in the interactive session are available.
$_
bound to
the line text, collecting the resulting values of $_
. With a
prefix argument, replace the region with the result.
$_
bound to the entire region,
collecting the final value of $_
. With a prefix argument,
replace the region.
Sepia also supports a scratchpad, another form of interaction inspired
by Emacs' *scratch*
buffer. To create or switch to the
scratchpad, type M-x sepia-scratch. Scratchpad mode is exactly
like Sepia mode, except <C-j> evaluates the current line and prints
the result on the next line.
While Sepia can be customized in both the Perl and Emacs Lisp, most of the user-accessible configuration is in the latter. The two variables most likely to need customization are sepia-program-name and sepia-perl5lib. Since Sepia tries where possible to reuse existing Emacs functionality, its behavior should already be covered by existing customizations.
nil
, sepia-complete-symbol
will complete
simple method calls of the form $x->
or Module->
. Since
the former requires evaluation of $x
, this can be disabled.
Default: T
.
nil
, attempt to generate a declaration list for
sepia-eval-defun
. This is necessary when evaluating some code,
such as that calling functions without parentheses, because the presence
of declarations affects the parsing of barewords. Default: T
.
nil
, sepia-indent-or-complete
will, if
reindentation does not change the current line, expand an abbreviation
before point rather than performing completion. Only if no abbreviation
is found will it perform completion. Default: T
.
w3m-find-file
if Emacs-w3m is installed, or
browse-url-of-buffer
otherwise.
w3m-perldoc
if Emacs-w3m is installed, or cperl-perldoc
otherwise.
PERL5LIB
when starting
interactive Perl. Default: nil
.
sepia-keymap
. Default:
<M-.>.
nil
, various Sepia functions will generate completion
candidates from interactive Perl when called interactively. This may be
slow or undesirable in some situations. Default: T
.
sepia-w3m-view-pod
if Emacs-w3m is available, or
sepia-perldoc-buffer
otherwise.
The following variables in the Sepia package control various aspects of interactive evaluation.
$PACKAGE
main
.
$PRINTER
printer
shortcut.
$PRINT_PRETTY
$PRINTER
. Currently, this means columnating lists of simple
scalars. Default: true.
$PS1
"> "
.
$STOPDIE
die
from interactive code will invoke the Sepia
debugger. Default: true.
$STOPWARN
warn
from interactive code will invoke the
Sepia debugger. Default: false.
$WANTARRAY
Many things remain unexplained except by the code itself, and some
details mentioned above should probably be given less prominence. For
developer documentation, please see the POD for Sepia
and
Sepia::Xref
, and the doc-strings in sepia.el.
I would like to thank Hilko Bengen for finding and motivating me to fix a bunch of bugs, and for doing the Debian packaging.
I would also like to thank the authors of Emacs-w3m, SLIME, ido, and B::Xref for the code I stole.
sepia-apropos
: Navigationsepia-callees
: Navigationsepia-callers
: Navigationsepia-complete-symbol
: Completionsepia-defs
: Navigationsepia-dwim
: Navigationsepia-eval-defun
: Evaluationsepia-eval-expression
: Evaluationsepia-indent-or-complete
: Completionsepia-install-eldoc
: Documentationsepia-jump-to-symbol
: Navigationsepia-load-file
: Evaluationsepia-location
: Navigationsepia-mode
: Editingsepia-module-find
: Navigationsepia-module-list
: Documentationsepia-next
: Navigationsepia-package-list
: Documentationsepia-perl-ne-region
: Mutilationsepia-perl-pe-region
: Mutilationsepia-perldoc-this
: Documentationsepia-perlize-region
: Mutilationsepia-rebuild
: Navigationsepia-repl
: Interactive Perlsepia-scratch
: Scratchpadsepia-var-defs
: Navigationsepia-var-uses
: Navigationsepia-view-pod
: Documentation