/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/

To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>

The javascript SDK will call you on the following global functions.
You don't have to define them. If you don't need them you don't need to define them.
Be lazy... Define only the ones you need.
{{{onInit(currentDirectory)}}}
called when the plugin start. Initialisations can be done here. If you need the directory of the plugin you can get it here.
{{{onSearchBegin(querykey, explicit, queryraw, querynokeyword)}}}
onSearchBegin is called whenever a search begin.
* querykey is the key of the search, you must specify it unchanged when calling FARR.emitResult, FARR.setState or FARR.notifyStateChange
* explicit is true if the alias match.
* queryraw is the query with alias
* querynokeyword is the query without alias
* modifierstring
* triggermethod
{{{onRegexSearchMatch(querykey, queryraw, querynokeyword)}}}
onRegexSearchMatch is called whever a search match the regexfilter (this is useful if you want that FARR filter your results based on another part than the end of the query )
* querykey is the key of the search, you must specify it unchanged when calling FARR.emitResult, FARR.setState or FARR.notifyStateChange
* queryraw is the query with alias
* querynokeyword is the query without alias
* modifierstring
* triggermethod
remark : onRegexSearchMatch is always explicit
{{{onProcessTrigger(title,path)}}}
define onProcessTrigger if you want to do something special on a result
* returning true mean you handled the action (FARR will not launch default action )
* returning 1 mean you handled the action (FARR will not launch default action )
* returning 2 mean close the FARR window
1 and 2 are flags, you can return 1&2 for handled and close
{{{onOptionsChanged()}}}
define onOptionsChanged to know when the internal options have completed
{{{onDoAdvConfig()}}}
define onDoAdvConfig to show your custom options UI when the advanced options button is pressed * experimental *
{{{onReceiveKey(Key, altpressed, controlpressed, shiftpressed)}}}
onReceiveKey is called when a special key like enter is pressed in memo mode. (entered with setStrValue("window.richeditmode", "text" )
{{{onIdleTime(idleTime)}}}
onIdleTime is called when more than 500ms idle elapsed in memo mode
{{{onSetStrValue}}}
called when FARR set a value
{{{onGetStrValue}}}
called when FARR want a value from the plugin

Copy the FScript.dll to a folder in Farr/plugins, create a fscript.js file and copy the basic sample into it. Change the globals variables displayname, version, author, ... At this point your plugin should be listed in the FARR plugin list.
OR extract FScriptSample in Farr/plugins (it is a working plugin ) and start hacking from there.

Debugging can be improved by installing the microsoft javascript debugger and setting the DWORDs :
{{{HKEY_CURRENT_USER\Software\Microsoft\Windows Script\Settings\JITDebug=1}}}
{{{HKEY_CURRENT_USER\Software\Microsoft\Windows Script Host\Settings\JITDebug=1}}}
in the registry base.

{{{FARR.emitResult(querykey, title, path, icon, entrytype=FILE, resultpostprocessing=2, score=300);}}}
return result to FARR
{{{FARR.setState(querykey, s)}}}
you should set state to SEARCHING before search and to STOPPED when done
{{{FARR.notifyStateChange(querykey)}}}
call notifyStateChange when you want to publish intermediate results (farr does not seem to update display right now, but almost... )
{{{FARR.setStrValue(command, value)}}}
do some special FARR action like setting statusbar, richedit (see farr plugin action documentation )
{{{FARR.getStrValue(command, value)}}}
get a FARR internal value :
* Version.FARR (2.xx.xx style)
* Version.FARR_PLUGINAPI (1.xx.xx style)
* Version.FARR_PLUGINAPI_RELEASENUM (# style) <-- empty before V3. This is what I refer to with * API Version *
{{{FARR.debug(txt)}}}
display a message box for helping debugging (you probably won't need it :)
{{{FARR.setInterval(id, millisecond, pFunc)}}}
set a periodic callback (id is a number, millisecond the time before next event, pFunc a javacsript function )
{{{FARR.killInterval(id);}}}
stop a periodic callback (or die :)
{{{FARR.showOptions()}}}
show the internal option dialog
{{{FARR.exec(file,parameters,currentdirectory)}}}
run some command
{{{FARR.getIniValue(file,section,value,def)}}}
read an ini value in a file

The basic principle is to define global methods onSearchBegin in fscript.js and to return results to farr with FARR.emitResult.
You have to call FARR.setState(querykey,SEARCHING) before publishing any result and FARR.setState(querykey,STOPPED); when you are done.

{{{MSXML2.DOMDocument}}} : to read xml
{{{MSXML2.XMLHttpRequest}}} : to make requests
{{{WScript.Shell}}} : to run programs and other things
{{{Scripting.FileSystemObject}}} : to read and write files

I now recommand to store options as a ini file and to define the options dialog with the autohotkey program.
You can define a very simple option dialog by writing a options.xml file in the plugin directory.
It must have a root node named options and a list of node with the attributes 'label' and 'value'.
The Javascript SDK will generate a dialog with a label and a edit field for each node.
!! To plugins developers : be very careful to not zip your option file with logins informations
{{{<options>}}}
{{{<username label='Username :' value=''/>}}}
{{{<password label='Password :' value=''/>}}}
{{{</options>}}}
When the user press OK, the Javascript SDK will save options.xml to the disk and call you on onOptionChanged.
You can then reload options.xml and read values.
{{{function onInit(currentDirectory) { g_currentDirectory=currentDirectory; } }}}
{{{function onOptionsChanged() { options.load(currentDirectory+"\\options.xml"); ... } }}}
I used it in the Delicious plugin. You should look at if you want to do that.

The querykey is the mean to say to the Javascript SDK which request you are currently responding to. This is a number that change at each request. You must give it back unchanged when calling emitResult or setState. This allow results to not mix between differents request. This is useful when you plugin does asynchronous search (like network requests ).
You don't have to really care about it : just give it back unchanged to the methods that need it.
The programmer decide you have to just to bug you. It can't be that easy :)