TclX(3tclx)

๐Ÿ’– TclX โ€” the extended command set for Tcl ๐Ÿ’–

okay bestie, so this is the man page for TclX, aka Extended Tcl, living in the 3tclx section of the manual. it's a whole vibe, it's a whole era, and it's LONG, so buckle up ๐ŸŽ€


โœจ SYNOPSIS โœจ

package require Tclx

that's it. that's the whole synopsis. slay. ๐Ÿ’…


๐ŸŒธ INTRODUCTION ๐ŸŒธ

okay so, this man page right here? it holds the docs for every single extension that Extended Tcl (TclX) adds on top of Tcl. TclX levels Tcl's capabilities all the way up by dropping brand-new commands into it โ€” and the way that it does that is without changing the syntax of standard Tcl. no cap. Extended Tcl is a superset of standard Tcl, and it gets built right alongside the standard Tcl sources. they're roomies ๐Ÿซถ

Extended Tcl was created by Karl Lehenbauer and Mark Diekhans, and it is freely redistributable for any use without license or fee. no strings, no fees, no drama. iconic behavior fr fr ๐Ÿ’–

Available since 1989 โ€” yes, 1989, she's been serving looks for literal decades ๐Ÿ‘‘ โ€” Extended Tcl, also known as TclX, doesn't just add capabilities to Tcl. it has also been the source of many of the capabilities of the baseline Tcl release, including:

  • arrays
  • files
  • sockets
  • file events
  • date and time handling

among others. like, the baseline Tcl release owes her a thank-you note, lowkey ๐Ÿ˜ญ

Extended Tcl introduces a set of new commands and a user-extensible library of useful Tcl procedures โ€” and literally any of those can be automatically loaded on the first attempt to execute it. it just shows up when you need it. main character energy, no questions asked โœจ


๐Ÿฆ‹ the sections, bestie ๐Ÿฆ‹

the command descriptions are separated into several sections:

  • General Commands
  • Debugging and Development Commands
  • Unix Access Commands
  • File Commands
  • Network Programming Support
  • File Scanning Commands
  • Math Commands
  • List Manipulation Commands
  • Keyed Lists
  • String and Character Manipulation Commands
  • XPG/3 Message Catalog Commands
  • Help Facility
  • Tcl Loadable Libraries and Packages

that's the whole map. more parts coming, so don't go anywhere ๐Ÿ’œ

๐ŸŒˆ GENERAL COMMANDS ๐ŸŒˆ

okay bestie, this is the grab bag ๐Ÿ’– โ€” a set of general, actually-useful Tcl commands. In here you've got a command to begin an interactive session with Tcl, a facility for tracing execution, and a looping command. yes, all three, we love a multitasker. โœจ


๐Ÿ—‚๏ธ dirs

This procedure lists the directories in the directory stack. short, sweet, no notes. ๐ŸŽ€

๐Ÿ” commandloop

commandloop ?-async? ?-interactive on | off | tty? ?-prompt1 cmd? ?-prompt2 cmd? ?-endcommand cmd?

Creates an interactive command loop that reads commands from stdin and writes results to stdout. Command loops can either be blocking or event oriented. This one is for when your Tcl script doesn't normally chat interactively with a user through a Tcl command interpreter, but sometimes does wanna slide into that mode โ€” maybe for debugging, maybe for user configuration. The command loop terminates on EOF. ๐Ÿ‘‘

Here's what you can pass:

  • -async โ€” a command handler gets associated with stdin. When input is available on stdin, it gets read and accumulated until a full command is available, and then that command gets evaluated. Heads up: an event loop must be entered for input to actually be read and processed. ๐Ÿ’…
  • -interactive on | off | tty โ€” enable or disable interactive command mode. In interactive mode, commands are prompted for and the results of comments are printed. The value can be any boolean value or tty. If you use tty, interactive mode is enabled when stdin is associated with a terminal or terminal emulator. The default is tty. ๐Ÿ–ฅ๏ธ
  • -prompt1 cmd โ€” if specified, cmd is evaluated and its result is used for the main command prompt. If it's not specified, the command in tcl_prompt1 is evaluated to output the prompt. Note the difference in behavior, bestie: cmd's result is used, while tcl_prompt1 outputs. This is to allow for future expansion to command loops that write to something other than stdout. ๐ŸŒธ
  • -prompt2 cmd โ€” if specified, cmd is evaluated and its result is used for the secondary (continuation) command prompt. If not specified, the command in tcl_prompt2 is evaluated to output the prompt. ๐ŸŽ€
  • -endcommand cmd โ€” if specified, cmd is evaluated when the command loop terminates. ๐Ÿซถ

and two more lil facts, no cap:

  • In interactive mode, the results of set commands with two arguments are not printed.
  • If SIGINT is configured to generate a Tcl error, it can be used to delete the current command being typed without aborting the program in progress.

๐Ÿ“ข echo

echo ?str ...?

Writes zero or more strings to standard output, followed by a newline. that's the whole thing. ๐Ÿ’–

๐Ÿ•ต๏ธ infox

infox option

Returns information about Extended Tcl, or about the current application. Every option it takes:

  • version โ€” returns the version number of Extended Tcl. That number is generated by combining the base version of the standard Tcl code with another number indicating the version of Extended Tcl being used. ๐Ÿ”ข
  • patchlevel โ€” returns the patchlevel for Extended Tcl.
  • have_fchown โ€” returns 1 if the fchown system call is available. This supports the -fileid option on the chown and chgrp commands.
  • have_fchmod โ€” returns 1 if the fchmod system call is available. This supports the -fileid option on the chmod command.
  • have_flock โ€” returns 1 if the flock command is defined, 0 if it's not available.
  • have_fsync โ€” returns 1 if the fsync system call is available and the sync command will sync individual files. 0 if it's not available and the sync command will always sync all file buffers.
  • have_ftruncate โ€” returns 1 if the ftruncate or chsize system call is available. If it is, the ftruncate command's -fileid option may be used.
  • have_msgcats โ€” returns 1 if XPG message catalogs are available, 0 if they're not. catgets is designed to keep on functioning without message catalogs, always returning the default string.
  • have_posix_signals โ€” returns 1 if Posix signals are available (block and unblock options available for the signal command). 0 is returned if Posix signals are not available.
  • have_signal_restart โ€” returns 1 if restartable signals are available (-restart option available for the signal command). 0 is returned if restartable signals are not available.
  • have_truncate โ€” returns 1 if the truncate system call is available. If it is, the ftruncate command may truncate by file path.
  • have_waitpid โ€” returns 1 if the waitpid system call is available and the wait command has full functionality. 0 if the wait command has limited functionality.
  • appname โ€” returns the symbolic application name of the current application linked with the Extended Tcl library. The C variable tclAppName must be set by the application to return an application-specific value for this variable.
  • applongname โ€” returns a natural language name for the current application. The C variable tclLongAppName must be set by the application to return an application-specific value for this variable.
  • appversion โ€” returns the version number for the current application. The C variable tclAppVersion must be set by the application to return an application-specific value for this variable.
  • apppatchlevel โ€” returns the patchlevel for the current application. The C variable tclAppPatchlevel must be set by the application to return an application-specific value for this variable.

๐Ÿ”‘ for_array_keys

for_array_keys var array_name code

This procedure does a foreach-style loop for each key in the named array. The break and continue statements work just like they do with foreach. ๐Ÿ’…

๐ŸŒณ for_recursive_glob

for_recursive_glob var dirlist globlist code

This procedure does a foreach-style loop over recursively matched files. Every directory in dirlist is recursively searched (breadth-first), comparing each file it finds against the file glob patterns in globlist. For each matched file, the variable var is set to the file path and code is evaluated. And listen โ€” symbolic links are not followed. ๐Ÿฆ‹

๐Ÿ”„ loop

loop var first limit ?increment? body

loop is a looping command, similar in behavior to the Tcl for statement โ€” except loop achieves substantially higher performance and is easier to code when the beginning and ending values of a loop are already known, and the loop variable is meant to be incremented by a known, fixed amount every time through. iconic, honestly. โœจ

The var argument is the name of a Tcl variable that will hold the loop index. That index gets set to the value specified by first. The Tcl interpreter is invoked upon body zero or more times, where var is incremented by increment every time through the loop โ€” or by one if increment isn't specified. increment can be negative, in which case the loop counts downwards. ๐Ÿ“‰

When var reaches limit, the loop terminates without a subsequent execution of body. For instance, if the original loop parameters would cause loop to terminate โ€” say first was one, limit was zero, and increment was not specified or was non-negative โ€” then body isn't executed at all and loop returns. ๐Ÿซถ

first, limit and increment are integer expressions. They're only evaluated once, at the beginning of the loop. ๐Ÿ”ข

If a continue command is invoked within body, then any remaining commands in the current execution of body are skipped, same as with the for command. If a break command is invoked within body, then the loop command returns immediately. loop returns an empty string. ๐Ÿ’œ

