Skip to content

Instantly share code, notes, and snippets.

@kyrylo
Created June 14, 2012 12:14
Show Gist options
  • Save kyrylo/2929943 to your computer and use it in GitHub Desktop.
Save kyrylo/2929943 to your computer and use it in GitHub Desktop.
class Pry
module DefaultCommands
Cd = Pry::CommandSet.new do
create_command "cd" do
group "Context"
description "Move into a new context (object or scope)."
banner <<-BANNER
Usage: cd [OPTIONS] [--help]
Move into new context (object or scope). As in unix shells use
`cd ..` to go back, `cd /` to return to Pry top-level and `cd -`
to toggle between last two scopes).
Complex syntax (e.g cd ../@x/y) also supported.
e.g: `cd @x`
e.g: `cd ..
e.g: `cd /`
e.g: `cd -`
https://github.com/pry/pry/wiki/State-navigation#wiki-Changing_scope
BANNER
command_options :old_binding => nil, :append_binding => true
def process
# Extract command arguments. Delete blank arguments like " ", but
# don't delete empty string like "".
path = arg_string.split(/\//).delete_if { |a| a =~ /\A\s+\z/ }
stack = _pry_.binding_stack.dup
# Save previous command option values for the sake of restoring them
# them later (for example, when an exception raised).
old_binding = command_options[:old_binding]
append_binding = command_options[:append_binding]
# Special case when we only get a single "/", return to root.
if path.empty?
set_toggle_options(stack.last, true) if old_binding
stack = [stack.first]
end
path.each do |context|
begin
case context.chomp
when ""
set_toggle_options(stack.last, true)
stack = [stack.first]
when "::"
set_toggle_options(stack.last, false)
stack.push(TOPLEVEL_BINDING)
when "."
next
when ".."
unless stack.size == 1
set_toggle_options(stack.pop, true)
end
when "-"
if old_binding
toggle_old_binding(stack, old_binding, append_binding)
end
else
set_toggle_options(stack.last, false)
stack.push(Pry.binding_for(stack.last.eval(context)))
end
rescue RescuableException => e
# Restore previous values.
command_options[:old_binding] = old_binding
command_options[:append_binding] = append_binding
output.puts "Bad object path: #{arg_string.chomp}. Failed trying to resolve: #{context}"
output.puts e.inspect
return
end
end
_pry_.binding_stack = stack
end
private
# Toggle old binding value by either appending it to the current stack
# (when `append_binding` is `true`) or setting the new one (when
# `append_binding` is `false`).
#
# @param [Array<Binding>] The current stack of bindings.
# @param [Binding] The old binding.
# @param [Boolean] The append_binding flag.
#
# @return [Binding] The new old binding.
def toggle_old_binding(stack, old_binding, append_binding)
if append_binding
stack.push(old_binding)
old_binding = stack[-2]
else
old_binding = stack.pop
end
append_binding = !append_binding
set_toggle_options(old_binding, append_binding)
old_binding
end
# Set new values for command_options (`:old_binding` and
# `:append_binding`).
#
# @param [Binding] The old binding.
# @param [Boolean] The append_binding flag.
#
# @return [void]
def set_toggle_options(old_binding, append_binding)
command_options[:old_binding] = old_binding
command_options[:append_binding] = append_binding
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment