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
Binary file added .DS_Store
Binary file not shown.
Binary file added implement-shell-tools/.DS_Store
Binary file not shown.
49 changes: 49 additions & 0 deletions implement-shell-tools/cat/cat.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import process from "node:process";
import { promises as fs } from "node:fs";
import { program } from "commander";

program
.name("Cat")
.description("My version of cat command line tool")
.argument("<files...>", "Files to display")
.option("-n, --number", "Number all output lines")
.option("-b, --non-blank", "Number non empty output lines");

program.parse();

const { number, nonBlank } = program.opts();
const filePaths = program.args;

let lineNumber = 1;

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

if (!number && !nonBlank) {
process.stdout.write(content);
continue;
}
let text = content;
if (content.endsWith("\n")) {
text = content.slice(0, -1);
}
const lines = text.split("\n");

for (const line of lines) {
if (nonBlank) {
if (line == "") {
console.log();
} else {
console.log(`${lineNumber}\t${line}`);
lineNumber++;
}
} else if (number) {
console.log(`${lineNumber}\t${line}`);
lineNumber++;
}
}
} catch (error) {
console.error(`${error}`);
}
}
37 changes: 37 additions & 0 deletions implement-shell-tools/ls/ls.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import process from "node:process";
import { promises as fs } from "node:fs";
import { program } from "commander";

program
.name("list")
.description("Implement my version of ls")
.argument("[paths...]", "The file path to process")
.option("-1, --one", "This list the item one per line")
.option("-a, --all", "This lists all of the files");

program.parse();

const { one, all } = program.opts();
const paths = program.args;

let targetDir = paths[0] || ".";

try {
let files = await fs.readdir(targetDir);

if (all) {
files = [".", "..", ...files].sort();
} else {
files = files.filter((output) => !output.startsWith(".")).sort();
}

if (one) {
for (const file of files) {
console.log(file);
}
} else {
console.log(files.join(" "));
}
} catch (error) {
console.error(`${error}`);
}
25 changes: 25 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.

16 changes: 16 additions & 0 deletions implement-shell-tools/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "implement-shell-tools",
"version": "1.0.0",
"description": "Your task is to re-implement shell tools you have used.",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"commander": "^15.0.0"
}
}
Empty file.
84 changes: 84 additions & 0 deletions implement-shell-tools/wc/wc.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import process from "node:process";
import { promises as fs } from "node:fs";
import { program } from "commander";

program
.name("Word Count")
.description("my implementation of wc")
.argument("<path...>", "The file path to process")
.option("-l", "Count for the total number of lines")
.option("-c", "Count the total number of bytes")
.option("-w", "Count the total number of words");

program.parse();

let filePaths = program.args;
let options = program.opts();
let noFlags = !options.l && !options.w && !options.c;

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

for (const filePath of filePaths) {
try {
const content = await fs.readFile(filePath, "utf-8");
const outputs = [];

const lines = getLineCount(content);
const words = getWordCount(content);
const bytes = getByteCount(content);

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

if (noFlags || options.l) {
outputs.push(lines);
}
if (noFlags || options.w) {
outputs.push(words);
}
if (noFlags || options.c) {
outputs.push(bytes);
}

outputs.push(filePath);
console.log(outputs.join("\t"));
} catch (err) {
console.error(`${err.message}`);
}
}

if (filePaths.length > 1) {
const totalOutputs = [];

if (noFlags || options.l) {
totalOutputs.push(totalLines);
}
if (noFlags || options.w) {
totalOutputs.push(totalWords);
}
if (noFlags || options.c) {
totalOutputs.push(totalBytes);
}
totalOutputs.push("total");
console.log(totalOutputs.join("\t"));
}

function getWordCount(text) {
const trimmed = text.trim();
if (trimmed.length == 0) {
return 0;
}
return trimmed.split(/\s+/).length;
}

function getLineCount(text) {
if (text.length == 0) return 0;
return text.split("\n").length - 1;
}

function getByteCount(text) {
return Buffer.byteLength(text, "utf-8");
}
Loading