#!/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"; }