Skip to content

CAMEL-23867: camel tui - Add settings dialog#24545

Merged
davsclaus merged 5 commits into
apache:mainfrom
ammachado:CAMEL-23867
Jul 9, 2026
Merged

CAMEL-23867: camel tui - Add settings dialog#24545
davsclaus merged 5 commits into
apache:mainfrom
ammachado:CAMEL-23867

Conversation

@ammachado

@ammachado ammachado commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Description

Add a Settings dialog to the Camel TUI (F2 actions menu) for choosing the theme, the starting tab, and the default run-from-folder, with room for future settings. Settings are held in a single TuiSettings object (load -> mutate -> save) persisted under camel.tui.* keys.

The Theme row live-previews the selected theme as you cycle through it (Space/arrows), the same way the standalone Theme popup does: the theme applies instantly without closing the dialog, Enter persists the previewed theme, and Esc (or dismissing the dialog via any other action) reverts to whatever was active before the dialog was opened.

Bundles two related changes:

  • Rebrand the Camel CLI user configuration file from camel-jbang-user.properties to camel-cli.properties, keeping the existing dot convention (global ~/.camel-cli.properties hidden, local ./camel-cli.properties visible). A one-time best-effort migration renames a pre-existing global and local legacy file at CLI startup.
  • Make the TUI settings (theme, last folder, TuiSettings) local-aware: read/write ./camel-cli.properties when present, else ~/.camel-cli.properties.

The starting tab is applied on launch; the default folder is used only when there is no remembered last folder. Docs and the 4.22 upgrade guide are updated accordingly.

Target

  • I checked that the commit is targeting the correct branch (Camel 4 uses the main branch)

Tracking

  • If this is a large change, bug fix, or code improvement, I checked there is a JIRA issue filed for the change (usually before you start working on it).

Apache Camel coding standards and style

  • I checked that each commit in the pull request has a meaningful subject line and body.
  • I have run mvn clean install -DskipTests locally from root folder and I have committed all auto-generated changes.

AI-assisted contributions

  • If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., Co-authored-by trailers) and the PR description identifies the AI tool used.

Claude Code on behalf of Adriano Machado (ammachado)

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • docs
  • dsl/camel-jbang/camel-jbang-core
  • dsl/camel-jbang/camel-jbang-plugin-tui
  • test-infra/camel-test-infra-cli

🔬 Scalpel shadow comparison — Scalpel: 9 tested, 8 compile-only — current: 7 all tested

Maveniverse Scalpel detected 17 affected modules (current approach: 7).

⚠️ Modules only in Scalpel (10)
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-launcher
  • coverage
  • docs

Skip-tests mode would test 9 modules (4 direct + 5 downstream), skip tests for 8 (generated code, meta-modules)

Modules Scalpel would test (9)
  • camel-jbang-core
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-test-infra-cli
  • docs
Modules with tests skipped (8)
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-launcher
  • coverage

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • dsl/camel-jbang/camel-jbang-core: 1 test(s) disabled on GitHub Actions

💡 Manual integration tests recommended:

You modified dsl/camel-jbang/camel-jbang-core. The related integration tests in dsl/camel-jbang/camel-jbang-it are excluded from CI. Consider running them manually:

mvn verify -f dsl/camel-jbang/camel-jbang-it -Djbang-it-test
All tested modules (17 modules)
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: Test Infra :: Cli (Camel CLI)

⚙️ View full build and test results

@ammachado ammachado marked this pull request as ready for review July 8, 2026 22:56

@davsclaus davsclaus left a comment

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.

Thank you for this well-structured PR, @ammachado! The Settings dialog, config file rename with migration, and the per-key local/global routing in TuiUserConfig are nicely designed. The test coverage is thorough — 5 new test files covering migration idempotency, settings round-trip, popup rendering, popup interaction, and local/global key routing.

Two items need attention before this can be merged:

  1. Unmerged dependency — The PR description states it depends on #24541 (CAMEL-23971: fix ordered properties containsKey support), which is still open. TuiUserConfig.livesInLocal() explicitly works around the broken OrderedProperties.containsKey() (documented in the comment), but this PR should wait for #24541 to land first.

  2. Default folder vs. last folder precedence — see inline comment on FolderInputPopup.java.

