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");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

what will happen if file does not exist?

const lines = context.trimEnd().split("\n");
if (options.nonBlank) {
lines.forEach((line) => {
if (line.length != 0) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

what happens if i got a line consisting of whitespace?

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`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good idea to use colour output, the only caveat we should output the color only if we are in terminal mode. I.e. right now if I pass it into a pipe, it will output these codes as well

}
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];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

what happens if only -c is passed?

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");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What happens if file is absent?

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