eza icon indicating copy to clipboard operation
eza copied to clipboard

fix(theme): support multi-codepoint emojis in theme.yml glyph field

Open dcadenas opened this issue 2 months ago β€’ 0 comments

Summary

Fixes #1654 - Adds support for multi-codepoint emojis in theme.yml glyph fields.

Problem

Emojis with Unicode variation selectors (πŸ–ΌοΈ, πŸ–₯️) and other multi-codepoint sequences caused the entire theme.yml file to be silently ignored. The glyph field was typed as Option<char>, which can only hold single Unicode scalar values.

Solution

Changed the glyph field from Option<char> to Option<String> to support:

  • βœ… Emojis with variation selectors (U+FE0F): πŸ–ΌοΈ πŸ–₯️ ⌚️ ☎️
  • βœ… ZWJ (Zero Width Joiner) sequences: πŸ‘¨β€πŸ’» πŸ‘©β€πŸŽ¨ πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦
  • βœ… Flag emojis (regional indicators): πŸ‡ΊπŸ‡Έ πŸ‡¬πŸ‡§ πŸ‡―πŸ‡΅
  • βœ… Skin tone modifiers: πŸ‘‹πŸ» πŸ‘‹πŸΏ

Also improved error handling to report theme parsing failures instead of silently failing.

Changes

Type Changes

  • src/theme/ui_styles.rs: Changed IconStyle::glyph from Option<char> to Option<String>
  • src/options/config.rs: Changed IconStyleOverride::glyph from Option<char> to Option<String>
  • Removed Copy trait from structs containing String fields (IconStyle, FileNameStyle, IconStyleOverride, FileNameStyleOverride)

Function Updates

  • src/output/icons.rs: Changed icon_for_file() return type from char to String
  • src/output/file_name.rs: Updated icon usage to work with String type
  • src/theme/mod.rs: Changed from dereferencing to cloning for non-Copy types

Error Handling

  • src/options/config.rs: Replaced silent .ok() with explicit error messages when theme parsing fails

Testing

Added 7 comprehensive unit tests covering:

  • Single-codepoint emojis (πŸ’Ύ)
  • Emojis with variation selectors (πŸ–ΌοΈ, πŸ–₯️)
  • ZWJ sequences (πŸ‘¨β€πŸ’»)
  • Regional indicator sequences (πŸ‡ΊπŸ‡Έ)
  • Mixed emoji themes
  • Empty glyph strings
  • Invalid YAML error handling

Test Results:

  • All 462 tests pass βœ…
  • No clippy warnings βœ…
  • Code formatted with cargo fmt βœ…

Backward Compatibility

Fully backward compatible - existing single-character icons continue to work without changes.

Example Usage

# ~/.config/eza/theme.yml
filenames:
  data: {icon: {glyph: πŸ’Ύ}}         # Single codepoint - works
  Pictures: {icon: {glyph: πŸ–ΌοΈ}}     # Variation selector - now works!
  Desktop: {icon: {glyph: πŸ–₯️}}      # Variation selector - now works!
  developer: {icon: {glyph: πŸ‘¨β€πŸ’»}}   # ZWJ sequence - now works!

extensions:
  rs: {icon: {glyph: πŸ¦€}}
  py: {icon: {glyph: 🐍}}

Checklist

  • [x] Tests pass (cargo test)
  • [x] No clippy warnings (cargo clippy)
  • [x] Code formatted (cargo fmt)
  • [x] Follows conventional commits
  • [x] References issue (#1654)
  • [x] Backward compatible

dcadenas avatar Oct 27 '25 18:10 dcadenas