From 3f59bddf94da20ae25687f2dc51d5ab96a8a535c Mon Sep 17 00:00:00 2001 From: Mohammed Esafi <47392041+MohammedEsafi@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:44:38 +0300 Subject: [PATCH] feat: allow disabling emoji output via --no-emoji / NO_EMOJI For users on terminals without emoji glyphs, or anyone who prefers plain-text output. Follows the no-color.org semantics already used by NO_COLOR: unset or empty = enabled, any non-empty value = disabled --- lib/tui.rb | 22 ++++++++++++++++++---- try.rb | 29 +++++++++++++++++------------ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/tui.rb b/lib/tui.rb index 7ee1680..65ffec6 100644 --- a/lib/tui.rb +++ b/lib/tui.rb @@ -23,9 +23,10 @@ module Tui @colors_enabled = ENV["NO_COLORS"].to_s.empty? + @emoji_enabled = ENV["NO_EMOJI"].to_s.empty? class << self - attr_accessor :colors_enabled + attr_accessor :colors_enabled, :emoji_enabled def colors_enabled? @colors_enabled @@ -38,6 +39,18 @@ def disable_colors! def enable_colors! @colors_enabled = true end + + def emoji_enabled? + @emoji_enabled + end + + def disable_emoji! + @emoji_enabled = false + end + + def enable_emoji! + @emoji_enabled = true + end end # Precompiled regexes used in hot paths @@ -299,9 +312,10 @@ def fill(char = " ") SegmentWriter::FillSegment.new(char.to_s) end - # Use for emoji characters - precomputes width and enables fast-path - def emoji(char) - SegmentWriter::EmojiSegment.new(char) + # Use for emoji characters - precomputes width and enables fast-path. + # `trailing` is the gap after the icon, it disappears with the emoji when disabled. + def emoji(char, trailing = " ") + SegmentWriter::EmojiSegment.new(Tui.emoji_enabled? ? "#{char}#{trailing}" : "") end end diff --git a/try.rb b/try.rb index d966f80..d09f08d 100755 --- a/try.rb +++ b/try.rb @@ -331,7 +331,7 @@ def render(tries) width = screen.width height = screen.height - screen.header.add_line { |line| line.write << emoji("🏠") << Tui::Text.accent(" Try Directory Selection") } + screen.header.add_line { |line| line.write << emoji("🏠") << Tui::Text.accent("Try Directory Selection") } screen.header.add_line { |line| line.write.write_dim(fill("─")) } screen.header.add_line do |line| prefix = "Search: " @@ -405,7 +405,7 @@ def render_entry_line(screen, entry, is_selected, width) else emoji("📁") end - line.write << icon << " " + line.write << icon plain_name, rendered_name = formatted_entry_name(entry) prefix_width = 5 @@ -431,11 +431,11 @@ def render_create_line(screen, is_selected, width) line.write << (is_selected ? Tui::Text.highlight("→ ") : " ") date_prefix = Time.now.strftime("%Y-%m-%d") label = if @input_buffer.empty? - "📂 Create new: #{date_prefix}-" + "Create new: #{date_prefix}-" else - "📂 Create new: #{date_prefix}-#{@input_buffer}" + "Create new: #{date_prefix}-#{@input_buffer}" end - line.write << label + line.write << emoji("📂") << label end def formatted_entry_name(entry) @@ -594,12 +594,12 @@ def render_rename_dialog(current_name, rename_buffer, rename_cursor, rename_erro screen = Tui::Screen.new(io: STDERR) screen.header.add_line do |line| - line.center << emoji("✏️") << Tui::Text.accent(" Rename directory") + line.center << emoji("✏️", " ") << Tui::Text.accent("Rename directory") end screen.header.add_line { |line| line.write.write_dim(fill("─")) } screen.body.add_line do |line| - line.write << emoji("📁") << " #{current_name}" + line.write << emoji("📁") << current_name end # Add empty lines, then centered input prompt @@ -716,12 +716,12 @@ def render_ascend_dialog(current_name, ascend_buffer, ascend_cursor, ascend_erro screen = Tui::Screen.new(io: STDERR) screen.header.add_line do |line| - line.center << emoji("🚀") << Tui::Text.accent(" Graduate try to project") + line.center << emoji("🚀", " ") << Tui::Text.accent("Graduate try to project") end screen.header.add_line { |line| line.write.write_dim(fill("─")) } screen.body.add_line do |line| - line.write << emoji("📁") << " #{current_name}" + line.write << emoji("📁") << current_name end screen.body.add_line @@ -885,13 +885,13 @@ def render_delete_dialog(marked_items, confirmation_buffer, confirmation_cursor) count = marked_items.length screen.header.add_line do |line| - line.center << emoji("🗑️") << Tui::Text.accent(" Delete #{count} #{count == 1 ? 'directory' : 'directories'}?") + line.center << emoji("🗑️", " ") << Tui::Text.accent("Delete #{count} #{count == 1 ? 'directory' : 'directories'}?") end screen.header.add_line { |line| line.write.write_dim(fill("─")) } marked_items.each do |item| screen.body.add_line(background: Tui::Palette::DANGER_BG) do |line| - line.write << emoji("🗑️") << " #{item[:basename]}" + line.write << emoji("🗑️") << item[:basename] end end @@ -1012,6 +1012,11 @@ def print_global_help Tui.disable_colors! if disable_colors Tui.disable_colors! if ENV['NO_COLOR'] && !ENV['NO_COLOR'].empty? + disable_emoji = ARGV.delete('--no-emoji') + + Tui.disable_emoji! if disable_emoji + Tui.disable_emoji! if ENV['NO_EMOJI'] && !ENV['NO_EMOJI'].empty? + # Global help: show for --help/-h anywhere if ARGV.include?("--help") || ARGV.include?("-h") print_global_help @@ -1087,7 +1092,7 @@ def is_git_uri?(arg) and_exit = !!ARGV.delete('--and-exit') and_keys_raw = extract_option_with_value!(ARGV, '--and-keys') and_confirm = extract_option_with_value!(ARGV, '--and-confirm') - # Note: --no-expand-tokens and --no-colors are processed early (before --help check) + # Note: --no-expand-tokens, --no-colors, and --no-emoji are processed early (before --help check) command = ARGV.shift