CRAN resubmission following the initial 1.0.0 submission (not published on CRAN).
NOT_CRAN=true retains the full seed and iteration counts.First stable release, prepared as the first CRAN submission. This section summarizes the pre-1.0 work. Stability classifications are defined in API stability.
The release candidate tag v1.0.0-rc1 points to
1846527d3968cdd12fa9900bbe80a9f2a89a1a3e, whose DESCRIPTION retains
Version: 0.9.0.9000. Changes since that tag are limited to documentation,
release metadata and the following:
DESCRIPTION gains URL and BugReports.animate() and run_worker() examples now run headlessly with
test_app() instead of being wrapped in \dontrun{}.table_source() pages feed DataTable's bounded viewport cache.
SQLite tables and views support delegated sorting/filtering; read-only
db_query_source() adds bounded query-result paging and driver callbacks.sql_editor() keeps materialized query results by default; lazy mode is
opt-in. db_explorer() uses lazy SQLite previews and query results,
portable metadata and an in-memory history. Database calls are synchronous.status_bar(), property_grid(), record_view(), data_profile(),
and json_view() for reactive status, record inspection, vector profiling,
and paged R-object trees. record_view() reuses the property-grid
renderer; json_view() reuses lazy TreeView nodes.data-workbench composition example. These workflow widgets add
no mandatory runtime dependency; optional JSON text parsing uses jsonlite
from Suggests.docs/ssh.md.vt100 as monochrome, and avoids enabling
SGR mouse or bracketed paste for legacy Linux/VT100 terminals.args still serialize. The regression passed
on Linux, macOS and Windows.ssh -t
smoke were manually reported PASS. macOS real terminal, tmux, screen and RStudio
Terminal remain NOT RUN. PTY CI is separate from manual console validation.jsonlite), explicit knitr/Quarto
output (knitr), and a single write_rendered() convenience function.snapshot_json() is now screen_snapshot_json() and inspect_json() is
now widget_snapshot_json(), matching screen_snapshot() and
widget_snapshot(). Both were new in 0.9; there are no aliases.
widget_snapshot() gains a root schema_version (1).db_table_source(own_connection = ) is now owned = , as in
db_connection(owned = ).register_layout() gains replace = FALSE; pass TRUE to replace a
registration on purpose, e.g. when a package registering in .onLoad()
is reloaded.datatable.source_error is posted once per failure rather than once per
failed page, and carries the root error message; source_stats() gains
fetch_errors. db_explorer() therefore shows one notification for one
broken connection.Terminal input validates UTF-8 bytes before locale conversion and retains incomplete characters across reads, including on R 4.1.
Workers inherit the parent's library search paths while keeping R_TESTS
disabled. Process exit drains output without an unbounded EOF wait,
cleans up descendants immediately, and reports process diagnostics on
unexpected exit or a Pilot timeout.
The db_explorer() documentation example now stops its app and closes
the owned SQLite connection.
db_table_source() works with current RSQLite (3.53 / DBI 1.3), which
rejects an empty parameter list; previously every unfiltered SQLite source,
and therefore the db_explorer() preview, failed at creation. It now also
accepts a db_connection() wrapper.
data_table() with a table source fetches one page per source call for all
columns instead of one call per painted column.
Moving a mounted widget with mount() keeps its bind_reactive() bindings,
widget timers and owned workers; only remove() ends them.
widget$on() also accepts the argument order of on() / app$on():
widget$on(type, selector, handler).
Password inputs no longer reveal their value through print(), the event
log, the debug overlay or inspect_widget(), and never copy it to a
clipboard.
Text and cells drop C1 control characters (U+0080-U+009F) as well as C0 controls, so untrusted text cannot emit 8-bit CSI/OSC sequences.
The key parser replaces bytes that are not UTF-8 instead of failing, and drops over-long escape sequences instead of buffering them without bound.
batch() and watch() restore the reactive graph after an interrupt; an
interrupted handler previously left every watcher deferred.
render_html(trim = TRUE) trims only the end of each row (inner spaces were
removed, shifting columns); SVG output preserves runs of spaces.
Large trees no longer trigger the "too many events in one tick" warning at start-up; the guard counts events added during a tick.
db_explorer(): the object filter is case-insensitive as documented, and
expanding a group after the connection closed no longer errors.
db_explorer() with lazy DBI metadata browsing, SQLite table/view
browsing and lazy table previews, integrated SQL execution and result
tables, details, status, and in-memory query history.db_metadata() as a small portable metadata interface. DBI and
RSQLite remain optional dependencies; SQL query results are materialized
and generic DBI query execution is synchronous.table_source() protocol and lazy SQLite table
source, with viewport-driven pages, delegated sorting/filtering, bounded
caching and source lifecycle methods.sql_highlighter() and the sql_editor() text-area subclass with
selection-aware synchronous query or execute mode and SQL result events.db_connection() wrapper and the
sql-workspace example. DBI and RSQLite are suggested dependencies only.The package was renamed from retui to termr during 0.3 development (no
compatibility aliases; options are termr.*, variables TERMR_*).
app$last_paint reports repainted
cells, rectangles and ANSI bytes.invalidate_paint(), paint_states).tools/bench/bench.R, compare.R) measuring batches of
ticks and the repainted area; see docs/performance.md.text_area(): multi-line editor with selection, undo/redo, find, wrapping,
line numbers, mouse and paste.split_pane() with a draggable / keyboard-movable divider.markdown_view(): headings, lists, quotes, code, tables and links.process_view(): a program's output with status, cancel and restart.command() model shared with the command
palette (categories, shortcuts, enabled state).button(on_press = ); label(), button(), progress_bar(), metric(),
sparkline() and key_value() accept reactive functions.data_table() 2.0: resizable (mouse and keyboard), hideable and frozen
columns, multi-column sort with markers, header_sort, search (Ctrl+F),
goto_row(), auto_size_column() that never scans huge tables, and
experimental cell editing on the table's own copy (editable, on_edit,
datatable.cell_changed). Numeric column headers are now right-aligned.signal(), computed(), watch(), batch(), peek(),
untracked(), dispose().terminal_capabilities()).PasteEvent, on_paste()), system clipboard writes via
OSC 52 (app$clipboard_write(), write-only).drag.start/move/end) and capture
(widget$capture_mouse()).on_stdout / on_stderr,
timeout, interrupt-then-kill cancellation, shell-free run_process().
The worker progress function is now termr_progress()."high-contrast" theme; monochrome rendering for NO_COLOR (reverse video,
bold/underline, heavier focus border) so state never depends on colour alone.app(reduce_motion = ), options(termr.reduce_motion),
TERMR_REDUCE_MOTION).test_app(color_mode = ); pilot methods paste(), drag(), focus(),
find(), wait_for(), run_worker(), system_clipboard().data-explorer, task-runner, terminal-dashboard, editor,
accessibility-demo. New guides: text area, reactivity, workers, terminal and
accessibility, performance.retui_progress() is termr_progress().datatable Enter on an editable table edits instead of sending
datatable.row_activated; filter() keeps an active sort.Ctrl+F, Ctrl+G, F1, F3 and Alt+Left/Right are bound in tables;
F1 is bound in every app.on_stdout).A large expansion from the 0.1.0 MVP towards a complete TUI framework, with a focus on data-oriented applications.
data_table(): virtualised, read-only data frame viewer (millions of
rows), row/cell/no cursor, row names, column() options, formatters,
zebra stripes, row_style / cell_style hooks, horizontal and vertical
scrolling, sort() / filter() views, mouse support and
datatable.* messages.browse_data() / data_browser(): an interactive data frame browser
(metrics, search, sorting, column summaries, row details).metric(), key_value(), sparkline(), progress_bar(), log_view().scroll_view() with scroll bars, keyboard and wheel scrolling, and
scroll-into-view on focus changes.tree_view() / tree_node() with lazy loading.tabs() / tab().checkbox(), radio_set() / radio_button(), dropdown(),
option_list(), spinner(), rule(), panel() (with border titles).input(): selection, word movement and deletion, app clipboard
(app$clipboard), validate = with input.valid / input.invalid and
the :invalid state.label(wrap = ) / style(wrap = "word" | "char"): text wrapping by
display width; "auto" heights follow wrapped text.grid_layout() with fixed/auto/fr/percent tracks, gaps and spans.app$push_screen(), pop_screen(), switch_screen()
with focus restore and screen.show / screen.hide events.modal(), confirm_dialog(),
alert_dialog().app$notify().app$add_command().:hover), focus on click, and
pilot$click() / hover() / scroll() for tests.app$run_worker(),
run_worker(), termr_progress(), worker.* events.animate() / widget$animate() with easings.inspect_widget(), app$log_events(), F12 debug
overlay (app(debug = TRUE)).stylesheet(), stylesheet_file(),
app(stylesheet = ) with specificity, source order and pseudo classes
(:focus, :hover, :disabled, :pressed, :invalid). Errors report
line, column and property.termr_theme() and app(theme = ) with default, dark and
light; colours can refer to the theme ("$primary").style(hover = ), grid properties, options(termr.ascii = TRUE).Ctrl+A in inputs now selects all (Home still moves to the start).on() selectors match the target of key and mouse events.tools/pty/pty-check.py).tools/bench/bench.R rendering benchmarks.label(), button(), input(), vertical(),
horizontal()), layout, reactive state, events and bindings, focus,
timers, framebuffer diff renderer, Windows/Unix/headless drivers and
test_app().