make-folder-txt 2.0.1 → 2.1.0

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 CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  Perfect for sharing your codebase with **AI tools**, **teammates**, or **code reviewers** — without zipping files or giving repo access.
13
13
 
14
- [Installation](#-installation) · [Usage](#-usage) · [Help](#-get-help) · [Copy to Clipboard](#-copy-to-clipboard) · [Force Include Everything](#-force-include-everything) · [Shell Autocompletion](#-shell-autocompletion) · [Output Format](#-output-format) · [What Gets Skipped](#-what-gets-skipped) · [Contributing](#-contributing)
14
+ [Installation](#-installation) · [Usage](#-usage) · [Help](#-get-help) · [Copy to Clipboard](#-copy-to-clipboard) · [Force Include Everything](#-force-include-everything) · [Shell Autocompletion](#-shell-autocompletion) · [File Size Control](#-file-size-control) · [Output Splitting](#-output-splitting) · [Output Format](#-output-format) · [What Gets Skipped](#-what-gets-skipped) · [Contributing](#-contributing)
15
15
 
16
16
  </div>
17
17
 
@@ -24,6 +24,8 @@ Ever needed to share your entire project with ChatGPT, Claude, or a teammate —
24
24
  - ✅ Run it from any project directory — no arguments needed
25
25
  - ✅ Built-in help system with `--help` flag
26
26
  - ✅ **Built-in shell autocompletion** (installs automatically)
27
+ - ✅ **File size control** with `--skip-large` and `--no-skip`
28
+ - ✅ **Output splitting** by folders, files, or size
27
29
  - ✅ Copy to clipboard with `--copy` flag
28
30
  - ✅ Force include everything with `--force` flag
29
31
  - ✅ Generates a clean folder tree + every file's content
@@ -133,6 +135,76 @@ notepad $PROFILE
133
135
 
134
136
  The completion works out of the box - just run the tool once and restart your terminal!
135
137
 
138
+ ### 📏 File Size Control
139
+
140
+ ```bash
141
+ make-folder-txt --skip-large 400KB # Skip files larger than 400KB
142
+ make-folder-txt --skip-large 5GB # Skip files larger than 5GB
143
+ make-folder-txt --skip-large 1.5MB # Skip files larger than 1.5MB
144
+ make-folder-txt --no-skip # Include all files regardless of size
145
+ ```
146
+
147
+ **Default behavior**: Files larger than 500KB are skipped by default.
148
+
149
+ **Supported size units**:
150
+ - **B** - Bytes
151
+ - **KB** - Kilobytes (1024 bytes)
152
+ - **MB** - Megabytes (1024 KB)
153
+ - **GB** - Gigabytes (1024 MB)
154
+ - **TB** - Terabytes (1024 GB)
155
+
156
+ **Examples:**
157
+ ```bash
158
+ # More restrictive - skip anything over 100KB
159
+ make-folder-txt --skip-large 100KB
160
+
161
+ # More permissive - allow files up to 10MB
162
+ make-folder-txt --skip-large 10MB
163
+
164
+ # Include everything - no size limits
165
+ make-folder-txt --no-skip
166
+
167
+ # Combine with other options
168
+ make-folder-txt --skip-large 2MB --ignore-folder node_modules
169
+ ```
170
+
171
+ **Size format**: Accepts decimal numbers (e.g., `1.5MB`, `0.5GB`) and various units.
172
+
173
+ ### 📂 Output Splitting
174
+
175
+ ```bash
176
+ make-folder-txt --split-method folder # Split by folders
177
+ make-folder-txt --split-method file # Split by files
178
+ make-folder-txt --split-method size --split-size 5MB # Split by file size
179
+ ```
180
+
181
+ **Split Methods:**
182
+ - **`folder`** - Creates separate files for each folder
183
+ - **`file`** - Creates separate files for each individual file
184
+ - **`size`** - Splits output when content exceeds specified size
185
+
186
+ **Examples:**
187
+ ```bash
188
+ # Split by folders - creates folder-name.txt for each folder
189
+ make-folder-txt --split-method folder
190
+
191
+ # Split by files - creates filename.txt for each file
192
+ make-folder-txt --split-method file
193
+
194
+ # Split by size - creates part-1.txt, part-2.txt, etc.
195
+ make-folder-txt --split-method size --split-size 5MB
196
+
197
+ # Combine with other options
198
+ make-folder-txt --split-method size --split-size 2MB --ignore-folder node_modules
199
+ ```
200
+
201
+ **Output Files:**
202
+ - **Folder method**: `projectname-foldername.txt`
203
+ - **File method**: `projectname-filename.txt`
204
+ - **Size method**: `projectname-part-1.txt`, `projectname-part-2.txt`, etc.
205
+
206
+ **Note**: Splitting is not compatible with `--copy` flag.
207
+
136
208
  Ignore specific folders/files by name:
137
209
 
138
210
  ```bash
@@ -179,13 +179,37 @@ function collectFiles(
179
179
  return { lines, filePaths, hasIncluded: filePaths.length > 0 || lines.length > 0 };
180
180
  }
181
181
 
182
- function readContent(absPath, force = false) {
182
+ function parseFileSize(sizeStr) {
183
+ const units = {
184
+ 'B': 1,
185
+ 'KB': 1024,
186
+ 'MB': 1024 * 1024,
187
+ 'GB': 1024 * 1024 * 1024,
188
+ 'TB': 1024 * 1024 * 1024 * 1024
189
+ };
190
+
191
+ const match = sizeStr.match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB|TB)$/i);
192
+ if (!match) {
193
+ console.error(`Error: Invalid size format "${sizeStr}". Use format like "500KB", "2MB", "1GB".`);
194
+ process.exit(1);
195
+ }
196
+
197
+ const value = parseFloat(match[1]);
198
+ const unit = match[2].toUpperCase();
199
+ return Math.floor(value * units[unit]);
200
+ }
201
+
202
+ function readContent(absPath, force = false, maxFileSize = 500 * 1024) {
183
203
  const ext = path.extname(absPath).toLowerCase();
184
204
  if (!force && BINARY_EXTS.has(ext)) return "[binary / skipped]";
185
205
  try {
186
206
  const stat = fs.statSync(absPath);
187
- if (!force && stat.size > 500 * 1024) {
188
- return `[file too large: ${(stat.size / 1024).toFixed(1)} KB skipped]`;
207
+ if (!force && stat.size > maxFileSize) {
208
+ const sizeStr = stat.size < 1024 ? `${stat.size} B` :
209
+ stat.size < 1024 * 1024 ? `${(stat.size / 1024).toFixed(1)} KB` :
210
+ stat.size < 1024 * 1024 * 1024 ? `${(stat.size / (1024 * 1024)).toFixed(1)} MB` :
211
+ `${(stat.size / (1024 * 1024 * 1024)).toFixed(1)} GB`;
212
+ return `[file too large: ${sizeStr} – skipped]`;
189
213
  }
190
214
  return fs.readFileSync(absPath, "utf8");
191
215
  } catch (err) {
@@ -193,6 +217,238 @@ function readContent(absPath, force = false) {
193
217
  }
194
218
  }
195
219
 
220
+ function splitByFolders(treeLines, filePaths, rootName, effectiveMaxSize, forceFlag) {
221
+ const folders = new Map();
222
+
223
+ // Group files by folder
224
+ filePaths.forEach(({ abs, rel }) => {
225
+ const folderPath = path.dirname(rel);
226
+ const folderKey = folderPath === '/' ? rootName : folderPath.slice(1);
227
+
228
+ if (!folders.has(folderKey)) {
229
+ folders.set(folderKey, []);
230
+ }
231
+ folders.get(folderKey).push({ abs, rel });
232
+ });
233
+
234
+ const results = [];
235
+
236
+ folders.forEach((files, folderName) => {
237
+ const out = [];
238
+ const divider = "=".repeat(80);
239
+ const subDivider = "-".repeat(80);
240
+
241
+ out.push(divider);
242
+ out.push(`START OF FOLDER: ${folderName}`);
243
+ out.push(divider);
244
+ out.push("");
245
+
246
+ // Add folder structure (only this folder's structure)
247
+ const folderTreeLines = treeLines.filter(line =>
248
+ line.includes(folderName + '/') || line === `${rootName}/`
249
+ );
250
+
251
+ out.push(divider);
252
+ out.push("PROJECT STRUCTURE");
253
+ out.push(divider);
254
+ out.push(`Root: ${folderPath}\n`);
255
+ out.push(`${rootName}/`);
256
+ folderTreeLines.forEach(l => out.push(l));
257
+ out.push("");
258
+ out.push(`Total files in this folder: ${files.length}`);
259
+ out.push("");
260
+
261
+ out.push(divider);
262
+ out.push("FILE CONTENTS");
263
+ out.push(divider);
264
+
265
+ files.forEach(({ abs, rel }) => {
266
+ out.push("");
267
+ out.push(subDivider);
268
+ out.push(`FILE: ${rel}`);
269
+ out.push(subDivider);
270
+ out.push(readContent(abs, forceFlag, effectiveMaxSize));
271
+ });
272
+
273
+ out.push("");
274
+ out.push(divider);
275
+ out.push(`END OF FOLDER: ${folderName}`);
276
+ out.push(divider);
277
+
278
+ const fileName = `${rootName}-${folderName.replace(/[\/\\]/g, '-')}.txt`;
279
+ const filePath = path.join(process.cwd(), fileName);
280
+
281
+ fs.writeFileSync(filePath, out.join("\n"), "utf8");
282
+ const sizeKB = (fs.statSync(filePath).size / 1024).toFixed(1);
283
+
284
+ results.push({
285
+ file: filePath,
286
+ size: sizeKB,
287
+ files: files.length,
288
+ folder: folderName
289
+ });
290
+ });
291
+
292
+ return results;
293
+ }
294
+
295
+ function splitByFiles(filePaths, rootName, effectiveMaxSize, forceFlag) {
296
+ const results = [];
297
+
298
+ filePaths.forEach(({ abs, rel }) => {
299
+ const out = [];
300
+ const divider = "=".repeat(80);
301
+ const subDivider = "-".repeat(80);
302
+ const fileName = path.basename(rel, path.extname(rel));
303
+
304
+ out.push(divider);
305
+ out.push(`FILE: ${rel}`);
306
+ out.push(divider);
307
+ out.push("");
308
+
309
+ out.push(divider);
310
+ out.push("FILE CONTENTS");
311
+ out.push(divider);
312
+ out.push(readContent(abs, forceFlag, effectiveMaxSize));
313
+
314
+ out.push("");
315
+ out.push(divider);
316
+ out.push(`END OF FILE: ${rel}`);
317
+ out.push(divider);
318
+
319
+ const outputFileName = `${rootName}-${fileName}.txt`;
320
+ const filePath = path.join(process.cwd(), outputFileName);
321
+
322
+ fs.writeFileSync(filePath, out.join("\n"), "utf8");
323
+ const sizeKB = (fs.statSync(filePath).size / 1024).toFixed(1);
324
+
325
+ results.push({
326
+ file: filePath,
327
+ size: sizeKB,
328
+ files: 1,
329
+ fileName: fileName
330
+ });
331
+ });
332
+
333
+ return results;
334
+ }
335
+
336
+ function splitBySize(treeLines, filePaths, rootName, splitSize, effectiveMaxSize, forceFlag) {
337
+ const results = [];
338
+ let currentPart = 1;
339
+ let currentSize = 0;
340
+ let currentFiles = [];
341
+
342
+ const divider = "=".repeat(80);
343
+ const subDivider = "-".repeat(80);
344
+
345
+ // Start with header
346
+ let out = [];
347
+ out.push(divider);
348
+ out.push(`START OF FOLDER: ${rootName} (Part ${currentPart})`);
349
+ out.push(divider);
350
+ out.push("");
351
+
352
+ out.push(divider);
353
+ out.push("PROJECT STRUCTURE");
354
+ out.push(divider);
355
+ out.push(`Root: ${folderPath}\n`);
356
+ out.push(`${rootName}/`);
357
+ treeLines.forEach(l => out.push(l));
358
+ out.push("");
359
+ out.push(`Total files: ${filePaths.length}`);
360
+ out.push("");
361
+
362
+ out.push(divider);
363
+ out.push("FILE CONTENTS");
364
+ out.push(divider);
365
+
366
+ filePaths.forEach(({ abs, rel }) => {
367
+ const content = readContent(abs, forceFlag, effectiveMaxSize);
368
+ const fileContent = [
369
+ "",
370
+ subDivider,
371
+ `FILE: ${rel}`,
372
+ subDivider,
373
+ content
374
+ ];
375
+
376
+ const contentSize = fileContent.join("\n").length;
377
+
378
+ // Check if adding this file would exceed the split size
379
+ if (currentSize + contentSize > splitSize && currentFiles.length > 0) {
380
+ // Finish current part
381
+ out.push("");
382
+ out.push(divider);
383
+ out.push(`END OF FOLDER: ${rootName} (Part ${currentPart})`);
384
+ out.push(divider);
385
+
386
+ // Write current part
387
+ const fileName = `${rootName}-part-${currentPart}.txt`;
388
+ const filePath = path.join(process.cwd(), fileName);
389
+ fs.writeFileSync(filePath, out.join("\n"), "utf8");
390
+ const sizeKB = (fs.statSync(filePath).size / 1024).toFixed(1);
391
+
392
+ results.push({
393
+ file: filePath,
394
+ size: sizeKB,
395
+ files: currentFiles.length,
396
+ part: currentPart
397
+ });
398
+
399
+ // Start new part
400
+ currentPart++;
401
+ currentSize = 0;
402
+ currentFiles = [];
403
+
404
+ out = [];
405
+ out.push(divider);
406
+ out.push(`START OF FOLDER: ${rootName} (Part ${currentPart})`);
407
+ out.push(divider);
408
+ out.push("");
409
+
410
+ out.push(divider);
411
+ out.push("PROJECT STRUCTURE");
412
+ out.push(divider);
413
+ out.push(`Root: ${folderPath}\n`);
414
+ out.push(`${rootName}/`);
415
+ treeLines.forEach(l => out.push(l));
416
+ out.push("");
417
+ out.push(`Total files: ${filePaths.length}`);
418
+ out.push("");
419
+
420
+ out.push(divider);
421
+ out.push("FILE CONTENTS");
422
+ out.push(divider);
423
+ }
424
+
425
+ // Add file to current part
426
+ out.push(...fileContent);
427
+ currentSize += contentSize;
428
+ currentFiles.push(rel);
429
+ });
430
+
431
+ // Write final part
432
+ out.push("");
433
+ out.push(divider);
434
+ out.push(`END OF FOLDER: ${rootName} (Part ${currentPart})`);
435
+ out.push(divider);
436
+
437
+ const fileName = `${rootName}-part-${currentPart}.txt`;
438
+ const filePath = path.join(process.cwd(), fileName);
439
+ fs.writeFileSync(filePath, out.join("\n"), "utf8");
440
+ const sizeKB = (fs.statSync(filePath).size / 1024).toFixed(1);
441
+
442
+ results.push({
443
+ file: filePath,
444
+ size: sizeKB,
445
+ files: currentFiles.length,
446
+ part: currentPart
447
+ });
448
+
449
+ return results;
450
+ }
451
+
196
452
  // ── main ──────────────────────────────────────────────────────────────────────
197
453
 
198
454
  const args = process.argv.slice(2);
@@ -415,6 +671,10 @@ Dump an entire project folder into a single readable .txt file.
415
671
  --ignore-file, -ifi <names...> Ignore specific files by name
416
672
  --only-folder, -ofo <names...> Include only specific folders
417
673
  --only-file, -ofi <names...> Include only specific files
674
+ --skip-large <size> Skip files larger than specified size (default: 500KB)
675
+ --no-skip Include all files regardless of size
676
+ --split-method <method> Split output: folder, file, or size
677
+ --split-size <size> Split output when size exceeds limit (requires --split-method size)
418
678
  --copy Copy output to clipboard
419
679
  --force Include everything (overrides all ignore patterns)
420
680
  --install-completion Install shell autocompletion (bash/zsh/PowerShell) - usually automatic
@@ -425,6 +685,12 @@ Dump an entire project folder into a single readable .txt file.
425
685
  make-folder-txt
426
686
  make-folder-txt --copy
427
687
  make-folder-txt --force
688
+ make-folder-txt --skip-large 400KB
689
+ make-folder-txt --skip-large 5GB
690
+ make-folder-txt --no-skip
691
+ make-folder-txt --split-method folder
692
+ make-folder-txt --split-method file
693
+ make-folder-txt --split-method size --split-size 5MB
428
694
  make-folder-txt --install-completion
429
695
  make-folder-txt --ignore-folder node_modules dist
430
696
  make-folder-txt -ifo node_modules dist
@@ -456,6 +722,10 @@ const onlyFiles = new Set();
456
722
  let outputArg = null;
457
723
  let copyToClipboardFlag = false;
458
724
  let forceFlag = false;
725
+ let maxFileSize = 500 * 1024; // Default 500KB
726
+ let noSkipFlag = false;
727
+ let splitMethod = null; // 'folder', 'file', 'size'
728
+ let splitSize = null; // size in bytes
459
729
 
460
730
  for (let i = 0; i < args.length; i += 1) {
461
731
  const arg = args[i];
@@ -470,6 +740,81 @@ for (let i = 0; i < args.length; i += 1) {
470
740
  continue;
471
741
  }
472
742
 
743
+ if (arg === "--no-skip") {
744
+ noSkipFlag = true;
745
+ continue;
746
+ }
747
+
748
+ if (arg === "--skip-large") {
749
+ if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
750
+ console.error("Error: --skip-large requires a size value (e.g., 400KB, 5GB).");
751
+ process.exit(1);
752
+ }
753
+ maxFileSize = parseFileSize(args[i + 1]);
754
+ i += 1;
755
+ continue;
756
+ }
757
+
758
+ if (arg.startsWith("--skip-large=")) {
759
+ const value = arg.slice("--skip-large=".length);
760
+ if (!value) {
761
+ console.error("Error: --skip-large requires a size value (e.g., 400KB, 5GB).");
762
+ process.exit(1);
763
+ }
764
+ maxFileSize = parseFileSize(value);
765
+ continue;
766
+ }
767
+
768
+ if (arg === "--split-method") {
769
+ if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
770
+ console.error("Error: --split-method requires a method (folder, file, or size).");
771
+ process.exit(1);
772
+ }
773
+ const method = args[i + 1].toLowerCase();
774
+ if (!['folder', 'file', 'size'].includes(method)) {
775
+ console.error("Error: --split-method must be one of: folder, file, size");
776
+ process.exit(1);
777
+ }
778
+ splitMethod = method;
779
+ i += 1;
780
+ continue;
781
+ }
782
+
783
+ if (arg.startsWith("--split-method=")) {
784
+ const value = arg.slice("--split-method=".length);
785
+ if (!value) {
786
+ console.error("Error: --split-method requires a method (folder, file, or size).");
787
+ process.exit(1);
788
+ }
789
+ const method = value.toLowerCase();
790
+ if (!['folder', 'file', 'size'].includes(method)) {
791
+ console.error("Error: --split-method must be one of: folder, file, size");
792
+ process.exit(1);
793
+ }
794
+ splitMethod = method;
795
+ continue;
796
+ }
797
+
798
+ if (arg === "--split-size") {
799
+ if (i + 1 >= args.length || args[i + 1].startsWith("-")) {
800
+ console.error("Error: --split-size requires a size value (e.g., 5MB, 10MB).");
801
+ process.exit(1);
802
+ }
803
+ splitSize = parseFileSize(args[i + 1]);
804
+ i += 1;
805
+ continue;
806
+ }
807
+
808
+ if (arg.startsWith("--split-size=")) {
809
+ const value = arg.slice("--split-size=".length);
810
+ if (!value) {
811
+ console.error("Error: --split-size requires a size value (e.g., 5MB, 10MB).");
812
+ process.exit(1);
813
+ }
814
+ splitSize = parseFileSize(value);
815
+ continue;
816
+ }
817
+
473
818
  if (arg === "--ignore-folder" || arg === "-ifo") {
474
819
  let consumed = 0;
475
820
  while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
@@ -588,6 +933,17 @@ for (let i = 0; i < args.length; i += 1) {
588
933
  process.exit(1);
589
934
  }
590
935
 
936
+ // Validate split options
937
+ if (splitMethod === 'size' && !splitSize) {
938
+ console.error("Error: --split-method size requires --split-size to be specified.");
939
+ process.exit(1);
940
+ }
941
+
942
+ if (splitSize && splitMethod !== 'size') {
943
+ console.error("Error: --split-size can only be used with --split-method size.");
944
+ process.exit(1);
945
+ }
946
+
591
947
  const folderPath = process.cwd();
592
948
  const rootName = path.basename(folderPath);
593
949
 
@@ -611,7 +967,47 @@ const { lines: treeLines, filePaths } = collectFiles(
611
967
  { hasOnlyFilters, rootName, txtIgnore, force: forceFlag },
612
968
  );
613
969
 
614
- // ── build output ──────────────────────────────────────────────────────────────
970
+ // ── handle splitting ──────────────────────────────────────────────────────────────
971
+ const effectiveMaxSize = noSkipFlag ? Infinity : maxFileSize;
972
+
973
+ if (splitMethod) {
974
+ console.log(`🔧 Splitting output by: ${splitMethod}`);
975
+
976
+ let results;
977
+
978
+ if (splitMethod === 'folder') {
979
+ results = splitByFolders(treeLines, filePaths, rootName, effectiveMaxSize, forceFlag);
980
+ } else if (splitMethod === 'file') {
981
+ results = splitByFiles(filePaths, rootName, effectiveMaxSize, forceFlag);
982
+ } else if (splitMethod === 'size') {
983
+ results = splitBySize(treeLines, filePaths, rootName, splitSize, effectiveMaxSize, forceFlag);
984
+ }
985
+
986
+ console.log(`✅ Done! Created ${results.length} split files:`);
987
+ console.log('');
988
+
989
+ results.forEach((result, index) => {
990
+ if (splitMethod === 'folder') {
991
+ console.log(`📁 Folder: ${result.folder}`);
992
+ } else if (splitMethod === 'file') {
993
+ console.log(`📄 File: ${result.fileName}`);
994
+ } else if (splitMethod === 'size') {
995
+ console.log(`📦 Part ${result.part}`);
996
+ }
997
+ console.log(`📄 Output : ${result.file}`);
998
+ console.log(`📊 Size : ${result.size} KB`);
999
+ console.log(`🗂️ Files : ${result.files}`);
1000
+ console.log('');
1001
+ });
1002
+
1003
+ if (copyToClipboardFlag) {
1004
+ console.log('⚠️ --copy flag is not compatible with splitting - clipboard copy skipped');
1005
+ }
1006
+
1007
+ process.exit(0);
1008
+ }
1009
+
1010
+ // ── build output (no splitting) ───────────────────────────────────────────────────
615
1011
  const out = [];
616
1012
  const divider = "=".repeat(80);
617
1013
  const subDivider = "-".repeat(80);
@@ -636,11 +1032,12 @@ out.push("FILE CONTENTS");
636
1032
  out.push(divider);
637
1033
 
638
1034
  filePaths.forEach(({ abs, rel }) => {
639
- out.push("");
640
- out.push(subDivider);
641
- out.push(`FILE: ${rel}`);
642
- out.push(subDivider);
643
- out.push(readContent(abs, forceFlag));
1035
+ out.push("");
1036
+ out.push(subDivider);
1037
+ out.push(`FILE: ${rel}`);
1038
+ out.push(subDivider);
1039
+ const effectiveMaxSize = noSkipFlag ? Infinity : maxFileSize;
1040
+ out.push(readContent(abs, forceFlag, effectiveMaxSize));
644
1041
  });
645
1042
 
646
1043
  out.push("");
@@ -7,7 +7,7 @@ _make_folder_txt_completion() {
7
7
  cur="${COMP_WORDS[COMP_CWORD]}"
8
8
  prev="${COMP_WORDS[COMP_CWORD-1]}"
9
9
 
10
- opts="--ignore-folder -ifo --ignore-file -ifi --only-folder -ofo --only-file -ofi --copy --force --help --version -h -v"
10
+ opts="--ignore-folder -ifo --ignore-file -ifi --only-folder -ofo --only-file -ofi --skip-large --no-skip --split-method --split-size --copy --force --help --version -h -v"
11
11
 
12
12
  case "${prev}" in
13
13
  --ignore-folder|-ifo)
@@ -28,6 +28,24 @@ _make_folder_txt_completion() {
28
28
  COMPREPLY=( $(compgen -W "${folders}" -- ${cur}) )
29
29
  return 0
30
30
  ;;
31
+ --skip-large)
32
+ # Complete with common size formats
33
+ local sizes="100KB 200KB 400KB 500KB 1MB 5MB 10MB 100MB 1GB 5GB"
34
+ COMPREPLY=( $(compgen -W "${sizes}" -- ${cur}) )
35
+ return 0
36
+ ;;
37
+ --split-method)
38
+ # Complete with split methods
39
+ local methods="folder file size"
40
+ COMPREPLY=( $(compgen -W "${methods}" -- ${cur}) )
41
+ return 0
42
+ ;;
43
+ --split-size)
44
+ # Complete with common size formats
45
+ local sizes="1MB 5MB 10MB 50MB 100MB 500MB 1GB"
46
+ COMPREPLY=( $(compgen -W "${sizes}" -- ${cur}) )
47
+ return 0
48
+ ;;
31
49
  *)
32
50
  ;;
33
51
  esac
@@ -12,6 +12,10 @@ Register-ArgumentCompleter -Native -CommandName 'make-folder-txt' -ScriptBlock {
12
12
  '--ignore-file', '-ifi',
13
13
  '--only-folder', '-ofo',
14
14
  '--only-file', '-ofi',
15
+ '--skip-large',
16
+ '--no-skip',
17
+ '--split-method',
18
+ '--split-size',
15
19
  '--copy',
16
20
  '--force',
17
21
  '--install-completion',
@@ -49,6 +53,30 @@ Register-ArgumentCompleter -Native -CommandName 'make-folder-txt' -ScriptBlock {
49
53
  return @()
50
54
  }
51
55
  }
56
+ '--skip-large' {
57
+ # Complete with common size formats
58
+ $sizes = @('100KB', '200KB', '400KB', '500KB', '1MB', '5MB', '10MB', '100MB', '1GB', '5GB')
59
+ $matchingSizes = $sizes | Where-Object { $_ -like "*$currentArgument*" }
60
+ return $matchingSizes | ForEach-Object {
61
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', "Size: $_")
62
+ }
63
+ }
64
+ '--split-method' {
65
+ # Complete with split methods
66
+ $methods = @('folder', 'file', 'size')
67
+ $matchingMethods = $methods | Where-Object { $_ -like "*$currentArgument*" }
68
+ return $matchingMethods | ForEach-Object {
69
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', "Method: $_")
70
+ }
71
+ }
72
+ '--split-size' {
73
+ # Complete with common size formats
74
+ $sizes = @('1MB', '5MB', '10MB', '50MB', '100MB', '500MB', '1GB')
75
+ $matchingSizes = $sizes | Where-Object { $_ -like "*$currentArgument*" }
76
+ return $matchingSizes | ForEach-Object {
77
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', "Size: $_")
78
+ }
79
+ }
52
80
  default {
53
81
  # Complete with options
54
82
  if ($currentArgument -like '-*') {
@@ -12,6 +12,10 @@ _make_folder_txt() {
12
12
  '-ofo[Include only specific folders]:folder:_directories'
13
13
  '--only-file[Include only specific files]:file:_files'
14
14
  '-ofi[Include only specific files]:file:_files'
15
+ '--skip-large[Skip files larger than specified size]:size:(100KB 200KB 400KB 500KB 1MB 5MB 10MB 100MB 1GB 5GB)'
16
+ '--no-skip[Include all files regardless of size]'
17
+ '--split-method[Split output by method]:method:(folder file size)'
18
+ '--split-size[Split output when size exceeds limit]:size:(1MB 5MB 10MB 50MB 100MB 500MB 1GB)'
15
19
  '--copy[Copy output to clipboard]'
16
20
  '--force[Include everything (overrides all ignore patterns)]'
17
21
  '--help[Show help message]'
@@ -0,0 +1,52 @@
1
+ ================================================================================
2
+ START OF FOLDER: make-folder-txt
3
+ ================================================================================
4
+
5
+ ================================================================================
6
+ PROJECT STRUCTURE
7
+ ================================================================================
8
+ Root: C:\Programming\make-folder-txt
9
+
10
+ make-folder-txt/
11
+ ├── package.json
12
+
13
+ Total files: 1
14
+
15
+ ================================================================================
16
+ FILE CONTENTS
17
+ ================================================================================
18
+
19
+ --------------------------------------------------------------------------------
20
+ FILE: /package.json
21
+ --------------------------------------------------------------------------------
22
+ {
23
+ "name": "make-folder-txt",
24
+ "version": "2.0.1",
25
+ "description": "Generate a single .txt file containing the full folder structure and file contents of any project, ignoring node_modules and other junk.",
26
+ "main": "bin/make-folder-txt.js",
27
+ "bin": {
28
+ "make-folder-txt": "bin/make-folder-txt.js"
29
+ },
30
+ "scripts": {
31
+ "test": "echo \"No tests yet\" && exit 0"
32
+ },
33
+ "keywords": [
34
+ "folder",
35
+ "dump",
36
+ "project",
37
+ "structure",
38
+ "txt",
39
+ "cli",
40
+ "export"
41
+ ],
42
+ "author": "Muhammad Saad Amin",
43
+ "license": "MIT",
44
+ "engines": {
45
+ "node": ">=14.0.0"
46
+ }
47
+ }
48
+
49
+
50
+ ================================================================================
51
+ END OF FOLDER: make-folder-txt
52
+ ================================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "make-folder-txt",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "Generate a single .txt file containing the full folder structure and file contents of any project, ignoring node_modules and other junk.",
5
5
  "main": "bin/make-folder-txt.js",
6
6
  "bin": {