Repository navigation
feat(runtime): add document lifecycle commands and exact-byte persistence path #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
762aba7
7f6055a
2cebb5c
3f96ab1
d36df04
d1fb213
94adff1
073c10d
c3c5571
222a930
51bb49b
f6703c8
d053596
84379cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -110,6 +110,76 @@ function M.register(runtime) | |
| end, { | ||
| description = "Replace a byte range through the document Host API", | ||
| }) | ||
|
|
||
| commands:register("document.new", function(_, args) | ||
| local initial_bytes = args.initial_bytes | ||
| if initial_bytes == nil then initial_bytes = "" end | ||
| if type(initial_bytes) ~= "string" then | ||
| errors.raise("INVALID_ARGUMENT", "document.new initial_bytes must be a byte string") | ||
| end | ||
| if args.path ~= nil and (type(args.path) ~= "string" or args.path == "") then | ||
| errors.raise("INVALID_ARGUMENT", "document.new path must be a non-empty string") | ||
| end | ||
| local document = runtime:open_document(initial_bytes, { path = args.path }) | ||
| local ok, view = pcall(runtime._create_view, runtime, document.id, nil, false) | ||
| if not ok then | ||
| pcall(runtime.close_document, runtime, document.id) | ||
| error(errors.normalize(view, "INTERNAL", "create document view"), 0) | ||
| end | ||
| return { document_id = document.id, view_id = view.id, version = document.version } | ||
| end, { | ||
| description = "Create an empty or byte-initialized document and focus its first view", | ||
| }) | ||
|
|
||
| commands:register("document.open", function(_, args) | ||
| if type(args.path) ~= "string" or args.path == "" then | ||
| errors.raise("INVALID_ARGUMENT", "document.open requires a non-empty path") | ||
| end | ||
| local fs = runtime.host.fs | ||
| if type(fs) ~= "table" or type(fs.read_file) ~= "function" then | ||
| errors.raise("UNSUPPORTED", "Backend Host does not provide bounded file reads") | ||
| end | ||
| local bytes = fs:read_file(args.path, { max_bytes = args.max_bytes }) | ||
| if type(bytes) ~= "string" then | ||
| errors.raise("INTERNAL", "Backend Host file read did not return a byte string") | ||
| end | ||
| local document = runtime:open_document(bytes, { path = args.path }) | ||
| local ok, view = pcall(runtime._create_view, runtime, document.id, nil, false) | ||
| if not ok then | ||
| pcall(runtime.close_document, runtime, document.id) | ||
| error(errors.normalize(view, "INTERNAL", "create opened document view"), 0) | ||
| end | ||
| runtime.log:info("document opened", { | ||
| document_id = document.id, | ||
| version = document.version, | ||
| bytes = document.length, | ||
| }) | ||
| return { document_id = document.id, view_id = view.id, version = document.version } | ||
| end, { | ||
| description = "Open exact file bytes through the optional Backend Host filesystem service", | ||
| }) | ||
|
|
||
| commands:register("document.close", function(context) | ||
| local document = active_document(runtime, context) | ||
| if not document then | ||
| return false, "no active document" | ||
| end | ||
| return runtime:_close_document(document.id, false) | ||
| end, { | ||
| description = "Close the focused document and remove its views", | ||
| available = function(context) | ||
| return context.document ~= nil or runtime:focused_document() ~= nil | ||
| end, | ||
| }) | ||
|
|
||
| -- FE-016 / PROTO-041: default editing shortcuts are Runtime policy. The | ||
| -- Frontend emits raw key events and never duplicates or interprets bindings. | ||
| runtime.keymap:bind("ctrl+n", "document.new", { owner = "core" }) | ||
| runtime.keymap:bind("ctrl+s", "document.save", { owner = "core" }) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For a path-backed document on a Host without Useful? React with 👍 / 👎. |
||
| runtime.keymap:bind("ctrl+z", "document.undo", { owner = "core" }) | ||
| runtime.keymap:bind("ctrl+shift+z", "document.redo", { owner = "core" }) | ||
| runtime.keymap:bind("ctrl+w", "document.close", { owner = "core" }) | ||
|
|
||
| end | ||
|
|
||
| return M | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a document has unsaved edits, invoking this new command (including the newly bound Ctrl+W) unconditionally closes its Kernel handle and removes its views; no dirty-state check or confirmation runs, so the only canonical copy of those edits is discarded without a save/cancel choice. Guard dirty closes with a confirmation or explicit discard path rather than closing immediately.
AGENTS.md reference: AGENTS.md:L8-L9
Useful? React with 👍 / 👎.