tags:

views:

294

answers:

4

The question is not how to tell in a oneliner. If you're writing the code in a one-liner, you know you are. But how does a module, included by -MMy::Module::Name know that it all started from a oneliner.

This is mine. It's non-portable though and relies on UNIX standard commands (although, it can be made portable more or less.)

my $process_info = `ps $$ | tail -1`;
my $is_oneliner  
    = $process_info =~ m/perl.*?\s+-[^\P{IsLower}e]*e[^\P{IsLower}e]*\s+/m
    ;

And if you have a snazzier regex, feel free to improve upon mine.


A couple of people have asked why I would want to do this. brian correctly guessed that I wanted to change export behavior based on whether it's a script, which we can assume has had some amount of design, or whether it's a oneliner where the user is trying to do as much as possible in a single command line.

This sounds bad, because there's this credo that exporters should respect other packages--sometimes known as "@EXPORT is EVIL!" But it seems to me that it's a foolish consistency when applied to oneliners. After all perl itself goes out of it's way to violate the structure of its language and give you easy loops if you ask for them on the command line, I simply want to extend that idea for my operational/business domain. I even want to apply source filters (gasp!) if it helps.

But this question also suggests that I might want to be a good citizen of Perl as well, because I only to break the community guidelines in certain cases. It is quite awesome to be able to create major business-level actions just by changing the command line in a batch scheduler rather than writing a whole new module. The test cycle is much compressed.

+24  A: 

$0 is set to "-e" if you're running from -e.

Dan
D'oh! I printed out a lot of variables, but I didn't do that one!
Axeman
I didn't find that in perlvar, is that _documented_ anywhere?
Axeman
It's probably documented only in the source. :) But I think it has been true for a very long time.
Randal Schwartz
I know it because that's the name for the script in perl -de 0 :)
brian d foy
@Axeman: perldoc perlvar (" $0 Contains the name of the program being executed.")
dland
+7  A: 

Why are you trying to find out if the module was included from the command line? Is there some situation you have where it matters? Are you doing something odd with imports? Tell us what you're trying to do and I can probably come up with a better way to do it :)


Okay, you're asking about exporting. What's the problem you're trying to solve? Which way do you want it? Extra or less default exports from the command line? Do you know that you can specify an import list with -M, including an export tag (so, something from %EXPORT_TAGS)? And if you want an empty export list, you can use -m (lowercase m) instead. See the entry for -M/-m in perlrun.

You might also be interested in the "modulino" trick where a module file can be both a module and a script. You can either use it as a regular module, in which case you have access to all of its methods, or call it as a script, in which case it runs. I describe it in my "Scripts as Modules" article for The Perl Journal as well as "How a Script Becomes a Module" on Perlmonks.

brian d foy
Yeah, that's basically it. -e gets more exports than precisely defined scripts that at least suggest a designed package space. I'm not quite as worried about respecting the main of a oneliner.
Axeman
Brian: The ideas presented in your "modulino" article are /incredibly/ useful. It both discourages 'hacky' scripts, and provides immediate reusability. Love it, and I'm going to propose adding it to or internal coding guidelines on Monday - One of the problems we have is scripts tend to...
Dan
...start off small and slightly hackish, slowly growing to an unwieldy size, before sooner or later that functionality is required elsewhere, so the whole mess needs refactoring (which rarely goes smoothly). This should entirely remove the problem.
Dan
It's simply about turning up the power on oneliners. Because oneliners are not likely to define a named sub themselves, I throw every sub they might need into main. That's it. When the module is called from more complex code, it remains polite.
Axeman
+1  A: 

In your import(), the line number returned by caller() will be 0 if your module was loaded via -M. This is true whenever -M is used (with -e or not) but I think it is the only case where the line number is 0.

Eric Wilhelm
perl -le'#line 0' -e'sub { print join ":", caller }->()'
ysth
perl -le'#line 1' -e'sub { print join ":", caller }->()'
Brad Gilbert
+1  A: 

If you want different export behavior, the "clean" way to do it would be using a different module name. If you really expect to do a lot of one-liner use, you can even give it a short name. E.g. MMN.pm:

package MMN;
use My::Module::Name '/./';
use Exporter ();
@ISA = 'Exporter';
@EXPORT = @My::Module::Name::EXPORT_OK;
1;

Note that Exporter has a little known regex feature; you may just want to do

perl -MMy::Module::Name=/./ -e ...
ysth
I don't know that that is so clean, but I already do have a scheme to shorten the names for command line invocation.,
Axeman