How to enable auto completion in Ruby's IRB - ruby

When I use Merb's built in console, I get tab auto-completion similar to a standard bash prompt. I find this useful and would like to enable it in non-merb IRB sessions. How do I get auto-completion in IRB?

Just drop require 'irb/completion' in your irbrc.
If that doesn't work try bond, http://tagaholic.me/bond/:
require 'bond'; require 'bond/completion'
Bond not only improves irb's completion, http://tagaholic.me/2009/07/22/better-irb-completion-with-bond.html, but also offers an easy dsl for making custom autocompletions.

This is just repeating the information on Cody Caughlan's comment above so it is easier to find:
either require 'irb/completion' or add the following to ~/.irbrc
IRB.conf[:AUTO_INDENT] = true
IRB.conf[:USE_READLINE] = true
IRB.conf[:LOAD_MODULES] = [] unless IRB.conf.key?(:LOAD_MODULES)
unless IRB.conf[:LOAD_MODULES].include?('irb/completion')
IRB.conf[:LOAD_MODULES] << 'irb/completion'
end

This is what worked for me on Mac OS 10.11.5. using rvm. Do the following :
sudo gem install bond
Create the file .irbrc in your home directory. vi ~/.irbrc
Add the following lines in the .irbrc file
require 'bond'
Bond.start
Save and close the file
Open irb and use tab key to autocomplete

Related

Customising IRB console for gem

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
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.
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

Ruby 'require' error: cannot load such file

I've one file, main.rb with the following content:
require "tokenizer.rb"
The tokenizer.rb file is in the same directory and its content is:
class Tokenizer
def self.tokenize(string)
return string.split(" ")
end
end
If i try to run main.rb I get the following error:
C:\Documents and Settings\my\src\folder>ruby main.rb
C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- tokenizer.rb (LoadError)
from C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require '
from main.rb:1:in `<main>'
I just noticed that if I use load instead of require everything works fine. What may the problem be here?
I just tried and it works with require "./tokenizer".
Just do this:
require_relative 'tokenizer'
If you put this in a Ruby file that is in the same directory as tokenizer.rb, it will work fine no matter what your current working directory (CWD) is.
Explanation of why this is the best way
The other answers claim you should use require './tokenizer', but that is the wrong answer, because it will only work if you run your Ruby process in the same directory that tokenizer.rb is in. Pretty much the only reason to consider using require like that would be if you need to support Ruby 1.8, which doesn't have require_relative.
The require './tokenizer' answer might work for you today, but it unnecessarily limits the ways in which you can run your Ruby code. Tomorrow, if you want to move your files to a different directory, or just want to start your Ruby process from a different directory, you'll have to rethink all of those require statements.
Using require to access files that are on the load path is a fine thing and Ruby gems do it all the time. But you shouldn't start the argument to require with a . unless you are doing something very special and know what you are doing.
When you write code that makes assumptions about its environment, you should think carefully about what assumptions to make. In this case, there are up to three different ways to require the tokenizer file, and each makes a different assumption:
require_relative 'path/to/tokenizer': Assumes that the relative path between the two Ruby source files will stay the same.
require 'path/to/tokenizer': Assumes that path/to/tokenizer is inside one of the directories on the load path ($LOAD_PATH). This generally requires extra setup, since you have to add something to the load path.
require './path/to/tokenizer': Assumes that the relative path from the Ruby process's current working directory to tokenizer.rb is going to stay the same.
I think that for most people and most situations, the assumptions made in options #1 and #2 are more likely to hold true over time.
Ruby 1.9 has removed the current directory from the load path, and so you will need to do a relative require on this file, as David Grayson says:
require_relative 'tokenizer'
There's no need to suffix it with .rb, as Ruby's smart enough to know that's what you mean anyway.
require loads a file from the $LOAD_PATH. If you want to require a file relative to the currently executing file instead of from the $LOAD_PATH, use require_relative.
I would recommend,
load './tokenizer.rb'
Given, that you know the file is in the same working directory.
If you're trying to require it relative to the file, you can use
require_relative 'tokenizer'
I hope this helps.
Another nice little method is to include the current directory in your load path with
$:.unshift('.')
You could push it onto the $: ($LOAD_PATH) array but unshift will force it to load your current working directory before the rest of the load path.
Once you've added your current directory in your load path you don't need to keep specifying
require './tokenizer'
and can just go back to using
require 'tokenizer'
This will work nicely if it is in a gem lib directory and this is the tokenizer.rb
require_relative 'tokenizer/main'
For those who are absolutely sure their relative path is correct, my problem was that my files did not have the .rb extension! (Even though I used RubyMine to create the files and selected that they were Ruby files on creation.)
Double check the file extensions on your file!
What about including the current directory in the search path?
ruby -I. main.rb
I used jruby-1.7.4 to compile my ruby code.
require 'roman-numerals.rb'
is the code which threw the below error.
LoadError: no such file to load -- roman-numerals
require at org/jruby/RubyKernel.java:1054
require at /Users/amanoharan/.rvm/rubies/jruby-1.7.4/lib/ruby/shared/rubygems/custom_require.rb:36
(root) at /Users/amanoharan/Documents/Aptana Studio 3 Workspace/RubyApplication/RubyApplication1/Ruby2.rb:2
I removed rb from require and gave
require 'roman-numerals'
It worked fine.
The problem is that require does not load from the current directory. This is what I thought, too but then I found this thread. For example I tried the following code:
irb> f = File.new('blabla.rb')
=> #<File:blabla.rb>
irb> f.read
=> "class Tokenizer\n def self.tokenize(string)\n return string.split(
\" \")\n end\nend\n"
irb> require f
LoadError: cannot load such file -- blabla.rb
from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
from (irb):24
from D:/dev/Ruby193/bin/irb:12:in `<main>'
As it can be seen it read the file ok, but I could not require it (the path was not recognized). and here goes code that works:
irb f = File.new('D://blabla.rb')
=> #<File:D://blabla.rb>
irb f.read
=> "class Tokenizer\n def self.tokenize(string)\n return string.split(
\" \")\n end\nend\n"
irb> require f
=> true
As you can see if you specify the full path the file loads correctly.
First :
$ sudo gem install colored2
And,you should input your password
Then :
$ sudo gem update --system
Appear
Updating rubygems-update
ERROR: While executing gem ... (OpenSSL::SSL::SSLError)
hostname "gems.ruby-china.org" does not match the server certificate
Then:
$ rvm -v
$ rvm get head
Last
What language do you want to use?? [ Swift / ObjC ]
ObjC
Would you like to include a demo application with your library? [ Yes / No ]
Yes
Which testing frameworks will you use? [ Specta / Kiwi / None ]
None
Would you like to do view based testing? [ Yes / No ]
No
What is your class prefix?
XMG
Running pod install on your new library.
you need to give the path.
Atleast you should give the path from the current directory. It will work for sure.
./filename

