Skip to content

add pager to describe config command #1203

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

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

samtholiya
Copy link
Collaborator

@samtholiya samtholiya commented Apr 14, 2025

what

  • We are adding pager from https://github.com/charmbracelet/bubbletea
  • --pager flag, ATMOS_PAGER env boolean variable added to enable/disable pager if required
  • Normal View
    image
  • Help View
    image
  • When user presses c to copy the contents
    image

why

  • Our demos do not render well without a pager. Everything scrolls by too fast.

references

Summary by CodeRabbit

  • New Features

    • Introduced a terminal pager for configuration output, providing a scrollable, full-screen view with navigation, copy, and help features.
    • Added support for configuring the pager via a new settings.terminal.pager string setting and ATMOS_PAGER environment variable.
    • Added a new persistent pager flag to the describe commands for controlling paging behavior.
  • Improvements

    • Enhanced error handling and output formatting for configuration commands, including typed query evaluation and explicit format validation.
    • Updated CLI flags and descriptions for improved clarity regarding pager behavior.
    • Refined configuration loading and pager enablement logic with a flexible string-based pager setting and a method to check if the pager is enabled.
    • Improved YAML and JSON output with syntax highlighting where possible.
  • Bug Fixes

    • Fixed issues related to pager usage and provided clear debug messages when pager activation fails.
  • Tests

    • Added comprehensive tests for pager functionality, configuration output handling, and error scenarios.
  • Chores

    • Updated dependencies to explicitly list required modules.

Copy link

codecov bot commented Apr 14, 2025

Codecov Report

Attention: Patch coverage is 42.36842% with 219 lines in your changes missing coverage. Please review.

Project coverage is 33.77%. Comparing base (f26dfe1) to head (8feface).

Files with missing lines Patch % Lines
pkg/pager/model.go 50.94% 103 Missing and 1 partial ⚠️
pkg/utils/yq_utils.go 0.00% 31 Missing ⚠️
cmd/describe_config.go 0.00% 23 Missing ⚠️
pkg/pager/pager.go 0.00% 18 Missing ⚠️
pkg/utils/json_utils.go 0.00% 15 Missing ⚠️
pkg/pager/mock_pager.go 0.00% 14 Missing ⚠️
internal/exec/describe_config.go 81.25% 6 Missing and 3 partials ⚠️
pkg/utils/yaml_utils.go 60.00% 3 Missing and 1 partial ⚠️
cmd/docs.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1203      +/-   ##
==========================================
+ Coverage   33.56%   33.77%   +0.20%     
==========================================
  Files         226      229       +3     
  Lines       24219    24563     +344     
