diff --git a/buildroot/bin/__init__.py b/buildroot/bin/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/buildroot/bin/config.py b/buildroot/bin/config.py new file mode 100755 index 0000000000..b1a67ad965 --- /dev/null +++ b/buildroot/bin/config.py @@ -0,0 +1,96 @@ +''' +config.py - Helper functions for config manipulation +''' +import re + +FILES = ('Marlin/Configuration.h', 'Marlin/Configuration_adv.h') + +def set(file_path, define_name, value): + ''' + Replaces a define in a file with a new value. + Returns True if the define was found and replaced, False otherwise. + ''' + # Read the contents of the file + with open(file_path, 'r') as f: + content = f.readlines() + + modified = False + for i in range(len(content)): + # Regex to match the desired pattern + match = re.match(r'^(\s*)(/*)(\s*)(#define\s+{})\s+(.*)$'.format(re.escape(define_name)), content[i]) + if match: + new_line = f"{match[1]}{match[3]}{match[4]} {value} // {match[5]}\n" + content[i] = new_line + modified = True + + # Write the modified content back to the file only if changes were made + if modified: + with open(file_path, 'w') as f: + f.writelines(content) + return True + + return False + +def add(file_path, define_name, value=""): + ''' + Insert a define on the first blank line in a file. + Returns True if the define was found and replaced, False otherwise. + ''' + with open(file_path, 'r') as f: + content = f.readlines() + + # Prepend a space to the value if it's not empty + if value != "": + value = " " + value + + # Find the first blank line to insert the new define + for i in range(len(content)): + if content[i].strip() == '': + # Insert the define at the first blank line + content.insert(i, f"#define {define_name}{value}\n") + break + else: + # If no blank line is found, append to the end + content.append(f"#define {define_name}{value}\n") + + with open(file_path, 'w') as f: + f.writelines(content) + +def enable(file_path, define_name, enable=True): + ''' + Uncomment or comment the named defines in the given file path. + Returns True if the define was found, False otherwise. + ''' + # Read the contents of the file + with open(file_path, 'r') as f: + content = f.readlines() + + # Prepare the regex + regex = re.compile(r'^(\s*)(/*)(\s*)(#define\s+{}\b.*?)( *//.*)?$'.format(re.escape(define_name))) + + # Find the define in the file and uncomment or comment it + found = False + modified = False + for i in range(len(content)): + match = regex.match(content[i]) + if not match: continue + found = True + if enable: + if match[2]: + modified = True + comment = '' if match[5] is None else ' ' + match[5] + content[i] = f"{match[1]}{match[3]}{match[4]}{comment}\n" + else: + if not match[2]: + modified = True + comment = '' if match[5] is None else match[5] + if comment.startswith(' '): comment = comment[2:] + content[i] = f"{match[1]}//{match[3]}{match[4]}{comment}\n" + break + + # Write the modified content back to the file only if changes were made + if modified: + with open(file_path, 'w') as f: + f.writelines(content) + + return found diff --git a/buildroot/bin/opt_add b/buildroot/bin/opt_add index 2306ebdaa1..3abe309ab6 100755 --- a/buildroot/bin/opt_add +++ b/buildroot/bin/opt_add @@ -1,3 +1,11 @@ -#!/usr/bin/env bash +#!/usr/bin/env python -eval "echo '#define ${@}' | cat - Marlin/Configuration.h > temp && mv temp Marlin/Configuration.h" +import sys, config + +def main(): + args = sys.argv[1:] + for name in args: + config.add(config.FILES[0], name) + +if __name__ == "__main__": + main() diff --git a/buildroot/bin/opt_disable b/buildroot/bin/opt_disable index 8b36bc1f34..9331b2c924 100755 --- a/buildroot/bin/opt_disable +++ b/buildroot/bin/opt_disable @@ -1,36 +1,21 @@ -#!/usr/bin/env bash +#!/usr/bin/env python -# exit on first failure -set -e +import sys, os,config -# Get SED_CMD, SED_I, and the BSDSED flag -. $(dirname $0)/opt_sed +def main(): + args = sys.argv[1:] -for opt in "$@" ; do - DID=0 ; FOUND=0 - for FN in Marlin/Configuration.h Marlin/Configuration_adv.h; do - if [[ $BSDSED ]]; then - # BSD sed version (macOS) - "${SED_CMD}" "${SED_I[@]}" \ - "/^[[:space:]]*#define[[:space:]]+${opt}\b/{ - s/^[[:space:]]*\(#define[[:space:]]+${opt}\b.*\)/\/\/\1/ - h - \$b end - } - \$!b - :end - x - /./{ x; q0; } - x - q1" \ - $FN && DID=1 - else - # GNU sed version - "${SED_CMD}" "${SED_I[@]}" \ - "/^\(\s*\)\(#define\s\+${opt}\b\s\?\)\(\s\s\)\?/{s//\1\/\/\2/;h};\${x;/./{x;q0};x;q1}" \ - $FN && DID=1 - fi - ((DID||FOUND)) || { grep -E "^\s*\/\/#define\s+${opt}\b" $FN >/dev/null && FOUND=1 ; } - done - ((DID||FOUND)) || (echo "ERROR: $(basename $0) Can't find ${opt}" >&2 && exit 9) -done + for name in args: + changed = False + + for file in config.FILES: + if os.path.exists(file): + if config.enable(file, name, False): + changed = True + + if not changed: + print(f"ERROR: Can't find {name}") + exit(1) + +if __name__ == "__main__": + main() diff --git a/buildroot/bin/opt_enable b/buildroot/bin/opt_enable index 292b4952d7..fd5c3a1b4b 100755 --- a/buildroot/bin/opt_enable +++ b/buildroot/bin/opt_enable @@ -1,36 +1,21 @@ -#!/usr/bin/env bash +#!/usr/bin/env python -# exit on first failure -set -e +import sys, os,config -# Get SED_CMD, SED_I, and the BSDSED flag -. $(dirname $0)/opt_sed +def main(): + args = sys.argv[1:] -for opt in "$@" ; do - DID=0 ; FOUND=0 - for FN in Marlin/Configuration.h Marlin/Configuration_adv.h; do - if [[ $BSDSED ]]; then - # BSD sed version (macOS) - "${SED_CMD}" "${SED_I[@]}" \ - "/^[[:space:]]*\/\/[[:space:]]*#define[[:space:]]+${opt}\b/{ - s/^[[:space:]]*\/\/[[:space:]]*\(#define[[:space:]]+${opt}\b\)[[:space:]]*/\1 / - h - \$b end - } - \$!b - :end - x - /./{ x; q0; } - x - q1" \ - $FN && DID=1 - else - # GNU sed version - "${SED_CMD}" "${SED_I[@]}" \ - "/^\(\s*\)\/\/\(\s*\)\(#define\s\+${opt}\b\)\( \?\)/{s//\1\2\3\4\4\4/;h};\${x;/./{x;q0};x;q1}" \ - $FN && DID=1 - fi - ((DID||FOUND)) || { grep -E "^\s*#define\s+${opt}\b" $FN >/dev/null && FOUND=1 ; } - done - ((DID||FOUND)) || (echo "ERROR: $(basename $0) Can't find ${opt}" >&2 && exit 9) -done + for name in args: + changed = False + + for file in config.FILES: + if os.path.exists(file): + if config.enable(file, name): + changed = True + + if not changed: + print(f"ERROR: Can't find {name}") + exit(1) + +if __name__ == "__main__": + main() diff --git a/buildroot/bin/opt_sed b/buildroot/bin/opt_sed deleted file mode 100755 index d6075add01..0000000000 --- a/buildroot/bin/opt_sed +++ /dev/null @@ -1,9 +0,0 @@ -# Detect sed version -SED_CMD="sed" -SED_I=(-i) -if command -v gsed >/dev/null 2>&1; then - SED_CMD="gsed" -elif [[ "$(uname)" == "Darwin" ]]; then - SED_I=(-i '') - BSDSED=1 -fi diff --git a/buildroot/bin/opt_set b/buildroot/bin/opt_set index d58cfc3d14..cf8bbb9449 100755 --- a/buildroot/bin/opt_set +++ b/buildroot/bin/opt_set @@ -1,38 +1,25 @@ -#!/usr/bin/env bash +#!/usr/bin/env python -# exit on first failure -set -e +import sys, os, config -# Get SED_CMD, SED_I, and the BSDSED flag -. $(dirname $0)/opt_sed +def main(): + args = sys.argv[1:] + if len(args) % 2 != 0: + print("ERROR: Please provide pairs of ") + return -while [[ $# > 1 ]]; do - DID=0 - for FN in Marlin/Configuration.h Marlin/Configuration_adv.h; do - if [[ $BSDSED ]]; then - # BSD sed version (macOS) - $SED_CMD "${SED_I[@]}" \ - "/^[[:space:]]*\/\{0,2\}[[:space:]]*#define[[:space:]]+${1}\b/{ - s/^[[:space:]]*\/\{0,2\}[[:space:]]*\(#define[[:space:]]+${1}\b\)[[:space:]]*.*/\1 ${2} \/\/ &/ - h - \$b end - } - \$!b - :end - x - /./{ x; q0; } - x - q1" \ - $FN && DID=1 - else - # GNU sed version - $SED_CMD "${SED_I[@]}" \ - "/^\(\s*\)\/\{0,2\}\s*\(#define\s\+${1}\b\)\s*\(.*\)$/{s//\1\2 ${2} \/\/ \3/;h};\${x;/./{x;q0};x;q1}" \ - $FN && DID=1 - fi - done - ((DID)) || - eval "echo '#define ${1} ${2}' >>Marlin/Configuration.h" || - (echo "ERROR: opt_set Can't set or add ${1}" >&2 && exit 9) - shift 2 -done + for i in range(0, len(args), 2): + name = args[i] + value = args[i + 1] + changed = False + + for file in config.FILES: + if os.path.exists(file): + if config.set(file, name, value): + changed = True + + if not changed: + config.add(config.FILES[0], name, value) + +if __name__ == "__main__": + main()