๐Ÿ“ค popd

This procedure pops the top directory entry off the directory stack and makes it the current directory. bye bestie ๐Ÿ‘‹

๐Ÿ“ฅ pushd

pushd ?dir?

This procedure pushes the current directory onto the directory stack and cds to the specified directory. If no directory is specified, then the current directory is pushed, but it remains unchanged. ๐Ÿ’…

๐ŸŒฒ recursive_glob

recursive_glob dirlist globlist

This procedure returns a list of recursively matched files. Every directory in dirlist is recursively searched (breadth-first), comparing each file found against the file glob patterns in globlist. And once again for the people in the back: symbolic links are not followed. ๐Ÿ“

๐Ÿ“œ showproc

showproc ?procname ...?

This procedure lists the definition of the named procedures, loading them if they're not already loaded. If you don't supply any procedure names, the definitions of all currently loaded procedures are returned. very "show me everything" of it. ๐Ÿ‘‘

๐Ÿ›Ÿ try_eval

try_eval code catch ?finally?

The try_eval command evaluates code in the current context.

If an error occurs during the evaluation and catch is not empty, then catch is evaluated to handle the error. The result of the command, containing the error message, will be stored in a global variable errorResult. The global variables errorResult, errorInfo and errorCode will be imported into the current scope, so there's no need to execute a global command. The result of the catch command becomes the result of the try_eval command. And if the error that caused catch to be evaluated is meant to be continued, you use this command:

error $errorResult $errorCode $errorInfo

If the finally argument is supplied and not empty, it's evaluated after the evaluation of the code and the catch commands. If an error occurs during the evaluation of the finally command, it becomes the result of the try_eval command. Otherwise, the result of either code or catch is preserved, as described above. ๐Ÿซถ


๐Ÿ› DEBUGGING AND DEVELOPMENT COMMANDS ๐Ÿ›

okay bestie, this section is literally the backstage pass of TclX ๐Ÿ’… โ€” all the commands and procedures you're gonna be obsessed with when you're building and debugging your Tcl scripts. let's get into it.


cmdtrace

cmdtrace level | on ?noeval? ?notruncate? ?procs? ?fileid? ?command cmd?

Prints a trace statement for every command that gets executed at depth of level or below (and heads up, 1 is the top level, periodt). If you say on, then literally every command at any level gets traced. here's the lil menu of options you can pass:

  • noeval โ€” makes the arguments print unevaluated. So if noeval is on, the args get printed before evaluation; otherwise they get printed after. Also: if the command line is longer than 60 characters, it gets truncated to 60 and a "..." gets postpended to let you know there was more output than what got displayed. And if an evaluated argument contains a space, the whole argument gets wrapped in braces ({}) so you can visually tell the arguments apart from each other ๐Ÿซถ
  • notruncate โ€” turns off the truncation of commands and evaluated arguments. no more cutting things short, she gets to be her full self โœจ
  • procs โ€” enables tracing of procedure calls only. Commands that aren't procedure calls (like, calls to commands written in C, C++ or some object-compatible language) do not get traced if you pass procs. This one is highkey useful for massively reducing cmdtrace output while you're debugging. slay.
  • fileid โ€” this is a file id as returned by the open command. If you specify it, the trace output goes to the file instead of stdout. A stdio buffer flush happens after every single line is written, so you can monitor the trace externally, or get useful info for debugging problems that cause core dumps ๐Ÿ’€
  • command cmd โ€” calls the specified command cmd when each command is executed, instead of tracing to a file. See the description of the functionality below ๐Ÿ‘‡. This option may not be specified together with a fileid.

The most common use of this command is to enable tracing to a file during development, so that if a failure occurs, a trace is right there waiting when you need it. Real talk though: command tracing will slow down execution of your code, so it should be removed once the code is debugged. The following command enables tracing to a file for the rest of the program:

cmdtrace on [open cmd.log w]

The command option causes a user-specified trace command to be called for each command executed. The command will have the following arguments appended to it before evaluation:

  • command โ€” a string containing the text of the command, before any argument substitution.
  • argv โ€” a list of the final argument information that will be passed to the command after command, variable, and backslash substitution.
  • evalLevel โ€” the Tcl_Eval call level.
  • procLevel โ€” the procedure call level.

You should construct the command in such a manner that it will still work if additional arguments get added in the future. It is suggested that the command be a proc with the final argument being args ๐Ÿ‘‘

Tracing will be turned off while the command is being executed. The values of the errorInfo and errorCode variables will be saved and restored on return from the command. It is the command's responsibility to preserve all other state, bestie โ€” nobody else is doing it for you.

If an error occurs during the execution of command, an error message gets dumped to stderr and tracing is disabled. The underlying mechanism that this functionality is built on does not support returning an error to the interpreter. so like, don't expect that to work ๐Ÿ™ˆ

cmdtrace off

Turns off all tracing. bye girl ๐Ÿ’…

cmdtrace depth

Returns the current maximum trace level, or zero if trace is disabled.


edprocs

edprocs ?proc...?

This procedure writes the named procedures โ€” or all currently defined procedures if you don't name any โ€” to a temporary file, then calls an editor on it (as specified by the EDITOR environment variable, or vi if none is specified), and then sources the file back in if it was changed. it's giving "edit your whole vibe in one go" โœจ


profile

profile ?-commands? ?-eval? on
profile off arrayVar

This command collects a performance profile of a Tcl script. It collects data at the Tcl procedure level: the number of calls to a procedure, plus the amount of real and CPU time, all get collected. Time is also collected for the global context. The procedure data is collected by bucketing it based on the procedure call stack, which lets you figure out how much time is spent in a particular procedure in each of its calling contexts. iconic.

The on option enables profile data collection. If the -commands option is specified, data on all commands within a procedure is collected as well as procedures. Multiple occurrences of a command within a procedure are not distinguished from each other, but this data may still be useful for analysis, ngl.

The off option turns off profiling and moves the data collected into the array arrayVar. The array is addressed by a list containing the procedure call stack. Element zero is the top of the stack โ€” the procedure that the data is for. The data in each entry is a list consisting of the procedure call count and the real time and CPU time in milliseconds spent in the procedure (but not any procedures it calls). The list is in the form {count real cpu} ๐Ÿ’–

Normally, the variable scope stack is used when reporting where time is spent. So upleveled code is reported in the context that it was executed in, not the context that the uplevel was called in. If the -eval option is specified, the procedure evaluation (call) stack is used instead of the procedure scope stack โ€” so upleveled code is reported in the context of the procedure that did the uplevel. got it? got it. ๐ŸŽ€

A Tcl procedure profrep is supplied for reducing the data and producing a report.

On Windows, the profile command only reports elapsed real time โ€” CPU time is not available and gets reported as zero. ๐Ÿ˜ญ

profrep

profrep profDataVar sortKey ?outFile? ?userTitle?

This procedure generates a report from data collected from the profile command. ProfDataVar is the name of the array containing the data returned by the profile command. SortKey indicates which data value to sort by โ€” it should be one of "calls", "cpu" or "real". OutFile is the name of the file to write the report to; if omitted, stdout is assumed. UserTitle is an optional title line to add to the output.

Listed with indentation below each procedure or command is the procedure call stack. The first indented line is the procedure that invoked the reported procedure or command. The next line is the procedure that invoked the procedure above it, and so on and so on. If no indented procedures are shown, the procedure or command was called from the global context. Time actually spent in the global context is listed on a line labeled <global>. Upleveled code is reported in the context that it was executed in, not the context that the uplevel was called in. periodt. ๐Ÿ’…


saveprocs

saveprocs fileName ?proc...?

This procedure saves the definition of the named procedure โ€” or all currently defined procedures if none is specified โ€” to the named file. little archival queen ๐Ÿ‘‘


๐ŸŒˆ UNIX ACCESS COMMANDS ๐ŸŒˆ

These commands give you access to a whole bunch of basic Unix facilities, including process handling, date and time processing, signal handling, and executing commands via the shell. let's gooo ๐Ÿฆ‹


alarm

alarm seconds

Instructs the system to send a SIGALRM signal in the specified number of seconds. This is a floating point number, so fractions of a second may be specified. If seconds is 0.0, any previous alarm request gets canceled. Only one alarm at a time may be active โ€” and the command returns the number of seconds left in the previous alarm. On systems without the setitimer system call, seconds is rounded up to an integer number of seconds.

The alarm command is not available on Windows. ๐Ÿ™ˆ

execl

execl ?-argv0 argv0? prog ?arglist?

Does an execl, replacing the current program (either Extended Tcl or an application with Extended Tcl embedded into it) with prog, and passing the arguments in the list arglist.

The -argv0 option specifies that argv0 is to be passed to the program as argv [0] rather than prog.

Note: if you're using execl in a Tk application and it fails, you may not do anything that accesses the X server, or you'll get a BadWindow error from the X server. This includes executing the Tk version of the exit command. We suggest using the following command to abort Tk applications after an execl failure:
kill [id process]

