| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 | #!/usr/bin/perl
# make an executable file
use strict;
use warnings;
sub usage; sub mkexec; sub guesstype; sub getcmd; sub launch_editor;
sub nextarg { $ARGV[0] }
my $DEFAULT_TYPE = 'sh';
my $DEFAULT_MODE = 0755;
my $DEFAULT_FORCE = 0;
## .... ##   . . .  .   .    .     .      .       .        .         .
## INIT ## -------------------------------------------------------------------
## '''' ##   ' ' '  '   '    '     '      '       '        '         '
defined nextarg() or usage;
my $force   = (nextarg() eq '-f' ? shift : $DEFAULT_FORCE);
my $name    = (defined nextarg() ? shift : usage);
my $type    = (defined nextarg() ? shift : guesstype $name);
my $bangs = {
    pl   => `which perl`,
    sh   => '/bin/sh',
    py   => `which python`,
    bash => '/bin/bash',
    sed  => `which sed`,
    bc   => `which bc`
};
my $templates = {
    pl   => "use strict;\nuse warnings;\n",
    py   => "if __name__ == '__main__':\n"
};
my $editors = [ qw/ vim editor / ];
my $cmds;
$cmds->{vim}->{test}    = "vim --version 2>/dev/null";
$cmds->{vim}->{run}     = "vim +\"normal G\$\" '%s'";
$cmds->{editor}->{test} = "editor --version 2>/dev/null";
$cmds->{editor}->{run}  = "editor '%s'";
## ... ##   # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
## RUN ## ----------------------------------------------------------------- #
## ''' ##   # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
if (exists $bangs->{$type}) {
    $force and -e $name
        and (defined `cp "$name" "$name~"` or die $!);
    (not -e $name or $force)
        and mkexec $name, mkbody($type);
    chmod $DEFAULT_MODE, $name;
    launch_editor $name;
} else {
    die "unknown type: $type\n";
}
## .... ##   ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''-.
## SUBZ ## ----------------------------------------------------------------- :
## '''' ##   ..............................................................-'
sub usage {
    print STDERR "usage: $0 [-f] filename [type]\n";
    exit 0;
}
sub guesstype {
    my $name = shift;
    my ($ext) = $name =~ m|\.(\w+)$|;
    return ( $ext ? $ext : $DEFAULT_TYPE);
}
sub mkbody {
    my $type = shift;
    my $tmpl = "";
    $tmpl .= $templates->{$type} if exists $templates->{$type};
    return sprintf "#!%s\n%s\n", $bangs->{$type}, $tmpl;
}
sub mkexec {
    my ($name, $body) = @_;
    open EXE, ">", $name    or die "cannot open $name for writing: $!\n";
    -W EXE                  or die "file $name is not writable\n";
    print EXE $body;
    close EXE               or die "cannot close $name: $!\n";
}
sub get_cmd {
    foreach (@$editors) {
        return $cmds->{$_}->{run} if `$cmds->{$_}->{test}`
    }
    warn "no supported editor available\n";
    return;
}
sub launch_editor {
    my $name = shift;
    my $form = get_cmd;
    if ($form) {
        my $command = sprintf get_cmd, $name;
        exec "$command";
    } else { return }
    warn "failed to launch editor: $form\n";
}
 |