From 60fd9bbbc5a79b8d467b9e402b7821b3f480d791 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Fri, 25 Jul 2025 20:07:43 +0100 Subject: [PATCH 1/3] Just implemented the cat-like program to display the contents of a file --- implement-shell-tools/cat/cat.mjs | 49 +++++++++++++++++++++ implement-shell-tools/cat/package-lock.json | 20 +++++++++ implement-shell-tools/cat/package.json | 6 +++ 3 files changed, 75 insertions(+) create mode 100644 implement-shell-tools/cat/cat.mjs create mode 100644 implement-shell-tools/cat/package-lock.json create mode 100644 implement-shell-tools/cat/package.json diff --git a/implement-shell-tools/cat/cat.mjs b/implement-shell-tools/cat/cat.mjs new file mode 100644 index 000000000..873fe76f0 --- /dev/null +++ b/implement-shell-tools/cat/cat.mjs @@ -0,0 +1,49 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; +import process from "node:process"; + + +program + .name("Display the contents of a file") + .description("Should effectively display the contents of a file as cat does even with extra flags") + .option("-n", "The character numbers all the lines of output.") + .option("-b", "The character numbers only the nonempty lines of the output") + .argument(""); + +program.parse(); + +const files = program.args; +const opts = program.opts(); + +if (files.length === 0) { + console.error(`Expected at least 1 argument (a path) to be passed but got ${files.length}.`); + process.exit(1); +} + +const path = files[0]; +let lineNum = 1; + +for (let file of files) { + const content = await fs.readFile(file, "utf-8"); + const lines = content.split("\n"); + + for (let i = 0; i < lines.length; i++) { + if (opts.b) { + if (lines[i].trim() !== "") { + console.log(`${(lineNum).toString().padStart(6)} ${lines[i]}`); + lineNum++; + } + else { + console.log(lines[i]); + } + } + else if (opts.n) { + console.log(`${(lineNum).toString().padStart(6)} ${lines[i]}`); + lineNum++; + } + else { + console.log(lines[i]); + } + } + +} diff --git a/implement-shell-tools/cat/package-lock.json b/implement-shell-tools/cat/package-lock.json new file mode 100644 index 000000000..749fee721 --- /dev/null +++ b/implement-shell-tools/cat/package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "cat", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "commander": "^14.0.0" + } + }, + "node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "engines": { + "node": ">=20" + } + } + } +} diff --git a/implement-shell-tools/cat/package.json b/implement-shell-tools/cat/package.json new file mode 100644 index 000000000..68279600c --- /dev/null +++ b/implement-shell-tools/cat/package.json @@ -0,0 +1,6 @@ +{ + "type": "module", + "dependencies": { + "commander": "^14.0.0" + } +} From f1ef3a457b9e88db2c5a76ab1b93f9e6d48623c0 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Mon, 28 Jul 2025 16:04:29 +0100 Subject: [PATCH 2/3] This is the functionality for the ls command --- implement-shell-tools/cat/cat.mjs | 21 ++++++------ implement-shell-tools/ls/ls.mjs | 39 ++++++++++++++++++++++ implement-shell-tools/ls/package-lock.json | 20 +++++++++++ implement-shell-tools/ls/package.json | 5 +++ 4 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 implement-shell-tools/ls/ls.mjs create mode 100644 implement-shell-tools/ls/package-lock.json create mode 100644 implement-shell-tools/ls/package.json diff --git a/implement-shell-tools/cat/cat.mjs b/implement-shell-tools/cat/cat.mjs index 873fe76f0..d9630c33a 100644 --- a/implement-shell-tools/cat/cat.mjs +++ b/implement-shell-tools/cat/cat.mjs @@ -13,36 +13,35 @@ program program.parse(); const files = program.args; -const opts = program.opts(); +const options = program.opts(); if (files.length === 0) { console.error(`Expected at least 1 argument (a path) to be passed but got ${files.length}.`); process.exit(1); } -const path = files[0]; let lineNum = 1; -for (let file of files) { +for (const file of files) { const content = await fs.readFile(file, "utf-8"); const lines = content.split("\n"); - for (let i = 0; i < lines.length; i++) { - if (opts.b) { - if (lines[i].trim() !== "") { - console.log(`${(lineNum).toString().padStart(6)} ${lines[i]}`); + for (const line of lines) { + if (options.b) { + if (line.trim() !== "") { + console.log(`${(lineNum).toString().padStart(6)} ${line}`); lineNum++; } else { - console.log(lines[i]); + console.log(line); } } - else if (opts.n) { - console.log(`${(lineNum).toString().padStart(6)} ${lines[i]}`); + else if (options.n) { + console.log(`${(lineNum).toString().padStart(6)} ${line}`); lineNum++; } else { - console.log(lines[i]); + console.log(line); } } diff --git a/implement-shell-tools/ls/ls.mjs b/implement-shell-tools/ls/ls.mjs new file mode 100644 index 000000000..05cff6afd --- /dev/null +++ b/implement-shell-tools/ls/ls.mjs @@ -0,0 +1,39 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; +import { connect } from "node:http2"; +import process from "node:process"; + +program + .name("ls") + .description("This is a program to display the childern of a directory.") + .option("-1, --one", "This is to list all the children of a directory, one per line.") + .option("-a", "The flag to list the children of a directory one per line in long format.") + .argument("") + +program.parse(process.argv); + +const opts = program.opts(); +const args = program.args; + +if (args.length != 1) { + console.error(`Expected exactly 1 argument (a path) to be passed but got ${args.length}.`); + process.exit(1); +} + +const content = await fs.readdir(args[0], "utf-8"); + +const results = content.join(' ') +// const regex = '/\n/' + +const filtered = content.filter((word) => word.charAt(0) !== '.') + +if (opts.one) { + console.log(filtered.join('\n')) +} +else if (opts.a) { + console.log(content.join(' ')); +} +else { + console.log(filtered.join(' ')) +} + diff --git a/implement-shell-tools/ls/package-lock.json b/implement-shell-tools/ls/package-lock.json new file mode 100644 index 000000000..381e1a391 --- /dev/null +++ b/implement-shell-tools/ls/package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "ls", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "commander": "^14.0.0" + } + }, + "node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "engines": { + "node": ">=20" + } + } + } +} diff --git a/implement-shell-tools/ls/package.json b/implement-shell-tools/ls/package.json new file mode 100644 index 000000000..ab8c9a348 --- /dev/null +++ b/implement-shell-tools/ls/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "commander": "^14.0.0" + } +} From bac1bdf2c89d6ffc82095725343d301f6fd96e38 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Tue, 29 Jul 2025 16:05:56 +0100 Subject: [PATCH 3/3] This is the functionality for wc command --- .vscode/launch.json | 18 +++++++ implement-shell-tools/ls/ls.mjs | 1 - implement-shell-tools/wc/package-lock.json | 20 ++++++++ implement-shell-tools/wc/package.json | 5 ++ implement-shell-tools/wc/wc.mjs | 55 ++++++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json create mode 100644 implement-shell-tools/wc/package-lock.json create mode 100644 implement-shell-tools/wc/package.json create mode 100644 implement-shell-tools/wc/wc.mjs diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..ba48d4ea0 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "skipFiles": [ + "/**" + ], + "program": "${workspaceFolder}/implement-shell-tools/wc/wc.mjs" + } + ] +} \ No newline at end of file diff --git a/implement-shell-tools/ls/ls.mjs b/implement-shell-tools/ls/ls.mjs index 05cff6afd..fa34aa906 100644 --- a/implement-shell-tools/ls/ls.mjs +++ b/implement-shell-tools/ls/ls.mjs @@ -1,6 +1,5 @@ import { program } from "commander"; import { promises as fs } from "node:fs"; -import { connect } from "node:http2"; import process from "node:process"; program diff --git a/implement-shell-tools/wc/package-lock.json b/implement-shell-tools/wc/package-lock.json new file mode 100644 index 000000000..6a23cbf7d --- /dev/null +++ b/implement-shell-tools/wc/package-lock.json @@ -0,0 +1,20 @@ +{ + "name": "wc", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "commander": "^14.0.0" + } + }, + "node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "engines": { + "node": ">=20" + } + } + } +} diff --git a/implement-shell-tools/wc/package.json b/implement-shell-tools/wc/package.json new file mode 100644 index 000000000..ab8c9a348 --- /dev/null +++ b/implement-shell-tools/wc/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "commander": "^14.0.0" + } +} diff --git a/implement-shell-tools/wc/wc.mjs b/implement-shell-tools/wc/wc.mjs new file mode 100644 index 000000000..84f7f4d13 --- /dev/null +++ b/implement-shell-tools/wc/wc.mjs @@ -0,0 +1,55 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; +import process from "node:process"; + +program + .name("wc") + .description("A program to implement word, character and line counter.") + .option("-l", "Counts the lines in a file") + .option("-w", "Counts the words in a file") + .option("-c", "Counts the characters in a file") + .argument(""); + +program.parse(process.argv); + +const opts = program.opts(); +const args = program.args; + +if (args.length === 0) { + console.error(`Expected at least one argument but received ${args.length}`); + process.exit(1); +} + +let totalLines = 0; +let totalWords = 0; +let totalChars = 0; + +for (const file of args) { + const content = await fs.readFile(file, "utf-8"); + const linesArr = content.split('\n'); + const lines = linesArr[linesArr.length - 1] === '' ? linesArr.length - 1 : linesArr.length; + const words = content.split(/\s+/).filter(Boolean).length; + const chars = content.length; + + totalLines += lines; + totalWords += words; + totalChars += chars; + + let output = ''; + if (opts.l) output += `${lines} `; + if (opts.w) output += `${words} `; + if (opts.c) output += `${chars} `; + if (!opts.l && !opts.w && !opts.c) output += `${lines} ${words} ${chars} `; + output += file; + console.log(output); +} + +if (args.length > 1) { + let totalOutput = ''; + if (opts.l) totalOutput += `${totalLines} `; + if (opts.w) totalOutput += `${totalWords} `; + if (opts.c) totalOutput += `${totalChars} `; + if (!opts.l && !opts.w && !opts.c) totalOutput += `${totalLines} ${totalWords} ${totalChars} `; + totalOutput += 'total'; + console.log(totalOutput); +} \ No newline at end of file