Skill Tracer
Skills › Scientific Agent Skills › venue-templates › customize_template.py

customize_template.py

212 lines · skills/venue-templates/scripts/customize_template.py at 5f2bc03

1#!/usr/bin/env python3
2"""
3Customize Template Script
4Customize LaTeX templates with author information and project details.
5
6Usage:
7 python customize_template.py --template nature_article.tex --output my_paper.tex
8 python customize_template.py --template nature_article.tex --title "My Research" --output my_paper.tex
9 python customize_template.py --interactive
10"""
12import argparse
13import re
14from pathlib import Path
16def get_skill_path():
17 """Get the path to the venue-templates skill directory."""
18 script_dir = Path(__file__).parent
19 skill_dir = script_dir.parent
20 return skill_dir
22def find_template(template_name):
23 """Find template file in assets directory."""
24 if Path(template_name).name != template_name or not template_name.endswith('.tex'):
25 return None
26 skill_path = get_skill_path()
27 assets_path = skill_path / "assets"
29 # Search in all subdirectories
30 for subdir in ["journals", "posters", "grants"]:
31 template_path = assets_path / subdir / template_name
32 if template_path.is_file():
33 return template_path
35 return None
37def customize_template(template_path, output_path, **kwargs):
38 """Customize a template with provided information."""
40 # Read template
41 with open(template_path, 'r', encoding='utf-8') as f:
42 content = f.read()
44 # Replace placeholders
45 replacements = {
46 'title': (
47 [r'Insert Your Title Here[^}]*', r'Your [^}]*Title[^}]*Here[^}]*',
48 r'Your Paper Title: Concise and Descriptive \\\\ \(Maximum Two Lines\)'],
49 kwargs.get('title', '')
50 ),
51 'authors': (
52 [re.escape(r'First Author\textsuperscript{1}, Second Author\textsuperscript{1,2}, Third Author\textsuperscript{2,*}'),
53 re.escape(r'First Author\inst{1}, Second Author\inst{1,2}, Third Author\inst{2}')],
54 kwargs.get('authors', '')
55 ),
56 'affiliations': (
57 [r'Department Name, Institution Name, City, State[^\\}\n]*',
58 r'Department of [^,}\n]*, University Name[^\\}\n]*'],
59 kwargs.get('affiliations', '')
60 ),
61 'email': (
62 [r'first\.author@university\.edu',
63 r'\[email protected\]'],
64 kwargs.get('email', '')
65 )
66 }
68 # Apply replacements
69 modified = False
70 for key, (patterns, replacement) in replacements.items():
71 if replacement:
72 for pattern in patterns:
73 if re.search(pattern, content):
74 # A function replacement preserves literal LaTeX backslashes;
75 # a replacement string would interpret \1, \t, or \n.
76 content = re.sub(pattern, lambda _match: replacement, content, count=1)
77 modified = True
78 print(f"[OK] Replaced {key}")
79 break
81 # Write output
82 with open(output_path, 'w', encoding='utf-8') as f:
83 f.write(content)
85 if modified:
86 print(f"\n[OK] Customized template saved to: {output_path}")
87 else:
88 print(f"\n[WARN] Template copied to: {output_path}")
89 print(" No customizations applied (no matching placeholders found or no values provided)")
91 print(f"\nNext steps:")
92 print(f"1. Open {output_path} in your LaTeX editor")
93 print(f"2. Replace remaining placeholders")
94 print(f"3. Add your content")
95 print(f"4. Compile with pdflatex or your preferred LaTeX compiler")
97def interactive_mode():
98 """Run in interactive mode."""
99 print("\n=== Template Customization (Interactive Mode) ===\n")
101 # List available templates
102 skill_path = get_skill_path()
103 assets_path = skill_path / "assets"
105 print("Available templates:\n")
106 templates = []
107 for i, subdir in enumerate(["journals", "posters", "grants"], 1):
108 subdir_path = assets_path / subdir
109 if subdir_path.exists():
110 print(f"{subdir.upper()}:")
111 for j, template_file in enumerate(sorted(subdir_path.glob("*.tex")), 1):
112 templates.append(template_file)
113 print(f" {len(templates)}. {template_file.name}")
115 print()
117 # Select template
118 while True:
119 try:
120 choice = int(input(f"Select template (1-{len(templates)}): "))
121 if 1 <= choice <= len(templates):
122 template_path = templates[choice - 1]
123 break
124 else:
125 print(f"Please enter a number between 1 and {len(templates)}")
126 except ValueError:
127 print("Please enter a valid number")
129 print(f"\nSelected: {template_path.name}\n")
131 # Get customization info
132 title = input("Paper title (press Enter to skip): ").strip()
133 authors = input("Authors (e.g., 'John Doe, Jane Smith') (press Enter to skip): ").strip()
134 affiliations = input("Affiliations (press Enter to skip): ").strip()
135 email = input("Corresponding email (press Enter to skip): ").strip()
137 # Output file
138 default_output = f"my_{template_path.stem}.tex"
139 output = input(f"Output filename [{default_output}]: ").strip()
140 if not output:
141 output = default_output
143 output_path = Path(output)
145 # Customize
146 print()
147 customize_template(
148 template_path,
149 output_path,
150 title=title,
151 authors=authors,
152 affiliations=affiliations,
153 email=email
154 )
156def main():
157 parser = argparse.ArgumentParser(
158 description="Customize LaTeX templates with author and project information",
159 formatter_class=argparse.RawDescriptionHelpFormatter,
160 epilog="""
161Examples:
162 %(prog)s --interactive
163 %(prog)s --template nature_article.tex --output my_paper.tex
164 %(prog)s --template neurips_article.tex --title "My ML Research" --output my_neurips.tex
165 """
166 )
168 parser.add_argument('--template', type=str, help='Template filename')
169 parser.add_argument('--output', type=str, help='Output filename')
170 parser.add_argument('--title', type=str, help='Paper title')
171 parser.add_argument('--authors', type=str, help='Author names')
172 parser.add_argument('--affiliations', type=str, help='Institutions/affiliations')
173 parser.add_argument('--email', type=str, help='Corresponding author email')
174 parser.add_argument('--interactive', action='store_true', help='Run in interactive mode')
176 args = parser.parse_args()
178 # Interactive mode
179 if args.interactive:
180 interactive_mode()
181 return 0
183 # Command-line mode
184 if not args.template or not args.output:
185 print("Error: --template and --output are required (or use --interactive)")
186 parser.print_help()
187 return 2
189 # Find template
190 template_path = find_template(args.template)
191 if not template_path:
192 print(f"Error: Template '{args.template}' not found")
193 print("\nSearched in:")
194 skill_path = get_skill_path()
195 for subdir in ["journals", "posters", "grants"]:
196 print(f" - {skill_path}/assets/{subdir}/")
197 return 2
199 # Customize
200 output_path = Path(args.output)
201 customize_template(
202 template_path,
203 output_path,
204 title=args.title,
205 authors=args.authors,
206 affiliations=args.affiliations,
207 email=args.email
208 )
209 return 0
211if __name__ == "__main__":
212 raise SystemExit(main())