Skip to content

v0.13.0

Choose a tag to compare

@github-actions github-actions released this 12 Oct 22:46
· 54 commits to main since this release
0d3518f
  • @tooee/cli@0.13.0
  • @tooee/ask@0.13.0
  • @tooee/choose@0.13.0
  • @tooee/clipboard@0.13.0
  • @tooee/commands@0.13.0
  • @tooee/config@0.13.0
  • @tooee/diff@0.13.0
  • @tooee/fuzzy@0.13.0
  • @tooee/marks@0.13.0
  • @tooee/layout@0.13.0
  • @tooee/overlays@0.13.0
  • @tooee/panels@0.13.0
  • @tooee/renderers@0.13.0
  • @tooee/router@0.13.0
  • @tooee/search@0.13.0
  • @tooee/shell@0.13.0
  • @tooee/themes@0.13.0
  • @tooee/toasts@0.13.0
  • @tooee/view@0.13.0

Copy tells you when no clipboard tool is installed (158d524)

copyToClipboard now resolves true when a clipboard tool took the text, and false when no tool is installed or the tool exits with an error. Before, it resolved nothing, and the copy commands always showed "Copied".

The copy commands in @tooee/shell and the Ask editor now show an error toast when the copy fails. On Linux, install wl-copy, xclip or xsel.

Enter always calls onSubmit and onConfirm (7ec1a31)

Before, an action with the id submit took the place of the onSubmit callback in Ask and the onConfirm callback in Choose. Enter ran the action and skipped the callback, so launch() from @tooee/ask and @tooee/choose resolved null when a caller passed a submit action.

Now Enter always calls the callback, and launch() returns the value. An action with the id submit is an ordinary command. It runs from the command palette or from its own hotkey. AskOverlay, ChooseOverlay and the dialog hooks already worked this way.

If your app used a submit action to read the value, move that code into onSubmit or onConfirm.

Keep the status bar and title bar on one row (6b453e0)

The status bar and the title bar no longer wrap onto a second row when the terminal is narrow. Before, a label could also lose its gap to its value.

StatusBarItem has new optional fields. priority sets which items stay longest. align: "end" puts an item at the right edge. compact gives a shorter form. truncate and minValueWidth let a value shorten with an ellipsis. When items do not fit, the bar uses compact forms first. Then it shortens or hides items, lowest priority first. A ⋯ glyph shows when items hide. Pass hiddenMarker to StatusBar or AppLayout.statusBar to change the glyph, or false to turn it off.

StatusPriority names the shared scale: critical, position, focus, content, background (the default), and hint. fitStatusBar, fitTitleBar, and truncateCells are exported for apps and tests.

DocumentScreen now shows Mode: and Cursor: at the right edge. Cursor: shortens to Ln when the bar is narrow. Built-in items in @tooee/view, @tooee/ask, and @tooee/choose have priorities, and their key hints go first.

The title bar shortens its subtitle first, hides it below 8 cells, and then shortens the title.

Items with only label and value look the same as before when they fit.

ctx.exit() closes the app everywhere (8428a47)

ctx.exit() did nothing in a launchCli app or in View, because only Ask and Choose supplied an exit. The command provider now uses the renderer's destroy as the default exit. A context source can still supply its own exit.

The command palette hides unavailable commands and shows remapped keys (3f0e08e)

The palette now leaves out a command whose when returns false when the palette opens. Before, it listed the command, and choosing it did nothing.

The palette now shows the key from the keys config, not the command's default key. A root command that a panel command shadows under its remapped key loses its key hint, as dispatch does.

useEffectiveCommands() returns two new functions: hotkeyFor(id) gives the key that runs a command now, and isAvailable(id) checks the command's when against the context of the surface that owns it.

A + hotkey works (ee072a0)

A command bound to "+" now runs when you press +. Before, the parser split the step on + and the hotkey never matched. "ctrl++" binds ctrl with the + key, and + also works as one step in a sequence such as "z +".

Quit and retry from a route's pending or error screen (8bb6d7d)

While a route's pending or error component replaces the screen, the screen's own commands are unmounted. Before, an app that bound q only inside its screens could not quit from a failed load. Now, inside a CommandProvider, the router registers two fallback commands while the pending or error component shows:

  • q calls ctx.exit().
  • r runs the route loader again. This command exists only on the error screen.

Commands that the app or the error component registers on the same keys run first.

The errorComponent now gets a retry prop next to error. The props type is exported as RouteErrorProps.

@tooee/commands exports useHasCommandProvider(), which tells a component whether a CommandProvider is above it.

writeGlobalConfig keeps keys it does not know (deba08a)

writeGlobalConfig used to decode the global config file, merge the update, and write the decoded result back. Any key that Tooee does not decode, for example "editor", went away. Now the write merges into the raw JSON document. Unknown keys stay, at the top level and inside theme, keys and view.

If the global config file is not valid JSON, the write now leaves it unchanged. Before, the write replaced the file.

SearchBar.onCancel is optional and deprecated (6d6ac1f)

SearchBar never called onCancel. Escape reaches the search-cancel command that useSearchBindings registers, and that command cancels the search. The prop is now optional and marked deprecated, and AppLayout no longer passes it. A later release will remove it.

OverlayRole no longer accepts "panel" (85b10fc)

An owned overlay opened with role: "panel" never became active, because a panel surface needs a panel group and overlays have none. OverlayRole is now "modal" | "passive", so TypeScript rejects "panel". Use @tooee/panels for panel surfaces.

Escape closes an ownCommands modal (2192a36)

An overlay opened with ownCommands: true and the default dismissOnEscape now closes on Escape, with the close reason "escape". Before, the modal surface suspended root dispatch, so the root Escape command never ran, and dismissOnEscape had no effect. An Escape command that the overlay registers itself still runs first.

RouterProvider accepts a router made with context (ac86ced)

RouterProvider now accepts a router created with createRouter({ context }). Before, the router prop had the type RouterInstance with no type argument, so TypeScript rejected a router with an app context.

useRouter() now returns RouterInstance<unknown>, because the provider can hold a router with any context type. Code that reads useRouter().context must check the value before use.

n and N skip rows the cursor cannot stop on (ace8626)

searchNext and searchPrevious now move the cursor to the nearest selectable row in the search direction, the same way typing and Enter already do. Before, n and N could put the cursor on a row that isSelectable rejects.

Remove the unused Search: status item from DocumentScreen (be89d2c)

DocumentScreen built a Search: status item only while the search bar was open. The search bar replaces the status bar then, so the item never showed. The dead item is gone. The search bar still shows the query and the match count while it is open.

Export useNavigationBindings (6477c3e)

@tooee/shell now exports useNavigationBindings(store, options). It registers the cursor, select and multi-select keys for a nav-search store that you own. Use it with useNavSearchStore and useSearchBindings from @tooee/search when one screen shares a store between navigation and search. Before, such a screen had to register its own movement keys.

Add search highlight theme tokens (a87db90)

Themes have four new keys: searchMatchBg, searchCurrentMatchBg, searchMatchFg, and searchCurrentMatchFg. Every bundled theme sets them.

Search matches in row documents now use a background tinted from warning, and the current match uses a background tinted from primary. Before, both used the full warning and primary colours, which made the matched text hard to read. The gutter signs keep their old colours.

A custom theme that leaves out the new keys gets derived values: 22% of warning over background for searchMatchBg, 35% of primary over background for searchCurrentMatchBg, and warning and primary for the signs. Over a transparent background, the derived backgrounds are translucent.

The nearest project theme folder wins (3da62af)

Tooee loads .tooee/themes/ folders from the filesystem root down to the current folder. When two folders have a theme with the same name, the theme in the folder nearest to the current folder is used. Before, the parent folder's theme replaced the child's. Config files already used nearest wins.

useThemeSwitcher can change light or dark mode (48f8894)

useThemeSwitcher() returns a new setMode(mode, { persist }) function. It switches the current theme between its light and dark variants while the app runs. With persist: true, it also writes the mode to the global config, as setTheme does.

Directory view moves file keys to g n and g p (e28d9f9)

In the directory view, g n opens the next file and g p opens the previous file. Before, these commands used l and h. The markdown and diff subviews also use h and l for horizontal scroll, so the command that registered first ran, and mount order decided which one that was. Now h and l only scroll.

To keep the old keys, set "dir.next-file": "l" and "dir.prev-file": "h" in the keys config.

launch() accepts onMarkdownLinkActivate (6d9f781)

launch() from @tooee/view now takes the onMarkdownLinkActivate option that the View component already had. The handler runs when the user activates a Markdown link with the mouse or with Enter on the cursor line. It replaces the default handling: linkHandlers, local file navigation, and the stdin "Links need a source file" toast.