Hacking Wiki's Methods

The Method plugin has already grown complex interacting across pages and between other plugins. Here I consider how I approached a large increment in functionality when I added units and expressions.

A method sums a column of numbers.

2 Family 3 Friends 5 Children SUM For Dinner

Context

A Method looks above and to the left for other sources of variable bindings. These could be other Methods, Data sets or any item advertising radarData. github

A Method offers its output as radarData to be consumed by, say, Radar plugins. github

A Method plugin can be instantiated independent of a displayed page and "force fed" items to be evaluated. The Rollup and Reduce plugins use this mechanism.

The page load refresh is careful to sequentially evaluate Methods for the top to bottom, left to right flow of data holds. github

Specification

I wrote casual specifications of both unit and equation extensions to Method and asked that Michael Mehaffy, the first intended user, review these. I created checklists from these while coding.

I wrote Mocha tests for calculations that were already known to work. I ran these through the runtests.html interface available on the Ruby/Sinatra server implementation. I ran these from localhost using Mocha's grep option to focus on Method. localhost

Given some conversion factors. gas

3.59 Gas Price (dollars) given (gallons) 24 Fuel Economy (miles) given (gallons) 1.60934 Metric Distance (km) given (miles)

Estimate gas money required for a drive from Vancouver to Portland and beyond. maps

505 Driving from Vancouver (km) 635 Driving to S.F. (miles) SUM Burns Gas (gallons) SUM Costs Money (dollars)

Code

Units. Utility functions that extract values and units from objects, parse labels as units, and perform likely coercions. All new except for asValue which anticipated units. This could reasonably be another module. github

Calculation. Functions to perform sums, products and related operations with attention to units. Only here do we know what kind of coercion will be applied. github

Driving from Vancouver (km) Driving to S.F. (miles) Costs Money (dollars) CALC dollars / ( from + to ) SHOW Gas Money

Expression. A lexer/parser/evaluator that calls calculation functions as specified by the expression grammar. All new. Variables are retrieved from local bindings. github

Interpreter. The "middle-school" evaluator looks for operation keywords, line by line, with long labels for variable names. Accumulates "local" bindings. github

Interface. The emit and bind of the wiki interface as well as the module interface used by the tests. Prints extra if "debug" variable exists and is non-zero. github

Development

We will use at least two repos during development: one to build the plugin, the other to serve the built plugin.

Clone the Method repo. Expose this location for linking. Start grunt doing builds. You will do your editing here. Watch for test results on save.

git clone ... wiki-plugin-method.git cd wiki-plugin-method npm install npm link grunt watch

Clone a test version of the server. Link it to the plugin directory. Start the server. Browse. localhost

git clone ... wiki-node.git cd wiki-node npm link ../wiki-plugin-method node bin/server.js -p 3030 &

Hard link plugin documentation to your server pages.

cd wiki-plugin-method ln pages/about-method-plugin ~/.wiki/pages

Write tests. Pass them. Revise documentation. Commit to a branch. Push to github and issue pull request.

git checkout -b you/feature git commit -a -m "your feature explained" git push origin you/feature

We will merge your feature. Test it. Bump the version. Publish. Update the repo tags.

cd wiki-plugin-method git pull grunt test npm version patch npm plublish git push --tags