From ace907b1b1959589ed56d24df5e481b90fcb665c Mon Sep 17 00:00:00 2001 From: Kyrylo Silin Date: Sun, 28 Oct 2018 19:02:14 +0800 Subject: [PATCH] prompt: make it possible to set name dynamically Fixes #1738 (Possible to make prompt_name dynamic?) The user-facing API is the following: ```rb Pry.config.prompt_name = Pry.lazy { rand(100) } [1] 80(main)> [2] 87(main)> [3] 30(main)> ``` --- lib/pry/config.rb | 26 ++++++++++++++++++++++++++ lib/pry/prompt.rb | 12 +++++++++--- lib/pry/pry_class.rb | 18 ++++++++++++++++++ spec/prompt_spec.rb | 19 ++++++++++++++++++- 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/lib/pry/config.rb b/lib/pry/config.rb index 2b1599c2..72da57ce 100644 --- a/lib/pry/config.rb +++ b/lib/pry/config.rb @@ -1,5 +1,31 @@ class Pry + # The Pry config. + # @api public class Config < Pry::BasicObject + # Wraps a block so it can have a name. + # + # @example + # proc1 = proc {} + # proc2 = Pry::Config::Lazy.new(&proc {}) + # + # proc1.is_a?(Pry::Config::Lazy) + # #=> false + # proc2.is_a?(Pry::Config::Lazy) + # #=> true + # + # @api private + # @since v0.12.0 + class Lazy + def initialize(&block) + @block = block + end + + # @return [Object] + def call + @block.call + end + end + include Behavior def self.shortcuts diff --git a/lib/pry/prompt.rb b/lib/pry/prompt.rb index 5ec3656f..072214b0 100644 --- a/lib/pry/prompt.rb +++ b/lib/pry/prompt.rb @@ -31,7 +31,7 @@ class Pry format( DEFAULT_TEMPLATE, in_count: _pry_.input_ring.count, - name: _pry_.config.prompt_name, + name: prompt_name(_pry_.config.prompt_name), context: Pry.view_clip(context), nesting: (nesting > 0 ? ":#{nesting}" : ''), separator: separator @@ -44,7 +44,7 @@ class Pry proc do |context, _nesting, _pry_| format( SHELL_TEMPLATE, - name: _pry_.config.prompt_name, + name: prompt_name(_pry_.config.prompt_name), context: Pry.view_clip(context), pwd: Dir.pwd, separator: separator @@ -59,12 +59,18 @@ class Pry format( NAV_TEMPLATE, in_count: _pry_.input_ring.count, - name: _pry_.config.prompt_name, + name: prompt_name(_pry_.config.prompt_name), tree: tree.join(' / '), stack_size: _pry_.binding_stack.size - 1 ) end end + + def prompt_name(name) + return name unless name.is_a?(Pry::Config::Lazy) + + name.call + end end # The default Pry prompt, which includes the context and nesting level. diff --git a/lib/pry/pry_class.rb b/lib/pry/pry_class.rb index d73339a0..356a2127 100644 --- a/lib/pry/pry_class.rb +++ b/lib/pry/pry_class.rb @@ -406,6 +406,24 @@ Readline version #{Readline::VERSION} detected - will not auto_resize! correctly ensure Thread.current[:pry_critical_section] -= 1 end + + # Wraps a block in a named block called `Pry::Config::Lazy`. This is used for + # dynamic config values, which are calculated every time + # {Pry::Config::Lazy#call} is called. + # + # @example + # # pryrc + # Pry.config.prompt_name = Pry.lazy { rand(100) } + # + # # Session + # [1] 96(main)> + # [2] 19(main)> + # [3] 80(main)> + # + # @return [#call] + def self.lazy(&block) + Pry::Config::Lazy.new(&block) + end end Pry.init diff --git a/spec/prompt_spec.rb b/spec/prompt_spec.rb index 1b0018a9..d376e5ec 100644 --- a/spec/prompt_spec.rb +++ b/spec/prompt_spec.rb @@ -1,6 +1,6 @@ require_relative 'helper' -describe "Prompts" do +describe Pry::Prompt do describe "one-parameter prompt proc" do it 'should get full config object' do config = nil @@ -67,4 +67,21 @@ describe "Prompts" do 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 }) + end + + enum = Enumerator.new do |y| + count = 100 + loop { y << count += 1 } + end + config._pry_.config.prompt_name = Pry.lazy { enum.next } + + proc = subject::DEFAULT.first + expect(proc.call(Object.new, 1, config._pry_)).to eq('[1] 101(#):1> ') + expect(proc.call(Object.new, 1, config._pry_)).to eq('[1] 102(#):1> ') + end end