Skip to content
51 changes: 51 additions & 0 deletions implement-shell-tools/cat/customCat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { program } from "commander";
import { promises as fs } from "node:fs";
import process from "node:process";

program
.name("custom-cat")
.description("my-own-version-of-cat")
.option("-n, --line", "Adding a number before each roll")
.option(
"-b, --nonBlank",
"Only adding a number before roll that is non blank",
)
.argument("<path...>", "The file path to process");

program.parse();

const options = program.opts();

const argumentArray = program.args;
if (argumentArray.length < 1) {
console.log(
`We need at least 1 path of file to process but we got ${argumentArray.length}`,
);
process.exit(1);
}

const pathsArray = argumentArray;

let count = 1;

for (let path of pathsArray) {
const context = await fs.readFile(path, "utf-8");
const lines = context.trimEnd().split("\n");
if (options.nonBlank) {
lines.forEach((line) => {
if (line.length != 0) {
console.log(` ${count} ${line}`);
count++;
} else {
console.log(line);
}
});
} else if (options.line) {
lines.forEach((line) => {
console.log(` ${count} ${line}`);
count++;
});
} else {
console.log(context.trimEnd());
}
}
72 changes: 72 additions & 0 deletions implement-shell-tools/ls/customLs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { program } from "commander";
import { promises as fs } from "node:fs";
import process from "node:process";

program
.name("Custom-ls")
.description("Custom-ls-that-works-like-ls")
.option("-1, --oneFile", "Showing one file per line")
.option("-a, --showHidden", "Showing hidden files")
.argument("[path]", "The file path to process");

program.parse();

const argumentsArray = program.args;

const path = argumentsArray[0] || "./";

async function formatFileName(base, fileName) {
try {
const fullPath = `${base.endsWith("/") ? base : base + "/"}${fileName}`;
const stats = await fs.stat(fullPath);
if (stats.isDirectory()) {
return `\x1b[1;34m${fileName}\x1b[0m`;
}
return fileName;
} catch (error) {
return fileName;
}
}

try {
const files = await fs.readdir(path);

const sortedFiles = files.sort((a, b) => {
const cleanA = a.replace(/^\./, "");
const cleanB = b.replace(/^\./, "");
return cleanA.localeCompare(cleanB, undefined, { sensitivity: "base" });
});

const options = program.opts();

let renderingFiles = [];

if (options.showHidden) {
renderingFiles = [".", "..", ...sortedFiles];
} else {
renderingFiles = sortedFiles.filter((file) => !/^\./.test(file));
}

if (options.oneFile) {
for (let file of renderingFiles) {
console.log(await formatFileName(path, file));
}
} else {
const formatted = await Promise.all(
renderingFiles.map((fileName) => {
return formatFileName(path, fileName);
}),
);
console.log(formatted.join(" "));
}
} catch (error) {
const stats = await fs.stat(path).catch(() => null);
if (stats && stats.isFile()) {
console.log(path);
} else {
console.log(
`Can't access to this path: ${path} - No such file or directory`,
);
process.exit(1);
}
}
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 @@
{
"dependencies": {
"commander": "^14.0.3"
},
"type": "module"
}
83 changes: 83 additions & 0 deletions implement-shell-tools/wc/customWc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { program } from "commander";
import { promises as fs } from "node:fs";
import process from "node:process";

program
.name("Custom-wc")
.description("Custom-wc-that-works-like-wc")
.option("-l, --lines", "Counting lines in the file")
.option("-w, --words", "Counting words in the file")
.option("-c, --characters", "Counting characters in the file")
.argument("<path...>", "Path of file to process");

program.parse();

const argumentArray = program.args;
if (argumentArray.length === 0) {
console.log(`We need at least one file path to process`);
process.exit(1);
}

const pathArray = argumentArray;
const options = program.opts();

function padStartNumbers(...args) {
const space = [3, 4, 4];
const numberStringArray = [];
for (let index = 0; index < args.length; index++) {
numberStringArray.push(String(args[index]).padStart(space[index], " "));
}
return numberStringArray.join("");
}

const totalRowNumbers = [];

let totalOfLines = 0;
let totalOfWords = 0;
let totalOfCharacters = 0;

for (let path of pathArray) {
let numberOfLines = 0;
let numberOfWords = 0;
let numberOfCharacters = 0;

const file = await fs.readFile(path, "utf-8");
numberOfLines = file.split("\n").length - 1;
const words = file.match(/\S+/g);
numberOfWords = words ? words.length : 0;
numberOfCharacters = file.length;

const rowNumbers = [];

if (options.lines) rowNumbers.push(numberOfLines);
if (options.words) rowNumbers.push(numberOfWords);
if (options.characters) rowNumbers.push(numberOfCharacters);

if (rowNumbers.length === 0) {
console.log(
`${padStartNumbers(numberOfLines, numberOfWords, numberOfCharacters)} ${path}`,
);
} else {
if (pathArray.length === 1 && rowNumbers.length === 1) {
console.log(`${rowNumbers[0]} ${path}`);
} else {
console.log(`${padStartNumbers(...rowNumbers)} ${path}`);
}
}
totalOfLines += numberOfLines;
totalOfWords += numberOfWords;
totalOfCharacters += numberOfCharacters;
}

if (pathArray.length > 1) {
if (options.lines) totalRowNumbers.push(totalOfLines);
if (options.words) totalRowNumbers.push(totalOfWords);
if (options.characters) totalRowNumbers.push(totalOfCharacters);
if (totalRowNumbers.length > 0) {
console.log(`${padStartNumbers(...totalRowNumbers)} total`);
} else {
console.log(
`${padStartNumbers(totalOfLines, totalOfWords, totalOfCharacters)} total`,
);
}
}
Loading