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
Marc Siegel 25114d0c1d Add Rubocop and run checks in CI
This should finally allow us to adopt code style lints, as well
as others such as performance linting, and have them enforced by
the Github Actions continuous integration (CI) jobs.

For now, I'm choosing to depend on the 'panolint' gem from
Panorama Education, which is my current workplace, as I'd like
to adopt and stay consistent with the setting used there.

Changes
  * Move development and test dependencies from gemspec to Gemfile
  * Add dependency on 'panolint' gem
  * Add .rubocop.yml
  * Fix all existing issues
  * Run rubocop in github actions CI
2021-05-10 17:20:00 -04:00

134 lines
4.4 KiB
Ruby

# frozen_string_literal: true
require "docile/version"
require "docile/execution"
require "docile/fallback_context_proxy"
require "docile/chaining_fallback_context_proxy"
require "docile/backtrace_filter"
# Docile keeps your Ruby DSLs tame and well-behaved.
module Docile
extend Execution
# Execute a block in the context of an object whose methods represent the
# commands in a DSL.
#
# @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("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)
dsl
end
ruby2_keywords :dsl_eval if respond_to?(:ruby2_keywords, true)
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
#
# @example Use a frozen String as a DSL
# Docile.dsl_eval_immutable("I'm immutable!".freeze) do
# reverse
# upcase
# end
# #=> "!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
end