Skip to content

Commit

Permalink
More robust filename parsing via stdin
Browse files Browse the repository at this point in the history
  • Loading branch information
fry69 committed Apr 17, 2024
1 parent 23c5a27 commit 4d3746a
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 3 deletions.
52 changes: 52 additions & 0 deletions files-to-prompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,58 @@ describe('files-to-prompt.ts', () => {
expect(filePathsFromStdin).toEqual(['file1.txt', 'file2.txt']);
});

test('should parse file paths with one file path per line', () => {
const stdinData = `file1.txt\nfile2.txt\nfile3.txt`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', 'file2.txt', 'file3.txt']);
});

test('should handle mixed input formats', () => {
const stdinData = `file1.txt:File 1 contents.\nfile2.txt\nfile3.txt:File 3 contents.`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', 'file2.txt', 'file3.txt']);
});

test('should handle empty lines in stdin data', () => {
const stdinData = `file1.txt:File 1 contents.\n\nfile2.txt:File 2 contents.\n`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', 'file2.txt']);
});

test('should handle binary data in stdin', () => {
const binaryData = Buffer.from([0x80, 0x81, 0x82, 0x83, 0x84, 0x85]);
const stdinData = `file1.txt:File 1 contents.\n${binaryData.toString('utf8')}\nfile2.txt:File 2 contents.`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', 'file2.txt']);
});

test('should handle common text/code files in stdin', () => {
const textData = `console.log('Hello, world\!');`;
const stdinData = `file1.txt:File 1 contents.\n${textData}\nfile2.txt:File 2 contents.`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', textData, 'file2.txt']);
});

test('should handle long file paths in stdin', () => {
const longFilePath = 'a'.repeat(1025);
const stdinData = `file1.txt:File 1 contents.\n${longFilePath}\nfile2.txt:File 2 contents.`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', 'file2.txt']);
});

test('should ignore file paths with the null character', () => {
const invalidFilePath = 'invalid_file\0.txt';
const stdinData = `file1.txt:File 1 contents.\n${invalidFilePath}\nfile2.txt:File 2 contents.`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', 'file2.txt']);
});

test('should ignore file paths with control characters', () => {
const stdinData = `file1.txt:File 1 contents.\nfile2.txt\x07.txt:File 2 contents.\nfile3.txt:File 3 contents.`;
const filePathsFromStdin = parseFilePathsFromStdin(stdinData);
expect(filePathsFromStdin).toEqual(['file1.txt', 'file3.txt']);
});

test('should output version string when --version is passed', async () => {
await main(['--version']);
expect(stdoutOutput).toContain(`files-to-prompt.ts version`);
Expand Down
40 changes: 37 additions & 3 deletions files-to-prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,24 @@ let readStdin = async (): Promise<string> => {
*/
export function parseFilePathsFromStdin(stdinData: string): string[] {
const filePathsFromStdin: string[] = [];
const lines = stdinData.trim().split('\n');
const seenFilePaths = new Set<string>();
const lines = stdinData.trim().split('\n');

for (const line of lines) {
const filePath = line.split(':')[0];
if (!seenFilePaths.has(filePath)) {
const filePath = line.trim();
if (filePath === '') {
// Ignore empty line
continue;
}
if (filePath.includes(':')) {
// Handle grep/ripgrep output format
const parts = filePath.split(':');
if (isValidFilePath(parts[0]) && !seenFilePaths.has(parts[0])) {
seenFilePaths.add(parts[0]);
filePathsFromStdin.push(parts[0]);
}
} else if (isValidFilePath(filePath) && !seenFilePaths.has(filePath)) {
// Handle file path per line format
seenFilePaths.add(filePath);
filePathsFromStdin.push(filePath);
}
Expand All @@ -263,6 +275,28 @@ export function parseFilePathsFromStdin(stdinData: string): string[] {
return filePathsFromStdin;
}

/**
* Checks if a given string is a valid file path.
* @function isValidFilePath
* @param {string} filePath - The file path to check.
* @returns {boolean} - `true` if the file path is valid, `false` otherwise.
*/
function isValidFilePath(filePath: string): boolean {
// Check if the file path contains only valid characters
for (const char of filePath) {
if (char.charCodeAt(0) < 32 || char.charCodeAt(0) > 126) {
return false;
}
}

// Check if the file path is not too long
if (filePath.length > 1024) {
return false;
}

// If the file path passes the above checks, consider it valid
return true;
}

/**
* The main entry point of the script.
Expand Down

0 comments on commit 4d3746a

Please sign in to comment.