Isocode
Search Perl 5 sources by given code example.
You can give it file or string as a pattern. Command line interface is compatible with grep
, so in common cases you can replace grep
with isocode
.
Binary is build for Linux and completely static, so no need to install any dependencies.
See --help
for all supported options.
Rules of matching:
- All brackets should have pair in pattern. E.g. you can not search for
if (
. Sorry :( "abc"
=='abc'
==q(abc)
==qq(abc)
. Even"123"
==123
m/[a-z]/
==/[a-z]/
=="[a-z]"
. But if there are any flags - it should be always a regexp.qw( 1 2 3 )
==qw(1 2 3)
==(1,2,3)
==("1", 2, "3")
...- Trailing separators ignored:
(1,2,3,)
==(1,2,3)
and{ a(); b(); }
=={ a(); b() }
- Variable names can be differrent! But must be consistent:
$a + $a
==$b + $b
, but$a + $b
!=$c + $c
- Whitespace, newlines and comments are ignored.
- BETA: Wildcard
***
matches anything till the end of the block. You can use it likeif (! ***) {die *** }
. (dont forget to surround it with spaces, so parser dont get confused) . #11
Run
$ ./isocode -nr -e 'my ( $type, %args ) = @_; my $a = {}; bless( $a, $type);' ~/tmp/otrs/
/home/spek/tmp/otrs/scripts/test/Layout/Template/OutputFilter.pm:15:5
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
/home/spek/tmp/otrs/scripts/test/Layout/Template/OutputFilterInclude.pm:15:5
my ( $Type, %Param ) = @_;
# allocate new hash for object
my $Self = {};
bless( $Self, $Type );
/home/spek/tmp/otrs/scripts/test/CommunicationChannel/Test.pm:19:5
my ( $Type, %Param ) = @_;
my $Self = {};
bless( $Self, $Type );
...
/home/spek/tmp/otrs/Kernel/Output/PDF/Ticket.pm:32:5
my ( $Type, %Param ) = @_;
# Allocate new hash for object.
my $Self = {};
bless( $Self, $Type );
Files in directory: 5381
Scanned 2728 files with 0 errors
Total 372 files matches
Total 372 matches
Why
https://www.youtube.com/watch?v=JtHi6bSZX4E
For fun. Maybe it will help someone.
"isocode" means "isomorphic code".
Build
I just gave up setting up ghc no my machine to build static binary, so its built in docker.
# ./build-in-docker.sh
# ./isocode --help
isocode - search source tree by Perl code sample
Usage: isocode (PATTERN | (-e|--regexp PATTERN) | (-f|--file PATTERN_FILE))
SEARCH_PATHS [-W|--verbose] [-Y|--debug]
[-l|--files-with-matches] [-r|--recursive] [-n|--line-number]
Searches for code similar to PATTERN_FILE or PATTERN in SEARCH_DIR.
Available options:
PATTERN code sample to search for
-e,--regexp PATTERN code sample to search for
-f,--file PATTERN_FILE path to code sample to search in
SEARCH_PATHS files or dirs to search
-W,--verbose (non grep compat) 'WHAT?' spew debug information
-Y,--debug (non grep compat) 'WHY?' just parse the pattern and
show, do not search for it
-l,--files-with-matches Show only filenames of matched files
-r,--recursive IGNORED, always on
-n,--line-number IGNORED, always on
-h,--help Show this help text
How it works
'Only Perl can parse Perl', but we only need to understand perl code at very basic level (is it var? is it string literal?).
- Parse example code to simple AST
- Given that AST, generate parser which search and parses only similar code
- Search directory recursively, applying that parser + do variable names consistency check
- Profit ???
Search is done by naive algorithm with simple optimization:
- get list of first characters that code can start with (e.g.
['u']
foruse
or['"', 'q', '\'' ... ]
for"string"
- Find next occurrence of one of this characters
- Run parser from this position
- If fail - go to 2
Its faster than parsing whole source, but stil may be slow for common characters.
TLDR: Basically, its three parser generators (one for command line arguments) stiched together.
What (doesn't) work and TODO
See Issues tab on github. Both already implemented and still TBD should be there.