Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added @compile #2

Closed
wants to merge 1 commit into from
Closed

added @compile #2

wants to merge 1 commit into from

Conversation

jdknezek
Copy link

I added a compile function that compiles a Coco template string into a function to be called with a context:

    $ coco -es
    t = '''
      <~! ul
      for v, i of @
        li "#i: #v"
    '''

    f = require \ckup .compile t

    console.log f <[a b c]>

    <ul
    ><li
    >0: a</li><li
    >1: b</li><li
    >2: c</li></ul>

ckup is included with with, and if context isn't specified then it defaults to ckup, so these should all be equivalent:

    console.log ckup.render 'doctype \\html'
    # <!DOCTYPE html>
    console.log ckup.render '@doctype \\html'
    # <!DOCTYPE html>

    console.log ckup.compile('doctype \\html')!
    # <!DOCTYPE html>
    console.log ckup.compile('@doctype \\html')!
    # <!DOCTYPE html>
    console.log ckup.compile('doctype \\html') \context
    # <!DOCTYPE html>

The only incompatibility should be if you combine @ and context:

    console.log ckup.compile('@doctype \\html') \context
    # TypeError: Object context has no method 'doctype'

@satyr
Copy link
Owner

satyr commented Jan 28, 2012

Is this only for replacing this within the template function? I don't think it a good idea if so.

How about simply delegating render arguments to template, and giving the generated function a default parameter?

  render: (template, ...args) ->
    unless typeof template is \function
      template = Function \context,
        'with(this)' + (Coco ? require \coco)compile "#template"
    template.apply me = ^this, args
    me._

@jdknezek
Copy link
Author

The use case was more for reusable compiled template functions. I really wanted to do something like this:

$.get 'my-template.ck', success: (text) ->
  template = ckup.compile text

  for item in items
    $ '#container' .append template item

It's really just a question of syntax though. Abstracting out the compilation and removing the magic context variable may be a good compromise?

    compile: (template) ->
      template = Function 'with(this)' + (Coco ? require \coco)compile "#template"
      ~>
        template.apply me = ^this, @@
        me._

    render: (template, ...args) ->
      unless typeof template is \function
        template = @compile template
      template.apply me = ^this, args
      me._

with

<-! ul
for v, i of @@0
  li "#i: #v"

instead of

<~! ul
for v, i of @
  li "#i: #v"

I don't consider @@0 as pretty as just @, but it would save having to bind every function. And of course you could leave the first argument as context for the common use case, but I hate introducing magic identifiers.

Edit: Sorry, forgot the binding in compile.

@jdknezek
Copy link
Author

Forget that idea; @@ gets overwritten in every block, so it has to be a special variable.

    compile: (template) ->
      template = Function \arg,
        'with(this)' + (Coco ? require \coco)compile "#template"
      (arg) ~>
        template.call me = ^this, arg
        me._

    render: (template, arg) ->
      unless typeof template is \function
        template = @compile template
      template.call me = ^this, arg
      me._

Replace arg with whatever name.

@jdknezek
Copy link
Author

I really don't like the arg approach either, but maybe this is beyond the scope of what you intended for ckup.

I was really looking for the same sort of usage as CoffeeKup but with Coco's beautiful extensions, but both CoffeeKup and ck keep more state and manipulate this to eliminate the need for bound calls. I might mess with it more and open another pull request, but if that's not the direction you'd like to take ckup just let me know.

@jdknezek jdknezek closed this Jan 29, 2012
@satyr
Copy link
Owner

satyr commented Jan 29, 2012

The use case was more for reusable compiled template functions

You should ideally be passing a function for dynamic rendering. (The @-less style isn't very efficient due to with.)

for item of items
  $ '#container' .append ckup.render ->
    @ul ->
      for v, i of item
      @li "#i: #v"

Though I understand the need for compiling to the withed function. It's certainly nicer to omit all those @.

I really don't like the arg approach either, but maybe this is beyond the scope of what you intended for ckup.

Maybe importing the context object into the instance works?

How about:

  render: (template, context) -> @renderer(template) context

  renderer: (template) ->
    template = @compile template unless typeof template is \function
    (context) ~>
      template.call me = ^this <<< context
      me._

  # Compile a template Coco code into a renderer function,
  # enabling `@`-less style using `with`.
  compile: (code) ->
    Function 'with(this)' + (Coco ? require \coco)compile "#code"

Then you'd be able to:

f = require \ckup .renderer '''
  for v, i of list
    li "#i: #v"
'''
f list: <[a b c]>

satyr added a commit that referenced this pull request Jan 30, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants