feat: F4.6f2 the text editor on the document's Y.Text, files both ways while the simulation runs
Oracle TextEditorWindowRun uses Java's text editor window and its file dialog as a person does. The open file's text is its Y.Text in the document (plan 7.3): typed is in the file at once, for everyone and for the running engine. Core openText/saveTextAs without Java's mistakes (lost saves after save-as onto a file or a removed file, files named 'ordner/d.txt' or ''); doc files.ts (changeFiles, fileText, nodeFiles, readFilesInto); the room takes a person's files into the engine at once and writes the engine's files back at the tick they changed; the editor's window, Java's dialog, the text area following others' changes with the caret in place, its own undo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,11 @@
|
||||
// file system's rule), and one that changes only the case is done (Java
|
||||
// finds the entry itself and refuses);
|
||||
// - "save as" onto a folder's name, and an import onto it, is refused (Java
|
||||
// throws);
|
||||
// throws); "save as" with an empty name, or one with blanks at its ends,
|
||||
// is refused (Java makes such a file), a name with "/" leads into a
|
||||
// folder (Java makes a file whose name holds the separator);
|
||||
// - "open" opens text files only (Java shows an image as its Base64 text)
|
||||
// and keeps the open file when it finds none (Java forgets it);
|
||||
// - a text file's size is its length in characters (as the command line's).
|
||||
|
||||
import type { VirtualFileContent, VirtualFileSystem } from '../../model/virtualFileSystem.js';
|
||||
@@ -223,15 +227,38 @@ export function saveText(files: VirtualFileSystem, path: string, text: string):
|
||||
/**
|
||||
* The editor's "save as" (Dateisystem.speicherDatei): the text as a file of
|
||||
* the folder, over one of that name in any case (its name kept as it is).
|
||||
* The name may lead into a folder of the folder ("ordner/d.txt", as "open"
|
||||
* takes it; Java makes a file with "/" in its name); a name the file system
|
||||
* does not take (empty, or with blanks at its ends; Java makes such a file)
|
||||
* is invalidName, one whose folder is not there folderMissing.
|
||||
*/
|
||||
export function saveTextAs(files: VirtualFileSystem, folder: string, name: string, text: string): 'saved' | 'folderMissing' | 'isFolder' {
|
||||
export function saveTextAs(files: VirtualFileSystem, folder: string, name: string, text: string): 'saved' | 'folderMissing' | 'isFolder' | 'invalidName' {
|
||||
if (name.split('/').some((part) => part.trim() !== part) || evaluatedPath(name) === '/') return 'invalidName';
|
||||
const target = fileTarget(files, folder, name);
|
||||
if (target === undefined) return 'folderMissing';
|
||||
if (target.isFolder) return 'isFolder';
|
||||
files.writeTextFile(target.path, text);
|
||||
try {
|
||||
files.writeTextFile(target.path, text);
|
||||
} catch {
|
||||
return 'folderMissing';
|
||||
}
|
||||
return 'saved';
|
||||
}
|
||||
|
||||
/**
|
||||
* The editor's "open" (holeDatei of the dialog's folder and name): the name
|
||||
* taken as a path from the folder, in any case. Java opens whatever file it
|
||||
* finds, an image as its Base64 text, and with none forgets the open file;
|
||||
* here a file that is not text is notText, none notFound (the open file
|
||||
* stays open).
|
||||
*/
|
||||
export function openText(files: VirtualFileSystem, folder: string, name: string): { readonly path: string; readonly text: string } | 'notFound' | 'notText' {
|
||||
// No name is the folder itself: not found.
|
||||
const entry = found(files, evaluatedPath(name.startsWith('/') ? name : `${folder}/${name}`));
|
||||
if (entry === undefined || entry.content.kind === 'directory') return 'notFound';
|
||||
return entry.content.kind === 'text' ? { path: entry.path, text: entry.content.text } : 'notText';
|
||||
}
|
||||
|
||||
/** The image viewer's "open": an image file's bytes and media type; none for any other file. */
|
||||
export function imageFile(files: VirtualFileSystem, path: string): { readonly data: Uint8Array; readonly mediaType: string } | undefined {
|
||||
const entry = found(files, path);
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
renameEntry,
|
||||
saveText,
|
||||
saveTextAs,
|
||||
openText,
|
||||
VirtualFileSystem,
|
||||
type Clipboard,
|
||||
type PageLanguage,
|
||||
@@ -238,4 +239,30 @@ describe('the file programs beyond the cases', () => {
|
||||
expect(imageFile(files, '/text.txt')).toBeUndefined();
|
||||
expect(imageFile(files, '/fehlt.png')).toBeUndefined();
|
||||
});
|
||||
|
||||
// Measured with TextEditorWindowRun (packages/sim/test/textEditorWindow.java.json).
|
||||
it("opens a text file by the dialog's folder and name, in any case, and neither an image nor what is not there", () => {
|
||||
const files = new VirtualFileSystem();
|
||||
files.writeTextFile('/notiz.txt', 'Hallo');
|
||||
files.createDirectory('/ordner');
|
||||
files.writeTextFile('/ordner/b.txt', '');
|
||||
files.writeImageFile('/bild.png', new Uint8Array([1]), 'image/png');
|
||||
expect(openText(files, '/', 'NOTIZ.TXT')).toEqual({ path: '/notiz.txt', text: 'Hallo' });
|
||||
expect(openText(files, '/', 'ordner/b.txt')).toEqual({ path: '/ordner/b.txt', text: '' });
|
||||
expect(openText(files, '/ordner', '../notiz.txt')).toEqual({ path: '/notiz.txt', text: 'Hallo' });
|
||||
expect(openText(files, '/ordner', '/notiz.txt')).toEqual({ path: '/notiz.txt', text: 'Hallo' });
|
||||
expect(['fehlt.txt', '', 'ordner'].map((name) => openText(files, '/', name))).toEqual(['notFound', 'notFound', 'notFound']);
|
||||
expect(openText(files, '/', 'bild.png')).toBe('notText');
|
||||
});
|
||||
|
||||
it('saves as a name leading into a folder, and not as an empty name, one with blanks at its ends or one whose folder is missing', () => {
|
||||
const files = new VirtualFileSystem();
|
||||
files.createDirectory('/ordner');
|
||||
expect(saveTextAs(files, '/', 'ordner/d.txt', 'd')).toBe('saved');
|
||||
expect(files.textFile('/ordner/d.txt')).toBe('d');
|
||||
expect(['', ' x.txt', 'x.txt ', 'ordner/ e.txt', '..'].map((name) => saveTextAs(files, '/ordner', name, 'x'))).toEqual(['invalidName', 'invalidName', 'invalidName', 'invalidName', 'invalidName']);
|
||||
expect(saveTextAs(files, '/', 'fehlt/e.txt', 'e')).toBe('folderMissing');
|
||||
expect(saveTextAs(files, '/', 'ORDNER', 'e')).toBe('isFolder');
|
||||
expect(files.allEntries().map((entry) => entry.path)).toEqual(['/', '/ordner', '/ordner/d.txt']);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user