@ssebastien/tcmd 0.1.3 → 0.1.7
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 +256 -62
- package/bin/tcmd +10 -2
- package/bin/tcmd.js +13 -2
- package/desktop/dist/index.html +13 -0
- package/desktop/dist/main.js +20298 -0
- package/desktop/dist/style.css +1515 -0
- package/desktop/frontend/index.html +13 -0
- package/package.json +19 -6
- package/public/fonts/OFL.txt +93 -0
- package/public/index.html +14 -0
- package/public/licenses/LUCIDE.txt +43 -0
- package/public/main.js +20679 -0
- package/public/style.css +1515 -0
- package/scripts/build-desktop.js +31 -0
- package/scripts/serve-web.js +61 -0
- package/src/js/tcmd/components/App.html +80 -14
- package/src/js/tcmd/components/App.js +339 -114
- package/src/js/tcmd/components/App.xml +76 -22
- package/src/js/tcmd/components/BookmarkList.html +5 -5
- package/src/js/tcmd/components/BookmarkList.js +15 -41
- package/src/js/tcmd/components/BookmarkList.xml +1 -2
- package/src/js/tcmd/components/BookmarkRow.html +2 -1
- package/src/js/tcmd/components/BookmarkRow.js +14 -9
- package/src/js/tcmd/components/BookmarkRow.xml +1 -1
- package/src/js/tcmd/components/Breadcrumbs.js +1 -1
- package/src/js/tcmd/components/CommandArgRow.html +28 -0
- package/src/js/tcmd/components/CommandArgRow.js +146 -30
- package/src/js/tcmd/components/CommandArgRow.xml +55 -4
- package/src/js/tcmd/components/CommandBar.html +2 -2
- package/src/js/tcmd/components/CommandBar.js +33 -27
- package/src/js/tcmd/components/CommandBar.xml +2 -2
- package/src/js/tcmd/components/CommandItem.html +1 -1
- package/src/js/tcmd/components/CommandItem.js +25 -25
- package/src/js/tcmd/components/CommandItem.xml +2 -2
- package/src/js/tcmd/components/CommandPanel.html +29 -0
- package/src/js/tcmd/components/CommandPanel.js +78 -52
- package/src/js/tcmd/components/CommandPanel.xml +49 -25
- package/src/js/tcmd/components/Confirm.html +2 -2
- package/src/js/tcmd/components/EntryDetail.html +7 -7
- package/src/js/tcmd/components/EntryDetail.js +22 -8
- package/src/js/tcmd/components/FileList.html +5 -1
- package/src/js/tcmd/components/FileList.js +2 -1
- package/src/js/tcmd/components/FilePicker.html +10 -0
- package/src/js/tcmd/components/FilePicker.js +43 -0
- package/src/js/tcmd/components/FilePicker.xml +13 -0
- package/src/js/tcmd/components/FilePickerRow.html +6 -0
- package/src/js/tcmd/components/FilePickerRow.js +27 -0
- package/src/js/tcmd/components/FilePickerRow.xml +10 -0
- package/src/js/tcmd/components/FilePreview.html +14 -4
- package/src/js/tcmd/components/FilePreview.js +111 -12
- package/src/js/tcmd/components/FilePreview.xml +28 -8
- package/src/js/tcmd/components/FileRow.html +2 -1
- package/src/js/tcmd/components/FileRow.js +70 -12
- 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/components/Frame.js +324 -0
- package/src/js/tcmd/components/Help.html +15 -0
- package/src/js/tcmd/components/Help.js +260 -0
- package/src/js/tcmd/components/Help.xml +13 -4
- package/src/js/tcmd/components/HelpRow.html +8 -0
- package/src/js/tcmd/components/HelpRow.xml +7 -0
- package/src/js/tcmd/components/OverlayList.html +8 -0
- package/src/js/tcmd/components/OverlayList.js +69 -0
- package/src/js/tcmd/components/{CommandPalette.xml → OverlayList.xml} +2 -5
- package/src/js/tcmd/components/OverlayRow.html +5 -0
- package/src/js/tcmd/components/OverlayRow.js +47 -0
- package/src/js/tcmd/components/OverlayRow.xml +9 -0
- package/src/js/tcmd/components/Summary.html +1 -1
- package/src/js/tcmd/components/Summary.js +1 -6
- package/src/js/tcmd/components/format.js +4 -23
- package/src/js/tcmd/components/icons.js +176 -5
- package/src/js/tcmd/components/index.js +9 -5
- package/src/js/tcmd/components/rows.js +176 -48
- package/src/js/tcmd/core/base64.js +64 -0
- package/src/js/tcmd/core/bookmarks.js +45 -8
- package/src/js/tcmd/core/commands.js +978 -260
- package/src/js/tcmd/core/concurrency.js +59 -0
- package/src/js/tcmd/core/decompress.js +117 -0
- package/src/js/tcmd/core/directory.js +219 -93
- package/src/js/tcmd/core/format.js +36 -0
- package/src/js/tcmd/core/fs.js +438 -54
- package/src/js/tcmd/core/history.js +58 -0
- package/src/js/tcmd/core/index.js +3 -9
- package/src/js/tcmd/core/journal.js +93 -0
- package/src/js/tcmd/core/keymap.js +42 -6
- package/src/js/tcmd/core/operations.js +813 -48
- package/src/js/tcmd/core/os.js +29 -3
- package/src/js/tcmd/core/pane.js +33 -8
- package/src/js/tcmd/core/panel.js +280 -104
- package/src/js/tcmd/core/path.js +30 -3
- package/src/js/tcmd/core/permissions.js +107 -0
- package/src/js/tcmd/core/picker.js +156 -0
- package/src/js/tcmd/core/preview.js +102 -0
- 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 +498 -200
- package/src/js/tcmd/core/watch.js +153 -0
- package/src/js/tcmd/desktop/backend/api.js +165 -0
- package/src/js/tcmd/desktop/backend/fs.js +626 -0
- package/src/js/tcmd/desktop/backend/main.ts +9 -0
- package/src/js/tcmd/desktop/bookmarks.js +23 -0
- package/src/js/tcmd/desktop/fs.js +91 -0
- package/src/js/tcmd/desktop/main.js +194 -0
- package/src/js/tcmd/desktop/os.js +33 -0
- package/src/js/tcmd/index.js +0 -1
- package/src/js/tcmd/tui/app.js +118 -60
- package/src/js/tcmd/tui/catalogue.js +238 -42
- package/src/js/tcmd/tui/index.js +18 -19
- package/src/js/tcmd/tui/opentui.js +33 -0
- package/src/js/tcmd/tui/syntax.js +91 -0
- package/src/js/tcmd/tui/theme.js +32 -2
- package/src/js/tcmd/vendor/bzip2.js +276 -0
- package/src/js/tcmd/web/app.js +225 -41
- package/src/js/tcmd/web/bookmarks.js +36 -0
- package/src/js/tcmd/web/catalogue.js +81 -38
- package/src/js/tcmd/web/effects.js +223 -0
- package/src/js/tcmd/web/header.html +1 -1
- package/src/js/tcmd/web/header.js +15 -11
- package/src/js/tcmd/web/http.js +13 -0
- package/src/js/tcmd/web/index.js +2 -2
- package/src/js/tcmd/web/main.js +6 -66
- package/src/js/tcmd/web/opfs.js +297 -30
- package/src/js/tcmd/web/seed.js +4 -4
- package/src/js/tcmd/web/server.js +124 -21
- package/src/js/tcmd/web/theme.js +4 -0
- package/tinyjs.json +16 -0
- package/src/js/tcmd/components/CommandPalette.html +0 -7
- package/src/js/tcmd/components/CommandPalette.js +0 -58
- 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/frame.js +0 -269
- package/src/js/tcmd/tui/help.js +0 -32
|
@@ -14,6 +14,7 @@ export { createNodeFs } from "./fs.js"
|
|
|
14
14
|
export { createNullOs, createNodeOs } from "./os.js"
|
|
15
15
|
export { filterEntries, rankEntries, sortEntries, viewEntries } from "./entries.js"
|
|
16
16
|
export { clampCursor, currentEntry, moveCursor, toggleMark } from "./selection.js"
|
|
17
|
+
export { createHistory } from "./history.js"
|
|
17
18
|
export { PANE_BUFFERS, PANE_LABELS, createPane } from "./pane.js"
|
|
18
19
|
export { createDirectory } from "./directory.js"
|
|
19
20
|
export {
|
|
@@ -26,14 +27,7 @@ export {
|
|
|
26
27
|
export { DEFAULT_KEYMAP, matchKeymap } from "./keymap.js"
|
|
27
28
|
export { createDispatch, getCommand, getCommands } from "./commands.js"
|
|
28
29
|
export { expandAll, expandArg, decodePathToken, getOperation, getOperations, pathToken, runOperation } from "./operations.js"
|
|
29
|
-
export {
|
|
30
|
-
|
|
31
|
-
argvFor,
|
|
32
|
-
bindArgs,
|
|
33
|
-
panelOperations,
|
|
34
|
-
panelRowList,
|
|
35
|
-
paneSelectionPaths,
|
|
36
|
-
} from "./panel.js"
|
|
37
|
-
export { parseLine, runLine, scriptItems, tokenize } from "./script.js"
|
|
30
|
+
export { PANEL_FOCUS, argvFor, bindArgs, panelEntries, panelRowList, paneSelectionPaths } from "./panel.js"
|
|
31
|
+
export { parseLine, runLine, tokenize } from "./script.js"
|
|
38
32
|
export { createSession, load } from "./session.js"
|
|
39
33
|
export { SEP, basename, extname, join, normalize, parent, prefix, split } from "./path.js"
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Project: TinyCommand
|
|
2
|
+
// Author: Sebastien Pierre
|
|
3
|
+
// License: BSD
|
|
4
|
+
// Created: 2026-10-17
|
|
5
|
+
|
|
6
|
+
// Module: tcmd/core/journal
|
|
7
|
+
// The undo/redo journal: an ordered list of applied file operations, each
|
|
8
|
+
// carrying an inverse (`undo`) and a forward (`redo`) action. `index` points at
|
|
9
|
+
// the last *applied* entry; entries after it are undone and can be redone.
|
|
10
|
+
// `record` appends and truncates any redo tail (a new action forks history), so
|
|
11
|
+
// the model is a plain linear history like a text editor's.
|
|
12
|
+
//
|
|
13
|
+
// Actions are closures over the paths an operation touched, so the journal is
|
|
14
|
+
// session-only (not persisted): a fresh session starts empty. `rows()` projects
|
|
15
|
+
// the entries for the history panel, marking which are applied and where the
|
|
16
|
+
// pointer sits.
|
|
17
|
+
|
|
18
|
+
import { cell } from "select/state/cells"
|
|
19
|
+
|
|
20
|
+
// Function: createJournal
|
|
21
|
+
// Creates an empty journal. `entries` is the ordered action list (oldest
|
|
22
|
+
// first); `index` is the last applied entry (-1 when nothing is applied).
|
|
23
|
+
function createJournal({ entries = [], index = -1 } = {}) {
|
|
24
|
+
const journal = {}
|
|
25
|
+
journal.entries = cell(entries.slice())
|
|
26
|
+
journal.index = cell(Math.min(index, entries.length - 1))
|
|
27
|
+
let sequence = entries.length
|
|
28
|
+
|
|
29
|
+
// Function: record
|
|
30
|
+
// Appends `entry` — `{ label, undo?, redo? }` — discarding any undone tail,
|
|
31
|
+
// and moves the pointer onto it. Returns the entry's id.
|
|
32
|
+
journal.record = (entry) => {
|
|
33
|
+
const kept = journal.entries.value.slice(0, journal.index.value + 1)
|
|
34
|
+
const recorded = { id: ++sequence, at: Date.now(), ...entry }
|
|
35
|
+
kept.push(recorded)
|
|
36
|
+
journal.entries.set(kept)
|
|
37
|
+
journal.index.set(kept.length - 1)
|
|
38
|
+
return recorded.id
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Function: canUndo / canRedo
|
|
42
|
+
journal.canUndo = () => journal.index.value >= 0
|
|
43
|
+
journal.canRedo = () => journal.index.value < journal.entries.value.length - 1
|
|
44
|
+
|
|
45
|
+
// Function: undo
|
|
46
|
+
// Runs the inverse of the entry at the pointer and steps back. Returns the
|
|
47
|
+
// entry, or null when there is nothing to undo.
|
|
48
|
+
journal.undo = async (session) => {
|
|
49
|
+
if (!journal.canUndo()) return null
|
|
50
|
+
const entry = journal.entries.value[journal.index.value]
|
|
51
|
+
await entry?.undo?.(session)
|
|
52
|
+
journal.index.set(journal.index.value - 1)
|
|
53
|
+
return entry
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Function: redo
|
|
57
|
+
// Re-applies the next undone entry and steps onto it. Returns the entry, or
|
|
58
|
+
// null when there is nothing to redo.
|
|
59
|
+
journal.redo = async (session) => {
|
|
60
|
+
if (!journal.canRedo()) return null
|
|
61
|
+
const next = journal.index.value + 1
|
|
62
|
+
const entry = journal.entries.value[next]
|
|
63
|
+
await entry?.redo?.(session)
|
|
64
|
+
journal.index.set(next)
|
|
65
|
+
return entry
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Function: goTo
|
|
69
|
+
// Undoes or redoes repeated until the pointer sits on `target` (-1 empties
|
|
70
|
+
// the applied set). Used by the history panel to jump to an entry.
|
|
71
|
+
journal.goTo = async (session, target) => {
|
|
72
|
+
while (journal.index.value > target && journal.canUndo()) await journal.undo(session)
|
|
73
|
+
while (journal.index.value < target && journal.canRedo()) await journal.redo(session)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Function: rows
|
|
77
|
+
// Panel rows, oldest first: `{ id, label, at, index, applied, current }`.
|
|
78
|
+
journal.rows = () =>
|
|
79
|
+
journal.entries.value.map((entry, i) => ({
|
|
80
|
+
id: entry.id,
|
|
81
|
+
label: entry.label,
|
|
82
|
+
at: entry.at,
|
|
83
|
+
index: i,
|
|
84
|
+
applied: i <= journal.index.value,
|
|
85
|
+
current: i === journal.index.value,
|
|
86
|
+
}))
|
|
87
|
+
|
|
88
|
+
return journal
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { createJournal }
|
|
92
|
+
|
|
93
|
+
// EOF
|
|
@@ -26,18 +26,26 @@ const DEFAULT_KEYMAP = [
|
|
|
26
26
|
{ key: "tab", command: "pane.toggle" },
|
|
27
27
|
{ key: "tab", shift: true, command: "pane.toggle" },
|
|
28
28
|
{ key: "space", command: "list.mark" },
|
|
29
|
-
{ key: "b", command: "bookmark.
|
|
30
|
-
{ key: "g", command: "bookmark.jump" },
|
|
31
|
-
{ key: "m", command: "panel.toggle" },
|
|
29
|
+
{ key: "b", command: "bookmark.open" },
|
|
32
30
|
{ key: ":", command: "panel.open" },
|
|
33
|
-
{ key: "!", command: "
|
|
31
|
+
{ key: "!", command: "panel.shell" },
|
|
34
32
|
{ key: "/", command: "filter.start" },
|
|
33
|
+
{ key: "f5", command: "pane.reload" },
|
|
34
|
+
{ key: "r", command: "pane.reload" },
|
|
35
35
|
{ key: "r", ctrl: true, command: "pane.reload" },
|
|
36
36
|
{ key: "v", command: "view.togglePreview" },
|
|
37
|
+
{ key: "v", shift: true, command: "view.maximize" },
|
|
38
|
+
{ key: "t", command: "view.toggleMode" },
|
|
39
|
+
{ key: "t", shift: true, command: "trash.open" },
|
|
40
|
+
{ key: "n", command: "file.mkdir" },
|
|
41
|
+
{ key: "u", command: "history.open" },
|
|
42
|
+
{ key: "z", ctrl: true, command: "history.undo" },
|
|
43
|
+
{ key: "z", ctrl: true, shift: true, command: "history.redo" },
|
|
44
|
+
{ key: "y", ctrl: true, command: "history.redo" },
|
|
37
45
|
{ key: "o", shift: true, command: "file.open" },
|
|
38
46
|
{ key: "e", shift: true, command: "file.edit" },
|
|
39
|
-
{ key: "p", ctrl: true, command: "palette.toggle" },
|
|
40
47
|
{ key: "q", command: "app.quit" },
|
|
48
|
+
{ key: "?", command: "app.help" },
|
|
41
49
|
]
|
|
42
50
|
|
|
43
51
|
// Function: matchKeymap
|
|
@@ -55,6 +63,34 @@ function matchKeymap(keymap, chord) {
|
|
|
55
63
|
return null
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
// Function: keyGlyph
|
|
67
|
+
// Human-readable label for a keymap chord ("↑", "⇧Tab", "^W", "PgUp").
|
|
68
|
+
function keyGlyph(chord) {
|
|
69
|
+
const name = chord.key
|
|
70
|
+
const named = {
|
|
71
|
+
up: "↑",
|
|
72
|
+
down: "↓",
|
|
73
|
+
left: "←",
|
|
74
|
+
right: "→",
|
|
75
|
+
return: "↵",
|
|
76
|
+
enter: "↵",
|
|
77
|
+
space: "Space",
|
|
78
|
+
tab: "Tab",
|
|
79
|
+
pageup: "PgUp",
|
|
80
|
+
pagedown: "PgDn",
|
|
81
|
+
escape: "Esc",
|
|
82
|
+
backspace: "Bksp",
|
|
83
|
+
home: "Home",
|
|
84
|
+
end: "End",
|
|
85
|
+
f5: "F5",
|
|
86
|
+
}
|
|
87
|
+
let base = named[name] ?? (name.length === 1 ? name.toUpperCase() : `${name}`)
|
|
88
|
+
if (chord.ctrl) base = `^${base}`
|
|
89
|
+
if (chord.meta) base = `⌘${base}`
|
|
90
|
+
if (chord.shift) base = `⇧${base}`
|
|
91
|
+
return base
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { DEFAULT_KEYMAP, keyGlyph, matchKeymap }
|
|
59
95
|
|
|
60
96
|
// EOF
|