paiq/blackcoffee — pull request #1 by xkxx (2013-11-07 05:20:02+00:00)
Title: Method Macro Expansion proposal

Hello there,

I would like to propose adding support for method macros. They are similar to normal macros, except they take an extra object argument and are used in place of methods. This pull requests implements a rough example implementation of the concept. I used `macro.defmethod` to denote method macro in my implementation, but it serves as a placeholder only and the actual keyword is open for suggestion.

A short example (setting/getting DOM data-* fields):
```coffeescript
macro.defmethod $data (el, name, val) ->
if val?
macro.codeToNode(-> el.dataset[name] = val).subst {el: el, name: name, val: val}
else
macro.codeToNode(-> el.dataset[name]).subst {el: el, name: name}

```

A more extensive example and my main use case for this feature, a JQuery-like utility that compiles to bare-bone HTML5:

```coffeescript
macro $id (id) ->
macro.codeToNode(-> document.getElementById id).subst {id: id}
macro $tag (name) ->
macro.codeToNode(-> document.getElementsByTagName name).subst {name: name}
macro $class (name) ->
macro.codeToNode(-> document.getElementsByClassName name).subst {name, name}
macro $query (q) ->
macro.codeToNode(-> document.querySelector q).subst {q, q}
macro $queryAll (q) ->
macro.codeToNode(-> document.querySelectorAll q).subst {q, q}

macro.defmethod $data (el, name, val) ->
if val?
macro.codeToNode(-> el.dataset[name] = val).subst {el: el, name: name, val: val}
else
macro.codeToNode(-> el.dataset[name]).subst {el: el, name: name}

macro.defmethod $css (el, name, val) ->
if val?
macro.codeToNode(-> el.style.setPropertyValue(name)).subst {el: el, name: name, val: val}
else
macro.codeToNode(-> el.style.getPropertyValue(name)).subst {el: el, name: name}

macro.defmethod $hasClass (el, name) ->
macro.codeToNode(-> el.classList.contains(name)).subst {el: el, name: name}

macro.defmethod $addClass (el, name) ->
macro.codeToNode(-> el.classList.add(name)).subst {el: el, name: name}

macro.defmethod $toggleClass (el, name) ->
macro.codeToNode(-> el.classList.toggle(name)).subst {el: el, name: name}

macro.defmethod $removeClass (el, name) ->
macro.codeToNode(-> el.classList.remove(name)).subst {el: el, name: name}

$id("myform").$data "user", "foo"
$id("important_text").$css "fontSize", "24px"

```