How to format irb command prompt - ruby

Previously I was using Ruby 1.8 and my irb command prompt used to look like this:
Air ~: irb
>> a = 1
=> 1
>> b = 2
=> 2
>> a + b
=> 3
I installed rvm (and Ruby 1.9.2) and now my irb command prompt looks like this:
Air ~: irb
ruby-1.9.2-p180 :001 > a = 1
=> 1
ruby-1.9.2-p180 :002 > b = 2
=> 2
ruby-1.9.2-p180 :003 > a + b
=> 3
Is there a way to remove the ruby-1.9.2-p180 :001 from the command line?

The irb man page has a section on "Customizing prompt". Here's mine for example:
IRB.conf[:PROMPT][:CUSTOM] = {
:PROMPT_I => ">> ",
:PROMPT_S => "%l>> ",
:PROMPT_C => ".. ",
:PROMPT_N => ".. ",
:RETURN => "=> %s\n"
}
IRB.conf[:PROMPT_MODE] = :CUSTOM
IRB.conf[:AUTO_INDENT] = true
To use this, add it to your ~/.irbrc file (creating it if it doesn't exist.)

In your ~/.irbrc, simply add
IRB.conf[:PROMPT_MODE] = :SIMPLE

When you would usually run the irb command, try running irb --simple-prompt instead. That greatly shortens the prompt and makes it easier to understand.

irb --simple-prompt
saw this in Lynda.com

To avoid giving the prompt you wish on the command line all the time, you can configure the prompt via the ~/.irbrc config file:
$ echo "IRB.conf[:PROMPT_MODE] = :DEFAULT" > ~/.irbrc
$ irb
irb(main):001:0> quit
$ echo "IRB.conf[:PROMPT_MODE] = :SIMPLE" > ~/.irbrc
$ irb
>> quit
$

Whoever want to add a prompt timestamp, this isn't possible yet (check "special strings" section), so I implemented it in a monkey-patchy way:
module IrbTimePrompt
def prompt(prompt, ltype, indent, line_no)
# I used %T as time format, but you could use whatever you want to.
# Check https://apidock.com/ruby/Time/strftime for more options
p = prompt.dup.gsub(/%t/, Time.new.strftime('%T'))
super(p, ltype, indent, line_no)
end
end
module IRB
class Irb
prepend IrbTimePrompt
end
end
Now, add this to your lib/ project folder (in case is a Rails project, ensure lib/ is part of config.autoload_paths in config/application.rb) or in a more aggresive way (not recommended), look for lib/irb.rb file in your local ruby instance and in def prompt method, add a new when condition to the method, like:
when "t"
Time.now.strftime('%-d-%-m %T%Z')
then in your .irbrc file (it could be located in your home folder or root project folder) you could modify your prompt. I'm adding my current prompt, but please adjust it to your needs:
def rails_prompt
# This is my base prompt, displaying line number and time
def_prompt = '[%01n][%t]'
# Maybe you're only running as `irb` an not `rails console`, so check first
# if rails is available
if defined? Rails
app_env = Rails.env[0...4]
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"
app_env = "\e[31m#{app_env}\e[0m" # red
else
app_env = "\e[32m#{app_env}\e[0m" # green
end
def_prompt << "(\e[1m#{app_env}\e[22m)" # bold
end
IRB.conf[:PROMPT] ||= {}
IRB.conf[:PROMPT][:WITH_TIME] = {
PROMPT_I: "#{def_prompt}> ",
PROMPT_N: "#{def_prompt}| ",
PROMPT_C: "#{def_prompt}| ",
PROMPT_S: "#{def_prompt}%l ",
RETURN: "=> %s\n",
AUTO_INDENT: true,
}
IRB.conf[:PROMPT_MODE] = :WITH_TIME
end
rails_prompt
Then start irb or rails console and check the awesomeness:
[1][13:01:15](deve)> 'say hello to your new prompt'
=> "say hello to your new prompt"
[2][13:01:23](deve)>

See this note about IRB prompt in RVM.
Note that you can create a .irbrc file in your home folder for various settings for IRB.
For example, see "Configuring the Prompt" in this document
You can also puts IRB.conf[:PROMPT_MODE] or puts IRB.conf to see all the various settings currently in effect. For example, the :PROMPT_MODE is probably set to "RVM" in your case.

Related

TOPLEVEL_BINDING difference in irb and script

If i put the following code:
a = 42
p TOPLEVEL_BINDING.local_variable_defined?(:a)
in a file "rubyScratch.rb" and ruby it using
ruby rubyScratch.rb
I get
true
However in irb I get
2.3.1 :001 > a = 42
=> 42
2.3.1 :002 > TOPLEVEL_BINDING.local_variable_defined?(:a)
=> false
Why is there this difference?
This is because the irb command (on my system, anyways) runs a small ruby script that looks like this:
#!/usr/bin/env ruby
#
# irb.rb - interactive ruby
# $Release Version: 0.9.6 $
# $Revision: 40560 $
# by Keiju ISHITSUKA(keiju#ruby-lang.org)
#
require "irb"
IRB.start(__FILE__)
So, the TOPLEVEL_BINDING is this script and not your IRB context.
While looking for some more information, I ran across this short article which states:
It is, as its name suggest, the Binding of your script's main scope:
a = 42
p binding.local_variable_defined?(:a) # => true
p TOPLEVEL_BINDING.local_variable_defined?(:a) # => true
def example_method
p binding.local_variable_defined?(:a) # => false
p TOPLEVEL_BINDING.local_variable_defined?(:a) # => true
end
example_method
To summarize, the TOPLEVEL_BINDING is the binding for the first script in the current context that was run by the Ruby VM. When running IRB, that script is the one that starts the IRB session.

How to allow users to edit given string via $stdin in ruby

I'm searching to allows users to edit an existing string.
Edit the following string: Edit me
# After user delete and add characters
Edit the following string: Edit you
I thought to prepend some data to the $stdin but seems like it's not possible and anyway IMHO it's a too radical solution.
Someone told me to use GNU Readline's Ruby wrapper so I've taken a quick look and I found Readline#pre_input_hook which acts before Readline start taking the input.
I tried:
require 'readline'
Readline.pre_input_hook = -> { "Edit me" }
result = Readline.readline("Edit the following string: ")
puts result
But seems not work.
begin
system("stty raw -echo")
print (acc = "Edit me: ")
loop.each_with_object(acc) do |_,acc|
sym = $stdin.getc
case sym.ord
when 13 # carriage return
break acc
when 127 # backspace
print "\e[1D \e[1D"
acc.slice!(acc.length - 1) if acc.length > 0
else # regular symbol
print sym
acc << sym
end
end
ensure
system("stty -raw echo")
puts
puts "\e[0mEntered: |#{acc}|"
end
Here you go. More info on terminal control sequences. Also, ANSI terminal codes.
I found prompt.ask from tty-prompt fulfilled my need:
$ gem install tty-prompt
$ irb
irb(main):001:0> require "tty-prompt"
=> true
irb(main):002:0> prompt = TTY::Prompt.new
=> #<TTY::Prompt prefix="" quiet=false enabled_color=nil active_color=:green
error_color=:red help_color=:bright_black input=#<IO:<ST...
irb(main):003:0> prompt.ask("What is your name?", default: ENV["USER"])
What is your name? xxx
=> "xxx"
irb(main):004:0> prompt.ask("What is your name?", value: "Mike")
What is your name? Michael
=> "Michael"

How to change to color of the Command Prompt [duplicate]

Previously I was using Ruby 1.8 and my irb command prompt used to look like this:
Air ~: irb
>> a = 1
=> 1
>> b = 2
=> 2
>> a + b
=> 3
I installed rvm (and Ruby 1.9.2) and now my irb command prompt looks like this:
Air ~: irb
ruby-1.9.2-p180 :001 > a = 1
=> 1
ruby-1.9.2-p180 :002 > b = 2
=> 2
ruby-1.9.2-p180 :003 > a + b
=> 3
Is there a way to remove the ruby-1.9.2-p180 :001 from the command line?
The irb man page has a section on "Customizing prompt". Here's mine for example:
IRB.conf[:PROMPT][:CUSTOM] = {
:PROMPT_I => ">> ",
:PROMPT_S => "%l>> ",
:PROMPT_C => ".. ",
:PROMPT_N => ".. ",
:RETURN => "=> %s\n"
}
IRB.conf[:PROMPT_MODE] = :CUSTOM
IRB.conf[:AUTO_INDENT] = true
To use this, add it to your ~/.irbrc file (creating it if it doesn't exist.)
In your ~/.irbrc, simply add
IRB.conf[:PROMPT_MODE] = :SIMPLE
When you would usually run the irb command, try running irb --simple-prompt instead. That greatly shortens the prompt and makes it easier to understand.
irb --simple-prompt
saw this in Lynda.com
To avoid giving the prompt you wish on the command line all the time, you can configure the prompt via the ~/.irbrc config file:
$ echo "IRB.conf[:PROMPT_MODE] = :DEFAULT" > ~/.irbrc
$ irb
irb(main):001:0> quit
$ echo "IRB.conf[:PROMPT_MODE] = :SIMPLE" > ~/.irbrc
$ irb
>> quit
$
Whoever want to add a prompt timestamp, this isn't possible yet (check "special strings" section), so I implemented it in a monkey-patchy way:
module IrbTimePrompt
def prompt(prompt, ltype, indent, line_no)
# I used %T as time format, but you could use whatever you want to.
# Check https://apidock.com/ruby/Time/strftime for more options
p = prompt.dup.gsub(/%t/, Time.new.strftime('%T'))
super(p, ltype, indent, line_no)
end
end
module IRB
class Irb
prepend IrbTimePrompt
end
end
Now, add this to your lib/ project folder (in case is a Rails project, ensure lib/ is part of config.autoload_paths in config/application.rb) or in a more aggresive way (not recommended), look for lib/irb.rb file in your local ruby instance and in def prompt method, add a new when condition to the method, like:
when "t"
Time.now.strftime('%-d-%-m %T%Z')
then in your .irbrc file (it could be located in your home folder or root project folder) you could modify your prompt. I'm adding my current prompt, but please adjust it to your needs:
def rails_prompt
# This is my base prompt, displaying line number and time
def_prompt = '[%01n][%t]'
# Maybe you're only running as `irb` an not `rails console`, so check first
# if rails is available
if defined? Rails
app_env = Rails.env[0...4]
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"
app_env = "\e[31m#{app_env}\e[0m" # red
else
app_env = "\e[32m#{app_env}\e[0m" # green
end
def_prompt << "(\e[1m#{app_env}\e[22m)" # bold
end
IRB.conf[:PROMPT] ||= {}
IRB.conf[:PROMPT][:WITH_TIME] = {
PROMPT_I: "#{def_prompt}> ",
PROMPT_N: "#{def_prompt}| ",
PROMPT_C: "#{def_prompt}| ",
PROMPT_S: "#{def_prompt}%l ",
RETURN: "=> %s\n",
AUTO_INDENT: true,
}
IRB.conf[:PROMPT_MODE] = :WITH_TIME
end
rails_prompt
Then start irb or rails console and check the awesomeness:
[1][13:01:15](deve)> 'say hello to your new prompt'
=> "say hello to your new prompt"
[2][13:01:23](deve)>
See this note about IRB prompt in RVM.
Note that you can create a .irbrc file in your home folder for various settings for IRB.
For example, see "Configuring the Prompt" in this document
You can also puts IRB.conf[:PROMPT_MODE] or puts IRB.conf to see all the various settings currently in effect. For example, the :PROMPT_MODE is probably set to "RVM" in your case.

Is it possible to configure the IRB prompt to change dynamically?

I'd like to navigate around the filesystem in IRB and have the prompt change to reflect the current working directory, but I can't figure out how to make the prompt update after each command. Ultimately I'd like to use IRB in day to day work a lot more and let bash slip away. I tried this in my .irbrc:
require 'fileutils'
include FileUtils
IRB.conf[:PROMPT][:CUSTOM] = {
:PROMPT_N => "\e[1m:\e[m ",
:PROMPT_I => "\e[1m#{pwd} >\e[m ",
:PROMPT_S => "FOO",
:PROMPT_C => "\e[1m#{pwd} >\e[m ",
:RETURN => ""
}
IRB.conf[:PROMPT_MODE] = :CUSTOM
But the IRB prompt is not updated:
julianmann#mango:~ > irb
/users/julianmann > puts pwd
/users/julianmann
/users/julianmann > cd 'dev'
/users/julianmann > puts pwd
/users/julianmann/dev
/users/julianmann >
I'd really like the prompt to change.
Here's a quick hack to get the working dir. It's sort of fragile, but it worked on ruby 1.8.7 and 1.9.2.
Set your prompt string to something like this:
"%N(%m):%03n:%i %~> ".tap {|s| def s.dup; gsub('%~', Dir.pwd); end }
The "%~" directive is not understood by irb itself, so I used it to do the replacement. This hack relies on the fact that irb calls dup to generate the prompt.
Another option is to use fresh. It's based on the irb alternative ripl and also shows the current directory as its prompt :]
You have to run(alias) irb like so
irb --prompt custom
Or alternatively add IRB.conf[:PROMPT_MODE] = :CUSTOM to your .irbrc
P.S. This isn't an EXACT answer to your question. But you might try using RUSH.
It doesn't have the concept of a current working directory, but it is easily configurable.
Its kind of static though
but have a look, it may help you
IN Linux ( Ubuntu 14.04)
You can change the irritating prompt of the irb console just by following some simple steps
Open your terminal
goto the location /home/leapfrog/.rvm/scripts
$ cd ~/.rvm/scripts
Open the file ‘irbrc.rb’, use superuser power to over-write the
$ sudo gedit irbrc.rb
You can see a portion of code like this. Replace the former with latter codes
# Set up the prompt to be RVM specific.
##prompt = {
# :PROMPT_I => "#{rvm_ruby_string} :%03n > ", # default prompt
# :PROMPT_S => "#{rvm_ruby_string} :%03n%l> ", # known continuation
# :PROMPT_C => "#{rvm_ruby_string} :%03n > ",
# :PROMPT_N => "#{rvm_ruby_string} :%03n?> ", # unknown continuation
# :RETURN => " => %s \n",
# :AUTO_INDENT => true
#}
#prompt = {
:PROMPT_I => "ROR: %03n > ", # default prompt
:PROMPT_S => "%03n%l> ", # known continuation
:PROMPT_C => "%03n > ",
:PROMPT_N => "%03n?> ", # unknown continuation
:RETURN => " O/P => %s \n",
:AUTO_INDENT => true
}
Just save the file and restart the irb console
Further mode you can see this link
https://cbabhusal.wordpress.com/2014/12/22/ruby-rvm-change-prompt-of-irb/
If it may serve to contribute to the discussion, albeit belatedly: It may be possible to change the prompt after the IRB environment is initialized, such as via some values on IRB.conf[:MAIN_CONTEXT]
For a binding of c = IRB.conf[:MAIN_CONTEXT] the fields affecting prompt formatting may include the following
c.prompt_c
c.prompt_i
c.prompt_n
c.prompt_s
c.return_format
c.auto_indent_mode
c.prompt_mode
An example in updating the prompt_i field directly:
irb(main):009:0> IRB.conf[:MAIN_CONTEXT].prompt_i="%N %m %i >>"
=> "%N %m %i >>"
irb main 0 >>
Outside of the set of formatting specifiers documented in the IRB module documentation (3.0.0) it may not be supported - at present - to use an expression that would be evaluated when the prompt is displayed, in IRB. Each of the prompt strings may be used as simply a literal format string.
With some limitations albeit, but it may be possible to update the IRB prompt after IRB is initialized.
Disclaimer: This is not guaranteed to update all state values related to the prompt, under IRB.conf[:MAIN_CONTEXT]

⌃⇧H in TextMate to 'Tidy' HTML causes NoMethodError

I tried using 'Tidy' in an HTML document for the first time yesterday, and got...
/tmp/temp_textmate.Z2P0KX:30:in `<main>': undefined method `empty?' for nil:NilClass (NoMethodError)
I've not done anything to the code in the bundle...
#!/usr/bin/env ruby -wKU
require ENV['TM_SUPPORT_PATH'] + '/lib/ui.rb'
require ENV['TM_SUPPORT_PATH'] + '/lib/exit_codes.rb'
result = `"${TM_TIDY:-tidy}" -f /tmp/tm_tidy_errors -iq -utf8 \
-wrap 0 --tab-size $TM_TAB_SIZE --indent-spaces $TM_TAB_SIZE \
--indent yes \
${TM_XHTML:+-asxhtml --output-xhtml yes} \
${TM_SELECTED_TEXT:+--show-body-only yes} \
--enclose-text yes \
--doctype strict \
--wrap-php no \
--tidy-mark no`
status = $?.exitstatus
at_exit { File.unlink('/tmp/tm_tidy_errors') } # Clean up error log
if status == 2 # Errors
msg = "Errors: " + File.read('/tmp/tm_tidy_errors')
TextMate.exit_show_tool_tip msg
elsif status == 1 # Warnings - use output but also display notification with warnings
log = File.read('/tmp/tm_tidy_errors').to_a.select do |line|
! (ENV['TM_SELECTED_TEXT'] and (line.include?('Warning: missing <!DOCTYPE> declaration') or line.include?("Warning: inserting missing 'title' element")))
end.join rescue nil
unless log.empty?
options = {
:title => "Tidy Warnings",
:summary => "Warnings for tidying your document (press escape to close):",
:log => log
}
TextMate::UI.simple_notification(options)
end
end
if ENV['TM_SOFT_TABS'] == "YES"
print result
else
in_pre = false
result.each_line do |line|
unless in_pre
tab_size = ENV["TM_TAB_SIZE"].to_i
space, text = /( *)(.*)/m.match(line)[1..2]
line = "\t" * (space.length / tab_size).floor + " " * (space.length % tab_size) + text
end
print line
in_pre = true if line.include?("<pre>")
in_pre = false if line.include?("</pre>")
end
end
The problem line is unless log.empty?.
I'm running TextMate 1.5.10 (1631) on OS X 10.6.6. I recently installed rvm and upgraded default Ruby to 1.9.2, though forcing TextMate to use 1.8.7 did not fix the problem.
I had the same problem. I have setup my Textmate to use the RVM version of ruby so that I can quickly test scripts.
I solved the problem by unchecking the "TM_RUBY" for the environment variable I had created.
What appears to be happening is the Textmate scripts that wrapper the /usr/bin/tidy command are not executing properly when using a ruby version other than the one that ships with OSX.
I'm curious to see what happens when Lion comes out. Hopefully, Textmate will take another look at these build-in scripts and give them a little "dusting-off".
If you look at the assignment to log, you'll see this:
log = File.read('/tmp/tm_tidy_errors').to_a.select do |line| ... end.join rescue nil
The rescue nil at the end will put a nil into log if the /tmp/tm_tidy_errors file isn't there or it can't be read or what ever. Then the script will call the .empty? method on nil but the nil object has no such method and the script falls over and dies.
You can suppress the problem by changing rescue nil to rescue '' or by changing unless log.empty? to unless log.nil? || log.empty? but that might not be the real problem.
Do you have a TM_TIDY environment variable set? Is there a tidy command in your PATH? Looks like your Tidy install isn't right (or possible not there at all). My OSX has /usr/bin/tidy and apparently that's standard. Try running that big tidy command by hand in a terminal and see what happens.
I had the same problem too, on a machine running OS X 10.9.5 with Ruby upgraded to ruby 2.0.0. Fixed it by taking mu is too short's suggestion to change unless log.empty? to unless long.nil? || log.empty?. That allowed Tidy to run properly, but the top of my HTML selection was still showing me annoying errors:
ruby: warning: -K is specified; it is for 1.8 compatibility and may cause odd behavior
/Applications/TextMate.app/Contents/SharedSupport/Support/lib/ui.rb:129: warning: assigned but unused variable - pid
I shut that up by changing the first line of the script from #!/usr/bin/env ruby -wKU to #!/usr/bin/env ruby -wKU -W0. Obviously the problems are still there under the hood, but for something helpful but not essential, as this functionality is, I think it's plenty good enough.

Resources