Skip to content
Open
Show file tree
Hide file tree
Changes from 16 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
53 changes: 53 additions & 0 deletions implement-shell-tools/cat/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { program } from "commander";
import process from "node:process";
import { promises as fs } from "node:fs";

program
.name("cat")
.description("print the content of file")
.option("-n, --line-numbers","Number the output lines, starting at 1")
.option("-b, --number-nonblank", "Number non-empty output lines, overrides -n")
.argument("<paths...>", "The file path(s) to process"); // to support multiple file
program.parse();

const argv = program.args;
const options = program.opts();
if (argv.length === 0) {
console.error(`No file paths provided`);// to support more files
process.exit(1);
}

let lineCounter = 1;

for (const path of argv) {
try {
const content = await fs.readFile(path, "utf-8");

Choose a reason for hiding this comment

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

Be careful of the indentation here - try to make it consistent across a file.

Copy link
Author

Choose a reason for hiding this comment

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

@LonMcGregor thank you for review and added the extension for indentation checking .

const lines= content.split(/\r?\n/);
if (lines.length && lines[lines.length - 1] === '') {//// Remove trailing empty line if it's just from the final newline
lines.pop();
}

if (options.numberNonblank) {
lines.forEach((line) => {
if (line.trim() === "") {
console.log(""); // Blank line, no number
} else {
const lineNumber = String(lineCounter++).padStart(6, " ");

Choose a reason for hiding this comment

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

You duplicating your code a bit when printing out with line numbers, can you think of a way to reduce this duplication?

Copy link
Author

Choose a reason for hiding this comment

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

I tried to use a function to remove duplication of code.

console.log(`${lineNumber}\t${line}`);
}
});

}else if (options.lineNumbers) {
lines.forEach((line) => {
const lineNumber = String(lineCounter++).padStart(6, ' ');
console.log(`${lineNumber}\t${line}`)
});

} else {
process.stdout.write(content);
if (!content.endsWith('\n')) process.stdout.write('\n');
}
} catch (err) {
console.error(`cat: ${path}: ${err.message}`);
}
}
35 changes: 35 additions & 0 deletions implement-shell-tools/ls/ls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { program } from "commander";
import { promises as fs } from "node:fs";

program
.name("ls")
.description("Displays files in a directory")
.option("-1, --one", "Display each file on a new line")// for listing one file per line
.option("-a, --all", "Include hidden files")
.argument("[filepath]", "Directory to list files from (default: current)")

await program.parseAsync();

const opts = program.opts();
const args = program.args;

const path = args[0] || "."; //Use current directory if no path provided
let files ;
try {
files = await fs.readdir(path);
}catch (err) {
console.error(`ls: cannot access '${path}': ${err.message}`);
process.exit(1);

}

if (!opts.all) {
files = files.filter(file => !file.startsWith("."));// if path not provided use current directory
}

if (opts.one) {
files.forEach(file => console.log(file));
} else {
console.log(files.join(" "));
}

21 changes: 21 additions & 0 deletions implement-shell-tools/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions implement-shell-tools/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "module",
"dependencies": {
"commander": "^14.0.0"
}
}
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 @@
import { program } from "commander";
import { promises as fs } from "node:fs";

program
.name("wc")
.description("Count lines, words, and bytes in files")
.option("-l, --lines", "Only print line counts")
.option("-w, --words", "Only print word counts")
.option("-c, --bytes", "Only print byte counts")
.argument("<files...>", "One or more files to process");
await program.parseAsync();

const files = program.args;
const options = program.opts();

function countContent(content){
const lines = (content.match(/\n/g) || []).length;
const words = content.trim().split(/\s+/).filter(Boolean).length;
const bytes = Buffer.byteLength(content, 'utf-8');
return {lines, words, bytes};
}

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

for(const file of files){
try{
const content = await fs.readFile(file, "utf-8");
const {lines, words, bytes } = countContent(content);

if (options.lines) {
console.log(`${lines} ${file}`);
} else if (options.words) {
console.log(`${words} ${file}`);
}else if (options.bytes) {
console.log(`${bytes} ${file}`);
}else {
console.log(`${lines} ${words} ${bytes} ${file}`);
}

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

}catch (err) {
console.error(`wc: ${file}: ${err.message}`);
}
}

if (files.length > 1) {
if (options.lines) {
console.log(`${totalLines} total`)//if more then 1 file is

Choose a reason for hiding this comment

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

There is some duplication when you are printing out your total and counts. Can you think how to reduce that?

Copy link
Author

Choose a reason for hiding this comment

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

thank you . try to make change as you suggested.

}else if (options.words) {
console.log(`${totalWords} total`);
} else if (options.bytes) {
console.log(`${totalBytes} total`);
} else {
console.log(`${totalLines} ${totalWords} ${totalBytes} total`);
}
}