Skip to content

Commit f4d8a3e

Browse files
committed
Add exercise grep
1 parent 45f1677 commit f4d8a3e

File tree

9 files changed

+428
-0
lines changed

9 files changed

+428
-0
lines changed

exercises/grep/.eslintrc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"root": true,
3+
"parser": "babel-eslint",
4+
"parserOptions": {
5+
"ecmaVersion": 7,
6+
"sourceType": "module"
7+
},
8+
"env": {
9+
"es6": true,
10+
"node": true,
11+
"jest": true
12+
},
13+
"extends": [
14+
"eslint:recommended",
15+
"plugin:import/errors",
16+
"plugin:import/warnings"
17+
],
18+
"rules": {
19+
"linebreak-style": "off",
20+
21+
"import/extensions": "off",
22+
"import/no-default-export": "off",
23+
"import/no-unresolved": "off",
24+
"import/prefer-default-export": "off"
25+
}
26+
}

exercises/grep/babel.config.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
presets: [
3+
[
4+
'@babel/env',
5+
{
6+
targets: {
7+
node: 'current',
8+
},
9+
useBuiltIns: false,
10+
},
11+
12+
],
13+
],
14+
};

exercises/grep/data/iliad.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Achilles sing, O Goddess! Peleus' son;
2+
His wrath pernicious, who ten thousand woes
3+
Caused to Achaia's host, sent many a soul
4+
Illustrious into Ades premature,
5+
And Heroes gave (so stood the will of Jove)
6+
To dogs and to all ravening fowls a prey,
7+
When fierce dispute had separated once
8+
The noble Chief Achilles from the son
9+
Of Atreus, Agamemnon, King of men.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
I do entreat your grace to pardon me.
2+
I know not by what power I am made bold,
3+
Nor how it may concern my modesty,
4+
In such a presence here to plead my thoughts;
5+
But I beseech your grace that I may know
6+
The worst that may befall me in this case,
7+
If I refuse to wed Demetrius.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Of Mans First Disobedience, and the Fruit
2+
Of that Forbidden Tree, whose mortal tast
3+
Brought Death into the World, and all our woe,
4+
With loss of Eden, till one greater Man
5+
Restore us, and regain the blissful Seat,
6+
Sing Heav'nly Muse, that on the secret top
7+
Of Oreb, or of Sinai, didst inspire
8+
That Shepherd, who first taught the chosen Seed

exercises/grep/example.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/usr/bin/env node
2+
const fs = require('fs')
3+
4+
// Helpers
5+
const availables_options = [
6+
'n', // add line numbers
7+
'l', // print file names where pattern is found
8+
'i', // ignore case
9+
'v', // reverse files results
10+
'x' // match entire line
11+
];
12+
13+
const does_line_matche_pattern = (line, pattern) => {
14+
let left = line;
15+
let right = pattern;
16+
17+
if (is_option_set('i')) {
18+
left = line.toLowerCase()
19+
right = pattern.toLowerCase()
20+
}
21+
22+
if (is_option_set('x')) {
23+
return left === right;
24+
}
25+
26+
return left.match(right) !== null;
27+
28+
}
29+
30+
const getConfigFromArgs = () => {
31+
const config = {
32+
'pattern': '',
33+
'options': [],
34+
'files': []
35+
};
36+
37+
let has_pattern_been_found = false;
38+
39+
process.argv.slice(2).forEach(val => {
40+
if (has_pattern_been_found) {
41+
config.files.push(val)
42+
} else if (val.indexOf('-') !== -1) {
43+
const option = val.replace('-', '')
44+
45+
if (!availables_options.includes(option)) {
46+
throw new Error(`Unknown option ${option}`)
47+
}
48+
49+
config.options.push(option)
50+
} else {
51+
has_pattern_been_found = true
52+
config.pattern = val
53+
}
54+
})
55+
56+
return config;
57+
}
58+
59+
const config = getConfigFromArgs()
60+
const is_option_set = option => config.options.includes(option);
61+
62+
// Actual script
63+
config.files.forEach(file => {
64+
const data = fs.readFileSync(file, { encoding: 'utf-8' })
65+
66+
if (is_option_set('l')) {
67+
data.split('\n').find(line => {
68+
const does_line_match_pattern = does_line_matche_pattern(line, config.pattern)
69+
70+
return is_option_set('v') ? !does_line_match_pattern : does_line_match_pattern
71+
}) && console.log(file)
72+
} else {
73+
data.split('\n').forEach((line, index) => {
74+
let result = '';
75+
let should_output_line = does_line_matche_pattern(line, config.pattern);
76+
77+
if (is_option_set('v')) {
78+
should_output_line = !should_output_line;
79+
}
80+
81+
if (should_output_line) {
82+
if (config.files.length > 1) {
83+
result += `${file}:`
84+
}
85+
86+
if (is_option_set('n')) {
87+
result += `${index+1}:`;
88+
}
89+
90+
result += line;
91+
92+
console.log(result)
93+
}
94+
})
95+
}
96+
});

exercises/grep/grep.js

Whitespace-only changes.

0 commit comments

Comments
 (0)