HackTree lets you organize and share your console hacks in a simple and efficient way.
Console hacks (or tricks) are handy methods you use in IRB console to do repetitive tasks. HackTree gives you the following opportunities:
- Create hacks using a simple and uniform DSL.
- Describe your hacks, much like you describe tasks in Rakefiles.
- List available hacks with descriptions right in your console.
- Share hacks with your teammates, reuse them in different projects.
Add to your Gemfile
:
gem "hack_tree"
#gem "hack_tree", :git => "git://github.com/dadooda/hack_tree.git" # Edge version.
Install the gem:
$ bundle install
Generate essentials:
$ rails generate hack_tree
Start console:
$ rails console
List available hacks:
>> c
Request help on a hack:
>> c.hello?
Use a hack:
>> c.hello
Hello, world!
>> c.hello "Ruby"
Hello, Ruby!
Create a hack (create and edit lib/hacks/ping.rb
):
HackTree.define do
desc "Play ping-pong"
hack :ping do
puts "Pong!"
end
end
Reload hacks:
>> c.hack_tree.reload
Use your hack:
>> c.ping
Pong!
That's it for the basics, read further for more detailed information.
The definition language has just 3 statements: desc
, group
and hack
.
To enter the definition language use the wrapper block:
HackTree.define do
...
end
NOTE: Inside the wrapper
self
is the object of typeHackTree::Instance
.
To define a hack, use hack
. To describe it, use desc
.
HackTree.define do
desc "Say hello to the world"
hack :hello do
puts "Hello, world!"
end
end
Hack arguments are block arguments in regular Ruby syntax.
HackTree.define do
desc "Say hello to the world or to a specific person"
hack :hello do |*args|
puts "Hello, %s!" % (args[0] || "world")
end
In Ruby 1.9 this form will also work:
HackTree.define do
desc "Say hello to the world or to a specific person"
hack :hello do |who = "world"|
puts "Hello, #{who}!"
end
end
Once your hack begins to take arguments it is recommended that you extend desc
to a full block of text. Keep the heading line, add a few examples and possibly some other descriptive information.
HackTree.define do
desc <<-EOT
Say hello to the world or to a specific person
Examples:
>> c.hello
Hello, world!
>> c.hello "Ruby"
Hello, Ruby!
EOT
hack :hello do |*args|
puts "Hello, %s!" % (args[0] || "world")
end
end
See it in console:
>> c
hello # Say hello to the world or to a specific person
>> c.hello?
Say hello to the world or to a specific person
Examples:
>> c.hello
Hello, world!
>> c.hello "Ruby"
Hello, Ruby!
Groups act as namespaces and are used to encapsulate hacks and other groups. You can nest groups to any level.
HackTree.define do
desc "DB management"
group :db do
desc "List tables in native format"
hack :tables do
...
end
desc "Get `ActiveRecord::Base.connection`"
hack :conn do
...
end
end
end
See it in console:
>> c
db/ # DB management
...
>> c.db
conn # Get `ActiveRecord::Base.connection`
tables # List tables in native format
If the hack runs uninterrupted, it returns the result of its last statement.
>> HackTree.define do
hack :five do
5
end
end
>> c.five
=> 5
To exit from a hack, use next
. Unfortunately, you cannot use break
or return
, please keep that in mind.
HackTree.define do
hack :hello do |*args|
who = args[0] || "world"
if who == "Java"
puts "Goodbye, Java!"
next false
end
puts "Hello, #{who}!"
true
end
end
In the above example, the hack should return false
if the argument is "Java".
See it in console:
>> c.hello "Ruby"
Hello, Ruby!
=> true
>> c.hello "Java"
Goodbye, Java!
=> false
In real life it's possible that your hack depends on particular gems, environment settings, etc.
Please follow these recommendations when dealing with dependencies:
- Make sure your hack can be loaded regardless of dependencies. In other words, use dependencies inside the hack, not outside of it.
- Use
begin ... rescue
to catch possible unmet dependencies. Upon an unmet dependency report about it and return a noticeable result, e.g.false
.
Example:
HackTree.define do
group :db do
desc "Get `ActiveRecord::Base.connection`"
hack :conn do
begin
ActiveRecord::Base.connection
rescue
puts "Error: ActiveRecord not found"
false
end
end
end
end
If your hack needs to use a custom method or class, it is recommended that you use a hierarchy of Ruby module namespaces matching your hack's name.
Example (lib/hacks/db/tables.rb
):
HackTree.define do
group :db do
desc "List tables in native format"
hack :tables do
tables = Hacks::DB::Tables.get_tables
tables.each do |table|
puts table
end
end
end
end
module Hacks
module DB
module Tables
def self.get_tables
# Some logic here.
["authors", "books"]
end
end
end
end
Copyright © 2012 Alex Fortuna.
Licensed under the MIT License.
Send bug reports, suggestions and criticisms through project's page on GitHub.