mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
01785a8020
Before this change the watch command was broken because Pry::Code#to_s contained ansi codes which it passed into eval.
180 lines
5.5 KiB
Ruby
180 lines
5.5 KiB
Ruby
class Pry
|
|
class Command::Hist < Pry::ClassCommand
|
|
match 'hist'
|
|
group 'Editing'
|
|
description 'Show and replay Readline history.'
|
|
|
|
banner <<-'BANNER'
|
|
Usage: hist [--head|--tail]
|
|
hist --all
|
|
hist --head N
|
|
hist --tail N
|
|
hist --show START..END
|
|
hist --grep PATTERN
|
|
hist --clear
|
|
hist --replay START..END
|
|
hist --save [START..END] FILE
|
|
Aliases: history
|
|
|
|
Show and replay Readline history.
|
|
BANNER
|
|
|
|
def options(opt)
|
|
opt.on :a, :all, "Display all history"
|
|
opt.on :H, :head, "Display the first N items", :optional_argument => true, :as => Integer
|
|
opt.on :T, :tail, "Display the last N items", :optional_argument => true, :as => Integer
|
|
opt.on :s, :show, "Show the given range of lines", :optional_argument => true, :as => Range
|
|
opt.on :G, :grep, "Show lines matching the given pattern", :argument => true, :as => String
|
|
opt.on :c, :clear , "Clear the current session's history"
|
|
opt.on :r, :replay, "Replay a line or range of lines", :argument => true, :as => Range
|
|
opt.on :save, "Save history to a file", :argument => true, :as => Range
|
|
opt.on :e, :'exclude-pry', "Exclude Pry commands from the history"
|
|
opt.on :n, :'no-numbers', "Omit line numbers"
|
|
end
|
|
|
|
def process
|
|
@history = find_history
|
|
|
|
if opts.present?(:show)
|
|
@history = @history.between(opts[:show])
|
|
end
|
|
|
|
if opts.present?(:grep)
|
|
@history = @history.grep(opts[:grep])
|
|
end
|
|
|
|
@history = case
|
|
when opts.present?(:head)
|
|
@history.take_lines(1, opts[:head] || 10)
|
|
when opts.present?(:tail)
|
|
@history.take_lines(-(opts[:tail] || 10), opts[:tail] || 10)
|
|
when opts.present?(:show)
|
|
@history.between(opts[:show])
|
|
else
|
|
@history
|
|
end
|
|
|
|
if opts.present?(:'exclude-pry')
|
|
@history = @history.select do |loc|
|
|
!command_set.valid_command?(loc.line)
|
|
end
|
|
end
|
|
|
|
if opts.present?(:save)
|
|
process_save
|
|
elsif opts.present?(:clear)
|
|
process_clear
|
|
elsif opts.present?(:replay)
|
|
process_replay
|
|
else
|
|
process_display
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def process_display
|
|
unless opts.present?(:'no-numbers')
|
|
@history = @history.with_line_numbers
|
|
end
|
|
|
|
Pry::Pager.with_pager(output) do |pager|
|
|
@history.print_to_output(pager, _pry_.config.color)
|
|
end
|
|
end
|
|
|
|
def process_save
|
|
case opts[:save]
|
|
when Range
|
|
@history = @history.between(opts[:save])
|
|
|
|
unless args.first
|
|
raise CommandError, "Must provide a file name."
|
|
end
|
|
|
|
file_name = File.expand_path(args.first)
|
|
when String
|
|
file_name = File.expand_path(opts[:save])
|
|
end
|
|
|
|
output.puts "Saving history in #{file_name}..."
|
|
|
|
File.open(file_name, 'w') { |f| f.write(@history.raw) }
|
|
|
|
output.puts "History saved."
|
|
end
|
|
|
|
def process_clear
|
|
Pry.history.clear
|
|
output.puts "History cleared."
|
|
end
|
|
|
|
def process_replay
|
|
@history = @history.between(opts[:r])
|
|
replay_sequence = @history.raw
|
|
|
|
# If we met follow-up "hist" call, check for the "--replay" option
|
|
# presence. If "hist" command is called with other options, proceed
|
|
# further.
|
|
check_for_juxtaposed_replay(replay_sequence)
|
|
|
|
replay_sequence.lines.each do |line|
|
|
_pry_.eval line, :generated => true
|
|
end
|
|
end
|
|
|
|
# Checks +replay_sequence+ for the presence of neighboring replay calls.
|
|
# @example
|
|
# [1] pry(main)> hist --show 46894
|
|
# 46894: hist --replay 46675..46677
|
|
# [2] pry(main)> hist --show 46675..46677
|
|
# 46675: 1+1
|
|
# 46676: a = 100
|
|
# 46677: hist --tail
|
|
# [3] pry(main)> hist --replay 46894
|
|
# Error: Replay index 46894 points out to another replay call: `hist -r 46675..46677`
|
|
# [4] pry(main)>
|
|
#
|
|
# @raise [Pry::CommandError] If +replay_sequence+ contains another
|
|
# "hist --replay" call
|
|
# @param [String] replay_sequence The sequence of commands to be replayed
|
|
# (per saltum)
|
|
# @return [Boolean] `false` if +replay_sequence+ does not contain another
|
|
# "hist --replay" call
|
|
def check_for_juxtaposed_replay(replay_sequence)
|
|
if replay_sequence =~ /\Ahist(?:ory)?\b/
|
|
# Create *fresh* instance of Options for parsing of "hist" command.
|
|
_slop = self.slop
|
|
_slop.parse replay_sequence.split(' ')[1..-1]
|
|
|
|
if _slop.present?(:r)
|
|
replay_sequence = replay_sequence.split("\n").join('; ')
|
|
index = opts[:r]
|
|
index = index.min if index.min == index.max || index.max.nil?
|
|
|
|
raise CommandError, "Replay index #{ index } points out to another replay call: `#{ replay_sequence }`"
|
|
end
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
# Finds history depending on the given switch.
|
|
#
|
|
# @return [Pry::Code] if it finds `--all` (or `-a`) switch, returns all
|
|
# entries in history. Without the switch returns only the entries from the
|
|
# current Pry session.
|
|
def find_history
|
|
h = if opts.present?(:all)
|
|
Pry.history.to_a
|
|
else
|
|
Pry.history.to_a.last(Pry.history.session_line_count)
|
|
end
|
|
# The last value in history will be the 'hist' command itself.
|
|
Pry::Code(h[0..-2])
|
|
end
|
|
end
|
|
|
|
Pry::Commands.add_command(Pry::Command::Hist)
|
|
Pry::Commands.alias_command 'history', 'hist'
|
|
end
|