@@ -87,58 +87,97 @@ class IgnorePatternModel: ObservableObject {
8787 }
8888
8989 func savePatterns( ) {
90- // Suspend the file monitor to avoid self-triggered updates
91- stopFileMonitor ( )
92-
93- defer {
94- startFileMonitor ( )
95- }
90+ stopFileMonitor ( ) // Suspend the file monitor to avoid self-triggered updates
91+ defer { startFileMonitor ( ) }
9692
97- // Get the file contents; if the file doesn't exist, create it with the patterns
9893 guard let fileContent = try ? String ( contentsOf: fileURL) else {
9994 writeAllPatterns ( )
10095 return
10196 }
10297
10398 let lines = fileContent. split ( separator: " \n " , omittingEmptySubsequences: false ) . map ( String . init)
104- var patternToLineIndex : [ String : Int ] = [ : ] // Map patterns to their line indices
105- var reorderedLines : [ String ] = [ ] // Store the final reordered lines
99+ let ( patternToLineIndex, nonPatternLines) = mapLines ( lines)
100+ let globalCommentLines = extractGlobalComments ( nonPatternLines, patternToLineIndex)
101+
102+ var reorderedLines = reorderPatterns ( globalCommentLines, patternToLineIndex, nonPatternLines, lines)
103+
104+ // Ensure single blank line at the end
105+ reorderedLines = cleanUpWhitespace ( in: reorderedLines)
106+
107+ // Write the updated content back to the file
108+ let updatedContent = reorderedLines. joined ( separator: " \n " )
109+ try ? updatedContent. write ( to: fileURL, atomically: true , encoding: . utf8)
110+ }
111+
112+ private func mapLines( _ lines: [ String ] ) -> ( [ String : Int ] , [ ( line: String , index: Int ) ] ) {
113+ var patternToLineIndex : [ String : Int ] = [ : ]
114+ var nonPatternLines : [ ( line: String , index: Int ) ] = [ ]
106115
107- // Map existing patterns in the file
108116 for (index, line) in lines. enumerated ( ) {
109117 let trimmedLine = line. trimmingCharacters ( in: . whitespaces)
110118 if !trimmedLine. isEmpty && !trimmedLine. hasPrefix ( " # " ) {
111119 patternToLineIndex [ trimmedLine] = index
120+ } else if index != lines. count - 1 {
121+ nonPatternLines. append ( ( line: line, index: index) )
112122 }
113123 }
114124
115- // Add patterns in the new order specified by the `patterns` array
125+ return ( patternToLineIndex, nonPatternLines)
126+ }
127+
128+ private func extractGlobalComments(
129+ _ nonPatternLines: [ ( line: String , index: Int ) ] ,
130+ _ patternToLineIndex: [ String : Int ]
131+ ) -> [ String ] {
132+ let globalComments = nonPatternLines. filter { $0. index < ( patternToLineIndex. values. min ( ) ?? Int . max) }
133+ return globalComments. map ( \. line)
134+ }
135+
136+ private func reorderPatterns(
137+ _ globalCommentLines: [ String ] ,
138+ _ patternToLineIndex: [ String : Int ] ,
139+ _ nonPatternLines: [ ( line: String , index: Int ) ] ,
140+ _ lines: [ String ]
141+ ) -> [ String ] {
142+ var reorderedLines : [ String ] = globalCommentLines
143+ var usedNonPatternLines = Set < Int > ( )
144+ var usedPatterns = Set < String > ( )
145+
116146 for pattern in patterns {
117147 let value = pattern. value
118- if let index = patternToLineIndex [ value] {
119- // Keep the original line if it matches a pattern
120- reorderedLines. append ( lines [ index] )
121- patternToLineIndex. removeValue ( forKey: value)
122- } else {
123- // Add new patterns that don't exist in the file
124- reorderedLines. append ( value)
148+
149+ // Insert the pattern
150+ reorderedLines. append ( value)
151+ usedPatterns. insert ( value)
152+
153+ // Preserve associated non-pattern lines
154+ if let currentIndex = patternToLineIndex [ value] {
155+ for nextIndex in ( currentIndex + 1 ) ..< lines. count {
156+ if let nonPatternLine = nonPatternLines. first ( where: { $0. index == nextIndex } ) ,
157+ !usedNonPatternLines. contains ( nonPatternLine. index) {
158+ reorderedLines. append ( nonPatternLine. line)
159+ usedNonPatternLines. insert ( nonPatternLine. index)
160+ } else {
161+ break
162+ }
163+ }
125164 }
126165 }
127166
128- // Add remaining non-pattern lines (comments, whitespace)
129- for (index , line ) in lines . enumerated ( ) {
130- let trimmedLine = line . trimmingCharacters ( in : . whitespaces )
131- if trimmedLine . isEmpty || trimmedLine . hasPrefix ( " # " ) {
132- reorderedLines . insert ( line , at : index)
167+ // Retain non-pattern lines that follow deleted patterns
168+ for (line , index ) in nonPatternLines {
169+ if !usedNonPatternLines . contains ( index ) && !reorderedLines . contains ( line ) {
170+ reorderedLines . append ( line )
171+ usedNonPatternLines . insert ( index)
133172 }
134173 }
135174
136- // Ensure single blank line at the end
137- reorderedLines = cleanUpWhitespace ( in: reorderedLines)
175+ // Add new patterns that were not in the original file
176+ for pattern in patterns where !usedPatterns. contains ( pattern. value) {
177+ reorderedLines. append ( pattern. value)
178+ }
138179
139- // Write the updated content back to the file
140- let updatedContent = reorderedLines. joined ( separator: " \n " )
141- try ? updatedContent. write ( to: fileURL, atomically: true , encoding: . utf8)
180+ return reorderedLines
142181 }
143182
144183 private func writeAllPatterns( ) {
0 commit comments