Skip to content

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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

nadika-zavodovska
Copy link

Hello,

I've done all the tasks for the Implement-Shell-Tools.

Self checklist

  • I have committed my files one by one, on purpose, and for a reason
  • I have titled my PR with COHORT_NAME | FIRST_NAME LAST_NAME | REPO_NAME | WEEK
  • I have tested my changes
  • My changes follow the style guide
  • My changes meet the requirements of this task

Thank you.

@ehwus ehwus added Review in progress This review is currently being reviewed. This label will be replaced by "Reviewed" soon. and removed Needs Review Participant to add when requesting review labels Mar 29, 2025
Copy link

@ehwus ehwus left a 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!

return line;
});
// join lines back to the string and print them
console.log(arrayContentLines.join("\n"));
Copy link

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?

Copy link
Author

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

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

Copy link
Author

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

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?

Copy link
Author

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) {
Copy link

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?

Copy link
Author

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

Choose a reason for hiding this comment

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

praise: 🌈

Copy link
Author

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) {
Copy link

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

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

Copy link
Author

Choose a reason for hiding this comment

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

Thank you!

// 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() === "") {
Copy link

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?

Copy link
Author

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!

}

// Get the number of lines
const countNumLines = arrayLines.length;
Copy link

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?

Copy link
Author

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) {
Copy link

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

Copy link
Author

Choose a reason for hiding this comment

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

Thank you!

@ehwus ehwus added Reviewed Volunteer to add when completing a review and removed Review in progress This review is currently being reviewed. This label will be replaced by "Reviewed" soon. labels Mar 29, 2025
@nadika-zavodovska
Copy link
Author

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Reviewed Volunteer to add when completing a review 📅 Sprint 3 Assigned during Sprint 3 of this module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants