Sage
Tusk Language
Welcome to Sage
Volume (100%) Hide Volume
Topics
Tusk Config Files

Introduction

Before reading this article, you should be familiar with .DSConfig files.

Since early 2003, we have been using config files with the .dsconfig extension, using MiniCalc as the scripting language.

Now, with Tusk, we can write config files with the .tkconfig extension, using Tusk as the scripting language.

Required Units

For a Delphi program to use .tkconfig files, you must add some units from TuskLib to the project.

Minimally, you'll need to add TuskConfig (and anything required by it). This unit implements the basics of .tkconfig files, similar to the DSConfig unit in the Utility folder.

For server-side applications, and/or those that need database access, you'll also need to add TuskConfigEx (and anything required by it). This unit implements the First Trust-specific ideas from AppServerConfig, such as HostEnv, ServerMap.ini, etc.

Finally, you'll need to ensure that the project contains all relevant TuskFuncs_* units that expose the global routines called by your config file (and any included files). For example, if your config file includes the shared Console.tkconfig or Template.tkconfig files, you'll need to add the following units…
  • TuskFuncs_DSGenUtil
  • TuskFuncs_DSPropertyBag
  • TuskFuncs_DSStringList
  • TuskFuncs_DSStringUtil
  • TuskFuncs_RTL
  • TuskFuncs_System
  • TuskFuncs_DSProfile
  • TuskFuncs_SysUtils
  • TuskFuncs_DSConfig
  • TuskFuncs_AppServerConfig
As ever, use the Add Missing Units wizard to add any indirectly required units (there will be many of the form TuskTypes_*).

Overview

In general, TKConfig files offer the same features as DSConfig files. The familiar keywords such as section, if, calc, stringlist, and include are all implemented.

One obvious difference is that square brackets now contain Tusk code instead of MiniCalc code.

A less obvious difference has to do with how the config file and the scripting language interact. A DSConfig treats each MiniCalc code fragment (contained in square brackets) separate from all others. For example, consider this .dsconfig file…

calc [ const x = 45 ] if [Production] begin LogFileSize=[x*100] end

When the above file is parsed, the three MiniCalc code fragments, const x = 45, Production, and x*100, are each parsed into separate ICalcExpr objects. These are evaluated if and when the overall config file needs them at runtime.

In contrast, a TKConfig file does not parse the various code fragments separately. Instead, the entire config file is translated into a Tusk program, which is then evaluated. For example, consider this .tkconfig file…

calc [ const x = 45 ] if [Production] begin LogFileSize=[x*100] end

When the above file is parsed, it is translated into the following Tusk program…

__TKPushCfgFile('C:\Src\Tusk\Bin\Tusk.tkconfig'); const x = 45; if Programmer then begin Section.LogFileSize := x*100; end; __TKPopCfgFile;

This Tusk program is subsequently parsed (in its entirety) and evaluated to build the config object. This translation step is key to bringing Tusk's static type safety to the config file.

Include Files

In TKConfig files, the include statement has a new option not present in DSConfig files: inline. This option allows you to include a "file" whose contents you supply from an expression.

For example…

include :inline [ DSFormat('%s=%s', [GetUserName, GetCurrentProcessID]) ]

Above, the call to DSFormat produces a string like this…

JayHuber=12345

The include directive then parses that text, producing a config object like this…

{ JayHuber = 12345 }

Important

The expression after the inline option is evaluated immediately when the include statement is parsed. Thus, the expression cannot use any variables or constants defined by earlier calc blocks. See below for a way around this limitation.


Early Blocks

TKConfig files have a new feature: the early block, which is a companion to the familiar calc block. The difference is that early blocks execute as the TKConfig file is being parsed, while calc blocks execute in a later phase, after all parsing has completed.

The main purpose of early blocks is to dynamically compute the text for an inline include statement. For example…

early [ var Text := ''; for var i := 0 to 9 do Text := Text + DSFormat('Data%d=%d%!', [i, Sqr(i)]); ] include :inline [Text]

Above, the early block executes immediately, setting Text to the following…

Data0=0 Data1=1 Data2=4 Data3=9 Data4=16 Data5=25 Data6=36 Data7=49 Data8=64 Data9=81

This text is then processed by the include statement, producing the following config object…

{ Data0 = 0, Data1 = 1, Data2 = 4, Data3 = 9, Data4 = 16, Data5 = 25, Data6 = 36, Data7 = 49, Data8 = 64, Data9 = 81 }

This technique allows TKConfig files to be more dynamic than would be possible otherwise.

Last Modified: 2/15 10:06:11 am
In this article (top)  View article's Sage markup
2/15 10:06:11 am