Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[Sass] Add some callback infrastructure.

  • Loading branch information...
commit 4987a5cb0dbc57f3091c90df4eb7196479404bbd 1 parent 6248ca3
@nex3 nex3 authored
View
50 lib/sass/callbacks.rb
@@ -0,0 +1,50 @@
+# A lightweight infrastructure for defining and running callbacks.
+# Callbacks are defined using \{#define\_callback\} at the class level,
+# and called using `run_#{name}` at the instance level.
+#
+# Clients can add callbacks by calling the generated `on_#{name}` method,
+# and passing in a block that's run when the callback is activated.
+#
+# @example Define a callback
+# class Munger
+# extend Sass::Callbacks
+# define_callback :string_munged
+#
+# def munge(str)
+# res = str.gsub(/[a-z]/, '\1\1')
+# run_string_munged str, res
+# res
+# end
+# end
+#
+# @example Use a callback
+# m = Munger.new
+# m.on_string_munged {|str, res| puts "#{str} was munged into #{res}!"}
+# m.munge "bar" #=> bar was munged into bbaarr!
+module Sass::Callbacks
+ protected
+
+ # Define a callback with the given name.
+ # This will define an `on_#{name}` method
+ # that registers a block,
+ # and a `run_#{name}` method that runs that block
+ # (optionall with some arguments).
+ #
+ # @param name [Symbol] The name of the callback
+ # @return [void]
+ def define_callback(name)
+ class_eval <<RUBY
+def on_#{name}(&block)
+ @_sass_callbacks ||= {}
+ (@_sass_callbacks[#{name.inspect}] ||= []) << block
+end
+
+def run_#{name}(*args)
+ return unless @_sass_callbacks
+ return unless @_sass_callbacks[#{name.inspect}]
+ @_sass_callbacks[#{name.inspect}].each {|c| c[*args]}
+end
+private :run_#{name}
+RUBY
+ end
+end
View
2  lib/sass/plugin.rb
@@ -1,6 +1,7 @@
require 'fileutils'
require 'sass'
+require 'sass/callbacks'
module Sass
# This module handles the compilation of Sass files.
@@ -14,6 +15,7 @@ module Sass
# Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
module Plugin
include Haml::Util
+ include Sass::Callbacks
extend self
@options = {
View
61 test/sass/callbacks_test.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../test_helper'
+require 'sass/callbacks'
+
+class CallerBack
+ extend Sass::Callbacks
+ define_callback :foo
+ define_callback :bar
+
+ def do_foo
+ run_foo
+ end
+
+ def do_bar
+ run_bar 12
+ end
+end
+
+module ClassLevelCallerBack
+ extend Sass::Callbacks
+ define_callback :foo
+ extend self
+
+ def do_foo
+ run_foo
+ end
+end
+
+class SassCallbacksTest < Test::Unit::TestCase
+ def test_simple_callback
+ cb = CallerBack.new
+ there = false
+ cb.on_foo {there = true}
+ cb.do_foo
+ assert there, "Expected callback to be called."
+ end
+
+ def test_multiple_callbacks
+ cb = CallerBack.new
+ str = ""
+ cb.on_foo {str += "first"}
+ cb.on_foo {str += " second"}
+ cb.do_foo
+ assert_equal "first second", str
+ end
+
+ def test_callback_with_arg
+ cb = CallerBack.new
+ val = nil
+ cb.on_bar {|a| val = a}
+ cb.do_bar
+ assert_equal 12, val
+ end
+
+ def test_class_level_callback
+ there = false
+ ClassLevelCallerBack.on_foo {there = true}
+ ClassLevelCallerBack.do_foo
+ assert there, "Expected callback to be called."
+ end
+end
View
29 yard/callbacks.rb
@@ -0,0 +1,29 @@
+class CallbacksHandler < YARD::Handlers::Ruby::Legacy::Base
+ handles /\Adefine_callback(\s|\()/
+
+ def process
+ callback_name = tokval(statement.tokens[2])
+ attr_index = statement.comments.each_with_index {|c, i| break i if c[0] == ?@}
+ if attr_index.is_a?(Fixnum)
+ docstring = statement.comments[0...attr_index]
+ attrs = statement.comments[attr_index..-1]
+ else
+ docstring = statement.comments
+ attrs = []
+ end
+
+ yieldparams = ""
+ attrs.reject! do |a|
+ next unless a =~ /^@yield *(\[.*?\])/
+ yieldparams = $1
+ true
+ end
+
+ o = register(MethodObject.new(namespace, "on_#{callback_name}", scope))
+ o.docstring = docstring + [
+ "@return [void]",
+ "@yield #{yieldparams} When the callback is run"
+ ] + attrs
+ o.signature = true
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.