Skip to content

Commit

Permalink
Merge pull request #5 from yamadashy/feature/top-files-len
Browse files Browse the repository at this point in the history
Add --top-files-length option to customize top files display
  • Loading branch information
yamadashy authored Jul 22, 2024
2 parents 27ddfbe + 7e186d1 commit 6b0c44d
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 13 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ This file contains the contents of my repository combined into a single file. I'

- `-v, --version`: Show tool version
- `-o, --output <file>`: Specify the output file name
- `--top-files-len <number>`: Number of top files to display in the summary
- `-i, --ignore <patterns>`: Additional ignore patterns (comma-separated)
- `-c, --config <path>`: Path to a custom config file
- `--verbose`: Enable verbose logging
Expand All @@ -98,6 +99,7 @@ Create a `repopack.config.json` file in your project root for custom configurati
|`output.filePath`| The name of the output file | `"repopack-output.txt"` |
|`output.headerText`| Custom text to include in the file header |`null`|
|`output.removeComments`| Whether to remove comments from supported file types. Suppurts python | `false` |
|`output.topFilesLength`| Number of top files to display in the summary |`5`|
|`ignore.useDefaultPatterns`| Whether to use default ignore patterns |`true`|
|`ignore.customPatterns`| Additional patterns to ignore |`[]`|