On Windows, where the fork command is not available, execl starts a new process and returns the process id.


chroot

chroot dirname

Changes the root directory to dirname, by invoking the POSIX chroot(2) system call. This command only succeeds if running as root. big main character energy only ๐Ÿ”ฅ


fork

fork

Forks the current Tcl process. fork returns zero to the child process and the process number of the child to the parent process. If the fork fails, a Tcl error is generated.

If an execl is not going to be performed before the child process does output, or if a close and dup sequence is going to be performed on stdout or stderr, then a flush should be issued against stdout, stderr and any other open output file before doing the fork. Otherwise characters from the parent process pending in the buffers will be output by both the parent and child processes. ๐Ÿ’€

Note: if you are forking in a Tk based application you must execl before doing any window operations in the child, or you will receive a BadWindow error from the X server.
The fork command is not available on Windows.

id

id options

This command provides a means of getting, setting and converting user, group and process ids. The id command has the following options:

  • id user ?name?
  • id userid ?uid? โ€” sets the real and effective user ID to name or uid, but only if that name (or uid) is actually valid and the permissions say yes ๐Ÿ’…. Leave name (or uid) off entirely and she just hands you back the current name (or uid).
  • id convert userid uid
  • id convert user name โ€” flips a user ID number into a user name, or a user name into a user ID number. Either direction, your call, bestie ๐Ÿ”„
  • id group ?name?
  • id groupid ?gid? โ€” sets the real and effective group ID to name or gid, again only if the name (or gid) is valid and permissions allow it. Omit the name (or gid) and you get the current group name (or gid) back ๐ŸŽ€
  • id groups
  • id groupids โ€” return the current group access list of the process. The groups flavor gives you group names, and groupids gives you the id numbers. pick your fighter โœจ
  • id convert groupid gid
  • id convert group name โ€” converts a group ID number to a group name, or a group name to a group ID number. same deal, both directions ๐Ÿ’œ
  • id effective user
  • id effective userid โ€” return the effective user name, or the effective user ID number, respectively. respectively!! ๐Ÿ‘‘
  • id effective group
  • id effective groupid โ€” return the effective group name, or the effective group ID number, respectively. no notes ๐Ÿซถ
  • id effective groupids โ€” returns all of the groupids this user is a member of. the whole roster, fr fr.
  • id host โ€” returns the hostname of the system the program is running on. ๐Ÿ–ฅ๏ธ
  • id process โ€” returns the process ID of the current process. that's you, that's your PID, main character energy ๐Ÿ’…
  • id process parent โ€” returns the process ID of the parent of the current process. hi mom ๐Ÿฅน
  • id process group โ€” returns the process group ID of the current process.
  • id process group set โ€” sets the process group ID of the current process to its own process ID. glowing up the group id, iconic.
  • id host โ€” returns the standard host name of the machine the process is executing on.
okay yes, she listed id host twice โ€” that's what the page says, so that's what you get, no cap. Not a typo on my end, I'm just the messenger ๐Ÿ˜ญ
On Windows, only the host and process options are implemented. that's it, that's the list ๐Ÿ™ˆ

๐Ÿ”ฅ kill ๐Ÿ”ฅ

kill ?-pgroup ?signal? idlist

Sends a signal to each process in the list idlist, if you're permitted to (permissions matter, always ๐ŸŒธ). signal, if present, is the signal number or the symbolic name of the signal โ€” go check the signal system call manual page for the lineup. The leading SIG is optional when you specify the signal by its symbolic name. And if you just don't give a signal at all, the default for signo is 15, aka SIGTERM. the classic ๐Ÿ’€

If -pgroup is specified, the numbers in idlist are taken as process group ids and the signal gets sent to all of the processes in that process group. A process group id of 0 specifies the current process group. group chat blast ๐Ÿ“ฃ

On Windows, the kill command can terminate a process, but it can't send an arbitrary signal. so, half the power, still something โœจ

link ?-sym? srcpath destpath

Creates a directory entry, destpath, linking it to the existing file srcpath. If -sym is specified you get a symbolic link instead of a hard link. (Heads up: the -sym option is only available on systems that support symbolic links.) ๐Ÿฆ‹

The link command is not available on Windows. Use the Tcl 8.4+ file link command instead. periodt.

๐ŸŒˆ nice ๐ŸŒˆ

nice ?priorityincr?

Changes or returns the process priority. Omit priorityincr and you just get the current priority back. If priorityincr is positive, it's added to the current priority level, up to a system defined maximum (normally 19).

Negative priorityincr values cumulatively increase the program's priority down to a system defined minimum (normally -19); increasing priority with negative niceness values will only work for the superuser. sorry bestie, root privileges required ๐Ÿ‘‘

The new priority is what gets returned.

The nice command is not available on Windows. ๐Ÿ’€

๐Ÿฆ‹ readdir ๐Ÿฆ‹

readdir ?-hidden? dirPath

Returns a list containing the contents of the directory dirPath. The directory entries "." and ".." are not returned โ€” we're not doing that today ๐Ÿ’…

On Windows, -hidden may be specified to include hidden files in the result. This flag is ignored on Unix systems. she simply doesn't care on Unix ๐Ÿ™ˆ

โญ signal โญ

signal ?-restart? action siglist ?command?
Warning: If signals are being used as an event source (a trap action), rather than generating an error to terminate a task; one must use the -restart option. This causes a blocked system call, such as read or waitpid, to be restarted rather than generate an error. Failure to do this may result in unexpected errors when a signal arrives while in one of these system calls. When available, the -restart option can prevent this problem. like actually read this one, it's important ๐Ÿ˜ญ

If -restart is specified, restart blocking system calls rather than generating an error. The signal will be handled once the Tcl command that issued the system call completes. The -restart option is not available on all operating systems, and using it will generate an error when it's not supported. Use infox have_signal_restart to check for availability. vibe check your platform first โœจ

