зеркало из https://github.com/github/ruby.git
[ruby/reline] Fallback to 256color if COLORTERM != truecolor
(https://github.com/ruby/reline/pull/604) * Fallback to 256color if COLORTERM != truecolor * Add Reline::Face.force_truecolor to force truecolor without COLORTERM env https://github.com/ruby/reline/commit/090e1e4df0
This commit is contained in:
Родитель
8e64c87f64
Коммит
90b49024c0
|
@ -102,7 +102,10 @@ irb(main):001:0> Reline::Face.configs
|
|||
:scrollbar=>{:foreground=>:white, :background=>:cyan, :escape_sequence=>"\e[0m\e[37;46m"}}}
|
||||
```
|
||||
|
||||
## Backlog
|
||||
|
||||
- Support for 256-color terminal emulator. Fallback hex color code such as "#FF1020" to 256 colors
|
||||
## 256-Color and TrueColor
|
||||
|
||||
Reline will automatically detect if your terminal emulator supports truecolor with `ENV['COLORTERM] in 'truecolor' | '24bit'`. When this env is not set, Reline will fallback to 256-color.
|
||||
If your terminal emulator supports truecolor but does not set COLORTERM env, add this line to `.irbrc`.
|
||||
```ruby
|
||||
Reline::Face.force_truecolor
|
||||
```
|
||||
|
|
|
@ -74,6 +74,13 @@ class Reline::Face
|
|||
@definition[name] = values
|
||||
end
|
||||
|
||||
def reconfigure
|
||||
@definition.each_value do |values|
|
||||
values.delete(:escape_sequence)
|
||||
values[:escape_sequence] = format_to_sgr(values.to_a).freeze
|
||||
end
|
||||
end
|
||||
|
||||
def [](name)
|
||||
@definition.dig(name, :escape_sequence) or raise ArgumentError, "unknown face: #{name}"
|
||||
end
|
||||
|
@ -82,6 +89,14 @@ class Reline::Face
|
|||
|
||||
def sgr_rgb(key, value)
|
||||
return nil unless rgb_expression?(value)
|
||||
if Reline::Face.truecolor?
|
||||
sgr_rgb_truecolor(key, value)
|
||||
else
|
||||
sgr_rgb_256color(key, value)
|
||||
end
|
||||
end
|
||||
|
||||
def sgr_rgb_truecolor(key, value)
|
||||
case key
|
||||
when :foreground
|
||||
"38;2;"
|
||||
|
@ -90,6 +105,24 @@ class Reline::Face
|
|||
end + value[1, 6].scan(/../).map(&:hex).join(";")
|
||||
end
|
||||
|
||||
def sgr_rgb_256color(key, value)
|
||||
# 256 colors are
|
||||
# 0..15: standard colors, hight intensity colors
|
||||
# 16..232: 216 colors (R, G, B each 6 steps)
|
||||
# 233..255: grayscale colors (24 steps)
|
||||
# This methods converts rgb_expression to 216 colors
|
||||
rgb = value[1, 6].scan(/../).map(&:hex)
|
||||
# Color steps are [0, 95, 135, 175, 215, 255]
|
||||
r, g, b = rgb.map { |v| v <= 95 ? v / 48 : (v - 35) / 40 }
|
||||
color = (16 + 36 * r + 6 * g + b)
|
||||
case key
|
||||
when :foreground
|
||||
"38;5;#{color}"
|
||||
when :background
|
||||
"48;5;#{color}"
|
||||
end
|
||||
end
|
||||
|
||||
def format_to_sgr(ordered_values)
|
||||
sgr = "\e[" + ordered_values.map do |key_value|
|
||||
key, value = key_value
|
||||
|
@ -124,6 +157,15 @@ class Reline::Face
|
|||
|
||||
private_constant :SGR_PARAMETERS, :Config
|
||||
|
||||
def self.truecolor?
|
||||
@force_truecolor || %w[truecolor 24bit].include?(ENV['COLORTERM'])
|
||||
end
|
||||
|
||||
def self.force_truecolor
|
||||
@force_truecolor = true
|
||||
@configs&.each_value(&:reconfigure)
|
||||
end
|
||||
|
||||
def self.[](name)
|
||||
@configs[name]
|
||||
end
|
||||
|
|
|
@ -5,12 +5,19 @@ require_relative 'helper'
|
|||
class Reline::Face::Test < Reline::TestCase
|
||||
RESET_SGR = "\e[0m"
|
||||
|
||||
def setup
|
||||
@colorterm_backup = ENV['COLORTERM']
|
||||
ENV['COLORTERM'] = 'truecolor'
|
||||
end
|
||||
|
||||
def teardown
|
||||
Reline::Face.reset_to_initial_configs
|
||||
ENV['COLORTERM'] = @colorterm_backup
|
||||
end
|
||||
|
||||
class WithInsufficientSetupTest < self
|
||||
def setup
|
||||
super
|
||||
Reline::Face.config(:my_insufficient_config) do |face|
|
||||
end
|
||||
@face = Reline::Face[:my_insufficient_config]
|
||||
|
@ -37,6 +44,7 @@ class Reline::Face::Test < Reline::TestCase
|
|||
|
||||
class WithSetupTest < self
|
||||
def setup
|
||||
super
|
||||
Reline::Face.config(:my_config) do |face|
|
||||
face.define :default, foreground: :blue
|
||||
face.define :enhanced, foreground: "#FF1020", background: :black, style: [:bold, :underlined]
|
||||
|
@ -148,9 +156,15 @@ class Reline::Face::Test < Reline::TestCase
|
|||
|
||||
class ConfigTest < self
|
||||
def setup
|
||||
super
|
||||
@config = Reline::Face.const_get(:Config).new(:my_config) { }
|
||||
end
|
||||
|
||||
def teardown
|
||||
super
|
||||
Reline::Face.instance_variable_set(:@force_truecolor, nil)
|
||||
end
|
||||
|
||||
def test_rgb?
|
||||
assert_equal true, @config.send(:rgb_expression?, "#FFFFFF")
|
||||
end
|
||||
|
@ -190,9 +204,54 @@ class Reline::Face::Test < Reline::TestCase
|
|||
)
|
||||
end
|
||||
|
||||
def test_sgr_rgb
|
||||
def test_truecolor
|
||||
ENV['COLORTERM'] = 'truecolor'
|
||||
assert_equal true, Reline::Face.truecolor?
|
||||
ENV['COLORTERM'] = '24bit'
|
||||
assert_equal true, Reline::Face.truecolor?
|
||||
ENV['COLORTERM'] = nil
|
||||
assert_equal false, Reline::Face.truecolor?
|
||||
Reline::Face.force_truecolor
|
||||
assert_equal true, Reline::Face.truecolor?
|
||||
end
|
||||
|
||||
def test_sgr_rgb_truecolor
|
||||
ENV['COLORTERM'] = 'truecolor'
|
||||
assert_equal "38;2;255;255;255", @config.send(:sgr_rgb, :foreground, "#ffffff")
|
||||
assert_equal "48;2;18;52;86", @config.send(:sgr_rgb, :background, "#123456")
|
||||
end
|
||||
|
||||
def test_sgr_rgb_256color
|
||||
ENV['COLORTERM'] = nil
|
||||
assert_equal '38;5;231', @config.send(:sgr_rgb, :foreground, '#ffffff')
|
||||
assert_equal '48;5;16', @config.send(:sgr_rgb, :background, '#000000')
|
||||
# Color steps are [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]
|
||||
assert_equal '38;5;24', @config.send(:sgr_rgb, :foreground, '#005f87')
|
||||
assert_equal '38;5;67', @config.send(:sgr_rgb, :foreground, '#5f87af')
|
||||
assert_equal '48;5;110', @config.send(:sgr_rgb, :background, '#87afd7')
|
||||
assert_equal '48;5;153', @config.send(:sgr_rgb, :background, '#afd7ff')
|
||||
# Boundary values are [0x30, 0x73, 0x9b, 0xc3, 0xeb]
|
||||
assert_equal '38;5;24', @config.send(:sgr_rgb, :foreground, '#2f729a')
|
||||
assert_equal '38;5;67', @config.send(:sgr_rgb, :foreground, '#30739b')
|
||||
assert_equal '48;5;110', @config.send(:sgr_rgb, :background, '#9ac2ea')
|
||||
assert_equal '48;5;153', @config.send(:sgr_rgb, :background, '#9bc3eb')
|
||||
end
|
||||
|
||||
def test_force_truecolor_reconfigure
|
||||
ENV['COLORTERM'] = nil
|
||||
|
||||
Reline::Face.config(:my_config) do |face|
|
||||
face.define :default, foreground: '#005f87'
|
||||
face.define :enhanced, background: '#afd7ff'
|
||||
end
|
||||
|
||||
assert_equal "\e[0m\e[38;5;24m", Reline::Face[:my_config][:default]
|
||||
assert_equal "\e[0m\e[48;5;153m", Reline::Face[:my_config][:enhanced]
|
||||
|
||||
Reline::Face.force_truecolor
|
||||
|
||||
assert_equal "\e[0m\e[38;2;0;95;135m", Reline::Face[:my_config][:default]
|
||||
assert_equal "\e[0m\e[48;2;175;215;255m", Reline::Face[:my_config][:enhanced]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче