Updated 2012-12-01 04:48:54 by RLE

puts - Write to a channel
puts ?-nonewline? ?channelId? string


Writes the characters given by string to the channel given by channelId. ChannelId must be a channel identifier such as returned from a previous invocation of open or socket. It must have been opened for output. If no channelId is specified then it defaults to stdout. Puts normally outputs a newline character after string, but this feature may be suppressed by specifying the -nonewline switch. The latter is necessary when Working with binary data.

NOTE: puts returns a null string as its return value - it does not return the output going to the channel. Some people write something like:
 set abc [puts "test"] 

thinking that the variable $abc will have the value "test" in it. It won't. (However, you can use the return value of set as an argument to puts instead.)

Newline characters in the output are translated by puts to platform-specific end-of-line sequences according to the current value of the -translation option for the channel (for example, on PCs newlines are normally replaced with carriage-return-linefeed sequences; on older Macintoshes newlines are normally replaced with carriage-returns). See the fconfigure manual entry for a discussion on ways in which fconfigure will alter output.

Tcl buffers output internally, so characters written with puts may not appear immediately on the output file or device; Tcl will normally delay output until the buffer is full or the channel is closed. You can force output to appear immediately with the flush command. Output to the terminal (i.e., stdout under normal circumstances) is normally line-buffered; stderr is unbuffered by default.

When the output buffer fills up, the puts command will normally block until all the buffered data has been accepted for output by the operating system. If channelId is in nonblocking mode then the puts command will not block even if the operating system cannot accept the data. Instead, Tcl continues to buffer the data and writes it in the background as fast as the underlying file or device can accept it. The application must use the Tcl event loop for nonblocking output to work; otherwise Tcl never finds out that the file or device is ready for more output data. It is possible for an arbitrarily large amount of data to be buffered for a channel in nonblocking mode, which could consume a large amount of memory. To avoid wasting memory, nonblocking I/O should normally be used in an event-driven fashion with the fileevent command (don't invoke puts unless you have recently been notified via a file event that the channel is ready for more output data). (From: Tcl Help)

The only value string may not always take is "-nonewline". If you want to print the string "-nonewline" with a newline, you can only do
 puts -nonewline -nonewline\n

(where the \n neutralizes the effect of the first -nonewline, which is the switch; but I never needed that so far;-) or, as Andreas Leitgeb pointed out,
 puts stdout $string

where string may have any value, including "-nonewline".

MG finds this not to be true, on Win XP and ActiveTcl 8.4.9 using wish. Doing
  puts -nonewline

does print the string '-nonewline' to the console. Presumably this is because it checks the number of args given, and only checks for the switch if there are two args.

Darren New recently pointed out in comp.lang.tcl that:
 > Last I looked,
 >   puts $x
 > actually called write() twice, one for $x, one for \n. This would leave
 > the possibility of getting two lines of data and two newlines.
 >   puts -nonewline $x\n
 > is what I use to prevent this.

This was in the context of two different programs/procs writing to the same log file...

puts from a tclsh may, when piped through more, raise
 error writing "stdout": broken pipe
    while executing
 "puts "<$tok> name=\"[string range $line 5 end]\">""
    ("while" body line 9)
    invoked from within...

No big problem but ugly - therefore I routinely add the one-liner
   proc puts! s {catch {puts $s}}

and call puts! in place of the real thing. (RS) A variation, which requires that you only use simple puts (to stdout, no -nonewline), but then is transparent (i.e. in your normal script you can just call normal puts):
 rename puts tcl::puts
 proc puts string {if [catch {tcl::puts $string}] exit}

Note that puts has an artifact from Tcl 6.4 (!) which is undocumented. If the puts command is invalidly called with 3 arguments, one gets the following error:
 % puts stdout foo bar
 bad argument "bar": should be "nonewline"

This is due to the fact that back in ancient times, the syntax for the -nonewline was not a leading argument, but a trailing string value of "nonewline":
 % puts stdout $tcl_version nonewline

puts workaround shows how to overload puts, so stdout and stderr (which are not available on iPaq) are rerouted to a text widget. See also getputs for a brief overload.

Tcl 8.3 on Windows had a puts performance problem, when data was written to a file file. The problem was that every buffer write caused a flush of the disk cache. The workaround in 8.3 was to do (once, at beginning of script):
    fconfigure stdout -buffering full -buffersize 262144

so that there were few disk writes performed. (Thanks KBK and the Tcl chatroom for the quick answer! RS)

Silas - 2006-01-06 - You can print colors or bold text with puts (at least, in a Linux shell which supports that (like xterm or rxvt)).

puts supports ANSI standard (ISO) 6429. In ANSI color control, RS uses that to color pieces of text in a text widget.

Here is a little example:
 % puts "\033\[01;32mFoo\033\[0mbar"

The Foo is bold green.

By supports above, it appears someone means "can be forced to emulate". Which is fine, I suppose. However, note that this support is no different than put's general "support" of outputting whatever characters someone wants to specify in the argument. In this case, someone hand coded the escape sequences necessary to change the colors of one particular kind of terminal emulation. If you need some other escape sequence, then you would edit the string and hard code the new sequence. Or you could look into terminfo/curses related work being done in things like ck, CTk, etc.

Any ISO 6429 url about?

Vadtec - 2007-09-02 - I found these links which provide information on ANSI color control. The first link, to ECMA, is quite large and is the entire ISO 6429 specification. It is probably over kill for most needs. The relevant sections start on page 75 (pdf)/page 61 (print) of the document, section 8.3.117 SGR - SELECT GRAPHIC RENDITION and ends on page 62 of the document.

The second link I found by chance with Google. The relevant information for ANSI color control is in the section labled ISO 6429 (ANSI) COLOR SEQUENCES. (Note that "brighter colors" means "bold".)

I hope this helps someone. :)