irb history not working

in ~/.irbrc i have these lines:
require 'irb/ext/save-history'
#History configuration
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"
and yet when i run irb and hit the up arrow nothing happens. also the irb history file specified is not getting created and nothing is logged to it.
irb history works in Debian Linux out of the box. There's no etc/irbrc, nor do I have a ~/.irbrc. So, hmmmm.
This person put a bit more in his irbrc than you did. Do you suppose the ARGV.concat could be the missing piece?
require 'irb/completion'
require 'irb/ext/save-history'
ARGV.concat [ "--readline", "--prompt-mode", "simple" ]
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"
I don't have an answer for you why the above doesn't work, but I did find a file, /etc/irbrc on my system (OS X - Snow Leopard, Ruby 1.8.7) that does provide a working, persistent history for me. So two pieces of advice: i) check your /etc/irbrc (or equivalent) to make sure that there isn't anything in there that might interfere with your settings, and ii) try out the settings below to see if you can get history working that way.
# Some default enhancements/settings for IRB, based on
# http://wiki.rubygarden.org/Ruby/page/show/Irb/TipsAndTricks
unless defined? ETC_IRBRC_LOADED
# Require RubyGems by default.
require 'rubygems'
# Activate auto-completion.
require 'irb/completion'
# Use the simple prompt if possible.
IRB.conf[:PROMPT_MODE] = :SIMPLE if IRB.conf[:PROMPT_MODE] == :DEFAULT
# Setup permanent history.
HISTFILE = "~/.irb_history"
MAXHISTSIZE = 100
begin
histfile = File::expand_path(HISTFILE)
if File::exists?(histfile)
lines = IO::readlines(histfile).collect { |line| line.chomp }
puts "Read #{lines.nitems} saved history commands from '#{histfile}'." if $VERBOSE
Readline::HISTORY.push(*lines)
else
puts "History file '#{histfile}' was empty or non-existant." if $VERBOSE
end
Kernel::at_exit do
lines = Readline::HISTORY.to_a.reverse.uniq.reverse
lines = lines[-MAXHISTSIZE, MAXHISTSIZE] if lines.nitems > MAXHISTSIZE
puts "Saving #{lines.length} history lines to '#{histfile}'." if $VERBOSE
File::open(histfile, File::WRONLY|File::CREAT|File::TRUNC) { |io| io.puts lines.join("\n") }
end
rescue => e
puts "Error when configuring permanent history: #{e}" if $VERBOSE
end
ETC_IRBRC_LOADED=true
end
This is a known bug with a patch available. Easiest solution is to overwrite save-history.rb:
/usr/lib/ruby/1.8/irb/ext/save-history.rb
with a fixed version:
http://pastie.org/513500
or to do it in one go:
wget -O /usr/lib/ruby/1.8/irb/ext/save-history.rb http://pastie.org/pastes/513500/download
Check to make sure you built ruby with libreadline as irb history seems to not work without it.
This may also happen if you have extra irb config file, e.g. ~/.irbrc. If this is the case, copy the content from liwp's answer to the extra config and it should work.
I had the same problem on ubuntu 20.04 and fixed it by running:
gem install irb

