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 command "shell-mode", "Toggle shell mode. Bring in pwd prompt and file completion." do
case Pry.active_instance.prompt case Pry.active_instance.prompt
when Pry::SHELL_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 Pry.active_instance.custom_completions = Pry::DEFAULT_CUSTOM_COMPLETIONS
else else
Pry.active_instance.prompt = Pry::SHELL_PROMPT Pry.active_instance.push_prompt Pry::SHELL_PROMPT
Pry.active_instance.custom_completions = Pry::FILE_COMPLETIONS Pry.active_instance.custom_completions = Pry::FILE_COMPLETIONS
Readline.completion_proc = Pry::InputCompleter.build_completion_proc target, Readline.completion_proc = Pry::InputCompleter.build_completion_proc target,
Pry.active_instance.instance_eval(&Pry::FILE_COMPLETIONS) Pry.active_instance.instance_eval(&Pry::FILE_COMPLETIONS)

View file

@ -30,7 +30,7 @@ class Pry
default_options.merge!(options) default_options.merge!(options)
CONFIG_OPTIONS.each do |key| CONFIG_OPTIONS.each do |key|
instance_variable_set("@#{key}", default_options[key]) send "#{key}=", default_options[key]
end end
@command_processor = CommandProcessor.new(self) @command_processor = CommandProcessor.new(self)
@ -320,6 +320,63 @@ class Pry
end end
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" if RUBY_VERSION =~ /1.9/ && RUBY_ENGINE == "ruby"
require 'ripper' require 'ripper'

View file

@ -737,6 +737,67 @@ describe Pry do
Pry.new.select_prompt(true, 0).should == "test prompt> " Pry.new.select_prompt(true, 0).should == "test prompt> "
Pry.new.select_prompt(false, 0).should == "test prompt* " Pry.new.select_prompt(false, 0).should == "test prompt* "
end 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 end
it 'should set the hooks default, and the default should be overridable' do it 'should set the hooks default, and the default should be overridable' do