You can annotate the PGN output of CQL using the comment filter. A comment filter consists of the word comment followed by a list of arguments enclosed in parentheses:
  comment ("The white king is on square: " K)

Each argument in the argument list can be either a quoted string or a filter with a value.

In the example above, the first argument is the quoted string "The white king is on square: " and the second argument is the piece designator K, which denotes the square where the white king is. If this comment filter is evaluated at the start position, the comment The white king is on square: e1 will be inserted into the PGN file.

A comment filter matches any position.

If the argument is a quoted string, the comment filter outputs that string. If the argument is a set filter (other than a piece variable) the comment filter outputs the set of squares to which it corresponds. If the argument is a piece variable, the comment filter outputs the character representation of the piece that is the value of the piece variable, as well as the square it is on.

If the argument is a position filter, the comment filter outputs the textual representation of the corresponding position location. If the position is in the mainline, then this textual representation consists of the move number and side to move (e.g. move 24 (wtm)). If the position is in a variation, then, in addition to the move number and side to move, the positionid of the value of the argument is also output. In addition, that id is output at the position location itself.

Where the comment is inserted

In PGN, positions are not commented: moves are commented. But in CQL, a comment filter is evaluated at a particular position. Therefore, the comment associated with a comment filter is output in the PGN file just after the previous move to the position (or before the initial position, if the current position is the initial position).

Using comment with the move filter

This could cause confusion when used with the move filter. Consider this CQL fragment:

    move from K
    {comment "The King moved from: " K}

Suppose the current position is with white to move just before white's move 10, which is a king move and the previous move was a black queen move. Suppose the King is on the square b2:

    9. Ra1 Qa8
    10. Kb3

The move filter would match that position and the comment string, "The King moved from: b2" would be output after the previous move. Thus, the output pgn would be:

    9. Ra1 Qa8 {The King moved from b2}
    10. Kb3

This is confusing because it looks like a comment to a move is commenting the wrong move.

Therefore, the move filter has a special feature to prevent this: it accepts a parameter named "comment" that is part of the move filter itself, and evaluates the comment at the position reached as a result of making the move, in this case the position after white's move 10. Since the comment is evaluated at the position after white's move 10, the comment appears after the previous move, which is white's move 10. That is, using the CQL (note that the left braces around the comment filter have been removed):

    move from K
    comment "The King move from: " k

The above is actually parsed as a single move filter with a from parameter a and a comment parameter. The output pgn will be:

    9. Ra1 Qa8 
    10. Kb3 {The King moved from b2}

Usually when you want to comment a move filter (other than move previous or move legal or move pseudolegal) this is the behavior you want, and you should put the comment adjacent to the move filter.

Smart comments

CQL tries to avoid cluttering the pgn files with unnecessary comments. It does that in two ways:
  • If a filter doesn't match a position all its "associated comments" are deleted. The associated comments of a filter are comments that appear in the filter.
  • Only comments associated with the maximum value of a sort filter are output.

smart comments as part of another filter

For example, comments in a compound filter are not printed unless the whole compound filter matches:
    {comment "This will not be output"

smart comments as part of a line filter

This feature is particularly useful in conjunction with line, because each move in a particular can be commented, but the comments will only be printed if the whol maneuver matches:
    line --> {check comment ("the first check")}
         --> {check comment ("the second check")}
         -->  {mate comment ("and mate")}

Here, the line filter is intended to match a maneuver in which two consecutive checks are delivered followed by mate on the next move. The output PGN file will comment only moves which are part of the entire maneuver: a check that that is not followed by a check and mate will not be commented.

smart comments as part of a sort filter

An example of the use of smart comments with sort is in most-visited-square-2.cql:
square VisitedSquare in .
 sort "max number of visits to a single square"{
   comment ("The most visited square is: " VisitedSquare)
   find all
      move to VisitedSquare
  }>= 15
The main work here is done by the find filter, which finds and comments all visits to the square VisitedSquare (which is set sequentially to each square on the board). The find filter is being sorted, together with a comment that states what the most visited square actually is.

Without smart comments, this CQL file would print comments for each square on the board, for each move in fact. Because of smart comments and the sort, however, only the comments that pertain to the value of VisitedSquare for which the maximum number of visits was reached are inserted into the output PGN file.

Note as well how only the moves that move to the most visited square are commented as "Found" in the pgn file. That is because all the comments pertaining to visits by other squares are automatically discarded by the smart comment logic.

Controlling which comments are output

CQL inserts three kinds of comments into output PGN files:
  1. User-generated comments via the comment filter.
  2. CQL-generated comments associated to certain filters (find, echo, line, consecutivemoves).
  3. The comment "CQL" in a position that matches the body of the CQL file.
By default all these are output.

If the CQL header contains the word quiet or if CQL was invoked with the -quiet option, only user-generated comments and header comments are output.

If the CQL header contains the word silent or if CQL was invoked with the -silent option, no comments are inserted into the PGN file.

If the CQL header a different level of quietness than an option specified at the command line, the command line option controls.

The word CQL can be changed by using the matchstring quoted_string header option or the -matchstring string command line parameter. If an argument to matchstring is the empty string, then the CQL word is not printed on matching.

Notes on comment

Comments are very useful both for debugging and for explaining the output. For example, to show the value of a variable, use say
    x= #P
    comment ("The white pawns are on squares: " P 
              "and the value of x is: " x)


The diagram below shows the oldest smothered mate study:
Lucena 1497
(found from CQL file: smotheredmate.cql)

Note how in the output file generated from the CQL, the blockers of the black king are annotated.

A more sophisticated example is from serialpin-out.pgn. Note the comments to the following position, taken from a Troitzky/Korolkov study:

Troitzky/Korolkov 1938, (corrected 2004)
(found from CQL file: serialpin.cql)

The comment is:

    Pin chain: Rd8 pins bd7 pins Bb5 pins rc4 pins Rb4
This uses smart comments to make sure only the correct pins are printed. Without delving too deeply into the specific logic of serialpin.cql, each pinned piece in a position makes a sequence of comments that describe the pin chain beginning at that piece. At the end, however, only the longest chain is actually output to the PGN file.

Another example of smart comments is in the file most-visited-square-2.cql, which was discussed above.