FindFileApplication.st
changeset 5231 d74730347ed8
parent 5224 93c284d6fe4b
child 5252 453aee873a3d
--- a/FindFileApplication.st	Thu Oct 02 17:15:12 2003 +0200
+++ b/FindFileApplication.st	Thu Oct 02 19:42:02 2003 +0200
@@ -13,9 +13,10 @@
 "{ Package: 'stx:libtool' }"
 
 AbstractFileApplicationNoteBookComponent subclass:#FindFileApplication
-	instanceVariableNames:'contentsPatternHolder searchDirectories ignoreCaseInName
-		notSearchForSameContents namePatternHolder ignoreCaseInContents
-		searchDirectoryHolder findFileView searchResultTable resultList
+	instanceVariableNames:'searchDirectories searchDirectoryHolder notSearchForSameContents
+		namePatternHolder ignoreCaseInName contentsPatternHolder
+		ignoreCaseInContents notContentsPatternHolder
+		ignoreCaseInNotContents findFileView searchResultTable resultList
 		enableStop enableSearch stopSignal accessLock searchTask expanded
 		searchRecursively selectionHolder hasListEntries
 		targetApplication useLocate'
@@ -101,7 +102,7 @@
           name: 'File Search'
           min: (Point 377 131)
           max: (Point 1280 1024)
