Skip to content

London | 25-SDC-July | Andrei Filippov | Sprint 3 | Implement shell tools#1

Open
Droid-An wants to merge 3 commits intoCodeYourFuture:mainfrom
Droid-An:implement-shell-tools
Open

London | 25-SDC-July | Andrei Filippov | Sprint 3 | Implement shell tools#1
Droid-An wants to merge 3 commits intoCodeYourFuture:mainfrom
Droid-An:implement-shell-tools

Conversation

@Droid-An
Copy link
Collaborator

Learners, PR Template

Self checklist

  • I have committed my files one by one, on purpose, and for a reason
  • I have titled my PR with Region | Cohort | FirstName LastName | Sprint | Assignment Title
  • I have tested my changes
  • My changes follow the style guide
  • My changes meet the requirements of this task

Changelist

Done shell tools

Questions

none

@github-actions

This comment has been minimized.

@Droid-An Droid-An added the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Mar 13, 2026
@github-actions

This comment has been minimized.

@github-actions github-actions bot removed the Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. label Mar 13, 2026
@Droid-An Droid-An added NotCoursework Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. 🧠 Prep work Prep material to be completed before Saturday's session 👀 Review Git Changes requested to do with Git and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. 🧠 Prep work Prep material to be completed before Saturday's session 👀 Review Git Changes requested to do with Git labels Mar 13, 2026
@cyf-ai-code-reviewer
Copy link

Thanks for opening a new PR! AI started to review it

Comment on lines +39 to +52
async function example(path) {
try {
const data = await fs.readFile(path, { encoding: "utf8" });
if (opts["b"]) {
countLines(data);
} else if (opts["n"]) {
countLines(data);
} else {
console.log(data.trimEnd());
}
} catch (err) {
console.error(err);
}
}

Choose a reason for hiding this comment

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

How do you usually choose names for your functions and variables? What could you rename 'example' and 'argv' to make their purposes clearer, both to you in the future and to someone else reading your code?

Comment on lines +24 to +36
for (const line of lines) {
if (opts.b) {
if (line.trim() === "") {
console.log();
} else {
console.log(`${lineNum} ${line}`);
lineNum++;
}
} else if (opts.n) {
console.log(`${lineNum} ${line}`);
lineNum++;
}
}

Choose a reason for hiding this comment

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

When you have two code sections that are very similar except for a small difference, is there a way you could combine them? What would that look like here?

}
})();

const flag_1 = (files) => {

Choose a reason for hiding this comment

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

If you explained what each function and variable does to a friend who had never seen the code, what might you name them instead so they're easy to understand?

Comment on lines +23 to +45
if (programArgv.length === 1) {
pathToFile = programArgv[0];
try {
const stats = await fs.stat(pathToFile);
if (stats.isFile()) {
await listFiles("file");
} else if (stats.isDirectory()) {
listFiles("directory");
} else {
console.error("Not a file or directory.");
}
} catch (err) {
console.error("Invalid path:", err.message);
}
} else if (programArgv.length === 0) {
pathToFile = process.cwd();
await listFiles("directory");
} else {
console.error(
`Expected no more than 1 argument (sample-files) but got ${programArgv.length}.`
);
}
})();

Choose a reason for hiding this comment

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

Is there a way you could structure your code so the decision of whether to list files, directories, or error messages, and how to display them, is handled in just one spot? Why might that make maintenance simpler over time?


program.parse();

let pathToFile = "";

Choose a reason for hiding this comment

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

Can you spot a way to limit the scope of 'pathToFile' so it's only available where it's actually used? What changes would that require in your structure?

Comment on lines +46 to +54
if (opts["l"]) {
outputPerFile.push(flag_l(content));
}
if (opts["w"]) {
outputPerFile.push(flag_w(content));
}
if (opts["c"]) {
outputPerFile.push(flag_c(content));
}

Choose a reason for hiding this comment

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

If you look for patterns in the way you're handling each of the '-l', '-w', and '-c' options, can you imagine a way to combine the operations to make your code shorter and easier to change in the future?

const total = [];
const output = [];
const countsPerFile = [];
let columnWidth = 0;

Choose a reason for hiding this comment

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

What would happen if you moved the declaration of 'columnWidth' inside 'handleInput' instead of declaring it outside? How might that affect readability and maintainability for you or someone else looking at your code?

.argument("<sample-files...>", "The file path to process")
.parse();

const argv = program.args;

Choose a reason for hiding this comment

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

How do you usually choose names for your functions and variables? What could you rename 'example' and 'argv' to make their purposes clearer, both to you in the future and to someone else reading your code?

});
};

