Skip to content

feat(csv): add standard compliant CSV parser#77

Merged
jiacai2050 merged 3 commits intomainfrom
feat-csv
Mar 22, 2026
Merged

feat(csv): add standard compliant CSV parser#77
jiacai2050 merged 3 commits intomainfrom
feat-csv

Conversation

@jiacai2050
Copy link
Owner

Replace naive parser logic with the new module. Includes RFC 4180 support for embedded newlines and proper quote escaping.

Replace naive parser logic with the new module. Includes RFC 4180 support for embedded newlines and proper quote escaping.
Copilot AI review requested due to automatic review settings March 22, 2026 10:33
@gemini-code-assist
Copy link

Summary of Changes

Hello, 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 significantly upgrades the CSV parsing functionality within the zigcli project by integrating a new, dedicated csv module. This change moves away from a more basic parsing approach to one that adheres strictly to RFC 4180, ensuring greater accuracy and reliability when handling complex CSV data. The update also benefits existing tools like pretty-csv by providing them with a more capable and compliant parsing engine, ultimately improving the overall data processing robustness of the library.

Highlights

  • New CSV Parser Module: A new csv package has been introduced to the zigcli library, providing robust and standard-compliant CSV parsing capabilities.
  • RFC 4180 Compliance: The new CSV parser fully implements RFC 4180 rules, including support for embedded newlines, doubled-quote unescaping in quoted fields, and consistent field counts across records.
  • Updated pretty-csv Tool: The pretty-csv utility has been refactored to leverage the new csv module, enhancing its parsing accuracy and feature set.
  • Build System Enhancement: The build script now includes the VERSION in the build flags, improving release management.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new, robust, RFC 4180-compliant CSV parser and integrates it into pretty-csv, replacing the previous naive implementation. The changes are a significant improvement, providing better error handling and support for complex CSV features like embedded newlines. The new csv module is well-designed with a state machine-based parser and includes comprehensive tests. The memory management is handled carefully. I have one suggestion to improve the clarity of the documentation for one of the parsing options.

- =parseLine()= parses a single delimited line into fields
- =parseDocument()= parses a full input buffer into rows
- Configurable delimiter through =ParseOptions.delimiter=
- Optional empty-line skipping and CR trimming

Choose a reason for hiding this comment

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

medium

The phrase "CR trimming" could be misleading. The trim_trailing_cr option doesn't trim carriage returns but rather controls whether a lone \r (not part of a \r\n sequence) is an error or part of the field's data. Clarifying this in the documentation would help users better understand the behavior, especially since it differs from typical line-based processing that might simply trim the character.

- Optional empty-line skipping and strict handling of lone carriage returns

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new zigcli.csv package and wires pretty-csv to use it, replacing the previous ad-hoc line parser with an RFC 4180–aware state machine.

Changes:

  • Export new csv module from zigcli and add a full-document CSV parser with quote/newline support.
  • Update pretty-csv to parse via csv.parseDocument() instead of splitting lines manually.
  • Add/refresh documentation and changelog entries; pass -Dversion through release builds.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/lib.zig Exports the new zigcli.csv module.
src/csv.zig Introduces CSV parsing API (parseLine, parseDocument) plus tests.
src/bin/pretty-csv.zig Switches to the shared CSV parser and removes the old local parser.
docs/content/programs/pretty-csv.org Updates pretty-csv feature documentation for RFC 4180 behavior.
docs/content/packages/csv.org Adds package docs for the new csv module.
docs/content/packages/_index.org Lists the new csv package in the packages index.
docs/content/install.org Updates install docs to reflect the additional submodule.
docs/content/_index.org Mentions the new csv package on the docs homepage.
CHANGELOG.md Records the new csv package and behavior in the changelog.
.github/build-release.sh Passes -Dversion to zig build for release artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +6 to +10
pub const ParseOptions = struct {
delimiter: u8 = ',',
skip_empty_lines: bool = false,
trim_trailing_cr: bool = true,
};
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

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

ParseOptions.trim_trailing_cr is named like it will trim a trailing '\r', but the current parser never trims; it only treats a bare '\r' (not followed by '\n') as an InvalidRecordTerminator (and parseLine rejects any '\r' regardless). Either implement actual CR trimming where intended (e.g., allow/strip a final '\r' in parseLine inputs), or rename/remove this option so callers aren't misled.

Copilot uses AI. Check for mistakes.
src/csv.zig Outdated
Comment on lines +402 to +407
test "parseDocument skips empty lines and trims trailing CR" {
const allocator = std.testing.allocator;
var document = try parseDocument(allocator, "a,b\r\n\r\n1,2\r\n", .{
.skip_empty_lines = true,
});
defer document.deinit(allocator);
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

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

The test name says it "trims trailing CR", but the input uses normal CRLF record terminators (no stray/trailing '\r' to trim). Consider renaming the test to match what it's asserting, or add a case that actually covers the intended CR-trimming behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +27
The package also keeps a few explicit extensions for CLI use cases:

- Alternate delimiters such as TSV via =ParseOptions.delimiter=
- Optional empty-line skipping via =ParseOptions.skip_empty_lines=
- Acceptance of LF-only line endings in addition to RFC 4180 CRLF

Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

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

This doc claims "CR trimming" as an extension, but the current implementation doesn't trim CR characters; it rejects a bare '\r' as error.InvalidRecordTerminator (and parseLine rejects '\r' entirely). Please update the documentation to reflect the actual behavior, or adjust the parser/API to provide the documented trimming behavior.

Copilot uses AI. Check for mistakes.
Add release-single.sh for isolated CI builds.
Extend workflow to support matrix targets (Linux, macOS, Windows, FreeBSD).
Remove trim_trailing_cr to enforce strict record terminators.
@jiacai2050 jiacai2050 force-pushed the feat-csv branch 6 times, most recently from 0f65d53 to d3141f9 Compare March 22, 2026 13:04
@jiacai2050 jiacai2050 merged commit 7d99a65 into main Mar 22, 2026
16 checks passed
@jiacai2050 jiacai2050 deleted the feat-csv branch March 22, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants