`exec` command improvements #96

Open
gugod opened this Issue May 23, 2011 · 7 comments

Projects

None yet

5 participants

@gugod
Owner
gugod commented May 23, 2011

To provide better interactive / non-interactive use perl installations, there are should be some easy usages for people to run programs with specified perl without a switch/use beforehand.

Suppose a perlbrew root with the following installations:

> perlbrew list
  perl-5.10.1
  perl-5.12.3
* perl-5.14.0
  perl-5.8.9
  /usr/bin/perl (5.10.0)

Then perlbrew should take an additional selector argument before exec, to specify the installation names. For example:

# run myprogram.pl with perl-5.12.3
perlbrew perl-5.12.3 exec  myprogram.pl

# run myprogram.pl with perl-5.12.3 and perl-5.14.0
perlbrew perl-5.12.3,perl-5.14.0 exec  myprogram.pl

# run myprogram.pl with all perls
perlbrew exec  myprogram.pl

# die with error, because perl-5.10.0 is not installed here
perlbrew perl-5.10.0 exec  myprogram.pl

# die with error, also because perl-5.10.0 is not installed here

perlbrew perl-5.12.3,perl-5.10.0 exec myprogram.pl

The content of selector should be a comma-separated list of installation names, without spaces in between.

If any one or more of the specified installations cannot be found, then perlbrew must die with error messages specifying the missing ones, without executing the command at all.

@gugod gugod was assigned May 23, 2011
@doy
Contributor
doy commented May 23, 2011

That seems like it'd be pretty irritating to parse correctly (and would also have ambiguities in some cases). What about perlbrew exec --perl=perl-5.12.3 myprogram.pl, perlbrew exec --perl=perl5.12.3 --perl=perl-5.14.0 myprogram.pl, perlbrew exec --all myprogram.pl (and have --all be implied if no --perl option is passed)?

@gugod
Owner
gugod commented May 23, 2011

@doy, I like simplicity over explicitly.

This command syntax can only be ambiguous if the installation name (or alias) contains commas, or is the same as one of perlbrew command: install, uninstall, switch, use, list, available, etc etc.

If one name (or alias) their perl installation to, say, "install", it is likely they either have a crystal clear mind, or get totally confused in their daily life with perlbrew. Besides, we can just let perlbrew install exec app.pl to invoke the install command, and then just shows an error message (that perl-exec cannot be found) from there.

The parsing is actually extremely simple because the search space is finite: it's just the list of installation names and alias. The algorithm is illustrated:

$selector = <the second arg from command line>;
$re = <regex that matches all installation names>; # qr(perl-5.12.3|perl-5.12.0|foobar,name-with-camma|)
while{ /^$re(,|$)/ } {
    push @perls, $1;
}
if (length($selector) != 0) {
   die;
}

In short: extract one name from the beginning at a time.

However this does not deal with the ambiguity when installation names contain commas, in extreme cases, when one name can be a substr of another, with surrounding commas. I have a feeling that if the $re is sorted by the length of installation name in descending order, such ambiguity can be eliminated, but I do not have a prove in my mind right now. Even if it does not completely eliminated the ambiguity, I'm fine not doing it. I really doubt why would anyone have to confuse himself by naming their perl installations like "a,b,c", "a,b", "b,c", "a", "b", "c".

An alternative thought is to let the selector be a list of partial names. For example, "5.13" can match installation names like "perl-5.13.1", "perl-5.13.2" and potentially all perl-5.13.* series. "5.10,5.12,5.14" matches all of the stable versions. The exec command only has to die if the selector matches nothing at all. This approach actually increase the ambiguity, but it seems simpler to use. At least the ambiguity becomes so obvious that user can easily realize how to fix it (by increasing the length of selector.)

I shall try both approaches to get some feeling about what's the right thing to do. Not in a rush to release this feature at all. :)

@doy
Contributor
doy commented May 23, 2011

It's not really about simplicity vs being explicit - it's about being consistent. At the moment, perlbrew is always invoked as perlbrew <command> [arguments...], and this is standard with pretty much any command line tool that uses subcommands. For instance, why is it perlbrew perl-5.12.3 exec foo but not perlbrew perl-5.12.3 install (or perlbrew some-alias install perl-5.12.3, or something)? And if you did decide to make install work that way, how would you handle the parsing for that, in a way that would work with both subcommands? Also, having the selector come before the command makes it seem like the selector is some kind of modifier on perlbrew itself, but it's actually something that configures a specific subcommand that follows, which makes it read really weirdly. Basically, having this one command be a special case in terms of how it's parsed makes things a lot less simple, not more, because you have to keep the special case in mind whenever you use it, rather than using a standard way of passing options to subcommands, and you also have to make sure you avoid the edge cases it introduces.

@gugod
Owner
gugod commented May 23, 2011

Of course it does not make sense to just design the command for one 'exec' command, and that's not the whole picture.

Take a look of the "Set Actions" from rvm: https://rvm.beginrescueend.com/set/. The command syntax is simply stealing from there. exec is one generic example, but there can be more commands that make things simple, to name a few:

  • perlbrew cpan Moose
    • install Moose to all installations of perl
  • perlbrew 5.12,5.13,5.14 benchmark app.pl
    • run app.pl with many perls, and generate a benchmark report
  • perlbrew 5.12,5.13,5.14 prove -l t
    • run prove
  • perlbrew cover
    • ditto

Many of these are just slight shorter equivalents of "exec", but again, I'd like it to be very simple to use.

One other idea about worth mentioning (and investigating) about the selector is to make it run with shebang:

#!/usr/bin/env perlbrew 5.14.0
say "Hi";

I agree that it does not read nicely, but hey, exec is not a proper verb, shell script ain't English anyway.

@rwstauner
Contributor

Interesting idea...
One thing to note specifically about that shebang idea...
Some systems only recognize a single argument in the shebang...

on ubuntu 10.04, trying to run this shell script:

#!/usr/bin/env perl -w
print "hi\n";

produces:

/usr/bin/env: perl -w: No such file or directory

It's actually searching for a command named "perl -w".
If I make a shell script named "perl -w" it calls that and succeeds.

@dagolden
Contributor

At this point, I think the easiest thing would be to have a separate command to run against a single perl:

$ perlbrew run 5.14.2 perl ...
$ perlbrew run 5.12.3 cpanm ...

If you want to make that second argument be some sort of pattern or glob, you could:

$ perlbrew run 5.12.3,5.14.2 cpanm ...
$ perlbrew run 5.12.\* cpanm ...

I would have written 'exec' that way originally rather than have it be "run against every perl" because it's easier to generalize to the universal case than it is to restrict the universal case to a specific one. E.g.:

$ perlbrew run \* cpanm ...
@celogeek
celogeek commented May 8, 2012

An interesting thing should be add "lib" in exec.

like this :

perlbrew exec --lib=mytest cpanm MooX::Options

it will run over all perl version with lib "mytest".

so like

perl-5.14.2@mytest
====

perl-5.10.1@mytest
====

...

and if the lib is missing for a version of perl, it create it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment