Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Measure command without ruby arg #962

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Debugging

Misc
edit Open a file or source location.
measure `measure` enables the mode to measure processing time. `measure :off` disables it.
measure `measure` enables the mode to measure processing time. `measure off` disables it.

Context
show_doc Look up documentation with RI.
Expand Down
43 changes: 26 additions & 17 deletions lib/irb/command/measure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,51 @@ module IRB

module Command
class Measure < Base
include RubyArgsExtractor

category "Misc"
description "`measure` enables the mode to measure processing time. `measure :off` disables it."

def initialize(*args)
super(*args)
end
description "`measure` enables the mode to measure processing time. `measure off` disables it."

def execute(arg)
if arg&.match?(/^do$|^do[^\w]|^\{/)
warn 'Configure IRB.conf[:MEASURE_PROC] to add custom measure methods.'
return
end
args, kwargs = ruby_args(arg)
execute_internal(*args, **kwargs)

if arg.empty?
execute_internal(nil, nil)
elsif arg.start_with? ':'
# Legacy style `measure :stackprof`, `measure :off, :time`
type, arg_val = arg.split(/,\s*/, 2).map { |v| v.sub(/\A:/, '') }
warn "`measure #{arg}` is deprecated. Please use `measure #{[type, arg_val].compact.join(' ')}` instead."
execute_internal(type.to_sym, arg_val)
else
type, arg_val = arg.split(/\s+/, 2)
execute_internal(type.to_sym, arg_val)
end
end

def execute_internal(type = nil, arg = nil)
def execute_internal(type, arg)
# Please check IRB.init_config in lib/irb/init.rb that sets
# IRB.conf[:MEASURE_PROC] to register default "measure" methods,
# "measure :time" (abbreviated as "measure") and "measure :stackprof".
# "measure time" (abbreviated as "measure") and "measure stackprof".

case type
when :off
IRB.unset_measure_callback(arg)
IRB.unset_measure_callback(arg&.to_sym)
when :list
IRB.conf[:MEASURE_CALLBACKS].each do |type_name, _, arg_val|
puts "- #{type_name}" + (arg_val ? "(#{arg_val.inspect})" : '')
end
when :on
added = IRB.set_measure_callback(arg)
puts "#{added[0]} is added." if added
else
added = IRB.set_measure_callback(type, arg)
puts "#{added[0]} is added." if added
type, arg = arg&.to_sym, nil if type == :on

measure_methods = IRB.conf[:MEASURE_PROC].keys.map(&:downcase)
if type && !measure_methods.include?(type)
puts "Measure method `#{type}` not found."
puts "Available measure methods: %w[#{measure_methods.join(' ')}]."
else
added = IRB.set_measure_callback(type&.to_sym, arg)
puts "#{added[0]} is added." if added
end
end
nil
end
Expand Down
14 changes: 2 additions & 12 deletions lib/irb/init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,19 +204,9 @@ def IRB.set_measure_callback(type = nil, arg = nil, &block)
added = [type_sym, IRB.conf[:MEASURE_PROC][type_sym], arg]
end
elsif IRB.conf[:MEASURE_PROC][:CUSTOM]
added = [:CUSTOM, IRB.conf[:MEASURE_PROC][:CUSTOM], arg]
elsif block_given?
added = [:BLOCK, block, arg]
found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] }
if found
found[1] = block
return added
else
IRB.conf[:MEASURE_CALLBACKS] << added
return added
end
added = [:CUSTOM, IRB.conf[:MEASURE_PROC][:CUSTOM], nil]
else
added = [:TIME, IRB.conf[:MEASURE_PROC][:TIME], arg]
added = [:TIME, IRB.conf[:MEASURE_PROC][:TIME], nil]
end
if added
IRB.conf[:MEASURE] = true
Expand Down
75 changes: 48 additions & 27 deletions test/irb/test_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ def test_irb_info_lang
end

