class Pry # Prompt represents the Pry prompt, which can be used with Readline-like # libraries. It defines a few default prompts (default prompt, simple prompt, # etc) and also provides an API to add custom prompts. # # @example # Pry::Prompt.add( # :ipython, # 'IPython-like prompt', [':', '...:'] # ) do |_context, _nesting, _pry_, sep| # sep == ':' ? "In [#{_pry_.input_ring.count}]: " : ' ...: ' # end # # # Produces: # # In [3]: def foo # # ...: puts 'foo' # # ...: end # # => :foo # # In [4]: # @since v0.11.0 # @api public module Prompt # @return [String] DEFAULT_NAME = 'pry'.freeze # @return [Array] the list of objects that are known to have a # 1-line #inspect output suitable for prompt SAFE_CONTEXTS = [String, Numeric, Symbol, nil, true, false].freeze # @deprecated Use {Pry::Prompt.add} instead. MAP = {} deprecate_constant(:MAP) if respond_to?(:deprecate_constant) # A Hash that holds all prompts. The keys of the Hash are prompt # names, the values are Hash instances of the format {:description, :value}. @prompts = {} class << self # Retrieves a prompt. # # @example # Prompt[:my_prompt][:value] # # @param [Symbol] prompt_name The name of the prompt you want to access # @return [Hash{Symbol=>Object}] # @since v0.12.0 def [](prompt_name) all[prompt_name.to_s] end # @return [Hash{Symbol=>Hash}] the duplicate of the internal prompts hash # @note Use this for read-only operations # @since v0.12.0 def all @prompts.dup end # Adds a new prompt to the prompt hash. # # @param [Symbol] prompt_name # @param [String] description # @param [Array] separators The separators to differentiate # between prompt modes (default mode and class/method definition mode). # The Array *must* have a size of 2. # @yield [context, nesting, _pry_, sep] # @yieldparam context [Object] the context where Pry is currently in # @yieldparam nesting [Integer] whether the context is nested # @yieldparam _pry_ [Pry] the Pry instance # @yieldparam separator [String] separator string # @return [nil] # @raise [ArgumentError] if the size of `separators` is not 2 # @since v0.12.0 def add(prompt_name, description = '', separators = %w[> *]) unless separators.size == 2 raise ArgumentError, "separators size must be 2, given #{separators.size}" end @prompts[prompt_name.to_s] = { description: description, value: separators.map do |sep| proc { |context, nesting, _pry_| yield(context, nesting, _pry_, sep) } end } nil end private def prompt_name(name) return name unless name.is_a?(Pry::Config::Lazy) name.call 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| format( "[%s] %s(%s)%s%s ", in_count: _pry_.input_ring.count, name: prompt_name(_pry_.config.prompt_name), context: Pry.view_clip(context), nesting: (nesting > 0 ? ":#{nesting}" : ''), separator: sep ) end add( 'simple', "A simple `>>`.", ['>> ', ' | '] ) do |_, _, _, sep| sep end add( '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[> *] ) do |context, nesting, _pry_, sep| tree = _pry_.binding_stack.map { |b| Pry.view_clip(b.eval('self')) } format( "[%s] (%s) %s: %s%s ", in_count: _pry_.input_ring.count, name: prompt_name(_pry_.config.prompt_name), tree: tree.join(' / '), stack_size: _pry_.binding_stack.size - 1, separator: sep ) end add( 'shell', 'A prompt that displays `$PWD` as you change it.', %w[$ *] ) do |context, nesting, _pry_, sep| format( "%s %s:%s %s ", name: prompt_name(_pry_.config.prompt_name), context: Pry.view_clip(context), pwd: Dir.pwd, separator: sep ) end add( 'none', 'Wave goodbye to the Pry prompt.', Array.new(2) ) { '' } end end