@@ -13,7 +13,8 @@ interface
1313 uses
1414 NppSimpleObjects;
1515
16- procedure FindMatchingTag (ASelect: boolean = False; AContentsOnly: Boolean = False);
16+ type TSelectionOptions = set of (soNone, soTags, soContents);
17+ procedure FindMatchingTag (SelectionOptions: TSelectionOptions = [soNone]);
1718
1819// //////////////////////////////////////////////////////////////////////////////////////////////////
1920implementation
@@ -141,7 +142,7 @@ function ExtractTagName(AView: TActiveDocument;
141142end { ExtractTagName} ;
142143
143144{ ------------------------------------------------------------------------------------------------ }
144- procedure FindMatchingTag (ASelect: boolean = False; AContentsOnly: Boolean = False );
145+ procedure FindMatchingTag (SelectionOptions: TSelectionOptions );
145146var
146147 npp: TApplication;
147148 doc: TActiveDocument;
@@ -150,9 +151,9 @@ procedure FindMatchingTag(ASelect: boolean = False; AContentsOnly: Boolean = Fal
150151 Tag, NextTag, MatchingTag, Target: TTextRange;
151152 TagName: string;
152153 TagOpens, TagCloses: boolean;
153-
154+ InitPos: Sci_Position;
154155 Direction: TDirectionEnum;
155- IsXML: boolean;
156+ IsXML, ASelect, AContentsOnly, TagsOnly : boolean;
156157 DisposeOfTag: boolean;
157158 i: integer;
158159 Found: TTextRange;
@@ -184,14 +185,41 @@ procedure FindMatchingTag(ASelect: boolean = False; AContentsOnly: Boolean = Fal
184185 end ;
185186 end ;
186187 // ---------------------------------------------------------------------------------------------
187- var
188- InitPos: Sci_Position;
188+ procedure SelectTags (Tag, MatchingTag: TTextRange);
189+ var
190+ Doc: TActiveDocument;
191+ TagAttrPos: Integer;
192+ begin
193+ Doc := Tag.Document;
194+ // Trim attributes from tag selection
195+ TagAttrPos := Pos(' ' , Tag.Text);
196+ if TagAttrPos > Pos(' <' , Tag.Text) then
197+ Tag.EndPos := Tag.StartPos + TagAttrPos;
198+ // Trim '<' or '</' and '>' from selection
199+ if not Assigned(MatchingTag) then begin
200+ // Narrow selection for a self-closing tag
201+ Tag.StartPos := Tag.StartPos + Pos(' <' , Tag.Text);
202+ if Pos(' />' , Tag.Text) > 0 then
203+ Tag.EndPos := Tag.EndPos - 1 ;
204+ end else
205+ Tag.StartPos := Tag.StartPos + (Pos(' /' , Tag.Text) shr 1 ) + 1 ;
206+ Doc.SendMessage(SCI_SETSELECTION, Tag.StartPos, Tag.EndPos - 1 );
207+ if Assigned(MatchingTag) then begin
208+ TagAttrPos := Pos(' ' , MatchingTag.Text);
209+ if TagAttrPos > Pos(' <' , MatchingTag.Text) then
210+ MatchingTag.EndPos := MatchingTag.StartPos + TagAttrPos;
211+ Doc.SendMessage(SCI_ADDSELECTION, MatchingTag.StartPos + (Pos(' /' , MatchingTag.Text) shr 1 ) + 1 , MatchingTag.EndPos - 1 );
212+ end ;
213+ end ;
214+ // ---------------------------------------------------------------------------------------------
189215begin
190216 npp := GetApplication();
191217 doc := npp.ActiveDocument;
192218
193219 IsXML := (doc.Language = L_XML);
194-
220+ ASelect := not (soNone in SelectionOptions);
221+ AContentsOnly := ASelect and ([soContents] = SelectionOptions);
222+ TagsOnly := ASelect and (not (soContents in SelectionOptions));
195223 Tags := TStringList.Create;
196224 MatchingTag := nil ;
197225 NextTag := nil ;
@@ -298,8 +326,10 @@ procedure FindMatchingTag(ASelect: boolean = False; AContentsOnly: Boolean = Fal
298326 Tags.LineBreak := #9 ;
299327 if Assigned(MatchingTag) then begin
300328 if Tags.Count = 2 then begin
329+ // Matching tag may be hidden by a fold
330+ doc.SendMessage(SCI_FOLDLINE, doc.SendMessage(SCI_LINEFROMPOSITION, MatchingTag.StartPos), SC_FOLDACTION_EXPAND);
301331 Tag := TTextRange(Tags.Objects[0 ]);
302- if ASelect then begin
332+ if ASelect and not TagsOnly then begin
303333 if Tag.StartPos < MatchingTag.StartPos then begin
304334 if AContentsOnly then begin
305335 Target := doc.GetRange(Tag.EndPos, MatchingTag.StartPos);
@@ -336,12 +366,14 @@ procedure FindMatchingTag(ASelect: boolean = False; AContentsOnly: Boolean = Fal
336366 finally
337367 Target.Free;
338368 end ;
369+ end else if ASelect then begin
370+ SelectTags(Tag, MatchingTag);
339371 end else begin
340372 MatchingTag.Select;
341373 end ;
342- end else begin
343- if ASelect then begin
344- MatchingTag.Select ;
374+ end else begin // Self-closing tag
375+ if TagsOnly then begin
376+ SelectTags( MatchingTag, nil ) ;
345377 end else begin
346378 MatchingTag.Select;
347379 end ;
0 commit comments