-
-
Notifications
You must be signed in to change notification settings - Fork 27
London | 25-SDC-July | Priscilla Emebo | Sprint 3 | Implement shell tools #147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { program } from "commander"; | ||
import { promises as fs } from "node:fs"; | ||
import process from "node:process"; | ||
|
||
program | ||
.name("mycat") | ||
.description("Outputs the content of the given file(s), like the cat command") | ||
.option("-n", "Number all lines") | ||
.option("-b", "Number non-blank lines only") | ||
.argument("<files...>", "File paths to display"); | ||
|
||
program.parse(); | ||
|
||
const options = program.opts(); | ||
const filePaths = program.args; | ||
|
||
let lineNumber = 1; | ||
|
||
for (const path of filePaths) { | ||
try { | ||
const content = await fs.readFile(path, "utf-8"); | ||
const lines = content.trimEnd().split("\n"); | ||
|
||
for (const line of lines) { | ||
const isBlank = line.trim() === ""; | ||
|
||
if (options.b) { | ||
// -b: number only non-blank lines | ||
if (!isBlank) { | ||
process.stdout.write(`${String(lineNumber).padStart(6)} ${line}\n`); | ||
lineNumber++; | ||
} else { | ||
process.stdout.write("\n"); | ||
} | ||
} else if (options.n) { | ||
// -n: number all lines | ||
process.stdout.write(`${String(lineNumber).padStart(6)} ${line}\n`); | ||
lineNumber++; | ||
} else { | ||
// no flags | ||
process.stdout.write(line + "\n"); | ||
} | ||
} | ||
} catch (error) { | ||
process.stderr.write(`Error reading file ${path}: ${error.message}\n`); | ||
process.exit(1); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "cat", | ||
"version": "1.0.0", | ||
"description": "You should already be familiar with the `cat` command line tool.", | ||
"main": "mycat.js", | ||
"type": "module", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"commander": "^14.0.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { program } from "commander"; | ||
import { promises as fs } from "node:fs"; | ||
import process from "node:process"; | ||
|
||
program | ||
.name("myls") | ||
.description("list file(s) in the directory, like the ls command") | ||
.option("-1", "list one file per line") | ||
.option("-a", "include hidden files") | ||
.argument("[directory]", "Directory to list", "."); | ||
|
||
program.parse(); | ||
|
||
const options = program.opts(); | ||
const directory = program.args[0] || "."; | ||
|
||
try { | ||
let files = await fs.readdir(directory); | ||
|
||
// if "-a" is used, include hidden files; those that start with "." | ||
if (options.a) { | ||
files = [".", "..", ...files]; | ||
} | ||
|
||
for (const file of files) { | ||
// if "-a" is not used, skip hidden files; those that start with "." | ||
if (!options.a && file.startsWith(".")) { | ||
continue; | ||
} | ||
|
||
console.log(file); // print file name; one file per line | ||
} | ||
} catch (error) { | ||
console.error(`Error reading directory ${directory}:`, error.message); | ||
process.exit(1); | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "ls", | ||
"version": "1.0.0", | ||
"description": "You should already be familiar with the `ls` command line tool.", | ||
"main": "index.js", | ||
"type": "module", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"commander": "^14.0.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { program } from "commander"; | ||
import { promises as fs } from "node:fs"; | ||
|
||
program | ||
.name("mywc") | ||
.description( | ||
"Counts lines, words, and bytes in files like the Unix wc command" | ||
) | ||
.option("-l", "counts the number of lines") | ||
.option("-w", "counts words") | ||
.option("-c", "counts bytes") | ||
.argument("<files...>", "Files to count"); | ||
|
||
program.parse(); | ||
|
||
const options = program.opts(); | ||
const files = program.args; | ||
|
||
// If there are no given flags, default to counting lines, words and bytes like the Unix wc command | ||
if (!options.l && !options.w && !options.c) { | ||
options.l = true; | ||
options.w = true; | ||
options.c = true; | ||
} | ||
|
||
const showLines = options.l; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are you creating new variables here which are the same as accessing the options dictionary? |
||
const showWords = options.w; | ||
const showBytes = options.c; | ||
|
||
// To support multiple files and a total | ||
let totalLines = 0; | ||
let totalWords = 0; | ||
let totalBytes = 0; | ||
|
||
for (const file of files) { | ||
try { | ||
const content = await fs.readFile(file, "utf-8"); | ||
|
||
const lineCount = content.split("\n").length - 1; | ||
const wordCount = content.trim().split(/\s+/).filter(Boolean).length; | ||
const byteCount = Buffer.byteLength(content, "utf-8"); | ||
|
||
totalLines += lineCount; | ||
totalWords += wordCount; | ||
totalBytes += byteCount; | ||
|
||
let output = ""; | ||
if (showLines) output += `${lineCount.toString().padStart(8)}`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is duplication here when you are printing your outputs, can you think how to solve that? |
||
if (showWords) output += `${wordCount.toString().padStart(8)}`; | ||
if (showBytes) output += `${byteCount.toString().padStart(8)}`; | ||
output += ` ${file}`; | ||
|
||
console.log(output); | ||
} catch (err) { | ||
console.error(`Error reading file ${file}: ${err.message}`); | ||
} | ||
} | ||
|
||
// If multiple files were given, show the total | ||
if (files.length > 1) { | ||
let totalOutput = ""; | ||
if (showLines) totalOutput += `${totalLines.toString().padStart(8)}`; | ||
if (showWords) totalOutput += `${totalWords.toString().padStart(8)}`; | ||
if (showBytes) totalOutput += `${totalBytes.toString().padStart(8)}`; | ||
totalOutput += " total"; | ||
|
||
console.log(totalOutput); | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "wc", | ||
"version": "1.0.0", | ||
"description": "You should already be familiar with the `wc` command line tool.", | ||
"main": "index.js", | ||
"type": "module", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"commander": "^14.0.0" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think about what the purpose of the -1 option here is. Have you missed something in your implementation?