Module: Boson::Pipe
Overview
This module passes an original command’s return value through methods/commands specified as pipe options. Pipe options are processed in this order:
-
A :query option searches an array of objects or hashes using Pipes.query_pipe.
-
A :sort option sorts an array of objects or hashes using Pipes.sort_pipe.
-
A :reverse_sort pipe option reverses an array.
-
A :pipes option takes an array of commands that modify the return value using Pipes.pipes_pipe.
-
All user-defined pipe options (:pipe_options key in Repo.config) are processed in random order.
Some points:
-
User-defined pipes call a command (the option’s name by default). It’s the user’s responsibility to have this command loaded when used. The easiest way to do this is by adding the pipe command’s library to :defaults in main config.
-
By default, pipe commands do not modify the value their given. This means you can activate multiple pipes using a method’s original return value.
-
A pipe command expects a command’s return value as its first argument. If the pipe option takes an argument, it’s passed on as a second argument.
-
When piping occurs in relation to rendering depends on the Hirb view. With the default Hirb view, piping occurs occurs in the middle of the rendering, after Hirb has converted the return value into an array of hashes. If using a custom Hirb view, piping occurs before rendering.
-
What the pipe command should expect as a return value depends on the type of command. If it’s a command rendered with hirb’s tables, the return value is a an array of hashes. For everything else, it’s the method’s original return value.
User Pipes
User pipes have the following attributes which alter their behavior:
- :pipe
-
Pipe command the pipe executes when called. Default is the pipe’s name.
- :env
-
Boolean which enables passing an additional hash to the pipe command. This hash contains information from the first command’s input with the following keys: :args (command’s arguments), :options (command’s options), :global_options (command’s global options) and :config (a command’s configuration hash). Default is false.
- :filter
-
Boolean which has the pipe command modify the original command’s output with the value it returns. Default is false.
- :no_render
-
Boolean to turn off auto-rendering of the original command’s final output. Only applicable to :filter enabled pipes. Default is false.
- :solo
-
Boolean to indicate this pipe can’t run with other user pipes or pipes from :pipes option. If a user calls multiple solo pipes, only the first one detected is called.
Repo Config
This class adds the following key to the main repo config:
- :pipe_options
-
Hash of options available to all option commands for piping (see Pipe). A pipe option has the normal option attributes and these:
-
:pipe: Specifies the command to call when piping. Defaults to the pipe’s option name.
-
:filter: Boolean which indicates that the pipe command will modify its input with what it returns. Default is false.
-
User Pipes Example
Let’s say you want to have two commands, browser and copy, you want to make available as pipe options:
# Opens url in browser. This command already ships with Boson.
def browser(url)
system('open', url)
end
# Copy to clipboard
def copy(str)
IO.popen('pbcopy', 'w+') {|clipboard| clipboard.write(str)}
end
To configure them, drop the following config in ~/.boson/config/boson.yml:
:pipe_options:
:browser:
:type: :boolean
:desc: Open in browser
:copy:
:type: :boolean
:desc: Copy to clipboard
Now for any command that returns a url string, these pipe options can be turned on to execute the url.
Some examples of these options using commands from my libraries:
# Creates a gist and then opens url in browser and copies it.
$ cat some_file | boson gist -bC # or cat some_file | boson gist --browser --copy
# Generates rdoc in current directory and then opens it in browser
irb>> rdoc '-b' # or rdoc '--browser'
Defined Under Namespace
Modules: TableCallbacks
Instance Method Summary collapse
-
#add_pipes(hash) ⇒ Object
A hash that defines user pipes in the same way as the :pipe_options key in Repo.config.
- #any_no_render_pipes?(global_opt) ⇒ Boolean
- #get_env(key, global_opt) ⇒ Object
-
#internal_pipes(global_opt) ⇒ Object
:stopdoc:.
- #pipe(key) ⇒ Object
- #pipe_options ⇒ Object
- #pipes_to_process(global_opt) ⇒ Object
-
#process_pipes(obj, options) ⇒ Object
Main method which processes all pipe commands, both default and user-defined ones.
-
#process_user_pipes(result, global_opt) ⇒ Object
global_opt can come from Hirb callback or Scientist.
-
#scientist_process(object, global_opt, env = {}) ⇒ Object
Process pipes for Scientist.
- #setup_pipes(hash) ⇒ Object
Instance Method Details
#add_pipes(hash) ⇒ Object
A hash that defines user pipes in the same way as the :pipe_options key in Repo.config. This method should be called when a pipe’s library is loading.
93 94 95 |
# File 'lib/boson/pipe.rb', line 93 def add_pipes(hash) .merge! setup_pipes(hash) end |
#any_no_render_pipes?(global_opt) ⇒ Boolean
136 137 138 139 |
# File 'lib/boson/pipe.rb', line 136 def any_no_render_pipes?(global_opt) !(pipes = pipes_to_process(global_opt)).empty? && pipes.any? {|e| pipe(e)[:no_render] } end |
#get_env(key, global_opt) ⇒ Object
128 129 130 131 132 133 134 |
# File 'lib/boson/pipe.rb', line 128 def get_env(key, global_opt) { :global_options=>global_opt.merge(:delete_callbacks=>[:z_boson_pipes]), :config=>(@env[:config].dup[key] || {}), :args=>@env[:args], :options=>@env[:options] || {} } end |
#internal_pipes(global_opt) ⇒ Object
:stopdoc:
98 99 100 101 102 |
# File 'lib/boson/pipe.rb', line 98 def internal_pipes(global_opt) internals = [:query, :sort, :reverse_sort, :pipes] internals.delete(:pipes) if pipes_to_process(global_opt).any? {|e| pipe(e)[:solo] } internals end |
#pipe(key) ⇒ Object
112 113 114 |
# File 'lib/boson/pipe.rb', line 112 def pipe(key) [key] || {} end |
#pipe_options ⇒ Object
104 105 106 |
# File 'lib/boson/pipe.rb', line 104 def @pipe_options ||= setup_pipes(Boson.repo.config[:pipe_options] || {}) end |
#pipes_to_process(global_opt) ⇒ Object
141 142 143 144 |
# File 'lib/boson/pipe.rb', line 141 def pipes_to_process(global_opt) pipes = (global_opt.keys & .keys) (solo_pipe = pipes.find {|e| pipe(e)[:solo] }) ? [solo_pipe] : pipes end |
#process_pipes(obj, options) ⇒ Object
Main method which processes all pipe commands, both default and user-defined ones.
84 85 86 87 88 89 |
# File 'lib/boson/pipe.rb', line 84 def process_pipes(obj, ) internal_pipes().each {|pipe| obj = Pipes.send("#{pipe}_pipe", obj, [pipe]) if [pipe] } process_user_pipes(obj, ) end |
#process_user_pipes(result, global_opt) ⇒ Object
global_opt can come from Hirb callback or Scientist
117 118 119 120 121 122 123 124 125 126 |
# File 'lib/boson/pipe.rb', line 117 def process_user_pipes(result, global_opt) pipes_to_process(global_opt).each {|e| args = [pipe(e)[:pipe], result] args << global_opt[e] unless pipe(e)[:type] == :boolean args << get_env(e, global_opt) if pipe(e)[:env] pipe_result = Boson.invoke(*args) result = pipe_result if pipe(e)[:filter] } result end |
#scientist_process(object, global_opt, env = {}) ⇒ Object
Process pipes for Scientist
77 78 79 80 81 |
# File 'lib/boson/pipe.rb', line 77 def scientist_process(object, global_opt, env={}) @env = env [:query, :sort, :reverse_sort].each {|e| global_opt.delete(e) } unless object.is_a?(Array) process_pipes(object, global_opt) end |
#setup_pipes(hash) ⇒ Object
108 109 110 |
# File 'lib/boson/pipe.rb', line 108 def setup_pipes(hash) hash.each {|k,v| v[:pipe] ||= k } end |