Changeset 11105


Ignore:
Timestamp:
03/13/10 10:45:22 (2 years ago)
Author:
karl.forner
Message:

Development related to the braces highlighting and matching.

Added some methods to enforce a uniform definition of what is a brace (so currently it is {}[](). All features using braces share this same definition :

  • highlighting
  • goto matching brace
  • select to matching brace

Moved all related code into Editor.pm.

Modified goto matching brace (CTRL+1) and select to matching brace in order to:

  • use the defined braces
  • respect the inside/outsideness of starting point, meaning that is the cursor is inside the braces; its detination point is also inside
  • the select to matching brace should also now work properly if there is an existing selection to the right of a closing brace
Location:
trunk/Padre/lib/Padre
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Padre/lib/Padre/Action/Edit.pm

    r11097 r11105  
    324324        need_editor => 1, 
    325325        label       => Wx::gettext('&Select to matching brace'), 
    326         comment     => Wx::gettext('Select to the matching opening or closing brace: { }, ( ), [ ], < >'), 
     326        comment     => Wx::gettext('Select to the matching opening or closing brace'), 
    327327        shortcut    => 'Ctrl-4', 
    328         menu_event  => sub { 
    329             my $self = shift; 
    330             my $INVALID_POSITION = Wx::wxSTC_INVALID_POSITION; 
    331             my $page = $self->current->editor; 
    332             my $pos1 = $page->GetCurrentPos; 
    333             my $pos2 = $page->BraceMatch($pos1); 
    334             if ( $pos2 == $INVALID_POSITION ) { #Wx::wxSTC_INVALID_POSITION 
    335                 if ( $pos1 > 0 ) { 
    336                     $pos1--; 
    337                     $pos2 = $page->BraceMatch($pos1); 
    338                 } 
    339             } 
    340  
    341             if ( $pos2 != $INVALID_POSITION ) { #Wx::wxSTC_INVALID_POSITION 
    342                 my $start = $page->GetSelectionStart(); 
    343                 $page->SetSelection($start, $pos2+1); 
    344             } 
    345  
    346             return;          
    347         }, 
     328        menu_event  => sub { shift->current->editor->select_to_matching_brace } 
    348329    ); 
    349330 
  • trunk/Padre/lib/Padre/Wx/Editor.pm

    r10997 r11105  
    3838    'application/x-php'  => 'perl', # temporary solution 
    3939); 
     40 
     41# Karl 
     42# these are the allowed braces for brace highlighting and brace matching 
     43# this has to be subset of  ( ) [ ] { } < > since we use the scintilla 
     44# Brace* methods 
     45# always altern opening and starting braces in the constant 
     46my $BRACES = '{}[]()'; 
     47my $STC_INVALID_POSITION =  Wx::wxSTC_INVALID_POSITION; 
    4048 
    4149my $data; 
     
    152160} 
    153161 
     162# convenience accessor method (and to ensure consistency) 
     163# return the Padre::Config instance 
     164sub get_config { 
     165    return shift->main->ide->config; 
     166} 
     167 
     168# convenience methods 
     169# return the character at a given position as a perl string 
     170sub get_character_at { 
     171    my ($self, $pos) = @_; 
     172    return chr( $self->GetCharAt($pos) ); 
     173} 
     174 
     175 
     176 
     177 
    154178sub data { 
    155179    my $name    = shift; 
     
    398422} 
    399423 
     424 
     425 
     426     
     427     
     428 
     429 
     430 
     431=head2 get_brace_info 
     432 
     433Look at a given position in the editor if there is a brace (according to the  
     434setting editor_braces) before or after, and return the information about the context 
     435It always look first at the character after the position. 
     436 
     437    Params: 
     438        pos - the cursor position in the editor [defaults to cursor position) : int 
     439         
     440    Return: 
     441        undef if no brace, otherwise [brace, actual_pos, is_after, is_opening] 
     442        where: 
     443            brace - the brace char at actual_pos 
     444            actual_pos - the actual position where the brace has been found 
     445            is_after - true iff the brace is after the cursor : boolean 
     446            is_opening - true iff only the brace is an opening one 
     447             
     448    Examples: 
     449 
     450        |{} => should find the { : [0,{,1,1]  
     451        {|} => should find the } : [1,},1,0] 
     452        {| } => should find the { : [0,{,0,1] 
     453 
     454=cut 
     455 
     456 
     457sub get_brace_info { 
     458    my ($self, $pos) = @_; 
     459    $pos = $self->GetCurrentPos unless defined $pos; 
     460      
     461    # try the after position first (default one for BraceMatch) 
     462    my $is_after = 1; 
     463    my $brace = $self->get_character_at($pos); 
     464    my $is_brace = $self->get_brace_type($brace); 
     465    if (!$is_brace && $pos > 0) { # try the before position 
     466        $brace = $self->get_character_at(--$pos); 
     467        $is_brace  = $self->get_brace_type($brace) or return undef; 
     468        $is_after = 0; 
     469    } 
     470    my $is_opening = $is_brace % 2; # odd values are opening 
     471    return [$pos, $brace, $is_after, $is_opening]; 
     472} 
     473 
     474 
     475=head2 get_brace_type 
     476 
     477Tell if a character is a brace, and if it is an opening or a closing one 
     478 
     479    Params: 
     480        char - a character : string 
     481         
     482    Return: 
     483        int : 0 if this is not a brace, an odd value if it is an opening brace and an even 
     484        one for a closing brace 
     485 
     486=cut 
     487my %_cached_braces; 
     488sub get_brace_type { 
     489    my ($self, $char) = @_; 
     490    unless (%_cached_braces) { 
     491        my $i = 1; # start from one so that all values are true 
     492        $_cached_braces{$_} = $i++ foreach (split //, $BRACES); 
     493    } 
     494    my $v = $_cached_braces{$char} or return 0; 
     495    return $v; 
     496} 
     497 
     498 
     499 
     500# some uncorrect behaviour (| is the cursor) 
     501# {} : never highlighted 
     502# { } : always correct 
     503#  
     504# 
     505 
    400506sub highlight_braces { 
    401507    my ($self) = @_; 
    402  
    403     $self->BraceHighlight( -1, -1 ); # Wx::wxSTC_INVALID_POSITION 
     508     
     509    # remove current highlighting if any 
     510    $self->BraceHighlight( $STC_INVALID_POSITION, $STC_INVALID_POSITION  ); 
     511     
    404512    my $pos1 = $self->GetCurrentPos; 
    405     my $chr  = chr( $self->GetCharAt($pos1) ); 
    406  
    407     my @braces = ( '{', '}', '(', ')', '[', ']' ); 
    408     if ( not grep { $chr eq $_ } @braces ) { 
    409         if ( $pos1 > 0 ) { 
    410             $pos1--; 
    411             $chr = chr( $self->GetCharAt($pos1) ); 
    412             return unless grep { $chr eq $_ } @braces; 
    413         } 
    414     } 
    415  
    416     my $pos2 = $self->BraceMatch($pos1); 
    417     return if abs( $pos1 - $pos2 ) < 2; 
    418  
    419     return if $pos2 == -1; #Wx::wxSTC_INVALID_POSITION  #???? 
    420  
    421     $self->BraceHighlight( $pos1, $pos2 ); 
    422  
    423     return; 
    424 } 
    425  
     513    my $info1 = $self->get_brace_info($pos1) or return; 
     514    my ($actual_pos1) = @$info1; 
     515     
     516    my $actual_pos2 = $self->BraceMatch($actual_pos1); 
     517#   return if abs( $pos1 - $pos2 ) < 2; 
     518 
     519    return if $actual_pos2 == $STC_INVALID_POSITION; #Wx::wxSTC_INVALID_POSITION  #???? 
     520 
     521    $self->BraceHighlight( $actual_pos1, $actual_pos2 ); 
     522 
     523    return; 
     524} 
     525 
     526=head2 goto_matching_brace 
     527 
     528Move the cursor to the matching brace if any. If the cursor is inside the braces the destination  
     529will be inside too, same it is outside. 
     530 
     531    Params: 
     532        pos - the cursor position in the editor [defaults to cursor position) : int 
     533         
     534 
     535 
     536=cut 
     537sub goto_matching_brace { 
     538    my ($self, $pos) = @_; 
     539    $pos = $self->GetCurrentPos unless defined $pos; 
     540    my $info1 = $self->get_brace_info($pos) or return; 
     541    my ($actual_pos1, $brace, $is_after, $is_opening) = @$info1; 
     542     
     543    my $actual_pos2 = $self->BraceMatch($actual_pos1); 
     544    return if $actual_pos2 == $STC_INVALID_POSITION; 
     545     
     546    # several cases: 
     547    my $pos2 = $actual_pos2; 
     548    $pos2++ if $is_after; # ensure is stays inside if origin is inside, same four outside 
     549 
     550    $self->GotoPos($pos2); 
     551} 
     552 
     553=head2 select_to_matching_brace 
     554 
     555Select to the matching opening or closing brace. If the cursor is inside the braces the destination  
     556will be inside too, same it is outside. 
     557 
     558    Params: 
     559        pos - the cursor position in the editor [defaults to cursor position) : int 
     560         
     561 
     562 
     563=cut 
     564 
     565sub select_to_matching_brace { 
     566    my ($self, $pos) = @_; 
     567    $pos = $self->GetCurrentPos unless defined $pos; 
     568 
     569 
     570    my $info1 = $self->get_brace_info($pos) or return; 
     571    my ($actual_pos1, $brace, $is_after, $is_opening) = @$info1; 
     572     
     573    my $actual_pos2 = $self->BraceMatch($actual_pos1); 
     574    return if $actual_pos2 == $STC_INVALID_POSITION; 
     575     
     576    # several cases: 
     577    my $pos2 = $actual_pos2; 
     578    $pos2++ if $is_after; # ensure is stays inside if origin is inside, same four outside 
     579 
     580    my $start = $is_opening ? $self->GetSelectionStart() : $self->GetSelectionEnd(); 
     581    $self->SetSelection($start, $pos2); 
     582         
     583} 
     584         
    426585# currently if there are 9 lines we set the margin to 1 width and then 
    427586# if another line is added it is not seen well. 
  • trunk/Padre/lib/Padre/Wx/Main.pm

    r11098 r11105  
    29122912 
    29132913sub on_brace_matching { 
    2914     my $self = shift; 
    2915     my $page = $self->current->editor; 
    2916     my $pos1 = $page->GetCurrentPos; 
    2917     my $pos2 = $page->BraceMatch($pos1); 
    2918     if ( $pos2 == -1 ) { #Wx::wxSTC_INVALID_POSITION 
    2919         if ( $pos1 > 0 ) { 
    2920             $pos1--; 
    2921             $pos2 = $page->BraceMatch($pos1); 
    2922         } 
    2923     } 
    2924  
    2925     if ( $pos2 != -1 ) { #Wx::wxSTC_INVALID_POSITION 
    2926         $page->GotoPos($pos2); 
    2927     } 
    2928  
    2929     # TO DO: or any nearby position. 
    2930  
    2931     return; 
     2914    shift->current->editor->goto_matching_brace; 
    29322915} 
    29332916 
Note: See TracChangeset for help on using the changeset viewer.