Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions implement-shell-tools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.venv
44 changes: 44 additions & 0 deletions implement-shell-tools/cat/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import process from "node:process";
import { promises as fs } from "node:fs";

const argv = process.argv.slice(2);

const showNumbers = argv.includes("-n");
const showNonBlankNumbers = argv.includes("-b");

const filePaths = argv.filter((arg) => !arg.startsWith("-"));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if someone passed a -q flag here? What should happen?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviewing, you are right to point that out, my logic will let the user confused thinking that the -q flag exists and worked, I implemented in place a flag check and ensured print an error and exit with not 0 code.


const flagsUsed = argv.filter((arg) => arg.startsWith("-"));
const supportedFlags = ["-n", "-b"];
for (const flag of flagsUsed) {
if (!supportedFlags.includes(flag)) {
console.error(`Invalid option: please try "-n or "-b"`);
process.exit(1);
}
}

let counterLines = 1;

for (const path of filePaths) {
try {
const content = await fs.readFile(path, "utf-8");
.
const splitLines = content.split("\n");

splitLines.forEach((line) => {
let prefix = "";

if (showNonBlankNumbers) {
if (line.trim() !== "") {
prefix = `${counterLines++} `;
}
} else if (showNumbers) {
prefix = `${counterLines++} `;
}
Comment on lines +31 to +37
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think about collapsing this into one if:

if (showNumbers || (howNonBlankNumbers && line.trim() !== "")) {

because they have the same intent, but wouldn't push strongly for this if you prefer it as-is :)

console.log(`${prefix}${line}`);
});
} catch (error) {
console.error(`Error ${path}: ${error.message}`);
process.exit(1);
}
}
27 changes: 27 additions & 0 deletions implement-shell-tools/ls/ls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import fs from "node:fs";
import process from "node:process";

const argv = process.argv.slice(2);

const filePaths = argv.filter((arg) => !arg.startsWith("-"));
const showHiddenFiles = argv.includes("-a");

if (filePaths.length > 1) {
console.error("Error: This version only supports one directory path a time.");
process.exit(1);
}

const target = filePaths[0] || ".";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if someone specified multiple paths, e.g. ls /some/file /some/other/file? What does your implementation do?

The README.md only requires that your programme works with simple paths, but I would recommend implementing support for multiple. But if you don't implement that, you generally want to give an error to the user if they supply input you don't expect, rather than just ignoring it.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviewing, I should at least display an stderr and exit .


const files = fs.readdirSync(target);

let filteredFIles = files;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let filteredFIles = files;
let filteredFiles = files;

if (!showHiddenFiles) {
filteredFIles = files.filter((file) => !file.startsWith("."));
} else {
filteredFIles = [".", "..", ...files];
}

filteredFIles.forEach((file) => {
console.log(file);
});
67 changes: 67 additions & 0 deletions implement-shell-tools/wc/wc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import process, { exit } from "node:process";
import fs from "node:fs";

const argv = process.argv.slice(2);

let showWords = argv.includes("-w");
let showLines = argv.includes("-l");
let showBytes = argv.includes("-c");
let showCharacters = argv.includes("-m");

const filePaths = argv.filter((arg) => !arg.startsWith("-"));
// if no flags enable all.
if (!showLines && !showCharacters && !showWords && !showBytes) {
showLines = true;
showCharacters = true;
showWords = true;
showBytes = true;
}

if (filePaths.length === 0) {
console.error("PLease provide a file path");
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You frequently have typos where the second letter after a capital letter is also capitalised. Please look out for these and fix them.

process.exit(1);
}

let totalLines = 0;
let totalWords = 0;
let totalBytes = 0;
let totalChars = 0;

filePaths.forEach((filePath) => {
try {
const content = fs.readFileSync(filePath, "utf-8");
const lineArray = content.split("\n");
if (content.endsWith("\n")) lineArray.pop();
const lines = lineArray.length;

const words = content.trim().split(/\s+/).filter((word) => word != "").length;
const bytes = Buffer.byteLength(content);
const characters = content.length;

totalLines += lines;
totalWords += words;
totalBytes += bytes;
totalChars += characters;

let output = "";
if (showLines) output += lines.toString().padStart(8);
if (showWords) output += words.toString().padStart(8);
if (showBytes) output += bytes.toString().padStart(8);
if (showCharacters) output += characters.toString().padStart(8)

console.log(`${output} ${filePath}`);
} catch(error) {
console.error(`Error reading ${filePath}: ${error.message}`);
}
});

if (filePaths.length > 1) {
let totalOutput = "";
if (showLines) totalOutput += `${totalLines.toString().padStart(8)}`;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit repetitive with the single-file formatting case :)

if (showWords) totalOutput += `${totalWords.toString().padStart(8)}`;
if (showBytes) totalOutput += `${totalBytes.toString().padStart(8)}`;
if (showCharacters) totalOutput += `${totalChars.toString().padStart(8)}`;

console.log(`${totalOutput} total`);
}

Loading