Welcome Tour
Site Checklist
Our Story




Search is a powerful command/function that can be used to generate all kinds of dynamic reports. It can by modified in many ways and accepts numberous parameters. It is more often used as a function.

The search function and query function are similar. Search extracts information from sets of pages in your site. Query extracts information from an info page. Because queries only have to read one page, they are often much faster. However, the search function can be used to generate reports when data is spread across pages without it having to be indexed first.

Here's a simple function to illustrate how it works:

[(search group=test fmt='[[{+p}]]')]

This gathers all the pages in the test page group on your site and runs that list through the report engine to generate this output. I've escaped it so you can see the connection with the fmt.


The search command works exactly as the search function, except it is processed after a form is submitted and can be modified based on user input. Consider the following form:

Directory:   [radio dir docs] Documents   [radio dir solutions] Solutions   [radio dir test] Test
[command search group={=dir} fmt='[[{+p}]]']
[command passdata search mode=post]


The user selects a directory. Then the search command generates a report of the pages in that directory. Passdata then sends that information back to the page when it reloads on form submission, and the post variable picks it up and displays it.

For the sake of illustration, the same thing could be done with this approach:

Directory:   [radio dir docs] Documents   [radio dir solutions] Solutions   [radio dir test] Test
[command passdata dir]

[if set {?dir}]<(search group={?dir} fmt=''[[{+p}]]')>[if]

Here, the dir is selected and only it is passed back to the page. When the page reloads, the conditional sees that the dir has been set and the search is generated. In many cases it is easier to use a function than a command.

Pagelist Options

To generate a list of pages you must set one of the following four parameter: pages, pattern, group, or dir.

Pages allows me to specify a list of pages. Pages=page1,page2,page3. If this is set the next three parameters are full ignored. It makes the search function to essentially behave as the list function.

Group refer to groups of pages. If I set group=test, search will look for all of test's child pages, like test.abort, test.header and It will not match test, tester, test.child.grandchild. If I add an asterisk, I can search all anything that begin with the appropriate string. That is group=test* will match test, tester, test.child.grandchild. If I want to exclude test and tester, I just set it to group=test.* and they will no longer match. I can also use a csv list of pages, some with and some without the asterisk, ie: group=docs.*,test will generate all docs descendents but only test's direct children. You can also specify that BoltWire only return pages that match a certain pattern. So group=test.+.+ will only return test pages with three page part. To get three and four part pages, do group=test.+.+,test.+.+.+.

Dir allows me to search specific directories. There are several reasons you might want to do this. First you could set dir=system to only list system pages, or dir=pages to only view local pages. By default, both directories are searched. Or I could set dir=files or dir=stamps to view either of those directories. I can also view specific subfolders like dir=files/pub/imgs to list those. There is also special code to scan the shared dir, so I could do dir=shared, dir=shared/plugins, dir=shared/skins, or even dir=shared/skins/gnome. by default all pages in all subfolders are included as well, but I can turn this off by adding folders=false. In this way I could just see what is in the shared/img folder directly and ignore any files in shared/img/smileys and shared/img/gui. Local pages are normally all placed in the pages folder, but BoltWire has a mechanism to store some pages in specific subfolders (see the folders tutorial). So if you had a large site with many pages and many subfolders, you could speed up your search dramatically by setting dir=pages/forum (and if needed folders=false). BoltWire now runs through just the pages I want!

Pattern is the most powerful of all, allowing you to use regular expressions and only return page names that match it. For example, you could do: pat='/^[a-z]+\.posts/' to return page names like forum.posts or blog.posts. Pattern matching is an advanced programming topic I won't get into here, but it offers you virtually unlimited possibilities.

Note: You can combine these last three parameters however you want to come up with a list of just the pages you want.

Refining Your List

There are a number of additional options you can use to refine your final output:,
add these items to those already in the list,
remove these items from the list

return only pages whose last page part is info or index

remove all pages of these page types

only return pages whose last page part is a number

this doesn't work in pagelists, but will in queries

shuffle the order of the list

list pages modified most recently first

sort={+p} or {+field} or {+2}, etc
sorts the output based on various vars

reverse the order of the list

when='number {+p2} && more {+p2} 1200'
only returns pages with p2 > 1200 (can use any conditional).

only return first 10 items

return items 10-20

return all items (ignore searchlimit in site.config, or default of 50).

Note: The sort parameter can recognize a wide variety of values including most data, page, and template variables. You can also try {+group}, {+lastmodified} and possibly others.

Generating the Report

Once the items in the list are established, and the results refined, the function sends them over to the report engine. This engine is very powerful and gives you a wide very variety of options. See the tutorial for more information. Here's a brief summary:

You can use either a template or a fmt to generate the report. Templates run each item through the entire BoltWire markup engine and allow maximum versatility. It can be inline (defined in the function/command) or you can refer to a template page. The fmt returns raw markup back to the page and the BoltWire markup engine simply completes its cycle for the entire page. This is far faster, but it only allows you to include markup in the fmt that has not already been processed. So in general, templates are safer, fmts are faster.

If neither the template or fmt parameter is defined, list tries to set fmt to the value of parameter 2.

Several templates/fmts are built into BoltWire. You can set either template or fmt to any of these:

count - returns total number of hits
csv - returns a csv list of hits
list - returns a line of items separated by linebreaks
title - returns a list of titles linked to the pages
toc - returns a list of links indented by {p0}
default - returns a list of breadcrumbs

Note: the default for the search command/function is the last option--breadcrumbs. For the list command/function, it uses list.


Normally each item in the output is joined together by a simple line break. You can change what joins them by resetting the join parameter. For example, [(search pages=a,b,c join=' | ')] will generate: a | b | c. To eliminate any delimiter set join=false.

Tables & Columns

You can create a table easily by using the following format. It supplies the opening and closing table markups, and each item generates a row. If you want to customize the table, you can set its attributes in the table parameter, like table='border=1' instead of table=true.

[(search bob,joe,dave fmt=[r][c]{+p} [c]{~{+p}:phone} table=true)]

If you have a short output (like title or {+page}), you can set cols=3 (or some other number) and a table will be generated with an equal portion of elements in each column. If you want special formatting for the table, you can add a table='some parameters' to the function as well. You do NOT need to put table=true for columns.


Suppose you set fmt=mydisplay. BoltWire first looks for an anchored section on the current page (or the action page if you are calling an action). Then it tries to find template.mydisplay. Finally it looks for a page called mydisplay. If none of these can be found, it will use the letters "mydisplay" as your fmt. You can of course put your fmt value directly in the fmt parameter. That's called an inline fmt.

Once BoltWire has a fmt value, it applies this value to each item in the list and links them together using the report delimiter (usually a line break). BoltWire then does whatever processing remains for the page on the output. This requires you to be familiar with the markup table to see which rules follow the function calling the list, and which are before. For long reports, the speed advantages of fmts over templates are significant.

Though not usually desirable, if you want to freeze the list output and stop all further processing use output=escape or escape=true.

The following template replacements are available to your fmt through some special code in the BoltWire report engine:

{+p} = The current item
{+p0} = The number of page parts
{+p1}, {+p2} = Individual page parts
{+page} = Last page part
{+count} = Return 7 if the seventh item
{+prev} = The item immediately preceding
{+next} = The next item
{+group} = The current page minus the last page part
{+first} = The first item in the report
{+last} = The last item in the report
{+matches} = Total number of items

You can also insert any parameter in the command/function directly into the fmt/template. So if you added color=red to the search command/function, you could put {+color} in the fmt and it would be replaced with red.


Templates are similar to fmts. BoltWire looks for a value in the same locations as fmts, and if nothing is found, it too will use an inline template. Once it has its value it applies it to each item in the report. However, it runs the entire markup table on each item, meaning you can use any markup and create as elaborate a template as you wish. Another difference is that the output is escaped by default. Though not recommended you can turn this off by setting escape=false.

All the template replacements available for fmts (see above, including the parameter insertions) are also available for templates. If you set (and that page has items in your list as info fields), the following template replacements become available:

{+field} = the page name
{+value} = the corresponding info value
{+value::1} = the correspondng info value, part 1
{+#1} = the corresponding info value, part 1

If you use a full template, rather than an inline template you can greatly customize your report. For example, you can modify the report for the first item, the last item, for each new group, and even for specific items. You can also control what to display if there are no matches. Here's an easy example of a full template:

[(list bob,mary,sue,dave template=profile)]

[(template first)]Welcome to my profile report!
[(template each)]{+p}
Phone: {~:phone}
Email: {~:email}
Address: {~:address}
[(template last)]Printed <(time %x)>
[(template none)]No records found...
The template is defined by the anchor and continues to the next anchor. It is hidden in comment markups, so the template is not visible on the page.

This particular template creates a nice header, displays each members id, phone, email and address drawn from the member page, and then the date is printed. If no matches are found. If there were more than one group in my list, I could have added a [(template group)] option to insert something between each change of page groups. If I wanted to display something special for sue, I could have added [(template 3)]. Actually, that would apply to mary, because once the output is alphabetized, mary will be number three.