1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

Add prompt stack to fix bug where prompt is not restored after returning from shell-mode

When returning from shell-mode, the prompt is not properly restored.
The problem is that it gets clobbered by the new prompt, so we need somewhere to store it.
This adds a prompt stack so you can push and pop prompts in order to temporarily change
the current prompt and then later restore the previous prompt.

prompt and prompt= are also overridden to have meaning in the context of the prompt stack.
This commit is contained in:
Josh Cheek 2011-04-30 16:16:20 -05:00
parent fde297e05b
commit 94c618cbd1
3 changed files with 121 additions and 3 deletions

View file

@ -270,10 +270,10 @@ e.g: gist -d my_method
command "shell-mode", "Toggle shell mode. Bring in pwd prompt and file completion." do
case Pry.active_instance.prompt
when Pry::SHELL_PROMPT
Pry.active_instance.prompt = Pry::DEFAULT_PROMPT
Pry.active_instance.pop_prompt
Pry.active_instance.custom_completions = Pry::DEFAULT_CUSTOM_COMPLETIONS
else
Pry.active_instance.prompt = Pry::SHELL_PROMPT
Pry.active_instance.push_prompt Pry::SHELL_PROMPT
Pry.active_instance.custom_completions = Pry::FILE_COMPLETIONS
Readline.completion_proc = Pry::InputCompleter.build_completion_proc target,
Pry.active_instance.instance_eval(&Pry::FILE_COMPLETIONS)

View file

@ -30,7 +30,7 @@ class Pry
default_options.merge!(options)
CONFIG_OPTIONS.each do |key|
instance_variable_set("@#{key}", default_options[key])
send "#{key}=", default_options[key]
end
@command_processor = CommandProcessor.new(self)
@ -320,6 +320,63 @@ class Pry
end
end
# the array that the prompt stack is stored in
def prompt_stack
@prompt_stack ||= Array.new
end
private :prompt_stack
# The current prompt, this is the prompt at the top of the prompt stack.
# @return [Array<Proc>] Current prompt.
# @example
# push_prompt(Pry::SIMPLE_PROMPT)
# prompt # => Pry::SIMPLE_PROMPT
def prompt
prompt_stack.last
end
# Replaces the current prompt with the new prompt.
# Does not change the rest of the prompt stack.
# @param [Array<Proc>] new_prompt
# @return [Array<Proc>] new_prompt
# @example
# pry.prompt = Pry::SIMPLE_PROMPT # => Pry::SIMPLE_PROMPT
# pry.prompt # => Pry::SIMPLE_PROMPT
def prompt=(new_prompt)
if prompt_stack.empty?
push_prompt new_prompt
else
prompt_stack[-1] = new_prompt
end
end
# Pushes the current prompt onto a stack that it can be restored from later.
# Use this if you wish to temporarily change the prompt.
# @param [Array<Proc>] new_prompt
# @return [Array<Proc>] new_prompt
# @example
# new_prompt = [ proc { '>' }, proc { '>>' } ]
# push_prompt(new_prompt) # => new_prompt
def push_prompt(new_prompt)
prompt_stack.push new_prompt
end
# Pops the current prompt off of the prompt stack.
# If the prompt you are popping is the last prompt, it will not be popped.
# Use this to restore the previous prompt.
# @return [Array<Proc>] Prompt being popped.
# @example
# prompt1 = [ proc { '>' }, proc { '>>' } ]
# prompt2 = [ proc { '$' }, proc { '>' } ]
# pry = Pry.new :prompt => prompt1
# pry.push_prompt(prompt2)
# pry.pop_prompt # => prompt2
# pry.pop_prompt # => prompt1
# pry.pop_prompt # => prompt1
def pop_prompt
if prompt_stack.size > 1 then prompt_stack.pop else prompt end
end
if RUBY_VERSION =~ /1.9/ && RUBY_ENGINE == "ruby"
require 'ripper'

View file

@ -737,6 +737,67 @@ describe Pry do
Pry.new.select_prompt(true, 0).should == "test prompt> "
Pry.new.select_prompt(false, 0).should == "test prompt* "
end
describe 'storing and restoring the prompt' do
before do
make = lambda do |name,i|
prompt = [ proc { "#{i}>" } , proc { "#{i+1}>" } ]
(class << prompt; self; end).send(:define_method, :inspect) { "<Prompt-#{name}>" }
prompt
end
@a , @b , @c = make[:a,0] , make[:b,1] , make[:c,2]
@pry = Pry.new :prompt => @a
end
it 'should have a prompt stack' do
@pry.push_prompt @b
@pry.push_prompt @c
@pry.prompt.should == @c
@pry.pop_prompt
@pry.prompt.should == @b
@pry.pop_prompt
@pry.prompt.should == @a
end
it 'should restore overridden prompts when returning from file-mode' do
pry = Pry.new :input => InputTester.new('shell-mode', 'shell-mode'),
:prompt => [ proc { 'P>' } ] * 2
pry.select_prompt(true, 0).should == "P>"
pry.re
pry.select_prompt(true, 0).should =~ /\Apry .* \$ \z/
pry.re
pry.select_prompt(true, 0).should == "P>"
end
it '#pop_prompt should return the popped prompt' do
@pry.push_prompt @b
@pry.push_prompt @c
@pry.pop_prompt.should == @c
@pry.pop_prompt.should == @b
end
it 'should not pop the last prompt' do
@pry.push_prompt @b
@pry.pop_prompt.should == @b
@pry.pop_prompt.should == @a
@pry.pop_prompt.should == @a
@pry.prompt.should == @a
end
describe '#prompt= should replace the current prompt with the new prompt' do
it 'when only one prompt on the stack' do
@pry.prompt = @b
@pry.prompt.should == @b
@pry.pop_prompt.should == @b
@pry.pop_prompt.should == @b
end
it 'when several prompts on the stack' do
@pry.push_prompt @b
@pry.prompt = @c
@pry.pop_prompt.should == @c
@pry.pop_prompt.should == @a
end
end
end
end
it 'should set the hooks default, and the default should be overridable' do