Note: An alternative skin, TW4MW (work in progress), is available from the user preferences.

Dev:Custom Macros

TiddlyWiki Community Wiki

Jump to: navigation, search
This page is to be merged with Dev:Developing and Testing a Plugin.

Contents

[edit] Introduction

This guide describes creating a basic custom macro. Macros in TiddlyWiki look like this in a tiddler's markup (i.e. unformatted contents):

<<myMacro>>

[edit] Macro parameter formatting

Macros can take parameters like so:

<<myMacro param1 param2>>

Parameters with spaces can be quoted using either single quotes, double quotes, or double square brackets. For example:

<<myMacro [[first param]] 'second param' "third param">>

(To prevent confusion, it's a good idea to pick one quoting character and stick with it.)

Macros can also have named parameters:

<<myMacro this:Foo that:Bar>>

Named parameters can be passed quoted strings, just like positional parameters:

<<myMacro this:'hello there' that:"what's up">>

If a quote is required inside a parameter, put a backslash in front of it:

<<myMacro this:'what\'s up'>>

Parameters can be the result of executing a JavaScript expression. TiddlyWiki evaluates the expression before passing it along to the macro.

<<myMacro {{'tiddler.getTiddlerText("TiddlerName")'}} >>

The JavaScript expression can span multiple lines of text, so it can be formatted for readability.

Parameters cannot contain double closing angle brackets. This won't work, for example:

<<myMacro 'over this way ->>'>>

This confuses the parser, which thinks the macro invocation ended early.

Parameters can be placed on multiple lines to help readability:

<<myMacro
  thing1
  thing2
>>

[edit] Hello world, part 1

Creating a custom macro requires writing a Plugin. A Plugin in TiddlyWiki is merely a tiddler that contains some JavaScript that will be executed when TiddlyWiki starts up. First create a very basic Plugin and make sure it's running.

[edit] Creating a Plugin

  • Create a new tiddler by clicking "new tiddler"
  • Give it a title, e.g. "MyFirstPlugin"
  • Give it the tag "systemConfig" (without the quotes). Tags are case sensitive in TiddlyWiki, so you must have the lowercase 's' and upper case C correct.
  • In the body of the tiddler, paste in the following:
// this will run on startup
alert("Hello world");
  • Click "done" to finish editing the tiddler. Save the TiddlyWiki and reload.
  • When the TiddlyWiki loads an alert should appear with the message "Hello world". If so, then the Plugin is working! If not, check to make sure it is tagged properly.

The Plugin is not very useful so far, but it's a good first step.

[edit] Fixing JavaScript Errors

When TiddlyWiki 2.1 or later, there is a PluginManager that handles problems with Plugins gracefully. It can be used to diagnose problems.

  • Edit the MyFirstPlugin tiddler.
  • Make a deliberate typo by changing alert to alerrt.
  • Click "done", save the TiddlyWiki and reload.
  • The PluginManager should display this message next to the tiddler's name: "Error: ReferenceError: alerrt is not defined"
  • Fix the typo, save, and reload the TiddlyWiki.

[edit] Making the Code Look Better

To make the code more readable, one can use a special version of the preformatted text formatting syntax, {{{ and }}}. It's specifically for use in Plugins. Edit the Plugin tiddler so it looks like this:

//{{{
 
// this will run on startup
alert("Hello world");
 
//}}}

Double forward slashes (//) introduce a JavaScript comment. When these edits are finished, it should look more like code. Also, TiddlyWiki won't try to interpret any of the code as formatting instructions.

[edit] Hello world, part 2

The above shows how to call a macro from within a tiddler and how to plug some code into TiddlyWiki itself. The following section puts these two concepts together.

[edit] Linking a Macro to the Code

When TiddlyWiki encounters a macro in a tiddler, it looks for an identically named 'macro' within the global object config.macros and then calls the handler function of that macro. Edit the Plugin tiddler so it looks like this:

//{{{
config.macros.helloWorld = {
  handler: function (place, macroName, params, wikifier, paramString, tiddler)
  {
      // this will run when macro is called from a tiddler
      alert("Hello world");
  }
};
//}}}

Save the TiddlyWiki and reload. This time, the alert shouldn't pop up immediately. That's because the macro needs to be invoked by a tiddler to act. Do that by following these steps:

  1. Create a new tiddler by clicking "new tiddler".
  2. Give it a title, e.g. "MyFirstPluginTest".
  3. In the body of the tiddler, type in the following: <<helloWorld>>
  4. Click "done" to finish editing the tiddler. As soon as this is done the alert box should pop up again. This is because TiddlyWiki immediately re-displays the tiddler after it is edited.

If there is an error message after reloading the TiddlyWiki, check the punctuation. A stray semicolon can sometimes mess things up.

[edit] Getting Parameters

The macro does something now when called. Making it more flexible requires parameters as discussed above. The argument params provides the macro with an array of strings that are passed in from the tiddler.

Try it out. Replace:

alert("Hello world");

with

var who = params[0] || "world";
alert("Hello " + who);

Save, reload, and look at MyFirstPluginTest again. So far it's the same old popup message... edit it as well, so that it looks like:

<<helloWorld 'all you TiddlyWiki fans'>>

The message will change. In many cases, it's a good idea to have defaults for macro parameters, as in the example. JavaScript's logical-or operator makes this straightforward; if params[0] is missing, as when the macro is invoked as helloWorld, the variable who gets the value "world".

In order to use named parameters, the parameter string must first be parsed. For example, if the macro was called like so <<foo key:"bar baz">> then the handler

config.macros.foo.handler = function(place, macroName, params,
    wikifier, paramString) {
       var prms = paramString.parseParams(null, null, true);
       var bar = getParam(prms, "key");
       alert(bar);
};

would pop an alert box containing the words "bar baz".

cf. Dev:Macro Parameters

[edit] The Handler Function

So what do the rest of those arguments to the handler function do? Here's a quick summary:

place the DOM object that provides the document location where the macro is being rendered in the tiddler
macroName the name of the macro being called. It's possible to have several different invocations call the same macro; in that case, this would allow the code to determine how the macro is being called.
params An array corresponding to the parameters passed into this macro.
wikifier The Wikifier object displaying the current tiddler. Modifying this can alter how the rest of a tiddler is rendered.
paramString all the params passed to the macro, as a single string (suitable for calling parseParams)
tiddler a TiddlyWiki object representing the tiddler from which the macro was called


Finally, combine these parameters with a TiddlyWiki global function named wikify to finish the macro. Instead of popping open an alert box, it'll display its message right in the tiddler itself.

 //{{{
 config.macros.helloWorld = {
   handler: function (place, macroName, params, wikifier, paramString, tiddler) {
     // this will run when macro is called from a tiddler
     var who = params[0] || 'world';
     wikify('Hello //' + who + '// from the "' + macroName + '" macro in tiddler [[' + tiddler.title + ']].', place);
   }
 };
 //}}}

[edit] Hello World, Part 3

[edit] Adding Plugin Documentation

This is under construction

[edit] The Complete Hello World Plugin

The complete Plugin for the HelloWorld macro is available for importing or viewing here: HelloWorldMacro

Personal tools