fix(cobra): escape newlines, tabs, and carriage returns in kdlQuoteAlways#539
fix(cobra): escape newlines, tabs, and carriage returns in kdlQuoteAlways#539
Conversation
…ways Co-authored-by: thecodesmith <[email protected]>
…ecial-characters fix(cobra): escape newlines, tabs, and carriage returns in kdlQuoteAlways
Summary of ChangesHello, 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 resolves an issue where Cobra-generated KDL specifications would become invalid and fail to parse if help text fields contained special characters like newlines, tabs, or carriage returns. By correctly escaping these characters during KDL generation, the change ensures robust and parsable output, improving the reliability of the Cobra integration. Highlights
Changelog
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
|
Greptile SummaryThis PR fixes a bug in
Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Input string] --> B{needsQuoting?}
B -- No --> C[Return bare identifier]
B -- Yes --> D[kdlQuoteAlways]
A2[Input string] --> D
D --> E["Escape \\ → \\\\"]
E --> F["Escape \" → \\\""]
F --> G["Escape LF → \\n (NEW)"]
G --> H["Escape TAB → \\t (NEW)"]
H --> I["Escape CR → \\r (NEW)"]
I --> J["Wrap in double quotes"]
J --> K[Valid KDL string literal]
style G fill:#c8f7c5
style H fill:#c8f7c5
style I fill:#c8f7c5
Last reviewed commit: 91be5a5 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #539 +/- ##
=======================================
Coverage 77.94% 77.94%
=======================================
Files 48 48
Lines 6682 6682
Branches 6682 6682
=======================================
Hits 5208 5208
Misses 1114 1114
Partials 360 360 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR fixes KDL output generation for Cobra-derived specs by ensuring control characters in quoted strings are properly escaped, preventing invalid KDL when help text contains newlines/tabs/carriage returns.
Changes:
- Escape
\n,\t, and\rinkdlQuoteAlwaysso generated KDL remains syntactically valid. - Add unit tests covering escaping behavior and end-to-end generation cases for multiline help text.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| integrations/cobra/kdl.go | Escapes newline/tab/carriage-return characters in kdlQuoteAlways to produce valid KDL strings. |
| integrations/cobra/cobra_usage_test.go | Adds tests validating escape behavior and verifying generated KDL contains escaped sequences instead of literal control characters. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Code Review
This pull request addresses an issue where special characters in Cobra help text were not properly escaped for KDL output, leading to parsing errors. The fix correctly escapes newlines, tabs, and carriage returns. The added tests are comprehensive, covering unit tests for the escaping logic and integration tests for command and flag help text. I have one suggestion to improve the performance of the string replacement logic.
| s = strings.ReplaceAll(s, `\`, `\\`) | ||
| s = strings.ReplaceAll(s, `"`, `\"`) | ||
| s = strings.ReplaceAll(s, "\n", `\n`) | ||
| s = strings.ReplaceAll(s, "\t", `\t`) | ||
| s = strings.ReplaceAll(s, "\r", `\r`) |
There was a problem hiding this comment.
Chaining multiple strings.ReplaceAll calls can be inefficient as it requires multiple passes over the string, allocating a new string for each replacement. A more performant approach is to use strings.NewReplacer, which performs all replacements in a single pass. For optimal performance, the Replacer instance should be created once at the package level and reused across function calls.
s = strings.NewReplacer(
"\\", "\\\\",
"\"", "\\\"",
"\n", "\\n",
"\t", "\\t",
"\r", "\\r"
).Replace(s)### 🚀 Features - **(spec)** **breaking** add support for license, before/after help metadata by [@jdx](https://github.com/jdx) in [#542](#542) ### 🐛 Bug Fixes - **(cobra)** escape newlines, tabs, and carriage returns in kdlQuoteAlways by [@thecodesmith](https://github.com/thecodesmith) in [#539](#539) - bump major version for breaking changes in release automation by [@jdx](https://github.com/jdx) in [#544](#544) - add custom_major_increment_regex for breaking change detection by [@jdx](https://github.com/jdx) in [#545](#545) - handle all breaking change commit formats in major bump regex by [@jdx](https://github.com/jdx) in [27e1ab1](27e1ab1) - normalize breaking change commit format in preprocessor by [@jdx](https://github.com/jdx) in [aa72b92](aa72b92) ### 📚 Documentation - add argparse-usage integration by [@jdx](https://github.com/jdx) in [#531](#531) - mark KDL code blocks as KDL and use correct inline-comment `//` by [@muzimuzhi](https://github.com/muzimuzhi) in [#536](#536) - fix include syntax to match implementation by [@jdx](https://github.com/jdx) in [#540](#540) - consolidate integration list to single source by [@jdx](https://github.com/jdx) in [#541](#541) - fix link to integrations by [@muzimuzhi](https://github.com/muzimuzhi) in [#543](#543) ### 🛡️ Security - **(deps)** update dependency eslint to v10 by [@renovate[bot]](https://github.com/renovate[bot]) in [#526](#526) ### 🔍 Other Changes - Added an integration with ruby's OptionParser by [@packrat386](https://github.com/packrat386) in [#533](#533) ### 📦️ Dependency Updates - update actions/setup-node digest to 53b8394 by [@renovate[bot]](https://github.com/renovate[bot]) in [#525](#525) - update jdx/mise-action action to v3 by [@renovate[bot]](https://github.com/renovate[bot]) in [#528](#528) - update rust crate roff to v1 by [@renovate[bot]](https://github.com/renovate[bot]) in [#529](#529) ### New Contributors - @thecodesmith made their first contribution in [#539](#539) - @packrat386 made their first contribution in [#533](#533)
⚠️ **CAUTION: this is a major update, indicating a breaking change!**⚠️ This MR contains the following updates: | Package | Update | Change | |---|---|---| | [usage](https://github.com/jdx/usage) | major | `2.18.2` → `3.2.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>jdx/usage (usage)</summary> ### [`v3.2.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#320---2026-03-23) [Compare Source](jdx/usage@v3.1.0...v3.2.0) ##### 🚀 Features - Support env-backed choices with `choices env=...` by [@​mustafa0x](https://github.com/mustafa0x) in [#​548](jdx/usage#548) ##### 🐛 Bug Fixes - **(zsh)** escape parentheses and brackets in completion descriptions by [@​jdx](https://github.com/jdx) in [#​559](jdx/usage#559) ##### New Contributors - [@​mustafa0x](https://github.com/mustafa0x) made their first contribution in [#​548](jdx/usage#548) ### [`v3.1.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#310---2026-03-22) [Compare Source](jdx/usage@v3.0.0...v3.1.0) ##### 🚀 Features - **(cli)** render all doc-related fields in --help output by [@​jdx](https://github.com/jdx) in [#​554](jdx/usage#554) - **(cli)** support reading spec from stdin via --file - by [@​jdx](https://github.com/jdx) in [#​555](jdx/usage#555) ##### 🐛 Bug Fixes - **(zsh)** remove trailing space from completions and add directory slash by [@​jdx](https://github.com/jdx) in [#​556](jdx/usage#556) - use field assignment for non-exhaustive Spec in benchmarks by [@​jdx](https://github.com/jdx) in [#​552](jdx/usage#552) ##### 📦️ Dependency Updates - update apple-actions/import-codesign-certs digest to [`fe74d46`](jdx/usage@fe74d46) by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​550](jdx/usage#550) - update codecov/codecov-action digest to [`1af5884`](jdx/usage@1af5884) by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​551](jdx/usage#551) - lock file maintenance by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​547](jdx/usage#547) ### [`v3.0.0`](https://github.com/jdx/usage/blob/HEAD/CHANGELOG.md#300---2026-03-13) [Compare Source](jdx/usage@v2.18.2...v3.0.0) ##### 🚀 Features - **(spec)** **breaking** add support for license, before/after help metadata by [@​jdx](https://github.com/jdx) in [#​542](jdx/usage#542) ##### 🐛 Bug Fixes - **(cobra)** escape newlines, tabs, and carriage returns in kdlQuoteAlways by [@​thecodesmith](https://github.com/thecodesmith) in [#​539](jdx/usage#539) - bump major version for breaking changes in release automation by [@​jdx](https://github.com/jdx) in [#​544](jdx/usage#544) - add custom\_major\_increment\_regex for breaking change detection by [@​jdx](https://github.com/jdx) in [#​545](jdx/usage#545) - handle all breaking change commit formats in major bump regex by [@​jdx](https://github.com/jdx) in [27e1ab1](jdx/usage@27e1ab1) - normalize breaking change commit format in preprocessor by [@​jdx](https://github.com/jdx) in [aa72b92](jdx/usage@aa72b92) ##### 📚 Documentation - add argparse-usage integration by [@​jdx](https://github.com/jdx) in [#​531](jdx/usage#531) - mark KDL code blocks as KDL and use correct inline-comment `//` by [@​muzimuzhi](https://github.com/muzimuzhi) in [#​536](jdx/usage#536) - fix include syntax to match implementation by [@​jdx](https://github.com/jdx) in [#​540](jdx/usage#540) - consolidate integration list to single source by [@​jdx](https://github.com/jdx) in [#​541](jdx/usage#541) - fix link to integrations by [@​muzimuzhi](https://github.com/muzimuzhi) in [#​543](jdx/usage#543) ##### 🛡️ Security - **(deps)** update dependency eslint to v10 by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​526](jdx/usage#526) ##### 🔍 Other Changes - Added an integration with ruby's OptionParser by [@​packrat386](https://github.com/packrat386) in [#​533](jdx/usage#533) ##### 📦️ Dependency Updates - update actions/setup-node digest to [`53b8394`](jdx/usage@53b8394) by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​525](jdx/usage#525) - update jdx/mise-action action to v3 by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​528](jdx/usage#528) - update rust crate roff to v1 by [@​renovate\[bot\]](https://github.com/renovate\[bot]) in [#​529](jdx/usage#529) ##### New Contributors - [@​thecodesmith](https://github.com/thecodesmith) made their first contribution in [#​539](jdx/usage#539) - [@​packrat386](https://github.com/packrat386) made their first contribution in [#​533](jdx/usage#533) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDIuMTAiLCJ1cGRhdGVkSW5WZXIiOiI0My4xMDIuMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbIlJlbm92YXRlIEJvdCIsImF1dG9tYXRpb246Ym90LWF1dGhvcmVkIiwiZGVwZW5kZW5jeS10eXBlOjptYWpvciJdfQ==-->
This change fixes the issue where Cobra help text fields with newlines would be rendered as literal newlines in the output KDL spec, which was invalid and failed to parse.