Better ruby terminal coloring library - ruby

There are plenty of coloring libraries: colored, term-ansicolor.
But is there any which can do this:
puts "#{'hello'.red} world!".bold
And world! should be bold.
To make it clear, I want to get this:
"\e[1m\e[31mhello\e[0m\e[1m world!\e[0m"
or better even this (just shorter):
"\e[1;31mhello\e[0;1m world!\e[0m"
instead of this:
"\e[1m\e[31mhello\e[0m world!\e[0m"

As there is none, I wrote my own, with blackjack and hookers smart one — smart_colored
gem install smart_colored
and run
require 'smart_colored/extend'
# without extend you'll need to use 'string'.colored.red
puts "#{'hello'.red} world!".bold

The lib is called Highline
It has a color method: say("This should be <%= color('bold', BOLD) %>!")
Which can be easily used to implement String#bold.

In case you are using highline I made a gem that extends colors and provides helpers such as:
say_bold 'this is bold text'
https://github.com/bonzofenix/highline-color

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

How can I "require" code from another .rb file like in PHP?

Coming to Ruby from a PHP background, I'm used to being able to use require, require_once, include, or include_once which all have a similar effect, but the key being they continue to process code in the same scope where the include / require command was invoked.
Example:
sub.php
<?php
echo $foo;
main.php
<?php
$foo = 1234;
include('sub.php'); // outputs '1234'
When I first started using Ruby I tried to include / require / require_relative / load other .rb files, and after becoming a little frustrated with not having it work how I would expect it to I decided that there were better ways to go about breaking up large files and that Ruby didn't need to behave in the same way PHP did.
However, occasionally I feel that for testing purposes it would be nice to to load code from another .rb file in the way PHP does - in the same scope with access to all the same variables - without having to use class / instance variables or constants. Is this possible? Maybe somehow using a proc / binding / or eval command?
Again, I'm not advocating that this should be used during development - but I am curious if it is possible - and if so, how?
Yes, this is possible, although certainly not something I'd recommend doing. This works:
includer.rb:
puts var
include.rb:
var = "Hello!"
eval(File.read("include.rb"), binding)
Running this (Ruby 2.2.1, Ruby 1.9.3) will print Hello!. It works simply: eval takes an optional binding with which to evaluate the code it is passed, and Kernel#binding returns the current binding.
To have code run in same binding, you could simply eval the file contents as follows:
example.rb
class Example
def self.called_by_include
"value for bar"
end
def foo
puts "Called foo"
end
eval( File.read( 'included.rb' ) )
end
Example.new.bar
included.rb
BAR_CONSTANT = called_by_include
def bar
puts BAR_CONSTANT
end
Running ruby example.rb produces output
value for bar
The important thing is the eval( File.read( 'included.rb' ) ) code, which if you really wanted you could define as a class method on Object, to allow arbitrary source to be included with a convenience function*. The use of constants, class variables etc just shows influences working in both directions between the two pieces of source code.
It would be bad practice to use this in any production code. Ruby gives you much better tools for meta-programming, such as ability to use mix-ins, re-open classes, define methods from blocks etc.
* Something like this
class Object
def self.include_source filename
eval( File.read( filename ) )
end
end
And the line in example.rb would become just
include_source 'included.rb'
Again I have to repeat this is not such a great idea . . .
To import external .rb file in your code, I'm not sure but I think it have to be a gem.
Use require followed by the name of the gem you want to import.
Example
require 'foobar'
# do some stuff
Or you can use load to import entire rb file
load 'foobar.rb'
# do some stuff
Good luck and sorry for my english

Ruby koans triangle.rb require error

