info complete

info complete indicates whether a string is a complete Tcl script.


info complete script


Returns 1 if script is a complete in the sense that the following things are syntactically complete:

  • braced words
  • quoted words
  • command substitutions (brackets)
  • array element names
  • commands

Otherwise, info complete returns 0. This command is typically used in line-oriented input environments to allow users to type in commands that span multiple lines; if the command isn't complete, the script can delay evaluating it until additional lines have been typed to complete the command.

A command is not considered complete if it ends in a backslash followed by a newline:

info complete \\\n
# -> 0

However, a script ending in just a backslash may be complete:

info complete \\
# -> 1

Therefore, when using info complete on a line that has been read from a channel using gets, the \n stripped off by gets should be re-added first. See also issue 1775878 .

info complete is not a full Tcl syntax checker, and there are some values that it considers complete even though they contain syntax errors. As previously stated, the purpose of info complete is to determine whether enough of the script has been read to parse it as a sequence of complete commands.


Tool Protocol Language
uses info complete to parse data that is formatted as a syntactically valid Tcl script.

Not for Validating Lists

RS: Could it be that info complete can be used generally to check whether a string can be parsed as a list? I used to use expr {![catch {llength $x}]} for that purpose...

The answer: "no". It is possible for a string to be "info complete" but not be a list. To wit:

medranocalvo: One can use string is list.

% set foo "{this is a test}{more stuff}"
{this is a test}{more stuff}
% llength $foo
list element in braces followed by "{more" instead of space
% info complete $foo

Trailing Backslash

AMG: It seems odd to me that info complete doesn't return false when its argument has a trailing backslash (or an odd number of trailing backslashes), since that's normally used to signify that the command is continued onto the next line. An interactive shell relying on info complete likely has to implement its own check for trailing backslashes, e.g.:

proc complete {script} {
    expr {[info complete $script] && [regexp {(?:^|[^\\])(?:\\\\)*$} $script]}

Example usage:

# single word
info complete a            ;# 1
complete      a            ;# 1

# two words
info complete a\ b         ;# 1
complete      a\ b         ;# 1

# unclosed quote
info complete \"a          ;# 0
complete      \"a          ;# 0

# closed quote
info complete \"a\"        ;# 1
complete      \"a\"        ;# 1

# unclosed brace
info complete \{a          ;# 0
complete      \{a          ;# 0

# closed brace
info complete \{a\}        ;# 1
complete      \{a\}        ;# 1

# unclosed nested brace
info complete \{\{a\}      ;# 0
complete      \{\{a\}      ;# 0

# line ends in double backslash
info complete a\\\\        ;# 1
complete      a\\\\        ;# 1

# line ends in single backslash
info complete a\\          ;# 1
complete      a\\          ;# 0

DKF: The key is that info complete in those cases sees a backslash at the end of a string which is OK, complete. It's when the backslash is followed by a newline that things are magically different:

puts [info complete "abc\\"]        ;# 1
puts [info complete "abc\\\n"]      ;# 0
puts [info complete "abc\\\ndef"]   ;# 1
puts [info complete "abc\\\n "]     ;# 1

AMG: Therefore, the desired functionality (for the use case described at the top of this page) can be had simply:

proc complete {script} {
    info complete $script\n

That's cool. As far as I know, this version of complete gives exactly the same results as the one involving regexp.

PYK 2014-04-23: It's also the solution implemented to fix issue 1775878

TMH 2017-10-18: Is there a way to differentiate between a string/list/dict and a anonymous proc you are passing to the apply command? My use case is that Im trying to build a proc where the first parameter is a list and the second parameter is either a string or an anonymous proc. The string version is a shorthand, and will define the anonymous proc for you. Otherwise run the anonymous proc. Trick is that the string isnt a constant, so I cant just say is arg2=="predefined string".

AMG: No, because everything is a string. Therefore all lambdas (argument to the [apply] command) are also strings. You can write some heuristic to guess, e.g. lambdas are always two- or three-element lists, but many single-command scripts are as well.