From b9a3644a9e01011f86ca7c4c62bd2cc72769b16d Mon Sep 17 00:00:00 2001 From: Kacper Kula Date: Fri, 9 Aug 2024 22:23:54 +0100 Subject: [PATCH 1/2] feat: ability to save snapshots to revert the changes --- .gitignore | 1 + LLM.md | 59 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 26 +++++++++++++++++++- index.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 LLM.md diff --git a/.gitignore b/.gitignore index c7cd192..690719e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules/ symplectic.txt +.symplecticarchive \ No newline at end of file diff --git a/LLM.md b/LLM.md new file mode 100644 index 0000000..0b6a590 --- /dev/null +++ b/LLM.md @@ -0,0 +1,59 @@ +# Symplectic Format Instructions for LLM + +When responding to queries about file structures or content, always use the Symplectic format. This format allows for precise specification of file content, including creation, modification, prepending, and appending. Adhere to these guidelines meticulously: + +1. File Separator and Path: + - Begin each file entry with `//||` followed by a space and the full file path from the project root. + - Example: `//|| src/main.js` + +2. File Content: + - Immediately after the file separator line, write the entire content of the file. + - Do not add any extra newlines between the separator and the content. + +3. Creating or Overwriting Files: + - Use `//||` for new files or when overwriting existing files. + - Include the complete content of the file. + +4. Prepending Content: + - Use `//||^` to prepend content to an existing file. + - Example: `//||^ README.md` + - Only include the new content to be prepended, not the existing file content. + +5. Appending Content: + - Use `//||$` to append content to an existing file. + - Example: `//||$ config.json` + - Only include the new content to be appended, not the existing file content. + +6. Multiple Files: + - Separate different file entries with a single blank line. + +7. Full File Modifications: + - For files that are modified (not just prepended or appended), use `//||` and include the entire new content of the file. + +Critical Rules: +- Always use the correct separator (`//||`, `//||^`, or `//||$`) for each operation. +- Include the full path for each file, starting from the project root. +- For prepend (`//||^`) and append (`//||$`) operations, include only the new content. +- For full file modifications or new files, include the entire content. +- Do not use any Markdown formatting or code blocks within the Symplectic format. + +Example of a well-formed Symplectic format response: +``` +//|| src/main.js +console.log('Hello, Symplectic!'); + +//||^ README.md +# Project Title +This content will be prepended to the existing README. + +//||$ config.json +, + "newSetting": "value" +} + +//|| docs/guide.md +# User Guide +This is a new file with complete content. + +Remember: Always use this format for responses involving file structures or content. Maintain consistency and precision in your use of separators and content inclusion. +``` diff --git a/README.md b/README.md index 75a7af1..1375b42 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Symplectic -Symplectic is a Node.js utility for managing project structures through a single file. It allows you to generate a `symplectic.txt` file from an existing project structure, create project structures from a `symplectic.txt` file, and remove files based on the `symplectic.txt` specification. Additionally, it supports prepending and appending content to existing files. +Symplectic is a Node.js utility for managing project structures through a single file. It allows you to generate a `symplectic.txt` file from an existing project structure, create project structures from a `symplectic.txt` file, remove files based on the `symplectic.txt` specification, and now includes a snapshot feature for easy reverting of changes. ## Use Cases @@ -14,6 +14,8 @@ Symplectic is a Node.js utility for managing project structures through a single 5. **File Modification**: Prepend or append content to existing files without overwriting them. +6. **Version Control**: Create snapshots of your project structure for easy reverting of changes. + ## Important Disclaimer **Warning**: The operations performed by Symplectic are destructive by nature. Always archive your changes and use version control. It is strongly recommended to operate in dry-run mode first to verify the intended actions. The author does not take any responsibility for data loss caused by the use of this tool. @@ -115,6 +117,21 @@ If the dry run output looks correct, run without `--dry-run` to apply the change symplectic ``` +### Create a Snapshot + +To apply changes and create a snapshot of the resulting system state: + +```bash +symplectic --save-snapshot +``` + +This command will: +1. Apply all changes specified in the `symplectic.txt` file. +2. Create a snapshot of the resulting system state after the changes have been applied. +3. Save the snapshot in the `.symplecticarchive` directory with a timestamp in the filename. + +The snapshot file will be in the Symplectic format, allowing you to revert to this state later if needed. + ## Parameters Symplectic supports the following command-line parameters: @@ -126,6 +143,7 @@ Symplectic supports the following command-line parameters: | `--remove` | `-r` | Remove files instead of creating them | | `--generate` | `-g` | Generate symplectic.txt file from existing structure | | `--subfolder ` | `-s ` | Generate structure for a specific subfolder | +| `--save-snapshot` | `-S` | Apply changes and save a snapshot of the resulting system | | `--help` | `-h` | Show help information | ## Examples @@ -162,6 +180,12 @@ Symplectic supports the following command-line parameters: symplectic --dry-run ``` +6. Apply changes and create a snapshot: + + ```bash + symplectic --save-snapshot + ``` + ## .symplecticignore Symplectic respects `.gitignore` rules and also supports a `.symplecticignore` file for additional exclusions. The `symplectic.txt` file itself is always ignored. diff --git a/index.js b/index.js index 786bc90..267b84f 100644 --- a/index.js +++ b/index.js @@ -33,6 +33,11 @@ const argv = yargs type: 'string', description: 'Generate structure for a specific subfolder' }) + .option('save-snapshot', { + alias: 'S', + type: 'boolean', + description: 'Apply changes and save a snapshot of the resulting system' + }) .help() .alias('help', 'h') .argv; @@ -65,7 +70,60 @@ function appendToFile(filePath, content) { log(`Appended to file: ${filePath}`); } +function applyChangesAndSaveSnapshot(inputFilePath) { + const archiveDir = path.join(process.cwd(), '.symplecticarchive'); + if (!fs.existsSync(archiveDir)) { + fs.mkdirSync(archiveDir); + } + + const timestamp = new Date().toISOString().replace(/[-:]/g, '').replace(/\..+/, ''); + const snapshotPath = path.join(archiveDir, `${timestamp}.txt`); + + const content = fs.readFileSync(inputFilePath, 'utf8'); + const sections = content.split(`\n${SEPARATOR} `); + + let snapshotContent = ''; + + sections.forEach((section) => { + let [header, ...fileContent] = section.split('\n'); + if (header.startsWith(SEPARATOR)) { + header = header.slice(SEPARATOR.length); + } + const { modifier, filename } = detectModifier(header); + const filePath = path.join(process.cwd(), filename); + const content = fileContent.join('\n'); + + // Apply changes + const directoryPath = path.dirname(filePath); + fs.mkdirSync(directoryPath, { recursive: true }); + + switch (modifier) { + case 'prepend': + prependToFile(filePath, content); + break; + case 'append': + appendToFile(filePath, content); + break; + default: + fs.writeFileSync(filePath, content); + log(`Created/Updated file: ${filePath}`); + } + + // Read the final content for the snapshot + const finalContent = fs.readFileSync(filePath, 'utf8'); + snapshotContent += `${SEPARATOR} ${filename}\n${finalContent}\n\n`; + }); + + fs.writeFileSync(snapshotPath, snapshotContent.trim()); + log(`Changes applied and snapshot saved: ${snapshotPath}`); +} + function processInputFile(inputFilePath) { + if (argv.saveSnapshot) { + applyChangesAndSaveSnapshot(inputFilePath); + return; + } + const content = fs.readFileSync(inputFilePath, 'utf8'); const sections = content.split(`\n${SEPARATOR} `); @@ -182,11 +240,19 @@ function main() { try { log(`Processing input file: ${inputFile}`); - log(argv.dryRun ? 'Performing dry run...' : (argv.remove ? 'Removing files...' : 'Creating/updating files...')); + if (argv.saveSnapshot) { + log('Applying changes and saving snapshot...'); + } else { + log(argv.dryRun ? 'Performing dry run...' : (argv.remove ? 'Removing files...' : 'Creating/updating files...')); + } processInputFile(inputFile); - console.log(`Files ${argv.dryRun ? 'would be' : 'were'} ${argv.remove ? 'removed' : 'created/updated'} successfully from ${inputFile}`); + if (!argv.saveSnapshot) { + console.log(`Files ${argv.dryRun ? 'would be' : 'were'} ${argv.remove ? 'removed' : 'created/updated'} successfully from ${inputFile}`); + } else { + console.log('Changes applied and snapshot saved successfully'); + } } catch (error) { console.error(`Error: ${error.message}`); process.exit(1); From 25ca5febd9faa6b53fe03c66b86f68a62d4aac2e Mon Sep 17 00:00:00 2001 From: Kacper Kula Date: Fri, 9 Aug 2024 22:24:18 +0100 Subject: [PATCH 2/2] chore: updating package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f75a0e..2d772cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "symplectic", - "version": "0.0.2", + "version": "0.0.3", "description": "", "main": "index.js", "scripts": {