-          bounds: (Rectangle 16 52 681 384)
+          bounds: (Rectangle 10 46 675 378)
         )
         component: 
        (SpecCollection
@@ -115,7 +116,7 @@
             )
            (ViewSpec
               name: 'Box1'
-              layout: (LayoutFrame 0 0.0 32 0 0 1.0 126 0)
+              layout: (LayoutFrame 0 0.0 32 0 0 1.0 132 0)
               component: 
              (SpecCollection
                 collection: (
@@ -134,6 +135,15 @@
                     acceptOnPointerLeave: false
                   )
                  (CheckBoxSpec
+                    label: 'Use ''locate'' Cmd'
+                    name: 'UseLocateCheckBox'
+                    layout: (LayoutFrame -236 1 5 0 -105 1 28 0)
+                    visibilityChannel: canUseLocate
+                    tabable: true
+                    model: useLocate
+                    translateLabel: true
+                  )
+                 (CheckBoxSpec
                     label: 'Recursively'
                     name: 'RecursiveSearchCheckBox'
                     layout: (LayoutFrame -97 1 5 0 0 1 28 0)
@@ -144,13 +154,13 @@
                  (LabelSpec
                     label: 'Search files named:'
                     name: 'FileNameLabel'
-                    layout: (LayoutFrame 4 0 31 0 136 0 48 0)
+                    layout: (LayoutFrame 4 0 30 0 136 0 47 0)
                     translateLabel: true
                     adjust: left
                   )
                  (InputFieldSpec
                     name: 'FileNameEntryField'
-                    layout: (LayoutFrame 140 0 29 0 -246 1 49 0)
+                    layout: (LayoutFrame 140 0 28 0 -246 1 48 0)
                     tabable: true
                     model: namePatternHolder
                     immediateAccept: true
@@ -160,7 +170,7 @@
                  (CheckBoxSpec
                     label: 'Directories'
                     name: 'SearchDirectoriesCheckBox'
-                    layout: (LayoutFrame -236 1 30 0 -105 1 50 0)
+                    layout: (LayoutFrame -236 1 29 0 -105 1 49 0)
                     tabable: true
                     model: searchDirectories
                     translateLabel: true
@@ -168,7 +178,7 @@
                  (CheckBoxSpec
                     label: 'Ignore case'
                     name: 'IgnoreCaseInNameCheckBox'
-                    layout: (LayoutFrame -97 1 30 0 0 1 50 0)
+                    layout: (LayoutFrame -97 1 29 0 0 1 49 0)
                     tabable: true
                     model: ignoreCaseInName
                     translateLabel: true
@@ -176,13 +186,13 @@
                  (LabelSpec
                     label: 'Containing the string:'
                     name: 'ContentsLabel'
-                    layout: (LayoutFrame 4 0 57 0 136 0 74 0)
+                    layout: (LayoutFrame 4 0 55 0 136 0 72 0)
                     translateLabel: true
                     adjust: left
                   )
                  (InputFieldSpec
                     name: 'ContentsEntryField'
-                    layout: (LayoutFrame 140 0 54 0 -115 1 74 0)
+                    layout: (LayoutFrame 140 0 52 0 -115 1 72 0)
                     enableChannel: notSearchForSameContents
                     tabable: true
                     model: contentsPatternHolder
@@ -192,19 +202,35 @@
                  (CheckBoxSpec
                     label: 'Ignore case'
                     name: 'IgnoreCaseInContentsCheckBox'
-                    layout: (LayoutFrame -97 1 54 0 0 1 77 0)
+                    layout: (LayoutFrame -97 1 52 0 0 1 75 0)
                     enableChannel: notSearchForSameContents
                     tabable: true
                     model: ignoreCaseInContents
                     translateLabel: true
                   )
+                 (LabelSpec
+                    label: 'Not Containing:'
+                    name: 'NotContentsLabel'
+                    layout: (LayoutFrame 4 0 79 0 136 0 96 0)
+                    translateLabel: true
+                    adjust: left
+                  )
+                 (InputFieldSpec
+                    name: 'NotContentsEntryField'
+                    layout: (LayoutFrame 140 0 76 0 -115 1 96 0)
+                    enableChannel: notSearchForSameContents
+                    tabable: true
+                    model: notContentsPatternHolder
+                    immediateAccept: true
+                    acceptOnPointerLeave: false
+                  )
                  (CheckBoxSpec
-                    label: 'Use ''locate'' Cmd'
-                    name: 'UseLocateCheckBox'
-                    layout: (LayoutFrame -236 1 5 0 -105 1 28 0)
-                    visibilityChannel: canUseLocate
+                    label: 'Ignore case'
+                    name: 'IgnoreCaseInNotContentsCheckBox'
+                    layout: (LayoutFrame -97 1 76 0 0 1 99 0)
+                    enableChannel: notSearchForSameContents
                     tabable: true
-                    model: useLocate
+                    model: ignoreCaseInNotContents
                     translateLabel: true
                   )
                  )
@@ -213,7 +239,7 @@
             )
            (SequenceViewSpec
               name: 'List1'
-              layout: (LayoutFrame 0 0.0 117 0 0 1.0 0 1)
+              layout: (LayoutFrame 0 0.0 132 0 0 1.0 0 1)
               model: selectionHolder
               menu: menu
               hasHorizontalScrollBar: true
@@ -435,7 +461,7 @@
 
 doSearch
 
-    | namePattern namePatterns contentsPattern dir|
+    | namePattern namePatterns contentsPattern notContentsPattern dir|
 
 "/    self changeExtentToSeeSearchResult.
 
@@ -475,6 +501,14 @@
             contentsPattern := contentsPattern asLowercase
         ]
     ].
+    notContentsPattern := self notContentsPatternHolder value.
+    notContentsPattern size == 0 ifTrue:[
+        notContentsPattern := nil
+    ] ifFalse:[
+        self ignoreCaseInNotContents value ifTrue:[
+            notContentsPattern := notContentsPattern asLowercase
+        ]
+    ].
     searchTask := Process for:[
         |message t|
 
@@ -491,6 +525,8 @@
                         ignoreCase:(self ignoreCaseInName value)
                         containingString:contentsPattern
                         ignoreCaseInContents:(self ignoreCaseInContents value)
+                        notContainingString:notContentsPattern
+                        ignoreCaseInNotContents:(self ignoreCaseInNotContents value)
                         sameContentsAsFile:nil 
                         sameContentsAs:nil 
                         in:(self searchDirectoryHolder value).
@@ -644,6 +680,13 @@
     ^ ignoreCaseInName.
 !
 
+ignoreCaseInNotContents
+    ignoreCaseInNotContents isNil ifTrue:[
+        ignoreCaseInNotContents := false asValue.
+    ].
+    ^ ignoreCaseInNotContents.
+!
+
 namePatternHolder
 
     namePatternHolder isNil ifTrue:[
@@ -652,6 +695,14 @@
     ^ namePatternHolder.
 !
 
+notContentsPatternHolder
+
+    notContentsPatternHolder isNil ifTrue:[
+        notContentsPatternHolder := nil asValue.
+    ].
+    ^ notContentsPatternHolder.
+!
+
 notSearchForSameContents
 
     notSearchForSameContents isNil ifTrue:[
@@ -803,10 +854,18 @@
 
 !FindFileApplication methodsFor:'private - searching'!
 
-doFindFileNamed:namePatterns directories:searchDirectories ignoreCase:ignCaseInName containingString:contentsString ignoreCaseInContents:ignCaseInString sameContentsAsFile:filenameToCompareContentsOrNil sameContentsAs:bytesToCompareContentsOrNil in:aDirectory
+doFindFileNamed:namePatterns directories:searchDirectories ignoreCase:ignCaseInName 
+    containingString:contentsStringArg ignoreCaseInContents:ignCaseInContents 
+    notContainingString:notContentsStringArg ignoreCaseInNotContents:ignCaseInNotContents 
+    sameContentsAsFile:filenameToCompareContentsOrNil sameContentsAs:bytesToCompareContentsOrNil in:aDirectory
 
     |dir subDirs nameMatches lines contentsToCompare list directoryContents inStream
-     doesFileMatch|
+     doesFileMatch contentsString notContentsString check checkNot|
+
+    contentsString := contentsStringArg.
+    ignCaseInContents ifTrue:[ contentsString := contentsString asLowercase ].
+    notContentsString := notContentsStringArg.
+    ignCaseInNotContents ifTrue:[ notContentsString := notContentsString asLowercase ].    
 
     dir := aDirectory asFilename.
     self changeInformationTo:'Find File ' , '- searching .' , ((dir name) copyFrom:(self searchDirectoryHolder value asString size + 1)) toTab:false.
@@ -841,7 +900,8 @@
                 ]
             ] ifFalse:[
                 "/ string search ...
-                (contentsMatches := contentsString isNil) ifFalse:[
+                contentsMatches := true.
+                (contentsString notNil or:[notContentsString notNil]) ifTrue:[
                     (f exists and:[f isReadable]) ifFalse:[
                         list add: (('*** ' , f pathName , ' skipped - unreadable or bad symbolic link ***') asText colorizeAllWith:(Color red darkened)).
                     ] ifTrue:[
@@ -853,17 +913,40 @@
 
                                 "/ this typically happens, when a binary file is read linewise ...
                                 cont := f readStream binary contentsOfEntireFile asString.
-                                ignCaseInString ifTrue:[
-                                    contentsMatches := cont asLowercase includesString:contentsString asLowercase
+                                check notNil ifTrue:[
+                                    checkNot isNil ifTrue:[
+                                        contentsMatches := check value:cont
+                                    ] ifFalse:[
+                                        contentsMatches := (check value:cont) and:[(checkNot value:cont) not].
+                                    ]
                                 ] ifFalse:[
-                                    contentsMatches := cont includesString:contentsString
+                                    contentsMatches := (checkNot value:cont) not.
                                 ].
                             ] do:[    
+                                contentsString notNil ifTrue:[
+                                    ignCaseInContents ifTrue:[
+                                        check := [:l | l asLowercase includesString:contentsString]
+                                    ] ifFalse:[
+                                        check := [:l | l includesString:contentsString]
+                                    ].
+                                ].
+                                notContentsString notNil ifTrue:[
+                                    ignCaseInNotContents ifTrue:[
+                                        checkNot := [:l | l asLowercase includesString:notContentsString]
+                                    ] ifFalse:[
+                                        checkNot := [:l | l includesString:notContentsString]
+                                    ].
+                                ].
+
                                 lines := f contents ? #().
-                                ignCaseInString ifTrue:[
-                                    contentsMatches := (lines findFirst:[:l | l asLowercase includesString:contentsString asLowercase]) ~~ 0
+                                check notNil ifTrue:[
+                                    checkNot isNil ifTrue:[
+                                        contentsMatches := (lines contains:check).
+                                    ] ifFalse:[
+                                        contentsMatches := (lines contains:check) and:[(lines contains:checkNot) not]
+                                    ]
                                 ] ifFalse:[
-                                    contentsMatches := (lines findFirst:[:l | l includesString:contentsString]) ~~ 0
+                                    contentsMatches := (lines contains:checkNot) not.
                                 ].
                             ].
                         ].
@@ -953,8 +1036,8 @@
                 doFindFileNamed:namePatterns 
                 directories:searchDirectories
                 ignoreCase:ignCaseInName 
-                containingString:contentsString 
-                ignoreCaseInContents:ignCaseInString 
+                containingString:contentsString ignoreCaseInContents:ignCaseInContents 
+                notContainingString:notContentsString ignoreCaseInNotContents:ignCaseInNotContents 
                 sameContentsAsFile:filenameToCompareContentsOrNil 
                 sameContentsAs:contentsToCompare
                 in:dir
@@ -1024,5 +1107,5 @@
 !FindFileApplication class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/FindFileApplication.st,v 1.16 2003-10-01 12:52:58 penk Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/FindFileApplication.st,v 1.17 2003-10-02 17:42:02 cg Exp $'
 ! !