1
0
Fork 0
mirror of https://github.com/ms-ati/docile synced 2023-03-27 23:21:52 -04:00
docile/lib/docile.rb

135 lines
4.4 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2018-01-14 18:55:16 -05:00
require "docile/version"
require "docile/execution"
require "docile/fallback_context_proxy"
require "docile/chaining_fallback_context_proxy"
require "docile/backtrace_filter"
2011-12-06 13:51:56 -05:00
2013-07-29 00:14:15 -04:00
# Docile keeps your Ruby DSLs tame and well-behaved.
2011-12-06 13:51:56 -05:00
module Docile
extend Execution
# Execute a block in the context of an object whose methods represent the
# commands in a DSL.
2011-12-06 14:46:46 -05:00
#
# @note Use with an *imperative* DSL (commands modify the context object)
2011-12-06 18:46:14 -05:00
#
# Use this method to execute an *imperative* DSL, which means that:
2011-12-06 14:46:46 -05:00
#
# 1. Each command mutates the state of the DSL context object
# 2. The return value of each command is ignored
# 3. The final return value is the original context object
#
# @example Use a String as a DSL
# Docile.dsl_eval("Hello, world!") do
# reverse!
# upcase!
# end
# #=> "!DLROW ,OLLEH"
#
# @example Use an Array as a DSL
# Docile.dsl_eval([]) do
# push 1
# push 2
# pop
# push 3
# end
# #=> [1, 3]
#
# @param dsl [Object] context object whose methods make up the DSL
# @param args [Array] arguments to be passed to the block
# @param block [Proc] the block of DSL commands to be executed against the
# `dsl` context object
# @return [Object] the `dsl` context object after executing the block
def dsl_eval(dsl, *args, &block)
exec_in_proxy_context(dsl, FallbackContextProxy, *args, &block)
2011-12-06 14:46:46 -05:00
dsl
end
ruby2_keywords :dsl_eval if respond_to?(:ruby2_keywords, true)
2011-12-06 14:46:46 -05:00
module_function :dsl_eval
# Execute a block in the context of an object whose methods represent the
# commands in a DSL, and return *the block's return value*.
#
# @note Use with an *imperative* DSL (commands modify the context object)
#
# Use this method to execute an *imperative* DSL, which means that:
#
# 1. Each command mutates the state of the DSL context object
# 2. The return value of each command is ignored
# 3. The final return value is the original context object
#
# @example Use a String as a DSL
# Docile.dsl_eval_with_block_return("Hello, world!") do
# reverse!
# upcase!
# first
# end
# #=> "!"
#
# @example Use an Array as a DSL
# Docile.dsl_eval_with_block_return([]) do
# push "a"
# push "b"
# pop
# push "c"
# length
# end
# #=> 2
#
# @param dsl [Object] context object whose methods make up the DSL
# @param args [Array] arguments to be passed to the block
# @param block [Proc] the block of DSL commands to be executed against the
# `dsl` context object
# @return [Object] the return value from executing the block
def dsl_eval_with_block_return(dsl, *args, &block)
exec_in_proxy_context(dsl, FallbackContextProxy, *args, &block)
end
if respond_to?(:ruby2_keywords, true)
ruby2_keywords :dsl_eval_with_block_return
end
module_function :dsl_eval_with_block_return
# Execute a block in the context of an immutable object whose methods,
# and the methods of their return values, represent the commands in a DSL.
#
# @note Use with a *functional* DSL (commands return successor
# context objects)
#
# Use this method to execute a *functional* DSL, which means that:
#
# 1. The original DSL context object is never mutated
# 2. Each command returns the next DSL context object
# 3. The final return value is the value returned by the last command
#
2013-07-29 00:14:15 -04:00
# @example Use a frozen String as a DSL
# Docile.dsl_eval_immutable("I'm immutable!".freeze) do
# reverse
# upcase
# end
2013-07-29 00:14:15 -04:00
# #=> "!ELBATUMMI M'I"
#
# @example Use a Float as a DSL
# Docile.dsl_eval_immutable(84.5) do
# fdiv(2)
# floor
# end
# #=> 42
#
# @param dsl [Object] immutable context object whose methods make up the
# initial DSL
# @param args [Array] arguments to be passed to the block
# @param block [Proc] the block of DSL commands to be executed against the
# `dsl` context object and successor return values
# @return [Object] the return value of the final command in the block
def dsl_eval_immutable(dsl, *args, &block)
exec_in_proxy_context(dsl, ChainingFallbackContextProxy, *args, &block)
end
ruby2_keywords :dsl_eval_immutable if respond_to?(:ruby2_keywords, true)
module_function :dsl_eval_immutable
2011-12-06 13:51:56 -05:00
end