{"id":2432,"date":"2012-01-28T16:50:15","date_gmt":"2012-01-28T15:50:15","guid":{"rendered":"http:\/\/www.devco.net\/?p=2432"},"modified":"2012-01-28T16:50:21","modified_gmt":"2012-01-28T15:50:21","slug":"writing-oldskool-plugins","status":"publish","type":"post","link":"https:\/\/www.devco.net\/archives\/2012\/01\/28\/writing-oldskool-plugins.php","title":{"rendered":"Writing Oldskool Plugins"},"content":{"rendered":"

Earlier this week I wrote about Oldskool<\/a> which is a Gem extendable search tool. Today I want to show how to create a plugin for it to query some custom source.<\/p>\n

<\/a>We’ll build a plugin that shows Puppet Type references, you can see how it will look in the image, click for a larger version.<\/p>\n

The end result is that I can just search for “type exec” to get the correct documentation for my Puppet install. I’ll go quite quick through all the various bits here, the complete working plugin is in my GitHub<\/a>.<\/p>\n

The nice thing about rendering the type references locally is that you can choose exactly which version to render the docs for and you could possibly also render docs for locally written types that are not part of Puppet – not tried to see how you might render custom types though.<\/p>\n

Plugins are made up of a few things that should have predictable names, in the case of our Puppet plugin I decided to call it puppet<\/em> which means we need a class called Oldskool::PuppetHandler<\/code> that does the work for that plugin. You can see the one here and it goes in lib\/oldskool\/puppet_handler.rb<\/code> in your gem:<\/p>\n

<\/p>\n

\r\nmodule Oldskool\r\n  class PuppetHandler\r\n    def initialize(params, keyword, config)\r\n      @params = params\r\n      @keyword = keyword\r\n      @config = config\r\n      self\r\n    end\r\n\r\n    def plugin_template(template)\r\n      File.read(File.expand_path(\"..\/..\/..\/views\/#{template}.erb\", __FILE__))\r\n    end\r\n\r\n    def handle_request(keyword, query)\r\n      type = Puppetdoc.new(query)\r\n\r\n      menu = [{:title => \"Type Reference\", :url => \"http:\/\/docs.puppetlabs.com\/references\/stable\/type.html\"},\r\n              {:title => \"Function Reference\", :url => \"http:\/\/docs.puppetlabs.com\/references\/stable\/function.html\"},\r\n              {:title => \"Language Guide\", :url => \"http:\/\/docs.puppetlabs.com\/guides\/language_guide.html\"}]\r\n\r\n      {:template => plugin_template(:type), :type => type.doc, :topmenu => menu}\r\n    end\r\n  end\r\nend\r\n<\/pre>\n

<\/code><\/p>\n

The initialize<\/code> and plugin_template<\/code> methods will rarely change, the handle_request<\/code> is where the magic happens. It gets called with the keyword and the query, so I set this up to respond to searched like type exec<\/code>. If you needed any kind of configuration data from the main Oldskool config file you’d just add data to that YAML file and the data would be available in @config<\/code>.<\/p>\n

The keyword<\/code> would be type<\/code> and the query<\/code> would be exec<\/code>. The idea is that we could route for example type<\/code> as well as function<\/code> keywords into the plugin and then do different things with the query string.<\/p>\n

We then create a simple menu that’s just an array of title<\/em> and url<\/em> pairs that will be used to build the top menu that you see in the screenshot.<\/p>\n

And finally we just return a hash. The hash that you return must<\/strong> include a template<\/em> key the rest is optional, I override the meaning of the word template a bit – probably should have chosen a better name:<\/p>\n

I wrote a class called Puppetdoc<\/code> that takes care of the Puppet introspection, I won’t go into the details but you can see it here<\/a>, it just returns a hash with all the Markdown for each parameter, meta parameter and the type itself.<\/p>\n