平衡点
2023/02/17
_ ruby 3.1 の irb がシンドかったのでなんとかする.
次期リリース候補の Debian 12 (Bookworm) の Ruby は ruby 3.1 です. これに同梱されている irb を叩いた所, 補完が効くようになっていてちょっと感動したんですが…
これは irb → reline ときて
で修正されています.
- Feature #18996: Proposal: Introduce new APIs to reline for changing dialog UI colours - Ruby master - Ruby Issue Tracking System
- Feature #19010: Follow up of #18996: Support changing irb's autocompletion background - Ruby master - Ruby Issue Tracking System
あたりを見ると, そのうち直りそうですが, まぁ.
といわけで, reline
にハードコードされている色を
まるっと上書きすることに.
cat ~/.irbrc
#-*- mode:ruby; coding:utf-8 -*-
IRB.conf[:SAVE_HISTORY] = 1000
## monkey patch for bgcolor
class Reline::LineEditor
alias_method :_orig_render_each_dialog, :render_each_dialog
private def render_each_dialog(dialog, cursor_column)
if @in_pasting
clear_each_dialog(dialog)
dialog.contents = nil
dialog.trap_key = nil
return
end
dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
dialog_render_info = dialog.call(@last_key)
if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
dialog.lines_backup = {
lines: modify_lines(whole_lines),
line_index: @line_index,
first_line_started_from: @first_line_started_from,
started_from: @started_from,
byte_pointer: @byte_pointer
}
clear_each_dialog(dialog)
dialog.contents = nil
dialog.trap_key = nil
return
end
old_dialog = dialog.clone
dialog.contents = dialog_render_info.contents
pointer = dialog.pointer
if dialog_render_info.width
dialog.width = dialog_render_info.width
else
dialog.width = dialog.contents.map { |l| calculate_width(l, true) }.max
end
height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT
height = dialog.contents.size if dialog.contents.size < height
if dialog.contents.size > height
if dialog.pointer
if dialog.pointer < 0
dialog.scroll_top = 0
elsif (dialog.pointer - dialog.scroll_top) >= (height - 1)
dialog.scroll_top = dialog.pointer - (height - 1)
elsif (dialog.pointer - dialog.scroll_top) < 0
dialog.scroll_top = dialog.pointer
end
pointer = dialog.pointer - dialog.scroll_top
end
dialog.contents = dialog.contents[dialog.scroll_top, height]
end
if dialog.contents and dialog.scroll_top >= dialog.contents.size
dialog.scroll_top = dialog.contents.size - height
end
if dialog_render_info.scrollbar and dialog_render_info.contents.size > height
bar_max_height = height * 2
moving_distance = (dialog_render_info.contents.size - height) * 2
position_ratio = dialog.scroll_top.zero? ? 0.0 : ((dialog.scroll_top * 2).to_f / moving_distance)
bar_height = (bar_max_height * ((dialog.contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
dialog.scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
else
dialog.scrollbar_pos = nil
end
upper_space = @first_line_started_from - @started_from
dialog.column = dialog_render_info.pos.x
dialog.width += @block_elem_width if dialog.scrollbar_pos
diff = (dialog.column + dialog.width) - (@screen_size.last)
if diff > 0
dialog.column -= diff
end
if (@rest_height - dialog_render_info.pos.y) >= height
dialog.vertical_offset = dialog_render_info.pos.y + 1
elsif upper_space >= height
dialog.vertical_offset = dialog_render_info.pos.y - height
else
if (@rest_height - dialog_render_info.pos.y) < height
scroll_down(height + dialog_render_info.pos.y)
move_cursor_up(height + dialog_render_info.pos.y)
end
dialog.vertical_offset = dialog_render_info.pos.y + 1
end
Reline::IOGate.hide_cursor
if dialog.column < 0
dialog.column = 0
dialog.width = @screen_size.last
end
reset_dialog(dialog, old_dialog)
move_cursor_down(dialog.vertical_offset)
Reline::IOGate.move_cursor_column(dialog.column)
dialog.contents.each_with_index do |item, i|
if i == pointer
# bg_color = '45'
bg_color = '44'
else
if dialog_render_info.bg_color
bg_color = dialog_render_info.bg_color
else
# bg_color = '46'
bg_color = '100'
end
end
str_width = dialog.width - (dialog.scrollbar_pos.nil? ? 0 : @block_elem_width)
str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
@output.write "\e[#{bg_color}m#{str}"
if dialog.scrollbar_pos and (dialog.scrollbar_pos != old_dialog.scrollbar_pos or dialog.column != old_dialog.column)
@output.write "\e[37m"
if dialog.scrollbar_pos <= (i * 2) and (i * 2 + 1) < (dialog.scrollbar_pos + bar_height)
@output.write @full_block
elsif dialog.scrollbar_pos <= (i * 2) and (i * 2) < (dialog.scrollbar_pos + bar_height)
@output.write @upper_half_block
str += ''
elsif dialog.scrollbar_pos <= (i * 2 + 1) and (i * 2) < (dialog.scrollbar_pos + bar_height)
@output.write @lower_half_block
else
@output.write ' ' * @block_elem_width
end
end
@output.write "\e[0m"
Reline::IOGate.move_cursor_column(dialog.column)
move_cursor_down(1) if i < (dialog.contents.size - 1)
end
Reline::IOGate.move_cursor_column(cursor_column)
move_cursor_up(dialog.vertical_offset + dialog.contents.size - 1)
Reline::IOGate.show_cursor
dialog.lines_backup = {
lines: modify_lines(whole_lines),
line_index: @line_index,
first_line_started_from: @first_line_started_from,
started_from: @started_from,
byte_pointer: @byte_pointer
}
end
end
というわけで.