ramnathv / poirot

Reproducible Blogging with R Markdown
http://ramnathv.github.com/poirotBlog
32 stars 19 forks source link

some initial questions & thoughts #13

Open cboettig opened 11 years ago

cboettig commented 11 years ago

Ramnath,

This looks fantastic. I quite like the building on Mustache and yaml. Thanks for sharing this and I look forward to seeing where it goes. A few preliminary questions, sorry if they're silly or don't make sense:

Probably more questions as I understand better what's going on here... Great work!

(p.s. github list's your homepage as http://rstats.posterous.com which appears to be broken)

ramnathv commented 11 years ago

Thanks for the feedback. Let me address your questions one at a time.

Ruhoh

Poirot only draws inspiration from Ruhoh. My implementation is independent of Ruhoh, and in fact differs significantly from Ruhoh on a number of fronts.

Compiling

I apologize for the lack of documentation, but all the functionality resides in the function blogify. Here is a quick way to get started and compile the blog.

$ git clone git@github.com:ramnathv/poirotBlog
$ cd poirotBlog
$ R -e "library(slidify); blogify('.')"
$ python -m simpleHTTPServer 

Blogify essentially knits and parses all Rmd files recursively and constructs a giant payload, which is then passed through a template to construct the blog. The config file site.yml controls some metadata, while the rest are controlled by the YAML front matter and config.yml in the posts directory.

Jekyll

I agree that a comparison with Jekyll would be good. I will try to put together an explanation in the README section.

Plugins

Mustache does not support plugins. It does support lambdas to run functions, but that functionality has not been implemented in the whisker package, although it seems to be on the to-do list of @edwindj. I have been toying with some ideas of using knitr and a custom %|% function that acts like a unix filter, to implement this, but it has been trickier than I thought.

My home page has been in the works perenially! I will point it to Poirot for now.

PS. I am looking to get more people involved with development of Poirot. Let me know if you would be interested. I would be happy to set up some time to chat, since it would be easier for me to explain a lot of things about its design and clarify questions you have.

plusjade commented 11 years ago

Mustache does not support plugins.

Mustache requires a different form of thinking from traditional embedded templating languages.

Mustache is really just an interface into native ruby which makes it the ultimate plugin system, because everything is a plugin. Here's an example:

Template:

{{some_crazy_calculation_plugin}}

{{ endless.method.chaining }}

{{#handle_some_data}}
apple
banana
pear
{{/handle_some_data}}

{{argument_passing_hack_within_method_call_45}}

<ul>
{{#site.navigation?to_pages}}
<li>{{title}}<li>
{{/site.navigation?to_pages}}
</ul>

View:

class View < Mustache
  def some_crazy_calculation_plugin
    # All the ruby code in the world can be done here
    "bam"
  end

  class Endless
    def method
      Method.new
    end
  end

  class Method
    def chaining
      "yay"
    end
  end

  def endless
    Endless.new
  end

  # Here I've managed to pass in multiple arguments to this method via newlines.
  def handle_some_data(sub_context)
    data = sub_context.split("\n")
    "output some data"
  end

  ## Advanced argument passing can be done via method_missing syntax
end

I do admit that argument passing is pretty hacky. But again, if you have full uninhibited access to native ruby then you can simply make a small custom method for every/any situation you need.

Mustache requires a strict mind-shift from traditional thinking of "let me just embed half of my application's code in my template". It is a little harder to instead rethink your actual need and break this need into a strict separation of:

  1. data
  2. logic
  3. presentation

IMO this is the use-case that Mustache was designed and optimized for. You'd have a beautiful separation of logic =)

cboettig commented 11 years ago

@plusjade thanks for the clarification. Quick question: is Mustache ruby-specific in this sense?

On Thu, May 16, 2013 at 11:21 AM, Jade notifications@github.com wrote:

Mustache does not support plugins.

Mustache requires a different form of thinking from traditional embedded templating languages.

Mustache is really just an interface into native ruby which makes it the ultimate plugin system, because everything is a plugin. Here's an example:

Template:

{{some_crazy_calculation_plugin}}

{{ endless.method.chaining }}

{{#handle_some_data}} apple banana pear {{/handle_some_data}}

{{argument_passing_hack_within_method_call_45}}

    {{#site.navigation?to_pages}}
  • {{title}}
  • {{/site.navigation?to_pages}}

View:

class View < Mustache def some_crazy_calculation_plugin

All the ruby code in the world can be done here

"bam"

end

class Endless def method Method.new end end

class Method def chaining "yay" end end

def endless Endless.new end

Here I've managed to pass in multiple arguments to this method via newlines.

def handle_some_data(sub_context) data = sub_context.split("\n") "output some data" end

Advanced argument passing can be done via method_missing syntaxend

I do admit that argument passing is pretty hacky. But again, if you have full uninhibited access to native ruby then you can simply make a small custom method for every/any situation you need.

Mustache requires a strict mind-shift from traditional thinking of "let me just embed half of my application's code in my template". It is a little harder to instead rethink your actual need and break this need into a strict separation of:

  1. data
  2. logic
  3. presentation

IMO this is the use-case that Mustache was designed and optimized for. You'd have a beautiful separation of logic =)

— Reply to this email directly or view it on GitHubhttps://github.com/ramnathv/poirot/issues/13#issuecomment-18019449 .

Carl Boettiger UC Santa Cruz http://carlboettiger.info/

ramnathv commented 11 years ago

@plusjade If I understand correctly, the version of Mustache you are referring to is the one you customized to work with plugins, correct? I don't see any of this in the Mustache specification manual.

AFAIK, mustache is logicless and intended to be so to allow clear separation of logic and view. It is language agnostic, which is beautiful, since it is then possible to seamlessly implement functionality with the same set of templates.

UPDATE. I realized that this is just the ruby implementation of lambdas, which is mentioned in the mustache manual.

plusjade commented 11 years ago

UPDATE. I realized that this is just the ruby implementation of lambdas, which is mentioned in the mustache manual.

Right, the mustache specification is just saying "I will delegate this method call to whatever object is is given to me at this endpoint"

So in simplest form, you'd just have a method respond with a string: {{ site_name }}. But if the method returns an object then you get chaining: {{ data.name }}

The one exception is my custom implementation of "contextual helper methods"

{{#site.navigation?to_pages}}
{{name}}
{{/site.navigation?to_pages}}

You are correct in that I extended Mustache with this functionality. But it's very much the same principle of method chaining. The basic idea is that site.navigation will return a basic data structure like a String or Array. If i wanted to support "to_pages" natively I'd have to hack String/Array object itself to respond to to_pages.

Instead, I intercept the mustache process if the method contains ? . In this one special case scenario I still let mustache do its thing and give me the array, as well as try to find the to_pages method in the call stack. The only difference is I manually provide the "context" to to_pages which is the Array in this case.

Long story less long: It's basically a convenient way to pass in arguments.

plusjade commented 11 years ago

@cboettig Mustache has been implemented in many languages because the API is language-agnostic. http://mustache.github.io/ (list of supported languages and libraries)

As you may have guessed, I'm a Mustache fanboy =)

ramnathv commented 11 years ago

As you may have guessed, I'm a Mustache fanboy =)

Me too :)

So, if whisker can be extended to support mustache lambdas and maybe even contextual helpers, then we can get the plugin functionality easily.