const flag_a = (files) => {

Choose a reason for hiding this comment

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

If you explained what each function and variable does to a friend who had never seen the code, what might you name them instead so they're easy to understand?

Comment on lines +59 to +86
async function listFiles(type) {
let output = [];
let formattedPath = "";
if (type == "directory") {
formattedPath = pathToFile;
} else if (type == "file") {
formattedPath = path.dirname(pathToFile);
}
const char = program.opts();
const files = await fs.readdir(formattedPath);
const sortedOutput = files.sort((a, b) => a.localeCompare(b));

if (char["a"]) {
output = flag_a(sortedOutput);
} else {
sortedOutput.forEach(function (file) {
if (file[0] != ".") {
output.push(file);
}
});
}

if (char["1"]) {
flag_1(output);
} else {
console.log(output.join(" "));
}
}

Choose a reason for hiding this comment

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

Is there a way you could structure your code so the decision of whether to list files, directories, or error messages, and how to display them, is handled in just one spot? Why might that make maintenance simpler over time?


(async () => {
if (programArgv.length === 1) {
pathToFile = programArgv[0];

Choose a reason for hiding this comment

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

Can you spot a way to limit the scope of 'pathToFile' so it's only available where it's actually used? What changes would that require in your structure?

Comment on lines +81 to +91
for (const row of output) {
for (let i = 0; i < numOfColumns; i++) {
columnWidth = Math.max(columnWidth, String(row[i]).length);
}
}

for (let row of output) {
const line_parts = [];
for (let i = 0; i < numOfColumns; i++) {
line_parts.push(String(row[i]).padStart(columnWidth + 4));
}

Choose a reason for hiding this comment

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

What would happen if you moved the declaration of 'columnWidth' inside 'handleInput' instead of declaring it outside? How might that affect readability and maintainability for you or someone else looking at your code?

} else if (type == "file") {
formattedPath = path.dirname(pathToFile);
}
const char = program.opts();

Choose a reason for hiding this comment

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

If you explained what each function and variable does to a friend who had never seen the code, what might you name them instead so they're easy to understand?

console.error("Invalid path:", err.message);
}
} else if (programArgv.length === 0) {
pathToFile = process.cwd();

Choose a reason for hiding this comment

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

Can you spot a way to limit the scope of 'pathToFile' so it's only available where it's actually used? What changes would that require in your structure?

Comment on lines +63 to +65
formattedPath = pathToFile;
} else if (type == "file") {
formattedPath = path.dirname(pathToFile);

Choose a reason for hiding this comment

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

Can you spot a way to limit the scope of 'pathToFile' so it's only available where it's actually used? What changes would that require in your structure?

@Droid-An Droid-An added Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Mar 15, 2026
@cyf-ai-code-reviewer
Copy link

Thanks for opening a new PR! AI started to review it

Comment on lines +39 to +52
async function example(path) {
try {
const data = await fs.readFile(path, { encoding: "utf8" });
if (opts["b"]) {
countLines(data);
} else if (opts["n"]) {
countLines(data);
} else {
console.log(data.trimEnd());
}
} catch (err) {
console.error(err);
}
}

Choose a reason for hiding this comment

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

How do you decide on meaningful names for your functions? Can you think of a name that might better communicate this function's purpose?

Comment on lines +41 to +46
const data = await fs.readFile(path, { encoding: "utf8" });
if (opts["b"]) {
countLines(data);
} else if (opts["n"]) {
countLines(data);
} else {

Choose a reason for hiding this comment

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

When two different options lead to almost the same behavior, what pattern could you use to reduce duplicated code and keep it easier to update later?

Comment on lines +24 to +36
for (const line of lines) {
if (opts.b) {
if (line.trim() === "") {
console.log();
} else {
console.log(`${lineNum} ${line}`);
lineNum++;
}
} else if (opts.n) {
console.log(`${lineNum} ${line}`);
lineNum++;
}
}

Choose a reason for hiding this comment

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

When two different options lead to almost the same behavior, what pattern could you use to reduce duplicated code and keep it easier to update later?


program.parse();

let pathToFile = "";

Choose a reason for hiding this comment

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

Why do you think keeping variables inside the smallest possible scope is a helpful practice? Can you imagine how this variable could be kept within the async block or passed as a parameter instead of being an outer variable?


(async () => {
if (programArgv.length === 1) {
pathToFile = programArgv[0];

Choose a reason for hiding this comment

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

Why do you think keeping variables inside the smallest possible scope is a helpful practice? Can you imagine how this variable could be kept within the async block or passed as a parameter instead of being an outer variable?

if (type == "directory") {
formattedPath = pathToFile;
} else if (type == "file") {
formattedPath = path.dirname(pathToFile);

Choose a reason for hiding this comment

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

Why do you think keeping variables inside the smallest possible scope is a helpful practice? Can you imagine how this variable could be kept within the async block or passed as a parameter instead of being an outer variable?

Comment on lines +47 to +51
const flag_1 = (files) => {
files.forEach(function (file) {
console.log(file);
});
};

Choose a reason for hiding this comment

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

When you name your functions, how do you decide on a name? What might be some more descriptive names for flag_1?

Comment on lines +74 to +78
sortedOutput.forEach(function (file) {
if (file[0] != ".") {
output.push(file);
}
});

Choose a reason for hiding this comment

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

Have you encountered array filter methods before? How could you use them to make this block of code shorter or clearer?

Comment on lines +43 to +67
const countAndDisplay = async (path) => {
const outputPerFile = [];
const content = await fs.readFile(path, "utf-8");
if (opts["l"]) {
outputPerFile.push(flag_l(content));
}
if (opts["w"]) {
outputPerFile.push(flag_w(content));
}
if (opts["c"]) {
outputPerFile.push(flag_c(content));
}
if (argv.length > 1) {
if (total.length == 0) {
total.push(...outputPerFile);
} else {
for (let index = 0; index < outputPerFile.length; index++) {
total[index] += outputPerFile[index];
}
}
countsPerFile.push(...outputPerFile);
}
outputPerFile.push(path);
output.push([...outputPerFile]);
};

Choose a reason for hiding this comment

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

If you wanted to adapt this code to work differently (for example, outputting results in a different format), how might breaking this apart into smaller functions make it easier to change?

Comment on lines +46 to +54
if (opts["l"]) {
outputPerFile.push(flag_l(content));
}
if (opts["w"]) {
outputPerFile.push(flag_w(content));
}
if (opts["c"]) {
outputPerFile.push(flag_c(content));
}

Choose a reason for hiding this comment

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

What would happen if you had to add more options like -m for characters? Can you imagine a way to pair up the options with their processing functions so the code to handle them doesn't need to be written out every time?

@Droid-An Droid-An added Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Mar 15, 2026
@cyf-ai-code-reviewer
Copy link

Thanks for opening a new PR! AI started to review it

Comment on lines +59 to +86
async function listFiles(type) {
let output = [];
let formattedPath = "";
if (type == "directory") {
formattedPath = pathToFile;
} else if (type == "file") {
formattedPath = path.dirname(pathToFile);
}
const char = program.opts();
const files = await fs.readdir(formattedPath);
const sortedOutput = files.sort((a, b) => a.localeCompare(b));

if (char["a"]) {
output = flag_a(sortedOutput);
} else {
sortedOutput.forEach(function (file) {
if (file[0] != ".") {
output.push(file);
}
});
}

if (char["1"]) {
flag_1(output);
} else {
console.log(output.join(" "));
}
}

Choose a reason for hiding this comment

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

What do you think a better name for the function that handles both files and directories could be? Does calling it 'listFiles' match what you expect it to do when reading code?

Comment on lines +53 to +57
const flag_a = (files) => {
files.unshift("..");
files.unshift(".");
return files;
};

Choose a reason for hiding this comment

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

How could you ensure that you're not duplicating '.' and '..' entries if flag_a gets called several times on the same array? What do you think would happen currently if someone tried that?


program.parse();

let pathToFile = "";

Choose a reason for hiding this comment

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

What would be the effect of declaring pathToFile inside your main async function, instead of at the top? Would this make it clearer where it's used and how it's set?

Comment on lines +26 to +28
const total = [];
const output = [];
const countsPerFile = [];

Choose a reason for hiding this comment

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

Do you see a way to combine or clarify these arrays so it's obvious what each one does, or maybe structure your results a little differently for clarity and future flexibility?

Comment on lines +39 to +41
const flag_l = (content) => {
return content.split("\n").length - 1;
};

Choose a reason for hiding this comment

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

How could you ensure that the count matches typical behavior, especially for files that may or may not end with a newline? Could you test with different kinds of files and see what outputs you get?

Comment on lines +42 to +46
if (opts["b"]) {
countLines(data);
} else if (opts["n"]) {
countLines(data);
} else {

Choose a reason for hiding this comment

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

Is there a case where both -b and -n could be set? What does the standard tool do if this happens? Could you adjust your logic to handle this in a way that would make sense to users?

Comment on lines +39 to +52
async function example(path) {
try {
const data = await fs.readFile(path, { encoding: "utf8" });
if (opts["b"]) {
countLines(data);
} else if (opts["n"]) {
countLines(data);
} else {
console.log(data.trimEnd());
}
} catch (err) {
console.error(err);
}
}

Choose a reason for hiding this comment

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

Is there another function name that would help a future reader quickly understand what this function does? What about something like 'processFile'?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. NotCoursework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant