Skip to content

Releases: ofamtools/ochazuke

v0.82.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 01 Nov 09:49
  • Fixed: editing a long Markdown document no longer pegs the CPU. Glamour draws the document in runs of top-level blocks, each cached, so an edit redraws only the run it touched (output byte-identical); Tasks and Elements no longer copy the source per item. 10 edits on a 3,000-line doc: 3.0 s → 0.8 s CPU.
  • Added markdown.wrap, default true: the Markdown block editor soft-wraps a long line at the last space that fits as you type (a word wider than the pane breaks at the edge), a list item's next rows under its text; the source gets no line breaks. false keeps the sideways scroll.
  • Added Input.Wrap and Input.WrapIndent (soft wrap in InputBlock, off by default) and InputRows(in, width).

v0.17.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 13:57
  • Framework namespace is ochazuke: framework nouns are ochazuke.settings, ochazuke.page, ochazuke.state and so on. In v0.16.0 they were app.<noun>, which collided with the app noun's own verbs (app.state). The short names stay as aliases, and app.<framework noun> is accepted silently for one release. Exported noun constants changed value.
  • cli.ExtensionNamespace(bin): strips a leading o- and refuses reserved names (o-ai → ai, o-qbt → qbt). Hosts use it with cli.Namespace.
  • Catalog fix: cli.Catalog lists each noun once, sorted by name. It used to split one noun into several entries.
  • Card timeline: AddTimeline draws boxed cards with wrapped headers (no …), lazily drawn bodies with foldable sections, Active (bold, ●) and Muted cards, group rules, and follow-tail scrolling.

v0.16.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 13:05
  • Noun namespaces:
    • Framework nouns are now app.<noun> (app.settings, app.config, …), and their short names stay as aliases.
    • Define extends a framework noun with the same short name; DefineOwn(name) lets an app claim the short name instead.
    • Dotted nouns split on the last dot (SplitKey); a verb can't contain a dot.
    • The CLI takes nested, dotted and alias spellings (bin app settings list, bin app.settings list, bin settings list).
    • Extension hosts namespace extension nouns with cli.Namespace(ext). The catalog publishes aliases.
  • Compatibility: Runtime.Nouns and Runtime.Operations are keyed by canonical names, so look framework nouns up through Noun()/Operation(). Several exported noun constants changed value.
  • State explorer: ochazuke/explore presses keys through any app built headless with fakes, and checks invariants in every state:
    • no panic, focus and modal rules, honest hints, no traps, render fits, jobs settle.
    • Findings come with shrunk key paths, as gap stories or Go tests.
    • Entry points: explore.Run, Survey, Reproduce; o-story explore; make explore.

v0.15.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 11:32
  • config.reload: reads themes.json, settings.json, actions.json and bindings.json again, in dependency order, then each app hook (Runtime.OnConfigReload(name, fn)). Problems are reported per file and stale notices withdrawn.
  • Noun places: each instance's noun, ancestor-noun chain, page and modal are recorded and persisted per app in noun-places.json. Read them with nouns places, nouns list and Runtime.NounPlaces.
  • ? help views: S cycles here → pick → table. Pick shows a noun and mode you choose (n, m); table shows keys by mode. Both resolve at a recorded place (p), defaulting to where ? was opened. Settings help.pick-view, help.table-view and help.pending-modes.
  • ctrl+\\ opens the help from any insert mode.
  • Bindings export: rows print as mode, noun, request (verb first), keys. bindings list --all and bindings.reference.json are sorted the same way.

v0.14.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 07:17
  • Modals: about 80% of the terminal width with no 78-column cap; a chooser fills the modal width and no longer resizes while typing (story chooser/wide-fills).
  • Terminal overlays: Terminal.SetOverlay(*TerminalOverlay{Dim, Marks}) draws over a live pane without touching its frame or stream. With an app passthrough mode entered from the leader, this gives tuios-style hints (stories terminal/hints-*).
  • Keys: the key classes upper and ctrl+alpha, and the argument source letter.
  • Palette: Parameter.Noun lists that noun's things as the parameter's choices.

