Joseph Brenner


Emacs::Rep - a find & replace engine for and rep.el


  use Emacs::Rep qw( do_finds_and_reps  parse_perl_substitutions );

   my $substitutions =>>'END_S';

  my $find_replaces_aref =
    parse_perl_substitutions( \$substitutions );

  my $change_metatdata_aref =
        do_finds_and_reps( \$text, $find_replaces_aref );


Emacs::Rep is a module that acts as a back-end for the script which in turn is used by the emacs library. rep.el.

Emacs::Rep is a find and replace engine that can perform multiple perl substitution commands (e.g. s///g) on a given file, recording all metadata about each change so that an an external program (such as emacs) can interactively display and control the changes.

The end user isn't expected to need to use these routines directly.

An application programmer might use these routines to add support to an interactive front-end (Emacs or otherwise).


None by default. Any of the following may be requested (or all with the ':all' tag).


Breaks down a set of perl substitution command (i.e. "s///;", "s{}{};", etc.) into it's main components (the find pattern and the replace expression). It returns this in an an array of arrays data structure (which is the form used by do_finds_and_args).

Takes one argument, a scalar reference to a block of text containing one or more perl substitution commands, in any form (PPI is used internally to parse this).

The more elaborate "s{}{}xmsg;" is fine, as well as "s///g;".

End of line comments (after the closing semicolon) beginning with a "#", are allowed, as are embedded comments inside the find pattern if the /x modifier is in use.

Example usage:

my $substitutions =>>'END_S'; s/pointy-haired boss/esteemed leader/g; s/death spiral/minor adjustment/g; END_S

my $find_replaces_aref = parse_perl_substitutions( \$substitutions );

Where the returned data should look like:

   [ ['pointy-haired boss', 'esteemed leader'],
     ['death spiral',       'minor adjustment'],

Any trailing modifiers are automatically prefixed to the find_pattern, using the (? ... ) notation, *except* for /g and /e.

For purposes of do_finds_and_reps /e is always ignored (as of this writing), and /g is always assumed, irrespective of whether it was added explicitly.


For internal use. Example usage:

 accumulate_find_reps( \@find_reps, $find, $rep, $raw_mods );

Does a series of finds and replaces on some text and returns the beginning and end points of each of the modfied regions, along with some other information about the matches.

Takes two arguments:

(1) The text to be modified, usually as a reference, though a scalar is okay (2) A series of find and replace pairs in the form of an aref of arefs, e.g.

  $find_replaces_aref =
   [ ['jerk',            'iconoclast'],
     ['conniving',       'shrewd'].
     ['(?i)(t)asteless', '$1alented'].

(See parse_perl_substitutions.)

Example usage:

$locations_aref = do_finds_and_reps( \$text, $find_replaces_aref );

The returned change metadata is an aref of arefs of hrefs; an array of passes with an entry for each substitution pair, an an array of changes made by each pass. The href has keys: 'beg', 'delta', 'orig', 'rep'.

The fields 'orig' and 'rep' contain the modified string, before and after the change.

'delta' is the change in length due to the change.

'beg' is the beginning of the region that was modified, an integer counting from the start of the file, where the first character is 1.

This numbering does not change while a s///g is in progress, even if it is changing the length of the strings. And further, these change locations are recorded *during* each pass, which means that later passes throw off the numbering.

In practice, for the rep.el application, we apply this data on the emacs side in inverse order, so that the numbering is correct in the context we use it.

Note, error messages are routed to stdout, labeled with the prefix "Problem:". The elisp call shell-command-to-string merges stdout and stderr, but we use the 'Problem' prefix to spot error messages


Verify that all three pieces of the system have the same version: the *.pl, *.pm and *.el.

The elisp code is expected to run this command string with it's own version number:

   perl --check_versions="0.08" then runs this check_versions routine, passing along the elisp version and the version number:

Example usage:

  check_versions( $elisp_version, $script_version );

This compares those two versions with the module's version, and warns if they're not all the same.


The web page for this project is:

The code is available on github (as well as on CPAN):

Emacs::Rep is the back-end for the script which in turn is the back-end for the emacs lisp code rep.el.

If rep.el is not installed, look in the "elisp" sub-directory of this CPAN package.

A good discussion forum for projects such as this is:


Joseph Brenner, <>


Copyright (C) 2010,2012 by Joseph Brenner

This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.

See for more information.


None reported... yet.