One minor observation: CommandLineHelperMigrationTest.renamesLegacyLocalFileToNewName creates files in the actual CWD (not @TempDir) since local config paths are CWD-relative. The try/finally cleanup mitigates this, but it's fragile if the test is interrupted.

This review does not replace specialized AI review tools (CodeRabbit, Sourcery) or static analyzers (SonarCloud).

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of davsclaus

@ammachado

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @davsclaus.

On the #24541 dependency (item 1): I've removed the OrderedProperties.containsKey() workaround in TuiUserConfig.livesInLocal(), which now calls containsKey() directly. This relies on the CAMEL-23971 fix from #24541, so this PR should land on top of / be rebased onto that change. I've dropped the explicit "Depends on #24541" line from the description now that the code references the fix directly, but the ordering still stands: #24541 first. A regression test (writeUpdatesLocalForExistingLocalKeyWithEmptyValue) covers the empty-valued-key case that containsKey handles but the old getProperty null-check did not.

On the folder precedence (inline comment): fixed. FolderInputPopup.open() now checks lastFolder first, falling back to defaultFolder and then user.dir, matching the docs and PR description. Added FolderInputPopupTest with three cases covering the full precedence chain.

On renamesLegacyLocalFileToNewName: the local config path resolves relative to the JVM working directory via Paths.get(LOCAL_USER_CONFIG), and CommandLineHelper exposes no seam to redirect it (unlike home, which has useHomeDir), so the test must write to the real CWD by design. It already guards with deleteIfExists on both files before writing plus try/finally cleanup after. Happy to add a CWD-injection seam if you'd prefer stronger isolation.

Claude Code on behalf of Adriano Machado (ammachado)

@ammachado

Copy link
Copy Markdown
Contributor Author

Correction / course change to my previous comment: to keep this PR self-contained and mergeable independently of #24541, I've kept the existing getProperty-based local-key check in TuiUserConfig.livesInLocal() rather than switching it to containsKey(). The getProperty(key) != null check already handles the empty-valued-key case correctly (an empty property line loads as "", not null), so there is no functional gap on this branch.

The switch to OrderedProperties.containsKey() will come in a follow-up PR once #24541 lands. This PR now has no dependency on #24541.

Still included here: the FolderInputPopup folder-precedence fix (lastFolder > defaultFolder > user.dir) with FolderInputPopupTest, plus a TuiUserConfig regression test for the empty-valued local override. Full TUI module test suite is green.

Claude Code on behalf of Adriano Machado (ammachado)

@davsclaus

Copy link
Copy Markdown
Contributor

There is merge conflict now as TUI has been updated with themes

@oscerd oscerd left a comment

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.

Nice feature, and the test coverage is thorough — the *RenderTest / real-KeyEvent patterns mirror the module well and the config migration is well covered. The two substantive items from @davsclaus's review look addressed: the OrderedProperties.containsKey dependency was dropped in favour of getProperty(key) != null (correct for java.util.Properties, with a regression test for the empty-value case), and the folder precedence lastFolder > defaultFolder > user.dir is fixed and tested.

The remaining blocker is the merge conflict @davsclaus mentioned (the TUI picked up themes in CAMEL-23839) — a rebase onto current main should clear it, then it's ready for re-review.

Reviewed with Claude Code on behalf of Andrea Cosentino. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

ammachado and others added 3 commits July 9, 2026 09:04
Add a Settings dialog to the Camel TUI (F2 actions menu) for choosing the
theme, the starting tab, and the default run-from-folder, with room for
future settings. Settings are held in a single TuiSettings object
(load -> mutate -> save) persisted under camel.tui.* keys.

Bundle two related changes:
- Rebrand the Camel CLI user configuration file from camel-jbang-user.properties
  to camel-cli.properties, keeping the existing dot convention (global
  ~/.camel-cli.properties hidden, local ./camel-cli.properties visible). A
  one-time best-effort migration renames a pre-existing global and local
  legacy file at CLI startup.
- Make the TUI settings (theme, last folder, TuiSettings) local-aware:
  read/write ./camel-cli.properties when present, else ~/.camel-cli.properties.

