Skip to content

Feat: CLI Support for Field Formatters in Export Commands#15184

Merged
calixtus merged 16 commits into
JabRef:mainfrom
D-Prasanth-Kumar:clean-cli-feature
Mar 16, 2026
Merged

Feat: CLI Support for Field Formatters in Export Commands#15184
calixtus merged 16 commits into
JabRef:mainfrom
D-Prasanth-Kumar:clean-cli-feature

Conversation

@D-Prasanth-Kumar

@D-Prasanth-Kumar D-Prasanth-Kumar commented Feb 21, 2026

Copy link
Copy Markdown
Contributor

Related issues and pull requests

Closes #11520

PR Description

This PR adds a --field-formatters option to the convert and generate-bib-from-aux CLI commands.

It lets users run JabRef's field formatters (like cleaning up dates, fixing page numbers, or clearing comments) directly from the command line when exporting files. This is really useful for users who want to clean up their .bib files for publication without having to open the GUI or permanently change their main database. It works by passing a comma-separated list of formatters directly to the existing cleanup logic.

Steps to test

  1. Create a test file called origin.bib with some unformatted data and a private comment.
  2. Run the convert command from your terminal, passing a list of formatters to the new --field-formatters flag.
  3. Check the new clean.bib file that gets generated.
  4. Make sure the output is clean.

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description (if change is visible to the user)
  • I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository

@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add CLI field formatters support to export commands

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add --field-formatters CLI option to convert and generate-bib-from-aux commands
• Enable field formatter application during export without GUI interaction
• Support comma-separated formatter list with field-specific cleanup operations
• Include comprehensive test coverage for formatter application during conversion
Diagram
flowchart LR
  CLI["CLI Arguments<br/>--field-formatters"]
  Parser["Parse Formatters<br/>FieldFormatterCleanupMapper"]
  Convert["Convert/GenerateBibFromAux<br/>Commands"]
  Apply["Apply Cleanup<br/>to BibEntries"]
  Output["Export Clean<br/>Bibliography"]
  CLI -- "comma-separated list" --> Parser
  Parser -- "FieldFormatterCleanup objects" --> Convert
  Convert -- "iterate entries" --> Apply
  Apply -- "formatted entries" --> Output
Loading

Grey Divider

File Changes

1. jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java ✨ Enhancement +16/-0

Add field formatters option to Convert command

• Added --field-formatters CLI option to accept formatter specifications
• Implemented formatter parsing and application logic using FieldFormatterCleanupMapper
• Applied cleanups to all BibEntry objects before export
• Imported required cleanup-related classes

jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java


2. jabkit/src/main/java/org/jabref/toolkit/commands/GenerateBibFromAux.java ✨ Enhancement +16/-0

Add field formatters option to GenerateBibFromAux command

• Added --field-formatters CLI option matching Convert command interface
• Implemented identical formatter parsing and application logic
• Applied cleanups to generated BibDatabase entries
• Imported required cleanup and List utility classes

jabkit/src/main/java/org/jabref/toolkit/commands/GenerateBibFromAux.java


3. jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java 🧪 Tests +32/-0

Add test for field formatters in conversion

• Added comprehensive test for field formatter application during conversion
• Tests multiple formatters: page normalization, month normalization, unicode ligature replacement,
 comment clearing
• Validates output contains expected transformations and excludes private comments
• Added assertFalse import for negative assertion

jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java


View more (1)
4. CHANGELOG.md 📝 Documentation +1/-0

Document field formatters CLI feature

• Documented new --field-formatters CLI option for convert and generate-bib-from-aux commands
• Referenced issue #11520 for tracking
• Added to "Added" section of changelog

CHANGELOG.md


Grey Divider

Qodo Logo

@github-actions github-actions Bot added the good second issue Issues that involve a tour of two or three interweaved components in JabRef label Feb 21, 2026
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Feb 21, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (3) 📎 Requirement gaps (0)

Grey Divider


Action required

1. convert formatter parsing broken📘 Rule violation ✓ Correctness
Description
The new --field-formatters parsing replaces all commas, which breaks specifying multiple
formatters within a single field (commas inside [...]). This can silently apply the wrong
formatter(s) or none at all, producing incorrect export output.
Code

jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java[R72-75]

