123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #!/usr/bin/perl
  2. # make an executable file
  3. use strict;
  4. use warnings;
  5. sub usage; sub mkexec; sub guesstype; sub getcmd; sub launch_editor;
  6. sub nextarg { $ARGV[0] }
  7. my $DEFAULT_TYPE = 'pl';
  8. my $DEFAULT_MODE = 0755;
  9. my $DEFAULT_FORCE = 0;
  10. ## .... ## . . . . . . . . . . .
  11. ## INIT ## -------------------------------------------------------------------
  12. ## '''' ## ' ' ' ' ' ' ' ' ' ' '
  13. defined nextarg() or usage;
  14. my $force = (nextarg() eq '-f' ? shift : $DEFAULT_FORCE);
  15. my $name = (defined nextarg() ? shift : usage);
  16. my $type = (defined nextarg() ? shift : guesstype $name);
  17. my $bangs = {
  18. pl => `which perl`,
  19. sh => '/bin/sh',
  20. py => `which python`,
  21. bash => '/bin/bash',
  22. sed => `which sed`,
  23. bc => `which bc`
  24. };
  25. my $templates = {
  26. pl => "use strict;\nuse warnings;\n",
  27. py => "if __name__ == '__main__':\n"
  28. };
  29. my $editors = [ qw/ vim editor / ];
  30. my $cmds;
  31. $cmds->{vim}->{test} = "vim --version 2>/dev/null";
  32. $cmds->{vim}->{run} = "vim +\"normal G\$\" '%s'";
  33. $cmds->{editor}->{test} = "editor --version 2>/dev/null";
  34. $cmds->{editor}->{run} = "editor '%s'";
  35. ## ... ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  36. ## RUN ## ----------------------------------------------------------------- #
  37. ## ''' ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  38. if (exists $bangs->{$type}) {
  39. $force and -e $name
  40. and (defined `cp "$name" "$name~"` or die $!);
  41. (not -e $name or $force)
  42. and mkexec $name, mkbody($type);
  43. chmod $DEFAULT_MODE, $name;
  44. launch_editor $name;
  45. } else {
  46. die "unknown type: $type\n";
  47. }
  48. ## .... ## ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''-.
  49. ## SUBZ ## ----------------------------------------------------------------- :
  50. ## '''' ## ..............................................................-'
  51. sub usage {
  52. print STDERR "usage: $0 [-f] filename [type]\n";
  53. exit 0;
  54. }
  55. sub guesstype {
  56. my $name = shift;
  57. my ($ext) = $name =~ m|\.(\w+)$|;
  58. return ( $ext ? $ext : $DEFAULT_TYPE);
  59. }
  60. sub mkbody {
  61. my $type = shift;
  62. my $tmpl = "";
  63. $tmpl .= $templates->{$type} if exists $templates->{$type};
  64. return sprintf "#!%s\n%s\n", $bangs->{$type}, $tmpl;
  65. }
  66. sub mkexec {
  67. my ($name, $body) = @_;
  68. open EXE, ">", $name or die "cannot open $name for writing: $!\n";
  69. -W EXE or die "file $name is not writable\n";
  70. print EXE $body;
  71. close EXE or die "cannot close $name: $!\n";
  72. }
  73. sub get_cmd {
  74. foreach (@$editors) {
  75. return $cmds->{$_}->{run} if `$cmds->{$_}->{test}`
  76. }
  77. warn "no supported editor available\n";
  78. return;
  79. }
  80. sub launch_editor {
  81. my $name = shift;
  82. my $form = get_cmd;
  83. if ($form) {
  84. my $command = sprintf get_cmd, $name;
  85. exec "$command";
  86. } else { return }
  87. warn "failed to launch editor: $form\n";
  88. }