From ee61854981b88de9c843ae6cb6d7e08f1be45869 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 23 Oct 2024 06:57:10 -0400 Subject: [PATCH 1/7] Re-write of Search and Replace Added some options: - Replace the 'First Instance Only' of the Search term. - Limit the Search to a layer range. - 'Ignore StartUp G-code' and 'Ignore Ending G-code' --- .../scripts/SearchAndReplace.py | 176 ++++++++++++++++-- 1 file changed, 157 insertions(+), 19 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py index dabc6b725a..264531de59 100644 --- a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -1,16 +1,16 @@ # Copyright (c) 2017 Ghostkeeper # The PostProcessingPlugin is released under the terms of the LGPLv3 or higher. +# Altered by GregValiant (Greg Foresi) February, 2023. +# Added an option to replace the 'First Instance Only' +# Added option to limit the Search to a layer range. +# Added 'Ignore StartUp G-code' and 'Ignore Ending G-code' options -import re # To perform the search and replace. - +import re from ..Script import Script - +from UM.Application import Application class SearchAndReplace(Script): - """Performs a search-and-replace on all g-code. - - Due to technical limitations, the search can't cross the border between - layers. + """Performs a search-and-replace on the g-code. """ def getSettingDataString(self): @@ -23,37 +23,175 @@ class SearchAndReplace(Script): { "search": { - "label": "Search", - "description": "All occurrences of this text will get replaced by the replacement text.", + "label": "Search for:", + "description": "All occurrences of this text (within the search range) will be replaced by the 'Replace with' text. The search string is CASE SPECIFIC so 'LAYER' is not the same as 'layer'.", "type": "str", "default_value": "" }, "replace": { - "label": "Replace", - "description": "The search text will get replaced by this text.", + "label": "Replace with:", + "description": "The 'Search For' text will get replaced by this text. For Multi-Line insertions use the newline character 'backslash plus n' as the delimiter. Also for multi-line insertions the last character must be 'backslash plus n'", "type": "str", "default_value": "" }, "is_regex": { "label": "Use Regular Expressions", - "description": "When enabled, the search text will be interpreted as a regular expression.", + "description": "When disabled the search string is treated as a simple text string. When enabled, the search text will be re-compiled as a 'regular' python expression.", "type": "bool", "default_value": false + }, + "enable_layer_search": + { + "label": "Enable search within a Layer Range:", + "description": "When enabled, You can choose a Start and End layer for the search. When 'Layer Search' is enabled the StartUp and Ending g-codes are always ignored.", + "type": "bool", + "default_value": false, + "enabled": true + }, + "search_start": + { + "label": "Start S&R at Layer:", + "description": "Use the Cura Preview layer numbering. The Start Layer will be included. Enter '1' to start with gcode ';LAYER:0'. Enter ''-6'' to start with the first layer of a raft.", + "type": "int", + "default_value": 1, + "minimum_value": -6, + "enabled": "enable_layer_search" + }, + "search_end": + { + "label": "Stop S&R at end of Layer:", + "description": "Use the Cura Preview layer numbering. Enter '-1' to search and replace to the end of the file. Enter any other layer number and the replacements will conclude at the end of that layer. If the End Layer is equal to the Start Layer then only that single layer is searched.", + "type": "int", + "default_value": -1, + "minimum_value": -1, + "enabled": "enable_layer_search" + }, + "first_instance_only": + { + "label": "Replace first instance only:", + "description": "When enabled only the first instance is replaced.", + "type": "bool", + "default_value": false, + "enabled": true + }, + "ignore_start": + { + "label": "Ignore StartUp G-code:", + "description": "When enabled the StartUp G-code is unaffected. The StartUp G-code is everything from ';generated with Cura...' to ';LAYER_COUNT:' inclusive.", + "type": "bool", + "default_value": true, + "enabled": "not enable_layer_search" + }, + "ignore_end": + { + "label": "Ignore Ending G-code:", + "description": "When enabled the Ending G-code is unaffected.", + "type": "bool", + "default_value": true, + "enabled": "not enable_layer_search" } } }""" def execute(self, data): + curaApp = Application.getInstance().getGlobalContainerStack() + extruder = curaApp.extruderList + retract_enabled = bool(extruder[0].getProperty("retraction_enable", "value")) + # If retractions are enabled then the CuraEngine inserts a single data item for the retraction at the end of the last layer + # 'top_layer' accounts for that + if retract_enabled: + top_layer = 2 + else: + top_layer = 1 search_string = self.getSettingValueByKey("search") - if not self.getSettingValueByKey("is_regex"): - search_string = re.escape(search_string) #Need to search for the actual string, not as a regex. - search_regex = re.compile(search_string) - replace_string = self.getSettingValueByKey("replace") + is_regex = self.getSettingValueByKey("is_regex") + enable_layer_search = self.getSettingValueByKey("enable_layer_search") + start_layer = self.getSettingValueByKey("search_start") + end_layer = self.getSettingValueByKey("search_end") + ignore_start = self.getSettingValueByKey("ignore_start") + ignore_end = self.getSettingValueByKey("ignore_end") + if enable_layer_search: + ignore_start = True + ignore_end = True + first_instance_only = bool(self.getSettingValueByKey("first_instance_only")) - for layer_number, layer in enumerate(data): - data[layer_number] = re.sub(search_regex, replace_string, layer) #Replace all. + #Find the raft and layer:0 indexes-------------------------------------------------------------------------- + raft_start_index = 0 + layer_0_index = 0 + start_index = 1 + end_index = len(data) + try: + for l_num in range(2,12,1): + layer = data[l_num] + if ";LAYER:-" in layer and raft_start_index == 0: + raft_start_index = l_num + if ";LAYER:0" in layer: + layer_0_index = l_num + break + if raft_start_index == 0: + raft_start_index = layer_0_index + raft_layers = 0 + elif raft_start_index < layer_0_index: + raft_layers = layer_0_index - raft_start_index + else: + raft_layers = 0 + except: + pass + #Determine the actual start and end indexes of the data---------------------------------------------------- + try: + if not enable_layer_search: + if ignore_start: + start_index = 2 + else: + start_index = 1 + if ignore_end: + end_index = len(data) - top_layer + else: + end_index = len(data) + elif enable_layer_search: + if start_layer < 1 and start_layer != -6: + start_index = layer_0_index - raft_layers + elif start_layer == -6: + start_index = 2 + else: + start_index = raft_start_index + start_layer - 1 + if end_layer == -1: + end_index = len(data) - top_layer + else: + end_index = raft_start_index + int(end_layer) + if end_index > len(data) - 1: end_index = len(data) - 1 #For possible user input error + if int(end_index) < int(start_index): end_index = start_index #For possible user input error + except: + start_index = 2 + end_index = len(data) - top_layer - return data \ No newline at end of file + # If "first_instance_only" is enabled: + replaceone = False + if first_instance_only: + if not is_regex: + search_string = re.escape(search_string) + search_regex = re.compile(search_string) + for num in range(start_index, end_index, 1): + layer = data[num] + if re.search(search_regex, layer) and replaceone == False: + data[num] = re.sub(search_regex, replace_string, data[num], 1) + replaceone = True + break + if replaceone: break + return data + + # For all the replacements + if not is_regex: + search_string = re.escape(search_string) + search_regex = re.compile(search_string) + if end_index > start_index: + for index in range(start_index, end_index, 1): + layer = data[index] + data[index] = re.sub(search_regex, replace_string, layer) + elif end_index == start_index: + layer = data[start_index] + data[start_index] = re.sub(search_regex, replace_string, layer) + return data From 349c5284a9e79a082e48ac7f5e22bead4b10aaa4 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:14:47 -0500 Subject: [PATCH 2/7] Update SearchAndReplace.py Update a description Update SearchAndReplace.py Fixed the "descriptions". Cura didn't like the dashes or backslashes. --- .../scripts/SearchAndReplace.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py index 264531de59..f3261633d0 100644 --- a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -1,8 +1,7 @@ # Copyright (c) 2017 Ghostkeeper # The PostProcessingPlugin is released under the terms of the LGPLv3 or higher. # Altered by GregValiant (Greg Foresi) February, 2023. -# Added an option to replace the 'First Instance Only' -# Added option to limit the Search to a layer range. +# Added option for a layer search with a Start Layer and an End layer. # Added 'Ignore StartUp G-code' and 'Ignore Ending G-code' options import re @@ -31,21 +30,21 @@ class SearchAndReplace(Script): "replace": { "label": "Replace with:", - "description": "The 'Search For' text will get replaced by this text. For Multi-Line insertions use the newline character 'backslash plus n' as the delimiter. Also for multi-line insertions the last character must be 'backslash plus n'", + "description": "The 'Search For' text will get replaced by this text. For MultiLine insertions use the newline character 'backslash plus n' as the delimiter. If your Search term ends with a 'newline' remember to add 'newline' to the end of this Replace term.", "type": "str", "default_value": "" }, "is_regex": { "label": "Use Regular Expressions", - "description": "When disabled the search string is treated as a simple text string. When enabled, the search text will be re-compiled as a 'regular' python expression.", + "description": "When disabled the search string is treated as a simple text string. When enabled, the search text will be recompiled as a 'regular' python expression.", "type": "bool", "default_value": false }, "enable_layer_search": { "label": "Enable search within a Layer Range:", - "description": "When enabled, You can choose a Start and End layer for the search. When 'Layer Search' is enabled the StartUp and Ending g-codes are always ignored.", + "description": "When enabled, You can choose a Start and End layer for the search. When 'Layer Search' is enabled the StartUp and Ending gcodes are always ignored.", "type": "bool", "default_value": false, "enabled": true @@ -79,7 +78,7 @@ class SearchAndReplace(Script): "ignore_start": { "label": "Ignore StartUp G-code:", - "description": "When enabled the StartUp G-code is unaffected. The StartUp G-code is everything from ';generated with Cura...' to ';LAYER_COUNT:' inclusive.", + "description": "When enabled the StartUp Gcode is unaffected. The StartUp Gcode is everything from ';generated with Cura...' to ';LAYER_COUNT:' inclusive.", "type": "bool", "default_value": true, "enabled": "not enable_layer_search" @@ -87,7 +86,7 @@ class SearchAndReplace(Script): "ignore_end": { "label": "Ignore Ending G-code:", - "description": "When enabled the Ending G-code is unaffected.", + "description": "When enabled the Ending Gcode is unaffected.", "type": "bool", "default_value": true, "enabled": "not enable_layer_search" From be509b66962ecc69374a766011007bec277754d0 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:20:21 -0500 Subject: [PATCH 3/7] Update SearchAndReplace.py Update SearchAndReplace.py Changed comments. Revised code below line 170. Changed 'curaApp' to 'cura_app' --- .../scripts/SearchAndReplace.py | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py index f3261633d0..5f440a67e9 100644 --- a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -1,6 +1,7 @@ # Copyright (c) 2017 Ghostkeeper # The PostProcessingPlugin is released under the terms of the LGPLv3 or higher. # Altered by GregValiant (Greg Foresi) February, 2023. +# Added option for "first instance only" # Added option for a layer search with a Start Layer and an End layer. # Added 'Ignore StartUp G-code' and 'Ignore Ending G-code' options @@ -23,7 +24,7 @@ class SearchAndReplace(Script): "search": { "label": "Search for:", - "description": "All occurrences of this text (within the search range) will be replaced by the 'Replace with' text. The search string is CASE SPECIFIC so 'LAYER' is not the same as 'layer'.", + "description": "CASE SPECIFIC. 'LAYER' is not the same as 'Layer'. All occurrences of this text (within the search range) will be replaced by the 'Replace with' string.", "type": "str", "default_value": "" }, @@ -95,8 +96,8 @@ class SearchAndReplace(Script): }""" def execute(self, data): - curaApp = Application.getInstance().getGlobalContainerStack() - extruder = curaApp.extruderList + cura_app = Application.getInstance().getGlobalContainerStack() + extruder = cura_app.extruderList retract_enabled = bool(extruder[0].getProperty("retraction_enable", "value")) # If retractions are enabled then the CuraEngine inserts a single data item for the retraction at the end of the last layer # 'top_layer' accounts for that @@ -117,7 +118,7 @@ class SearchAndReplace(Script): ignore_end = True first_instance_only = bool(self.getSettingValueByKey("first_instance_only")) - #Find the raft and layer:0 indexes-------------------------------------------------------------------------- + #Find the raft and layer:0 indexes raft_start_index = 0 layer_0_index = 0 start_index = 1 @@ -139,7 +140,7 @@ class SearchAndReplace(Script): raft_layers = 0 except: pass - #Determine the actual start and end indexes of the data---------------------------------------------------- + #Determine the actual start and end indexes of the data try: if not enable_layer_search: if ignore_start: @@ -167,30 +168,24 @@ class SearchAndReplace(Script): start_index = 2 end_index = len(data) - top_layer - # If "first_instance_only" is enabled: + # Make replacements replaceone = False - if first_instance_only: - if not is_regex: - search_string = re.escape(search_string) - search_regex = re.compile(search_string) - for num in range(start_index, end_index, 1): - layer = data[num] + if not is_regex: + search_string = re.escape(search_string) + search_regex = re.compile(search_string) + for num in range(start_index, end_index, 1): + layer = data[num] + # First_instance only + if first_instance_only: if re.search(search_regex, layer) and replaceone == False: data[num] = re.sub(search_regex, replace_string, data[num], 1) replaceone = True break - if replaceone: break - return data - - # For all the replacements - if not is_regex: - search_string = re.escape(search_string) - search_regex = re.compile(search_string) - if end_index > start_index: - for index in range(start_index, end_index, 1): - layer = data[index] - data[index] = re.sub(search_regex, replace_string, layer) - elif end_index == start_index: - layer = data[start_index] - data[start_index] = re.sub(search_regex, replace_string, layer) - return data + # All + else: + if end_index > start_index: + data[num] = re.sub(search_regex, replace_string, layer) + elif end_index == start_index: + layer = data[start_index] + data[start_index] = re.sub(search_regex, replace_string, layer) + return data \ No newline at end of file From 5678c64f1899375e2d9409dc01778404f586bcb9 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Sun, 12 Jan 2025 10:04:39 -0500 Subject: [PATCH 4/7] Update SearchAndReplace.py Change variable name from cura_app to global_stack. --- plugins/PostProcessingPlugin/scripts/SearchAndReplace.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py index 5f440a67e9..4d81b9f98d 100644 --- a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -96,8 +96,8 @@ class SearchAndReplace(Script): }""" def execute(self, data): - cura_app = Application.getInstance().getGlobalContainerStack() - extruder = cura_app.extruderList + global_stack = Application.getInstance().getGlobalContainerStack() + extruder = global_stack.extruderList retract_enabled = bool(extruder[0].getProperty("retraction_enable", "value")) # If retractions are enabled then the CuraEngine inserts a single data item for the retraction at the end of the last layer # 'top_layer' accounts for that @@ -140,6 +140,7 @@ class SearchAndReplace(Script): raft_layers = 0 except: pass + #Determine the actual start and end indexes of the data try: if not enable_layer_search: From 36141b082c4b516850ada98ed9bec67ab43c2a15 Mon Sep 17 00:00:00 2001 From: GregValiant <64202104+GregValiant@users.noreply.github.com> Date: Fri, 7 Feb 2025 18:40:19 -0500 Subject: [PATCH 5/7] Update SearchAndReplace.py Replaced the complex method of dealing with rafts to something simpler. Update SearchAndReplace.py Update --- .../scripts/SearchAndReplace.py | 107 +++++++----------- 1 file changed, 41 insertions(+), 66 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py index 4d81b9f98d..0ad90b4de2 100644 --- a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -24,14 +24,14 @@ class SearchAndReplace(Script): "search": { "label": "Search for:", - "description": "CASE SPECIFIC. 'LAYER' is not the same as 'Layer'. All occurrences of this text (within the search range) will be replaced by the 'Replace with' string.", + "description": "All occurrences of this text (within the search range) will be replaced by the 'Replace with' string. The search string is 'Case Specific' and 'Layer' is not the same as 'layer'.", "type": "str", "default_value": "" }, "replace": { "label": "Replace with:", - "description": "The 'Search For' text will get replaced by this text. For MultiLine insertions use the newline character 'backslash plus n' as the delimiter. If your Search term ends with a 'newline' remember to add 'newline' to the end of this Replace term.", + "description": "The 'Search For' text will get replaced by this text. For MultiLine insertions use the newline character 'backslash n' as the delimiter. If your Search term ends with a 'newline' remember to add 'newline' to the end of this Replace term.", "type": "str", "default_value": "" }, @@ -53,19 +53,19 @@ class SearchAndReplace(Script): "search_start": { "label": "Start S&R at Layer:", - "description": "Use the Cura Preview layer numbering. The Start Layer will be included. Enter '1' to start with gcode ';LAYER:0'. Enter ''-6'' to start with the first layer of a raft.", + "description": "Use the Cura Preview layer numbering.", "type": "int", "default_value": 1, - "minimum_value": -6, + "minimum_value": 1, "enabled": "enable_layer_search" }, "search_end": { "label": "Stop S&R at end of Layer:", - "description": "Use the Cura Preview layer numbering. Enter '-1' to search and replace to the end of the file. Enter any other layer number and the replacements will conclude at the end of that layer. If the End Layer is equal to the Start Layer then only that single layer is searched.", + "description": "Use the Cura Preview layer numbering. The replacements will conclude at the end of this layer. If the End Layer is equal to the Start Layer then only that single layer is searched.", "type": "int", - "default_value": -1, - "minimum_value": -1, + "default_value": 2, + "minimum_value": 1, "enabled": "enable_layer_search" }, "first_instance_only": @@ -99,12 +99,6 @@ class SearchAndReplace(Script): global_stack = Application.getInstance().getGlobalContainerStack() extruder = global_stack.extruderList retract_enabled = bool(extruder[0].getProperty("retraction_enable", "value")) - # If retractions are enabled then the CuraEngine inserts a single data item for the retraction at the end of the last layer - # 'top_layer' accounts for that - if retract_enabled: - top_layer = 2 - else: - top_layer = 1 search_string = self.getSettingValueByKey("search") replace_string = self.getSettingValueByKey("replace") is_regex = self.getSettingValueByKey("is_regex") @@ -118,71 +112,52 @@ class SearchAndReplace(Script): ignore_end = True first_instance_only = bool(self.getSettingValueByKey("first_instance_only")) - #Find the raft and layer:0 indexes - raft_start_index = 0 - layer_0_index = 0 + # Account for missing layer numbers when a raft is used start_index = 1 - end_index = len(data) - try: - for l_num in range(2,12,1): - layer = data[l_num] - if ";LAYER:-" in layer and raft_start_index == 0: - raft_start_index = l_num - if ";LAYER:0" in layer: - layer_0_index = l_num - break - if raft_start_index == 0: - raft_start_index = layer_0_index - raft_layers = 0 - elif raft_start_index < layer_0_index: - raft_layers = layer_0_index - raft_start_index + end_index = len(data) - 1 + data_list = [0,1] + layer_list = [-1,0] + lay_num = 1 + for index, layer in enumerate(data): + if re.search(";LAYER:(-?\d+)", layer): + data_list.append(index) + layer_list.append(lay_num) + lay_num += 1 + + # Get the start and end indexes within the data + if not enable_layer_search: + if ignore_start: + start_index = 2 else: - raft_layers = 0 - except: - pass - - #Determine the actual start and end indexes of the data - try: - if not enable_layer_search: - if ignore_start: - start_index = 2 - else: - start_index = 1 - if ignore_end: - end_index = len(data) - top_layer - else: - end_index = len(data) - elif enable_layer_search: - if start_layer < 1 and start_layer != -6: - start_index = layer_0_index - raft_layers - elif start_layer == -6: - start_index = 2 - else: - start_index = raft_start_index + start_layer - 1 - if end_layer == -1: - end_index = len(data) - top_layer - else: - end_index = raft_start_index + int(end_layer) - if end_index > len(data) - 1: end_index = len(data) - 1 #For possible user input error - if int(end_index) < int(start_index): end_index = start_index #For possible user input error - except: - start_index = 2 - end_index = len(data) - top_layer + start_index = 1 + + if ignore_end: + end_index = data_list[len(data_list) - 1] + else: + # Account for the extra data item when retraction is enabled + end_index = data_list[len(data_list) - 1] + (2 if retract_enabled else 1) + + elif enable_layer_search: + for index, num in enumerate(layer_list): + if num == start_layer: + start_index = data_list[index] + if num == end_layer: + end_index = data_list[index] # Make replacements - replaceone = False + replace_one = False if not is_regex: search_string = re.escape(search_string) search_regex = re.compile(search_string) - for num in range(start_index, end_index, 1): + for num in range(start_index, end_index + 1, 1): layer = data[num] # First_instance only if first_instance_only: - if re.search(search_regex, layer) and replaceone == False: + if re.search(search_regex, layer) and replace_one == False: data[num] = re.sub(search_regex, replace_string, data[num], 1) - replaceone = True + replace_one = True break - # All + # All instances else: if end_index > start_index: data[num] = re.sub(search_regex, replace_string, layer) From e1bd4baed226af595306fb413d8d791444a08060 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 10 Feb 2025 10:36:44 +0100 Subject: [PATCH 6/7] Adjust settings descriptions --- .../PostProcessingPlugin/scripts/SearchAndReplace.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py index 0ad90b4de2..aeda053b56 100644 --- a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -14,7 +14,7 @@ class SearchAndReplace(Script): """ def getSettingDataString(self): - return """{ + return r"""{ "name": "Search and Replace", "key": "SearchAndReplace", "metadata": {}, @@ -24,21 +24,21 @@ class SearchAndReplace(Script): "search": { "label": "Search for:", - "description": "All occurrences of this text (within the search range) will be replaced by the 'Replace with' string. The search string is 'Case Specific' and 'Layer' is not the same as 'layer'.", + "description": "All occurrences of this text (within the search range) will be replaced by the 'Replace with' string. The search string is 'Case Sensitive' and 'Layer' is not the same as 'layer'.", "type": "str", "default_value": "" }, "replace": { "label": "Replace with:", - "description": "The 'Search For' text will get replaced by this text. For MultiLine insertions use the newline character 'backslash n' as the delimiter. If your Search term ends with a 'newline' remember to add 'newline' to the end of this Replace term.", + "description": "The 'Search For' text will get replaced by this text. For MultiLine insertions use the newline character '\\n' as the delimiter. If your Search term ends with a '\\n' remember to add '\\n' to the end of this Replace term.", "type": "str", "default_value": "" }, "is_regex": { "label": "Use Regular Expressions", - "description": "When disabled the search string is treated as a simple text string. When enabled, the search text will be recompiled as a 'regular' python expression.", + "description": "When disabled the search string is treated as a simple text string. When enabled, the search text will be interpreted as a Python regular expression.", "type": "bool", "default_value": false }, @@ -119,7 +119,7 @@ class SearchAndReplace(Script): layer_list = [-1,0] lay_num = 1 for index, layer in enumerate(data): - if re.search(";LAYER:(-?\d+)", layer): + if re.search(r";LAYER:(-?\d+)", layer): data_list.append(index) layer_list.append(lay_num) lay_num += 1 From 80fa6aabc343e928f9a8eb1f865fa83b967aebfb Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 10 Feb 2025 13:38:15 +0100 Subject: [PATCH 7/7] Update altered year --- plugins/PostProcessingPlugin/scripts/SearchAndReplace.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py index aeda053b56..db062f4084 100644 --- a/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py +++ b/plugins/PostProcessingPlugin/scripts/SearchAndReplace.py @@ -1,6 +1,6 @@ # Copyright (c) 2017 Ghostkeeper # The PostProcessingPlugin is released under the terms of the LGPLv3 or higher. -# Altered by GregValiant (Greg Foresi) February, 2023. +# Altered by GregValiant (Greg Foresi) February, 2025. # Added option for "first instance only" # Added option for a layer search with a Start Layer and an End layer. # Added 'Ignore StartUp G-code' and 'Ignore Ending G-code' options @@ -164,4 +164,4 @@ class SearchAndReplace(Script): elif end_index == start_index: layer = data[start_index] data[start_index] = re.sub(search_regex, replace_string, layer) - return data \ No newline at end of file + return data