#!/usr/bin/env python3 """ Make all form fields in LaTeX documents readonly by adding readonly=true attribute. This script carefully parses LaTeX commands to avoid breaking the syntax. """ import re import sys from pathlib import Path def add_readonly_to_textfield(content): """Add readonly=true to CustomTextFieldDefault commands.""" # Pattern to match CustomTextFieldDefault{...}{...}{...}{params} pattern = r'(\\CustomTextFieldDefault\{[^}]*\}\{[^}]*\}\{[^}]*\}\{)([^}]*)\}' def replacer(match): prefix = match.group(1) params = match.group(2) # Check if readonly is already present if 'readonly=' in params: return match.group(0) # Add readonly=true to the parameters if params.strip(): new_params = params + ',readonly=true' else: new_params = 'readonly=true' return prefix + new_params + '}' return re.sub(pattern, replacer, content) def add_readonly_to_choicemenu(content): """Add readonly=true to CustomChoiceMenuDefault commands.""" # Pattern to match CustomChoiceMenuDefault{...}{...}{params}{...} pattern = r'(\\CustomChoiceMenuDefault\{[^}]*\}\{[^}]*\}\{)([^}]*)\}(\{[^}]*\})' def replacer(match): prefix = match.group(1) params = match.group(2) suffix = match.group(3) # Check if readonly is already present if 'readonly=' in params: return match.group(0) # Add readonly=true to the parameters if params.strip(): new_params = params + ',readonly=true' else: new_params = 'readonly=true' return prefix + new_params + '}' + suffix return re.sub(pattern, replacer, content) def add_readonly_to_checkbox(content): """Add readonly=true to CheckBox commands.""" # Pattern to match CheckBox[params] pattern = r'(\\CheckBox\[)([^\]]*)\]' def replacer(match): prefix = match.group(1) params = match.group(2) # Check if readonly is already present if 'readonly=' in params: return match.group(0) # Add readonly=true to the parameters params_lines = params.split('\n') # Find a good place to insert readonly=true (after first parameter) for i, line in enumerate(params_lines): if line.strip() and not line.strip().startswith('%'): # Insert after this line params_lines.insert(i + 1, '\t\t\t\treadonly=true,') break new_params = '\n'.join(params_lines) return prefix + new_params + ']' return re.sub(pattern, replacer, content, flags=re.MULTILINE | re.DOTALL) def add_readonly_to_textfield_multiline(content): """Add readonly=true to TextField commands (multiline text fields).""" # Pattern to match TextField[params] for multiline fields pattern = r'(\\TextField\[)([^\]]*name=pa-project-description[^\]]*)\]' def replacer(match): prefix = match.group(1) params = match.group(2) # Check if readonly is already present if 'readonly=' in params: return match.group(0) # Add readonly=true to the parameters params_lines = params.split('\n') # Find a good place to insert readonly=true (after multiline parameter) for i, line in enumerate(params_lines): if 'multiline' in line: # Insert after this line params_lines.insert(i + 1, '\t\t\t\treadonly=true,') break new_params = '\n'.join(params_lines) return prefix + new_params + ']' return re.sub(pattern, replacer, content, flags=re.MULTILINE | re.DOTALL) def process_file(filepath): """Process a single LaTeX file to make all fields readonly.""" print(f"Processing {filepath}...") with open(filepath, 'r', encoding='utf-8') as f: content = f.read() # Apply transformations content = add_readonly_to_textfield(content) content = add_readonly_to_choicemenu(content) content = add_readonly_to_checkbox(content) content = add_readonly_to_textfield_multiline(content) # Write back with open(filepath, 'w', encoding='utf-8') as f: f.write(content) print(f"✓ Processed {filepath}") def main(): """Main function to process QSM and VSM LaTeX files.""" base_dir = Path(__file__).parent.parent files_to_process = [ base_dir / "latex-qsm" / "Content" / "01_content.tex", base_dir / "latex-vsm" / "Content" / "01_content.tex", ] for filepath in files_to_process: if filepath.exists(): process_file(filepath) else: print(f"✗ File not found: {filepath}") if __name__ == "__main__": main()