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/cat/cat.mjs b/implement-shell-tools/cat/cat.mjs new file mode 100644 index 000000000..d9630c33a --- /dev/null +++ b/implement-shell-tools/cat/cat.mjs @@ -0,0 +1,48 @@ +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 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); +} + +let lineNum = 1; + +for (const file of files) { + const content = await fs.readFile(file, "utf-8"); + const lines = content.split("\n"); + + for (const line of lines) { + if (options.b) { + if (line.trim() !== "") { + console.log(`${(lineNum).toString().padStart(6)} ${line}`); + lineNum++; + } + else { + console.log(line); + } + } + else if (options.n) { + console.log(`${(lineNum).toString().padStart(6)} ${line}`); + lineNum++; + } + else { + console.log(line); + } + } + +} 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" + } +} diff --git a/implement-shell-tools/ls/ls.mjs b/implement-shell-tools/ls/ls.mjs new file mode 100644 index 000000000..fa34aa906 --- /dev/null +++ b/implement-shell-tools/ls/ls.mjs @@ -0,0 +1,38 @@ +import { program } from "commander"; +import { promises as fs } from "node:fs"; +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" + } +} 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