Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customising IRB console for gem

Tags:

ruby

irb

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
like image 597
Neil Slater Avatar asked Oct 19 '22 01:10

Neil Slater


2 Answers

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.

like image 66
Maciej Małecki Avatar answered Oct 21 '22 06:10

Maciej Małecki


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
like image 42
Rashmirathi Avatar answered Oct 21 '22 06:10

Rashmirathi