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
60 changes: 60 additions & 0 deletions implement-shell-tools/cat/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

function cat(files, options) {
let lineNumber = 1;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The variable 'lineNumber' is used to number lines, but its behavior changes depending on the options. For example, with '-b', it only numbers non-empty lines, but the name doesn't reflect this conditional behavior. When naming variables, it's helpful to consider if the name always matches its use, especially when options change how it's incremented.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The variable 'lineNumber' is used to number lines, but its behavior changes depending on the options. For example, with '-b', it only numbers non-empty lines, but the name doesn't reflect this conditional behavior. When naming variables, it's helpful to consider if the name always matches its use, especially when options change how it's incremented.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The variable 'lineNumber' is used to number lines, but its behavior changes depending on the options. For example, with '-b', it only numbers non-empty lines, but the name doesn't reflect this conditional behavior. When naming variables, it's helpful to consider if the name always matches its use, especially when options change how it's incremented.


files.forEach((file) => {
const filePath = path.resolve(file);

try {
const data = fs.readFileSync(filePath, 'utf8');
const lines = data.split('\n');

lines.forEach((line) => {
if (options.numberNonEmpty && line.trim()) {
console.log(`${lineNumber}\t${line}`);
lineNumber++;
} else if (options.numberLines) {
console.log(`${lineNumber}\t${line}`);
lineNumber++;
} else {
console.log(line);
}
});
} catch (err) {
console.error(`cat: ${file}: No such file or directory`);
}
});
}

function main() {
const args = process.argv.slice(2);
const options = {
numberLines: false,
numberNonEmpty: false,
};

const files = [];

args.forEach((arg) => {
if (arg === '-n') {
options.numberLines = true;
} else if (arg === '-b') {
options.numberNonEmpty = true;
} else {
files.push(arg);
}
});

if (files.length === 0) {
console.error('Usage: node cat.js [-n | -b] <file>...');
process.exit(1);
}

cat(files, options);
}

main();
44 changes: 44 additions & 0 deletions implement-shell-tools/ls/ls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

function listFiles(directory, options) {
try {
const files = fs.readdirSync(directory, { withFileTypes: true });

files.forEach((file) => {
if (!options.all && file.name.startsWith('.')) {
return; // Skip hidden files unless -a is specified
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 12, there's a comment: // Skip hidden files unless -a is specified. The code right above it is a simple if-statement that checks if the file name starts with a dot and the -a option is not set, and then returns. For someone reading the code, it's quite clear that this line is skipping hidden files unless the all option is true. When code is self-explanatory, adding a comment can sometimes make the code harder to maintain, because if you change the code but forget to update the comment, it can become misleading. How might you decide when a comment is truly needed, and when the code speaks for itself?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 12, there's a comment: // Skip hidden files unless -a is specified. The code right below it is a simple if-statement that checks if the file name starts with a dot and if the -a option is not set. For someone reading the code, the logic is quite clear from the condition itself. Sometimes, adding comments for very straightforward code can make the code look more cluttered and doesn't add much value. How do you decide when a comment is helpful versus when the code is already self-explanatory?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 12, there's a comment: // Skip hidden files unless -a is specified. The code right below it is a simple if-statement that checks if the file name starts with a dot and if the -a option is not set. For someone reading the code, the logic is quite clear from the condition itself. Sometimes, adding comments for very straightforward code can make the code look more cluttered and doesn't add much value. How do you decide when a comment is helpful versus when the code is already self-explanatory?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 12, there's a comment: // Skip hidden files unless -a is specified. The code right below it is a simple if-statement that checks if the file name starts with a dot and if the -a option is not set. For someone reading the code, the logic is quite clear from the condition itself. Sometimes, adding comments for very straightforward code can make the code look more cluttered and doesn't add much value. How do you decide when a comment is helpful versus when the code is already self-explanatory?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 12, you have a comment: // Skip hidden files unless -a is specified. The code right above it is already very clear: it checks if the file name starts with a dot and if the -a option is not set, then it returns early. For simple and self-explanatory code like this, do you think the comment adds much value? Sometimes, too many obvious comments can make it harder to spot the comments that really matter. How might you decide when a comment is truly helpful versus when the code speaks for itself?

}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 31, there's a comment: // -1 is the default behavior, so no action needed. Since the code doesn't do anything in this branch, and the comment just restates that, it might not be necessary. If the code is clear without the comment, do you think it's better to leave it out? What could you do if you wanted to make the code self-explanatory without needing this comment?

console.log(file.name);
});
} catch (err) {
console.error(`ls: cannot access '${directory}': No such file or directory`);
}
}

