5

I'd like to extend the default console application that is built as standard with bundle gem by applying some of the IRB config options.

Looking at the documentation, I can see that it should be possible for instance to change the prompt, and this works fine on an interactive session. For example I can play with the displayed prompt like this:

2.1.4 :001 > conf.prompt_mode=:SIMPLE
=> :SIMPLE
>>
?> conf.prompt_mode=:DEFAULT
=> :DEFAULT
irb(main):004:0>

However, I cannot find how to translate this into syntax for use in the console app. For example this script:

require 'irb'
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.start

Just starts with the generic configured prompt:

2.1.4 :001 >

I have spent some time trying to find an example use of IRB for a custom repl without loading global defaults, but not found anything I can copy from.

I can see that the undocumented method IRB.setup has something to do with this, it is setting all the config somehow. Is my only option to write my own version of IRB.start that applies my desired config after calling IRB.setup, or is there support for what I want to do built-in but not documented in standard location?


E.g. the following works, but I feel it's a bit heavy handed extending IRB module this way (and also prone to failing if IRB internals change).

require 'irb'

def IRB.custom_start custom_conf = {}
  STDOUT.sync = true

  IRB.setup(nil)

  custom_conf.each do |k,v|
    IRB.conf[k] = v
  end

  if @CONF[:SCRIPT]
    irb = IRB::Irb.new(nil, @CONF[:SCRIPT])
  else
    irb = IRB::Irb.new
  end

  @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
  @CONF[:MAIN_CONTEXT] = irb.context

  trap("SIGINT") do
    irb.signal_handle
  end

  begin
    catch(:IRB_EXIT) do
      irb.eval_input
    end
  ensure
    irb_at_exit
  end
end

IRB.custom_start :PROMPT_MODE => :SIMPLE
Neil Slater
  • 26,512
  • 6
  • 76
  • 94

2 Answers2

2

You can apply custom configurations in two ways.

The first one is to use irbrc file. It may be tricky in building console application (calling IRB.start from the ruby file instead of irb from the console).

The second one is the approach that you have described in the post. You can write your own IRB::start method based on the original one. There are exactly the same potential issues as in using undocumented API - it can break in the future with newer versions of irb.

You should think if you really need to build a console application on the top of irb. For example you can solve this problem using Pry. It allows to define configuration before starting interactive session.

Maciej Małecki
  • 2,725
  • 19
  • 29
  • 1
    Thank you for pointing me at Pry again. I looked at it before, but the focus on debugging features made me think it was not suitable. It may well be better than `irb` for me, even if just for the properly documented support to change config programatically. – Neil Slater Sep 27 '16 at 21:31
1
require 'irb'
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.start

The approach above doesn't work because conf[:PROMPT_MODE] gets over-riden in a method called IRB.init_config here

When IRB.start is called, it calls IRB.setup which in turn calls the method IRB.init_config -- which over-rides conf[:PROMPT_MODE] setting.


Here is one approach which solves the problem (relies on internal knowledge of the implementation).

require 'irb'

module IRB
  singleton_class.send(:alias_method, :old_setup, :setup)

  def IRB.setup(ap_path)
    IRB.old_setup(ap_path)

    conf[:PROMPT_MODE] = :SIMPLE
  end
end

IRB.start
Rashmirathi
  • 1,744
  • 12
  • 10
  • This is cleaner than my solution, but does share the problem that it works with the implementation, not the "official" interface. – Neil Slater Sep 29 '16 at 21:20
  • @NeilSlater Yeah, that's why I said it "relies on internal knowledge of the implementation". I guess, `setup` is a public method, hence part of the public interface. It's just not documented very well. – Rashmirathi Sep 29 '16 at 21:28