==========================================
+ Hits         8130     8295     +165     
- Misses      14875    15049     +174     
- Partials     1214     1219       +5     
Flag Coverage Δ
unittests 33.77% <42.36%> (+0.20%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@samtholiya samtholiya force-pushed the feature/dev-3131-add-pager-to-atmos-describe-config-command branch from 6b4f627 to 39dd127 Compare April 14, 2025 23:12
@samtholiya samtholiya force-pushed the feature/dev-3131-add-pager-to-atmos-describe-config-command branch from 39dd127 to 180bc51 Compare April 15, 2025 19:44
@samtholiya samtholiya added the minor New features that do not break anything label Apr 15, 2025
@github-actions github-actions bot added size/l and removed size/m labels Apr 15, 2025
@osterman
Copy link
Member

osterman commented Apr 16, 2025

TODO:

  • Support PAGER env if set, then downgrade to normal behavior
  • Automatically disable pager functionality if no TTY attached
  • Support flag to disable pager

@samtholiya samtholiya force-pushed the feature/dev-3131-add-pager-to-atmos-describe-config-command branch 2 times, most recently from c52536d to 7de12fb Compare April 16, 2025 20:01
@samtholiya samtholiya marked this pull request as ready for review April 16, 2025 20:36
@samtholiya samtholiya requested a review from a team as a code owner April 16, 2025 20:36
Copy link
Contributor

coderabbitai bot commented Apr 16, 2025

📝 Walkthrough

Walkthrough

This change introduces a native pager UI for the atmos describe commands, leveraging the Bubble Tea framework. It adds a new pager package, integrates pager logic into the describe config command, and provides configuration options to enable or disable the pager via CLI flags, environment variables, or config files. The codebase now supports paged terminal output for configuration descriptions, with error handling for unsupported formats and TTY detection. Supporting utilities for JSON/YAML output and syntax highlighting are also updated. Tests and mocks are included for the new pager and describe logic.

Changes

Files / Paths Change Summary
cmd/describe.go, cmd/describe_config.go Added/renamed pager flag; refactored describeConfigCmd to use new pager logic, error handling, and config initialization.
internal/exec/describe_config.go, internal/exec/describe_config_test.go Refactored describe config execution into a struct with pager integration, added error types, modularized flow, and added unit tests.
pkg/pager/pager.go, pkg/pager/model.go, pkg/pager/model_test.go, pkg/pager/mock_pager.go Introduced new pager package with Bubble Tea-based UI, model logic, tests, and GoMock-generated mock.
pkg/config/load.go Added support for settings.terminal.pager config and ATMOS_PAGER env var.
pkg/utils/json_utils.go, pkg/utils/yaml_utils.go, pkg/utils/yq_utils.go Added/updated helpers for config output formatting, highlighting, and typed YQ evaluation.
go.mod Promoted Bubble Tea and related dependencies to direct requirements.
tests/snapshots/..., tests/test-cases/demo-stacks.yaml Updated test snapshots and cases to reflect pager config and debug output changes.
cmd/docs.go Changed pager flag access to use IsPagerEnabled() method with fallback and deprecation warning.
pkg/schema/schema.go, pkg/schema/schema_test.go, pkg/config/default.go Changed Terminal.Pager from bool to string; added IsPagerEnabled() method and tests; updated default pager value.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI
    participant ConfigLoader
    participant Pager
    participant Terminal

    User->>CLI: Run `atmos describe config`
    CLI->>ConfigLoader: Load config, parse flags/env
    ConfigLoader-->>CLI: Return config, check pager enabled
    CLI->>Pager: If pager enabled, call Pager.Run(title, content)
    Pager->>Terminal: Render content in Bubble Tea UI
    Terminal-->>Pager: User navigation/copy/quit
    Pager-->>CLI: Return on exit
    CLI->>User: Show output or errors
Loading

Assessment against linked issues

Objective (Issue) Addressed Explanation
Implement native pager for all atmos describe commands and --help commands (DEV-2958)
Pager should only load if content exceeds max height of the TTY (DEV-2958)
Pager should support forcing color via config or ENV (DEV-2958)

Suggested reviewers

  • osterman
  • aknysh

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4ec621 and 8feface.

📒 Files selected for processing (8)
  • go.mod (2 hunks)
  • pkg/config/default.go (1 hunks)
  • pkg/config/load.go (2 hunks)
  • pkg/schema/schema.go (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_-f_yaml.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stdout.golden (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden
🚧 Files skipped from review as they are similar to previous changes (7)
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stdout.golden
  • pkg/config/default.go
  • pkg/config/load.go
  • tests/snapshots/TestCLICommands_atmos_describe_config_-f_yaml.stdout.golden
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stdout.golden
  • pkg/schema/schema.go
  • go.mod
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • 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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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 or @auto-summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @auto-title anywhere in the PR title to generate the title automatically.

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.

Copy link
Contributor

@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: 3

🔭 Outside diff range comments (1)
pkg/pager/pager.go (1)

1-38: 🛠️ Refactor suggestion

Add test coverage for the pager implementation

The static analysis shows no test coverage for this file. Consider adding tests to verify the pager functionality, especially since it's a core user-facing feature.

#!/bin/bash
# Check if there are any tests for the pager
rg "TestPager|pager.*test" --type go
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 17-20: pkg/pager/pager.go#L17-L20
Added lines #L17 - L20 were not covered by tests


[warning] 23-36: pkg/pager/pager.go#L23-L36
Added lines #L23 - L36 were not covered by tests

🧹 Nitpick comments (9)
pkg/utils/json_utils.go (1)

38-56: Solid implementation of GetAtmosConfigJSON function

The function properly handles JSON conversion, indentation, and highlighting with appropriate error handling. The two code paths (highlighted or fallback to plain text) are clear and maintainable.

A small improvement would be to add test coverage for this function since static analysis shows it's not currently covered.

#!/bin/bash
# Check if there are any tests for this function
rg "TestGetAtmosConfigJSON|func.*GetAtmosConfigJSON.*test" --type go
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 38-42: pkg/utils/json_utils.go#L38-L42
Added lines #L38 - L42 were not covered by tests


[warning] 44-48: pkg/utils/json_utils.go#L44-L48
Added lines #L44 - L48 were not covered by tests


[warning] 50-53: pkg/utils/json_utils.go#L50-L53
Added lines #L50 - L53 were not covered by tests


[warning] 55-55: pkg/utils/json_utils.go#L55
Added line #L55 was not covered by tests

pkg/utils/yaml_utils.go (1)

52-63: GetAtmosConfigYAML implementation is solid

The function follows the same pattern as GetAtmosConfigJSON with proper error handling. The key difference is that on highlighting error, this function returns the original YAML with the error instead of swallowing the error and proceeding with plain text.

Consider adding test coverage for this function.

#!/bin/bash
# Check if there are any tests for this function
rg "TestGetAtmosConfigYAML|func.*GetAtmosConfigYAML.*test" --type go
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 55-56: pkg/utils/yaml_utils.go#L55-L56
Added lines #L55 - L56 were not covered by tests


[warning] 60-60: pkg/utils/yaml_utils.go#L60
Added line #L60 was not covered by tests

cmd/describe_config.go (1)

19-50: Improved error handling with RunE implementation

The change from Run to RunE with explicit error handling for each step is a significant improvement. The code now properly initializes the CLI config, checks flags, and propagates errors.

Consider adding tests for this command execution path since static analysis shows no coverage.

#!/bin/bash
# Check if there are any tests for this command
rg "TestDescribeConfigCmd|describe_config.*test" --type go
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 19-25: cmd/describe_config.go#L19-L25
Added lines #L19 - L25 were not covered by tests


[warning] 27-30: cmd/describe_config.go#L27-L30
Added lines #L27 - L30 were not covered by tests


[warning] 32-35: cmd/describe_config.go#L32-L35
Added lines #L32 - L35 were not covered by tests


[warning] 37-42: cmd/describe_config.go#L37-L42
Added lines #L37 - L42 were not covered by tests


[warning] 45-45: cmd/describe_config.go#L45
Added line #L45 was not covered by tests


[warning] 49-49: cmd/describe_config.go#L49
Added line #L49 was not covered by tests

pkg/pager/pager.go (1)

23-37: Concise Run implementation with proper error handling

The Run method is straightforward and handles errors appropriately. The use of tea.WithAltScreen() and tea.WithMouseCellMotion() options provides a good user experience.

Consider adding a context parameter for cancellation support, as UI operations might run for extended periods.

-func (p *pageCreator) Run(title, content string) error {
+func (p *pageCreator) Run(ctx context.Context, title, content string) error {
 	if _, err := p.newTeaProgram(
 		&model{
 			title:    title,
 			content:  content,
 			ready:    false,
 			viewport: viewport.New(0, 0),
 		},
 		tea.WithAltScreen(),       // use the full size of the terminal in its "alternate screen buffer"
 		tea.WithMouseCellMotion(), // turn on mouse support so we can track the mouse wheel
+		tea.WithContext(ctx),      // add context support for cancellation
 	).Run(); err != nil {
 		return err
 	}
 	return nil
}
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 23-36: pkg/pager/pager.go#L23-L36
Added lines #L23 - L36 were not covered by tests

internal/exec/describe_config_test.go (1)

98-112: Test case name doesn't match implementation

The test case name suggests it's testing query functionality, but it appears to be testing the same scenario as the NoQuery_NoTTY test with an empty query string.

Consider renaming this test case to better reflect what it's actually testing, or update the test to include a meaningful query expression.

pkg/pager/model_test.go (1)

157-160: Error message has a typo

The assertion message states "max(3, 5) should return 3" but it should say "max(3, 5) should return 5".

-		assert.Equal(t, 5, result, "max(3, 5) should return 3")
+		assert.Equal(t, 5, result, "max(3, 5) should return 5")
pkg/pager/model.go (1)

54-64: Consider documenting viewport limitations

While the implementation is sound, the viewport doesn't reflow content after it's set. This is likely a limitation of the viewport component itself.

Consider adding a brief comment about this limitation for future developers working with this code.

internal/exec/describe_config.go (2)

23-24: Prefer errors.New for static error values

fmt.Errorf incurs the (tiny) formatting overhead that is unnecessary for a constant‑string error. Swapping to errors.New keeps the intent clear and is consistent with other static error declarations in the code‑base.

-import "fmt"
+import (
+	"errors"
+	"fmt"
 ...

-var ErrTTYNotSupported = fmt.Errorf("tty not supported for this command")
+var ErrTTYNotSupported = errors.New("tty not supported for this command")

71-83: Exercise the error branches in tests

codecov points out that the YAML/JSON conversion error paths (L77‑78, 82‑83) and the pager failure branch (L90‑91) are not covered.
Adding unit tests that stub GetAtmosConfigYAML/JSON and pageCreator.Run to return errors will:

  • lock‑in the fallback behaviour you intend, and
  • keep coverage above the project threshold.

Happy to help draft the tests if you’d like.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 77-78: internal/exec/describe_config.go#L77-L78
Added lines #L77 - L78 were not covered by tests


[warning] 82-83: internal/exec/describe_config.go#L82-L83
Added lines #L82 - L83 were not covered by tests

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a62050b and 7de12fb.

📒 Files selected for processing (17)
  • cmd/describe.go (1 hunks)
  • cmd/describe_config.go (2 hunks)
  • internal/exec/describe_config.go (1 hunks)
  • internal/exec/describe_config_test.go (1 hunks)
  • pkg/config/load.go (2 hunks)
  • pkg/pager/mock_pager.go (1 hunks)
  • pkg/pager/model.go (1 hunks)
  • pkg/pager/model_test.go (1 hunks)
  • pkg/pager/pager.go (1 hunks)
  • pkg/schema/schema.go (1 hunks)
  • pkg/utils/json_utils.go (1 hunks)
  • pkg/utils/yaml_utils.go (1 hunks)
  • pkg/utils/yq_utils.go (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_-f_yaml.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stdout.golden (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
pkg/utils/yq_utils.go (2)
pkg/schema/schema.go (1)
  • AtmosConfiguration (13-46)
pkg/utils/yaml_utils.go (2)
  • ConvertToYAML (89-95)
  • UnmarshalYAML (222-224)
pkg/pager/model.go (2)
internal/tui/components/code_view/main.go (1)
  • Model (11-16)
pkg/pager/pager.go (1)
  • New (17-21)
🪛 GitHub Check: codecov/patch
pkg/utils/json_utils.go

[warning] 38-42: pkg/utils/json_utils.go#L38-L42
Added lines #L38 - L42 were not covered by tests


[warning] 44-48: pkg/utils/json_utils.go#L44-L48
Added lines #L44 - L48 were not covered by tests


[warning] 50-53: pkg/utils/json_utils.go#L50-L53
Added lines #L50 - L53 were not covered by tests


[warning] 55-55: pkg/utils/json_utils.go#L55
Added line #L55 was not covered by tests

pkg/utils/yq_utils.go

[warning] 82-91: pkg/utils/yq_utils.go#L82-L91
Added lines #L82 - L91 were not covered by tests


[warning] 93-108: pkg/utils/yq_utils.go#L93-L108
Added lines #L93 - L108 were not covered by tests


[warning] 110-113: pkg/utils/yq_utils.go#L110-L113
Added lines #L110 - L113 were not covered by tests


[warning] 115-115: pkg/utils/yq_utils.go#L115
Added line #L115 was not covered by tests

cmd/describe_config.go

[warning] 19-25: cmd/describe_config.go#L19-L25
Added lines #L19 - L25 were not covered by tests


[warning] 27-30: cmd/describe_config.go#L27-L30
Added lines #L27 - L30 were not covered by tests


[warning] 32-35: cmd/describe_config.go#L32-L35
Added lines #L32 - L35 were not covered by tests


[warning] 37-42: cmd/describe_config.go#L37-L42
Added lines #L37 - L42 were not covered by tests


[warning] 45-45: cmd/describe_config.go#L45
Added line #L45 was not covered by tests


[warning] 49-49: cmd/describe_config.go#L49
Added line #L49 was not covered by tests

pkg/pager/pager.go

[warning] 17-20: pkg/pager/pager.go#L17-L20
Added lines #L17 - L20 were not covered by tests


[warning] 23-36: pkg/pager/pager.go#L23-L36
Added lines #L23 - L36 were not covered by tests

pkg/utils/yaml_utils.go

[warning] 55-56: pkg/utils/yaml_utils.go#L55-L56
Added lines #L55 - L56 were not covered by tests


[warning] 60-60: pkg/utils/yaml_utils.go#L60
Added line #L60 was not covered by tests

internal/exec/describe_config.go

[warning] 77-78: internal/exec/describe_config.go#L77-L78
Added lines #L77 - L78 were not covered by tests


[warning] 82-83: internal/exec/describe_config.go#L82-L83
Added lines #L82 - L83 were not covered by tests


[warning] 90-91: internal/exec/describe_config.go#L90-L91
Added lines #L90 - L91 were not covered by tests

pkg/pager/mock_pager.go

[warning] 25-28: pkg/pager/mock_pager.go#L25-L28
Added lines #L25 - L28 were not covered by tests


[warning] 32-33: pkg/pager/mock_pager.go#L32-L33
Added lines #L32 - L33 were not covered by tests


[warning] 37-41: pkg/pager/mock_pager.go#L37-L41
Added lines #L37 - L41 were not covered by tests


[warning] 45-47: pkg/pager/mock_pager.go#L45-L47
Added lines #L45 - L47 were not covered by tests

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Summary
🔇 Additional comments (19)
tests/snapshots/TestCLICommands_atmos_describe_configuration.stdout.golden (1)

63-63: LGTM: Configuration update for pager feature

The addition of disable_pager: false is consistent with the PR's objective to implement a pager feature. This default value ensures the pager is enabled by default.

tests/snapshots/TestCLICommands_atmos_describe_config_imports.stdout.golden (1)

168-168: LGTM: Configuration update for pager feature

The addition of disable_pager: false properly reflects the default state of the pager feature in configuration imports. This maintains consistency with the core configuration structure.

tests/snapshots/TestCLICommands_atmos_describe_config_-f_yaml.stdout.golden (1)

50-50: LGTM: Configuration update for pager feature

The addition of disable_pager: false in the YAML output format is consistent with the other configuration snapshots and correctly reflects the default pager behavior.

tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1)

155-156: Configuration update for pager feature looks good.

The new disable_pager field with default value false has been properly added to the configuration snapshot, maintaining the overall structure of the configuration and supporting the new pager functionality.

pkg/schema/schema.go (1)

45-45: Clean schema implementation for the DisablePager field.

The new DisablePager field is properly tagged for all serialization formats and follows the established naming conventions of the codebase. This field allows the pager feature to be controlled via configuration files, CLI flags, and environment variables.

cmd/describe.go (1)

18-18: Good CLI flag implementation.

The disable-pager flag is properly added as a persistent flag to make it available across all describe subcommands. The default value of false ensures paging is enabled by default, which aligns with the PR objectives to improve demo readability.

pkg/config/load.go (2)

104-104: Environment variable binding looks correct.

The ATMOS_DISABLE_PAGER environment variable is properly bound to the disable_pager configuration key, following the established pattern for environment variable configuration in the codebase.


122-122: Default configuration value is appropriate.

Setting the default value to false ensures that the pager is enabled by default, which aligns with the PR objective to improve rendering of demos through paging.

pkg/utils/yaml_utils.go (1)

43-50: Good refactoring of PrintAsYAML

The refactoring simplifies the function by delegating the detailed implementation to the new GetAtmosConfigYAML function. Excellent separation of concerns.

pkg/pager/pager.go (2)

8-11: Good use of interface for PageCreator

Defining a PageCreator interface with a single Run method makes the code more testable and facilitates mocking. The go:generate directive for mockgen is a nice touch to automate mock generation.


13-21: Effective dependency injection pattern

The pageCreator struct uses dependency injection by accepting a tea program creation function. This approach makes the code more testable by allowing the injection of mock implementations.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 17-20: pkg/pager/pager.go#L17-L20
Added lines #L17 - L20 were not covered by tests

internal/exec/describe_config_test.go (3)

17-33: Good test structure and coverage

The test function covers the creation of a new describe config executor and verifies core dependencies are properly initialized.


34-50: Excellent TTY handling test case

Good test for YAML output with proper TTY support. The mock expectations are clear and the test verifies that the pager is used when TTY is available.


114-123: Good error handling test

Properly verifies that malformed query expressions return appropriate errors with descriptive messages.

pkg/pager/mock_pager.go (1)

1-48: LGTM - Auto-generated mock

This mock was correctly generated by MockGen and follows standard Go mock patterns. The warnings about code coverage can be ignored as this is an auto-generated file designed for testing purposes.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 25-28: pkg/pager/mock_pager.go#L25-L28
Added lines #L25 - L28 were not covered by tests


[warning] 32-33: pkg/pager/mock_pager.go#L32-L33
Added lines #L32 - L33 were not covered by tests


[warning] 37-41: pkg/pager/mock_pager.go#L37-L41
Added lines #L37 - L41 were not covered by tests


[warning] 45-47: pkg/pager/mock_pager.go#L45-L47
Added lines #L45 - L47 were not covered by tests

pkg/pager/model_test.go (1)

21-82: Comprehensive Update method tests

Good test coverage for all relevant message types and state transitions in the Update method, including key events, window sizing, and viewport updates.

pkg/pager/model.go (3)

26-35: Well-structured pager model

The model struct and Init method are correctly implemented, following Bubble Tea conventions with pointer receivers to satisfy the tea.Model interface.


37-75: Good handling of window resize events

The Update method correctly handles initialization and resize events, with proper delegation to the viewport component for keyboard and mouse events.

You're correctly using pointer receivers for the model methods, which addresses the previously flagged "hugeParam" static analysis warnings.


77-82: Clean, concise View implementation

The View method properly composes the UI with header, content, and footer while handling the uninitialized state.

@github-actions github-actions bot added size/xl and removed size/l labels Apr 20, 2025
Copy link

mergify bot commented Apr 20, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@samtholiya samtholiya force-pushed the feature/dev-3131-add-pager-to-atmos-describe-config-command branch from e885be7 to f557e06 Compare April 20, 2025 16:11
Copy link
Contributor

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (3)
pkg/pager/err.go (1)

5-5: Delegated Error() implementation
The Error() method properly satisfies the error interface by forwarding to the wrapped error’s Error(). For extra clarity, you might add a brief GoDoc comment above the method to explain its intent.

pkg/utils/utils.go (2)

17-32: Consider supporting additional frontmatter formats

The implementation correctly detects and removes YAML frontmatter, but only handles the YAML format (using --- delimiters). You might want to consider supporting other common frontmatter formats like TOML (using +++) or JSON (using {}), especially if your project supports multiple document formats.


25-26: Add a descriptive comment for the regex pattern

It would be helpful to add a comment explaining what the regex pattern is matching - YAML frontmatter boundaries with optional whitespace.

-var yamlPattern = regexp.MustCompile(`(?m)^---\r?\n(\s*\r?\n)?`)
+// yamlPattern matches YAML frontmatter boundaries (---) at the beginning of a line with optional whitespace
+var yamlPattern = regexp.MustCompile(`(?m)^---\r?\n(\s*\r?\n)?`)
🛑 Comments failed to post (2)
pkg/utils/utils.go (2)

34-41: 🛠️ Refactor suggestion

Error handling could be improved in ExpandPath

The function silently ignores errors from homedir.Expand and falls back to using the original path. Consider either:

  1. Returning the error to let callers handle it appropriately
  2. Logging the error before fallback
  3. Adding a comment explaining the fallback behavior

This would make the error handling strategy more explicit and maintainable.


72-107: ⚠️ Potential issue

Bug: TokyoNightStyle uses DraculaStyleConfig

There's a bug on line 104-105: TokyoNightStyle is using DraculaStyleConfig instead of its own configuration. This should be fixed.

case styles.TokyoNightStyle:
-	styleConfig = styles.DraculaStyleConfig
+	styleConfig = styles.TokyoNightStyleConfig
📝 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.

// GlamourStyle returns a glamour.TermRendererOption based on the given style.
func GlamourStyle(style string, isCode bool) glamour.TermRendererOption {
	if !isCode {
		if style == styles.AutoStyle {
			return glamour.WithAutoStyle()
		}
		return glamour.WithStylePath(style)
	}

	// If we are rendering a pure code block, we need to modify the style to
	// remove the indentation.

	var styleConfig ansi.StyleConfig

	switch style {
	case styles.AutoStyle:
		if lipgloss.HasDarkBackground() {
			styleConfig = styles.DarkStyleConfig
		} else {
			styleConfig = styles.LightStyleConfig
		}
	case styles.DarkStyle:
		styleConfig = styles.DarkStyleConfig
	case styles.LightStyle:
		styleConfig = styles.LightStyleConfig
	case styles.PinkStyle:
		styleConfig = styles.PinkStyleConfig
	case styles.NoTTYStyle:
		styleConfig = styles.NoTTYStyleConfig
	case styles.DraculaStyle:
		styleConfig = styles.DraculaStyleConfig
	case styles.TokyoNightStyle:
-		styleConfig = styles.DraculaStyleConfig
+		styleConfig = styles.TokyoNightStyleConfig
	default:
		return glamour.WithStylesFromJSONFile(style)
	}

	// ...rest of function...
}

Copy link
Contributor

@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: 3

♻️ Duplicate comments (1)
pkg/pager/model.go (1)

256-256: 🛠️ Refactor suggestion

Use pointer receiver for large struct method.

The helpView method uses a value receiver, but the model struct is large (approximately 1280 bytes). Using a pointer receiver would be more efficient as it avoids copying the entire struct.

-func (m model) helpView() (s string) {
+func (m *model) helpView() (s string) {
🧰 Tools
🪛 GitHub Check: golangci-lint

[failure] 256-256:
hugeParam: m is heavy (1280 bytes); consider passing it by pointer

🧹 Nitpick comments (7)
pkg/utils/utils.go (3)

25-32: Consider adding a comment to explain return values.

The detectFrontmatter helper function would benefit from a comment explaining what the returned indices represent, especially the -1, -1 case.

-func detectFrontmatter(c []byte) []int {
+// detectFrontmatter locates YAML frontmatter boundaries in content.
+// Returns [start, end] indices of the frontmatter section.
+// Returns [-1, -1] when no frontmatter is detected.
+func detectFrontmatter(c []byte) []int {

52-70: Document the default assumption for files without extensions.

The function assumes files without extensions are markdown files. This behavior should be explicitly documented.

-// IsMarkdownFile returns whether the filename has a markdown extension.
+// IsMarkdownFile returns whether the filename has a markdown extension.
+// Files without extensions are assumed to be markdown files by default.

72-113: Reduce cyclomatic complexity in GlamourStyle function.

The static analysis tool flagged this function as having too high cyclomatic complexity (12 > 10). Consider refactoring it to separate the style selection logic into a helper function.

func GlamourStyle(style string, isCode bool) glamour.TermRendererOption {
	if !isCode {
		if style == styles.AutoStyle {
			return glamour.WithAutoStyle()
		}
		return glamour.WithStylePath(style)
	}

	// If we are rendering a pure code block, we need to modify the style to
	// remove the indentation.

+	styleConfig := getStyleConfig(style)
+	var margin uint
+	styleConfig.CodeBlock.Margin = &margin
+
+	return glamour.WithStyles(styleConfig)
+}
+
+// getStyleConfig returns the appropriate style configuration based on the style name
+func getStyleConfig(style string) ansi.StyleConfig {
	var styleConfig ansi.StyleConfig

	switch style {
	case styles.AutoStyle:
		if lipgloss.HasDarkBackground() {
			styleConfig = styles.DarkStyleConfig
		} else {
			styleConfig = styles.LightStyleConfig
		}
	case styles.DarkStyle:
		styleConfig = styles.DarkStyleConfig
	case styles.LightStyle:
		styleConfig = styles.LightStyleConfig
	case styles.PinkStyle:
		styleConfig = styles.PinkStyleConfig
	case styles.NoTTYStyle:
		styleConfig = styles.NoTTYStyleConfig
	case styles.DraculaStyle:
		styleConfig = styles.DraculaStyleConfig
	case styles.TokyoNightStyle:
		styleConfig = styles.TokyoNightStyleConfig
	default:
-		return glamour.WithStylesFromJSONFile(style)
+		// Return empty config for custom JSON styles
+		// This will be handled in the calling function
+		return styleConfig
	}

-	var margin uint
-	styleConfig.CodeBlock.Margin = &margin
-
-	return glamour.WithStyles(styleConfig)
+	return styleConfig

After this refactoring, you'll need to handle the custom JSON case specially in the GlamourStyle function:

func GlamourStyle(style string, isCode bool) glamour.TermRendererOption {
	if !isCode {
		if style == styles.AutoStyle {
			return glamour.WithAutoStyle()
		}
		return glamour.WithStylePath(style)
	}

	// If we are rendering a pure code block, we need to modify the style to
	// remove the indentation.

	styleConfig := getStyleConfig(style)
+	// Handle custom JSON style case
+	if style != styles.AutoStyle && 
+	   style != styles.DarkStyle && 
+	   style != styles.LightStyle && 
+	   style != styles.PinkStyle && 
+	   style != styles.NoTTYStyle && 
+	   style != styles.DraculaStyle && 
+	   style != styles.TokyoNightStyle {
+		return glamour.WithStylesFromJSONFile(style)
+	}
+
	var margin uint
	styleConfig.CodeBlock.Margin = &margin

	return glamour.WithStyles(styleConfig)
}
🧰 Tools
🪛 GitHub Check: golangci-lint

[failure] 73-73:
cyclomatic: function GlamourStyle has cyclomatic complexity 12 (> max enabled 10)

pkg/pager/model.go (4)

51-51: Clean up unused style variables.

The code defines styling variables that aren't referenced anywhere in the implementation. Clean up the codebase by removing these unused variables.

-var (
-	lineNumberFg = lipgloss.AdaptiveColor{Light: "#656565", Dark: "#7D7D7D"}
-
-	statusBarNoteFg = lipgloss.AdaptiveColor{Light: "#656565", Dark: "#7D7D7D"}
+var (
+	statusBarNoteFg = lipgloss.AdaptiveColor{Light: "#656565", Dark: "#7D7D7D"}
-	lineNumberStyle = lipgloss.NewStyle().
-			Foreground(lineNumberFg).
-			Render
	green = lipgloss.Color("#04B575")

Also applies to: 86-88

🧰 Tools
🪛 golangci-lint (1.64.8)

[error] 51-51: var lineNumberFg is unused

(unused)

🪛 GitHub Check: golangci-lint

[failure] 51-51:
var lineNumberFg is unused


94-94: Remove unused field.

The cwd field in the commonModel struct isn't used anywhere in the implementation.

// Common stuff we'll need to access in all models.
type commonModel struct {
-	cwd    string
	width  int
	height int
}
🧰 Tools
🪛 golangci-lint (1.64.8)

[error] 94-94: field cwd is unused

(unused)

🪛 GitHub Check: golangci-lint

[failure] 94-94:
field cwd is unused


267-271: Create a constant for newline characters.

The string literal "\n" appears multiple times. Create a named constant for better readability and maintenance.

+const (
+	// existing constants
+	newLine = "\n"
+)

// In helpView method:
-s += "\n"
-s += "k/↑      up                  " + col1[0] + "\n"
-s += "j/↓      down                " + col1[1] + "\n"
-s += "b/pgup   page up             " + col1[2] + "\n"
-s += "f/pgdn   page down           " + col1[3] + "\n"
-s += "u        ½ page up           " + col1[4] + "\n"
+s += newLine
+s += "k/↑      up                  " + col1[0] + newLine
+s += "j/↓      down                " + col1[1] + newLine
+s += "b/pgup   page up             " + col1[2] + newLine
+s += "f/pgdn   page down           " + col1[3] + newLine
+s += "u        ½ page up           " + col1[4] + newLine
🧰 Tools
🪛 golangci-lint (1.64.8)

[error] 267-267: add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it

(revive)

🪛 GitHub Check: golangci-lint

[failure] 267-267:
add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it


303-367: Refactor the statusBarView method for better maintainability.

This method exceeds the recommended length of 60 lines. Consider breaking it down into smaller, focused functions.

// Refactor into smaller functions:
func (m *model) statusBarView(b *strings.Builder) {
	showStatusMessage := m.state == pagerStateStatusMessage
+	
+	scrollPercent := m.renderScrollPercent(showStatusMessage)
+	note := m.renderNote(showStatusMessage)
+	helpNote := m.renderHelpNote(showStatusMessage)
+	emptySpace := m.renderEmptySpace(showStatusMessage, scrollPercent, note, helpNote)
+
+	fmt.Fprintf(b, "%s%s%s%s%s",
+		logo,
+		note,
+		emptySpace,
+		scrollPercent,
+		helpNote,
+	)
+	if m.showHelp {
+		fmt.Fprint(b, "\n"+m.helpView())
+	}
}

+func (m *model) renderScrollPercent(showStatusMessage bool) string {
+	percent := math.Max(minPercent, math.Min(maxPercent, m.viewport.ScrollPercent()))
+	scrollPercent := fmt.Sprintf(" %3.f%% ", percent*percentToStringMagnitude)
+	if showStatusMessage {
+		return statusBarMessageScrollPosStyle(scrollPercent)
+	}
+	return statusBarNoteStyle(scrollPercent)
+}
🧰 Tools
🪛 golangci-lint (1.64.8)

[error] 303-303: function-length: maximum number of lines per function exceeded; max 60 but got 63

(revive)

🪛 GitHub Check: golangci-lint

[failure] 303-303:
function-length: maximum number of lines per function exceeded; max 60 but got 63

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e885be7 and 68c3e83.

📒 Files selected for processing (5)
  • go.mod (2 hunks)
  • pkg/pager/err.go (1 hunks)
  • pkg/pager/model.go (1 hunks)
  • pkg/pager/model_test.go (1 hunks)
  • pkg/utils/utils.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • go.mod
  • pkg/pager/model_test.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
pkg/utils/utils.go (1)
pkg/config/go-homedir/homedir.go (1)
  • Expand (68-87)
🪛 golangci-lint (1.64.8)
pkg/pager/model.go

[error] 51-51: var lineNumberFg is unused

(unused)


[error] 86-86: var lineNumberStyle is unused

(unused)


[error] 94-94: field cwd is unused

(unused)


[error] 267-267: add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it

(revive)


[error] 303-303: function-length: maximum number of lines per function exceeded; max 60 but got 63

(revive)

pkg/pager/err.go

[error] 3-3: type errMsg is unused

(unused)


[error] 5-5: func errMsg.Error is unused

(unused)

🪛 GitHub Check: golangci-lint
pkg/pager/model.go

[failure] 45-45:
Comment should end in a period


[failure] 51-51:
var lineNumberFg is unused


[failure] 86-86:
var lineNumberStyle is unused


[failure] 94-94:
field cwd is unused


[failure] 256-256:
hugeParam: m is heavy (1280 bytes); consider passing it by pointer


[failure] 267-267:
add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it


[failure] 303-303:
function-length: maximum number of lines per function exceeded; max 60 but got 63

pkg/pager/err.go

[failure] 3-3:
type errMsg is unused


[failure] 5-5:
func errMsg.Error is unused

pkg/utils/utils.go

[failure] 73-73:
cyclomatic: function GlamourStyle has cyclomatic complexity 12 (> max enabled 10)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (4)
pkg/utils/utils.go (2)

17-23: Good modular design for frontmatter removal.

This function cleanly separates the responsibility of detecting frontmatter from actually removing it, making the code more maintainable.


34-41: Well-implemented path expansion.

This function effectively handles both tilde expansion and environment variables, with a good fallback mechanism when tilde expansion fails.

pkg/pager/model.go (2)

113-124: Good model structure with clear separation of concerns.

The model struct is well-organized with fields for content, state management, and UI components. This makes the code more maintainable and easier to understand.


137-194: Well-implemented Update method with good event handling.

The Update method clearly handles different types of messages and provides appropriate responses, including keyboard navigation, viewport updates, and message passing. The workflow for each event type is logically structured.

@samtholiya samtholiya force-pushed the feature/dev-3131-add-pager-to-atmos-describe-config-command branch from 68c3e83 to 7e40baf Compare April 20, 2025 16:27
Copy link
Contributor

@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: 2

♻️ Duplicate comments (5)
pkg/pager/err.go (1)

3-5: 🛠️ Refactor suggestion

Add documentation to explain the purpose of this error type.

This error message type is likely intended for use with the Bubble Tea framework's message passing system. To avoid static analysis warnings and make the code more maintainable, you should add documentation explaining its purpose.

 package pager

+// errMsg is an error message type designed to be used with the Bubble Tea framework.
+// It wraps a standard error and is used to propagate errors through the Bubble Tea update cycle.
 type errMsg struct{ err error }

 func (e errMsg) Error() string { return e.err.Error() }

If this error type is indeed not used anywhere in the codebase, consider removing it entirely to maintain clean code.

🧰 Tools
🪛 golangci-lint (1.64.8)

[error] 3-3: type errMsg is unused

(unused)


[error] 5-5: func errMsg.Error is unused

(unused)

🪛 GitHub Check: golangci-lint

[failure] 3-3:
type errMsg is unused


[failure] 5-5:
func errMsg.Error is unused

pkg/pager/model.go (2)

154-157: Handle clipboard write errors.

The current implementation ignores potential errors when writing to the clipboard. While it might be acceptable to continue if clipboard access fails, you should at least log the error for diagnostic purposes.

// Copy using OSC 52
termenv.Copy(StripANSI(m.content))
// Copy using native system clipboard
-_ = clipboard.WriteAll(StripANSI(m.content))
+if err := clipboard.WriteAll(StripANSI(m.content)); err != nil {
+	cmds = append(cmds, m.showStatusMessage(pagerStatusMessage{"Failed to copy to clipboard", true}))
+} else {
+	cmds = append(cmds, m.showStatusMessage(pagerStatusMessage{"Copied contents", false}))
+}
-cmds = append(cmds, m.showStatusMessage(pagerStatusMessage{"Copied contents", false}))

256-256: 🛠️ Refactor suggestion

Pass large struct by pointer.

The helpView method takes a large struct (1280 bytes) by value, which can be inefficient. Consider changing it to use a pointer receiver to avoid unnecessary copying.

-func (m model) helpView() (s string) {
+func (m *model) helpView() (s string) {
🧰 Tools
🪛 GitHub Check: golangci-lint

[failure] 256-256:
hugeParam: m is heavy (1280 bytes); consider passing it by pointer

pkg/utils/utils.go (2)

73-113: Refactor GlamourStyle to reduce complexity.

This function has high cyclomatic complexity (12) which exceeds the maximum threshold (10). Consider refactoring to reduce complexity, perhaps by extracting the style selection into a separate function.

-// GlamourStyle returns a glamour.TermRendererOption based on the given style.
-func GlamourStyle(style string, isCode bool) glamour.TermRendererOption {
+// GlamourStyle returns a glamour.TermRendererOption based on the given style.
+func GlamourStyle(style string, isCode bool) glamour.TermRendererOption {
+	if !isCode {
+		if style == styles.AutoStyle {
+			return glamour.WithAutoStyle()
+		}
+		return glamour.WithStylePath(style)
+	}
+	
+	// For code blocks, get the style config and customize it
+	styleConfig := getStyleConfig(style)
+	var margin uint
+	styleConfig.CodeBlock.Margin = &margin
+	
+	return glamour.WithStyles(styleConfig)
+}
+
+// getStyleConfig returns the appropriate style configuration based on the style name
+func getStyleConfig(style string) ansi.StyleConfig {
 	if !isCode {
 		if style == styles.AutoStyle {
 			return glamour.WithAutoStyle()
 		}
 		return glamour.WithStylePath(style)
 	}

 	// If we are rendering a pure code block, we need to modify the style to
 	// remove the indentation.

 	var styleConfig ansi.StyleConfig

 	switch style {
 	case styles.AutoStyle:
 		if lipgloss.HasDarkBackground() {
 			styleConfig = styles.DarkStyleConfig
 		} else {
 			styleConfig = styles.LightStyleConfig
 		}
 	case styles.DarkStyle:
 		styleConfig = styles.DarkStyleConfig
 	case styles.LightStyle:
 		styleConfig = styles.LightStyleConfig
 	case styles.PinkStyle:
 		styleConfig = styles.PinkStyleConfig
 	case styles.NoTTYStyle:
 		styleConfig = styles.NoTTYStyleConfig
 	case styles.DraculaStyle:
 		styleConfig = styles.DraculaStyleConfig
 	case styles.TokyoNightStyle:
-		styleConfig = styles.DraculaStyleConfig
+		styleConfig = styles.TokyoNightStyleConfig
 	default:
-		return glamour.WithStylesFromJSONFile(style)
+		return ansi.StyleConfig{}
 	}
-
-	var margin uint
-	styleConfig.CodeBlock.Margin = &margin
-
-	return glamour.WithStyles(styleConfig)
+	return styleConfig
 }
🧰 Tools
🪛 GitHub Check: golangci-lint

[failure] 73-73:
cyclomatic: function GlamourStyle has cyclomatic complexity 12 (> max enabled 10)


104-104: ⚠️ Potential issue

Fix incorrect style configuration for TokyoNightStyle.

There appears to be a copy-paste error - TokyoNightStyle is using the Dracula style configuration.

-	styleConfig = styles.DraculaStyleConfig
+	styleConfig = styles.TokyoNightStyleConfig
🧹 Nitpick comments (2)
pkg/pager/model.go (2)

45-45: Add a period to the comment for consistency.

Every comment should end with a period for consistent code documentation style.

-// Logo
+// Logo.
🧰 Tools
🪛 GitHub Check: golangci-lint

[failure] 45-45:
Comment should end in a period


267-271: Create a constant for recurring newline character.

The string literal "\n" appears multiple times in the code. Create a named constant for better maintainability.

+const (
+	// Existing constants...
+	newline = "\n"
+)

// Then throughout the code:
-s += "\n"
+s += newline
-s += "k/↑      up                  " + col1[0] + "\n"
+s += "k/↑      up                  " + col1[0] + newline
// And so on for other instances
🧰 Tools
🪛 golangci-lint (1.64.8)

[error] 267-267: add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it

(revive)

🪛 GitHub Check: golangci-lint

[failure] 267-267:
add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68c3e83 and 1f92874.

📒 Files selected for processing (5)
  • go.mod (2 hunks)
  • pkg/pager/err.go (1 hunks)
  • pkg/pager/model.go (1 hunks)
  • pkg/pager/model_test.go (1 hunks)
  • pkg/utils/utils.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • go.mod
  • pkg/pager/model_test.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
pkg/utils/utils.go (1)
pkg/config/go-homedir/homedir.go (1)
  • Expand (68-87)
🪛 GitHub Check: golangci-lint
pkg/utils/utils.go

[failure] 73-73:
cyclomatic: function GlamourStyle has cyclomatic complexity 12 (> max enabled 10)

pkg/pager/model.go

[failure] 45-45:
Comment should end in a period


[failure] 51-51:
var lineNumberFg is unused


[failure] 86-86:
var lineNumberStyle is unused


[failure] 94-94:
field cwd is unused


[failure] 256-256:
hugeParam: m is heavy (1280 bytes); consider passing it by pointer


[failure] 267-267:
add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it


[failure] 303-303:
function-length: maximum number of lines per function exceeded; max 60 but got 63

pkg/pager/err.go

[failure] 3-3:
type errMsg is unused


[failure] 5-5:
func errMsg.Error is unused

🪛 golangci-lint (1.64.8)
pkg/pager/model.go

[error] 51-51: var lineNumberFg is unused

(unused)


[error] 86-86: var lineNumberStyle is unused

(unused)


[error] 94-94: field cwd is unused

(unused)


[error] 267-267: add-constant: string literal "\n" appears, at least, 4 times, create a named constant for it

(revive)


[error] 303-303: function-length: maximum number of lines per function exceeded; max 60 but got 63

(revive)

pkg/pager/err.go

[error] 3-3: type errMsg is unused

(unused)


[error] 5-5: func errMsg.Error is unused

(unused)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (7)
pkg/pager/model.go (4)

370-381: Good use of helper function.

The indent function is a clean, well-implemented helper that efficiently handles string indentation. The comment accurately describes its purpose as a lightweight version of reflow's indent function.


126-135: Good implementation of string processing utility.

The StripANSI function and its regex pattern are well-implemented for removing ANSI escape sequences from text. This is essential for clipboard operations that need plain text without terminal formatting codes.


196-227: Well-designed status message system.

The status message timeout implementation with proper timer management is a good design pattern. It correctly handles cleanup of previous timers and uses a command-based approach that fits well with the Bubble Tea framework's architecture.


113-125: Well-structured model design.

The model struct is well-organized with clear separation of concerns for UI state, content, viewport, and status message handling. This design makes the code maintainable as features are added.

pkg/utils/utils.go (3)

34-41: The ExpandPath function handles path expansion correctly.

This function properly expands both tilde (~) to the user's home directory and environment variables in paths. The error handling is appropriate, falling back to expanding only environment variables if homedir expansion fails.


17-23: The frontmatter removal implementation is clean and effective.

The function properly handles YAML frontmatter in markdown files by detecting the frontmatter boundaries and removing the content between them. The implementation is straightforward and effective.


56-59:

❓ Verification inconclusive

Consider revisiting the default assumption for files without extensions.

The current implementation assumes that files without extensions are markdown files. This might work for many cases but could lead to unexpected behavior for non-markdown files without extensions. Consider if this is the intended behavior for your use case.


🏁 Script executed:

#!/bin/bash
# Check if there are any non-markdown files without extensions in the codebase
# that might be affected by this assumption

echo "Searching for files without extensions that might not be markdown..."
find . -type f -not -path "*/\.*" -not -path "*/node_modules/*" -not -path "*/vendor/*" | grep -v "\." | xargs file | grep -v "text" || echo "No non-text files without extensions found."

Length of output: 415


Re-evaluate handling of extension‑less files

By treating every file with no “.” in its name as Markdown, you’ll also pick up things like LICENSE, NOTICE, script files or any future binary assets without extensions. Please double‑check whether:

  • You have any extension‑less resources (text or binary) that shouldn’t be rendered as Markdown
  • This default behavior is truly desired, or if it should be driven by an explicit flag/whitelist
  • You’d prefer to require a “.md” (or a config) rather than blanket‑defaulting to Markdown

Affected location:
• pkg/utils/utils.go lines 56–59

@samtholiya samtholiya force-pushed the feature/dev-3131-add-pager-to-atmos-describe-config-command branch from daf011c to 3fa3c1d Compare April 24, 2025 19:44
Copy link
Contributor

@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

🧹 Nitpick comments (1)
internal/exec/describe_config.go (1)

42-67: Good error handling with fallback mechanism

The command execution flow properly handles error conditions and falls back to direct printing when the pager fails. This is a user-friendly approach that maintains functionality even when the pager can't be used.

Consider adding a bit more context to the debug log message to help with troubleshooting:

-			log.Debug("Failed to use pager")
+			log.Debug("Failed to use pager, falling back to direct output", "error", err)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between daf011c and 3fa3c1d.

📒 Files selected for processing (24)
  • cmd/describe.go (1 hunks)
  • cmd/describe_config.go (2 hunks)
  • cmd/docs.go (1 hunks)
  • go.mod (2 hunks)
  • internal/exec/describe_config.go (1 hunks)
  • internal/exec/describe_config_test.go (1 hunks)
  • pkg/config/default.go (1 hunks)
  • pkg/config/load.go (2 hunks)
  • pkg/pager/mock_pager.go (1 hunks)
  • pkg/pager/model.go (1 hunks)
  • pkg/pager/model_test.go (1 hunks)
  • pkg/pager/pager.go (1 hunks)
  • pkg/schema/schema.go (1 hunks)
  • pkg/schema/schema_test.go (1 hunks)
  • pkg/utils/json_utils.go (1 hunks)
  • pkg/utils/yaml_utils.go (1 hunks)
  • pkg/utils/yq_utils.go (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_-f_yaml.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stdout.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden (1 hunks)
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stdout.golden (1 hunks)
  • tests/test-cases/demo-stacks.yaml (3 hunks)
✅ Files skipped from review due to trivial changes (3)
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stderr.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stdout.golden
  • pkg/pager/mock_pager.go
🚧 Files skipped from review as they are similar to previous changes (20)
  • tests/snapshots/TestCLICommands_atmos_describe_config.stdout.golden
  • tests/snapshots/TestCLICommands_atmos_describe_config_imports.stderr.golden
  • tests/test-cases/demo-stacks.yaml
  • pkg/config/default.go
  • cmd/describe.go
  • tests/snapshots/TestCLICommands_atmos_describe_config_-f_yaml.stdout.golden
  • pkg/config/load.go
  • cmd/docs.go
  • tests/snapshots/TestCLICommands_atmos_describe_configuration.stdout.golden
  • pkg/schema/schema_test.go
  • internal/exec/describe_config_test.go
  • pkg/utils/json_utils.go
  • pkg/utils/yaml_utils.go
  • go.mod
  • cmd/describe_config.go
  • pkg/pager/model_test.go
  • pkg/utils/yq_utils.go
  • pkg/schema/schema.go
  • pkg/pager/pager.go
  • pkg/pager/model.go
🧰 Additional context used
🪛 GitHub Check: Build (macos-latest, macos)
internal/exec/describe_config.go

[failure] 16-16:
other declaration of ErrInvalidFormat

🪛 GitHub Check: Build (ubuntu-latest, linux)
internal/exec/describe_config.go

[failure] 16-16:
other declaration of ErrInvalidFormat

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (5)
internal/exec/describe_config.go (5)

24-24: Good use of a static error variable

Defining ErrTTYNotSupported as a package-level variable with a clear, descriptive message follows Go best practices.


26-31: Well-structured dependency injection pattern

The describeConfigExec struct and constructor function follow good dependency injection principles, making the code testable and modular.

Also applies to: 33-40


69-95: Well-implemented format handling in viewConfig

The viewConfig method handles different output formats appropriately and performs necessary validation before using the pager.


47-47: Good use of generic typed function for evaluation

Using the generic typed EvaluateYqExpressionWithType function provides type safety for the query evaluation.


55-65: Effective conditional pager enablement

The code correctly uses the IsPagerEnabled() method to determine whether to use the pager, which respects user configuration preferences.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (2)
internal/exec/describe_config.go (2)

55-65: Consider validating format earlier.

The function takes a format parameter but only validates it deep in the viewConfig method. Consider validating the format parameter earlier in ExecuteDescribeConfigCmd to fail fast.

func (d *describeConfigExec) ExecuteDescribeConfigCmd(query, format, output string) error {
+	// Validate format early for faster feedback
+	if format != "yaml" && format != "json" {
+		return DescribeConfigFormatError{format}
+	}
+
	var res *schema.AtmosConfiguration
	var err error
	// ... rest of function

63-63: Consider including error details in debug log.

The current debug message doesn't include the actual error, which might make troubleshooting harder. Consider including the error details in the log message.

-		log.Debug("Failed to use pager")
+		log.Debug("Failed to use pager", "error", err)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3fa3c1d and 1649fa7.

📒 Files selected for processing (2)
  • internal/exec/describe_config.go (1 hunks)
  • internal/exec/describe_config_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/exec/describe_config_test.go
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Summary
🔇 Additional comments (6)
internal/exec/describe_config.go (6)

16-22: Good error type naming.

The DescribeConfigFormatError type name is clear and avoids the collision with ErrInvalidFormat flagged in previous builds. This implementation properly follows Go error handling conventions.


24-24: Clear error definition for TTY support.

Good practice defining a static error variable for the TTY support check. This makes error handling more explicit and easier to test.


26-40: Clean dependency injection pattern.

The describeConfigExec struct and its constructor follow solid dependency injection principles. This design improves testability by allowing dependencies to be mocked.


43-53: Appropriate query handling.

The typed query evaluation with EvaluateYqExpressionWithType is a good approach that leverages Go's type system. This is cleaner than the previous implementation.


69-95: Good error handling in viewConfig method.

The viewConfig method has proper error handling for TTY support and content generation. The method correctly checks each potential failure point and returns appropriate errors.


91-94: Clear pager execution.

The pager creation and execution is straightforward and properly handles errors. Good job isolating this functionality through the pageCreator interface.

coderabbitai[bot]
coderabbitai bot previously approved these changes Apr 24, 2025
@osterman
Copy link
Member

osterman commented May 2, 2025

@samtholiya update screenshots in PR description

Copy link

mergify bot commented May 7, 2025

💥 This pull request now has conflicts. Could you fix it @samtholiya? 🙏

@mergify mergify bot added the conflict This PR has conflicts label May 7, 2025
@mergify mergify bot removed the conflict This PR has conflicts label May 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor New features that do not break anything size/xl
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants