bundleUUID B5A22967-2E6A-4B66-9C71-DA8762C01E27 commands argument action findNext findInProjectIgnoreCase findInProjectRegularExpression findString ignoreCase regularExpression replaceAllScope document replaceString $1 wrapAround command findWithOptions: argument beforeRunningCommand nop command export __CF_USER_TEXT_ENCODING=0x1F5:0x8000100:0x8000100 perl -Xe ' ########################################## ## Select Balanced (HT|X)ML Tags: bug report/feature request to Hans-Jörg Bibiko bibiko@eva.mpg.de ########################################### BEGIN { if (!eval { require HTML::Parser}) { print STDERR "The Perl package HTML::Parser is not installed!\n\nExecute in Terminal:\nsudo -H cpan -i HTML::Parser\n\nHint: You need install Apple\x27s developer toolkit (gcc compiler)."; exit 1; } } our @stack = (); our $start; our $end; $utf8a = q{ [\x00-\x7F] | [\xC2-\xDF][\x80-\xBF] | \xE0[\xA0-\xBF][\x80-\xBF] | [\xE1-\xEF][\x80-\xBF][\x80-\xBF] | \xF0[\x90-\xBF][\x80-\xBF][\x80-\xBF] | [\xF1-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF] | \xF8[\x88-\xBF][\x80-\xBF][\x80-\xBF][\x80-\xBF] | [\xF9-\xFB][\x88-\xBF][\x88-\xBF][\x88-\xBF][\x88-\xBF] | \xFC[\x84-\xBF][\x88-\xBF][\x88-\xBF][\x88-\xBF][\x88-\xBF] | \xFD[\x88-\xBF][\x88-\xBF][\x88-\xBF][\x88-\xBF][\x88-\xBF] }; undef $/; $org = <>; if(defined($ENV{"TM_INPUT_START_LINE"})) { $line = $ENV{"TM_INPUT_START_LINE"}-1; $line_index = $ENV{"TM_INPUT_START_LINE_INDEX"}+0; } else { $line = $ENV{"TM_LINE_NUMBER"}-1; $line_index = $ENV{"TM_LINE_INDEX"}+0; } # get position of the caret and set it to $curindex our $curindex = 0; $count = $line; while($count--){ $curindex = index($org,"\n",$curindex); $curindex++; } $curindex += $line_index; @ign_tag = (); if(defined($ENV{"TM_HTML_EMPTY_TAGS"})) { @ign_tag = split(/\|/, $ENV{"TM_HTML_EMPTY_TAGS"}); push(@ign_tag,map{$_."/"}@ign_tag); } $xmlmode = ($ENV{"TM_MODE"} =~ m/(xml|property list|xlst)/i) ? 1 : 0; ###### parse left from caret # adjust curindex if curindex is inside of a tag our $p = HTML::Parser->new( api_version => 3, start_h => [\&starttag_l0,"offset, offset_end"], end_h => [\&endtag_l0, "offset_end"], ); $p->ignore_tags( @ign_tag ); $p->xml_mode($xmlmode); $p->parse($org); # start parse left from caret @stack = (); $p = HTML::Parser->new( api_version => 3, start_h => [\&starttag_left,"tagname, offset, line, offset_end"], end_h => [\&endtag_left, "tagname"], ); $p->ignore_tags( @ign_tag ); $p->xml_mode($xmlmode); $text = substr($org,0,$curindex); $p->parse($text); $start = shift(@stack); # calculate $column for setting the caret and check for the very left edge of a multi-line block $offset = rindex(substr($text,0,$start->[1]), "\n"); $offtext = substr($org, $offset+1, $start->[1]-$offset); $offtext =~ m/^([ \t]*?)<$/;$a=$1; $offtext =~ m/^(.*?)<$/; $b=$1; ## in case that close tag is not the very right edge @len = $offtext =~ /$utf8a/gox; $column_temp = $#len+1; $column = $column_temp; $start_temp = $start->[1]; $is_edge = 0; if(length($a)==length($b)) { $start->[1] -= length($a); $column = 1; $is_edge = 1; } undef $text; ####### search right from caret @stack = (); $p = HTML::Parser->new( api_version => 3, start_h => [\&starttag_right,"tagname"], end_h => [\&endtag_right, "tagname, offset_end"], ); $p->ignore_tags( @ign_tag ); $p->xml_mode($xmlmode); # readjust caret $curindex = $start->[3]; $p->parse(substr($org,$curindex,length($org)-$curindex)); # check for the very right edge of a multi-line block if($is_edge) { $offtext = substr($org,$end->[1]+$curindex,length($org)-$end->[1]-$curindex); $offtext = substr($offtext,0,index($offtext,"\n")); $offtext =~ m/^([ \t]*$)/m; $a=$1; $offtext =~ m/^(.*?)$/m; $b=$1; if(length($a)==length($b)){ $end->[1] += length($1)+1; } else { $column = $column_temp; $start->[1] = $start_temp; } } # exit if no open tag is found if(!length($start->[0])){ print STDERR "No balanced tags found!"; exit 1; } # warn if open and close tag names differ print STDERR "Please verify start/end tag:\n\n\x27$start->[0]\x27 ≠ \x27$end->[0]\x27" if($start->[0] ne $end->[0]); # set the caret and return the chunk system("open \"txmt://open/?line=$start->[2]&column=$column\""); print substr($org,$start->[1],$end->[1]+$curindex-$start->[1]); sub starttag_l0 { ($offset, $offset_end) = @_; if($offset>=$curindex) { $curindex = $adjustindex + 1; $p->eof(); return; } $adjustindex = $offset_end; } sub endtag_l0 { ($offset_end) = @_; if($offset_end>$curindex) { $curindex = $adjustindex + 1; $p->eof(); return; } $adjustindex = $offset_end; } sub starttag_left { unshift(@stack, [@_]); } sub endtag_left { ($tag) = @_; while(@stack) { last if (shift(@stack)->[0] eq $tag) }; } sub starttag_right { unshift(@stack, [@_]); } sub endtag_right { ($tag, $offset_end) = @_; if(!@stack){ $end = [$tag,$offset_end]; $p->eof() if ($end->[0] eq $tag); } else { while(@stack) { last if (shift(@stack)->[0] eq $tag) }; } } ' | pbcopy -pboard find input document keyEquivalent ^1 name start output showAsTooltip uuid 44875D0C-086B-4B25-9F6F-79B9BAA1C03A command executeCommandWithOptions: command findNext: keyEquivalent @B name Select Balanced (HT|X)ML Tags scope text.html -(comment.block.html) -(text.html source), text.xml -(comment.block.xml) -(text.xml source) uuid 154ED053-9860-4249-B159-E7A8D7482AE5