Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions implement-shell-tools/cat/cat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import process from "node:process";
import { promises as fs } from "node:fs";

const argv = process.argv.slice(2, process.argv.length);
const flags = [];
const paths = [];
for (let i = 0; i < argv.length; i++) {
if (argv[i][0] == "-") {
flags.push(argv[i]);
} else {
paths.push(argv[i]);
}
}

displayFiles(paths, flags);

async function displayFiles(paths, flags) {
let content = '';
for (let i = 0; i < paths.length; i++) {
content += await fs.readFile(paths[i], "utf-8");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What happens if we can't open one of the files?

}

const lines = content.split("\n");
if (lines[lines.length - 1] == '') {
lines.pop();
}
let lineNumber = 1;
for (let i = 0; i < lines.length; i++) {
let output = lines[i];
if (
(flags.includes("-n") && !flags.includes("-b")) ||
(flags.includes("-b") && lines[i] != "")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

shouldn't we use strict inequality in javascript?

) {
output = " " + (lineNumber).toString() + " " + lines[i];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Here we always prepend 5 spaces. But we need to right-align into a fixed-width field. (So numbers like 10, 100 etc does not shift the column

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Real cat uses tab separator between number and lines

lineNumber++;
}
console.log(output);
}
}

27 changes: 27 additions & 0 deletions implement-shell-tools/ls/ls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import process from "node:process";
import { promises as fs } from "node:fs";

const argv = process.argv.slice(2, process.argv.length);
const currentDir = './';
const flags = [];
let path = '';
for (let i = 0; i < argv.length; i++) {
if (argv[i][0] == "-") {
flags.push(argv[i]);
} else {
path = argv[i];
}
}
if (path == '') path = currentDir;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do we have multiple path support?


const content = await fs.readdir(path);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Raw reddir includes hidden files, is it intentional?


if (flags.includes("-l")) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

We should use flag -1, not -l

for (let i = 0; i < content.length; i++) {
let line = content[i];
if (!flags.includes("-a") && line[0] == ".") continue;
console.log(line);
}
} else {
console.log(content.join(" "));
}
13 changes: 13 additions & 0 deletions implement-shell-tools/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "implement-shell-tools",
"version": "1.0.0",
"type": "module",
"description": "Your task is to re-implement shell tools you have used.",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
91 changes: 91 additions & 0 deletions implement-shell-tools/wc/wc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import process from "node:process";
import { promises as fs } from "node:fs";

const argv = process.argv.slice(2, process.argv.length);
let flag = '';
const paths = [];
let dir = '';
let ending = '';
for (let i = 0; i < argv.length; i++) {
if (argv[i][0] == "-") {
flag = argv[i];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What if we have multiple flags passed?

} else {
paths.push(argv[i]);
}
}

if (paths.length > 0) {
dir = paths[0].slice(0, paths[0].indexOf("/"));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This approach means node wc.js dir/a.txt dir/b.txt reads every file in dir/ instead of just a.txt and b.txt.

ending = paths[0].slice(paths[0].indexOf("/") + 1);
};

const files = await resolveQuery(paths, dir, ending);
await logFilesInfo(files, flag);

async function resolveQuery(paths, dir, ending) {
let files = [];
if (paths.length > 1) {
files = await fs.readdir(dir);
} else {
files = [ending];
}
return files;
}

async function logFilesInfo(files, flag) {
let totalLines = 0;
let totalWords = 0;
let totalBytes = 0;
let totalOutput = '';
for (const fileName of files) {
let fileOutput = '';
let filePath = dir + "/" + fileName;
let file = await fs.readFile(filePath, "utf-8");
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What will happen if the file does not exist?

let linesNum = countLinesInString(file);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

we do not reassign let- variables here, so we should use const instead

let wordsNum = countWordsInString(file);
let bytes = file.length;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

what will happen with length if the file has non ASCII characters?

totalLines += linesNum;
totalWords += wordsNum;
totalBytes += bytes;
if (flag == "-l") {
fileOutput = linesNum + " " + filePath;
} else if (flag == "-w") {
fileOutput = wordsNum + " " + filePath;
} else if (flag == '-c') {
fileOutput = bytes + " " + filePath;
} else {
fileOutput = linesNum + " " + wordsNum + " " + bytes + " " + filePath;
}
console.log(fileOutput);
}
if (files.length > 1) {
if (flag == "-l") {
totalOutput = totalLines + " total";
} else if (flag == "-w") {
totalOutput = totalWords + " total";
} else if (flag == '-c') {
totalOutput = totalBytes + " total";
} else {
totalOutput = totalLines + " " + totalWords + " " + totalBytes + " total";
}
console.log(totalOutput);
}
}

function countLinesInString(str) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

like for splitting logic intot functions

let lines = str.split('\n');
let linesNum = lines.length;
if (lines[lines.length - 1] == '') {
linesNum--;
}
return linesNum;
}

function countWordsInString(str) {
let words = str.replace(/\n/g, ' ').split(' ');
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do we need to take tabs and other whitespace into account?

words = words.filter((word) => {
return (word != '')
});
let wordsNum = words.length;
return wordsNum;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Trailing new line is missing

Loading