summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyrylo Silin <silin@kyrylo.org>2018-11-11 04:20:45 +0800
committerKyrylo Silin <silin@kyrylo.org>2018-11-16 05:25:46 +0800
commitda5ab88274d3aab297d140af0c8ade40be5d430f (patch)
tree03f9be1539cab424a52cb81a7503b8a068dd0c4a
parent62d8ddc616bc0bd90e86834d67d1dcaef8cab530 (diff)
downloadpry-prompt-simpler-api.tar.gz
Simplify Prompt APIprompt-simpler-api
Before this change when you set a prompt, you have to do the following: ```rb Pry.config.prompt = Pry::Prompt[:simple][:value] ``` The `[:value]` part was leaking implementation details and it proved to be an unnecessary step. With this change we can do the following: ```rb Pry.config.prompt = Pry::Prompt[:simple] ``` `[:value]` is omitted. I have also refactored some tests and removed irrelevant ones. The Array API for prompt is deprecated: `Pry.config.prompt = [proc {}, proc {}]` emits a warning now.
-rw-r--r--lib/pry.rb2
-rw-r--r--lib/pry/cli.rb4
-rw-r--r--lib/pry/commands/change_prompt.rb8
-rw-r--r--lib/pry/commands/shell_mode.rb2
-rw-r--r--lib/pry/config/behavior.rb9
-rw-r--r--lib/pry/config/default.rb2
-rw-r--r--lib/pry/prompt.rb54
-rw-r--r--lib/pry/pry_instance.rb49
-rw-r--r--spec/prompt_spec.rb90
-rw-r--r--spec/pry_defaults_spec.rb92
10 files changed, 156 insertions, 156 deletions
diff --git a/lib/pry.rb b/lib/pry.rb
index afe1c12f..bd224ad6 100644
--- a/lib/pry.rb
+++ b/lib/pry.rb
@@ -110,6 +110,7 @@ require 'pry/commands'
require 'pry/plugins'
require 'pry/core_extensions'
require 'pry/basic_object'
+require "pry/prompt"
require 'pry/config/behavior'
require 'pry/config/memoization'
require 'pry/config/default'
@@ -125,7 +126,6 @@ require 'pry/editor'
require 'pry/rubygem'
require "pry/indent"
require "pry/last_exception"
-require "pry/prompt"
require "pry/inspector"
require 'pry/object_path'
require 'pry/output'
diff --git a/lib/pry/cli.rb b/lib/pry/cli.rb
index a694ee7a..6fc021bc 100644
--- a/lib/pry/cli.rb
+++ b/lib/pry/cli.rb
@@ -180,11 +180,11 @@ Pry::CLI.add_options do
end
on "simple-prompt", "Enable simple prompt mode" do
- Pry.config.prompt = Pry::Prompt[:simple][:value]
+ Pry.config.prompt = Pry::Prompt[:simple]
end
on "noprompt", "No prompt mode" do
- Pry.config.prompt = Pry::Prompt[:none][:value]
+ Pry.config.prompt = Pry::Prompt[:none]
end
on :r, :require=, "`require` a Ruby script at startup" do |file|
diff --git a/lib/pry/commands/change_prompt.rb b/lib/pry/commands/change_prompt.rb
index 85696734..37d81da2 100644
--- a/lib/pry/commands/change_prompt.rb
+++ b/lib/pry/commands/change_prompt.rb
@@ -25,15 +25,15 @@ class Pry::Command::ChangePrompt < Pry::ClassCommand
def list_prompts
prompts = Pry::Prompt.all.map do |name, prompt|
- "#{bold(name)}#{red(' (selected)') if _pry_.prompt == prompt[:value]}\n" +
- prompt[:description]
+ "#{bold(name)}#{red(' (selected)') if _pry_.prompt == prompt}\n" +
+ prompt.description
end
output.puts(prompts.join("\n" * 2))
end
def change_prompt(prompt)
- if Pry::Prompt.all.key?(prompt)
- _pry_.prompt = Pry::Prompt.all[prompt][:value]
+ if Pry::Prompt[prompt]
+ _pry_.prompt = Pry::Prompt[prompt]
else
raise Pry::CommandError, "'#{prompt}' isn't a known prompt. " \
"Run `change-prompt --list` to see the list of known prompts."
diff --git a/lib/pry/commands/shell_mode.rb b/lib/pry/commands/shell_mode.rb
index b6b42f84..8cb8fe52 100644
--- a/lib/pry/commands/shell_mode.rb
+++ b/lib/pry/commands/shell_mode.rb
@@ -13,7 +13,7 @@ class Pry
if state.disabled
state.prev_prompt = _pry_.prompt
- _pry_.prompt = Pry::Prompt[:shell][:value]
+ _pry_.prompt = Pry::Prompt[:shell]
else
_pry_.prompt = state.prev_prompt
end
diff --git a/lib/pry/config/behavior.rb b/lib/pry/config/behavior.rb
index 8bb68f05..27efb81a 100644
--- a/lib/pry/config/behavior.rb
+++ b/lib/pry/config/behavior.rb
@@ -1,8 +1,14 @@
class Pry
class Config < Pry::BasicObject
+ # rubocop:disable Metrics/ModuleLength
module Behavior
ASSIGNMENT = "=".freeze
- NODUP = [TrueClass, FalseClass, NilClass, Symbol, Numeric, Module, Proc].freeze
+
+ NODUP = [
+ TrueClass, FalseClass, NilClass, Symbol, Numeric, Module, Proc,
+ Pry::Prompt
+ ].freeze
+
INSPECT_REGEXP = /#{Regexp.escape "default=#<"}/
ReservedKeyError = Class.new(RuntimeError)
@@ -251,5 +257,6 @@ class Pry
@lookup.delete(key)
end
end
+ # rubocop:enable Metrics/ModuleLength
end
end
diff --git a/lib/pry/config/default.rb b/lib/pry/config/default.rb
index 928df4e8..f7a5cd6b 100644
--- a/lib/pry/config/default.rb
+++ b/lib/pry/config/default.rb
@@ -18,7 +18,7 @@ class Pry
Pry::Prompt::DEFAULT_NAME
},
prompt: proc {
- Pry::Prompt[:default][:value]
+ Pry::Prompt[:default]
},
prompt_safe_contexts: proc {
Pry::Prompt::SAFE_CONTEXTS
diff --git a/lib/pry/prompt.rb b/lib/pry/prompt.rb
index 1e43841a..cbb91870 100644
--- a/lib/pry/prompt.rb
+++ b/lib/pry/prompt.rb
@@ -19,7 +19,7 @@ class Pry
# # In [4]:
# @since v0.11.0
# @api public
- module Prompt
+ class Prompt
# @return [String]
DEFAULT_NAME = 'pry'.freeze
@@ -35,7 +35,7 @@ class Pry
# Retrieves a prompt.
#
# @example
- # Prompt[:my_prompt][:value]
+ # Prompt[:my_prompt]
#
# @param [Symbol] name The name of the prompt you want to access
# @return [Hash{Symbol=>Object}]
@@ -78,12 +78,13 @@ class Pry
raise ArgumentError, "the '#{name}' prompt was already added"
end
- @prompts[name] = {
- description: description,
- value: separators.map do |sep|
+ @prompts[name] = new(
+ name,
+ description,
+ separators.map do |sep|
proc { |context, nesting, _pry_| yield(context, nesting, _pry_, sep) }
end
- }
+ )
nil
end
@@ -97,10 +98,35 @@ class Pry
end
end
- add 'default',
- "The default Pry prompt. Includes information about the current expression \n" \
- "number, evaluation context, and nesting level, plus a reminder that you're \n" \
- 'using Pry.' do |context, nesting, _pry_, sep|
+ # @return [String]
+ attr_reader :name
+
+ # @return [String]
+ attr_reader :description
+
+ def initialize(name, description, prompt_procs)
+ @name = name
+ @description = description
+ @prompt_procs = prompt_procs
+ end
+
+ # @return [Proc] the proc which builds the wait prompt (`>`)
+ def wait_proc
+ @prompt_procs.first
+ end
+
+ # @return [Proc] the proc which builds the prompt when in the middle of an
+ # expression such as open method, etc. (`*`)
+ def incomplete_proc
+ @prompt_procs.last
+ end
+
+ add(
+ :default,
+ "The default Pry prompt. Includes information about the current expression \n" \
+ "number, evaluation context, and nesting level, plus a reminder that you're \n" \
+ 'using Pry.'
+ ) do |context, nesting, _pry_, sep|
format(
"[%<in_count>s] %<name>s(%<context>s)%<nesting>s%<separator>s ",
in_count: _pry_.input_ring.count,
@@ -112,7 +138,7 @@ class Pry
end
add(
- 'simple',
+ :simple,
"A simple `>>`.",
['>> ', ' | ']
) do |_, _, _, sep|
@@ -120,7 +146,7 @@ class Pry
end
add(
- 'nav',
+ :nav,
"A prompt that displays the binding stack as a path and includes information \n" \
"about #{Helpers::Text.bold('_in_')} and #{Helpers::Text.bold('_out_')}.",
%w[> *]
@@ -137,7 +163,7 @@ class Pry
end
add(
- 'shell',
+ :shell,
'A prompt that displays `$PWD` as you change it.',
%w[$ *]
) do |context, _nesting, _pry_, sep|
@@ -151,7 +177,7 @@ class Pry
end
add(
- 'none',
+ :none,
'Wave goodbye to the Pry prompt.',
Array.new(2)
) { '' }
diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb
index 517df038..cd698ac7 100644
--- a/lib/pry/pry_instance.rb
+++ b/lib/pry/pry_instance.rb
@@ -58,7 +58,7 @@ class Pry
# The object to use for commands.
# @option options [Hash] :hooks
# The defined hook Procs.
- # @option options [Array<Proc>] :prompt
+ # @option options [Pry::Prompt] :prompt
# The array of Procs to use for prompts.
# @option options [Proc] :print
# The Proc to use for printing return values.
@@ -85,14 +85,18 @@ class Pry
@input_ring << nil
push_initial_binding(target)
exec_hook(:when_started, target, options, self)
+ @prompt_warn = false
end
# This is the prompt at the top of the prompt stack.
- # @return [Array<Proc>] the current prompt
+ # @return [Pry::Prompt] the current prompt
def prompt
prompt_stack.last
end
+ # Sets the Pry prompt.
+ # @param [Pry::Prompt] new_prompt
+ # @return [void]
def prompt=(new_prompt)
if prompt_stack.empty?
push_prompt new_prompt
@@ -548,6 +552,22 @@ class Pry
})
Pry.critical_section do
+ # If input buffer is empty, then use normal prompt. Otherwise use the wait
+ # prompt (indicating multi-line expression).
+ if prompt.is_a?(Pry::Prompt)
+ prompt_proc = eval_string.empty? ? prompt.wait_proc : prompt.incomplete_proc
+ return prompt_proc.call(c.object, c.nesting_level, c._pry_)
+ end
+
+ unless @prompt_warn
+ @prompt_warn = true
+ output.warn(
+ "warning: setting prompt with help of " \
+ "`Pry.config.prompt = [proc {}, proc {}]` is deprecated. " \
+ "Use Pry::Prompt API instead"
+ )
+ end
+
# If input buffer is empty then use normal prompt
if eval_string.empty?
generate_prompt(Array(prompt).first, c)
@@ -575,27 +595,28 @@ class Pry
# 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
+ # push_prompt(Pry::Prompt[:my_prompt])
+ #
+ # @param [Pry::Prompt] new_prompt
+ # @return [Pry::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.
+ # 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.
+ #
# @example
- # prompt1 = [ proc { '>' }, proc { '>>' } ]
- # prompt2 = [ proc { '$' }, proc { '>' } ]
- # pry = Pry.new :prompt => prompt1
- # pry.push_prompt(prompt2)
+ # pry = Pry.new(prompt: Pry::Prompt[:my_prompt1])
+ # pry.push_prompt(Pry::Prompt[:my_prompt2])
# pry.pop_prompt # => prompt2
# pry.pop_prompt # => prompt1
# pry.pop_prompt # => prompt1
+ #
+ # @return [Pry::Prompt] the prompt being popped
def pop_prompt
prompt_stack.size > 1 ? prompt_stack.pop : prompt
end
diff --git a/spec/prompt_spec.rb b/spec/prompt_spec.rb
index c339282f..4ecdc760 100644
--- a/spec/prompt_spec.rb
+++ b/spec/prompt_spec.rb
@@ -23,7 +23,7 @@ describe Pry::Prompt do
it "adds a new prompt" do
described_class.add(:my_prompt)
- expect(described_class[:my_prompt]).to be_a(Hash)
+ expect(described_class[:my_prompt]).to be_a(described_class)
end
it "raises error when separators.size != 2" do
@@ -42,87 +42,21 @@ describe Pry::Prompt do
end
end
- describe "one-parameter prompt proc" do
- it 'should get full config object' do
- config = nil
- redirect_pry_io(InputTester.new("exit-all")) do
- Pry.start(self, prompt: proc { |v| config = v })
- end
- expect(config.is_a?(Pry::Config)).to eq true
- end
-
- it 'should get full config object, when using a proc array' do
- config1 = nil
- redirect_pry_io(InputTester.new("exit-all")) do
- Pry.start(self, prompt: [proc { |v| config1 = v }, proc { |v| _config2 = v }])
- end
- expect(config1.is_a?(Pry::Config)).to eq true
- end
-
- it 'should receive correct data in the config object' do
- config = nil
- redirect_pry_io(InputTester.new("def hello", "exit-all")) do
- Pry.start(self, prompt: proc { |v| config = v })
- end
-
- expect(config.eval_string).to match(/def hello/)
- expect(config.nesting_level).to eq 0
- expect(config.expr_number).to eq 1
- expect(config.cont).to eq true
- expect(config._pry_.is_a?(Pry)).to eq true
- expect(config.object).to eq self
- end
-
- specify "object is Hash when current binding is a Hash" do
- config = nil
- h = {}
- redirect_pry_io(InputTester.new("exit-all")) do
- Pry.start(h, prompt: proc { |v| config = v })
- end
- expect(config.object).to be(h)
- end
- end
-
- describe "BACKWARDS COMPATIBILITY: 3 parameter prompt proc" do
- it 'should get 3 parameters' do
- o = n = p = nil
- redirect_pry_io(InputTester.new("exit-all")) do
- Pry.start(:test, prompt: proc { |obj, nesting, _pry_|
- o, n, p = obj, nesting, _pry_ })
- end
- expect(o).to eq :test
- expect(n).to eq 0
- expect(p.is_a?(Pry)).to eq true
- end
+ describe "prompt invocation" do
+ let(:pry) { Pry.new }
- it 'should get 3 parameters, when using proc array' do
- o1 = n1 = p1 = nil
- redirect_pry_io(InputTester.new("exit-all")) do
- Pry.start(:test, prompt: [proc { |obj, nesting, _pry_|
- o1, n1, p1 = obj, nesting, _pry_ },
- proc { |obj, nesting, _pry_|
- _o2, _n2, _p2 = obj, nesting, _pry_ }])
+ let(:enum) do
+ Enumerator.new do |y|
+ range = ('a'..'z').to_enum
+ loop { y << range.next }
end
- expect(o1).to eq :test
- expect(n1).to eq 0
- expect(p1.is_a?(Pry)).to eq true
end
- end
- it "can compute prompt name dynamically" do
- config = nil
- redirect_pry_io(InputTester.new("def hello", "exit-all")) do
- Pry.start(self, prompt: proc { |v| config = v })
+ it "computes prompt name dynamically" do
+ proc = described_class[:default].wait_proc
+ pry.config.prompt_name = Pry.lazy { enum.next }
+ expect(proc.call(Object.new, 1, pry, '>')).to eq('[1] a(#<Object>):1> ')
+ expect(proc.call(Object.new, 1, pry, '>')).to eq('[1] b(#<Object>):1> ')
end
-
- enum = Enumerator.new do |y|
- count = 100
- loop { y << count += 1 }
- end
- config._pry_.config.prompt_name = Pry.lazy { enum.next }
-
- proc = described_class[:default][:value].first
- expect(proc.call(Object.new, 1, config._pry_)).to eq('[1] 101(#<Object>):1> ')
- expect(proc.call(Object.new, 1, config._pry_)).to eq('[1] 102(#<Object>):1> ')
end
end
diff --git a/spec/pry_defaults_spec.rb b/spec/pry_defaults_spec.rb
index a0d79424..dd31150e 100644
--- a/spec/pry_defaults_spec.rb
+++ b/spec/pry_defaults_spec.rb
@@ -132,6 +132,12 @@ describe "test Pry defaults" do
Pry.config.output = StringIO.new
end
+ after do
+ %w[test new_test test1 test2 test3].each do |k|
+ Pry::Prompt.instance_variable_get(:@prompts).delete(k)
+ end
+ end
+
def get_prompts(pry)
a = pry.select_prompt
pry.eval "["
@@ -141,15 +147,16 @@ describe "test Pry defaults" do
end
it 'should set the prompt default, and the default should be overridable (single prompt)' do
- Pry.prompt = proc { "test prompt> " }
- new_prompt = proc { "A" }
+ Pry::Prompt.add(:test, 'description') { 'test prompt> ' }
+ Pry.prompt = Pry::Prompt[:test]
+ Pry::Prompt.add(:new_test, 'description') { 'A' }
pry = Pry.new
expect(pry.prompt).to eq Pry.prompt
- expect(get_prompts(pry)).to eq ["test prompt> ", "test prompt> "]
+ expect(get_prompts(pry)).to eq ['test prompt> ', 'test prompt> ']
- pry = Pry.new(prompt: new_prompt)
- expect(pry.prompt).to eq new_prompt
+ pry = Pry.new(prompt: Pry::Prompt[:new_test])
+ expect(pry.prompt).to eq Pry::Prompt[:new_test]
expect(get_prompts(pry)).to eq ["A", "A"]
pry = Pry.new
@@ -158,15 +165,21 @@ describe "test Pry defaults" do
end
it 'should set the prompt default, and the default should be overridable (multi prompt)' do
- Pry.prompt = [proc { "test prompt> " }, proc { "test prompt* " }]
- new_prompt = [proc { "A" }, proc { "B" }]
+ Pry::Prompt.add(:test, 'description', %w[> *]) do |_, _, _, sep|
+ "test prompt#{sep} "
+ end
+ Pry.prompt = Pry::Prompt[:test]
+
+ Pry::Prompt.add(:new_test, 'description') do |_, _, _, sep|
+ sep == '>' ? 'A' : 'B'
+ end
pry = Pry.new
expect(pry.prompt).to eq Pry.prompt
expect(get_prompts(pry)).to eq ["test prompt> ", "test prompt* "]
- pry = Pry.new(prompt: new_prompt)
- expect(pry.prompt).to eq new_prompt
+ pry = Pry.new(prompt: Pry::Prompt[:new_test])
+ expect(pry.prompt).to eq Pry::Prompt[:new_test]
expect(get_prompts(pry)).to eq ["A", "B"]
pry = Pry.new
@@ -176,26 +189,25 @@ describe "test Pry defaults" do
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
+ Pry::Prompt.add(:test1, 'description1') { sep }
+ Pry::Prompt.add(:test2, 'description2') { sep }
+ Pry::Prompt.add(:test3, 'description3') { sep }
+ @pry = Pry.new(prompt: Pry::Prompt[:test1])
end
+
it 'should have a prompt stack' do
- @pry.push_prompt @b
- @pry.push_prompt @c
- expect(@pry.prompt).to eq @c
+ @pry.push_prompt(Pry::Prompt[:test2])
+ @pry.push_prompt(Pry::Prompt[:test3])
+ expect(@pry.prompt).to eq(Pry::Prompt[:test3])
@pry.pop_prompt
- expect(@pry.prompt).to eq @b
+ expect(@pry.prompt).to match(Pry::Prompt[:test2])
@pry.pop_prompt
- expect(@pry.prompt).to eq @a
+ expect(@pry.prompt).to eq(Pry::Prompt[:test1])
end
- it 'should restore overridden prompts when returning from file-mode' do
- pry = Pry.new(prompt: [ proc { 'P>' } ] * 2)
+ it 'should restore overridden prompts when returning from shell-mode' do
+ Pry::Prompt.add(:test, 'description') { 'P>' }
+ pry = Pry.new(prompt: Pry::Prompt[:test])
expect(pry.select_prompt).to eq "P>"
pry.process_command('shell-mode')
expect(pry.select_prompt).to match(/\Apry .* \$ \z/)
@@ -204,32 +216,32 @@ describe "test Pry defaults" do
end
it '#pop_prompt should return the popped prompt' do
- @pry.push_prompt @b
- @pry.push_prompt @c
- expect(@pry.pop_prompt).to eq @c
- expect(@pry.pop_prompt).to eq @b
+ @pry.push_prompt(Pry::Prompt[:test2])
+ @pry.push_prompt(Pry::Prompt[:test3])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test3])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test2])
end
it 'should not pop the last prompt' do
- @pry.push_prompt @b
- expect(@pry.pop_prompt).to eq @b
- expect(@pry.pop_prompt).to eq @a
- expect(@pry.pop_prompt).to eq @a
- expect(@pry.prompt).to eq @a
+ @pry.push_prompt(Pry::Prompt[:test2])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test2])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test1])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test1])
+ expect(@pry.prompt).to eq(Pry::Prompt[:test1])
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
- expect(@pry.prompt).to eq @b
- expect(@pry.pop_prompt).to eq @b
- expect(@pry.pop_prompt).to eq @b
+ @pry.prompt = Pry::Prompt[:test2]
+ expect(@pry.prompt).to eq(Pry::Prompt[:test2])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test2])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test2])
end
it 'when several prompts on the stack' do
- @pry.push_prompt @b
- @pry.prompt = @c
- expect(@pry.pop_prompt).to eq @c
- expect(@pry.pop_prompt).to eq @a
+ @pry.push_prompt(Pry::Prompt[:test2])
+ @pry.prompt = Pry::Prompt[:test3]
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test3])
+ expect(@pry.pop_prompt).to eq(Pry::Prompt[:test1])
end
end
end