-
-
Notifications
You must be signed in to change notification settings - Fork 11
London | Nadika Zavodovska | Module-Tools | Sprint 3 | Implement-Shell-Tools #45
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?
London | Nadika Zavodovska | Module-Tools | Sprint 3 | Implement-Shell-Tools #45
Conversation
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.
This is a great submission Nadika that betrays a good working knowledge of Node scripting as well as the functionality of the shell tools that you've been replicating. There are a few points that I've raised surrounding efficiency - as we're working with files, it's important that we're mindful of duplicating these into memory and the most efficient way to work with them will always be one line at a time, see this article for a guide on how to do that: https://www.geeksforgeeks.org/how-to-read-a-file-line-by-line-using-node-js/
Overall everything was very clear and readable and works when running it locally, keep it up!
implement-shell-tools/cat/cat.js
Outdated
return line; | ||
}); | ||
// join lines back to the string and print them | ||
console.log(arrayContentLines.join("\n")); |
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.
question: Do we need to join these back, or could we just print each line as we go?
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.
Thank you for the really useful comment, @ehwus Alex! You’re absolutely right, printing each line as we go is more efficient, especially when dealing with large files. I’ve updated my code to avoid unnecessary memory usage.
//Get user inputs from command line | ||
const filePaths = program.args; | ||
const displayLineNumbers = program.opts().n; | ||
const displayNonEmptyLineNumbers = program.opts().b; |
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.
praise: It's great to assign these options into variables that are more descriptive than the single letter flags, it makes the code much more readable
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.
Thank you for the positive feedback, @ehwus Alex. I'll continue to follow this approach in the future!
} | ||
|
||
// Handling multiply file processing using Promise.all and map() | ||
await Promise.all(arrayFilePaths.map(filePath => displayFileContents(filePath, displayLineNumbers, displayNonEmptyLineNumbers))); |
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.
question: Why is map
useful here over forEach
?
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.
Thank you, @ehwus Alex, great question. map
is used because it returns an array of promises, which is needed for Promise.all
to wait for all tasks to complete. forEach
doesn't return anything, so it wouldn't work with Promise.all
.
.parse(process.argv) | ||
|
||
// Function to print file contents with the flags | ||
async function displayFileContents(filePath, displayLineNumbers = false, displayNonEmptyLineNumbers = false) { |
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.
issue: This function works and is readable, but we're loading the same data into memory multiple times in different ways. Can you think of any ways that this could be made more efficient?
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.
@ehwus Alex, thank you for the really useful feedback! Yes, there is a more efficient way, I can use the readline module. I've updated the code to use readline to read the file line by line, which helps prevent loading the entire file into memory at once.
// Importing the 'program' object from 'commander' to help build command-line interfaces, handle user inputs. | ||
import { program } from "commander"; | ||
// Importing the 'chalk' module to add colors and styles to text in the console | ||
import chalk from "chalk"; |
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.
praise: 🌈
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.
Thank you!
// Array stores the names of the files and directories | ||
let displayFiles = []; | ||
// Ensure '.', '..' are on the top of list when we list hidden files | ||
if (showHiddenFiles) { |
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.
praise: This is a clever way of adding the dot directories
); | ||
}); | ||
// Array with style directory in bold and blue | ||
const styledAllFiles = await Promise.all(allFiles); |
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.
praise: Smart awaiting of Promises here
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.
Thank you!
implement-shell-tools/wc/wc.js
Outdated
// Split content into array by lines | ||
let arrayLines = content.split("\n"); | ||
// If the last line is empty - remove it | ||
while (arrayLines.length > 0 && arrayLines[arrayLines.length - 1].trim() === "") { |
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.
question: Do we really need a while
loop to achieve the result that we're looking for in the comment?
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.
You are right, we can simply filter out empty lines at the end by using arrayLines.filter(line => line.trim() !== "")
without needing the while loop. I have updated the code. Thank you, @ehwus Alex!
implement-shell-tools/wc/wc.js
Outdated
} | ||
|
||
// Get the number of lines | ||
const countNumLines = arrayLines.length; |
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.
nitpick: Do we always need to know the results of each of these?
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.
You're right, it's usually better to keep the code concise and avoid unnecessary variables. In this case, I used a variable because I needed the same value in two places, so it helped avoid repeating the calculation. But I agree, that keeping the code clean and minimal is a good practice.
.parse(process.argv); | ||
|
||
// Function to count bytes, words and lines in a file | ||
async function countDisplayNumBytesWordsLines(filePath, numLines = false, numWords = false, numBytes = false) { |
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.
praise: This function encapsculates the core logic well
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.
Thank you!
@ehwus Alex, thank you for your insightful and encouraging feedback, and the helpful link! I read through the article, and it was really useful for learning how to work with files one line at a time and manage memory more efficiently. I appreciate your support in writing cleaner and more maintainable code. |
Hello,
I've done all the tasks for the Implement-Shell-Tools.
Self checklist
Thank you.