The starting tab is applied on launch; the default folder is used only when
there is no remembered last folder. Docs and the 4.22 upgrade guide are
updated accordingly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fix the Run-from-Folder pre-fill precedence in FolderInputPopup to match the
documented contract: the most recently used folder wins, the configured
default folder is used only when there is no remembered folder, and user.dir
is the final fallback. Adds FolderInputPopupTest covering all three cases.

Also adds a TuiUserConfig regression test asserting that an explicitly-set
empty-valued local key is still recognized as a local override.

Note: TuiUserConfig.livesInLocal keeps the getProperty-based local-key check
for now, so this PR stays independent of CAMEL-23971 (apache#24541). Switching to
OrderedProperties.containsKey is left to a follow-up PR once apache#24541 lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@davsclaus davsclaus left a comment

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.

Nice work on this PR, @ammachado! The config file rename with migration, per-key local/global routing in TuiUserConfig, and the Settings dialog are well-structured. Test coverage is thorough — 5 new test files covering migration idempotency, settings round-trip, popup rendering, popup interaction, and local/global key routing.

The two items from the prior review by @davsclaus appear addressed:

  • Folder precedence is now correctly lastFolder > defaultFolder > user.dir (matching the docs), with lastFolderWinsOverDefaultFolder test confirming it.
  • #24541 dependency has been merged, and TuiUserConfig.livesInLocal() uses getProperty(key) != null with an explanatory comment.

One design concern worth discussing — see inline comment on SettingsPopup.java.

This review does not replace specialized AI review tools (CodeRabbit, Sourcery) or static analyzers (SonarCloud).

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of davsclaus

Address review feedback on PR apache#24545 (discussion_r3551915429): the Theme
row rendered all 15 ThemeMode ids inline via renderCycler(), overflowing
the ~44-char field and truncating most theme names.

Switch the Theme row to the same renderValue() pattern already used by
Starting Tab, and go further by wiring it into the live-preview machinery
ThemePopup already uses (Theme.preview/revertPreview/confirmPreview):
cycling the Theme row applies the theme instantly without closing the
dialog, Enter persists the previewed theme, Esc (or any global action
that dismisses all popups) reverts it.

Also fixes a pre-existing failing test, themeCyclerWrapsAroundValues,
which assumed only 2 themes existed; it now cycles through the full
ThemeMode count.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
gnodet added a commit to gnodet/camel that referenced this pull request Jul 9, 2026
Reviewed 3 PRs: apache#24566 (APPROVE, posted), apache#24565 (APPROVE, recorded),
apache#24545 (APPROVE after re-review, recorded). Updated skill to never
permanently skip CHANGES_REQUESTED PRs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…mes list

The doc had drifted from Theme.java's REQUIRED_TOKENS (27 -> 28,
missing the mnemonic token) and ThemeMode only listed dark/light
instead of all 15 registered themes.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>

@gnodet gnodet left a comment

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.

Re-reviewed after author addressed previous feedback. All three items from the prior review have been addressed:

  1. Folder precedence is now correctly lastFolder > defaultFolder > user.dir with the FolderInputPopupTest.lastFolderWinsOverDefaultFolder test covering it.
  2. #24541 dependency (OrderedProperties.containsKey) has been resolved — the code uses the getProperty(key) != null workaround with an explanatory comment.
  3. Theme rendering overflow — now uses renderValue() instead of renderCycler(), with live-preview during cycling matching ThemePopup behavior.

Test coverage is thorough: 7 new test files covering migration idempotency, settings round-trip, popup rendering, popup interaction, local/global key routing, folder precedence, and user config per-key routing. The TuiUserConfig per-key local/global routing design is clean — a key in the local file is treated as a project override and stays local, while personal preferences default to the global file.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

Claude Code on behalf of Guillaume Nodet

@davsclaus davsclaus added this to the 4.22.0 milestone Jul 9, 2026
@davsclaus davsclaus added the enhancement New feature or request label Jul 9, 2026
@davsclaus davsclaus merged commit 31c0a7e into apache:main Jul 9, 2026
6 checks passed
@ammachado ammachado deleted the CAMEL-23867 branch July 9, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants