8000 feat: per file custom delim overrides by hay-kot · Pull Request #261 · hay-kot/scaffold · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: per file custom delim overrides #261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 14, 2025

Conversation

hay-kot
Copy link
Owner
@hay-kot hay-kot commented Feb 14, 2025

Purpose

When working with files that contain go templates, like goreleaser files, it's annoying to have to escape those template values that should get rendered out. This feature allows a user to specify a glob pattern to substitute the opening and closing brackets for the templates.

This let's the file stay mostly in tack and the user can use a different syntax to template the file.

Proposed Changes

  • Add support for custom template delimiters

Checklist

  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Summary by CodeRabbit

  • New Features

    • Introduced support for custom template delimiters, allowing users to specify alternative left/right delimiters for template parsing.
    • Extended project scaffolding with configurable delimiter settings and updated render examples.
  • Documentation

    • Added a new section in the configuration reference explaining how to use custom delimiters.
    • Updated the configuration schema to reflect the new custom delimiter options.
  • Tests

    • Expanded test coverage to validate custom delimiter functionality.
  • Chores & Style

    • Applied internal maintenance updates and enhanced UI cues for interactive elements.

Copy link
coderabbitai bot commented Feb 14, 2025

Warning

Rate limit exceeded

@hay-kot has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 17 minutes and 33 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f4395b5 and 21ffc00.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (14)
  • .gitignore (1 hunks)
  • .golangci.toml (0 hunks)
  • app/core/engine/engine.go (5 hunks)
  • app/scaffold/.snapshots/render_rwfs/Test_RenderRWFileSystem-custom_delims.snapshot (1 hunks)
  • app/scaffold/main_test.go (2 hunks)
  • app/scaffold/project_scaffold_file.go (1 hunks)
  • app/scaffold/render_funcs.go (2 hunks)
  • app/scaffold/snapshot_test.go (1 hunks)
  • app/scaffold/testdata/projects/custom_delims/{{ .Project }}/custom.txt (1 hunks)
  • app/scaffold/testdata/projects/custom_delims/{{ .Project }}/standard.txt (1 hunks)
  • docs/docs/components/Featured.vue (1 hunks)
  • docs/docs/templates/config-reference.md (1 hunks)
  • docs/schema/schema.scaffold.ts (1 hunks)
  • go.mod (3 hunks)

Walkthrough

This pull request introduces enhancements for custom templating. It adds a new ignore rule for macOS’s .DS_Store files and removes an unused linter in the Go configuration. The core engine has been updated with a new options struct (opts) and a WithDelims function to support variable delimiters for template parsing. The scaffolding tests and sample files now include custom delimiter cases, and related documentation and schema definitions have been revised accordingly.

Changes

Files Summary
.gitignore Added entry to ignore .DS_Store files.
.golangci.toml Removed the "exportloopref" linter and cleaned up formatting.
app/.../engine.go Introduced opts struct and WithDelims function; updated parse and Factory method signatures to support custom template delimiters.
app/.../snapshots/*, app/.../main_test.go, app/.../snapshot_test.go, app/.../testdata/.../*.txt Added new test cases, sample files, and functions to validate custom delimiter functionality in templating and file rendering.
app/.../project_scaffold_file.go Added a new Delimiters field (slice of a new type) to support specifying custom template delimiters in scaffold files.
app/.../render_funcs.go Modified template rendering to check project configuration for custom delimiters and pass them via the engine’s Factory method.
docs/.../Featured.vue, docs/.../config-reference.md, docs/.../schema.scaffold.ts Corrected a Vue prop typo; introduced new documentation and schema sections describing custom delimiters and updated the property naming in the scaffold schema.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant RWFS as RenderRWFS
  participant Engine
  participant Template
  
  User->>RWFS: Invoke rendering with project config (incl. delimiters)
  RWFS->>Engine: Call Factory(reader, opfns...) with default opts
  Engine->>Engine: Initialize opts with default delimiters (e.g., "{{", "}}")
  Engine->>Engine: Apply any WithDelims options based on project config
  Engine->>Template: Create template using the resolved custom delimiters
  Template-->>Engine: Return parsed template
  Engine-->>RWFS: Return template for execution
  RWFS-->>User: Output rendered result
Loading

Possibly related PRs

Poem

I'm a hopping rabbit, coding all day,
With custom delimiters now leading the way.
Templates dance with a brand new style,
.DS_Store ignored—it’s all worthwhile!
Lint rules trimmed, tests set to play,
In this code garden, I happily sway.
🐰💻 Let’s celebrate change in a rabbit’s display!


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added documentation Improvements or additions to documentation feature labels Feb 14, 2025
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
docs/docs/components/Featured.vue (1)

37-44: ⚠️ Potential issue

Fix typo in type definition.

There's a typo in the Props type definition: deatures should be features.

 type Props = {
   features: {
     href: string;
     name: string;
     description: string;
-    deatures: string[];
+    features: string[];
   }[];
 };
🧹 Nitpick comments (5)
app/scaffold/project_scaffold_file.go (1)

22-26: Consider adding field validation for delimiters.

While the struct is well-defined, consider adding validation to ensure that:

  • The glob pattern is valid
  • The delimiters are non-empty and distinct

Example validation in ReadScaffoldFile:

 func ReadScaffoldFile(reader io.Reader) (*ProjectScaffoldFile, error) {
 	var out ProjectScaffoldFile
 
 	err := yaml.NewDecoder(reader).Decode(&out)
 	if err != nil {
 		return nil, err
 	}
+
+	// Validate delimiters
+	for _, d := range out.Delimiters {
+		if d.Left == "" || d.Right == "" {
+			return nil, fmt.Errorf("delimiters cannot be empty")
+		}
+		if d.Left == d.Right {
+			return nil, fmt.Errorf("left and right delimiters must be different")
+		}
+		if _, err := filepath.Match(d.Glob, "test"); err != nil {
+			return nil, fmt.Errorf("invalid glob pattern: %s", d.Glob)
+		}
+	}
 
 	return &out, nil
 }
docs/docs/components/Featured.vue (1)

58-64: Remove redundant cursor style.

The cursor: pointer on .feature-grid is redundant as the child a elements already have this style. This could cause confusion about which areas are clickable.

 .feature-grid {
-  cursor: pointer;
   width: 100%;
   display: grid;
   margin: 2rem 0;
   gap: 1rem;
 }
app/core/engine/engine.go (1)

91-117: Consider documenting the default delimiters.

The Factory method initializes default delimiters but this isn't documented in the function's comment.

 // Factory returns a new template from the provided reader.
 // if the reader is empty, an ErrTemplateIsEmpty is returned.
+// By default, the template uses "{{" and "}}" as delimiters unless
+// overridden using WithDelims.
 func (e *Engine) Factory(reader io.Reader, opfns ...func(*opts)) (*template.Template, error) {
app/scaffold/render_funcs.go (1)

273-288: Consider caching delimiter lookups for performance.

The current implementation looks up delimiters for each file. For better performance, consider:

  1. Pre-compiling glob patterns
  2. Caching delimiter matches for similar paths
+var defaultDelims = struct{ left, right string }{"{{", "}}"}
+
 func RenderRWFS(eng *engine.Engine, args *RWFSArgs, vars engine.Vars) error {
+    // Pre-compile glob patterns
+    type delimCache struct {
+        pattern *doublestar.Pattern
+        left, right string
+    }
+    delims := make([]delimCache, 0, len(args.Project.Conf.Delimiters))
+    for _, d := range args.Project.Conf.Delimiters {
+        pattern, err := doublestar.PathMatch(d.Glob, "")
+        if err != nil {
+            return fmt.Errorf("invalid glob pattern %q: %w", d.Glob, err)
+        }
+        delims = append(delims, delimCache{pattern, d.Left, d.Right})
+    }
docs/docs/templates/config-reference.md (1)

300-303: Fix grammar in documentation.

The sentence should use "are" instead of "is" since "delimiters" is plural.

-delimiters is a list of delimiter overrides for files.
+delimiters are a list of delimiter overrides for files.
🧰 Tools
🪛 LanguageTool

[grammar] ~302-~302: Did you mean “are” or “were”?
Context: ...ation. ::: ## delimiters delimiters is a list of delimiter overrides for files...

(SENT_START_NNS_IS)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a20dd66 and f4395b5.

📒 Files selected for processing (13)
  • .gitignore (1 hunks)
  • .golangci.toml (0 hunks)
  • app/core/engine/engine.go (5 hunks)
  • app/scaffold/.snapshots/render_rwfs/Test_RenderRWFileSystem-custom_delims.snapshot (1 hunks)
  • app/scaffold/main_test.go (2 hunks)
  • app/scaffold/project_scaffold_file.go (1 hunks)
  • app/scaffold/render_funcs.go (2 hunks)
  • app/scaffold/snapshot_test.go (1 hunks)
  • app/scaffold/testdata/projects/custom_delims/{{ .Project }}/custom.txt (1 hunks)
  • app/scaffold/testdata/projects/custom_delims/{{ .Project }}/standard.txt (1 hunks)
  • docs/docs/components/Featured.vue (1 hunks)
  • docs/docs/templates/config-reference.md (1 hunks)
  • docs/schema/schema.scaffold.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • .golangci.toml
✅ Files skipped from review due to trivial changes (2)
  • .gitignore
  • app/scaffold/.snapshots/render_rwfs/Test_RenderRWFileSystem-custom_delims.snapshot
🧰 Additional context used
🪛 LanguageTool
docs/docs/templates/config-reference.md

[grammar] ~302-~302: Did you mean “are” or “were”?
Context: ...ation. ::: ## delimiters delimiters is a list of delimiter overrides for files...

(SENT_START_NNS_IS)

app/scaffold/testdata/projects/custom_delims/{{ .Project }}/custom.txt

[uncategorized] ~1-~1: You might be missing the article “the” here.
Context: This should be project name = [[ .Project ]] This should rende...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

app/scaffold/testdata/projects/custom_delims/{{ .Project }}/standard.txt

[uncategorized] ~1-~1: You might be missing the article “the” here.
Context: This should be project name = {{ .Project }} This should rende...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

🔇 Additional comments (12)
app/scaffold/project_scaffold_file.go (1)

9-20: LGTM! Clean addition of the Delimiters field.

The placement of the new field at the end of the struct maintains backward compatibility, and the YAML tag is properly defined.

app/scaffold/snapshot_test.go (1)

49-53:

✅ Verification successful

LGTM! Good test coverage for custom delimiters.

The test case follows the established pattern and tests the new functionality.

Verify that the test helper functions exist:


🏁 Script executed:

#!/bin/bash
# Search for the helper functions used in the test
rg -A 5 'func CustomDelimsFiles\(\)' .
rg -A 5 'func CustomDelimsProject\(\)' .

Length of output: 752


LGTM: Custom delimiters test case correctly exercises the new functionality.

  • Verified that both CustomDelimsFiles() and CustomDelimsProject() exist in app/scaffold/main_test.go.
  • The test follows the established pattern and effectively tests the custom delimiters feature.
app/core/engine/engine.go (2)

21-24: LGTM! Clean struct design for delimiter options.

The opts struct is well-focused and encapsulates the delimiter configuration.


53-58: LGTM! Clean method update for custom delimiters.

The parse method cleanly integrates the custom delimiters while maintaining the existing functionality.

app/scaffold/main_test.go (2)

17-18: LGTM! Good test data organization.

The embedded filesystem for custom delimiters test data follows the established pattern in the codebase.


143-146: LGTM! Well-structured test helper functions.

The helper functions CustomDelimsFiles() and CustomDelimsProject() are well-implemented:

  • Follow consistent patterns with other test helpers
  • Provide clear test configuration for custom delimiters
  • Use meaningful glob patterns and delimiter values

Also applies to: 148-162

docs/schema/schema.scaffold.ts (2)

32-36: Fixed typo in property name.

Good catch on fixing the typo from presents to presets.


38-42: LGTM! Well-documented schema changes.

The new delimiters property and type are:

  • Well-documented with clear comments
  • Have proper TypeScript types
  • Follow the schema's documentation style

Also applies to: 44-54

app/scaffold/render_funcs.go (1)

289-302: LGTM! Good error handling.

The error handling for template creation and delimiter matching is robust:

  • Proper cleanup with f.Close()
  • Clear error propagation
docs/docs/templates/config-reference.md (1)

304-311: LGTM! Clear documentation with practical example.

The documentation:

  • Provides a clear use case with .goreleaser
  • Shows a complete configuration example
  • Explains the benefits of custom delimiters
app/scaffold/testdata/projects/custom_delims/{{ .Project }}/custom.txt (1)

1-2: LGTM! Test data properly validates custom delimiter functionality.

The test data correctly demonstrates:

  1. Custom delimiter processing with [[ .Project ]]
  2. Standard delimiter preservation with {{ .Project }}

This effectively validates the per-file custom delimiter override feature.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~1-~1: You might be missing the article “the” here.
Context: This should be project name = [[ .Project ]] This should rende...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

app/scaffold/testdata/projects/custom_delims/{{ .Project }}/standard.txt (1)

1-2: LGTM! Test data provides complementary coverage.

The test data correctly demonstrates the inverse scenario:

  1. Standard delimiter processing with {{ .Project }}
  2. Custom delimiter preservation with [[ .Project ]]

This effectively complements the custom.txt test case and validates proper per-file delimiter scoping.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~1-~1: You might be missing the article “the” here.
Context: This should be project name = {{ .Project }} This should rende...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

Comment on lines +26 to +31
func WithDelims(left string, right string) func(*opts) {
return func(o *opts) {
o.delimLeft = left
o.delimRight = right
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add validation in WithDelims function.

The function should validate that the delimiters are non-empty and distinct.

 func WithDelims(left string, right string) func(*opts) {
+	if left == "" || right == "" {
+		panic("delimiters cannot be empty")
+	}
+	if left == right {
+		panic("left and right delimiters must be different")
+	}
 	return func(o *opts) {
 		o.delimLeft = left
 		o.delimRight = right
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func WithDelims(left string, right string) func(*opts) {
return func(o *opts) {
o.delimLeft = left
o.delimRight = right
}
}
func WithDelims(left string, right string) func(*opts) {
if left == "" || right == "" {
panic("delimiters cannot be empty")
}
if left == right {
panic("left and right delimiters must be different")
}
return func(o *opts) {
o.delimLeft = left
o.delimRight = right
}
}

@hay-kot hay-kot force-pushed the feat/per-file-custom-delim-overrides branch from f4395b5 to 3126ce9 Compare February 14, 2025 13:21
@hay-kot hay-kot merged commit d0c160e into main Feb 14, 2025
3 checks passed
@hay-kot hay-kot deleted the feat/per-file-custom-delim-overrides branch February 14, 2025 13:27
@coderabbitai coderabbitai bot mentioned this pull request Mar 9, 2025
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant
0