Search code examples
debuggingconfigurationprypry-rails

How can I set my Pry prompt to be the current timestamp?


When I put the following line into ~/.pryrc it doesn't work as expected:

Pry.config.prompt_name = Time.now.to_s

Every prompt is equal to the time that Pry was launched.

How do I update the prompt with the current timestamp, each time the prompt is displayed (after each call)?


Solution

  • To whoever find this useful, I added the timestamp to .pryrc in this way.
    Keep an eye to my comments in the code, as the pry code has changed from time on time, also the way to add a timestamp to the prompt:

    # Unrelated, but it could be useful for you to print the current Rails env
    def rails_prompt
      # Maybe this is only running as `pry` an not `rails console`, so check first
      return '' unless defined? Rails
    
      app_env =
        if Rails.env.production?
          puts "\n\e[1m\e[41mWARNING: YOU ARE USING RAILS CONSOLE IN PRODUCTION!\n" \
                "Changing data can cause serious data loss.\n" \
                "Make sure you know what you're doing.\e[0m\e[22m\n\n"
          "\e[31m#{Rails.env[0...4]}\e[0m" # red
        else
          "\e[32m#{Rails.env[0...4]}\e[0m" # green
        end
      "(\e[1m#{app_env}\e[22m)" # bold
    end
    
    # This will generate a timestamp like 11:11:51NZST but change it any other
    # format you're expecting
    now = proc { Time.new.strftime('%T%Z') }
    
    # This worked for me with pry 0.10.1, but probably will work with older/not so
    # new versions?
    # == START 0.10.1 CODE ==
    def_proc = proc { |target_self, nest_level, pry|
      "[#{pry.input_array.size}][#{now.call}] "\
      "(#{Pry.view_clip(target_self)})"\
      "#{":#{nest_level}" unless nest_level.zero?}#{rails_prompt}"
    }
    Pry.config.prompt = [
      proc { |t, n, p| "#{def_proc.call(t, n, p)}> " },
      proc { |t, n, p| "#{def_proc.call(t, n, p)}* " }
    ]
    # == END 0.10.1 CODE ==
    
    # so, eventually I updated to 0.12.2 and I had to change stuff. This will be the
    # proc to be called to evaluate the current prompt status
    custom_prompt = proc { |context, nesting, pry_instance, sep|
      format(
        's[%<in_count>s][%<timestamp>s] %<name>s(%<context>s)%<rails_prompt>s%<nesting>s%<separator>s ',
        in_count: pry_instance.input_ring.count,
        timestamp: now.call,
        name: pry_instance.config.prompt_name,
        context: Pry.view_clip(context),
        rails_prompt: rails_prompt,
        nesting: (nesting > 0 ? ":#{nesting}" : ''),
        separator: sep
      )
    }
    
    # == START 0.12.2 CODE ==
    Pry::Prompt.add(:default_with_time, 'The same default, but with timestamp') do
      |context, nesting, pry_instance, sep|
      custom_prompt.call(context, nesting, pry_instance, sep)
    end
    Pry.config.prompt = Pry::Prompt[:default_with_time][:value]
    # == END 0.12.2 CODE ==
    
    # and my last update was to pry 0.14.0 and I had to tweak the code again. The
    # prompt status proc is the same as in 0.12.2, but is passed as parameter in a
    # different way.
    Pry.config.prompt = Pry::Prompt.new(
      :default_with_time,
      'The same default, but with timestamp',
      [custom_prompt]
    )
    

    Then you will get a prompt like this: enter image description here

    As reference, I took part of the default prompt format and I adapted it to my needs, so maybe this will change again for newer versions (or maybe not, who knows).