{"_id":"@acepad/files","name":"@acepad/files","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"scripts":{"test":"run test/test-acepad-files.js"},"bin":{"recents":"recents.js"},"description":"File and session management utilities for acepad.","main":"acepad-files.js","name":"@acepad/files","type":"module","version":"1.0.0","dependencies":{"@hoge1e3/lru":"^1.0.0","@acepad/shell":"^1.0.0","assert":"^1.0.0","petit-node":"^1.0.0","@acepad/mode-shell":"^1.0.0","@acepad/os":"^1.0.0","@acepad/here":"^1.0.0","textmatcher":"^1.0.0","@acepad/debug":"^1.0.0"},"gitHead":"35c559c798e6908047c7bf5b2fe136dd5e5f17af","_id":"@acepad/files@1.0.0","_nodeVersion":"22.17.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-rYkgjyIppR1wwihx1y/QE+98ahc7iEbJBiTI5WkW0tdiU65bdMivFDzO4eQ6xs9DYfO9e4Zz7kGS2n4m+4Ar1Q==","shasum":"6eb9976d127a3969c4549261a72b8bd8a997e6a1","tarball":"https://registry.npmjs.org/@acepad/files/-/files-1.0.0.tgz","fileCount":8,"unpackedSize":27191,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCwPteuiOpF3GbDuMqobNaZ7AtK4YVS/oXFNYgwkYerUgIgNh5R2OU5W4v6fsHdZBSG/F+0iyZdWCe3jnoMM2vFFxs="}]},"_npmUser":{"name":"acepad","email":"pnode.acepad@gmail.com"},"directories":{},"maintainers":[{"name":"acepad","email":"pnode.acepad@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/files_1.0.0_1770625905267_0.7110123251327771"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-09T08:31:45.187Z","1.0.0":"2026-02-09T08:31:45.412Z","modified":"2026-02-09T08:31:45.607Z"},"maintainers":[{"name":"acepad","email":"pnode.acepad@gmail.com"}],"description":"File and session management utilities for acepad.","readme":"NOTE: This package is supporsed to work in [acepad](https://github.com/hoge1e3/acepad-dev), not a regular node envronment.\n\n# @acepad/files\n\nFile and session management utilities for [acepad](https://github.com/hoge1e3/acepad-dev/). This package provides core functionality for opening files, managing editor sessions, directory navigation, and recent file tracking in the browser-based programming environment.\n\n## Features\n\n- **File opening and editing**: Open files and directories in the acepad editor\n- **Session management**: Create and manage editor sessions for files and directory listings\n- **Recent files tracking**: LRU-based tracking of recently accessed files with persistent storage\n- **Directory listings**: Interactive directory views with file operations\n- **Auto-save**: Automatic save on every typing.\n- **Auto-sync**: Automatic synchronization between editor content and file system\n- **Cursor position memory**: Remembers cursor position for each file\n- **Syntax highlighting**: Automatic mode detection based on file extensions\n- **Annotations support**: Display annotations (errors, warnings) in editor sessions(currently only in javascript)\n\n**Note**: This package is designed to run in the acepad/petit-node environment, not in standard Node.js.\n\n## Basic Usage\n\nThe following stuffs are supporsed to operate in [acepad](https://github.com/hoge1e3/acepad-dev).\n\n### Opening Files\n\nThe most common operation is opening files for editing. In acepad, files are automatically opened through the UI, but you can also open them programmatically.\n\nFrom the acepad interface:\n1. Navigate to a directory listing\n2. Press Ent(Enter) on a file name to open it\n3. The file opens in the editor with syntax highlighting\n4. Changes are automatically saved\n\nFrom a script (press F2 to create file and F5 to run):\n\n**Note: The following programs are generated by AI, not tested :-(**\n```js\n#!run\nimport {openFile} from \"@acepad/files\";\n\nexport async function main() {\n    // Open a file in the current directory\n    await openFile(this, \"myfile.js\");\n    \n    // Open a file with specific cursor position\n    await openFile(this, \"config.json\", {row: 10, column: 5});\n    \n    // Open a directory (shows directory listing)\n    await openFile(this, \"./mydir/\");\n}\n```\n\n### Working with Recent Files\n\nAccess your recently opened files:\n\n```js\n#!run\nimport {recents} from \"@acepad/files\";\n\nexport async function main() {\n    // Get list of recent files\n    const recentFiles = recents.list();\n    \n    for (let filePath of recentFiles) {\n        this.echo(filePath);\n    }\n    \n    // Add a file to recents\n    const file = this.resolve(\"important.txt\");\n    recents.add(this, file);\n}\n```\n\nIn the acepad interface:\n- Press **F1** to open the recent files list\n- Use arrow keys to navigate\n- Press Enter to open a file\n\n### Getting the Current File\n\nFind out which file is currently being edited:\n\n```js\n#!run\nimport {current} from \"@acepad/files\";\n\nexport async function main() {\n    const currentFile = current(this);\n    this.echo(`Currently editing: ${currentFile.path()}`);\n    this.echo(`File size: ${currentFile.size()} bytes`);\n}\n```\n\n## Developer Guide\n\n### Core API\n\n#### `openFile(sh, fileOrPath, options?)`\n\nOpens a file or directory in the editor.\n\n**Parameters:**\n- `sh` - Shell object (typically `this` in a command), see [@acepad/shell](https://www.npmjs.com/package/@acepad/shell) for details.\n- `fileOrPath` - File path string or [SFile](https://www.npmjs.com/package/@hoge1e3/sfile) object\n- `options` - Optional settings:\n  - `row` - Cursor row position (1-based)\n  - `column` - Cursor column position (0-based)\n\n**Returns:** Editor session object\n\n**Example:**\n\n```js\nimport {openFile} from \"@acepad/files\";\n\n// Open file at specific position\nawait openFile(sh, \"/home/user/code.js\", {row: 15, column: 8});\n\n// Open using SFile object\nconst file = sh.resolve(\"README.md\");\nawait openFile(sh, file);\n```\n\n**Behavior:**\n- If the file is already open in a session, switches to that session\n- For directories, creates an interactive directory listing\n- Creates new files if they don't exist\n- Restores previous cursor position if no position specified\n- Adds file to recent files list\n- Sets syntax highlighting mode based on file extension\n\n#### `current(sh)`\n\nReturns the SFile object of the currently edited file.\n\n**Parameters:**\n- `sh` - Shell object\n\n**Returns:** SFile object or undefined\n\n**Example:**\n\n```js\nimport {current} from \"@acepad/files\";\n\nconst file = current(sh);\nif (file) {\n    console.log(`Editing: ${file.name()}`);\n}\n```\n\n#### `createDirList(sh, directory)`\n\nCreates an interactive directory listing session.\n\n**Parameters:**\n- `sh` - Shell object\n- `directory` - SFile object pointing to a directory\n\n**Returns:** Editor session object\n\n**Features of directory listings:**\n- Shows files sorted by last modified time\n- Parent directory link (`../`)\n- `new: ` prompt for creating files/directories\n- `sh: ` prompt for executing shell commands\n- Recent shell command history for the directory\n- Keyboard shortcuts:\n  - `F6` - Refresh listing\n  - `F7` - Open parent directory\n  - `Ctrl+T` - Rename file\n  - `Ctrl+E` - Remove file\n  - `Enter` - Open file/execute command\n\n**Example:**\n\n```js\nimport {createDirList} from \"@acepad/files\";\n\nconst dir = sh.resolve(\"/home/user/projects/\");\nconst session = createDirList(sh, dir);\n// The session is automatically displayed in the editor\n```\n\n#### `createSessionListWithRecents(sh)`\n\nCreates a session list showing both open sessions and recent files.\n\n**Parameters:**\n- `sh` - Shell object\n\n**Returns:** Editor session object\n\n**Features:**\n- Shows currently open editor sessions\n- Lists recently accessed files (excluding already open ones)\n- Automatically removes duplicate entries\n- Keyboard shortcuts:\n  - `Enter` - Open selected file/session\n  - `F7` - Open most recent file\n\n**Example:**\n\n```js\nimport {createSessionListWithRecents} from \"@acepad/files\";\n\nconst listSession = createSessionListWithRecents(sh);\n// Press F1 in acepad to see this view\n```\n\n#### `findSessionByFile(file)`\n\nFinds an editor session for a given file.\n\n**Parameters:**\n- `file` - SFile object\n\n**Returns:** Editor session object or undefined\n\n**Example:**\n\n```js\nimport {findSessionByFile} from \"@acepad/files\";\n\nconst file = sh.resolve(\"config.json\");\nconst session = findSessionByFile(file);\n\nif (session) {\n    console.log(\"File is already open\");\n} else {\n    console.log(\"File is not open\");\n}\n```\n\n### Recent Files API\n\nThe `recents` module manages the recent files list with LRU (Least Recently Used) caching.\n\n#### `recents.list()`\n\nReturns array of recent file paths.\n\n```js\nimport {recents} from \"@acepad/files\";\n\nconst files = recents.list();\n// Returns: [\"/path/to/file1.js\", \"/path/to/dir/\", ...]\n```\n\n#### `recents.add(sh, file)`\n\nAdds a file to the recent files list.\n\n**Parameters:**\n- `sh` - Shell object\n- `file` - SFile object\n\n```js\nimport {recents} from \"@acepad/files\";\n\nconst file = sh.resolve(\"important.txt\");\nrecents.add(sh, file);\n```\n\n**Behavior:**\n- Maintains LRU order (most recent first)\n- Limits list to 36 entries\n- Persists to `.acepad/recents.json`\n- Updates submenu data for UI shortcuts\n\n#### `recents.read()`\n\nReads the raw recent files data structure.\n\n**Returns:** Lru object containing recent files\n\n```js\nimport {recents} from \"@acepad/files\";\n\nconst lru = recents.read();\nfor (let entry of lru) {\n    console.log(entry.path);\n}\n```\n\n### Cursor Position Memory\n\nThe `pos` module automatically saves and restores cursor positions.\n\n#### `pos.get(file)`\n\nGets the saved cursor position for a file.\n\n**Parameters:**\n- `file` - SFile object\n\n**Returns:** Object with `{row, column}` (defaults to `{row: 1, column: 1}`)\n\n#### `pos.set(file, {row, column})`\n\nSaves cursor position for a file.\n\n**Parameters:**\n- `file` - SFile object\n- Position object with `row` and `column`\n\n**Storage:** Positions are stored in `.meta/[dir-path]/pos.json`\n\n### Auto-sync Functionality\n\nThe auto-sync system keeps editor content and file system in sync.\n\n```js\nimport {init as initAutoSync} from \"@acepad/files/autoSync.js\";\n\n// Initialize auto-sync for an editor\n// (This is called automatically by openFile)\ninitAutoSync(editor);\n```\n\n**Behavior:**\n- Checks every 100ms for changes\n- If file changes on disk, updates editor content\n- If editor content changes, writes to file\n- Tracks file timestamps to detect external changes\n\n### Annotations\n\nDisplay errors, warnings, or other annotations in the editor.\n\n```js\nimport {setAnnotations} from \"@acepad/files\";\n\n// Set annotations for files\nawait setAnnotations([\n    {\n        file: sh.resolve(\"code.js\"),\n        row: 5,\n        column: 10,\n        text: \"Undefined variable\",\n        type: \"error\"\n    },\n    {\n        file: sh.resolve(\"code.js\"),\n        row: 12,\n        column: 0,\n        text: \"Unused parameter\",\n        type: \"warning\"\n    }\n]);\n```\n\n**Annotation types:**\n- `error` - Red marker\n- `warning` - Yellow marker\n- `info` - Blue marker\n\n### File Extension to Mode Mapping\n\nThe package includes built-in syntax highlighting for common file types:\n\n```js\nimport {modeMap} from \"@acepad/files\";\n\n// View supported extensions\nconsole.log(modeMap);\n// {\n//   \".js\": \"ace/mode/javascript\",\n//   \".html\": \"ace/mode/html\",\n//   \".py\": \"ace/mode/python\",\n//   ...\n// }\n```\n\nSupported file types:\n- JavaScript: `.js`, `.cjs`, `.mjs`\n- TypeScript: `.ts`\n- HTML: `.html`\n- CSS: `.css`\n- JSON: `.json`\n- Python: `.py`\n- C: `.c`\n- PHP: `.php`\n- Tonyu: `.tonyu`\n\nFiles starting with `#!run` or `//!run` automatically use JavaScript mode.\n\n## Advanced Examples\n\n### Creating a File Browser\n\n```js\n#!run\nimport {openFile, createDirList} from \"@acepad/files\";\n\nexport async function main() {\n    const projectDir = this.resolve(\"/home/user/projects/\");\n    \n    if (!projectDir.exists()) {\n        projectDir.mkdir();\n    }\n    \n    // Open directory browser\n    await openFile(this, projectDir);\n}\n```\n\n### File Navigator with Search\n\n```js\n#!run\nimport {recents, openFile} from \"@acepad/files\";\n\nexport async function main(searchTerm) {\n    const recentFiles = recents.list();\n    \n    // Search in recent files\n    const matches = recentFiles.filter(path => \n        path.includes(searchTerm)\n    );\n    \n    if (matches.length === 0) {\n        this.echo(\"No matches found\");\n        return;\n    }\n    \n    if (matches.length === 1) {\n        // Open directly if only one match\n        await openFile(this, matches[0]);\n    } else {\n        // Show matches\n        this.echo(\"Multiple matches:\");\n        matches.forEach((path, i) => {\n            this.echo(`${i + 1}. ${path}`);\n        });\n    }\n}\n```\n\n### Session Management Tool\n\n```js\n#!run\nimport {findSessionByFile} from \"@acepad/files\";\nimport {recentInfos} from \"@acepad/sessions\";\n\nexport async function main() {\n    this.echo(\"Currently open sessions:\");\n    \n    let count = 0;\n    for (let si of recentInfos()) {\n        if (si.file) {\n            this.echo(`  ${si.name} - ${si.file.path()}`);\n            count++;\n        }\n    }\n    \n    this.echo(`Total: ${count} sessions`);\n}\n```\n\n### Working with Cursor Positions\n\n```js\n#!run\nimport * as pos from \"@acepad/files/pos.js\";\n\nexport async function main() {\n    const file = this.resolve(\"mycode.js\");\n    \n    // Save a bookmark\n    pos.set(file, {row: 42, column: 0});\n    this.echo(\"Bookmark saved at line 42\");\n    \n    // Later, retrieve the bookmark\n    const bookmark = pos.get(file);\n    this.echo(`Bookmark: line ${bookmark.row}, column ${bookmark.column}`);\n}\n```\n\n## Directory Structure\n\n```\n@acepad/files/\n├── acepad-files.js    # Main module with file/session operations\n├── recents.js         # Recent files tracking (also a command)\n├── pos.js            # Cursor position memory\n├── autoSync.js       # Auto-sync between editor and file system\n├── annotations.js    # Annotation support\n├── package.json      # Package metadata\n└── test/\n    └── test-acepad-files.js\n```\n\n## Storage Locations\n\nThe package uses the following directories for persistent data:\n\n- **Recent files**: `.acepad/recents.json` (in PNODE_ROOT or detected root)\n- **Submenu cache**: `.acepad/submenus.json`\n- **Cursor positions**: `.meta/[directory]/pos.json` (per directory)\n\nThese files are automatically created and managed by the package.\n\n## Command-line Tool\n\nThe package includes a `recents` command that can be run from the shell:\n\n```bash\nsh: recents\n```\n\nThis displays all recent files and can be used to quickly navigate to them using the `edit` command.\n\n## Integration with acepad\n\nThis package is a core component of acepad and integrates with:\n\n- **@acepad/shell**: File operations and command execution\n- **@acepad/sessions**: Editor session management\n- **@acepad/cursor**: Cursor position tracking\n- **@acepad/mode-shell**: Shell mode for directory listings\n- **ace editor**: Underlying code editor\n\n## Dependencies\n\n- `petit-node`: Browser-based Node.js runtime\n- `@acepad/shell`: Shell environment\n- `@acepad/sessions`: Session management\n- `@acepad/cursor`: Cursor utilities\n- `@acepad/mode-shell`: Shell syntax mode\n- `@acepad/os`: OS utilities\n- `@acepad/here`: Path resolution\n- `@hoge1e3/lru`: LRU cache implementation\n- `textmatcher`: Text pattern matching\n- `@acepad/retry`: Retry utilities\n- `@acepad/debug`: Debug utilities\n\n## License\n\nISC\n\n## See Also\n\n- [acepad](https://hoge1e3.github.io/acepad/) - The acepad programming environment\n- [@acepad/shell](https://www.npmjs.com/package/@acepad/shell) - Shell command system\n- [petit-node](https://www.npmjs.com/package/petit-node) - Browser-based Node.js runtime\n","readmeFilename":"README.md","_rev":"1-e73adc41a9a3b75dbf383623303df44e"}