Tcl · Module 17
The Tool Console vs Batch Mode
Explore at the prompt, then keep what worked in a file. The handover is where scripts break, because three things change the moment nobody is watching.
Intermediate17 min readtcledapart-iibatchinteractiveexit-status
Part II · Module 17 · Chapter 17.2 · The Tool Console vs Batch Mode
There are two ways to run commands in a tool, and you will use both constantly.
Interactively, at the prompt — you type a command, see what it does, and decide what to try next. This is how you explore an unfamiliar design.
In batch, from a file — the tool reads a script and runs it with nobody watching. This is how real work happens: overnight, on a build machine, launched by something else.
The normal workflow moves from the first to the second: explore at the prompt, then keep what worked in a file. That handover is where scripts break, because three things change when nobody is watching.
1. Difference one: results are echoed
The same four commands, typed at a prompt:
set x 5
5
% expr {$x * 2}
10
% puts "explicit output"
explicit output
% llength {a b c}
3
%Now the identical four commands in a file, run as a script:
# demo.tcl
set x 5
expr {$x * 2}
puts "explicit output"explicit outputOne line. Interactively, every command printed its result — set x 5 showed 5, expr showed 10, llength showed 3. In batch, none of them did. Only puts produced output.
2. Difference two: prompts
% is the interpreter asking for the next command. It appears only when a human is there to answer.
That sounds trivial and has one real consequence: a batch script must never wait for input. A command that would prompt for confirmation interactively will, in batch, either hang forever or take a default you did not choose. If a tool command has an "are you sure" behaviour, find its non-interactive form before putting it in a script.
3. Difference three: what happens after an error
This is the important one.
In batch:
# err.tcl
puts "step 1 ok"
set y $nosuchvar
puts "step 3 — does this run?"step 1 ok
can't read "nosuchvar": no such variable
while executing
"set y $nosuchvar"
(file "err.tcl" line 2)
[exit status 1]The script stopped. Step 3 never ran, and the process exited 1.
The same three commands typed at a prompt:
puts "step 1 ok"
step 1 ok
% set y $nosuchvar
can't read "nosuchvar": no such variable
% puts "step 3 — does this run?"
step 3 — does this run?
%The error printed, and step 3 ran anyway.
The shorter interactive message is also worth knowing about, because the trace is the useful part. If an error is confusing at the prompt, $errorInfo has the full trace from Chapter 14.6:
puts $::errorInfo4. A script can tell which mode it is in
Tcl sets a variable for this:
tcl_interactive : 0That is from a batch run. Interactively it is 1.
So a script can adapt — ask for confirmation when a human is there, assume the safe default when not:
if {[info exists tcl_interactive] && $tcl_interactive} {
puts -nonewline "overwrite $out? \[y/N\] " ; flush stdout
if {[gets stdin ans] < 0 || ![string equal -nocase $ans y]} { exit 2 }
} else {
# no human: never prompt, take the documented default
}Use this sparingly. A script that behaves differently in the two modes is harder to reason about, and the usual right answer is to behave the same way in both. Confirmation prompts are the honest exception.
5. The handover, done properly
Moving from prompt to file is not copy-and-paste. Four things to add:
Add the puts calls. Anything you want to see must be printed explicitly — §1.
Re-run from a clean state. Your session has an hour of accumulated state behind it; the script will not. Every assumption it relies on must be in the file. This is Chapter 17.1 §6's long-lived session, and it is why a script that works for you fails for someone else.
Decide what each failure should do. At the prompt you saw errors and judged each one. A script needs that judgement written down — catch where continuing is right, let it stop where continuing is not, and an honest exit status either way.
Say what it needs. A usage line and a preflight, as in Chapter 15.9 and Chapter 14.10 §8.
A batch flow script therefore looks like this, which is Part I unchanged:
# Requires: a tool providing read_design, get_cells and report_area.
# exit status: 0 all stages ran, 1 a stage failed, 2 usage error.
if {[llength $argv] != 1} {
puts stderr "usage: [file tail $argv0] <design-file>"
exit 2
}
set failures 0
foreach stage {read elaborate check} {
if {[catch {run_stage $stage} err]} {
puts stderr "error: stage $stage failed: $err"
incr failures
break
}
puts "stage $stage ok"
}
exit [expr {$failures > 0 ? 1 : 0}]6. Which to use when
| Use the console for | Use batch for |
|---|---|
| exploring an unfamiliar design | anything that will run more than once |
| checking what a command returns | overnight and build-machine runs |
| trying a constraint before committing to it | anything another person will run |
| debugging a failure interactively | anything whose result is recorded |
The rule of thumb: the console is for finding out; the file is for doing. Work that is going to be repeated, reviewed or trusted belongs in a file, under version control, with an exit status.
7. Exercises
Exercise 1. Name the three things that change between console and batch.
Exercise 2. You typed llength $cells at the prompt and saw 412. The same line in a script prints nothing. Why, and what is the fix?
Exercise 3. Why must a batch script never wait for input?
Exercise 4. An error at the prompt shows one line; the same error in a script shows several. What is the difference, and how do you get the detail interactively?
Exercise 5. A sequence worked when you typed it and stops at step 4 as a script. What is probably true about step 4, and which mode is behaving correctly?
Exercise 6. How does a script find out whether a human is present?
Exercise 7. Name two things you must add when moving commands from the prompt into a file.
Where this fits
Part of the Tcl curriculum.
