reline 0.3.9 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f903d3b8f902335117d484007dcfbef5e8846061a8eb3c8820f9975c4c85ea5
4
- data.tar.gz: 2ccb2d104c5c52b4e4f8ab1dd8a48ceb738fa03826ab62a7b38483d0f4f1288a
3
+ metadata.gz: b632074a7d879f8c00b4af972fb39af64a4775fbfdf0bedd252fa629891b77b4
4
+ data.tar.gz: 2406a738d92b076047ee697f527e4839cfd3012975a188784197cfddba3ce277
5
5
  SHA512:
6
- metadata.gz: d8edd5b7d31464fbc150518f94d45d84466837fe78374dbc127f2226005eb73f2c238f274d685ed42c97db56e906fb90b5e6369dd03dbaeac4b6f2019f36cd68
7
- data.tar.gz: 317225a1374e59f3dbb654b67a732fd3daf669fd13cab0673d73e0b952cc8d6fad554c4318366479d162890d0c538ca09cc902a1ad2fad0e42e4684b54f81c3e
6
+ metadata.gz: 84f7857bea1edc1bdf6035c68be9c6278e3f9749b6978d5bdbe7471495d9b44ade2be95752446a82afbab7d653fff679523bc7d697a511cc8d2772ec190cdf49
7
+ data.tar.gz: 966a26ac5a42a2f8f21bc330e92469fa1543e87346f743282a7dc585611e4d0061a4db223367dac35fe37803984f8eec4126a1f5d4cd573c96bd2476b832f94e
data/README.md CHANGED
@@ -55,6 +55,13 @@ end
55
55
 
