plan: b, t and C open their own view alone or beside what is there, q closes one view

S still puts the board, the agenda and the calendar on the plan screen.
From the documents, b, t or C opens the plan with only that view; on the
plan they add the view beside the others, or focus it if it is there.
q and Esc close the focused view the way they close a document's tile,
back along the trail, and only closing the last view leaves the plan.
This commit is contained in:
nvrl committed 2026-10-23 00:48:50 +02:00
1 parent 4542b9692e
commit c6c5e9e144
9 files changed
+62 -52

No files matched your search

+1 -1
View File
@@ -565,7 +565,7 @@ export const actions: { [C in Context]: Record<ActionOf<C>, Run> } = {
calendar: () => void runCommand('cal'),
// `S`, as the desktop's special workspace is bound: the plan screen —
// the board, the agenda and the calendar — and back to the documents.
// `b`, `t` and `C` go there too, to their own view.
// `b`, `t` and `C` go there with their own view alone, or add it beside.
plan: () => void runCommand('plan'),
line: () => line(':'),
help: () => void runCommand('help'),
+3 -3
View File
@@ -605,14 +605,14 @@ export const commands: CommandSpec[] = [
{
name: 'board',
group: 'board',
help: "this space's board, on the plan screen — the last one shown when this space has none",
help: "this space's board, on the plan screen, alone or beside what is there — the last one shown when this space has none",
run: () => workspace.guard(() => workspace.tiles.show('board')),
},
{
name: 'plan',
aliases: ['special'],
group: 'board',
help: 'the plan screen: the board, the agenda and the calendar, in place of the documents — S goes there and back again; 1 … 9 on the board picks the board',
help: 'the plan screen with every view on it: the board, the agenda and the calendar, in place of the documents — S goes there and back again; 1 … 9 on the board picks the board',
run: () => workspace.guard(() => workspace.tiles.togglePlan()),
},
{
@@ -888,7 +888,7 @@ export const commands: CommandSpec[] = [
name: 'close',
aliases: ['clo'],
group: 'tiles',
help: 'close the focused tile — q while reading; on the plan screen, back to the documents; asks when its draft could not be written',
help: 'close the focused tile — q while reading; on the plan screen the view, and the last one back to the documents; asks when its draft could not be written',
run: () =>
workspace.guard(async () => {
await workspace.drafts.flushTile()
+5 -5
View File
@@ -108,14 +108,14 @@ export const bindings = [
{ context: 'tree', keys: ['za'], action: 'files', help: "a document's own files, folded open under it in the list — again folds them away; p drops marked files in there" },
{ context: 'tree', keys: ['M'], action: 'markAll', help: 'pick up the whole folder — again puts it all back' },
{ context: 'tree', label: 'Ctrl / Shift-click', help: 'pick a row up · every row up to it — drag them onto a folder' },
{ context: 'global', keys: ['S'], action: 'plan', help: 'the plan screen: the board, the agenda and the calendar, in place of the documents and the list — S again goes back to the documents as they were', essential: true },
{ context: 'global', keys: ['t'], action: 'agenda', help: 'agenda — late, due this week, in hand, on every board — on the plan screen', essential: true },
{ context: 'global', keys: ['S'], action: 'plan', help: 'the plan screen with every view on it: the board, the agenda and the calendar, in place of the documents and the list — S again goes back to the documents as they were', essential: true },
{ context: 'global', keys: ['t'], action: 'agenda', help: 'agenda — late, due this week, in hand, on every board — on the plan screen, alone or beside what is there', essential: true },
{ context: 'global', keys: ['T'], action: 'today', help: "today's diary entry, started if there is none — from templates/day when the diary has one", essential: true },
{ context: 'global', keys: ['C'], action: 'calendar', help: 'the diary by month, on the plan screen: h/l a day, j/k a week, H/L a month, . today, Enter opens or starts the day among the documents' },
{ context: 'global', keys: ['C'], action: 'calendar', help: 'the diary by month, on the plan screen, alone or beside what is there: h/l a day, j/k a week, H/L a month, . today, Enter opens or starts the day among the documents' },
{ context: 'tree', keys: ['[d'], action: 'previousEntry', label: '[d / ]d', help: 'the diary entry before / after the one open, by date' },
{ context: 'tree', keys: [']d'], action: 'nextEntry' },
{ context: 'global', keys: ['Ctrl-p'], action: 'find', label: 'Ctrl-P', help: 'go to anything by its name, in every space — words before the last narrow the path, as in proj/ingest; Tab or Ctrl-N/P walk, Enter goes', essential: true },
{ context: 'global', keys: ['b'], action: 'board', help: "the board, on the plan screen: this space's, or the last one shown — 1 … 9 there shows another's" },
{ context: 'global', keys: ['b'], action: 'board', help: "the board, on the plan screen, alone or beside what is there: this space's, or the last one shown — 1 … 9 there shows another's" },
{ context: 'tree', keys: ['c'], action: 'capture', help: "capture a card into this space's inbox, without leaving here — reading a document, a card about it; Tab on the line makes it a note, or a line in today's entry", essential: true },
{ context: 'tree', keys: ['q'], action: 'close', label: 'Esc · q', help: 'close the document, and its tile when there are several — Esc first puts down what m picked up, and in the list lets go of a search', essential: true },
{ context: 'tree', keys: ['Escape'], action: 'escape' },
@@ -141,7 +141,7 @@ export const bindings = [
{ context: 'writing', keys: ['*'], action: 'refocus' },
// --- what the views share: the board, the agenda, the calendar, a card's back
{ context: 'views', keys: ['q', 'Escape'], action: 'close', label: 'q · Esc', caps: ['q'], hint: 'close', help: "on the plan screen: from a card's back to the board, from the board, the agenda or the calendar back to the documents" },
{ context: 'views', keys: ['q', 'Escape'], action: 'close', label: 'q · Esc', caps: ['q'], hint: 'close', help: "on the plan screen: the view goes, and the plan stays while anything is left on it — a card's back goes back to the board, the last view back to the documents" },
// --- on a board ---------------------------------------------------------------
{ context: 'board', keys: ['h', 'ArrowLeft'], action: 'left', label: 'h / l', caps: ['h', 'j', 'k', 'l'], hint: 'move', help: 'to the list left / right — right of the last, to the tile beside' },
+23 -19
View File
@@ -171,11 +171,11 @@ export class Tiles {
/**
* `:close`: the focused tile goes, or with only one, what it shows. On the
* plan only a card's back goes; closing the board, the agenda or the
* calendar goes back to the documents.
* plan a view goes as a document's tile does, and the plan stays while
* anything is left on it; closing the last goes back to the documents.
*/
close() {
if (this.planning && this.current.kind !== 'card') return this.leavePlan()
if (this.planning && this.all.length === 1) return this.leavePlan()
this.ws.drafts.leaveCard()
this.current.clear()
this.prune()
@@ -219,11 +219,13 @@ export class Tiles {
/*
* The views — the board, the agenda, the calendar, a card's back — are
* the tiles of the plan screen. Each is read again whenever it is gone to:
* it is looked at in passing, and what it says should be what is true now.
* the tiles of the plan screen. The plan opens on the one asked for, and
* the others come beside it when they are asked for in turn. Each is read
* again whenever it is gone to: it is looked at in passing, and what it
* says should be what is true now.
*/
/** The views the plan screen holds, in the order they are tiled. */
/** The views `S` puts on the plan screen, in the order they are tiled. */
static readonly PLAN: View[] = ['board', 'agenda', 'calendar']
/** The other screen on show, and this one put away as it is. */
@@ -237,14 +239,12 @@ export class Tiles {
this.planning = !this.planning
}
/** To the plan screen, with every view on it, from wherever the documents were. */
enterPlan() {
/** To the plan screen, with `kinds` on it and nothing else, from wherever the documents were. */
enterPlan(kinds: View[]) {
if (this.planning) return
this.ws.drafts.leaveCard()
this.swap()
const cards = this.all.filter((tile) => tile.kind === 'card')
this.all = [...Tiles.PLAN.map((kind) => this.view(kind) ?? new Tile(kind)), ...cards]
this.focused = Math.min(this.focused, this.all.length - 1)
this.replace(kinds.map((kind) => new Tile(kind)))
this.ws.pane = 'document'
}
@@ -258,21 +258,25 @@ export class Tiles {
if (!this.current.empty) this.focusOn(this.focused)
}
/** `b`, `t`, `C`, Enter on a card: to the plan screen, and that view on it focused. */
async show(kind: View) {
// Coming to the plan, every view on it is read again, not only this one.
const kinds = this.planning ? [kind] : Tiles.PLAN
/**
* `b`, `t`, `C`, Enter on a card: that view focused on the plan screen —
* alone on it when coming from the documents, beside what is there when
* already on it.
*/
async show(kind: View, all = false) {
// Coming to the plan, every view put on it is read again, not only this one.
const kinds = all ? Tiles.PLAN : [kind]
await Promise.all(kinds.map((each) => this.loadView(each)))
this.enterPlan()
if (!this.view(kind)) this.all.push(new Tile(kind))
this.enterPlan(kinds)
if (!this.view(kind)) this.add(new Tile(kind))
this.focusOn(this.all.indexOf(this.view(kind)!))
if (kind === 'board' && this.ws.cards.boardSpaceId === null) this.ws.say('no space has a board — :set board turns one on', 'error')
}
/** `S`: the plan screen with the board focused, or back to the documents. */
/** `S`: the plan screen with every view on it and the board focused, or back to the documents. */
async togglePlan() {
if (this.planning) return this.leavePlan()
await this.show('board')
await this.show('board', true)
}
/** Read again what a view shows. */