package Padre::Plugin::ShellCommand; use 5.008; use strict; use warnings; use Padre::Constant (); use Padre::Current (); use Padre::Plugin (); use Padre::Wx (); use File::Temp qw/ tempfile /; our $VERSION = '0.10'; our @ISA = 'Padre::Plugin'; ##################################################################### # Padre::Plugin Methods sub plugin_name { 'ShellCommand'; } sub padre_interfaces { 'Padre::Plugin' => 0.43; } sub menu_plugins_simple { my ($self) = @_; ShellCommand => [ Wx::gettext("Run Command\tAlt+Shift+R") => sub { $self->run_command() }, ]; } ##################################################################### # Custom Methods sub run_command { my ($self) = @_; my $editor = $self->current->editor; my $document = $editor->{Document}; $editor->Freeze; my $cmd = $editor->GetSelectedText(); my @cmd_out; my $insert_start = 0; if ($cmd) { my $cstart = $editor->GetSelectionStart(); my $cend = $editor->GetSelectionEnd(); my $start_line = $editor->LineFromPosition($cstart); my $end_line = $editor->LineFromPosition($cend); $insert_start = $editor->GetLineEndPosition($end_line); if ( $start_line == $end_line ) { @cmd_out = `$cmd 2>&1`; } else { my ( $fh, $filename ) = tempfile('PD_XXXXXXXX'); if ($fh) { print $fh $cmd; close $fh; `chmod u+x $filename`; # do we have a shebang? if ( $cmd =~ m/^\s*#!/ ) { @cmd_out = `./$filename 2>&1`; } else { @cmd_out = `sh $filename 2>&1`; } # In case of errors, we don't want the temp filename # showing up in the output as it is pretty ugly and # doesn't add anything to the conversation. if ($?) { $_ =~ s/^$filename/ERR/ for @cmd_out; } # We could use "tempfile (..., UNLINK => 1)" above but # then the temporary files hang around until Padre exits. # Therefore we explicity delete the temporary file as soon # as we are done with them. ( -f $filename ) && unlink $filename; } } } else { my $pos = $editor->GetCurrentPos; my $line = $editor->LineFromPosition($pos); my $first = $editor->PositionFromLine($line); my $last = $editor->GetLineEndPosition($line); $cmd = $editor->GetTextRange( $first, $last ); $insert_start = $last; @cmd_out = `$cmd 2>&1`; } if (@cmd_out) { my $text = "\n" . join '', @cmd_out; $editor->GotoPos($insert_start); $editor->insert_text($text); } $editor->Thaw; } 1; __END__ =pod =head1 NAME Padre::Plugin::ShellCommand - A Shell Command plugin =head1 DESCRIPTION This plugin takes shell commands from the active document and inserts the ouput of the command into the document. If text is selected then the plugin will attemp to execute the selected text. If no text is selected the the plugin will attempt to execute the current line as a command. =head1 EXAMPLES =head4 With no selected text Typing `echo $USER` on an otherwise blank line and invoking 'Run Command' without selecting anything would insert your username on the next line down. echo $USER gsiems =head4 Selecting one or more words on a line By typing, on an otherwise blank line, `The date is:` then selecting the word `date` and invoking 'Run Command' results in the date being inserted on the next line down. The date is: Fri Oct 9 16:12:11 CDT 2009 =head4 Multi-line scripts Typing a multi-line script, selecting the entire script and invoking 'Run Command' will run the entire selection as a shell script: So: for I in 1 2 3 ; do echo " and a $I" done Inserts: and a 1 and a 2 and a 3 after the script block. =head4 The whole shebang Shebangs are supported so the scripts aren't limited to shell commands/scripts. For example, typing (and selecting) the following #!/usr/bin/env perl print " and a $_\n" for (qw(one two three)); and invoking 'Run Command' inserts: and a one and a two and a three after the script block. =head1 AUTHOR Gregory Siems Egsiems@gmail.comE =head1 COPYRIGHT AND LICENSE Copyright (C) 2009 by Gregory Siems This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. =cut