View Issue Details

IDProjectCategoryView StatusLast Update
0036798PackagesPackagespublic2020-04-03 17:36
ReporterRolf WetjenAssigned ToBart Broersma 
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformOSWindows 10 x64OS Version1909
Product Version2.0.6Product Build 
Target VersionFixed in Version 
Summary0036798: MatchesWindowsMask('[x]','[x]') return False
DescriptionTMask uses the brackets as a set indicator in the mask string. In this case the FMask.MinLength and FMask.MaxLength are set to 1. The brackets in the test string are not treated in any special way and so the match fails as the length of the test string is 3 (tested inside TMask.Matches).

I think that this isn't the expected behavior especially as [ and ] are regular character for file and path names in windows.
TagsNo tags attached.
Fixed in Revisionr62781, r62874
LazTarget-
WidgetsetWin32/Win64
Attached Files
  • masks.xml.patch (8,282 bytes)
    Index: docs/xml/lazutils/masks.xml
    ===================================================================
    --- docs/xml/lazutils/masks.xml	(revision 62776)
    +++ docs/xml/lazutils/masks.xml	(working copy)
    @@ -41,7 +41,23 @@
           <element name="TMaskCharType.mcAnyChar"><short/></element>
           <!-- enumeration value Visibility: default -->
           <element name="TMaskCharType.mcAnyText"><short/></element>
    +      <!-- enumeration value Visibility: default -->
    +      <element name="TMaskOption">
    +        <short/>
    +        <descr/>
    +        <seealso/>
    +      </element>
    +      <!-- enumeration value Visibility: default -->
    +      <element name="TMaskOption.moCaseSensitive"><short>Compare case sensitive.</short></element>
    +      <!-- enumeration value Visibility: default -->
    +      <element name="TMaskOption.moDisableSets"><short>Disable set processing. "[" and "]" are treated as <link id="TMask">literal characters</link>.</short></element>
           <!-- set type Visibility: default -->
    +      <element name="MaskOptions">
    +        <short/>
    +        <descr/>
    +        <seealso/>
    +      </element>
    +      <!-- set type Visibility: default -->
           <element name="TCharSet">
             <short/>
             <descr/>
    @@ -104,7 +120,12 @@
           <!-- object Visibility: default -->
           <element name="TMask">
             <short>The TMask class represents a mask.</short>
    -        <descr/>
    +        <descr><p>A mask is a compare pattern build of wildcards, sets and literal characters.</p>
    +<p>Each <b>literal character</b> must match a single character in the string. Case sensitivity depends on the option <link id="TMaskOption">moCaseSensitive</link>.<br/>
    +A <b>set</b> starts with "[" and ends with "]". Each element of a set is a literal character and or a range. A range is defined as first-last literal charcter. One character of a set must match a single character in the string. A set [!...] matches if the character is not in the set. The option <link id="TMaskOption">moDisableSets</link> disables set processing.<br/> 
    +<b>Wildcards</b> are * and ?. An asterisk matches any number of characters. A question mark matches a single character.</p>
    +<p>'Hello world' matches to the mask 'H?ll[xoy] w*d'.</p>
    +</descr>  
             <errors/>
             <seealso/>
           </element>
    @@ -117,9 +138,7 @@
           <!-- constructor Visibility: public -->
           <element name="TMask.Create">
             <short>Creates new mask for matching.</short>
    -        <descr>
    -          <p>Creates new mask for matching. Matching is case-insensitive. The mask consist of literal elements such as:</p>
    -        </descr>
    +        <descr>Creates new <link id="TMask">mask</link> for matching.</descr>
             <errors/>
             <seealso/>
           </element>
    @@ -134,7 +153,7 @@
           </element>
           <!-- function Visibility: public -->
           <element name="TMask.Matches">
    -        <short>If the file name matches the mask.</short>
    +        <short>Test if a filename matches the mask.</short>
             <descr/>
             <errors/>
             <seealso/>
    @@ -143,6 +162,17 @@
           <element name="TMask.Matches.Result"><short/></element>
           <!-- argument Visibility: default -->
           <element name="TMask.Matches.AFileName"><short/></element>
    +      <!-- function Visibility: public -->
    +      <element name="TMask.MatchesWindowsMask">
    +        <short>Test if a filename matches the mask. Implements some special rules for a Windows© filesystem comparison.</short>
    +        <descr/>
    +        <errors/>
    +        <seealso/>
    +      </element>
    +      <!-- function result Visibility: default -->
    +      <element name="TMask.MatchesWindowsMask.Result"><short/></element>
    +      <!-- argument Visibility: default -->
    +      <element name="TMask.MatchesWindowsMask.AFileName"><short/></element>
           <!-- object Visibility: default -->
           <element name="TParseStringList">
             <short>The TParseStringList class is used to parse text into the list of strings.</short>
    @@ -196,7 +226,7 @@
           <element name="TMaskList.GetItem.Index"><short/></element>
           <!-- constructor Visibility: public -->
           <element name="TMaskList.Create">
    -        <short>Creates new list of masks from passed value, each item is separated by separator.</short>
    +        <short>Creates new list of masks from passed value, each item is separated by the parameter Separator.</short>
             <descr/>
             <errors/>
             <seealso/>
    @@ -214,7 +244,7 @@
           </element>
           <!-- function Visibility: public -->
           <element name="TMaskList.Matches">
    -        <short>If the file name matches at least one of mask list items.</short>
    +        <short>Test if the file name matches at least one of mask list items.</short>
             <descr/>
             <errors/>
             <seealso/>
    @@ -223,6 +253,17 @@
           <element name="TMaskList.Matches.Result"><short/></element>
           <!-- argument Visibility: default -->
           <element name="TMaskList.Matches.AFileName"><short/></element>
    +      <!-- function Visibility: public -->
    +      <element name="TMaskList.MatchesWindowsMask">
    +        <short>Test if the file name matches at least one of mask list items. Implements some special rules for a Windows© filesystem comparison.</short>
    +        <descr/>
    +        <errors/>
    +        <seealso/>
    +      </element>
    +      <!-- function result Visibility: default -->
    +      <element name="TMaskList.MatchesWindowsMask.Result"><short/></element>
    +      <!-- argument Visibility: default -->
    +      <element name="TMaskList.MatchesWindowsMask.AFileName"><short/></element>
           <!-- property Visibility: public -->
           <element name="TMaskList.Count">
             <short>The count of mask list items.</short>
    @@ -239,7 +280,7 @@
           <element name="TMaskList.Items.Index"><short/></element>
           <!-- function Visibility: default -->
           <element name="MatchesMask">
    -        <short>If the file name matches the passed mask.</short>
    +        <short>Test if the file name matches the passed mask.</short>
             <descr/>
             <errors/>
             <seealso/>
    @@ -251,8 +292,21 @@
           <!-- argument Visibility: default -->
           <element name="MatchesMask.Mask"><short/></element>
           <!-- function Visibility: default -->
    +      <element name="MatchesWindowsMask">
    +        <short>Test if the file name matches the passed mask. Implements some special rules for a Windows© filesystem comparison.</short>
    +        <descr/>
    +        <errors/>
    +        <seealso/>
    +      </element>
    +      <!-- function result Visibility: default -->
    +      <element name="MatchesWindowsMask.Result"><short/></element>
    +      <!-- argument Visibility: default -->
    +      <element name="MatchesWindowsMask.FileName"><short/></element>
    +      <!-- argument Visibility: default -->
    +      <element name="MatchesWindowsMask.Mask"><short/></element>
    +      <!-- function Visibility: default -->
           <element name="MatchesMaskList">
    -        <short>If the file name matches at least one of passed masks separated by separator.</short>
    +        <short>Test if the file name matches at least one of passed masks separated by the parameter Separator.</short>
             <descr/>
             <errors/>
             <seealso/>
    @@ -265,6 +319,21 @@
           <element name="MatchesMaskList.Mask"><short/></element>
           <!-- argument Visibility: default -->
           <element name="MatchesMaskList.Separator"><short/></element>
    +      <!-- function Visibility: default -->
    +      <element name="MatchesWindowsMaskList">
    +        <short>Test if the file name matches at least one of passed masks separated by the parameter Separator. Implements some special rules for a Windows© filesystem comparison.</short>
    +        <descr/>
    +        <errors/>
    +        <seealso/>
    +      </element>
    +      <!-- function result Visibility: default -->
    +      <element name="MatchesWindowsMaskList.Result"><short/></element>
    +      <!-- argument Visibility: default -->
    +      <element name="MatchesWindowsMaskList.FileName"><short/></element>
    +      <!-- argument Visibility: default -->
    +      <element name="MatchesWindowsMaskList.Mask"><short/></element>
    +      <!-- argument Visibility: default -->
    +      <element name="MatchesWindowsMaskList.Separator"><short/></element>
         </module>
         <!-- Masks -->
       </package>
    
    masks.xml.patch (8,282 bytes)