I'm doing the Ruby Koans tutorial, using notepad++.
The about_triangle_project.rb can't seem to load the triangle.rb file.
no such file to load -- triangle.rb <LoadError>
from <internal:lib/rubygems/custom_require>:29:in 'require'
from about_triangle_project.rb:4: in '<main>'
However I don't think I've altered the files. (I tried to fix it but always undid these when they didn't work)...
Here's the code in about_triangle_project.rb
require File.expand_path(File.dirname(__FILE__) + '/edgecase')
require 'triangle.rb' # this is line 4
class AboutTriangleProject < EdgeCase::Koan
def test_equilateral_triangles_have_equal_sides
assert_equal :equilateral, triangle(2, 2, 2)
assert_equal :equilateral, triangle(10, 10, 10)
end
(etc)
I have tried require 'triangle', that didn't work.
I tried using an absolute pathname, that didn't work.
and the triangle.rb file is in the same directory, unaltered, with comments and just this:
def triangle(a,b,c)
end
class TriangleError < StandardError
end
The triangle.rb file does exist in the same directory, so why can't it be found?
I hope I'm not missing something glaringly obvious!
It appears that on Windows, adding the current directory to the load path doesn't quite work right. Substituting require 'triangle.rb' for require_relative 'triangle.rb' should work, but is a bit of a hack. I don't use Windows, so I'm not sure what the proper solution would be.
I'd definitely look into obtaining a version of Sublime Text Editor, it makes things much cleaner and you can actually open folders in it.
And it looks like your pathing is wrong, I would say make sure that the address of triangle.rb is correct in your code.
Mine looks something more like this
require File.expand_path(File.dirname(FILE) + '/neo')
#You need to write the triangle method in the file 'triangle.rb'
require './triangle'
I'm learning ruby with the Koans right now and found this issue too.
So what was happening to us is that the current working directory (cwd) where the code is ran from affects ruby's require method. You will need to change where the cwd is to the folder of all the koans with cd .\.ruby\koans\ for example. Or, as Ben Langfeld answered, require_relative 'triangle' is a good and easy alternative.
For more info, I'd suggest checking out this What is the difference between require_relative and require in Ruby? thread. My takeaway from this was that require is better used for installed gems and libraries while require_relative is better for code written by you.

Easiest way to parse gem-style command line arguments in Ruby

I would like to implement gem-style console app, and when I say gem (or apt-get etc) style, I mean that it will have invocation syntax like:
program.rb verb [argument] [--options ...]
For example
greeter.rb say "Hello world" --bold
I have used optparse but I think it is not suitable for anything except --option style arguments. Am I wrong about it or there is more suitable library to achieve this?
I suggest not to parse from scratch; I suggest to use GLI by which you can provide (via its DSL) a git like interface to your users. Get started here to see how it works.
You might also be interested in looking at a real (humble) implementation in a project of mine. Check these files:
https://github.com/empo/RuGPost/blob/master/bin/rugpost
https://github.com/empo/RuGPost/blob/master/lib/rugpost/commands.rb
https://github.com/empo/RuGPost/blob/master/lib/rugpost/commands/post_commands.rb
https://github.com/empo/RuGPost/blob/master/lib/rugpost/commands/project_commands.rb

RSpec. How to color the piped or redirected output?

In versions of RSpec before 2.0 I could pipe the color output to less or redirect it to a file. In order to do it I simply have to set the RSPEC_COLOR environment variable to true. However, in the new main version of the framework this variable has stopped to define the output type (color or monchrome). Is there any way to pipe or redirect the color in RSpec 2.0 and higher?
Thanks.
Debian GNU/Linux 5.0.7;
Ruby 1.9.2;
RSpec 2.4.0.
Updated
I found the answer by myself.
One should use the tty configuration option to achieve the effect.
Here's the example:
# spec/spec_helper.rb
RSpec.configure do |config|
config.tty = true
end
The answer in the question is the correct one:
# spec/spec_helper.rb
RSpec.configure do |config|
config.tty = true
end
Then rspec | grep --color="never" something keeps the coloring.
By looking at the sources, it seems that the color_enabled configuration option is now in the Configuration module of RSpec. However, if the output is not done to a tty, color is disabled.
My suggestion would be to set color_enabled = true and to monkey patch the RSpec Configuration module so that is works even when not outputting to a tty:
module RSpec
module Core
class Configuration
def color_enabled
true
end
end
end
end
This is not the nicest way, though. This is also untested and I think that monkey patching rspec is not the easiest thing to do because usually tests are run via the dedicated command line tool.
Maybe you could open a bug report to the maintainer and ask for a force_color_enabled option ? It would probably be very quick to implement...
Good Luck and Happy Coding !
It's as simple as:
# spec/spec_helper.rb
RSpec.configure do |config|
config.color_enabled = true
end

Resources