How do I drop to the IRB prompt from a running script?

Can I drop to an IRB prompt from a running Ruby script?
I want to run a script, but then have it give me an IRB prompt at a point in the program with the current state of the program, but not just by running rdebug and having a breakpoint.
Pry (an IRB alternative) also lets you do this, in fact it was designed from the ground up for exactly this use case :)
It's as easy as putting binding.pry at the point you want to start the session:
require 'pry'
x = 10
binding.pry
And inside the session:
pry(main)> puts x
=> 10
Check out the website: http://pry.github.com
Pry let's you:
drop into a session at any point in your code
view method source code
view method documentation (not using RI so you dont have to pre-generate it)
pop in and out of different contexts
syntax highlighting
gist integration
view and replay history
open editors to edit methods using edit obj.my_method syntax
A tonne more great and original features
you can use ruby-debug to get access to irb
require 'rubygems'
require 'ruby-debug'
x = 23
puts "welcome"
debugger
puts "end"
when program reaches debugger you will get access to irb.
apparently it requires a chunk of code to drop into irb.
Here's the link (seems to work well).
http://jameskilton.com/2009/04/02/embedding-irb-into-your-ruby-application
require 'irb'
module IRB
def self.start_session(binding) # call this method to drop into irb
unless #__initialized
args = ARGV
ARGV.replace(ARGV.dup)
IRB.setup(nil)
ARGV.replace(args)
#__initialized = true
end
workspace = WorkSpace.new(binding)
irb = Irb.new(workspace)
#CONF[:IRB_RC].call(irb.context) if #CONF[:IRB_RC]
#CONF[:MAIN_CONTEXT] = irb.context
catch(:IRB_EXIT) do
irb.eval_input
end
end
end
This feature is available from Ruby 2.4. You can just use binding.irb
E.g.
require 'irb'
a = 10
binding.irb
puts a
If you run above code, you will get irb console, so that you can inspect values of local variables and anything else that is in scope.
Source: http://blog.redpanthers.co/new-binding-irb-introduced-ruby-2-4/
Ruby commit: https://github.com/ruby/ruby/commit/493e48897421d176a8faf0f0820323d79ecdf94a
Just add this line to where you want the breakpoint:
require 'ruby-debug';debugger
but i suggest use pry instead of irb, which is super handy, insert the following line instead:
require 'pry'; binding.pry
I'm quite late to the game but if you're loading a script from within irb/pry already, a simple raise also works to pop you back out to the irb/pry prompt. I use this quite often when writing one off scripts within the rails console.

Open the default browser in Ruby

In Python, you can do this:
import webbrowser
webbrowser.open_new("http://example.com/")
It will open the passed in url in the default browser
Is there a ruby equivalent?
Cross-platform solution:
First, install the Launchy gem:
$ gem install launchy
Then, you can run this:
require 'launchy'
Launchy.open("http://stackoverflow.com")
This should work on most platforms:
link = "Insert desired link location here"
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
system "start #{link}"
elsif RbConfig::CONFIG['host_os'] =~ /darwin/
system "open #{link}"
elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
system "xdg-open #{link}"
end
Mac-only solution:
system("open", "http://stackoverflow.com/")
or
`open http://stackoverflow.com/`
Simplest Win solution:
`start http://www.example.com`
Linux-only solution
system("xdg-open", "http://stackoverflow.com/")
This also works:
system("start #{link}")
Windows Only Solution:
require 'win32ole'
shell = WIN32OLE.new('Shell.Application')
shell.ShellExecute(...)
Shell Execute on MSDN
You can use the 'os' gem: https://github.com/rdp/os to let your operating system (in the best case you own your OS, meaning not OS X) decide what to do with an URL.
Typically this will be a good choice.
require 'os'
system(OS.open_file_command, 'https://stackoverflow.com')
# ~ like `xdg-open stackoverflow.com` on most modern unixoids,
# but should work on most other operating systems, too.
Note On windows, the argument(s?) to system need to be escaped, see comment section. There should be a function in Rubys stdlib for that, feel free to add it to the comments and I will update the answer.
If it's windows and it's IE, try this: http://rubyonwindows.blogspot.com/search/label/watir also check out Selenium ruby: http://selenium.rubyforge.org/getting-started.html
HTH

Resources