feat: add non-interactive template replacer#9
Conversation
Summary of ChangesHello @sammyjoyce, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a fundamental shift in how project templates are handled, moving from an interactive setup process to a fully automated, non-interactive replacement mechanism. The core purpose is to streamline the instantiation of new projects from a template by programmatically injecting project-specific values and applying necessary string transformations, thereby enhancing efficiency and reducing manual intervention during project setup. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a non-interactive template replacer script, replacer.sh, which is a significant enhancement over the previous interactive setup. The script is well-structured, leveraging command-line arguments, external tools like jq and sd, and a JSON configuration file for variables. The accompanying changes to template-vars.json clean up the variable definitions and expand the replacement capabilities. My review focuses on improving the robustness and maintainability of the new shell script, with suggestions to fix a bug in the dry-run functionality, refine string transformations, and make file exclusion more configurable.
.template/replacer.sh
Outdated
|
|
||
| if (( dry_run )); then | ||
| (( verbose )) && printf '[dry-run] %s: "%s" -> "%s"\n' "$file" "$pattern" "$replacement" | ||
| sd --preview -F "$pattern" "$replacement" "$file" >/dev/null |
There was a problem hiding this comment.
The --dry-run feature is intended to show a preview of changes without writing them. The sd --preview command generates this preview, but its output is being redirected to /dev/null, which prevents the user from seeing it. This redirection defeats the purpose of the preview. Removing it will ensure the dry run feature works as expected.
| sd --preview -F "$pattern" "$replacement" "$file" >/dev/null | |
| sd --preview -F "$pattern" "$replacement" "$file" |
.template/replacer.sh
Outdated
| text=$(printf '%s' "$text" | sed -E 's/([a-z0-9])([A-Z])/\1 \2/g') | ||
| text=$(printf '%s' "$text" | tr '[:upper:]' '[:lower:]') | ||
| text=$(printf '%s' "$text" | tr -cs '[:alnum:]' ' ') | ||
| printf '%s' "$text" | xargs || true |
There was a problem hiding this comment.
The || true appended to the xargs command is redundant. xargs exits with a status of 0 when it receives no input from stdin, so there's no error to suppress. Removing this will make the code slightly cleaner and rely on standard xargs behavior.
| printf '%s' "$text" | xargs || true | |
| printf '%s' "$text" | xargs |
.template/replacer.sh
Outdated
|
|
||
| to_snake() { | ||
| local words="$(to_words "$1")" | ||
| [[ -z $words ]] && { printf '\n'; return; } |
There was a problem hiding this comment.
When to_words returns an empty string, this line causes the function to output a newline character (\n). This can lead to unintended newlines being inserted during template replacement. The function should return an empty string for an empty input.
| [[ -z $words ]] && { printf '\n'; return; } | |
| [[ -z $words ]] && return |
.template/replacer.sh
Outdated
|
|
||
| to_kebab() { | ||
| local words="$(to_words "$1")" | ||
| [[ -z $words ]] && { printf '\n'; return; } |
There was a problem hiding this comment.
When to_words returns an empty string, this line causes the function to output a newline character (\n). This can lead to unintended newlines being inserted during template replacement. The function should return an empty string for an empty input.
| [[ -z $words ]] && { printf '\n'; return; } | |
| [[ -z $words ]] && return |
.template/replacer.sh
Outdated
| error "'$1' is not installed. Please install it to continue." | ||
| to_pascal() { | ||
| local words="$(to_words "$1")" | ||
| [[ -z $words ]] && { printf '\n'; return; } |
There was a problem hiding this comment.
When to_words returns an empty string, this line causes the function to output a newline character (\n). This can lead to unintended newlines being inserted during template replacement. The function should return an empty string for an empty input.
| [[ -z $words ]] && { printf '\n'; return; } | |
| [[ -z $words ]] && return |
.template/replacer.sh
Outdated
| for rel in "${path_list[@]}"; do | ||
| [[ -z $rel ]] && continue | ||
| rel=${rel#./} | ||
| [[ $rel == .code/* ]] && continue |
There was a problem hiding this comment.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
| { | ||
| "variables": { | ||
| "PROJECT_NA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationME": { | ||
| "placeholders": ["myapp", "cli_starter", "cli-starter", "yourproject"], | ||
| "description": "The name of the project/A modern CLI application", | ||
| "source": "repository_name", | ||
| "validation": "^[a-zA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI application-Z][a-zA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI application-Z0-9_-]*$" | ||
| "PROJECT_NAME": { | ||
| "placeholders": ["My CLI App", "CLI Starter"], | ||
| "description": "Human-readable project name shown in documentation, metadata, and headings.", | ||
| "sources": ["repository_name"], | ||
| "validation": "^[A-Za-z][A-Za-z0-9 _-]*$" | ||
| }, | ||
| "PROJECT_NA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationME_SNA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationKE": { | ||
| "placeholders": ["cli_starter"], | ||
| "description": "Project name in snake_case format", | ||
| "source": "repository_name", | ||
| "PROJECT_NAME_SNAKE": { | ||
| "placeholders": ["my_cli_app", "cli_starter"], | ||
| "description": "Project name in snake_case for identifiers and configuration directories.", | ||
| "sources": ["repository_name"], | ||
| "transform": "snake_case", | ||
| "validation": "^[a-z][a-z0-9_]*$" | ||
| }, | ||
| "PROJECT_NA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationME_KEBA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationB": { | ||
| "placeholders": ["cli-starter", "cli-starter-c23", "c23-cli-template"], | ||
| "description": "Project name in kebab-case format", | ||
| "source": "repository_name", | ||
| "PROJECT_NAME_KEBAB": { | ||
| "placeholders": ["myapp", "my-cli-app", "cli-starter"], | ||
| "description": "Project name in kebab-case for CLI commands, binaries, and URLs.", | ||
| "sources": ["repository_name"], | ||
| "transform": "kebab_case", | ||
| "validation": "^[a-z][a-z0-9-]*$" | ||
| }, | ||
| "PROJECT_NA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationME_PA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationSCA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationL": { | ||
| "placeholders": ["CliStarter"], | ||
| "description": "Project name in PascalCase format", | ||
| "source": "repository_name", | ||
| "PROJECT_NAME_PASCAL": { | ||
| "placeholders": ["MyCliApp", "CliStarter"], | ||
| "description": "Project name in PascalCase for types, modules, and title casing.", | ||
| "sources": ["repository_name"], | ||
| "transform": "pascal_case", | ||
| "validation": "^[A A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI application-Z][a-zA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI application-Z0-9]*$" | ||
| "validation": "^[A-Z][A-Za-z0-9]*$" | ||
| }, | ||
| "GITHUB_USERNA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI applicationME": { | ||
| "placeholders": ["yourusername", "sammyjoyce"], | ||
| "description": "GitHub username or organization", | ||
| "source": "repository_owner", | ||
| "validation": "^[a-zA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI application-Z0-9][a-zA A modern A modern CLI A modern CLI application A modern CLI application A modern CLI A modern CLI application A modern CLI application-Z0-9-]*$" | ||
| "PROJECT_DESCRIPTION": { | ||
| "placeholders": ["A modern C23 CLI application template."], | ||
| "description": "Short project description used in README content and package metadata.", | ||
| "sources": ["repository_description"], | ||
| "fallback": "A modern C23 CLI application template.", | ||
| "required": false | ||
| }, |
There was a problem hiding this comment.
Keep setup.sh in sync with template-vars schema
The variables JSON was refactored to live under a nested "variables" object (e.g. PROJECT_NAME at lines 1‑36), but .template/setup.sh still reads defaults with jq -r ".__PROJECT_NAME__" and similar paths. After this change those lookups return null, so running the interactive setup now pre-fills every prompt with null and, if the user accepts the defaults, replaces placeholders across the repo with the literal string null. The setup script needs to read from the new schema or be removed to avoid generating broken projects.
Useful? React with 👍 / 👎.
|
@codex fix |
|
Summary
Testing
|
No description provided.