56
56
  See also: [test/reline/yamatanooroti/multiline_repl](https://github.com/ruby/reline/blob/master/test/reline/yamatanooroti/multiline_repl)
57
57
 
58
+ ## Documentation
59
+
60
+ ### Reline::Face
61
+
62
+ You can modify the text color and text decorations in your terminal emulator.
63
+ See [doc/reline/face.md](./doc/reline/face.md)
64
+
58
65
  ## Contributing
59
66
 
60
67
  Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/reline.
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Reline::Face
4
+ SGR_PARAMETERS = {
5
+ foreground: {
6
+ black: 30,
7
+ red: 31,
8
+ green: 32,
9
+ yellow: 33,
10
+ blue: 34,
11
+ magenta: 35,
12
+ cyan: 36,
13
+ white: 37,
14
+ bright_black: 90,
15
+ gray: 90,
16
+ bright_red: 91,
17
+ bright_green: 92,
18
+ bright_yellow: 93,
19
+ bright_blue: 94,
20
+ bright_magenta: 95,
21
+ bright_cyan: 96,
22
+ bright_white: 97
23
+ },
24
+ background: {
25
+ black: 40,
26
+ red: 41,
27
+ green: 42,
28
+ yellow: 43,
29
+ blue: 44,
30
+ magenta: 45,
31
+ cyan: 46,
32
+ white: 47,
33
+ bright_black: 100,
34
+ gray: 100,
35
+ bright_red: 101,
36
+ bright_green: 102,
37
+ bright_yellow: 103,
38
+ bright_blue: 104,
39
+ bright_magenta: 105,
40
+ bright_cyan: 106,
41
+ bright_white: 107,
42
+ },
43
+ style: {
44
+ reset: 0,
45
+ bold: 1,
46
+ faint: 2,
47
+ italicized: 3,
48
+ underlined: 4,
49
+ slowly_blinking: 5,
50
+ blinking: 5,
51
+ rapidly_blinking: 6,
52
+ negative: 7,
53
+ concealed: 8,
54
+ crossed_out: 9
55
+ }
56
+ }.freeze
57
+
58
+ class Config
59
+ ESSENTIAL_DEFINE_NAMES = %i(default enhanced scrollbar).freeze
60
+ RESET_SGR = "\e[0m".freeze
61
+
62
+ def initialize(name, &block)
63
+ @definition = {}
64
+ block.call(self)
65
+ ESSENTIAL_DEFINE_NAMES.each do |name|
66
+ @definition[name] ||= { style: :reset, escape_sequence: RESET_SGR }
67
+ end
68
+ end
69
+
70
+ attr_reader :definition
71
+
72
+ def define(name, **values)
73
+ values[:escape_sequence] = format_to_sgr(values.to_a).freeze
74
+ @definition[name] = values
75
+ end
76
+
77
+ def reconfigure
78
+ @definition.each_value do |values|
79
+ values.delete(:escape_sequence)
80
+ values[:escape_sequence] = format_to_sgr(values.to_a).freeze
81
+ end
82
+ end
83
+
84
+ def [](name)
85
+ @definition.dig(name, :escape_sequence) or raise ArgumentError, "unknown face: #{name}"
86
+ end
87
+
88
+ private
89
+
90
+ def sgr_rgb(key, value)
91
+ return nil unless rgb_expression?(value)
92
+ if Reline::Face.truecolor?
93
+ sgr_rgb_truecolor(key, value)
94
+ else
95
+ sgr_rgb_256color(key, value)
96
+ end
97
+ end
98
+
99
+ def sgr_rgb_truecolor(key, value)
100
+ case key
101
+ when :foreground
102
+ "38;2;"
103
+ when :background
104
+ "48;2;"
105
+ end + value[1, 6].scan(/../).map(&:hex).join(";")
106
+ end
107
+
108
+ def sgr_rgb_256color(key, value)
109
+ # 256 colors are
110
+ # 0..15: standard colors, hight intensity colors
111
+ # 16..232: 216 colors (R, G, B each 6 steps)
112
+ # 233..255: grayscale colors (24 steps)
113
+ # This methods converts rgb_expression to 216 colors
114
+ rgb = value[1, 6].scan(/../).map(&:hex)
115
+ # Color steps are [0, 95, 135, 175, 215, 255]
116
+ r, g, b = rgb.map { |v| v <= 95 ? v / 48 : (v - 35) / 40 }
117
+ color = (16 + 36 * r + 6 * g + b)
118
+ case key
119
+ when :foreground
120
+ "38;5;#{color}"
121
+ when :background
122
+ "48;5;#{color}"
123
+ end
124
+ end
125
+
126
+ def format_to_sgr(ordered_values)
127
+ sgr = "\e[" + ordered_values.map do |key_value|
128
+ key, value = key_value
129
+ case key
130
+ when :foreground, :background
131
+ case value
132
+ when Symbol
133
+ SGR_PARAMETERS[key][value]
134
+ when String
135
+ sgr_rgb(key, value)
136
+ end
137
+ when :style
138
+ [ value ].flatten.map do |style_name|
139
+ SGR_PARAMETERS[:style][style_name]
140
+ end.then do |sgr_parameters|
141
+ sgr_parameters.include?(nil) ? nil : sgr_parameters
142
+ end
143
+ end.then do |rendition_expression|
144
+ unless rendition_expression
145
+ raise ArgumentError, "invalid SGR parameter: #{value.inspect}"
146
+ end
147
+ rendition_expression
148
+ end
149
+ end.join(';') + "m"
150
+ sgr == RESET_SGR ? RESET_SGR : RESET_SGR + sgr
151
+ end
152
+
153
+ def rgb_expression?(color)
154
+ color.respond_to?(:match?) and color.match?(/\A#[0-9a-fA-F]{6}\z/)
155
+ end
156
+ end
157
+
158
+ private_constant :SGR_PARAMETERS, :Config
159
+
160
+ def self.truecolor?
161
+ @force_truecolor || %w[truecolor 24bit].include?(ENV['COLORTERM'])
162
+ end
163
+
164
+ def self.force_truecolor
165
+ @force_truecolor = true
166
+ @configs&.each_value(&:reconfigure)
167
+ end
168
+
169
+ def self.[](name)
170
+ @configs[name]
171
+ end
172
+
173
+ def self.config(name, &block)
174
+ @configs ||= {}
175
+ @configs[name] = Config.new(name, &block)
176
+ end
177
+
178
+ def self.configs
179
+ @configs.transform_values(&:definition)
180
+ end
181
+
182
+ def self.load_initial_configs
183
+ config(:default) do |conf|
184
+ conf.define :default, style: :reset
185
+ conf.define :enhanced, style: :reset
186
+ conf.define :scrollbar, style: :reset
187
+ end
188
+ config(:completion_dialog) do |conf|
189
+ conf.define :default, foreground: :white, background: :cyan
190
+ conf.define :enhanced, foreground: :white, background: :magenta
191
+ conf.define :scrollbar, foreground: :white, background: :cyan
192
+ end
193
+ end
194
+
195
+ def self.reset_to_initial_configs
196
+ @configs = {}
197
+ load_initial_configs
198
+ end
199
+ end
@@ -831,27 +831,24 @@ class Reline::LineEditor
831
831
  dialog.column = 0
832
832
  dialog.width = @screen_size.last
833
833
  end
834
+ face = Reline::Face[dialog_render_info.face || :default]
835
+ scrollbar_sgr = face[:scrollbar]
836
+ default_sgr = face[:default]
837
+ enhanced_sgr = face[:enhanced]
834
838
  dialog.contents = contents.map.with_index do |item, i|
835
- if i == pointer
836
- fg_color = dialog_render_info.pointer_fg_color
837
- bg_color = dialog_render_info.pointer_bg_color
838
- else
839
- fg_color = dialog_render_info.fg_color
840
- bg_color = dialog_render_info.bg_color
841
- end
839
+ line_sgr = i == pointer ? enhanced_sgr : default_sgr
842
840
  str_width = dialog.width - (scrollbar_pos.nil? ? 0 : @block_elem_width)
843
841
  str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
844
- colored_content = "\e[#{bg_color}m\e[#{fg_color}m#{str}"
842
+ colored_content = "#{line_sgr}#{str}"
845
843
  if scrollbar_pos
846
- color_seq = "\e[37m"
847
844
  if scrollbar_pos <= (i * 2) and (i * 2 + 1) < (scrollbar_pos + bar_height)
848
- colored_content + color_seq + @full_block
845
+ colored_content + scrollbar_sgr + @full_block
849
846
  elsif scrollbar_pos <= (i * 2) and (i * 2) < (scrollbar_pos + bar_height)
850
- colored_content + color_seq + @upper_half_block
847
+ colored_content + scrollbar_sgr + @upper_half_block
851
848
  elsif scrollbar_pos <= (i * 2 + 1) and (i * 2) < (scrollbar_pos + bar_height)
852
- colored_content + color_seq + @lower_half_block
849
+ colored_content + scrollbar_sgr + @lower_half_block
853
850
  else
854
- colored_content + color_seq + ' ' * @block_elem_width
851
+ colored_content + scrollbar_sgr + ' ' * @block_elem_width
855
852
  end
856
853
  else
857
854
  colored_content
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.3.9'
2
+ VERSION = '0.4.1'
3
3
  end
data/lib/reline.rb CHANGED
@@ -7,6 +7,7 @@ require 'reline/key_stroke'
7
7
  require 'reline/line_editor'
8
8
  require 'reline/history'
9
9
  require 'reline/terminfo'
10
+ require 'reline/face'
10
11
  require 'rbconfig'
11
12
 
12
13
  module Reline
@@ -36,10 +37,8 @@ module Reline
36
37
  DialogRenderInfo = Struct.new(
37
38
  :pos,
38
39
  :contents,
39
- :bg_color,
40
- :pointer_bg_color,
41
- :fg_color,
42
- :pointer_fg_color,
40
+ :face,
41
+ :bg_color, # For the time being, this line should stay here for the compatibility with IRB.
43
42
  :width,
44
43
  :height,
45
44
  :scrollbar,
@@ -260,10 +259,7 @@ module Reline
260
259
  contents: result,
261
260
  scrollbar: true,
262
261
  height: [15, preferred_dialog_height].min,
263
- bg_color: 46,
264
- pointer_bg_color: 45,
265
- fg_color: 37,
266
- pointer_fg_color: 37
262
+ face: :completion_dialog
267
263
  )
268
264
  }
269
265
  Reline::DEFAULT_DIALOG_CONTEXT = Array.new
@@ -606,4 +602,6 @@ else
606
602
  io
607
603
  end
608
604
 
605
+ Reline::Face.load_initial_configs
606
+
609
607
  Reline::HISTORY = Reline::History.new(Reline.core.config)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-03 00:00:00.000000000 Z
11
+ date: 2023-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console
@@ -37,6 +37,7 @@ files:
37
37
  - lib/reline.rb
38
38
  - lib/reline/ansi.rb
39
39
  - lib/reline/config.rb
40
+ - lib/reline/face.rb
40
41
  - lib/reline/general_io.rb
41
42
  - lib/reline/history.rb
42
43
  - lib/reline/key_actor.rb
@@ -72,7 +73,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
73
  - !ruby/object:Gem::Version
73
74
  version: '0'
74
75
  requirements: []
75
- rubygems_version: 3.4.13
76
+ rubygems_version: 3.5.0.dev
76
77
  signing_key:
77
78
  specification_version: 4
78
79
  summary: Alternative GNU Readline or Editline implementation by pure Ruby.