@ssebastien/tcmd 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -38
- package/bin/tcmd +10 -2
- package/bin/tcmd.js +13 -2
- package/package.json +4 -3
- package/public/index.html +14 -0
- package/public/main.js +17501 -0
- package/public/style.css +901 -0
- package/scripts/serve-web.js +61 -0
- package/src/js/tcmd/components/App.html +28 -12
- package/src/js/tcmd/components/App.js +135 -85
- package/src/js/tcmd/components/App.xml +64 -15
- package/src/js/tcmd/components/BookmarkList.html +3 -2
- package/src/js/tcmd/components/BookmarkList.js +1 -1
- package/src/js/tcmd/components/Breadcrumbs.js +1 -1
- package/src/js/tcmd/components/CommandArgRow.html +17 -0
- package/src/js/tcmd/components/CommandArgRow.js +86 -26
- package/src/js/tcmd/components/CommandArgRow.xml +31 -4
- package/src/js/tcmd/components/CommandBar.html +1 -1
- package/src/js/tcmd/components/CommandBar.js +3 -3
- package/src/js/tcmd/components/CommandItem.html +1 -1
- package/src/js/tcmd/components/CommandItem.js +1 -0
- package/src/js/tcmd/components/CommandPanel.html +29 -0
- package/src/js/tcmd/components/CommandPanel.js +54 -52
- package/src/js/tcmd/components/CommandPanel.xml +38 -24
- package/src/js/tcmd/components/Confirm.html +1 -1
- package/src/js/tcmd/components/EntryDetail.html +7 -7
- package/src/js/tcmd/components/EntryDetail.js +1 -1
- package/src/js/tcmd/components/FileList.html +5 -1
- package/src/js/tcmd/components/FileList.js +2 -1
- package/src/js/tcmd/components/FilePreview.html +14 -3
- package/src/js/tcmd/components/FilePreview.js +73 -10
- package/src/js/tcmd/components/FilePreview.xml +19 -6
- package/src/js/tcmd/components/FileRow.html +1 -1
- package/src/js/tcmd/components/FileRow.js +10 -3
- package/src/js/tcmd/components/FilterBar.html +1 -1
- package/src/js/tcmd/components/FilterBar.js +14 -4
- package/src/js/tcmd/components/FilterBar.xml +1 -1
- package/src/js/tcmd/{tui/frame.js → components/Frame.js} +120 -91
- package/src/js/tcmd/components/Help.html +7 -0
- package/src/js/tcmd/components/Help.js +109 -0
- package/src/js/tcmd/components/Summary.html +1 -1
- package/src/js/tcmd/components/Summary.js +1 -6
- package/src/js/tcmd/components/icons.js +39 -5
- package/src/js/tcmd/components/index.js +3 -4
- package/src/js/tcmd/components/rows.js +37 -33
- package/src/js/tcmd/core/commands.js +422 -180
- package/src/js/tcmd/core/directory.js +145 -95
- package/src/js/tcmd/core/fs.js +29 -2
- package/src/js/tcmd/core/history.js +58 -0
- package/src/js/tcmd/core/index.js +3 -9
- package/src/js/tcmd/core/keymap.js +3 -3
- package/src/js/tcmd/core/operations.js +108 -15
- package/src/js/tcmd/core/pane.js +31 -8
- package/src/js/tcmd/core/panel.js +172 -82
- package/src/js/tcmd/core/script.js +7 -95
- package/src/js/tcmd/core/selection.js +9 -1
- package/src/js/tcmd/core/session.js +280 -152
- package/src/js/tcmd/index.js +0 -1
- package/src/js/tcmd/tui/app.js +26 -5
- package/src/js/tcmd/tui/catalogue.js +6 -19
- package/src/js/tcmd/tui/index.js +1 -16
- package/src/js/tcmd/tui/theme.js +5 -0
- package/src/js/tcmd/web/app.js +158 -32
- package/src/js/tcmd/web/bookmarks.js +36 -0
- package/src/js/tcmd/web/catalogue.js +45 -39
- package/src/js/tcmd/web/effects.js +143 -0
- package/src/js/tcmd/web/header.html +1 -1
- package/src/js/tcmd/web/header.js +15 -11
- package/src/js/tcmd/web/main.js +6 -66
- package/src/js/tcmd/web/seed.js +3 -3
- package/src/js/tcmd/web/server.js +6 -4
- package/src/js/tcmd/web/theme.js +1 -0
- package/src/js/tcmd/components/CommandPalette.html +0 -7
- package/src/js/tcmd/components/CommandPalette.js +0 -58
- package/src/js/tcmd/components/CommandPalette.xml +0 -16
- package/src/js/tcmd/components/PaletteRow.html +0 -3
- package/src/js/tcmd/components/PaletteRow.js +0 -43
- package/src/js/tcmd/components/PaletteRow.xml +0 -4
- package/src/js/tcmd/tui/help.js +0 -32
|
@@ -49,18 +49,13 @@ function summaryShortDisk(disk) {
|
|
|
49
49
|
function createBehaviors(env) {
|
|
50
50
|
const measure = env.measure ?? ((text) => `${text}`.length)
|
|
51
51
|
return {
|
|
52
|
-
line: (self, data) => {
|
|
53
|
-
const text = summaryText(unwrap(data.entries), unwrap(data.disk))
|
|
54
|
-
const width = env.width ? env.width(self) : 0
|
|
55
|
-
return env.elide ? env.elide(text, width) : text
|
|
56
|
-
},
|
|
57
52
|
lineFg: () => env.lineFg,
|
|
58
53
|
// TUI: degrade by information value instead of chopping mid-token:
|
|
59
54
|
// full line -> short disk -> counts only -> elided counts.
|
|
60
55
|
priorityLine: (self, data) => {
|
|
61
56
|
const entries = unwrap(data.entries)
|
|
62
57
|
const disk = unwrap(data.disk)
|
|
63
|
-
const width = env.width ? env.width(self) : 0
|
|
58
|
+
const width = env.width ? env.width(self, data) : 0
|
|
64
59
|
const full = summaryText(entries, disk)
|
|
65
60
|
if (!width || measure(full) <= width) return full
|
|
66
61
|
const counts = `${INDENT}${summaryCounts(entries)}`
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
// Created: 2026-10-09
|
|
5
5
|
|
|
6
6
|
// Module: tcmd/components/icons
|
|
7
|
-
// Nerd Font
|
|
8
|
-
// (directory, symlink, device node)
|
|
9
|
-
// generic file icon
|
|
7
|
+
// Nerd Font icons, in the spirit of yazi. `iconFor` maps a file entry to its
|
|
8
|
+
// kind icon (directory, symlink, device node), then a per-extension icon, then
|
|
9
|
+
// the generic file icon; a few basenames map directly too, so `Makefile`,
|
|
10
10
|
// `Dockerfile` and dotfiles like `.gitignore` get their icon even without a
|
|
11
|
-
// distinguishing extension.
|
|
11
|
+
// distinguishing extension. `sourceMarker` maps a command-panel entry's
|
|
12
|
+
// namespace (a CLI operation or a TinyCmd action) to its marker.
|
|
12
13
|
//
|
|
13
14
|
// The glyphs are Nerd Font codepoints (from `glyphnames.json`), so they only
|
|
14
15
|
// render on a terminal patched with a Nerd Font: rows show them when the
|
|
@@ -27,6 +28,20 @@ const SYMLINK_ICON = "\u{f0c1}" // nf-fa-link
|
|
|
27
28
|
const DEVICE_ICON = "\u{e795}" // nf-dev-terminal
|
|
28
29
|
const FILE_ICON = "\u{f016}" // nf-fa-file_o
|
|
29
30
|
|
|
31
|
+
// Constant: SOURCE_ICON / SOURCE_TAG
|
|
32
|
+
// The namespace marker the command panel puts in front of each entry name:
|
|
33
|
+
// a terminal prompt for a CLI operation, a bolt for a TinyCmd action. Browsers
|
|
34
|
+
// lack the Nerd Font (and `TCMD_ICONS=0` opts out), so the same marker exists
|
|
35
|
+
// as a three-character tag that keeps the name column aligned either way.
|
|
36
|
+
const SOURCE_ICON = {
|
|
37
|
+
cli: "\u{ebca}", // nf-cod-terminal_bash
|
|
38
|
+
app: "\u{f0e7}", // nf-fa-bolt
|
|
39
|
+
}
|
|
40
|
+
const SOURCE_TAG = {
|
|
41
|
+
cli: "cli",
|
|
42
|
+
app: "app",
|
|
43
|
+
}
|
|
44
|
+
|
|
30
45
|
// Constant: NAME_ICONS
|
|
31
46
|
// Basename (lowercase, leading dot stripped) → glyph, checked before the
|
|
32
47
|
// extension table.
|
|
@@ -180,6 +195,25 @@ function iconsEnabled(environment = globalThis.process?.env ?? {}) {
|
|
|
180
195
|
return value !== "0" && value !== "false" && value !== "off"
|
|
181
196
|
}
|
|
182
197
|
|
|
183
|
-
|
|
198
|
+
// Function: sourceMarker
|
|
199
|
+
// The marker a command-panel entry carries: the Nerd Font glyph when icons are
|
|
200
|
+
// on, the three-character tag otherwise (browsers lack the font).
|
|
201
|
+
function sourceMarker(source, icons) {
|
|
202
|
+
if (icons) return SOURCE_ICON[source] ?? ""
|
|
203
|
+
return SOURCE_TAG[source] ?? ""
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export {
|
|
207
|
+
DEVICE_ICON,
|
|
208
|
+
DIR_ICON,
|
|
209
|
+
FILE_ICON,
|
|
210
|
+
SOURCE_ICON,
|
|
211
|
+
SOURCE_TAG,
|
|
212
|
+
SYMLINK_ICON,
|
|
213
|
+
extensionOf,
|
|
214
|
+
iconFor,
|
|
215
|
+
iconsEnabled,
|
|
216
|
+
sourceMarker,
|
|
217
|
+
}
|
|
184
218
|
|
|
185
219
|
// EOF
|
|
@@ -22,7 +22,6 @@ export { createBehaviors as commandBarBehaviors } from "./CommandBar.js"
|
|
|
22
22
|
export { createBehaviors as commandItemBehaviors } from "./CommandItem.js"
|
|
23
23
|
export { createBehaviors as commandArgRowBehaviors } from "./CommandArgRow.js"
|
|
24
24
|
export { createBehaviors as commandPanelBehaviors } from "./CommandPanel.js"
|
|
25
|
-
export { createBehaviors as commandPaletteBehaviors } from "./CommandPalette.js"
|
|
26
25
|
export { createBehaviors as confirmBehaviors } from "./Confirm.js"
|
|
27
26
|
export { createBehaviors as crumbBehaviors } from "./Crumb.js"
|
|
28
27
|
export { createBehaviors as entryDetailBehaviors } from "./EntryDetail.js"
|
|
@@ -30,12 +29,12 @@ export { createBehaviors as fileListBehaviors } from "./FileList.js"
|
|
|
30
29
|
export { createBehaviors as filePreviewBehaviors } from "./FilePreview.js"
|
|
31
30
|
export { createBehaviors as fileRowBehaviors } from "./FileRow.js"
|
|
32
31
|
export { createBehaviors as filterBarBehaviors } from "./FilterBar.js"
|
|
33
|
-
export { createBehaviors as
|
|
32
|
+
export { createBehaviors as helpBehaviors } from "./Help.js"
|
|
34
33
|
export { createBehaviors as summaryBehaviors } from "./Summary.js"
|
|
35
34
|
|
|
36
35
|
// Helpers
|
|
37
36
|
export { formatCounts, formatDisk, formatMode, formatSize, formatTime } from "./format.js"
|
|
38
|
-
export { iconFor, iconsEnabled } from "./icons.js"
|
|
39
|
-
export { bookmarkRows, commandItemRows, crumbRows, fileRows, fileWindow,
|
|
37
|
+
export { iconFor, iconsEnabled, sourceMarker } from "./icons.js"
|
|
38
|
+
export { bookmarkRows, commandItemRows, crumbRows, fileRows, fileWindow, panelArgRows, panelOpRows } from "./rows.js"
|
|
40
39
|
|
|
41
40
|
// EOF
|
|
@@ -36,7 +36,7 @@ function isCell(value) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
// Function: isSelected
|
|
39
|
-
// Whether a
|
|
39
|
+
// Whether a bookmark row is the current selection. The plain
|
|
40
40
|
// `selectedRow` flag (snapshotted by the row builder) wins over the shared
|
|
41
41
|
// `selected` cell, so a move only rewrites the rows that actually changed.
|
|
42
42
|
function isSelected(data) {
|
|
@@ -119,21 +119,6 @@ function fileRows(FileRow) {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
// Function: paletteRows
|
|
123
|
-
// `{ item: command, index, selectedRow }` bags for `PaletteRow` rows.
|
|
124
|
-
// `selectedRow` is the plain per-row selection flag so a palette move rewrites
|
|
125
|
-
// only the changed rows.
|
|
126
|
-
function paletteRows(PaletteRow) {
|
|
127
|
-
return (self, data) => {
|
|
128
|
-
const selected = isCell(data.selected) ? unwrap(data.selected) : data.selected
|
|
129
|
-
return PaletteRow.map(
|
|
130
|
-
data.items ?? [],
|
|
131
|
-
(item, index) => ({ item, index, selectedRow: index === selected }),
|
|
132
|
-
(command) => command.id,
|
|
133
|
-
)
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
122
|
// Function: commandItemRows
|
|
138
123
|
// `{ item: command, index }` bags for `CommandItem` rows.
|
|
139
124
|
function commandItemRows(CommandItem) {
|
|
@@ -146,23 +131,22 @@ function commandItemRows(CommandItem) {
|
|
|
146
131
|
}
|
|
147
132
|
|
|
148
133
|
// Function: panelOpRows
|
|
149
|
-
// `{ item
|
|
150
|
-
//
|
|
151
|
-
//
|
|
152
|
-
//
|
|
153
|
-
//
|
|
154
|
-
// column's selected index.
|
|
134
|
+
// `{ item, index, row, cursor, focus }` bags for the command panel's command
|
|
135
|
+
// list (`CommandArgRow`). The list is the flat `core/panel.panelEntryRows`: one
|
|
136
|
+
// operation per row. `row` is the normalized shape the component reads —
|
|
137
|
+
// `name` is the operation name and `summary` its argument list; `risk` tints
|
|
138
|
+
// destructive/caution operations.
|
|
155
139
|
function panelOpRows(CommandArgRow) {
|
|
156
140
|
return (self, data) =>
|
|
157
141
|
CommandArgRow.map(
|
|
158
142
|
data.items ?? [],
|
|
159
143
|
(item, index) => ({
|
|
160
144
|
item,
|
|
161
|
-
index,
|
|
145
|
+
index: item.entryIndex ?? index,
|
|
162
146
|
row: {
|
|
163
147
|
type: "op",
|
|
164
148
|
key: item.id,
|
|
165
|
-
name: item.
|
|
149
|
+
name: item.name,
|
|
166
150
|
summary: item.summary ?? "",
|
|
167
151
|
risk: item.risk ?? null,
|
|
168
152
|
},
|
|
@@ -174,22 +158,42 @@ function panelOpRows(CommandArgRow) {
|
|
|
174
158
|
}
|
|
175
159
|
|
|
176
160
|
// Function: panelArgRows
|
|
177
|
-
// `{ item
|
|
178
|
-
// argument
|
|
179
|
-
// `core/panel.panelRowList`;
|
|
161
|
+
// `{ item, index, row, cursor, focus, value, labelWidth }` bags for the command
|
|
162
|
+
// panel's argument pane (`CommandArgRow`). The rows are the flat
|
|
163
|
+
// `core/panel.panelRowList`; this wraps each selection's item run in a top and
|
|
164
|
+
// bottom `frame` row so the list reads as one bordered box. `index` is the
|
|
165
|
+
// row's flat position (the frame rows take none), so the pane cursor still
|
|
166
|
+
// addresses the same rows.
|
|
180
167
|
function panelArgRows(CommandArgRow) {
|
|
181
|
-
return (self, data) =>
|
|
182
|
-
|
|
183
|
-
|
|
168
|
+
return (self, data) => {
|
|
169
|
+
const rows = unwrap(data.rows) ?? []
|
|
170
|
+
const visual = []
|
|
171
|
+
for (let i = 0; i < rows.length; i++) {
|
|
172
|
+
const row = rows[i]
|
|
173
|
+
if (row.type !== "item") {
|
|
174
|
+
visual.push(row)
|
|
175
|
+
continue
|
|
176
|
+
}
|
|
177
|
+
const first = i === 0 || rows[i - 1].type !== "item"
|
|
178
|
+
const last = i === rows.length - 1 || rows[i + 1].type !== "item"
|
|
179
|
+
if (first) visual.push({ ...row, type: "frame", variant: "top", key: `frame:top:${row.argIndex}` })
|
|
180
|
+
visual.push(row)
|
|
181
|
+
if (last) visual.push({ ...row, type: "frame", variant: "bottom", key: `frame:bottom:${row.argIndex}` })
|
|
182
|
+
}
|
|
183
|
+
return CommandArgRow.map(
|
|
184
|
+
visual,
|
|
184
185
|
(item, index) => ({
|
|
185
186
|
item,
|
|
186
|
-
index,
|
|
187
|
+
index: item.type === "frame" ? -1 : item.rowIndex ?? index,
|
|
187
188
|
row: item,
|
|
188
189
|
cursor: data.argCursor,
|
|
189
190
|
focus: data.focus,
|
|
191
|
+
value: data.value,
|
|
192
|
+
labelWidth: unwrap(data.labelWidth) ?? 8,
|
|
190
193
|
}),
|
|
191
|
-
(
|
|
194
|
+
(item) => item.key,
|
|
192
195
|
)
|
|
196
|
+
}
|
|
193
197
|
}
|
|
194
198
|
|
|
195
199
|
// Function: bookmarkRows
|
|
@@ -207,6 +211,6 @@ function bookmarkRows(BookmarkRow) {
|
|
|
207
211
|
}
|
|
208
212
|
}
|
|
209
213
|
|
|
210
|
-
export { bookmarkRows, commandItemRows, crumbRows, fileRows, fileWindow, isSelected,
|
|
214
|
+
export { bookmarkRows, commandItemRows, crumbRows, fileRows, fileWindow, isSelected, panelArgRows, panelOpRows }
|
|
211
215
|
|
|
212
216
|
// EOF
|