callbacks.rb 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. module Sass
  2. # A lightweight infrastructure for defining and running callbacks.
  3. # Callbacks are defined using \{#define\_callback\} at the class level,
  4. # and called using `run_#{name}` at the instance level.
  5. #
  6. # Clients can add callbacks by calling the generated `on_#{name}` method,
  7. # and passing in a block that's run when the callback is activated.
  8. #
  9. # @example Define a callback
  10. # class Munger
  11. # extend Sass::Callbacks
  12. # define_callback :string_munged
  13. #
  14. # def munge(str)
  15. # res = str.gsub(/[a-z]/, '\1\1')
  16. # run_string_munged str, res
  17. # res
  18. # end
  19. # end
  20. #
  21. # @example Use a callback
  22. # m = Munger.new
  23. # m.on_string_munged {|str, res| puts "#{str} was munged into #{res}!"}
  24. # m.munge "bar" #=> bar was munged into bbaarr!
  25. module Callbacks
  26. # Automatically includes {InstanceMethods}
  27. # when something extends this module.
  28. #
  29. # @param base [Module]
  30. def self.extended(base)
  31. base.send(:include, InstanceMethods)
  32. end
  33. protected
  34. module InstanceMethods
  35. # Removes all callbacks registered against this object.
  36. def clear_callbacks!
  37. @_sass_callbacks = {}
  38. end
  39. end
  40. # Define a callback with the given name.
  41. # This will define an `on_#{name}` method
  42. # that registers a block,
  43. # and a `run_#{name}` method that runs that block
  44. # (optionall with some arguments).
  45. #
  46. # @param name [Symbol] The name of the callback
  47. # @return [void]
  48. def define_callback(name)
  49. class_eval <<RUBY
  50. def on_#{name}(&block)
  51. @_sass_callbacks ||= {}
  52. (@_sass_callbacks[#{name.inspect}] ||= []) << block
  53. end
  54. def run_#{name}(*args)
  55. return unless @_sass_callbacks
  56. return unless @_sass_callbacks[#{name.inspect}]
  57. @_sass_callbacks[#{name.inspect}].each {|c| c[*args]}
  58. end
  59. private :run_#{name}
  60. RUBY
  61. end
  62. end
  63. end