+        if (fieldFormatters != null && !fieldFormatters.isBlank()) {
+            String parseableString = fieldFormatters.replace(",", "\n");
+            List<FieldFormatterCleanup> cleanups = FieldFormatterCleanupMapper.parseActions(parseableString);
+            for (BibEntry entry : parserResult.get().getDatabase().getEntries()) {
Evidence
Compliance requires robust handling of external inputs and edge cases; replacing all commas modifies
the semantics of the formatter string and breaks valid inputs containing comma-separated formatter
lists inside brackets.

Rule 3: Generic: Robust Error Handling and Edge Case Management
jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java[72-78]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`--field-formatters` currently does `fieldFormatters.replace(&amp;quot;,&amp;quot;, &amp;quot;\n&amp;quot;)`, which corrupts valid formatter specs that contain comma-separated formatter lists inside brackets (e.g., `title[escapeAmpersands,latex_cleanup]`). This can lead to silently wrong/no cleanup actions.
## Issue Context
This CLI argument is external input and should be parsed robustly. The current approach cannot distinguish commas separating field blocks from commas separating formatters within a field.
## Fix Focus Areas
- jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java[72-80]
- jabkit/src/main/java/org/jabref/toolkit/commands/GenerateBibFromAux.java[86-94]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Cleanup loop duplicated📘 Rule violation ⛯ Reliability
Description
The same nested loop logic to apply FieldFormatterCleanup actions to entries is duplicated in two
commands. This increases maintenance cost and risks divergent behavior over time.
Code

jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java[R72-80]

+        if (fieldFormatters != null && !fieldFormatters.isBlank()) {
+            String parseableString = fieldFormatters.replace(",", "\n");
+            List<FieldFormatterCleanup> cleanups = FieldFormatterCleanupMapper.parseActions(parseableString);
+            for (BibEntry entry : parserResult.get().getDatabase().getEntries()) {
+                for (FieldFormatterCleanup cleanup : cleanups) {
+                    cleanup.cleanup(entry);
+                }
+            }
+        }
Evidence
The compliance checklist asks to avoid duplication; the identical cleanup-application block was
added in both Convert and GenerateBibFromAux.

AGENTS.md
jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java[72-80]
jabkit/src/main/java/org/jabref/toolkit/commands/GenerateBibFromAux.java[86-94]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The same cleanup-application loop was added in multiple commands, creating duplication and increasing the chance of inconsistent future changes.
## Issue Context
Both `convert` and `generate-bib-from-aux` apply field formatter cleanups in the same way and can share a small helper.
## Fix Focus Areas
- jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java[72-80]
- jabkit/src/main/java/org/jabref/toolkit/commands/GenerateBibFromAux.java[86-94]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Weak month assertion🐞 Bug ⛯ Reliability
Description
The added test checks only for substring "jan", which is also present in the original value
"January". This can let failures in normalize_month slip through without being detected.
Code

jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java[146]

+        assertTrue(outputContent.toLowerCase().contains("jan"));
Evidence
The test asserts that the output contains "jan" anywhere, but NormalizeMonthFormatter normalizes
months to JabRef format (e.g., #jan#). Since "January" contains "jan", the assertion can pass even
when normalization is not applied.

jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java[144-147]
jablib/src/main/java/org/jabref/logic/formatter/bibtexfields/NormalizeMonthFormatter.java[23-27]
jablib/src/main/java/org/jabref/model/entry/Month.java[158-168]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The month normalization test can pass even if the month was not normalized, because it only checks for the substring `jan`.
## Issue Context
`normalize_month` produces JabRef month format like `#jan#`, while the original input `January` also contains `jan`.
## Fix Focus Areas
- jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java[144-147]
## Suggested change
Replace the substring assertion with something that distinguishes normalized vs unnormalized, e.g.:
- `assertTrue(outputContent.contains(&amp;quot;#jan#&amp;quot;));`
(or assert on the exact `month` field line if stable).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Advisory comments

4. Test uses string concatenation📘 Rule violation ✓ Correctness
Description
The new test builds a multi-line BibTeX string via + concatenation instead of using a Java text
block. This is less readable and conflicts with the preference for modern Java APIs/patterns.
Code

jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java[R125-130]

+        String originBibtex = "@Article{test_entry,\n" +
+                "  title   = {my first research},\n" +
+                "  pages   = {1-10},\n" +
+                "  month   = {January},\n" +
+                "  comment = {private note}\n" +
+                "}";
Evidence
The checklist requests use of modern Java best practices; for multi-line string literals, text
blocks are preferred over repeated concatenation.

AGENTS.md
jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java[125-130]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test constructs a multi-line BibTeX literal using string concatenation, which is harder to read and maintain.
## Issue Context
Modern Java supports text blocks, which are the preferred style for multi-line string literals.
## Fix Focus Areas
- jabkit/src/test/java/org/jabref/toolkit/commands/ConvertTest.java[125-130]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +72 to +75
if (fieldFormatters != null && !fieldFormatters.isBlank()) {
String parseableString = fieldFormatters.replace(",", "\n");
List<FieldFormatterCleanup> cleanups = FieldFormatterCleanupMapper.parseActions(parseableString);
for (BibEntry entry : parserResult.get().getDatabase().getEntries()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Action required

1. convert formatter parsing broken 📘 Rule violation ✓ Correctness

The new --field-formatters parsing replaces all commas, which breaks specifying multiple
formatters within a single field (commas inside [...]). This can silently apply the wrong
formatter(s) or none at all, producing incorrect export output.
Agent Prompt
## Issue description
`--field-formatters` currently does `fieldFormatters.replace(",", "\n")`, which corrupts valid formatter specs that contain comma-separated formatter lists inside brackets (e.g., `title[escapeAmpersands,latex_cleanup]`). This can lead to silently wrong/no cleanup actions.

## Issue Context
This CLI argument is external input and should be parsed robustly. The current approach cannot distinguish commas separating field blocks from commas separating formatters within a field.

## Fix Focus Areas
- jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java[72-80]
- jabkit/src/main/java/org/jabref/toolkit/commands/GenerateBibFromAux.java[86-94]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@github-actions github-actions Bot added the status: changes-required Pull requests that are not yet complete label Feb 21, 2026
@testlens-app

This comment has been minimized.

@github-actions github-actions Bot added status: no-bot-comments status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete status: no-bot-comments labels Feb 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Feb 23, 2026
@faneeshh

Copy link
Copy Markdown
Collaborator

I feel like in the parsing logic using replace("," , "\n") might accidentally break formatters that contain internal commas. Since you are already using FieldFormatterCleanupMapper you could use a more robust regex split or split only on top level commas (ignoring commas inside brackets).

@D-Prasanth-Kumar

Copy link
Copy Markdown
Contributor Author

I feel like in the parsing logic using replace("," , "\n") might accidentally break formatters that contain internal commas. Since you are already using FieldFormatterCleanupMapper you could use a more robust regex split or split only on top level commas (ignoring commas inside brackets).

Yes I identified it, and working on that.

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Feb 25, 2026
@testlens-app

This comment has been minimized.

@github-actions github-actions Bot added status: no-bot-comments status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete status: no-bot-comments labels Mar 12, 2026
@testlens-app

This comment has been minimized.

@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 14, 2026
@koppor koppor added status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers and removed status: no-bot-comments labels Mar 16, 2026
Comment thread jabkit/src/main/java/org/jabref/toolkit/commands/Convert.java Outdated
@testlens-app

This comment has been minimized.

@koppor koppor added status: changes-required Pull requests that are not yet complete and removed status: ready-for-review Pull Requests that are ready to be reviewed by the maintainers labels Mar 16, 2026
@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 16, 2026
@testlens-app

testlens-app Bot commented Mar 16, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: cd57114
▶️ Tests: 10178 executed
⚪️ Checks: 52/52 completed


Learn more about TestLens at testlens.app.

@calixtus calixtus enabled auto-merge March 16, 2026 20:35
@calixtus calixtus added this pull request to the merge queue Mar 16, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Mar 16, 2026
Merged via the queue into JabRef:main with commit 7e10df2 Mar 16, 2026
52 checks passed
AnvitaPrasad pushed a commit to AnvitaPrasad/jabref that referenced this pull request Mar 18, 2026
* Add CLI support for field formatters in export commands

* update CHANGELOG.md

* update CHANGELOG.md

* fix CHANGELOG.md

* fix CHANGELOG.md

* new modifications

* removed unused imports

* Consistency in test class

* move static method to common util class, simplified regex

---------

Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Oliver Kopp <kopp.dev@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>
FynnianB pushed a commit to FynnianB/jabref that referenced this pull request Mar 19, 2026
* Add CLI support for field formatters in export commands

* update CHANGELOG.md

* update CHANGELOG.md

* fix CHANGELOG.md

* fix CHANGELOG.md

* new modifications

* removed unused imports

* Consistency in test class

* move static method to common util class, simplified regex

---------

Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Oliver Kopp <kopp.dev@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>
FynnianB pushed a commit to FynnianB/jabref that referenced this pull request Mar 19, 2026
* Add CLI support for field formatters in export commands

* update CHANGELOG.md

* update CHANGELOG.md

* fix CHANGELOG.md

* fix CHANGELOG.md

* new modifications

* removed unused imports

* Consistency in test class

* move static method to common util class, simplified regex

---------

Co-authored-by: Carl Christian Snethlage <50491877+calixtus@users.noreply.github.com>
Co-authored-by: Christoph <siedlerkiller@gmail.com>
Co-authored-by: Oliver Kopp <kopp.dev@gmail.com>
Co-authored-by: Carl Christian Snethlage <calixtus@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

good second issue Issues that involve a tour of two or three interweaved components in JabRef status: no-bot-comments status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CLI Support for Field Formatters in Export Commands

5 participants