Specify the action to take when a Unix signal is received by Extended Tcl, or a program that embeds it. Siglist is a list of either the symbolic or numeric Unix signal (the SIG prefix is optional). Action is one of the following things to do when the signal shows up. To specify all modifiable signals, use * (this will not include SIGKILL and SIGSTOP, because those two literally cannot be modified, they're built different ๐Ÿ’€).

  • default โ€” perform the system default action when the signal is received (see the signal system call documentation).
  • ignore โ€” ignore the signal. not me pretending I didn't see it ๐Ÿ™ˆ
  • error โ€” generate a catchable Tcl error. It will be as if the command that was running returned an error. The error code will be in the form:
POSIX SIG signame

For the death of child signal, signame will always be SIGCHLD, rather than SIGCLD, so you can write portable code. consistency slay ๐Ÿ‘‘

  • trap โ€” when the signal occurs, execute command and continue execution if an error is not returned by command. The command will be executed in the global context. The command will be edited before execution, replacing occurrences of "%S" with the signal name. Occurrences of "%%" result in a single "%". This editing happens just before the trap command is evaluated. If an error is returned, then follow the standard Tcl error mechanism. Often command will just do an exit. dramatic exit, valid ๐Ÿ’…
  • get โ€” retrieve the current settings of the specified signals. A keyed list will be returned where the keys are one of the specified signals and the values are a list consisting of the action associated with the signal, a 0 if the signal may be delivered (not block) and a 1 if it is blocked, and a flag indicating if restarting of system calls is specified. The actions may be one of default, ignore, error or trap. If the action is trap, the third element is the command associated with the action. The action unknown is returned if a non-Tcl signal handler has been associated with the signal. mystery handler detected ๐Ÿ•ต๏ธ
  • set โ€” set signals from a keyed list in the format returned by the get. For this action, siglist is the keyed list of signal state. Signals with an action of unknown are not modified. leave the mystery handlers alone, they didn't ask to be touched ๐Ÿซถ
  • block โ€” block the specified signals from being received. (Posix systems only).
  • unblock โ€” allow the specified signal to be received. Pending signals will not occur. (Posix systems only).

The signal action will remain enabled after the specified signal has occurred. The exception to this is SIGCHLD on systems without Posix signals. For these systems, SIGCHLD is not automatically re-enabled. After a SIGCHLD signal is received, a call to wait must be performed to retrieve the exit status of the child process before issuing another signal SIGCHLD ... command. For code that is to be portable between both types of systems, use this approach. write it once, run it everywhere, that's the dream ๐ŸŒˆ

Signals are not processed until after the completion of the Tcl command that is executing when the signal is received. If an interactive Tcl shell is running, then the SIGINT will be set to error, non-interactive Tcl sessions leave SIGINT unchanged from when the process started (normally default for foreground processes and ignore for processes in the background). iykyk ๐Ÿ’…


๐Ÿ’œ sleep ๐Ÿ’œ

sleep seconds

Sleeps the Extended Tcl process for seconds seconds. Seconds, if specified as a decimal number, is truncated to an integer value. nap time, but make it integer ๐Ÿ›Œ


๐ŸŒธ system ๐ŸŒธ

system cmdstr1 ?cmdstr2...?

Concatenates cmdstr1, cmdstr2 etc with space separators (see the concat command) into a single command, then evaluates that command using the standard system shell. On Unix systems, that's /bin/sh, and on Windows it's command.com. The exit code of the command is returned. โœจ

This command differs from the exec command in that system doesn't return the executed command's standard output as the result string, and system goes through the Unix shell to provide wild card expansion, redirection, etc, as is normal from an sh command line. different tool, different vibe ๐Ÿฆ‹


๐Ÿ“ sync ๐Ÿ“

sync ?fileId?

If fileId is not specified, or if it is specified and this system doesn't support the fsync system call, issues a sync system call to flush all pending disk output. If fileId is specified and the system does support the fsync system call, issues an fsync on the file corresponding to the specified Tcl fileId to force all pending output to that file out to the disk. flush it, bestie, flush it ๐Ÿ’…

If fileId is specified, the file must be writable. A flush will be issued against the fileId before the sync.

The infox have_fsync command can be used to determine if "sync fileId" will do a sync or an fsync. go check before you assume ๐Ÿ”


๐Ÿงš times ๐Ÿงš

times

Returns a list containing the process and child execution times in the form:

utime stime cutime cstime

Also see the times(2) system call manual page. The values are in milliseconds. โฑ๏ธ

  • umask ?octalmask? โ€” sets the file-creation mode mask to the octal value you hand it as octalmask. Leave octalmask out and it just tells you what the current mask is instead. ๐Ÿ’…
  • wait ?-nohang? ?-untraced? ?-pgroup? ?pid? โ€” this one waits for a process that got spawned with the execl command to finally call it quits, whether that's from an untrapped signal or from hitting the exit system call. Pass pid and it waits on that specific process; skip it and it'll wait on literally any child process to terminate. โœจ

If you throw in -nohang, it will not block waiting for a process to die โ€” if nothing is immediately available it just hands you back an empty list. -untraced makes it also report child processes that are stopped and whose status hasn't been reported yet since they stopped. And -pgroup, when pid isn't given, means wait on any child process whose process group ID matches the calling process. Give it pid with -pgroup and that pid is read as a process group ID, so it waits on any process in that group to terminate.

What comes back is a list with three elements, bestie, and here's the tea:

  1. the process id of the process that terminated.
  2. if it exited normally, this is EXIT โ€” and the third element is the numeric exit code.
  3. if it died from a signal, this is SIG โ€” and the third element is the signal name.

And if the process is currently stopped (only on systems that support SIGSTP), the second element is STOP, followed by the signal name.

ngl there's a little gotcha here ๐Ÿ‘€ โ€” you can wait on processes that were created in the background with the exec command. BUT if any other exec command runs after that process terminates, the exec command reaps the process status and wait will never get to see it. Rude of it honestly.

On systems that don't have the waitpid system call, the -nohang, -untraced and -pgroup options just aren't there. You can use the infox have_waitpid command to figure out if you've got this functionality or not. ๐Ÿซถ


๐ŸŽ€ FILE COMMANDS ๐ŸŽ€

These commands give you extended file access and manipulation, and the range is giving: searching ASCII-sorted data files, copying files, duplicating file descriptors, controlling file access options, pulling open file status, and creating pipes with the pipe system call. Also linking files, setting file/process/user attributes, and truncating files. On Unix systems that support it, there's even an interface to the select system call. ๐ŸŒˆ

Real talk though: Tcl file I/O is built on top of the stdio library, and by default a file is buffered. So when you're talking to a process through a pipe, you need to issue a flush command to force the data out. Or โ€” alt route โ€” you can use the fcntl command to set the file's buffering mode to line-buffered or unbuffered.

  • bsearch fileId key ?retvar? ?compare_proc? โ€” searches an opened file fileId that contains lines of text sorted into ascending order, looking for a match. key is the string you're hunting for. โœจ

If retvar is given, the line from the file lands in retvar, and the command returns 1 when key was found and 0 when it wasn't. If retvar is omitted or is a null name, the command just returns the line it found โ€” or an empty string if key wasn't found at all.

By default, key gets matched against the first white-space separated field in each line, treated as an ASCII string. If compare_proc is specified, it names a Tcl procedure that gets evaluated against each line read from the sorted file while bsearch runs. compare_proc takes two arguments โ€” the key and a line pulled from the file โ€” and it should return a number less than zero if the key is less than the line, zero if the key matches the line, or greater than zero if the key is greater than the line.

๐Ÿšจ the file must be sorted in ascending order according to the exact same criteria compare_proc uses to compare the key with the line, or you'll get erroneous results. no cap.

Also this command does not work on files containing binary data (bytes of zero). ๐Ÿ’€

  • chmod [-fileid] mode filelist โ€” sets the permissions of every file in the list filelist to mode, where mode is either an absolute numeric mode or symbolic permissions just like the UNIX chmod(1) command. To give a mode as octal, prefix it with a "0" (e.g. 0622). ๐Ÿ’…

With the -fileid option, filelist is a list of open file identifiers instead of file names. Heads up: this option isn't available on all Unix systems โ€” use the infox have_fchmod command to check if you've got it.

chmod is not available on Windows.

  • chown [-fileid] owner | {owner group} filelist โ€” sets the owner of every file in the list filelist to owner, which can be a user name or a numeric user id. If the first parameter is a list, then owner gets set to the first element of that list and the group gets set to the second element. The group can be a group name or a numeric group id. If group is {}, then the file group gets set to the login group of the specified user. โœจ

With the -fileid option, filelist is a list of open file identifiers instead of file names. Again, not available on all Unix systems โ€” use the infox have_fchown command to find out if you can use it.

chown is not available on Windows.

  • chgrp [-fileid] group filelist โ€” sets the group id of every file in the list filelist to group, which can be either a group name or a numeric group id. ๐Ÿซถ

With the -fileid option, filelist is a list of open file identifiers instead of file names. Not available on all Unix systems โ€” check with the infox have_fchown command.

chgrp is not available on Windows.

  • dup fileId ?targetFileId? โ€” duplicates an open file. A brand new file id gets opened that addresses the exact same file as fileId. ๐Ÿ‘‘

If targetFileId is specified, the file is dup'd onto that specified file id โ€” normally this is stdin, stdout, or stderr. The dup command handles flushing output and closing that file for you. The new file will be buffered; if it needs to be unbuffered, use the fcntl command to set it unbuffered.

If fileId is a number rather than a Tcl file id, then dup binds that file to a Tcl file id. Super useful for accessing files that were passed down from the parent process. The ?targetFileId? argument is not valid with this operation.

On Windows, only stdin, stdout, or stderr โ€” or a non-socket file handle number โ€” may be specified for targetFileId. And dup does not work on sockets on Windows at all.

  • fcntl fileId attribute ?value? โ€” this one either sets or clears a file option, or returns its current value. If value isn't specified, you get back the current value of attribute. All values are boolean. Some attributes can only be gotten, not modified. Here's the whole roster: โœจ
    • RDONLY โ€” the file is opened for reading only. (Get only)
    • WRONLY โ€” the file is opened for writing only. (Get only)
    • RDWR โ€” the file is opened for reading and writing. (Get only)
    • READ โ€” if the file is readable. (Get only)
    • WRITE โ€” if the file is writable. (Get only)
    • APPEND โ€” the file is opened for append-only writes; all writes get forced to the end of the file. (Get or set)
    • NONBLOCK โ€” the file is to be accessed with non-blocking I/O. See the read system call for a description of how this affects the behaviour of file reads.
    • CLOEXEC โ€” close the file on a process exec. If the execl command or some other mechanism makes the process do an exec, the file gets closed when this option is set.
    • NOBUF โ€” the file is not buffered. Set it and there's no buffering for the file, periodt.
    • LINEBUF โ€” output to the file will be line buffered. The buffer gets flushed when a newline is written, when the buffer is full, or when input is requested.
    • KEEPALIVE โ€” keep a socket connection alive. If SIGPIPE is enabled, it gets sent if the connection breaks and data is written to the socket. If SIGPIPE is ignored, an error is returned on the write instead. This attribute is valid only on sockets. By default, SIGPIPE is ignored in Tcl.

The NONBLOCK, NOBUF and LINEBUF ones are hanging around for compatibility with older scripts. The fconfigure command is the preferred method of getting and setting these attributes.

The APPEND and CLOEXEC options are not available on Windows.

  • flock options fileId ?start? ?length? ?origin? โ€” places a lock on all of a file, or part of it, as specified by fileId. The lock is either advisory or mandatory, depending on the mode bits of the file. The lock starts at relative byte offset start and covers length bytes. If start or length is omitted or empty, zero is assumed. If length is zero, then the lock always extends to the end of file โ€” even if the file grows. ๐ŸŒธ

Now for origin: "start" means the offset is relative to the beginning of the file. "current" means it's relative to the current access position in the file. "end" means it's relative to the end-of-file (a negative is before the EOF, positive is after). If origin is omitted, start is assumed.

These are the options it recognizes:

  • -read โ€” place a read lock on the file. Multiple processes may be accessing the file with read-locks. ๐Ÿซถ
  • -write โ€” place a write lock on the file. Only one process may be accessing a file if there's a write lock.
  • -nowait โ€” if specified, the process will not block when the lock can't be obtained. With this option, the command returns 1 if the lock is obtained and 0 if it isn't.
For the full deets on how file locking actually behaves, go read your system's fcntl system call documentation. And if you're locking ranges of a file, it's best to use unbuffered file access (see the fcntl command). ๐Ÿ”ฅ
The flock command is not available on Windows 95. It is available on Windows NT.

๐Ÿ“‚ the rest of the file commands, bestie

for_file var filename code

okay so this one is literally just a glow-up of a for-loop but for a file's contents ๐Ÿ’… For every single line in filename, it sets var to that line and runs code. that's it. that's the whole vibe.

and the break and continue commands work exactly like they do with foreach, no cap.

for example, this:

for_file line /etc/passwd {echo $line}

would echo all the lines in the password file. iconic behavior fr fr.

funlock fileId ?start? ?length? ?origin?

removes a lock from a file that you previously locked with the flock command ๐ŸŽ€ The arguments are the same as for flock, so go peek at that command for the deets.

funlock is not available on Windows 95. It is available on Windows NT.

fstat fileId ?item? | ?stat arrayvar?

get the tea โ˜• about an open file. status info, all of it.

these are the keys used to identify each data item:

  • atime โ€” the time of last access.
  • ctime โ€” the time of last file status change.
  • dev โ€” the device containing a directory for the file. this value uniquely identifies the file system that contains the file.
  • gid โ€” the group ID of the file's group.
  • ino โ€” the inode number. this field uniquely identifies the file in a given file system.
  • mode โ€” the mode of the file (see the mknod system call).
  • mtime โ€” time when the data in the file was last modified.
  • nlink โ€” the number of links to the file.
  • size โ€” the file size in bytes.
  • tty โ€” if the file is associated with a terminal, then 1, otherwise 0.
  • type โ€” the type of the file in symbolic form, which is one of these values: file, directory, characterSpecial, blockSpecial, fifo, link, or socket.
  • uid โ€” the user ID of the file's owner.

so if you pass one of those keys as item, you get that one data item back. just the one. minimal.

if you specify stat arrayvar, then all the info comes back in the array arrayvar, and each of the keys above indexes an element of that array. cute, right?

and if you only give fileId and nothing else? the command returns the data as a keyed list. slay.

these next two values are only returned if you explicitly ask for them by name โ€” they will not show up in the array form or the keyed list form. periodt.
  • remotehost โ€” if fileId is a TCP/IP socket connection, then a list is returned with the first element being the remote host IP address. if the remote host name can be found, it's returned as the second element of the list. the remote host IP port number is the third element.
  • localhost โ€” if fileId is a TCP/IP socket connection, then a list is returned with the first element being the local host IP address. if the local host name can be found, it's returned as the second element of the list. the local host IP port number is the third element.

ftruncate [-fileid] file newsize

chop a file down so it's at most newsize bytes long โœ‚๏ธ goodbye extra bytes.

if you pass the option -fileid, then file is an open file identifier โ€” otherwise it's a file path.

heads up bestie: this command is not available or not fully functional if the underlying operating system support isn't there. The command infox have_truncate will tell you if this command can truncate by file path. The command infox have_ftruncate will tell you if this command can truncate by file id. and the -fileid option is not available on Windows.

lgets fileId ?varName?

reads the next Tcl list from the file given by fileId and tosses the terminating newline character ๐Ÿ—‘๏ธ this is different from gets, which reads plain lines โ€” lgets reads Tcl lists instead. if the list contains newlines or binary data, then that newline or bytes of zero will be returned as part of the result. only a newline that is not quoted as part of the list actually marks the end of the list. there's no matching command for outputting lists, because puts already does that correctly. iykyk.

if varName is specified, the line gets placed in the variable with that name, and the return value is a count of the number of characters read (not counting the newline). if the end of the file is reached before reading any characters, then -1 is returned and varName is set to an empty string. and if varName is specified and an error occurs, whatever data was read will be returned in the variable โ€” but ngl the resulting string may not be a valid list.

if varName is not specified, then the return value will be the line (minus the newline character), or an empty string if the end of the file is reached before reading any characters. an empty string will also be returned if a line contains no characters except the newline, so you may have to use eof to figure out what actually happened. ๐Ÿ˜ญ

the lgets command may be used to read and write lists containing binary data, however translation must be set to lf or the data may be corrupted.

lgets is currently supported on non-blocking files.

pipe ?fileId_var_r fileId_var_w?

make a pipe ๐Ÿชˆ if fileId_var_r and fileId_var_r are specified, then pipe will set a variable named fileId_var_r to contain the fileId of the side of the pipe that was opened for reading, and fileId_var_w will contain the fileId of the side of the pipe that was opened for writing.

if the fileId variables are not specified, then a list containing the read and write fileIdw is returned as the result of the command.

read_file ?-nonewline? fileName

read_file fileName numBytes

this procedure reads the file fileName and returns the contents as a string ๐Ÿ“– if -nonewline is specified, then the last character of the file is discarded if it's a newline. the second form specifies exactly how many bytes will be read and returned โ€” unless there are fewer than numBytes bytes left in the file, in which case all the remaining bytes are returned.

select readfileIds ?writefileIds? ?exceptfileIds? ?timeout?

this command lets an Extended Tcl program wait on zero or more files being ready for reading, ready for writing, having an exceptional condition pending, or wait for a timeout period to expire ๐Ÿ‘‘

readFileIds, writeFileIds, and exceptFileIds are each lists of fileIds, as returned from open, to query. an empty list ({}) may be specified if a category isn't being used.

the files in the readFileIds list are checked to see if data is available for reading. the writeFileIds are checked to see if the specified files are clear for writing. the exceptFileIds are checked to see if an exceptional condition has occurred (typically, an error). the write and exception checking is most useful on devices, however the read checking is very useful when communicating with multiple processes through pipes. select considers data pending in the stdio input buffer for read files as being ready for reading โ€” the files do not have to be unbuffered. (yes, that sentence is a little chaotic, but it's the truth ๐Ÿ’€)

timeout is a floating point timeout value, in seconds. if an empty list is supplied (or the parameter is omitted), then no timeout is set. if the value is zero, then the select command acts as a poll of the files, returning immediately even if none are ready.

if the timeout period expires with none of the files becoming ready, then the command returns an empty list. otherwise the command returns a list of three elements, and each of those elements is a list of the fileIds that are ready in the read, write and exception classes. if none are ready in a class, then that element will be the null list. for example:

select {file3 file4 file5} {file6 file7} {} 10.5

could return

{file3 file4} {file6} {}

or perhaps

file3 {} {}
on Windows, only sockets can be used with the select command. Pipes, as returned by the open command, are not supported.

write_file fileName string ?string...?

this procedure writes the specified strings to the named file โœ๏ธ boom, done.


๐ŸŒ NETWORK PROGRAMMING SUPPORT ๐ŸŒ

TclX provides functionality to complement the Tcl socket command โœจ the host_info command is used to get information about a host by name or IP address. on top of that, the fstat and fcntl commands provide options for querying and controlling connected sockets. and to get the host name of the local system, use the id host command. ๐Ÿซถ

host_info option host

obtain information about an Internet host. the argument host can be either a host name or an IP address.

these subcommands are recognized:

  • addresses โ€” return the list of IP addresses for host.
  • official_name โ€” return the official name for host.
  • aliases โ€” return the list of aliases for host. (note that these are IP number aliases, not DNS CNAME aliases. see ifconfig(2).)

๐Ÿ” FILE SCANNING COMMANDS ๐Ÿ”

okay bestie, this is the part where Tcl basically becomes awk but make it fashion. These commands let you scan files, match lines against regular expressions, and run Tcl code whenever something hits. And because Tcl is all declarative and chill like that, some scripts that would have you crying in awk are lowkey easy here. ate. ๐Ÿ’…

Everything revolves around the โœจscan contextโœจ. A scan context is holding one or more match statements โ€” each one pairs a regex to look for with the Tcl code to fire off when it matches. iconic.

  • scancontext ?option? โ€” manages file scan contexts. A scan context is a lil collection of regular expressions plus the commands to run when one of those regexes matches a line of the file. A context can also have a single default match, which gets applied to any line that didn't match any of the regexes. You can define multiple scan contexts and reuse them across multiple files, no cap. Each scan context is identified by a context handle. The scancontext command takes these forms:
  • scancontext create โ€” makes a brand new scan context. You use the scanmatch command to define patterns inside it. It hands you back a contexthandle, which is what you use to refer to this new context in all your calls to the Tcl file scanning commands. ๐ŸŽ€
  • scancontext delete contexthandle โ€” deletes the scan context identified by contexthandle, and frees all the match statements and compiled regular expressions tied to that context. gone, reduced to atoms ๐Ÿ’€
  • scancontext copyfile contexthandle ?filehandle? โ€” sets or returns the file handle that unmatched lines get copied to (peep scanfile for the deets). If filehandle is omitted, it returns the copy file handle. If there's no copy file associated with the context, it returns {}. If you pass a file handle, that becomes the copy file for this context. And if filehandle is {}, it removes any copy file specification for the context. bye felicia ๐Ÿฆ‹
  • scanfile ?-copyfile copyFileId? contexthandle fileId โ€” scans the file given by fileId, starting from wherever the current file position is. It checks every pattern in the scan context named by contexthandle against it, and runs the match commands for whatever patterns matched.

If the optional -copyfile argument is there, the next argument is a file ID, and every line that isn't matched by any pattern (the default pattern does not count, bestie) gets written to it. If you specify the copy file with this flag instead of using the scancontext copyfile command, then the file gets disassociated from the scan context once the scan finishes.

๐Ÿšจ This command does not work on files containing binary data (bytes of zero). just... don't.
  • scanmatch ?-nocase? contexthandle ?regexp? commands โ€” specifies the Tcl commands to evaluate when regexp is matched by a scanfile command. The match gets added to the scan context named by contexthandle. You can add any number of match statements to a given context. Regexp is a regular expression (go look at the regexp command). If -nocase is the first argument, the pattern matches regardless of alphabetic case. ๐Ÿ’…

If regexp isn't specified, then you're setting a default match for the scan context. The default match fires when a line of the file doesn't match any of the regular expressions in the current scancontext.

The array matchInfo is available to the Tcl code that runs when an expression matches (or when the default does). It's got all the tea about the file being scanned and where in it the expression matched. ๐Ÿ“

matchInfo is local to the top level of the match command, unless it's declared global at that level with the Tcl global command. If you want to use it as a global, you must declare it global before scanfile is called โ€” because scanfile sets matchInfo before the match code runs, so a later global will override the local variable. awkward. ๐Ÿ™ˆ Here are the array entries you get:

  • matchInfo(line) โ€” the text of the line of the file that was matched.
  • matchInfo(offset) โ€” the byte offset into the file of the first character of the line that was matched.
  • matchInfo(linenum) โ€” the line number of the line that was matched. This is relative to the first line scanned, which is usually โ€” but not necessarily โ€” the first line of the file. The first line is line number one.
  • matchInfo(context) โ€” the context handle of the context this scan is associated with.
  • matchInfo(handle) โ€” the file id (handle) of the file currently being scanned.
  • matchInfo(copyHandle) โ€” the file id (handle) of the file specified by the -copyfile option. This element does not exist if -copyfile wasn't specified. ๐Ÿ™…
  • matchInfo(submatch0) โ€” holds the characters matching the first parenthesized subexpression. The second one lives in submatch1, and so on.
  • matchInfo(subindex0) โ€” holds a list of the starting and ending indices of the string matching the first parenthesized subexpression. The second one lives in subindex1, and so on.

All scanmatch patterns that match a line get processed in the order their specifications were added to the scan context. The rest of the scanmatch pattern-command pairs can be skipped for a file line if a continue is executed by the Tcl code of a preceding, matched pattern. โœจ

And if a return is executed inside the body of the match command, the scanfile command currently in progress returns, with the value passed to return as its return value. main character exit. ๐Ÿ‘‘


๐Ÿงฎ MATH COMMANDS ๐Ÿงฎ

ngl, several extended math commands make a whole bunch of extra math functions available in TclX. On top of that, there's a set of procedures that give you command access to the math functions supported by the expr command. it's giving calculator but cute. ๐Ÿ”ฅ

The following procedures give command interfaces to the expr math functions. They take the same arguments as the expr functions, and they can take expressions as arguments. periodt.

abs         acos        asin       atan2
atan        ceil        cos        cosh
double      exp         floor      fmod
hypot       int         log10      log
pow         round       sin        sinh
sqrt        tan         tanh
  • max num1 ?..numN?

expr max(num1, num2)

Returns the argument with the highest numeric value. Each argument can be any integer or floating point value. ๐Ÿ“ˆ

This functionality is also available as a math function max in the Tcl expr command.

  • min num1 ?..numN?

expr min(num1, num2)

Returns the argument with the lowest numeric value. Each argument can be any integer or floating point value. ๐Ÿ“‰

This functionality is also available as a math function min in the Tcl expr command.

  • random limit | seed ?seedval? โ€” generates a pseudorandom integer that's greater than or equal to zero and less than limit. If seed is specified, the command resets the random number generator to a starting point derived from seedval. This lets you reproduce pseudorandom number sequences for testing purposes โ€” so slay, deterministic chaos. ๐ŸŽฒ If seedval is omitted, then the seed gets set to a value based on the current system state and the current time, which gives you a reasonably interesting and ever-changing seed. ๐ŸŒˆ

โœจ LIST MANIPULATION COMMANDS โœจ

Extended Tcl said "let me give you MORE list toys" and honestly? iconic behavior. Here's the extra list manipulation commands and procedures you get on top of the standard ones. ๐Ÿ’–

  • intersect lista listb โ€” a procedure that hands you the logical intersection of two lists. The list it gives back is sorted. Slay.
  • intersect3 lista listb โ€” the โœจthree-wayโœจ version, bestie. It intersects two lists and returns a list containing three lists:
    1. everything in lista that wasn't in listb
    2. the intersection of the two lists
    3. all the elements that were in listb but weren't in lista

All the returned lists come back sorted.

  • lassign list var ?var...? โ€” assigns successive elements of a list into the variables you name. If you gave more variable names than there are fields, the leftover variables get set to the empty string. If there are more elements than variables, you get back a list of the unassigned elements. ๐Ÿซถ

Like, for example:

lassign {dave 100 200 {Dave Foo}} name uid gid longName

This assigns name to dave, uid to 100, gid to 200, and longName to Dave Foo. no cap.

  • lcontain list element โ€” vibe check: is element actually a list element of list? If yes, you get 1. If no, you get 0.
  • lempty list โ€” is this list empty or not? Empty โ†’ 1, not empty โ†’ 0. It's an alternative to comparing a list against an empty string, BUT it also catches a string of all whitespaces, because that counts as an empty list too. ๐Ÿ’…
  • lmatch ?mode? list pattern โ€” searches through the elements of list and returns a list of every element that matches pattern. If nothing matches, you get an empty list back, which is giving sad but correct.

The mode argument tells it how the elements should be matched against pattern, and it has to be one of these:

  • -exact โ€” the list element has to contain exactly the same string as pattern.
  • -glob โ€” pattern is a glob-style pattern, matched against each list element using the same rules as the string match command.
  • -regexp โ€” pattern gets treated as a regular expression and matched against each list element using the same rules as the regexp command.

If you leave mode out, it defaults to -glob.

Heads up bestie: only the -exact comparison will work on binary data. ๐Ÿšจ
  • lrmdups list โ€” procedure that removes duplicate elements from a list. The returned list is sorted. Duplicates? gone. not me deleting them ๐Ÿ’€
  • lvarcat var string ?string...? โ€” treats every string argument as a list and concatenates them all onto the end of whatever's already in var, forming a single list. The list gets stored back into var AND returned as the result. If var doesn't exist yet, it gets created. โœจ
  • lvarpop var ?indexExpr? ?string? โ€” pops (as in deletes) the element indexed by the expression indexExpr from the list living in the variable var. If index is omitted, then 0 is assumed. If string is specified, the deleted element gets replaced by string. Either way, the replaced-or-deleted element is what gets returned. So lvarpop argv 0 returns the first element of argv and sets argv to hold the rest of the string. main character energy honestly.

If the expression indexExpr starts with the string end, then end is replaced with the index of the last element in the list. And if the expression starts with len, then len is replaced with the length of the list.

  • lvarpush var string ?indexExpr? โ€” pushes (as in inserts) string as an element into the list living in the variable var. The element gets inserted before position indexExpr in the list. If index is omitted, then 0 is assumed. If var doesn't exist, it gets created.

Same deal with indexExpr: if it starts with the string end, then end is replaced with the index of the last element in the list; if it starts with len, then len is replaced with the length of the list.

Note that a value of end means insert the string before the last element. yes, that's the bit everyone gets wrong, you're welcome ๐ŸŽ€
  • union lista listb โ€” procedure that returns the logical union of the two specified lists. Any duplicate elements get removed. union slay. ๐Ÿ”ฅ

๐Ÿ”‘ KEYED LISTS ๐Ÿ”‘

Extended Tcl defines a special type of list called a keyed list. These give you a structured data type built on top of standard Tcl lists โ€” so basically the same energy as structs in the C programming language. C programmers could never make it this cute. ๐Ÿ’…

A keyed list is a list where each element contains a key and value pair. Those element pairs are stored as lists themselves: the key is the first element of the list, and the value is the second. These key-value pairs are called fields. Here's what one looks like:

{{NAME {Frank Zappa}} {JOB {musician and composer}}}

If the variable person contained the list above, then keylget person NAME would return {Frank Zappa}. And running this command:

keylset person ID 106

would make person contain

{{ID 106} {NAME {Frank Zappa}} {JOB {musician and composer}}

Fields can contain subfields, and . is the separator character. Subfields are really just fields where the value is another keyed list. So this following list has the top level fields ID and NAME, plus the subfields NAME.FIRST and NAME.LAST:

{ID 106} {NAME {{FIRST Frank} {LAST Zappa}}}

There's no limit to the recursive depth of subfields, so you can build up genuinely complex data structures. go off. ๐ŸŒˆ

Keyed lists get constructed and accessed through a bunch of commands. All of the keyed list management commands take the name of the variable containing the keyed list as an argument (so, passed by reference), rather than passing the list directly. iykyk.

  • keyldel listvar key โ€” deletes the field specified by key from the keyed list in the variable listvar. This removes both the key and the value from the keyed list. both. gone. ๐Ÿ’€
  • keylget listvar ?key? ?retvar | {}? โ€” returns the value associated with key from the keyed list in the variable listvar. If retvar isn't specified, the value comes back as the result of the command โ€” and in that case, if key isn't found in the list, you get an error. ๐Ÿ˜ญ

If retvar is specified and key is in the list, then the value is returned in the variable retvar and the command returns 1, meaning the key was present within the list. If key isn't in the list, the command returns 0, and retvar gets left unchanged. And if you specify {} for retvar, the value isn't returned at all โ€” which lets a Tcl programmer check whether a key is present in a keyed list without setting a variable as a side-effect. sneaky but valid ๐Ÿซถ

If key is omitted entirely, then you get back a list of all the keys in the keyed list.

  • keylkeys listvar ?key? โ€” returns a list of the keys in the keyed list in the variable listvar. If keys is specified, then it's the name of a key field whose subfield keys are to be retrieved. ๐ŸŽ€
  • keylset listvar key value ?key2 value2 ...? โ€” sets the value associated with key, in the keyed list contained in the variable listvar, to value. If listvar doesn't exist, it gets created. If key isn't currently in the list, it gets added. If it already exists, value replaces the existing value. You can specify multiple keywords and values if you want, because why not. ๐Ÿ’–

โœจ STRING AND CHARACTER MANIPULATION COMMANDS โœจ

Okay bestie, this whole squad is here to โœจelevateโœจ your string game โ€” classifying characters, flipping between chars and their numeric values, indexing into strings, getting lengths, pulling out ranges, duplicating strings, and transliterating (like the Unix tr program, but make it Tcl ๐Ÿ’…).


  • ccollate ?-local? string1 string2 โ€” compares two strings, queen vs queen. It returns -1 if string1 is less than string2, 0 if they're equal, and 1 if string1 is greater than string2.

If -local is specified, the strings get compared according to the collation environment of the current locale.

Heads up bestie: this command does not work with binary or UTF data. ๐Ÿšซ
  • cconcat ?string1? ?string2? ?...? โ€” concatenates the arguments and hands you back the resulting string. Normally the parser does string concatenation on its own, but every once in a while it's genuinely useful to have a command that returns a string โ€” usually when you need a command to evaluate. No separators get inserted between the strings, so they're just smooshed together, no cap. ๐Ÿซถ

This command is UTF-aware.

  • cequal string string โ€” compares two strings for equality and returns 1 if string1 and string2 are identical, 0 if they're not. It's basically a shortcut for string compare, and it dodges all those problems where string expressions get unintentionally treated as numbers. ๐Ÿ˜ญ

This command is UTF-aware and will also work on binary data. ๐Ÿ”ฅ

  • cindex string indexExpr โ€” returns the character indexed by the expression indexExpr (zero based) from string.

If indexExpr starts with the string end, then end gets replaced with the index of the last character in the string. If the expression starts with len, then len gets replaced with the length of the string. So flexible, we love her. ๐ŸŽ€

This command is UTF-aware.

  • clength string โ€” returns the length of string in characters. It's a shortcut for:
string length string

This command is UTF-aware.

  • crange string firstExpr lastExpr โ€” returns a range of characters from string, starting at the character indexed by firstExpr (zero-based) until the character indexed by lastExpr.

If firstExpr or lastExpr starts with the string end, then end gets replaced with the index of the last character in the string. If the expression starts with len, then len gets replaced with the length of the string.

This command is UTF-aware.

  • csubstr string firstExpr lengthExpr โ€” returns a range of characters from string, starting at the character indexed by firstExpr (zero-based) for lengthExpr characters.

If firstExpr or lengthExpr starts with the string end, then end gets replaced with the index of the last character in the string. If the expression starts with len, then len gets replaced with the length of the string.

This command is UTF-aware.

  • ctoken strvar separators โ€” parses a token out of a character string. The string to parse lives in the variable named strvar. The separators string contains all the valid separator characters for tokens in the string. All leading separators get skipped and the first token is returned. Then strvar gets modified to contain the remainder of the string following that token โ€” so it's lowkey mutating your variable, keep that in mind bestie. ๐Ÿ‘€
This command does not work with binary data.
  • ctype ?-failindex var? class string โ€” ctype figures out whether all characters in string are of the specified class. It returns 1 if they're all of class, and 0 if they're not, or if the string is empty. This command also gives you another method (besides format and scan) of converting between an ASCII character and its numeric value. The following ctype commands are available:
    • ctype ?-failindex var? alnum string โ€” tests that all characters are alphabetic or numeric characters as defined by the character set.
    • ctype ?-failindex var? alpha string โ€” tests that all characters are alphabetic characters as defined by the character set.
    • ctype ?-failindex var? ascii string โ€” tests that all characters are an ASCII character (a non-negative number less than 0200).
    • ctype char number โ€” converts the numeric value, string, to an ASCII character. Number must be in the range 0 through the maximum Unicode values.
    • ctype ?-failindex var? cntrl string โ€” tests that all characters are ``control characters'' as defined by the character set.
    • ctype ?-failindex var? digit string โ€” tests that all characters are valid decimal digits, i.e. 0 through 9.
    • ctype ?-failindex var? graph string โ€” tests that all characters within are any character for which ctype print is true, except for space characters.
    • ctype ?-failindex var? lower string โ€” tests that all characters are lowercase letters as defined by the character set.
    • ctype ord character โ€” converts a character into its decimal numeric value. The first character of the string gets converted to its numeric Unicode value.
    • ctype ?-failindex var? space string โ€” tests that all characters are either a space, horizontal-tab, carriage return, newline, vertical-tab, or form-feed.
    • ctype ?-failindex var? print string โ€” tests that all characters are a space or any character for which ctype alnum or ctype punct is true or other ``printing character'' as defined by the character set.
    • ctype ?-failindex var? punct string โ€” tests that all characters are made up of any of the characters other than the ones for which alnum, cntrl, or space is true.
    • ctype ?-failindex var? upper string โ€” tests that all characters are uppercase letters as defined by the character set.
    • ctype ?-failindex var? xdigit string โ€” tests that all characters are valid hexadecimal digits, that is 0 through 9, a through f or A through F.

If -failindex is specified, then the index into string of the first character that did not match the class gets returned in var. So you'll know exactly where it went wrong. ๐Ÿ’€

  • replicate string countExpr โ€” returns string, replicated the number of times indicated by the expression countExpr. Like copy-paste but โœจprogrammaticโœจ.

This command is UTF-aware and will work with binary data.

  • translit inrange outrange string โ€” translates characters in string, changing characters occurring in inrange to the corresponding character in outrange. Inrange and outrange may be a list of characters or a range in the form A-M. For example:
translit a-z A-Z foobar
Currently this command only supports characters in the ASCII range; UTF-8 characters out of this range will generate an error. ๐Ÿšจ

๐ŸŒธ XPG/3 MESSAGE CATALOG COMMANDS ๐ŸŒธ

okay bestie so these commands give you a Tcl interface to message catalogs that are compliant with the X/Open Portability Guide, Version 3 (XPG/3). it's giving internationalization, it's giving โœจglobal reachโœจ.

Tcl programmers can use message catalogs to create applications that are language-independent. through the use of message catalogs, prompts, messages, menus and so forth can exist for any number of languages, and they can be altered, and new languages added, without affecting any Tcl or C source code, which greatly eases the maintenance difficulties incurred by supporting multiple languages. no cap, this is the whole point.

A default text message is passed to the command that fetches entries from message catalogs. this lets the Tcl programmer create message catalogs containing messages in various languages, but still have a set of default messages available regardless of the presence of any message catalogs, and let the programs press on without difficulty when no catalogs are present. ๐Ÿ’…

So the normal approach to using message catalogs is to ignore errors on catopen, in which case catgets will return the default message that was specified in the call.

The Tcl message catalog commands normally ignore most errors. if it's desirable to detect errors, a special option is provided. this is normally used only during debugging, to insure that message catalogs are being used. if your Unix implementation does not have XPG/3 message catalog support, stubs will be compiled in that will create a version of catgets that always returns the default string. this allows for easy porting of software to environments that don't have support for message catalogs. ๐Ÿซถ

Message catalogs are global to the process โ€” an application with multiple Tcl interpreters within the same process may pass and share message catalog handles. iykyk.

  • catopen ?-fail | -nofail? catname โ€” open the message catalog catname. this may be a relative path name, in which case the NLSPATH environment variable is searched to find an absolute path to the message catalog. a handle in the form msgcatN is returned. normally, errors are ignored, and in the case of a failed call to catopen, a handle is returned to an unopened message catalog. (this handle may still be passed to catgets and catclose, causing catgets to simply return the default string, as described above.) if the -fail option is specified, an error is returned if the open fails. the option -nofail specifies the default behavior of not returning an error when catopen fails to open a specified message catalog. if the handle from a failed catopen is passed to catgets, the default string is returned.
  • catgets catHandle setnum msgnum defaultstr โ€” retrieve a message from a message catalog. CatHandle should be a Tcl message catalog handle that was returned by catopen. Setnum is the message set number, and msgnum is the message number. if the message catalog was not opened, or the message set or message number cannot be found, then the default string, defaultstr, is returned. ๐ŸŽ€
  • catclose ?-fail | -nofail? cathandle โ€” close the message catalog specified by cathandle. normally, errors are ignored. if -fail is specified, any errors closing the message catalog file are returned. the option -nofail specifies the default behavior of not returning an error. the use of -fail only makes sense if it was also specified in the call to catopen. ๐Ÿ’€
  • mainloop โ€” this procedure sets up a top-level event loop. events are processed until there are no more active event sources, at which time the process exits. it is used to build event oriented programs using the TclX shell in a style similar to that used with wish. if the global variable tcl_interactive exists and has a true value an interactive command handler is started as well. if the command handler is terminated by an EOF, the process will be exited. ๐Ÿ˜ญ

๐Ÿ” HELP FACILITY ๐Ÿ”

the help facility lets you look up help pages which were extracted from the standard Tcl manual pages and Tcl scripts during Tcl installation. help files are structured as a multilevel tree of subjects and help pages. help files are found by searching directories named help in the directories listed in the auto_path variable. all of the files in the list of help directories form a virtual root of the help tree. this method allows multiple applications to provide help trees without having the files reside in the same directory. so organized, so slay. ๐ŸŒˆ

The help facility can be accessed in two ways: as interactive commands in the Extended Tcl shell, or as an interactive Tk-based program (if you have built Extended Tcl with Tk). two vibes, one facility.

To run the Tk-based interactive help program:

tclhelp ?addpaths?

Where addpaths are additional paths to search for help directories. by default, only the auto_path used by tclhelp is searched. this will result in help on Tcl, Extended Tcl and Tk. ๐Ÿ‘‘

The following interactive Tcl commands and options are provided with the help package:

  • help โ€” help, without arguments, lists all of the help subjects and pages under the current help subject.
  • help subject โ€” displays all of the help pages and lower level subjects (if any exist) under the subject subject.
  • help subject/helppage โ€” display the specified help page. the help output is passed through a simple pager if output exceeds 23 lines, pausing waiting for a return to be entered. if any other character is entered, the output is terminated. โญ
  • helpcd ?subject? โ€” change the current subject, which is much like the Unix current directory. if subject is not specified, return to the top-level of the help tree. help subject path names may also include ``..'' elements. (yes bestie, you can go up a level, iconic behaviour.)
  • helppwd โ€” displays the current help subject. ๐Ÿ“
  • help help | ? โ€” displays help on the help facility at any directory level.
  • apropos pattern โ€” this command locates subjects by searching their one-line descriptions for a pattern. apropos is useful when you can remember part of the name or description of a command, and want to search through the one-line summaries for matching lines. full regular expressions may be specified (see the regexp command). ๐Ÿฆ‹

๐Ÿ“ฆ TCL LOADABLE LIBRARIES AND PACKAGES ๐Ÿ“ฆ

Extended Tcl supports standard Tcl tclIndex libraries and package libraries. a package library file can contain multiple independent Tcl packages. a package is a named collection of related Tcl procedures and initialization code. periodt.

The package library file is just a regular Unix text file, editable with your favorite text editor, containing packages of Tcl source code. the package library file name must have the suffix .tlib. an index file with the same prefix name and the suffix .tndx resides in the same directory as the .tlib file. the .tndx will be automatically created whenever it is out of date or missing (provided there is write access to the directory). ๐Ÿงš

The variable auto_path contains a list of directories that are searched for libraries. the first time an unknown command trap is taken, the indexes for the libraries are loaded into memory. if the auto_path variable is changed during execution of a program, it will be re-searched. only the first package of a given name found during the execution of a program is loaded. this can be overridden with the loadlibindex command.

The start of a package is delimited by:

#@package: package_name proc1 ?..procN?

These lines must start in column one. everything between the #@package: keyword and the next #@package: keyword or a #@packend keyword, or the end of the file, becomes part of the named package. the specified procedures, proc1..procN, are the entry points of the package. when a command named in a package specification is executed and detected as an unknown command, all code in the specified package will be sourced. this package should define all of the procedures named on the package line, define any support procedures required by the package and do any package-specific initialization. packages declarations maybe continued on subsequent lines using standard Tcl backslash line continuations. the #@packend keyword is useful to make sure only the minimum required section of code is sourced. thus for example a large comment block at the beginning of the next file won't be loaded. ๐Ÿ’…

Care should be taken in defining package_name, as the first package found in the path with a given name is loaded. this can be useful in developing new version of packages installed on the system.

For example, in a package source file, the presence of the following line:

#@package: directory_stack pushd popd dirs

says that the text lines following that line in the package file up to the next package line or the end of the file is a package named directory_stack and that an attempt to execute either pushd, popd or dirs when the routine is not already defined will cause the directory_stack portion of the package file to be loaded. ๐Ÿ”ฅ

๐Ÿ’– PACKAGE LIBRARY MANAGEMENT COMMANDS ๐Ÿ’–

Okay bestie, this section is all about building and managing package libraries. Several commands are available for building and managing package libraries. Commands that are extended versions of the standard Tcl library commands are listed here. All of the standard Tcl library management commands and variables are also supported.


โœจ auto_commands ?-loaders? โœจ

Lists the names of all known loadable procedures and commands procedures. If -loaders is specified, the command that will be executed to load the command will also be returned.

โœจ buildpackageindex libfilelist โœจ

Build index files for package libraries. The argument libfilelist is a list of package libraries. Each name must end with the suffix .tlib. A corresponding .tndx file will be built. The user must have write access to the directory containing each library.

Heads up, bestie: write access to the directory containing each library is required. No cap.

โœจ convert_lib tclIndex packagelib ?ignore? โœจ

Convert a Ousterhout style tclIndex index file and associate source files into a package library packagelib. If packagelib does not have a .tlib extension, one will be added. Any files specified in tclIndex that are in the list ignore will be skipped. Files listed in ignore should just be the base file names, not full paths.

โœจ loadlibindex libfile.tlib โœจ

Load the package library index of the library file libfile (which must have the suffix .tlib). Package library indexes along the auto_path are loaded automatically on the first demand_load; this command is provided to explicitly load libraries that are not in the path. If the index file (with a .tndx suffix) does not exists or is out of date, it will be rebuilt if the user has directory permissions to create it. If a package with the same name as a package in libfile.tlib has already been loaded, its definition will be overridden by the new package. However, if any procedure has actually been used from the previously defined package, the procedures from libfile.tlib will not be loaded.

โœจ auto_packages ?-location? โœจ

Returns a list of the names of all defined packages. If -location is specified, a list of pairs of package name and the .tlib path name, offset and length of the package within the library.

โœจ auto_load_file file โœจ

Source a file, as with the source command, except search auto_path for the file.

โœจ searchpath path file โœจ

Search all directories in the specified path, which is a Tcl list, for the specified file. Returns the full path name of the file, or an empty string if the requested file could not be found.


And that's the whole package-library management section, bestie. You're literally managing packages like a main character. ๐Ÿ’…

Signing off with footer energy: source/version is Tcl and TclX(3tclx), and the date is whatever that footer says โ€” we're not copy-pasting it, we're giving it a cute little shoutout instead. Byeee ๐Ÿ’–๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from