Teek API Documentation

Inherits: Object

Instance Methods

add_debug_console(keybinding '<F12>')

Enable the Tk debug console. The console starts hidden and can be toggled with the given keyboard shortcut (default: F12).

The Tk console is a built-in interactive Tcl shell — useful for inspecting variables, running Tcl commands, and debugging widget layouts at runtime. It is available on macOS and Windows only; on Linux this method is a no-op (Linux has the real terminal).

Parameters
  • keybinding String — Tk event to toggle the console (default: "")

Returns Boolean — true if the console was created, false if unavailable on this platform

Example
app = Teek::App.new
app.add_debug_console            # F12 toggles console
app.add_debug_console("<F11>")   # custom key

add_package_path(path)

Add a directory to Tcl’s package search path.

Parameters
  • path String — directory containing Tcl packages

Returns void

after(ms, on_error: :raise, &block)

Schedule a one-shot timer. Calls the block after ms milliseconds.

Parameters
  • ms Integer — delay in milliseconds
  • on_error :raise, Proc, nil — error handling strategy: - :raise (default) — exception propagates to Tcl background error handler. - Proc — called with the exception; error is swallowed. - nil — error is silently swallowed.

Returns String — timer ID, pass to #after_cancel to cancel

@yield block to call when the timer fires

after_cancel(after_id)

Cancel a pending #after or #after_idle timer.

Parameters

Returns void

after_idle(&block)

Schedule a block to run once when the event loop is idle.

Returns String — timer ID, pass to #after_cancel to cancel

@yield block to call when the event loop is idle

appearance

Get the macOS window appearance. No-op (returns nil) on non-macOS.

Returns String, nil — "aqua", "darkaqua", "auto", or nil on non-macOS

Example
app.appearance          # => "aqua", "darkaqua", or "auto"
app.appearance = :light # force light mode
app.appearance = :dark  # force dark mode
app.appearance = :auto  # follow system setting
See also

appearance=(mode)

Set the macOS window appearance. No-op on non-macOS.

Parameters
  • mode Symbol, String:light, :dark, :auto, or a raw Tk value

Returns void

bind(widget, event, *subs, &block)

bool_to_tcl(val)

Convert a Ruby boolean to a Tcl boolean string (“1” or “0”).

Parameters
  • val Boolean

Returns String — "1" or "0"

busy(window: '.')

Show a busy cursor on a window while executing a block. The cursor is restored even if the block raises.

Parameters
  • window String — Tk window path

Returns — the block's return value

@yield the work to perform while busy

choose_color(initial: nil, title: nil, parent: nil)

Show the native color picker dialog.

Parameters
  • initial String, nil — initial color (e.g. "#ff0000")
  • title String, nil — dialog window title
  • parent String, nil — parent window (defaults to the root window)

Returns String, nil — the chosen color as "#rrggbb", or nil if cancelled

choose_dir(initialdir: nil, mustexist: false, title: nil, parent: nil)

Show the native “choose directory” dialog.