v0.13.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 03:30

Table cell mode is opt-in: CellSelect(); every other table selects rows as before v0.12.0.

Table cell mode is opt-in: only a table added with CellSelect() is cell-based.

Tables

  • CellSelect() (an InstanceOption for AddList) makes a table cell-based: the current column, h/l, 0/^/home, $/end, N|, g c, y (copy the cell) and z >/z </z =, with the column and widths remembered in tables.json, as v0.12.0 gave every table. AddTree ignores it.
  • Every other table selects rows again, as on v0.11.0: h/l are free for row nouns, $, ^ and 0 (without a count) run list.scroll-columns (verb guard table-scrolls), z l/z h scroll a column, no current cell is drawn, and nothing is read from or written to tables.json for it (widths a v0.12.0 cell table saved no longer stick to it). Story tables/row-select.
  • RowSelect() is a deprecated no-op; the framework's trees, ? help modal and Settings page no longer pass it.
  • Y (copy the row's cells joined by tabs) answers on every table (verb guard list-table), y only on a cell-mode table.
  • V answers on every table with marks: a visual range over the marks, cell-mode or not. esc ends it through list.end-visual (verb and row guard list-visual), so the row no longer hides an outer esc hint, such as a modal's esc modal.pop, over a table.
  • The width keys z >/z </z = need a current column, so they answer on cell-mode tables only; List.SetColumnWidth still sets a width on any table.
  • list.column, list.choose-column and list.resize-column refuse a row-select table ("not a cell table"); list.yank {what: cell} too.
  • cli: catalog tables select rows, so the groups rail's h back row (guard list-first-column) answers at once on them. Story catalog/groups-table-h.

o-story

  • A story list takes cellSelect (ListSpec.CellSelect); the cell stories set it, and the goldens of tables that select rows read R| again.

v0.12.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 03:10

Tables are cell-based: a current column, per-column widths, and V for rows.

Tables are cell-based, like o-csv's grid: a current column, column widths, and a visual row selection.

Tables

  • A list with columns has a current column (List.Column, SetColumn; column in its state). On the list noun in normal mode, on a cell-mode table only: h/l/left/right move by column (counts), 0/^/home and $/end go to the first and last, N| to column N, g c chooses one from a chooser of the titles (list.column, list.choose-column, motions); j/k keep the column. Every frame scrolls the column offset as little as shows the current column; z l/z h carry it along. $, ^ and 0 no longer run list.scroll-columns; list.column scrolls a row-select table the same way. Stories tables/cell-motion, tables/column-count.
  • The current cell is drawn reverse and underlined inside the row's highlight, the header underlines the current column's title, and an unfocused table fades both. Story tables/unfocused-cell-dimmed.
  • y and Y copy the current cell, or the row's cells joined by tabs, into the registers (list.yank {what, register}).
  • z >/z < widen or narrow the current column by ColumnWidthStep (2) cells, never below 3; z = makes every column automatic (list.resize-column, list.reset-columns; List.SetColumnWidth, ColumnWidths, ResetColumnWidths). The widths and the current column are remembered per table id in the state directory's tables.json (Runtime.TableState, SetTableState). Story tables/column-resize.
  • V starts a visual row selection drawn into the marks: j/k extend it (they clamp), a row's application verb runs for every selected row through list.apply, esc or V ends it and the marks go back (list.visual, List.Visual, StartVisual, EndVisual). Story tables/visual-apply.
  • list.apply takes args for every row's request, and a verb with a confirm asks once for all the rows.
  • RowSelect() keeps a table on row selection: trees' lists (h/l expand and collapse), the ? help modal and the Settings page use it.
  • y, Y, V and the width keys are hidden from the footer; ? help lists them.
  • cli: the groups rail's h/left back rows take the new guard list-first-column, so in a table h moves left and goes back to the rail from the first column. Story catalog/groups-table-h.

grid

  • Per-column widths: z >/z </z = on the grid noun (grid.resize-column, grid.reset-columns; Grid.SetColumnWidth, ColumnWidth, ColumnWidths, ResetColumnWidths). A given width replaces MaxCellWidth for its column and is remembered under the grid's id.

o-story

  • Goldens read C| (c| dimmed) for a highlighted row that holds a table's current cell; the expect field cell names the current cell's text.

v0.11.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 02:28

The terminal leader can wait for the next key indefinitely.

  • terminal-leader-timeout (TerminalLeaderTimeoutSetting, duration): how long leader_pending waits for the next key before it sends the leader alone. 0 never expires, so the leader waits like tmux's prefix; a positive value is the leader's own timeout. EnsureTerminalLeader declares it beside terminal-leader unless the app declared it first (with its own default); the framework default is DefaultBindingTimeout, and until settings.json holds a value the leader follows BindingTimeout. Other key sequences keep BindingTimeout. Story terminal/leader-timeout-zero-waits.

v0.10.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 27 Oct 01:18

An unfocused list keeps its selected row, faded; the dims are settings. A list can clear its filter when enter picks a row.

Unfocused lists and dims

  • A page list without the focus keeps its selected row in reverse video and is drawn faded as a whole, so the row an unfocused list is on (a tree beside a live terminal) stays visible and the focused row is the one highlight at full strength. A list in a modal stays plain until focused; a tree editing a line is not faded. Replaces the old rule "an unfocused list draws every row plain" (UX rule R5.1). Stories lists/unfocused-dimmed, lists/beside-terminal-keeps-row.
  • Two framework settings, declared by EnsureConfigSettings: dim-unfocused (percent an unfocused list fades toward the background, default 20) and modal-dim (the page behind a modal, default 35, the backdrop's look until now). Both 0 to 90 (MaxDim); 0 is off.
  • Styles.Fade(percent) blends the scheme's text colour toward its surface (lipgloss.Blend1D, perceptual); in mono or NO_COLOR any fade is the faint attribute. Styles.WithDims(modal, unfocused) sets the new Styles.Backdrop and Styles.Unfocused; Model.Styles() applies the settings. NewStyles uses the defaults.
  • o-story: highlighted counts full-strength highlights only; the new dimmed counts highlights under faint; goldens mark a dimmed-only row r|.

Lists

  • ClearFilterOnEnter() (an InstanceOption for AddList and AddTree): enter in the list's filter line chooses the selected match (list.filter-choose, guard list-chooses): the filter clears, the selection stays on that row and on screen, the mode is normal. With no match enter keeps the filter, as on every list; other lists are unchanged. Story lists/filter-enter-clears.

Fixes

  • Custom components' explicit Block.Cursor now reaches Model.View().Cursor without a focused input, using the normal block or visual underline shape. Blocks without a cursor remain hidden; input and terminal cursor shapes are unchanged.

v0.9.0

Choose a tag to compare

@unixsuperhero unixsuperhero released this 26 Oct 21:31

List motions

  • Every list answers Vim's paging motions in normal mode: g g and G go to the first and last row, and with a count to that row (5G, 5gg, list.goto {position, row}); ctrl+d/ctrl+u move half a page (a count is rows) and ctrl+f/ctrl+b a page (a count is pages) (list.scroll {delta, half, steps}). A page is the list's own window, else the page body's height; the window moves with the selection. They clamp at the list's edges, never spill, and are motions (off the footer, under movement in ?). A row noun that binds the same key keeps it. Story lists/page-motions.
  • A table with more columns than fit scrolls them (list.scroll-columns {to, delta, steps}, List.ColumnOffset): $ brings the last column into view, ^ (and 0 without a count) goes back, z l/z h move one column. The first column stays; the unscrolled view still drops columns by Priority. The keys answer only on a table that hides a column or is scrolled. Story tables/column-motions.
  • A key-sequence prefix whose only remaining row is its generated <prefix> esc cancel (every sequence on it guarded off) no longer waits for a second key.