[ruby/irb] Handle long inspect and control character in prompt

string
(https://github.com/ruby/irb/pull/528)

* Handle long inspect and control characters in prompt string

* Add constants for prompt truncate length, omission and replace pattern

* Simply compare string instead of regexp in prompt truncation test
This commit is contained in:
tomoya ishida 2023-03-02 22:53:39 +09:00 committed by git
parent da6ac30d1e
commit 556439613a
2 changed files with 32 additions and 2 deletions

View File

@ -463,6 +463,10 @@ module IRB
# be parsed as :assign and echo will be suppressed, but the latter is
# parsed as a :method_add_arg and the output won't be suppressed
PROMPT_MAIN_TRUNCATE_LENGTH = 32
PROMPT_MAIN_TRUNCATE_OMISSION = '...'.freeze
CONTROL_CHARACTERS_PATTERN = "\x00-\x1F".freeze
# Creates a new irb session
def initialize(workspace = nil, input_method = nil)
@context = Context.new(self, workspace, input_method)
@ -775,6 +779,15 @@ module IRB
end
end
def truncate_prompt_main(str) # :nodoc:
str = str.tr(CONTROL_CHARACTERS_PATTERN, ' ')
if str.size <= PROMPT_MAIN_TRUNCATE_LENGTH
str
else
str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION
end
end
def prompt(prompt, ltype, indent, line_no) # :nodoc:
p = prompt.dup
p.gsub!(/%([0-9]+)?([a-zA-Z])/) do
@ -782,9 +795,9 @@ module IRB
when "N"
@context.irb_name
when "m"
@context.main.to_s
truncate_prompt_main(@context.main.to_s)
when "M"
@context.main.inspect
truncate_prompt_main(@context.main.inspect)
when "l"
ltype
when "i"

View File

@ -656,6 +656,23 @@ module TestIRB
$VERBOSE = verbose
end
def test_prompt_main_escape
irb = IRB::Irb.new(IRB::WorkSpace.new("main\a\t\r\n"))
assert_equal("irb(main )>", irb.prompt('irb(%m)>', nil, 1, 1))
end
def test_prompt_main_inspect_escape
main = Struct.new(:inspect).new("main\\n\nmain")
irb = IRB::Irb.new(IRB::WorkSpace.new(main))
assert_equal("irb(main\\n main)>", irb.prompt('irb(%M)>', nil, 1, 1))
end
def test_prompt_main_truncate
irb = IRB::Irb.new(IRB::WorkSpace.new("a" * 100))
assert_equal('irb(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa...)>', irb.prompt('irb(%m)>', nil, 1, 1))
assert_equal('irb("aaaaaaaaaaaaaaaaaaaaaaaaaaaa...)>', irb.prompt('irb(%M)>', nil, 1, 1))
end
def test_lineno
input = TestInputMethod.new([
"\n",