Skip to content

west: add --color option to control output colorization#930

Open
TharakaUJ wants to merge 2 commits intozephyrproject-rtos:mainfrom
TharakaUJ:main
Open

west: add --color option to control output colorization#930
TharakaUJ wants to merge 2 commits intozephyrproject-rtos:mainfrom
TharakaUJ:main

Conversation

@TharakaUJ
Copy link
Copy Markdown

Add a global --color option with values 'always', 'never', and 'auto' to override automatic terminal detection.

The command-line option takes precedence over configuration settings. When provided, it overrides the value returned by WestCommand.color_ui.

fixes #651

@TharakaUJ
Copy link
Copy Markdown
Author

I initially considered adding support for a west config color always style configuration. However, since the configuration system expects section.key format (e.g., color.ui), I decided not to extend it in that direction.

Also for now 'auto' value just initialize colorama as default (existing behaviour).

Let me know if any changes to be made.
Thank you.

@bencefr
Copy link
Copy Markdown

bencefr commented Mar 5, 2026

This change would be very welcome with regards to environments like VS Code where executing child processes like west build as tasks we cannot cleanly provide a tty attached to get colored output. While environment variables like FORCE_COLOR=1 CLICOLOR_FORCE=1 TERM=xterm-256color does help with some underlying tools, they don't help with west's colorama.

@marc-hb
Copy link
Copy Markdown
Collaborator

marc-hb commented Mar 6, 2026

Thanks @TharakaUJ ! Can you please run uv run poe format and force push? Please also look at the other CI check. Do NOT spend too much time with cosmetics before review (in case the code has to change), but uv run poe format takes approximately zero time to run! Maybe the other CI check is very quick to fix too; I haven't looked at it yet.

@TharakaUJ
Copy link
Copy Markdown
Author

Thanks! I ran uv run poe format and fixed the lint issues. Force pushed the updated commit.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 84.09091% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.84%. Comparing base (5f5931f) to head (55dc524).
⚠️ Report is 6 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/west/app/main.py 82.50% 7 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #930      +/-   ##
==========================================
- Coverage   85.95%   85.84%   -0.12%     
==========================================
  Files          11       11              
  Lines        3454     3511      +57     
==========================================
+ Hits         2969     3014      +45     
- Misses        485      497      +12     
Files with missing lines Coverage Δ
src/west/commands.py 94.66% <100.00%> (-0.88%) ⬇️
src/west/app/main.py 79.10% <82.50%> (+0.02%) ⬆️

... and 2 files with indirect coverage changes

@pdgendt
Copy link
Copy Markdown
Collaborator

pdgendt commented Mar 13, 2026

@TharakaUJ thanks for the PR, I still need to do a full review, but I wonder if we could test this somehow. Codecov coverage shows that most of the changes isn't even executed during testing.

@TharakaUJ
Copy link
Copy Markdown
Author

@TharakaUJ thanks for the PR, I still need to do a full review, but I wonder if we could test this somehow. Codecov coverage shows that most of the changes isn't even executed during testing.

ok. I will look into adding test cases. Thank you!

@pdgendt
Copy link
Copy Markdown
Collaborator

pdgendt commented Mar 14, 2026

Make sure to run the formatter on the newly added tests, thanks!

@TharakaUJ
Copy link
Copy Markdown
Author

Thanks, applied the suggestion.

@marc-hb
Copy link
Copy Markdown
Collaborator

marc-hb commented Mar 16, 2026

@TharakaUJ
Copy link
Copy Markdown
Author

TharakaUJ commented Mar 17, 2026

Thank you. Squashed the fixup commit.

Copy link
Copy Markdown
Collaborator

@marc-hb marc-hb left a comment

Choose a reason for hiding this comment

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

Sorry I really don't understand why we need this new cmd._color_override field and new override function. It should be possible to keep all the logic centralized in a single accessor like color_ui() rather than scattered in different places like this, why not?

BTW you can probably remove some of the if self.color_ui checks in the code to simplify it now that this PR uses colorama.init(strip=True) (some other places will likely still need that check).

Last but not least: make sure you test thoroughly on both Linux and Windows. I started to do some manual testing that I will summarize soon in #651 (EDIT: done) and I found some existing issues even before this PR. Fixing them is out of scope for this PR but we have to be sure this #930 is not making anything worse. Also, #651 provides a good list of manual tests.

config_value = self.config.get('color.ui', 'auto')
# Handle both string values (always/never/auto) and
# boolean values (true/false) for backward compatibility
if config_value in ('always', 'true', 'True', '1'):
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think we can do that because color.ui=True (or 1, etc.) had no effect since forever. Now with this PR it becomes always. That could seriously mess up some CI logs and others.

I think it's OK for True and always to have different meanings.

elif color_mode == 'never':
colorama.init(strip=True)
else:
# 'auto' or None: use colorama's default behavior
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
# 'auto' or None: use colorama's default behavior
# 'auto' or None or "true": defer to colorama's terminal detection

color_mode = self.color_mode

if color_mode is None and self.config:
config_value = self.config.get('color.ui', 'auto')
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We don't want to access self.config.get('color.ui',... in two different places in the code, this seems too complicated and too high-maintenance. You can read the config value at a different time and place if there's a good reason for that, but don't add a new place while keeping the old place.

grep.color and other quirks add enough complexity already :-(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please keep using getboolean() and catch the ValueError when it's always or never rather than duplicating the special values from configparser.

@TharakaUJ
Copy link
Copy Markdown
Author

Thank you the detailed feedback. I will look into necessary changes.

Add a global --color option with values 'always', 'never',
and 'auto' to override automatic terminal detection.

The command-line option takes precedence over configuration
settings. When provided, it overrides the value returned by
WestCommand.color_ui.

Signed-off-by: Tharaka Jayasena <9dmpires2k17.tuj@gmail.com>
Add tests for:
- CLI override precedence in WestCommand.color_ui
- behavior with and without configuration
- parsing of the new --color argument in parse_early_args

Signed-off-by: Tharaka Jayasena <9dmpires2k17.tuj@gmail.com>
@TharakaUJ
Copy link
Copy Markdown
Author

I made some changes and force pushed. I thought a early review might helpful to stay on needed track.
also, unfortunately I won't be able to test this on windows until Monday.

@TharakaUJ
Copy link
Copy Markdown
Author

Sorry I really don't understand why we need this new cmd._color_override field and new override function. It should be possible to keep all the logic centralized in a single accessor like color_ui() rather than scattered in different places like this, why not?

Got rid of most of the _color_override logic. But still could not centralize all the logic, mainly because I'm not sure whether calling calorama.init() in westCommand would initialize it more than once. I will look into it.

@marc-hb
Copy link
Copy Markdown
Collaborator

marc-hb commented Mar 20, 2026

Got rid of most of the _color_override logic.

Thanks and thanks for the heads-up.

But still could not centralize all the logic, mainly because I'm not sure whether calling calorama.init() in westCommand would initialize it more than once. I will look into it.

Why would we need colorama.init() is WestCommands? Thanks to your new colorama.init(strip=True), we should be able to have LESS color-related code in WestCommands. If not in this PR, at least in the future. But for sure no additional color-related code in WestCommands, or why? Colorization is global.

Ideally, the only color-related code in WestCommands should be decisions like "how important is this log message?" and never "What does the user/configuration/terminal want?".

OK, now I just realized we haven't looked at colorization from a west API perspective... no idea what is the colorization status there :-(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add west --color=always and west config color=always

4 participants