Skip to content

Commit 2df7e29

Browse files
committed
feat: improve setup script some
1 parent a1cdc32 commit 2df7e29

2 files changed

Lines changed: 88 additions & 28 deletions

File tree

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ ESP-IDF components.
88

99
- [ESP++ Template](#esp-template)
1010
- [Template](#template)
11-
- [Automated Setup (Windows Only)](#automated-setup-windows-only)
12-
- [Manual Setup (Windows / Linux / macOS)](#manual-setup-windows--linux--macos)
11+
- [Automated Setup](#automated-setup)
12+
- [Manual Setup](#manual-setup)
1313
- [Use within a Private Repository](#use-within-a-private-repository)
1414
- [Additional Dependencies](#additional-dependencies)
1515
- [Development](#development)
@@ -27,24 +27,24 @@ This repository is designed to be used as a template repository - so you can
2727
specify this as the template repository type when creating a new repository on
2828
GitHub.
2929

30-
### Automated Setup (Windows Only)
30+
### Automated Setup
3131

3232
After setting this as the template:
3333

34-
- Open a PowerShell terminal in the project root and run:
34+
- Open a terminal in the project root and run:
3535
- ```console
36-
python scripts/setup_project_windows.py
36+
python scripts/setup_project.py
3737
```
3838

39-
- The script will prompt you for the project name, target chip, GitHub workflow permissions, automatically update the corresponding files and setup pre-commit.
39+
- The script will prompt you for the project name, target chip, ESP-IDF version, GitHub workflow permissions, automatically update the corresponding files (including the logger tag in `main/main.cpp` and this README) and setup pre-commit.
4040

41-
- Close the terminal and open an **ESP-IDF Terminal** to build, flash and test.
41+
- Open an **ESP-IDF Terminal** to build, flash and test.
4242
- The serial monitor should print `Hello World!`
4343

4444
> **Note:** If you need non-default build outputs (e.g., littlefs images), update [./.github/workflows/package_main.yml](./.github/workflows/package_main.yml) manually.
4545

4646

47-
### Manual Setup (Windows / Linux / macOS)
47+
### Manual Setup
4848

4949
After setting this as the template, make sure to update the following:
5050
- [This README](./README.md) to contain the relevant description and images of
Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,46 @@ def ask(prompt, default=None):
3535
return value if value else default
3636

3737

38+
def _github_anchor(text):
39+
"""Approximate GitHub's heading-to-anchor slug (lowercase, spaces → hyphens)."""
40+
anchor = re.sub(r'[^\w\s-]', '', text.strip().lower())
41+
return re.sub(r'\s+', '-', anchor)
42+
43+
44+
def update_readme(app_name):
45+
"""Retitle the README and strip the template setup instructions. Returns a change description or None."""
46+
path = SCRIPT_DIR / 'README.md'
47+
if not path.exists():
48+
return None
49+
content = original = path.read_text(encoding='utf-8')
50+
51+
# Retitle the project (H1 heading + the matching table-of-contents entry)
52+
content = content.replace('# ESP++ Template\n', f'# {app_name}\n', 1)
53+
content = content.replace(
54+
'- [ESP++ Template](#esp-template)',
55+
f'- [{app_name}](#{_github_anchor(app_name)})',
56+
1,
57+
)
58+
59+
# Drop the Automated/Manual Setup entries from the table of contents
60+
content = re.sub(r'[ \t]*- \[Automated Setup\]\(#automated-setup\)\n', '', content)
61+
content = re.sub(r'[ \t]*- \[Manual Setup\]\(#manual-setup\)\n', '', content)
62+
63+
# Remove the Automated Setup and Manual Setup sections — they only apply
64+
# before the template has been instantiated.
65+
content = re.sub(
66+
r'### Automated Setup\n.*?(?=### Use within a Private Repository)',
67+
'',
68+
content,
69+
flags=re.DOTALL,
70+
)
71+
72+
if content == original:
73+
return None
74+
path.write_text(content, encoding='utf-8')
75+
return 'README.md retitled, template setup instructions removed'
76+
77+
3878
def find_idf_path():
3979
"""Return the ESP-IDF installation path, or None if undetectable."""
4080
# 1. IDF_PATH env var (set when IDF environment is activated)
@@ -324,6 +364,8 @@ def main():
324364
parser.add_argument('--name', help='Project name (lowercase, underscores)')
325365
parser.add_argument('--app-name', dest='app_name', help='Display name for CI')
326366
parser.add_argument('--target', choices=VALID_TARGETS, help='IDF target chip')
367+
parser.add_argument('--idf-version', dest='idf_version',
368+
help='ESP-IDF version to target, e.g. v5.5.1 (defaults to the detected install)')
327369
parser.add_argument('--flash-size', dest='flash_size', help='Flash size, bytes or shorthand (e.g. 8M)')
328370
parser.add_argument('--private', action='store_true', default=None,
329371
help='Private repo: updates static_analysis.yml trigger')
@@ -363,24 +405,31 @@ def main():
363405

364406
programmer_name = f'{name}_programmer'
365407

408+
def _yml_idf_version(p):
409+
if p.exists():
410+
m = re.search(r"IDF_VERSION: '(v[\d.]+)'", p.read_text(encoding='utf-8'))
411+
return m.group(1) if m else None
412+
return None
413+
366414
detected_idf = detect_idf_version()
367-
idf_already_current = False
368-
if detected_idf:
369-
def _yml_idf_version(p):
370-
if p.exists():
371-
m = re.search(r"IDF_VERSION: '(v[\d.]+)'", p.read_text(encoding='utf-8'))
372-
return m.group(1) if m else None
373-
return None
374-
build_ver = _yml_idf_version(SCRIPT_DIR / '.github/workflows/build.yml')
375-
pkg_ver = _yml_idf_version(SCRIPT_DIR / '.github/workflows/package_main.yml')
376-
if build_ver == detected_idf and pkg_ver == detected_idf:
377-
idf_version = None
378-
idf_already_current = True
379-
else:
380-
confirm = ask(f'Update IDF_VERSION on github workflow files to {detected_idf}? (y/n)', default='y')
381-
idf_version = detected_idf if confirm.lower().startswith('y') else None
415+
build_ver = _yml_idf_version(SCRIPT_DIR / '.github/workflows/build.yml')
416+
pkg_ver = _yml_idf_version(SCRIPT_DIR / '.github/workflows/package_main.yml')
417+
418+
# Ask which ESP-IDF version to target. Default to the detected install,
419+
# falling back to whatever the workflow files already specify.
420+
default_idf = detected_idf or (build_ver if build_ver == pkg_ver else None)
421+
if args.idf_version:
422+
chosen_idf = args.idf_version
382423
else:
383-
idf_version = None
424+
prompt = 'ESP-IDF version to use (e.g. v5.5.1)'
425+
if detected_idf:
426+
prompt += f' — detected {detected_idf}'
427+
chosen_idf = ask(prompt, default=default_idf)
428+
if chosen_idf and not chosen_idf.startswith('v'):
429+
chosen_idf = 'v' + chosen_idf
430+
431+
idf_already_current = bool(chosen_idf) and build_ver == chosen_idf and pkg_ver == chosen_idf
432+
idf_version = chosen_idf if (chosen_idf and not idf_already_current) else None
384433

385434
# GitHub — gather remote + permission intent before doing any long-running work
386435
remote = get_github_remote()
@@ -443,15 +492,22 @@ def _yml_idf_version(p):
443492
print()
444493
changes = []
445494

446-
if not detected_idf:
447-
print(f'{YELLOW}Could not detect IDF version — IDF_VERSION will not be changed.{RESET}')
495+
if not chosen_idf:
496+
print(f'{YELLOW}No ESP-IDF version specified — IDF_VERSION will not be changed.{RESET}')
448497

449498
path = SCRIPT_DIR / 'CMakeLists.txt'
450499
content = path.read_text(encoding='utf-8')
451500
if 'project(template)' in content:
452501
path.write_text(content.replace('project(template)', f'project({name})'), encoding='utf-8')
453502
changes.append(f'CMakeLists.txt project(template) → project({name})')
454503

504+
path = SCRIPT_DIR / 'main' / 'main.cpp'
505+
if path.exists():
506+
content = path.read_text(encoding='utf-8')
507+
if '.tag = "Template"' in content:
508+
path.write_text(content.replace('.tag = "Template"', f'.tag = "{app_name}"'), encoding='utf-8')
509+
changes.append(f'main/main.cpp logger tag "Template" → "{app_name}"')
510+
455511
path = SCRIPT_DIR / '.github/workflows/build.yml'
456512
content = path.read_text(encoding='utf-8')
457513
file_changes = []
@@ -534,6 +590,10 @@ def _yml_idf_version(p):
534590
path.write_text(new_content, encoding='utf-8')
535591
changes.append(f'sdkconfig.defaults CONFIG_IDF_TARGET="{target}" uncommented')
536592

593+
readme_change = update_readme(app_name)
594+
if readme_change:
595+
changes.append(readme_change)
596+
537597
def _force_remove(func, path, _):
538598
os.chmod(path, stat.S_IWRITE)
539599
func(path)
@@ -544,8 +604,8 @@ def _force_remove(func, path, _):
544604
for c in changes:
545605
print(f' {GREEN}{RESET} {c}')
546606
if idf_already_current:
547-
print(f' {GREEN}{RESET} build.yml IDF_VERSION already {detected_idf}')
548-
print(f' {GREEN}{RESET} package_main.yml IDF_VERSION already {detected_idf}')
607+
print(f' {GREEN}{RESET} build.yml IDF_VERSION already {chosen_idf}')
608+
print(f' {GREEN}{RESET} package_main.yml IDF_VERSION already {chosen_idf}')
549609
else:
550610
print(f'{YELLOW}Nothing to change — already renamed?{RESET}')
551611

0 commit comments

Comments
 (0)