README.md in hack_tree-0.1.0 vs README.md in hack_tree-0.1.1

- old
+ new

@@ -1,36 +1,45 @@ Organize and share your console hacks ===================================== -WARNING! THIS IS WORK IN PROGRESS, NOTHING IS GUARANDEED TO WORK AT ALL ------------------------------------------------------------------------ - Introduction ------------ -HackTree lets you organize and share your console hacks in an effective and uniform way. Blah-blah-blah. +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. + + Setup (Rails 3) --------------- Add to your `Gemfile`: ~~~ -group :development do - gem "hack_tree" -end +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 +~~~ + + Usage ----- Start console: @@ -48,17 +57,278 @@ ~~~ >> c.hello? ~~~ -Use the hack: +Use a hack: ~~~ >> c.hello +Hello, world! + >> c.hello "Ruby" +Hello, Ruby! ~~~ -Place your application's hacks in `lib/hacks/`. +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. + + +Definition language +------------------- + +### Overview ### + +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 type `HackTree::Instance`. + +### Defining hacks ### + +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 +~~~ + +### Handling hack arguments ### + +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 +~~~ + +### Using full descriptions ### + +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! +~~~ + +### Defining groups ### + +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 +~~~ + +### Exiting from hacks, returning values ### + +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 +~~~ + +### Handling external dependencies ### + +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 +~~~ + +### Defining classes and methods to be used in hacks ### + +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 ---------