Activities

Mattias Gaertner

2020-03-16 15:25

manager   ~0121622

Delphi's MatchesMask('[x]','[x]') returns False as well, which makes sense since the [x] mask matches 'x' or 'X'.

Bart Broersma

2020-03-16 22:08

developer   ~0121632

Last edited: 2020-03-16 22:08

View 2 revisions

To escape a '[', you need to use '[[]', so '[[]x]' as a Mask wil match.
Delphi does behave exactly the same.

A mechanisme to disable sets (so '[x]' isn't iterpreted as a set containing only 'x'), might be a usefull add-on though.

If other Lazarus devels dont object I'll try to implement somtehing like that.

Bart Broersma

2020-03-20 18:33

developer   ~0121665

Please test and close if OK.

Rolf Wetjen

2020-03-22 13:54

reporter   ~0121683

Hi Bart,

here's a patch for the documentation of TMask.

Regards
Rolf

masks.xml.patch (8,282 bytes)
Index: docs/xml/lazutils/masks.xml
===================================================================
--- docs/xml/lazutils/masks.xml	(revision 62776)
+++ docs/xml/lazutils/masks.xml	(working copy)
@@ -41,7 +41,23 @@
       <element name="TMaskCharType.mcAnyChar"><short/></element>
       <!-- enumeration value Visibility: default -->
       <element name="TMaskCharType.mcAnyText"><short/></element>
+      <!-- enumeration value Visibility: default -->
+      <element name="TMaskOption">
+        <short/>
+        <descr/>
+        <seealso/>
+      </element>
+      <!-- enumeration value Visibility: default -->
+      <element name="TMaskOption.moCaseSensitive"><short>Compare case sensitive.</short></element>
+      <!-- enumeration value Visibility: default -->
+      <element name="TMaskOption.moDisableSets"><short>Disable set processing. "[" and "]" are treated as <link id="TMask">literal characters</link>.</short></element>
       <!-- set type Visibility: default -->
+      <element name="MaskOptions">
+        <short/>
+        <descr/>
+        <seealso/>
+      </element>
+      <!-- set type Visibility: default -->
       <element name="TCharSet">
         <short/>
         <descr/>
@@ -104,7 +120,12 @@
       <!-- object Visibility: default -->
       <element name="TMask">
         <short>The TMask class represents a mask.</short>
-        <descr/>
+        <descr><p>A mask is a compare pattern build of wildcards, sets and literal characters.</p>
+<p>Each <b>literal character</b> must match a single character in the string. Case sensitivity depends on the option <link id="TMaskOption">moCaseSensitive</link>.<br/>
+A <b>set</b> starts with "[" and ends with "]". Each element of a set is a literal character and or a range. A range is defined as first-last literal charcter. One character of a set must match a single character in the string. A set [!...] matches if the character is not in the set. The option <link id="TMaskOption">moDisableSets</link> disables set processing.<br/> 
+<b>Wildcards</b> are * and ?. An asterisk matches any number of characters. A question mark matches a single character.</p>
+<p>'Hello world' matches to the mask 'H?ll[xoy] w*d'.</p>
+</descr>  
         <errors/>
         <seealso/>
       </element>
@@ -117,9 +138,7 @@
       <!-- constructor Visibility: public -->
       <element name="TMask.Create">
         <short>Creates new mask for matching.</short>
-        <descr>
-          <p>Creates new mask for matching. Matching is case-insensitive. The mask consist of literal elements such as:</p>
-        </descr>
+        <descr>Creates new <link id="TMask">mask</link> for matching.</descr>
         <errors/>
         <seealso/>
       </element>
@@ -134,7 +153,7 @@
       </element>
       <!-- function Visibility: public -->
       <element name="TMask.Matches">
-        <short>If the file name matches the mask.</short>
+        <short>Test if a filename matches the mask.</short>
         <descr/>
         <errors/>
         <seealso/>
@@ -143,6 +162,17 @@
       <element name="TMask.Matches.Result"><short/></element>
       <!-- argument Visibility: default -->
       <element name="TMask.Matches.AFileName"><short/></element>
+      <!-- function Visibility: public -->
+      <element name="TMask.MatchesWindowsMask">
+        <short>Test if a filename matches the mask. Implements some special rules for a Windows© filesystem comparison.</short>
+        <descr/>
+        <errors/>
+        <seealso/>
+      </element>
+      <!-- function result Visibility: default -->
+      <element name="TMask.MatchesWindowsMask.Result"><short/></element>
+      <!-- argument Visibility: default -->
+      <element name="TMask.MatchesWindowsMask.AFileName"><short/></element>
       <!-- object Visibility: default -->
       <element name="TParseStringList">
         <short>The TParseStringList class is used to parse text into the list of strings.</short>
@@ -196,7 +226,7 @@
       <element name="TMaskList.GetItem.Index"><short/></element>
       <!-- constructor Visibility: public -->
       <element name="TMaskList.Create">
-        <short>Creates new list of masks from passed value, each item is separated by separator.</short>
+        <short>Creates new list of masks from passed value, each item is separated by the parameter Separator.</short>
         <descr/>
         <errors/>
         <seealso/>
@@ -214,7 +244,7 @@
       </element>
       <!-- function Visibility: public -->
       <element name="TMaskList.Matches">
-        <short>If the file name matches at least one of mask list items.</short>
+        <short>Test if the file name matches at least one of mask list items.</short>
         <descr/>
         <errors/>
         <seealso/>
@@ -223,6 +253,17 @@
       <element name="TMaskList.Matches.Result"><short/></element>
       <!-- argument Visibility: default -->
       <element name="TMaskList.Matches.AFileName"><short/></element>
+      <!-- function Visibility: public -->
+      <element name="TMaskList.MatchesWindowsMask">
+        <short>Test if the file name matches at least one of mask list items. Implements some special rules for a Windows© filesystem comparison.</short>
+        <descr/>
+        <errors/>
+        <seealso/>
+      </element>
+      <!-- function result Visibility: default -->
+      <element name="TMaskList.MatchesWindowsMask.Result"><short/></element>
+      <!-- argument Visibility: default -->
+      <element name="TMaskList.MatchesWindowsMask.AFileName"><short/></element>
       <!-- property Visibility: public -->
       <element name="TMaskList.Count">
         <short>The count of mask list items.</short>
@@ -239,7 +280,7 @@
       <element name="TMaskList.Items.Index"><short/></element>
       <!-- function Visibility: default -->
       <element name="MatchesMask">
-        <short>If the file name matches the passed mask.</short>
+        <short>Test if the file name matches the passed mask.</short>
         <descr/>
         <errors/>
         <seealso/>
@@ -251,8 +292,21 @@
       <!-- argument Visibility: default -->
       <element name="MatchesMask.Mask"><short/></element>
       <!-- function Visibility: default -->
+      <element name="MatchesWindowsMask">
+        <short>Test if the file name matches the passed mask. Implements some special rules for a Windows© filesystem comparison.</short>
+        <descr/>
+        <errors/>
+        <seealso/>
+      </element>
+      <!-- function result Visibility: default -->
+      <element name="MatchesWindowsMask.Result"><short/></element>
+      <!-- argument Visibility: default -->
+      <element name="MatchesWindowsMask.FileName"><short/></element>
+      <!-- argument Visibility: default -->
+      <element name="MatchesWindowsMask.Mask"><short/></element>
+      <!-- function Visibility: default -->
       <element name="MatchesMaskList">
-        <short>If the file name matches at least one of passed masks separated by separator.</short>
+        <short>Test if the file name matches at least one of passed masks separated by the parameter Separator.</short>
         <descr/>
         <errors/>
         <seealso/>
@@ -265,6 +319,21 @@
       <element name="MatchesMaskList.Mask"><short/></element>
       <!-- argument Visibility: default -->
       <element name="MatchesMaskList.Separator"><short/></element>
+      <!-- function Visibility: default -->
+      <element name="MatchesWindowsMaskList">
+        <short>Test if the file name matches at least one of passed masks separated by the parameter Separator. Implements some special rules for a Windows© filesystem comparison.</short>
+        <descr/>
+        <errors/>
+        <seealso/>
+      </element>
+      <!-- function result Visibility: default -->
+      <element name="MatchesWindowsMaskList.Result"><short/></element>
+      <!-- argument Visibility: default -->
+      <element name="MatchesWindowsMaskList.FileName"><short/></element>
+      <!-- argument Visibility: default -->
+      <element name="MatchesWindowsMaskList.Mask"><short/></element>
+      <!-- argument Visibility: default -->
+      <element name="MatchesWindowsMaskList.Separator"><short/></element>
     </module>
     <!-- Masks -->
   </package>
masks.xml.patch (8,282 bytes)

Rolf Wetjen

2020-04-03 13:07

reporter   ~0121861

Documentation patch attached: https://bugs.freepascal.org/view.php?id=36798#c121683

Bart Broersma

2020-04-03 17:36

developer   ~0121867

Thanks for the patch.
It is customary to open a new issue for documentation patches though.
Please close if OK.

Issue History

Date Modified Username Field Change
2020-03-16 07:20 Rolf Wetjen New Issue
2020-03-16 15:25 Mattias Gaertner Note Added: 0121622
2020-03-16 22:08 Bart Broersma Note Added: 0121632
2020-03-16 22:08 Bart Broersma Assigned To => Bart Broersma
2020-03-16 22:08 Bart Broersma Status new => assigned
2020-03-16 22:08 Bart Broersma Note Edited: 0121632 View Revisions
2020-03-20 18:33 Bart Broersma Status assigned => resolved
2020-03-20 18:33 Bart Broersma Resolution open => fixed
2020-03-20 18:33 Bart Broersma Fixed in Revision => r62781
2020-03-20 18:33 Bart Broersma LazTarget => -
2020-03-20 18:33 Bart Broersma Widgetset Win32/Win64 => Win32/Win64
2020-03-20 18:33 Bart Broersma Note Added: 0121665
2020-03-22 13:54 Rolf Wetjen File Added: masks.xml.patch
2020-03-22 13:54 Rolf Wetjen Note Added: 0121683
2020-04-03 13:07 Rolf Wetjen Status resolved => assigned
2020-04-03 13:07 Rolf Wetjen Resolution fixed => reopened
2020-04-03 13:07 Rolf Wetjen Note Added: 0121861
2020-04-03 17:36 Bart Broersma Status assigned => resolved
2020-04-03 17:36 Bart Broersma Resolution reopened => fixed
2020-04-03 17:36 Bart Broersma Fixed in Revision r62781 => r62781, r62874
2020-04-03 17:36 Bart Broersma Widgetset Win32/Win64 => Win32/Win64
2020-04-03 17:36 Bart Broersma Note Added: 0121867