Changeset 10166
- Timestamp:
- 01/19/10 21:48:29 (2 years ago)
- Location:
- trunk/Padre-Plugin-PerlTidy
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Padre-Plugin-PerlTidy/Changes
r10135 r10166 1 1 Revision history for Perl extension Padre::Plugin::PerlTidy. 2 3 0.10 to be released 4 - A variety of cleanups to use Padre::Current more efficiently 5 - Added menu separator 6 - A somewhat cleaner code style that is closer to general conventions 7 - Added project config file that matches that of Padre itself 8 - Applied the Perl::Tidy plugin to itself, using the project config 2 9 3 10 0.09 Thu Jan 14 2010 -
trunk/Padre-Plugin-PerlTidy/lib/Padre/Plugin/PerlTidy.pm
r10135 r10166 17 17 =cut 18 18 19 use 5.00800 1;19 use 5.008002; 20 20 use strict; 21 21 use warnings; 22 use Params::Util (); 22 23 use Padre::Current (); 23 24 use Padre::Wx (); 24 25 use Padre::Plugin (); 25 use constant { SELECTIONSIZE => 40, }; # this constant is used when storing 26 # and restoring the cursor position. 27 # Keep it small to limit resource use. 28 our $VERSION = '0.09'; 26 27 our $VERSION = '0.10'; 29 28 our @ISA = 'Padre::Plugin'; 30 29 30 # This constant is used when storing 31 # and restoring the cursor position. 32 # Keep it small to limit resource use. 33 use constant { 34 SELECTIONSIZE => 40, 35 }; 36 31 37 sub padre_interfaces { 32 return 'Padre::Plugin' => '0.43', 33 'Padre::Config' => '0.54'; 38 'Padre::Plugin' => '0.43', 'Padre::Config' => '0.54'; 34 39 } 35 40 36 41 sub plugin_name { 37 Wx::gettext( 'Perl Tidy');42 Wx::gettext('Perl Tidy'); 38 43 } 39 44 40 45 sub menu_plugins_simple { 41 my $self = shift;42 return $self->plugin_name => [43 Wx::gettext( "Tidy the active document\tAlt+Shift+F" ) => 44 \&tidy_document, 45 Wx::gettext( "Tidy the selected text\tAlt+Shift+G" ) => 46 \&tidy_selection,47 Wx::gettext( 'Export active document to HTML file') =>48 \&export_document,49 Wx::gettext( 'Export selected text to HTML file') =>50 \&export_selection,51 ];46 my $self = shift; 47 return $self->plugin_name => [ 48 Wx::gettext("Tidy the active document\tAlt+Shift+F") => \&tidy_document, 49 Wx::gettext("Tidy the selected text\tAlt+Shift+G") => 50 \&tidy_selection, 51 '---' => undef, 52 Wx::gettext('Export active document to HTML file') => 53 \&export_document, 54 Wx::gettext('Export selected text to HTML file') => 55 \&export_selection, 56 ]; 52 57 } 53 58 54 59 sub _tidy { 55 my ( $main, $src ) = @_;56 57 require Perl::Tidy;58 59 return unless defined $src; 60 61 my $doc = $main->current->document; 62 63 if ( !$doc->isa( 'Padre::Document::Perl' ) ) { 64 return Wx::MessageBox( 65 Wx::gettext( 'Document is not a Perl document' ), 66 Wx::gettext( 'Error'),67 Wx::wxOK | Wx::wxCENTRE, $main 68 ); 69 } 70 71 my ( $output, $error ); 72 my %tidyargs = ( 73 argv => \'-nse -nst', 74 source => \$src, 75 destination => \$output, 76 errorfile => \$error,77 ); 78 79 if ( my $tidyrc = $doc->project->config->config_perltidy ) { 80 $tidyargs{ perltidyrc } = $tidyrc;81 Padre::Current->main->output->AppendText( 82 "Perl\::Tidy running with project-specific configuration $tidyrc\n" 83 );84 } 85 else { 86 Padre::Current->main->output->AppendText( 87 "Perl\::Tidy running with default or user configuration\n" ); 88 } 89 90 # TODO: suppress the senseless warning from PerlTidy 91 eval { Perl::Tidy::perltidy( %tidyargs ); }; 92 93 if ( $@ ) { 94 my $error_string = $@; 95 Wx::MessageBox( 96 $error_string, 97 Wx::gettext( "PerlTidy Error" ),98 Wx::wxOK | Wx::wxCENTRE, $main 99 ); 100 return; 101 } 102 103 if ( defined $error ) { 104 my $width = length( $doc->filename ) + 2; 105 Padre::Current->main->output->AppendText( "\n\n" 106 . "-" x $width . "\n" 107 . $doc->filename . "\n" 108 . "-" x $width 109 . "\n");110 Padre::Current->main->output->AppendText( "$error\n");111 Padre::Current->main->show_output( 1 ); 112 } 113 return $output;60 my $main = shift; 61 my $current = shift; 62 my $source = shift; 63 my $document = $current->document; 64 65 # Check for problems 66 unless ( defined $source ) { 67 return; 68 } 69 unless ( $document->isa('Padre::Document::Perl') ) { 70 return Wx::MessageBox( 71 Wx::gettext('Document is not a Perl document'), 72 Wx::gettext('Error'), 73 Wx::wxOK | Wx::wxCENTRE, 74 $main 75 ); 76 } 77 78 my $destination = undef; 79 my $errorfile = undef; 80 my %tidyargs = ( 81 argv => \'-nse -nst', 82 source => \$source, 83 destination => \$destination, 84 errorfile => \$errorfile, 85 ); 86 87 my $output = $main->output; 88 my $perltidyrc = $document->project->config->config_perltidy; 89 if ($perltidyrc) { 90 $tidyargs{perltidyrc} = $perltidyrc; 91 $output->AppendText("Perl::Tidy running with project configuration $perltidyrc\n"); 92 } else { 93 $output->AppendText("Perl::Tidy running with default or user configuration\n"); 94 } 95 96 # TODO: suppress the senseless warning from PerlTidy 97 require Perl::Tidy; 98 eval { Perl::Tidy::perltidy(%tidyargs); }; 99 100 if ($@) { 101 Wx::MessageBox( 102 $@, 103 Wx::gettext("PerlTidy Error"), 104 Wx::wxOK | Wx::wxCENTRE, 105 $main 106 ); 107 return; 108 } 109 110 if ( defined $errorfile ) { 111 my $filename = $document->filename; 112 my $width = length($filename) + 2; 113 $output->AppendText( "\n\n" . "-" x $width . "\n" . $filename . "\n" . "-" x $width . "\n" ); 114 $output->AppendText("$errorfile\n"); 115 $main->show_output(1); 116 } 117 118 return $destination; 114 119 } 115 120 116 121 sub tidy_selection { 117 my ( $main, $event ) = @_; 118 my $src = $main->current->text; 119 120 my $newtext = _tidy( $main, $src ); 121 122 return unless defined $newtext && length $newtext; 123 124 $newtext =~ s{\n$}{}; 125 126 my $editor = $main->current->editor; 127 $editor->ReplaceSelection( $newtext ); 122 my $main = shift; 123 124 # Tidy the current selected text 125 my $current = $main->current; 126 my $text = $current->text; 127 my $tidy = _tidy( $main, $current, $text ); 128 unless ( defined Params::Util::_STRING($tidy) ) { 129 return; 130 } 131 132 # If the selected text does not have a newline at the end, 133 # trim off any that Perl::Tidy has added. 134 unless ( $text =~ /\n\z/ ) { 135 $tidy =~ s{\n\z}{}; 136 } 137 138 # Overwrite the selected text 139 $current->editor->ReplaceSelection($tidy); 128 140 } 129 141 130 142 sub tidy_document { 131 my ( $main, $event ) = @_; 132 133 my $doc = $main->current->document; 134 my $src = $doc->text_get; 135 136 my $newtext = _tidy( $main, $src ); 137 138 return unless defined $newtext && length $newtext; 139 140 my ( $regex, $start ) = _store_cursor_position( $main ); 141 $doc->text_set( $newtext ); 142 _restore_cursor_position( $main, $regex, $start ); 143 my $main = shift; 144 145 # Tidy the entire current document 146 my $current = $main->current; 147 my $document = $current->document; 148 my $text = $document->text_get; 149 my $tidy = _tidy( $main, $current, $text ); 150 unless ( defined Params::Util::_STRING($tidy) ) { 151 return; 152 } 153 154 # Overwrite the entire document 155 my ( $regex, $start ) = _store_cursor_position($current); 156 $document->text_set($tidy); 157 _restore_cursor_position( $current, $regex, $start ); 143 158 } 144 159 145 160 sub _get_filename { 146 my $main = shift; 147 148 my $doc = $main->current->document or return; 149 my $current = $doc->filename; 150 my $default_dir = ''; 151 152 if ( defined $current ) { 153 require File::Basename; 154 $default_dir = File::Basename::dirname( $current ); 155 } 156 157 require File::Spec; 158 159 while ( 1 ) { 160 my $dialog = Wx::FileDialog->new( 161 $main, Wx::gettext( "Save file as..." ), 162 $default_dir, $doc->filename . '.html', 163 "*.*", Wx::wxFD_SAVE, 164 ); 165 if ( $dialog->ShowModal == Wx::wxID_CANCEL ) { 166 return; 167 } 168 my $filename = $dialog->GetFilename; 169 $default_dir = $dialog->GetDirectory; 170 my $path = File::Spec->catfile( $default_dir, $filename ); 171 if ( -e $path ) { 172 my $res = Wx::MessageBox( 173 Wx::gettext( "File already exists. Overwrite it?" ), 174 Wx::gettext( "Exist" ), 175 Wx::wxYES_NO, $main, 176 ); 177 if ( $res == Wx::wxYES ) { 178 return $path; 179 } 180 } 181 else { 182 return $path; 183 } 184 } 161 my $main = shift; 162 163 my $doc = $main->current->document or return; 164 my $current = $doc->filename; 165 my $default_dir = ''; 166 167 if ( defined $current ) { 168 require File::Basename; 169 $default_dir = File::Basename::dirname($current); 170 } 171 172 require File::Spec; 173 174 while (1) { 175 my $dialog = Wx::FileDialog->new( 176 $main, Wx::gettext("Save file as..."), 177 $default_dir, $doc->filename . '.html', 178 "*.*", Wx::wxFD_SAVE, 179 ); 180 if ( $dialog->ShowModal == Wx::wxID_CANCEL ) { 181 return; 182 } 183 my $filename = $dialog->GetFilename; 184 $default_dir = $dialog->GetDirectory; 185 my $path = File::Spec->catfile( $default_dir, $filename ); 186 if ( -e $path ) { 187 my $res = Wx::MessageBox( 188 Wx::gettext("File already exists. Overwrite it?"), 189 Wx::gettext("Exist"), 190 Wx::wxYES_NO, $main, 191 ); 192 if ( $res == Wx::wxYES ) { 193 return $path; 194 } 195 } else { 196 return $path; 197 } 198 } 185 199 } 186 200 187 201 sub _export { 188 my ( $main, $src ) = @_; 189 190 require Perl::Tidy; 191 192 return unless defined $src; 193 194 my $doc = $main->current->document; 195 196 if ( !$doc->isa( 'Padre::Document::Perl' ) ) { 197 return Wx::MessageBox( 198 Wx::gettext( 'Document is not a Perl document' ), 199 Wx::gettext( 'Error' ), 200 Wx::wxOK | Wx::wxCENTRE, $main 201 ); 202 } 203 204 my $filename = _get_filename( $main ); 205 206 return unless defined $filename; 207 208 my ( $output, $error ); 209 my %tidyargs = ( 210 argv => \'-html -nnn -nse -nst', 211 source => \$src, 212 destination => $filename, 213 errorfile => \$error, 214 ); 215 216 if ( my $tidyrc = $doc->project->config->config_perltidy ) { 217 $tidyargs{ perltidyrc } = $tidyrc; 218 Padre::Current->main->output->AppendText( 219 "Perl\::Tidy running with project-specific configuration $tidyrc\n" 220 ); 221 } 222 223 else { 224 Padre::Current->main->output->AppendText( 225 "Perl::Tidy running with default or user configuration\n" ); 226 } 227 228 # TODO: suppress the senseless warning from PerlTidy 229 eval { Perl::Tidy::perltidy( %tidyargs ); }; 230 231 if ( $@ ) { 232 my $error_string = $@; 233 Wx::MessageBox( 234 $error_string, 235 Wx::gettext( 'PerlTidy Error' ), 236 Wx::wxOK | Wx::wxCENTRE, $main 237 ); 238 return; 239 } 240 241 if ( defined $error ) { 242 my $width = length( $doc->filename ) + 2; 243 my $main = Padre::Current->main; 244 $main->output->AppendText( "\n\n" 245 . "-" x $width . "\n" 246 . $doc->filename . "\n" 247 . "-" x $width 248 . "\n" ); 249 $main->output->AppendText( "$error\n" ); 250 $main->show_output( 1 ); 251 } 252 253 return; 202 my ( $main, $src ) = @_; 203 204 require Perl::Tidy; 205 206 return unless defined $src; 207 208 my $doc = $main->current->document; 209 210 if ( !$doc->isa('Padre::Document::Perl') ) { 211 return Wx::MessageBox( 212 Wx::gettext('Document is not a Perl document'), 213 Wx::gettext('Error'), 214 Wx::wxOK | Wx::wxCENTRE, $main 215 ); 216 } 217 218 my $filename = _get_filename($main); 219 220 return unless defined $filename; 221 222 my ( $output, $error ); 223 my %tidyargs = ( 224 argv => \'-html -nnn -nse -nst', 225 source => \$src, 226 destination => $filename, 227 errorfile => \$error, 228 ); 229 230 if ( my $tidyrc = $doc->project->config->config_perltidy ) { 231 $tidyargs{perltidyrc} = $tidyrc; 232 Padre::Current->main->output->AppendText("Perl\::Tidy running with project-specific configuration $tidyrc\n"); 233 } 234 235 else { 236 Padre::Current->main->output->AppendText("Perl::Tidy running with default or user configuration\n"); 237 } 238 239 # TODO: suppress the senseless warning from PerlTidy 240 eval { Perl::Tidy::perltidy(%tidyargs); }; 241 242 if ($@) { 243 my $error_string = $@; 244 Wx::MessageBox( 245 $error_string, 246 Wx::gettext('PerlTidy Error'), 247 Wx::wxOK | Wx::wxCENTRE, $main 248 ); 249 return; 250 } 251 252 if ( defined $error ) { 253 my $width = length( $doc->filename ) + 2; 254 my $main = Padre::Current->main; 255 $main->output->AppendText( "\n\n" . "-" x $width . "\n" . $doc->filename . "\n" . "-" x $width . "\n" ); 256 $main->output->AppendText("$error\n"); 257 $main->show_output(1); 258 } 259 260 return; 254 261 } 255 262 256 263 sub export_selection { 257 my ( $main, $event ) = @_; 258 my $src = $main->current->text; 259 260 _export( $main, $src ); 261 return; 264 my $main = shift; 265 my $text = $main->current->text; 266 _export( $main, $text ); 267 return; 262 268 } 263 269 264 270 sub export_document { 265 my ( $main, $event ) = @_; 266 267 my $doc = $main->current->document; 268 my $src = $doc->text_get; 269 270 _export( $main, $src ); 271 return; 272 } 273 271 my $main = shift; 272 my $text = $main->current->document->text_get; 273 _export( $main, $text ); 274 return; 275 } 276 277 # parameter: $main, compiled regex 274 278 sub _restore_cursor_position { 275 276 # parameter: $main, compiled regex 277 my ( $main, $regex, $start ) = @_; 278 my $doc = $main->current->document; 279 my $editor = $doc->editor; 280 my $text = $editor->GetTextRange( 281 ( $start - SELECTIONSIZE ) > 0 ? $start - SELECTIONSIZE 282 : 0, 283 ( $start + SELECTIONSIZE < $editor->GetLength() ) 284 ? $start + SELECTIONSIZE 285 : $editor->GetLength() 286 ); 287 eval { 288 if ( $text =~ /($regex)/ ) 289 { 290 my $pos = $start + length $1; 291 $editor->SetCurrentPos( $pos ); 292 $editor->SetSelection( $pos, $pos ); 293 } 294 }; 295 $editor->goto_line_centerize( $editor->GetCurrentLine ); 296 return; 297 } 298 279 my $current = shift; 280 my $regex = shift; 281 my $start = shift; 282 my $editor = $current->editor; 283 my $text = $editor->GetTextRange( 284 ( $start - SELECTIONSIZE ) > 0 ? $start - SELECTIONSIZE 285 : 0, 286 ( $start + SELECTIONSIZE < $editor->GetLength ) ? $start + SELECTIONSIZE 287 : $editor->GetLength 288 ); 289 eval { 290 if ( $text =~ /($regex)/ ) 291 { 292 my $pos = $start + length $1; 293 $editor->SetCurrentPos($pos); 294 $editor->SetSelection( $pos, $pos ); 295 } 296 }; 297 $editor->goto_line_centerize( $editor->GetCurrentLine ); 298 return; 299 } 300 301 # parameter: $current 302 # returns: compiled regex, start position 303 # compiled regex is /^./ if no valid regex can be reconstructed. 299 304 sub _store_cursor_position { 300 301 # parameter: $main 302 # returns: compiled regex, start position 303 # compiled regex is /^./ if no valid regex can be reconstructed. 304 my $main = shift; 305 my $doc = $main->current->document; 306 my $editor = $doc->editor; 307 my $pos = $editor->GetCurrentPos; 308 my $start; 309 310 if ( ( $pos - SELECTIONSIZE ) > 0 ) { 311 $start = $pos - SELECTIONSIZE; 312 } 313 else { 314 $start = 0; 315 } 316 my $prefix = $editor->GetTextRange( $start, $pos ); 317 my $regex; 318 eval { 319 $prefix =~ s/(\W)/\\$1/gm; # Escape non-word chars 320 $prefix 321 =~ s/(\\\s+)/(\\s+|\\r*\\n)*/gm; # Replace whitespace by regex \s+ 322 $regex = qr{$prefix}; 323 }; 324 if ( $@ ) { 325 $regex = qw{^.}; 326 print STDERR @_; 327 } 328 return ( $regex, $start ); 305 my $current = shift; 306 my $editor = $current->editor; 307 my $pos = $editor->GetCurrentPos; 308 309 my $start; 310 if ( ( $pos - SELECTIONSIZE ) > 0 ) { 311 $start = $pos - SELECTIONSIZE; 312 } else { 313 $start = 0; 314 } 315 316 my $prefix = $editor->GetTextRange( $start, $pos ); 317 my $regex; 318 eval { 319 320 # Escape non-word chars 321 $prefix =~ s/(\W)/\\$1/gm; 322 323 # Replace whitespace by regex \s+ 324 $prefix =~ s/(\\\s+)/(\\s+|\\r*\\n)*/gm; 325 326 $regex = qr{$prefix}; 327 }; 328 if ($@) { 329 $regex = qw{^.}; 330 print STDERR @_; 331 } 332 return ( $regex, $start ); 329 333 } 330 334 -
trunk/Padre-Plugin-PerlTidy/padre.yml
r10165 r10166 1 1 --- 2 editor_indent_tab: 1 3 editor_indent_tab_width: 8 4 editor_indent_width: 8 2 5 config_perltidy: ../tools/perltidyrc
Note: See TracChangeset
for help on using the changeset viewer.