class MeasureTest < CommandTestCase
CUSTOM_MEASURE_PROC = proc { |context, line, line_no, &block|
raise 'Wrong argument' unless IRB::Context === context && String === line && Integer === line_no
time = Time.now
result = block.()
puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
result
}
def test_measure
conf = {
PROMPT: {
Expand All @@ -225,11 +232,11 @@ def test_measure
out, err = execute_lines(
"measure\n",
"3\n",
"measure :off\n",
"measure off\n",
"3\n",
"measure :on\n",
"measure on\n",
"3\n",
"measure :off\n",
"measure off\n",
"3\n",
conf: conf,
main: c
Expand Down Expand Up @@ -282,7 +289,7 @@ def test_measure_enabled_by_rc

out, err = execute_lines(
"3\n",
"measure :off\n",
"measure off\n",
"3\n",
conf: conf,
)
Expand All @@ -292,12 +299,6 @@ def test_measure_enabled_by_rc
end

def test_measure_enabled_by_rc_with_custom
measuring_proc = proc { |line, line_no, &block|
time = Time.now
result = block.()
puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
result
}
conf = {
PROMPT: {
DEFAULT: {
Expand All @@ -308,12 +309,12 @@ def test_measure_enabled_by_rc_with_custom
},
PROMPT_MODE: :DEFAULT,
MEASURE: true,
MEASURE_PROC: { CUSTOM: measuring_proc }
MEASURE_PROC: { CUSTOM: CUSTOM_MEASURE_PROC }
}

out, err = execute_lines(
"3\n",
"measure :off\n",
"measure off\n",
"3\n",
conf: conf,
)
Expand All @@ -322,12 +323,6 @@ def test_measure_enabled_by_rc_with_custom
end

def test_measure_with_custom
measuring_proc = proc { |line, line_no, &block|
time = Time.now
result = block.()
puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
result
}
conf = {
PROMPT: {
DEFAULT: {
Expand All @@ -338,13 +333,13 @@ def test_measure_with_custom
},
PROMPT_MODE: :DEFAULT,
MEASURE: false,
MEASURE_PROC: { CUSTOM: measuring_proc }
MEASURE_PROC: { CUSTOM: CUSTOM_MEASURE_PROC }
}
out, err = execute_lines(
"3\n",
"measure\n",
"3\n",
"measure :off\n",
"measure off\n",
"3\n",
conf: conf
)
Expand All @@ -365,24 +360,24 @@ def test_measure_toggle
PROMPT_MODE: :DEFAULT,
MEASURE: false,
MEASURE_PROC: {
FOO: proc { |&block| puts 'foo'; block.call },
BAR: proc { |&block| puts 'bar'; block.call }
FOO: proc { |ctx, line, line_no, arg, &block| puts "foo(#{arg.inspect})"; block.call },
BAR: proc { |ctx, line, line_no, arg, &block| puts "bar(#{arg.inspect})"; block.call }
}
}
out, err = execute_lines(
"measure :foo\n",
"measure foo arg\n",
"1\n",
"measure :on, :bar\n",
"measure on bar\n",
"2\n",
"measure :off, :foo\n",
"measure off foo\n",
"3\n",
"measure :off, :bar\n",
"measure off bar\n",
"4\n",
conf: conf
)

assert_empty err
assert_match(/\AFOO is added\.\nfoo\n=> 1\nBAR is added\.\nbar\nfoo\n=> 2\nbar\n=> 3\n=> 4\n/, out)
assert_match(/\AFOO is added\.\nfoo\("arg"\)\n=> 1\nBAR is added\.\nbar\(nil\)\nfoo\("arg"\)\n=> 2\nbar\(nil\)\n=> 3\n=> 4\n/, out)
end

def test_measure_with_proc_warning
Expand Down Expand Up @@ -410,6 +405,32 @@ def test_measure_with_proc_warning
assert_match(/\A=> 3\n=> 3\n/, out)
assert_empty(c.class_variables)
end

def test_legacy_measure_warning
conf = {
MEASURE_PROC: {
FOO: proc {},
BAR: proc {},
}
}
out, err = execute_lines(
"measure :foo\n",
"measure :on, :bar\n",
conf: conf
)
assert_match(/FOO is added/, out)
assert_match(/BAR is added/, out)
assert_match(/`measure :foo` is deprecated. Please use `measure foo`/, err)
assert_match(/`measure :on, :bar` is deprecated. Please use `measure on bar`/, err)
end

def test_unknown_method
out, err = execute_lines("measure foo\n", "measure on bar\n")
assert_empty(err)
assert_match(/`foo` not found/, out)
assert_match(/`bar` not found/, out)
assert_match(/time stackprof/, out)
end
end

class IrbSourceTest < CommandTestCase
Expand Down
Loading