Parameters
  • initialdir String, nil — directory the dialog starts in
  • mustexist Boolean — restrict the choice to an already-existing directory (Tk's own default is false, allowing a not-yet-created one)
  • title String, nil — dialog window title
  • parent String, nil — parent window (defaults to the root window)

Returns String, nil — the chosen directory path, or nil if cancelled

choose_open_file(filetypes: nil, initialdir: nil, initialfile: nil, title: nil, multiple: false, parent: nil)

Show the native “choose file to open” dialog.

Parameters
  • filetypes Array<Array>, nil — e.g. [["PNG Images", ".png"], ["All Files", "*"]] - the second element of each pair can also be an array of extensions (["Images", [".png", ".jpg"]])
  • initialdir String, nil — directory the dialog starts in
  • initialfile String, nil — filename pre-filled in the dialog
  • title String, nil — dialog window title
  • multiple Boolean — allow selecting more than one file
  • parent String, nil — parent window (defaults to the root window)

Returns String, Array<String>, nil — the chosen path (an array of paths if multiple:), or nil if the dialog was cancelled

choose_save_file(filetypes: nil, initialdir: nil, initialfile: nil, title: nil, defaultextension: nil, confirmoverwrite: true, parent: nil)

Show the native “choose file to save” dialog.

Parameters
  • filetypes Array<Array>, nil — see #choose_open_file
  • initialdir String, nil — directory the dialog starts in
  • initialfile String, nil — filename pre-filled in the dialog
  • title String, nil — dialog window title
  • defaultextension String, nil — extension appended if the typed filename doesn't already have one
  • confirmoverwrite Boolean — ask before overwriting an existing file (Tk's own default is true; pass false to skip the confirmation)
  • parent String, nil — parent window (defaults to the root window)

Returns String, nil — the chosen path, or nil if cancelled

command(cmd, *args, **kwargs)

Build and evaluate a Tcl command from Ruby values. Positional args are converted: Symbols pass bare, Procs become callbacks, everything else is brace-quoted. Keyword args become -key value option pairs.

Any Proc-valued arg or kwarg is tracked and released on overwrite, explicit removal, or the owning widget’s destruction - there is no unsafe way to attach a callback through this method, regardless of whether the call happens to match a registered per-widget-type interceptor (see CommandInterceptors) or falls through to the generic default. Widget type is inferred automatically from calls shaped like widget creation (a WIDGET_COMMANDS name as cmd, the new path as the first positional arg) - not tied to track_widgets.

Parameters
  • cmd Symbol, String — the Tcl command name
  • args — positional arguments
  • kwargs — keyword arguments mapped to -key value pairs

Returns String — the Tcl result

@raise AmbiguousCommandError if more than one registered interceptor claims the same call - see CommandInterceptors

Example
app.command(:pack, '.btn', side: :left, padx: 10)
# evaluates: pack .btn -side left -padx {10}

create_widget(type, path nil, parent: nil, idempotent: false, **kwargs)

Create a Tk widget and return a Widget wrapper.

Auto-generates a unique path if none is given. The path is derived from the widget type and a monotonic counter.

Parameters
  • type String, Symbol — Tk widget command (e.g. 'ttk::button', :canvas)
  • path String, nil — explicit Tk path, or nil for auto-naming
  • parent Widget, String, nil — parent widget for path nesting
  • idempotent Boolean — skip the creation command if a widget already exists at path - for widgets meant to be fetched by a stable, caller-chosen path and reused across many calls (see #menu) rather than freshly created each time
  • kwargs — keyword arguments passed to the Tk widget command

Returns Widget — the created widget

Examples
# Auto-named
btn = app.create_widget('ttk::button', text: 'Click')
# btn.path => ".ttkbtn1"
# Explicit path
frm = app.create_widget('ttk::frame', '.myframe')
# Nested under a parent
frm = app.create_widget('ttk::frame')
btn = app.create_widget('ttk::button', parent: frm, text: 'Click')
# btn.path => ".ttkfrm1.ttkbtn1"

dark?

Returns true if the window is currently displayed in dark mode. Always returns false on non-macOS.

Returns Boolean

destroy(widget '.')

Destroy a widget and all its children.

Parameters
  • widget String — Tk widget path (e.g. ".frame1")

Returns void

@raise ArgumentError

ensure_tcl_helper(name)

Evaluate script once per App instance under name, skipping it on later calls. Meant for widget-behavior modules that need to define a Tcl-side helper proc (e.g. a scan routine) without re-sending and re-parsing that definition on every call.

Parameters
  • name Symbol — unique name for this helper

Returns void

@yieldreturn String the Tcl script to evaluate the first time

every(ms, on_error: :raise, &block)

Schedule a repeating timer. Calls the block every ms milliseconds until cancelled. The block runs on the main thread in the event loop, so it must be fast (don’t block the UI).

Parameters
  • ms Integer — interval in milliseconds
  • on_error :raise, Proc, nil — error handling strategy: - :raise (default) — cancels the timer and raises the exception from the next call to #update. - Proc — called with the exception; timer keeps running. - nil — cancels the timer silently; error stored in RepeatingTimer#last_error.

Returns RepeatingTimer — cancel handle

@yield block to call on each tick

Examples
# Basic polling loop
timer = app.every(50) { update_display }
timer.cancel  # stop later
# With error handler (timer keeps running)
timer = app.every(100, on_error: ->(e) { log(e) }) { risky_work }
# Silent cancel on error
timer = app.every(50, on_error: nil) { maybe_fails }
timer.last_error  # => check later

font_metrics(font)

Get font metrics (ascent, descent, linespace) for a given font. Uses Tk’s C font API directly.

Parameters
  • font String — font description (e.g. "Helvetica 12", "TkDefaultFont")

Returns Hash{Symbol => Integer}:ascent, :descent, :linespace

@raise Teek::TclError if the font is not found

get_variable(name)

Get a Tcl variable’s value.

Parameters
  • name String — variable name (array-element and namespaced forms work)

Returns String — the value

@raise Teek::TclError if the variable doesn't exist

grab_release(window: '.')

Release a grab previously set with #grab_set. See Window#grab_release.

Parameters
  • window String, Widget — (default: the root window)

Returns void

@note Prefer app.window(window).grab_release for new code - this flat method is kept for compatibility and just delegates there.

grab_set(window: '.', global: false)

Set the input grab on window. See Window#grab_set.

Parameters
  • window String, Widget — (default: the root window)
  • global Boolean

Returns void

@note Prefer app.window(window).grab_set for new code - this flat method is kept for compatibility and just delegates there.

hide(window '.')

Hide a window without destroying it. Defaults to the root window (“.”).

Parameters
  • window String — Tk window path

Returns void

See also

initialize(title: nil, track_widgets: true, debug: false, &block)

Returns App — a new instance of App

mainloop

Enter the Tk event loop. Blocks until the application exits.

Returns void

make_list(*args)

Build a properly-escaped Tcl list from Ruby strings.

Parameters
  • args Array<String> — elements to join

Returns String — a Tcl-formatted list

measure_chars(font, text, max_pixels, **opts)

Measure how many bytes of text fit within a pixel width limit. Useful for text truncation, ellipsis, and line wrapping.

Parameters
  • font String — font description (e.g. "Helvetica 12")
  • text String — text to measure
  • max_pixels Integer — maximum pixel width (-1 for unlimited)
  • opts Hash — options

Returns Hash{Symbol => Integer}:bytes and :width

Options
  • :partial_ok Boolean — allow partial character at boundary
  • :whole_words Boolean — break only at word boundaries
  • :at_least_one Boolean — always return at least one character

@raise Teek::TclError if the font is not found

menu(path, **kwargs)

Wrap a Tk menu at the given path, creating it (tearoff disabled) if it doesn’t exist yet. Safe to call repeatedly with the same path - it’s a flyweight, not a handle you need to hold onto: call this again any time you’re about to rebuild the menu (e.g. on every right-click).

Parameters
  • path String — Tk menu path (e.g. ".card.ctx")
  • kwargs — extra options for the underlying `menu` command, used only the first time this path is created

Returns Widget

message_box(message:, title: nil, detail: nil, icon: :info, type: :ok, default: nil, parent: nil)

Show a message box with one or more buttons.

Parameters
  • message String — the main message text
  • title String, nil — dialog window title
  • detail String, nil — additional explanatory text, shown smaller below message
  • icon :error, :info, :question, :warning — icon to display
  • type :ok, :okcancel, :abortretryignore, :yesno, :yesnocancel, :retrycancel — which button(s) to show
  • default Symbol, nil — which button is focused by default (e.g. :cancel); defaults to Tk's own choice if omitted
  • parent String, nil — parent window (defaults to the root window)

Returns Symbol — the pressed button - :ok, :cancel, :yes, :no, :abort, :retry, or :ignore

modal(window: '.', global: false, &block)

Make window modal. See Window#modal.

Parameters
  • window String, Widget — (default: the root window)
  • global Boolean — see #grab_set

Returns void

@note Prefer app.window(window).modal <code></code> for new code - this flat method is kept for compatibility and just delegates there.

@yield optional - runs with the grab and focus already set

on_close(window: '.', &block)

Register a handler for the window manager’s close button (WM_DELETE_WINDOW - the titlebar close box, Cmd-W, Alt-F4, etc., depending on platform).

Tk’s own default behavior (destroy the window) only applies when nothing else has claimed this protocol - setting a handler here replaces it, so the block is entirely responsible for deciding whether the window actually closes. Call #destroy yourself if you want it to; do nothing (or show a confirmation first) if you don’t.

Parameters
  • window String — Tk window path (default: the root window)

Returns void

@note Prefer app.window(window).on_close <code></code> for new code - this flat method is kept for compatibility and just delegates there.

@yield called when the window's close button is pressed

Examples
# Confirm before quitting
app.on_close { app.destroy('.') if app.message_box(message: 'Quit?', type: :yesno) == :yes }
# A toplevel that just hides instead of closing
app.on_close(window: settings_window) { app.tcl_eval("wm withdraw #{settings_window}") }
See also

package_names

List all packages known to this interpreter. Scans auto_path for package indexes before querying.

Returns Array<String>

package_present?(name)

Check if a package is already loaded in this interpreter.

Parameters
  • name String — package name

Returns Boolean

package_versions(name)

List available versions of a package. Scans auto_path for package indexes before querying.

Parameters
  • name String — package name

Returns Array<String>

popup_menu(menu, x:, y:, entry: nil)

Pop up a menu at the given screen coordinates.

Parameters
  • menu Widget, String — the menu to pop up
  • x Integer — screen x coordinate
  • y Integer — screen y coordinate
  • entry Integer, String, nil — index or label of the entry to show as active

Returns void

raw_command(cmd, *args, **kwargs)

The dumb Tcl builder underneath #command - no interceptor lookup, no per-widget-type awareness. Used internally by interceptors (to actually perform their Tcl work without re-entering dispatch) and by #command’s own generic fallback. Any Proc here still gets registered as a real, working callback (positional: bind-shaped, relay_break_continue: true; kwarg, via #tcl_arg_value: option-shaped, relay_break_continue: false) - it just isn’t tracked for release. Prefer #command; call this directly only from within an interceptor.

Built as a plain argv array passed to Interp#tcl_invoke (Tcl_EvalObjv) rather than a joined string handed to tcl_eval, so no value needs escaping - unbalanced braces, $, [, newlines, whatever, all pass through verbatim. There is nothing here for a value to “break out” of.

Returns String — the Tcl result

record_widget_type(cmd, args)

Records that args[0] is a widget of type cmd, if this call looks like widget creation (cmd is a known WIDGET_COMMANDS entry). Not tied to track_widgets - this is what lets #command look up a registered interceptor for a bare path string on any later call, regardless of how the widget was created.

Returns void

register_callback(callable, relay_break_continue: true)

Register a Ruby callable as a Tcl callback. The callable can use throw for Tcl control flow: throw :teek_break - stop event propagation (like Tcl “break”) throw :teek_continue - Tcl TCL_CONTINUE throw :teek_return - Tcl TCL_RETURN

:teek_break/:teek_continue only mean something when Tcl actually dispatches the result through a context that knows how to handle TCL_BREAK/TCL_CONTINUE - Tk’s bind mechanism does; a plain script invocation (a menu entry’s or widget’s -command) does not, and returning either code there is a Tcl error (“invoked break/continue outside of a loop”), not a no-op. relay_break_continue: false is for exactly those non-bind callers: throw is still caught (so it can’t crash as an uncaught throw), but is treated as the callback simply finishing, instead of being relayed to Tcl. :teek_return is always relayed either way - TCL_RETURN is safe in any context.

Parameters
  • callable #call — a Proc or lambda to invoke from Tcl
  • relay_break_continue Boolean — whether a caught :teek_break/ :teek_continue is relayed to Tcl as TCL_BREAK/TCL_CONTINUE (true, for bind-dispatched callbacks) or silently absorbed (false, for callbacks invoked as a plain script - menu/widget -command options)

Returns Integer — callback ID, usable as ruby_callback <id> in Tcl

register_drop_target(widget)

Register a widget as a file drop target. After registration, dropping files onto the widget generates a single <<DropFile>> virtual event with all file paths as a Tcl list in the event data. Use #split_list to convert to a Ruby array.

Parameters
  • widget String — Tk widget path (e.g., ".", ".frame")

Returns void

Example
app.register_drop_target('.')
app.bind('.', '<<DropFile>>', :data) do |data|
  paths = app.split_list(data)
  puts "Dropped #{paths.length} file(s): #{paths.inspect}"
end

require_package(name, version nil)

Load a Tcl package into this interpreter.

Parameters
  • name String — package name (e.g. "BWidget")
  • version String, nil — minimum version constraint

Returns String — the version that was loaded

@raise Teek::TclError if the package is not found

set_variable(name, value)

Set a Tcl variable. Useful for widget textvariable and variable options. Goes through Tcl_SetVar directly (no re-parsing), so the value never needs escaping - braces, backslashes, $, [, whatever, all safe.

Parameters
  • name String — variable name (array-element and namespaced forms work)
  • value String — value to set

Returns String — the value

set_window_geometry(geometry, window: '.')

Set a window’s geometry (e.g. “400x300”, “400x30010050”).

Parameters
  • geometry String — geometry string
  • window String — Tk window path

Returns String — the geometry

set_window_resizable(width, height, window: '.')

Set whether a window is resizable.

Parameters
  • width Boolean — allow horizontal resize
  • height Boolean — allow vertical resize
  • window String — Tk window path

Returns void

set_window_title(title, window: '.')

Set a window’s title.

Parameters
  • title String — new title
  • window String — Tk window path

Returns String — the title

See also

show(window '.')

Show a window. Defaults to the root window (“.”).

Parameters
  • window String — Tk window path

Returns void

See also

split_list(str)

Split a Tcl list string into a Ruby array of strings.

Parameters
  • str String — a Tcl-formatted list

Returns Array<String>

tcl_eval(script)

Evaluate a raw Tcl script string and return the result. Prefer #command for building commands from Ruby values; use this when you need Tcl-level features like variable substitution or inline expressions that #command can’t express.

Parameters
  • script String — Tcl code to evaluate

Returns String — the Tcl result

@note Any callback embedded in script (e.g. a hand-built ruby_callback <id>) is on you to register and release - none of #command's tracking applies here. Creating a widget this way (instead of via #command/#create_widget/#menu) also means its type is never recorded, so a registered CommandInterceptors entry won't engage for it even on later, ordinary #command calls - create widgets through those methods and reach for tcl_eval for everything else.

tcl_invoke(*args)

Invoke a Tcl command with pre-split arguments (no Tcl parsing). Safer than #tcl_eval when arguments may contain special characters.

Parameters
  • args Array<String> — command name followed by arguments

Returns String — the Tcl result

tcl_to_bool(str)

Convert a Tcl boolean string (“0”, “1”, “yes”, “no”, etc.) to Ruby boolean.

Parameters
  • str String — a Tcl boolean value

Returns Boolean

text_width(font, text)

Measure the pixel width of a text string in a given font. Uses Tk’s C font API directly — faster than the Tcl font measure command.

Parameters
  • font String — font description (e.g. "Helvetica 12", "TkDefaultFont")
  • text String — text to measure

Returns Integer — pixel width

@raise Teek::TclError if the font is not found

track_widget_option_callbacks(cmd, args, kwargs)

#command’s fallback for any call that no registered interceptor claimed: registers any Proc-valued kwarg (e.g. command:, validatecommand:) as a callback tracked under cmd, releasing it if reconfigured or when the widget is destroyed. A widget’s own options are never silently renumbered or invalidated out from under us the way menu entries are, so this uses a cheap in-memory CallbackRegistry#reconcile rather than a live-scan one.

Tracked under the widget’s own path, by [*context, key], where context is args normalized to strings - except a bare configure (or widget creation - the container is the new widget’s path, not the cmd used to create it) normalizes to an empty context, since all three address the same underlying option namespace and must replace each other. Any other subcommand (e.g. a treeview’s heading col) keeps its own args as part of the key, so two different targets sharing an option name (two columns both using command:) don’t collide.

Returns Hashkwargs with any Proc values swapped for the Tcl script #raw_command embeds

unbind(widget, event)

Remove an event binding previously set with #bind.

Parameters
  • widget String — Tk widget path or class tag
  • event String — Tk event name, with or without angle brackets

Returns void

See also

unregister_callback(id)

Remove a previously registered callback by its ID.

Parameters

Returns void

update

Process all pending events and idle callbacks, then return.

Returns void

update_idletasks

Process only pending idle callbacks (e.g. geometry redraws), then return.

Returns void

window(path '.')

A single toplevel window, addressed by path - groups wm subcommands and composite window-lifecycle behaviors (#on_close, #grab_set/ #grab_release, #modal) into one object instead of threading window: through a pile of unrelated flat methods. This app’s own window_title/set_window_title/etc., #wm, #on_close, #grab_set, #grab_release, and #modal all delegate here internally - use whichever reads better to you, they’re the same underlying calls.

Parameters
  • path String, Widget — (default: the root window)

Returns Window

window_geometry(window: '.')

Get a window’s current geometry.

Parameters
  • window String — Tk window path

Returns String — geometry string (e.g. "400x30000")

See also

window_resizable(window: '.')

Get whether a window is resizable.

Parameters
  • window String — Tk window path

Returns Array(Boolean, Boolean) — [width_resizable, height_resizable]

See also

window_title(window: '.')

Get a window’s current title.

Parameters
  • window String — Tk window path

Returns String — current title

See also
Attributes

_pending_exception= [W]

@api private

callback_registry [R]

Returns the value of attribute callback_registry.

clipboard [R]

Returns the value of attribute clipboard.

debugger [R]

Returns the value of attribute debugger.

interp [R]

Returns the value of attribute interp.

widgets [R]

Returns the value of attribute widgets.

winfo [R]

Returns the value of attribute winfo.

wm [R]

Returns the value of attribute wm.