#!/usr/bin/perl # make an executable file use strict; use warnings; sub usage; sub mkexec; sub guesstype; sub guesspurpose; sub getcmd; sub launch_editor; my $DEFAULT_TYPE = 'sh'; my $DEFAULT_MODE = 0755; my $DEFAULT_FORCE = 0; my $DEFAULT_EDIT = 0; ## .... ## . . . . . . . . . . . ## INIT ## ------------------------------------------------------------------- ## '''' ## ' ' ' ' ' ' ' ' ' ' ' my $force = $DEFAULT_FORCE; my $edit = $DEFAULT_EDIT; my $name; my $type; my $purpose; foreach (@ARGV) { if (m/\b-f\b|\b--force\b/) { $force++; } elsif (m/\b-e\b|\b--edit\b/) { $edit++; } elsif (defined $type) { $purpose = $_; } elsif (defined $name) { $type = $_; } else { $name = $_; } } usage unless defined $name; $type = guesstype $name unless defined $type; $purpose = guesspurpose $name unless defined $purpose; my $bangs = { pl => `which perl`, sh => '/bin/sh', py => `which python`, bash => '/bin/bash', sed => `which sed`, bc => `which bc`, exp => `which expect` . " -f" }; my $templates = { py => { '' => "if __name__ == '__main__':\n", test => "import unittest\n\n\n" . "class TestCase(unittest.TestCase):\n" . " pass\n\n\n" . "if __name__ == '__main__':\n" ." unittest.main()\n", }, pl => { '' => "use strict;\nuse warnings;\n", test => "use strict;\nuse warnings;\nuse Test::More;\n\n", }, bash => { 'ffoo' => "\n. \"\$(ffoom path)\" || exit 3\n\n" . "ffoo import pretty\n\n" . "FFOO_DEBUG=true", } }; 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'"; unless ($purpose eq "" or exists $templates->{$type}->{$purpose}) { warn "undefined purpose '$purpose' for type '$type'\n"; $purpose = ""; } ## ... ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## 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, $purpose); chmod $DEFAULT_MODE, $name; launch_editor $name if $edit; } else { die "unknown type: $type\n"; } ## .... ## ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''-. ## SUBZ ## ----------------------------------------------------------------- : ## '''' ## ..............................................................-' sub usage { print STDERR "usage: $0 [-f|-e] filename [type] [purpose]\n"; exit 0; } sub guesstype { my $name = shift; my ($ext) = $name =~ m|\.(\w+)$|; return ( $ext ? $ext : $DEFAULT_TYPE); } sub guesspurpose { my $name = shift; my $testword = '[tT][eE][sS][tT]'; return 'test' if $name =~ m|^test_|i; return 'test' if $name =~ m|_test.py$|i; return 'test' if $name =~ m|_test.pl$|i; return 'test' if $name =~ m|\btest\w*/|i; return 'test' if $name =~ m|.*Test/|i; return 'test' if $name =~ m|\bt/|; return '' } sub mkbody { my $type = shift; my $purpose = shift; my $tmpl = ""; $tmpl .= $templates->{$type}->{$purpose} if exists $templates->{$type} and exists $templates->{$type}->{$purpose}; 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"; }