function main() {
const args = process.argv.slice(2);
const options = {
all: false,
};

let directories = ['.'];

args.forEach((arg) => {
if (arg === '-1') {
// -1 is the default behavior, so no action needed
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 31, there's a comment: // -1 is the default behavior, so no action needed. Since the code does nothing in this branch, and the option is not used elsewhere, the comment is not really necessary. If you find yourself writing a comment to explain why you're not doing anything, it might be a sign that the code could be written in a way that doesn't need that explanation. What do you think about removing this comment to keep the code clean and focused?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 31, there's a comment: // -1 is the default behavior, so no action needed. Since the code doesn't do anything in this branch, and the comment just restates that, it might not be necessary. If the code is clear without the comment, do you think it's better to leave it out? What could you do if you wanted to make the code self-explanatory without needing this comment?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 31, there's a comment: // -1 is the default behavior, so no action needed. Since the code doesn't do anything in this branch, and the comment just restates that, it might not be necessary. If the code is clear without the comment, do you think it's better to leave it out? What could you do if you wanted to make the code self-explanatory without needing this comment?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 31, there's a comment: // -1 is the default behavior, so no action needed. Since the code doesn't do anything in this branch, and the comment just restates that, it might not be necessary. If the code is clear without the comment, do you think it's better to leave it out? What could you do if you wanted to make the code self-explanatory without needing this comment?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 31, there's a comment: // -1 is the default behavior, so no action needed. Since the code does nothing in this branch, and the option is not used elsewhere, do you think this comment is needed? Sometimes, if the code is clear and the option is not handled, it might be better to leave it without a comment, or perhaps handle it in a way that doesn't require explanation. What do you think?

} else if (arg === '-a') {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

On line 31, there's a comment: // -1 is the default behavior, so no action needed. Since the code doesn't do anything in this branch, and the comment just restates that, it might not be necessary. If the code is clear without the comment, do you think it's better to leave it out? What could you do if you wanted to make the code self-explanatory without needing this comment?

options.all = true;
} else {
directories = [arg];
}
});
Comment on lines +27 to +37
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The variable 'directories' is named as if it could hold multiple directories, but your code only ever allows one directory to be listed at a time. This could be confusing to someone reading your code, as they might expect it to handle multiple directories. How could you name this variable to better reflect its purpose and avoid confusion?


directories.forEach((directory) => {
listFiles(directory, options);
});
}

main();
61 changes: 61 additions & 0 deletions implement-shell-tools/wc/wc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

function countFile(filePath, options) {
try {
const data = fs.readFileSync(filePath, 'utf8');

const lines = data.split('\n').length;
const words = data.split(/\s+/).filter(Boolean).length;
const bytes = Buffer.byteLength(data, 'utf8');

if (options.lines) {
console.log(`${lines}\t${filePath}`);
} else if (options.words) {
console.log(`${words}\t${filePath}`);
} else if (options.bytes) {
console.log(`${bytes}\t${filePath}`);
} else {
console.log(`${lines}\t${words}\t${bytes}\t${filePath}`);
}
} catch (err) {
console.error(`wc: ${filePath}: No such file or directory`);
}
}

function main() {
const args = process.argv.slice(2);
const options = {
lines: false,
words: false,
bytes: false,
};

const files = [];

args.forEach((arg) => {
if (arg === '-l') {
options.lines = true;
} else if (arg === '-w') {
options.words = true;
} else if (arg === '-c') {
options.bytes = true;
} else {
files.push(arg);
}
});

if (files.length === 0) {
console.error('Usage: wc [-l | -w | -c] <file>...');
process.exit(1);
}

files.forEach((file) => {
const filePath = path.resolve(file);
countFile(filePath, options);
});
}

main();
Loading