Expand Down
3 changes: 2 additions & 1 deletion repopack.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"output": {
"filePath": "repopack-output.txt",
"headerText": "This repository contains the source code for the Repopack tool.\nRepopack is designed to pack repository contents into a single file,\nmaking it easier for AI systems to analyze and process the codebase.\n\nKey Features:\n- Configurable ignore patterns\n- Custom header text support\n- Efficient file processing and packing\n\nPlease refer to the README.md file for more detailed information on usage and configuration.\n",
"removeComments": false
"removeComments": false,
"topFilesLength": 5
},
"ignore": {
"useDefaultPatterns": true,
Expand Down
28 changes: 28 additions & 0 deletions src/cli/cliOutput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import pc from 'picocolors';

export function printSummary(totalFiles: number, totalCharacters: number, outputPath: string) {
console.log(pc.white('📊 Pack Summary:'));
console.log(pc.dim('────────────────'));
console.log(`${pc.white('Total Files:')} ${pc.white(totalFiles.toString())}`);
console.log(`${pc.white('Total Chars:')} ${pc.white(totalCharacters.toString())}`);
console.log(`${pc.white(' Output:')} ${pc.white(outputPath)}`);
}

export function printTopFiles(fileCharCounts: Record<string, number>, topFilesLength: number) {
console.log(pc.white(`📈 Top ${topFilesLength} Files by Character Count:`));
console.log(pc.dim('──────────────────────────────────'));

const topFiles = Object.entries(fileCharCounts)
.sort((a, b) => b[1] - a[1])
.slice(0, topFilesLength);

topFiles.forEach(([filePath, count], index) => {
const indexString = `${index + 1}.`.padEnd(3, ' ');
console.log(`${pc.white(`${indexString}`)} ${pc.white(filePath)} ${pc.dim(`(${count} chars)`)}`);
});
}

export function printCompletion() {
console.log(pc.green('🎉 All Done!'));
console.log(pc.white('Your repository has been successfully packed.'));
}
24 changes: 15 additions & 9 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import { getVersion } from '../utils/packageJsonUtils.js';
import Spinner from '../utils/spinner.js';
import pc from 'picocolors';
import { handleError } from '../utils/errorHandler.js';
import { printSummary, printTopFiles, printCompletion } from './cliOutput.js';

interface CliOptions extends OptionValues {
version?: boolean;
output?: string;
ignore?: string;
config?: string;
verbose?: boolean;
topFilesLen?: number;
}

async function executeAction(directory: string, options: CliOptions) {
Expand All @@ -39,6 +41,9 @@ async function executeAction(directory: string, options: CliOptions) {
if (options.ignore) {
cliConfig.ignore = { customPatterns: options.ignore.split(',') };
}
if (options.topFilesLen !== undefined) {
cliConfig.output = { ...cliConfig.output, topFilesLength: options.topFilesLen };
}
logger.trace('CLI config:', cliConfig);

const config: RepopackConfigMerged = mergeConfigs(fileConfig, cliConfig);
Expand All @@ -54,19 +59,19 @@ async function executeAction(directory: string, options: CliOptions) {
spinner.start();

try {
const { totalFiles, totalCharacters } = await pack(targetPath, config);
const { totalFiles, totalCharacters, fileCharCounts } = await pack(targetPath, config);
spinner.succeed('Packing completed successfully!');

console.log('');
console.log(pc.white('📊 Pack Summary:'));
console.log(pc.dim('────────────────'));
console.log(`${pc.white('Total Files:')} ${pc.white(totalFiles.toString())}`);
console.log(`${pc.white('Total Chars:')} ${pc.white(totalCharacters.toString())}`);
console.log(`${pc.white(' Output:')} ${pc.white(config.output.filePath)}`);

if (config.output.topFilesLength > 0) {
printTopFiles(fileCharCounts, config.output.topFilesLength);
console.log('');
}

printSummary(totalFiles, totalCharacters, config.output.filePath);
console.log('');
console.log(pc.green('🎉 All Done!'));
console.log(pc.white('Your repository has been successfully packed.'));

printCompletion();
} catch (error) {
spinner.fail('Error during packing');
throw error;
Expand All @@ -86,6 +91,7 @@ export async function run() {
.option('-i, --ignore <patterns>', 'additional ignore patterns (comma-separated)')
.option('-c, --config <path>', 'path to a custom config file')
.option('--verbose', 'enable verbose logging for detailed output')
.option('--top-files-len <number>', 'specify the number of top files to display', parseInt)
.action((directory = '.', options: CliOptions) => executeAction(directory, options));

await program.parseAsync(process.argv);
Expand Down
1 change: 1 addition & 0 deletions src/config/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const defaultConfig: RepopackConfigDefault = {
output: {
filePath: 'repopack-output.txt',
removeComments: false,
topFilesLength: 5,
},
ignore: {
useDefaultPatterns: true,
Expand Down
7 changes: 7 additions & 0 deletions src/core/packager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface Dependencies {
export interface PackResult {
totalFiles: number;
totalCharacters: number;
fileCharCounts: Record<string, number>;
}

export async function pack(
Expand All @@ -44,9 +45,15 @@ export async function pack(

await deps.generateOutput(rootDir, config, packedFiles);

const fileCharCounts: Record<string, number> = {};
packedFiles.forEach((file) => {
fileCharCounts[file.path] = file.content.length;
});

return {
totalFiles,
totalCharacters,
fileCharCounts,
};
}

Expand Down
4 changes: 4 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ interface RepopackConfigBase {
filePath?: string;
headerText?: string;
removeComments?: boolean;
topFilesLength?: number;
};
ignore?: {
useDefaultPatterns?: boolean;
Expand All @@ -15,6 +16,7 @@ export type RepopackConfigDefault = RepopackConfigBase & {
filePath: string;
headerText?: string;
removeComments?: boolean;
topFilesLength: number;
};
ignore: {
useDefaultPatterns: boolean;
Expand All @@ -27,6 +29,7 @@ export type RepopackConfigFile = RepopackConfigBase & {
filePath?: string;
headerText?: string;
removeComments?: boolean;
topFilesLength?: number;
};
ignore?: {
useDefaultPatterns?: boolean;
Expand All @@ -39,6 +42,7 @@ export type RepopackConfigCli = RepopackConfigBase & {
filePath?: string;
headerText?: string;
removeComments?: boolean;
topFilesLength?: number;
};
ignore?: {
useDefaultPatterns?: boolean;
Expand Down
3 changes: 2 additions & 1 deletion tests/core/outputGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('outputGenerator', () => {

test('generateOutput should write correct content to file', async () => {
const mockConfig: RepopackConfigMerged = {
output: { filePath: 'output.txt' },
output: { filePath: 'output.txt', topFilesLength: 2 },
ignore: { useDefaultPatterns: true },
};
const mockPackedFiles = [
Expand All @@ -39,6 +39,7 @@ describe('outputGenerator', () => {
output: {
filePath: 'output.txt',
headerText: 'Custom header text',
topFilesLength: 2,
},
ignore: { useDefaultPatterns: true },
};
Expand Down
2 changes: 1 addition & 1 deletion tests/core/packager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('packager', () => {

test('pack should process files and generate output', async () => {
const mockConfig: RepopackConfigMerged = {
output: { filePath: 'output.txt' },
output: { filePath: 'output.txt', topFilesLength: 2 },
ignore: { useDefaultPatterns: true },
};

Expand Down
2 changes: 1 addition & 1 deletion tests/utils/fileHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('fileHandler', () => {
vi.mocked(fs.readFile).mockResolvedValue(mockContent);

const mockConfig: RepopackConfigMerged = {
output: { filePath: 'output.txt' },
output: { filePath: 'output.txt', topFilesLength: 2 },
ignore: { useDefaultPatterns: true },
};
const result = await processFile('/path/to/file.txt', mockConfig);
Expand Down

0 comments on commit 6b0c44d

Please sign in to comment.