| Input | Pattern | Result |
|---|---|---|
| Given an input and a pattern, WSCG applies the pattern to each row, substituting the input into the pattern. The symbol '$0' is replaced by the value of the first field; the symbol '$1' is replaced by the value of the second field, and so on. | ||
hello, world goodbye, world |
$0 $1 |
hello world goodbye world |
world, hello world, goodbye |
$1 $0 |
hello world goodbye world |
Smith, Peter Davies, Joan |
hello $1 $0 |
hello Peter Smith hello Joan Davies |
firstName, Peter lastName, Smith |
$0 = '$1'; |
firstName = 'Peter'; lastName = 'Smith'; |
| For the next example, change the column separator to '=' and the row separator to ';' | ||
name.Text = person.Name; address.Text = person.Address; |
$1 = $0; |
person.Name = name.Text; person.Address = address.Text; |
| WSCG excels at generating SQL. | ||
Smith, Peter Davies, Joan |
insert into People
(FirstName, Surname)
values ('$0','$1')
|
insert into People
(FirstName, Surname)
values ('Smith','Peter')
insert into People
(FirstName, Surname)
values ('Davies','Joan')
|
| HTML generation is another sweetspot for WSCG | ||
John Paul George Ringo |
<li>$0</li> |
<li>John</li> <li>Paul</li> <li>George</li> <li>Ringo</li> |
| Input | Pattern | Result |
The special term $row outputs the original row, unchanged.
|
||
hello world |
$row |
hello world |
$rownum outputs the current row number (the first row is called number 0, i.e. 'zero-based')
|
||
The first line The second line The third line |
$rownum: $row |
0: The first line 1: The second line 2: The third line |
The special term $rownumOne outputs the current row number (the first row is number 1, i.e. 'one-based'). The special term $numrows outputs the total number of rows
|
||
Page Page Page |
$0 $rownumOne of $numrows |
Page 1 of 3 Page 2 of 3 Page 3 of 3 |
Javascript can be embedded inside matching '<%' '%>' symbols. Here's some common examples... but there's no limit to what you can do with this feature. |
||
NumberOfFeet,4 HasTail,1 CanFly,0 |
<% if ($rownum != 0) {
'AND ';
} else {
' '}
%> $0 = $1 |
NumberOfFeet = 4 AND HasTail = 1 AND CanFly = 0 |
| Input | Pattern | Result |
The builtin function toUpperCase() will convert text into UPPER CASE
|
||
Hello World |
<% $0.toUpperCase() %> |
HELLO WORLD |
The builtin function toLowerCase() will convert text into lower case.
|
||
Hello World |
<% $0.toLowerCase() %> |
hello world |
The builtin function toPascalCase turns space separated words into a single PascalCased word (i.e. all words joined up, word boundaries indicated by upper case, first letter is upper case).
|
||
hello world |
<% $0.toPascalCase() %> |
HelloWorld |
int, age string, name |
private $0 _$1;
public $0 <% $1.toPascalCase() %> {
get { return _$1; }
set { _$1 = value; }
} |
private int _age;
public int Age {
get { return _age; }
set { _age = value; }
}
private string _name;
public string Name {
get { return _name; }
set { _name = value; }
} |
The builtin function toCamelCase() will convert text into camelCase (i.e. all words joined up, word boundaries indicated by upper case, but first word is lower case)
|
Hello world |
<% $0.toCamelCase() %> |
helloWorld |
The builtin function toSentenceCase() will convert text into Sentence case (i.e. first letter of first word is upper case, the rest is unchaged.)
|
||
hello world how are You? |
<% $0.toSentenceCase() %> |
Hello world how are You? |
The builtin function toTitleCase() will convert text into Title Case (also known as 'Proper Case', this means that the first letter of each word is capitalized)
|
||
hello world how are You? |
<% $0.toTitleCase() %> |
Hello World How Are You? |
The builtin function toWords() will split JoinedUpWords into separated words
|
||
HelloWorld |
<% $0.toWords() %> |
Hello World |
The builtin function reverse() will reverse the order of letters in a string.
|
||
hello world |
<% $0.reverse() %> |
dlrow olleh |
| Input | Pattern | Result |
To loop over the input multiple times, insert a $EACH delimiter in your pattern. This is the simplest and somehow most profound concept in the WSCG lexicon. Master this, and the world is your pretty little oyster.
|
||
int, age string, name |
private $0 _$1
$EACH
public $0 <% $1.toPascalCase() %> {
get { return _$1; }
set { _$1 = value; }
}
|
private int _age;
private string _name;
public int Age {
get { return _age; }
set { _age = value; }
}
public string Name {
get { return _name; }
set { _name = value; }
}
|
John,Rhythm Paul,Bass George,Lead Ringo,Drums |
$0 is a Beatle
$EACH
and $0 plays $1 |
John is a Beatle Paul is a Beatle George is a Beatle Ringo is a Beatle and John plays Rhythm and Paul plays Bass and George plays Lead and Ringo plays Drums |
| Input | Pattern | Result |
Once you've mastered $EACH, learn the wonders of $ONCE. Anything that follows a $ONCE will be output only once. Anything that follows an $EACH is output for each and every row.
|
||
John,Rhythm Paul,Bass George,Lead Ringo,Drums |
$0 is a Beatle $ONCE and also... $EACH $0 plays $1 |
John is a Beatle Paul is a Beatle George is a Beatle Ringo is a Beatle and also... John plays Rhythm Paul plays Bass George plays Lead Ringo plays Drums |
John Paul George Ringo |
$ONCE<ul> $EACH <li>$0</li> $ONCE</ul> |
<ul> <li>John</li> <li>Paul</li> <li>George</li> <li>Ringo</li> </ul> |
| Input | Pattern | Result |
These two keywords, $ONCE and $EACH, work together to let you output headers, footers, and other typical features of code generation. (Text that is predeeded by neither a $ONCE or an $EACH is output for every row. Hence, there is an implicit $EACH at the start of each pattern.)
|
||
firstName, Jack surName,Smith middleName,Terry address,31 North St |
$ONCE SELECT * FROM Person WHERE $EACH<% if ($rownum != 0) { 'AND '; } else { ' ' } %>$0 = '$1' |
SELECT *
FROM Person
WHERE
firstName = 'Jack'
AND surName = 'Smith'
AND middleName = 'Terry'
AND address = '31 North St' |
John,Guitar,Vocals Paul,Bass,Vocals George,Guitar,Vocals Ringo,Drums,Vocals |
$ONCE <table> $EACH <tr> <td>$0</td> <td>$1</td> <td>$2</td> </tr> $ONCE </table> |
<table>
<tr>
<td>John</td>
<td>Guitar</td>
<td>Vocals</td>
</tr>
<tr>
<td>Paul</td>
<td>Bass</td>
<td>Vocals</td>
</tr>
<tr>
<td>George</td>
<td>Guitar</td>
<td>Vocals</td>
</tr>
<tr>
<td>Ringo</td>
<td>Drums</td>
<td>Vocals</td>
</tr>
</table> |
| Input | Pattern | Result |
The final trick: $EACH+ (pronounced 'Each PLUS') is just like $EACH except it skips the first row.
This is useful when the first row contains header information, such as column headings.
|
||
Name, Instrument John,Rhythm guitar Paul,Bass guitar George,Lead guiat Ringo,Drums |
$EACH+
$0 plays $1 |
John plays Rhythm guitar Paul plays Bass guitar George plays Lead guiat Ringo plays Drums |
| Input | Pattern | Result |
| If you want to put the column headers to good use, you can use a $ONCE section. Note that when you use $0 (etc) in a $ONCE section, it is applied against the first row. (This is always true, not just when an Each Plus is in use) | ||
Name, Instrument John,Rhythm guitar Paul,Bass guitar George,Lead guiat Ringo,Drums |
$ONCE <table> <thead> <tr> <th>$0</th> <th>$1</th> </tr> </thead> <tbody> $EACH+ <tr> <td>$0</td> <td>$1</td> </tr> $ONCE </tbody> </table> |
<table>
<thead>
<tr>
<th>Name</th>
<th>Instrument</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Rhythm guitar</td>
</tr>
<tr>
<td>Paul</td>
<td>Bass guitar</td>
</tr>
<tr>
<td>George</td>
<td>Lead guiat</td>
</tr>
<tr>
<td>Ringo</td>
<td>Drums</td>
</tr>
</tbody>
</table> |
If there's a particular pattern that you use often, you can save it for later use.
The macro will be saved as a cookie, hence will only be available from the browser where you created it.
To save a macro, highlight the text you wish to keep, in the pattern textarea. Then, from the drop down list, select '** ADD YOUR OWN **'
You will be presented with a prompt, in which you should give the selected text an appropriate name.
Now, whenever you return to WSCG from that same browser on that same machine, there will be a new item in the drop down list: your own useful little macro/pattern/snippet. With this technique you can add as many of your own macros as you wish.
Yes. Yes, I know. This is woefully inadequate as a way to retain, develop and share your own macros, patterns and snippets. In the nonexistent enterprise version of WSCG, this feature is far more better.
If an error occurs within a javascript section, you'll get a message such as this, inside the result textarea.
(SyntaxError in "<% website toUpperCase() %>": "Expected ';'")
(TypeError in "<% website.ToUpperCase() %>": "Object doesn't support this property or method")
This is not an error in WSCG, this is an error in *your* javascript. ;-)
WSCG ignores 'empty' rows. There's no option to turn this off -- but in the nonexistent enterprise version of WSCG, there could be.
To use these as delimiters, use the special characters '\r', '\n' and '\t' respectively.
Each field is trimmed before being processed, i.e. spaces are removed from the start and end of each field.
There's no option to turn this off -- but in the nonexistent enterprise version of WSCG, there could be.
This is not something that WSCG does. It could become an option, if there's a demand for it.
This is not something that WSCG does. It could become an option, if there's a demand for it.
This is not handled.
WSCG doesn't contain a true CSV parser: it simply splits on the given delimiters, with no way of escaping a delimiter.
I originally intended to write a 'proper' csv parser for WSCG, but have not gotten around to it and haven't missed it. A true CSV parser would include the ability to 'qualify' values by wrapping them in quotes (single or double), and thus you could contain a comma or carriage return inside a qualified value. Then I'd need options for indicating the qualifying symbol, and at what point to error out of an unterminated string constant, and so on. The goal of wscg is always to avoid cluttering the interface.
There is a forum where you can ask for new features, or request help.
WSCG has been under constant improvement for three years so far. It has generated billions of lines of text, free of charge.
If you regularly benefit from WSCG, you are urged to leave a modest donation. Countless studies show that altruistic giving contributes to well-being and longevity. Plus, I hardly ever steal people's credit card numbers and sell them to criminal organisations.
TimeSnapper is a life analysis system,
helpful to programmers, freelancers, businesses and more.
wscg :: secretGeek