Skip to content

Commit

Permalink
before, after, section added
Browse files Browse the repository at this point in the history
  • Loading branch information
raikoug committed Apr 7, 2024
1 parent 05b13de commit 3c0e8a0
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 16 deletions.
37 changes: 26 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@ Arguments:
[PATH] The path to the file to read

Options:
-c, --color <COLOR> Color to use [default: red] [possible values: red, green, blue, yellow, magenta, cyan, white, black, bright-red, bright-green, bright-blue, bright-yellow, bright-magenta, bright-cyan, bright-white]
-b, --bold Bold
-u, --underline Underline
-i, --italic Italic
-s, --strike StrikeThrough
-l, --line-numbers Show LineNumbers
-R, --regex Pattern is a Regex
-I, --insensitive Case Insensitive
-d, --debug Debug
-h, --help Print help
-V, --version Print version
-c, --color <COLOR> Color to use [default: red] [possible values: red, green, blue, yellow, magenta, cyan, white, black, bright-red, bright-green, bright-blue, bright-yellow, bright-magenta, bright-cyan, bright-white]
-b, --bold Bold
-u, --underline Underline
-i, --italic Italic
-s, --strike StrikeThrough
-l, --line-numbers Show LineNumbers
-R, --regex Pattern is a Regex
-a, --after <AFTER> Show lines after the match
-b, --before <BEFORE> Show lines before the match
-S, --section Show lines before and after the match
-t, --tabs_c Value of spaces to evaluate a tab
-I, --insensitive Case Insensitive
-d, --debug Debug
-h, --help Print help
-V, --version Print version
```
## Setting up MyGrep with Windows Environment Variables

Expand All @@ -60,6 +64,17 @@ To use `mygrep` from any location in the command prompt, you need to add it to y

Now, you should be able to use `mygrep` from any location in the command prompt. Just type `mygrep` followed by your commands.

# Build it youself
```bash
git clone
cd mygrep
cargo build --release
```
Move it to the path
```bash
cp target/release/mygrep /usr/local/bin
```

# Exit Codes
```
0: Success
Expand Down
147 changes: 142 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use colored::*;
use std::io::{self, BufRead};
use regex::Regex;
use std::error::Error;
use std::process;
use std::{process, vec};


/// Search for a pattern in a file and display the lines that contain it.
#[derive(Parser, Debug, Clone)]
#[command(name = "MyGrep")]
#[command(author = "Riccardo Bella <[email protected]>")]
#[command(version = "1.0.0")]
#[command(version = "1.1.0")]
#[command(about = "Grep Equivalent", long_about = None)]
#[command(author, version, about, long_about = None)]
#[command(about, version, after_help =
Expand All @@ -26,6 +26,10 @@ use std::process;
The line_numbers option is used to show the line number of the pattern found.\n\
The regex option is used to search for a regex pattern.\n\
The insensitive option is used to search for a case insensitive pattern.\n\
The after option is used to print the number of lines after the match (not compatible with section).\n\
The before option is used to print the number of lines before the match (not compatible with section).\n\
The section option is used to print the section (same indentation or more) of the file where the pattern is found. (Not compatible with after and or before)\n\
The tabs_c option is used to set the number of spaces for a tab. Default is 4.\n\
The debug option is used to print all the args for debug.\n\
\n\
Example:\n\
Expand Down Expand Up @@ -53,7 +57,7 @@ struct Cli {
color: Colors,

/// Bold
#[arg(short, long, default_value_t = true)]
#[arg(short = 'B', long, default_value_t = true)]
bold: bool,

/// Underline
Expand All @@ -80,6 +84,22 @@ struct Cli {
#[arg(short = 'I', long, default_value_t = false)]
insensitive: bool,

/// After
#[arg(short, long, default_value_t = 0)]
after: usize,

/// Before
#[arg(short, long, default_value_t = 0)]
before: usize,

/// Section
#[arg(short = 'S', long, default_value_t = false)]
section: bool,

/// Tabs count
#[arg(short, long, default_value_t = 4)]
tabs_c: usize,

/// Debug
#[arg(short, long, default_value_t = false)]
debug: bool,
Expand Down Expand Up @@ -136,8 +156,17 @@ fn get_grep_indexes(line: &str, regex_pattern: &str) -> Vec<(usize, usize)>{
indexes
}

fn indentation(line: &str, tabs_c: usize) -> usize {
// return the number of spaces at the beginning of the line
let spaces = line.chars().take_while(|&c| c == ' ').count();
let tabs = line.chars().take_while(|&c| c == '\t').count() * tabs_c;

spaces + tabs

}

fn main() -> Result<()> {
let args = Cli::parse();
let mut args = Cli::parse();

// print all args for debug
if args.debug {
Expand All @@ -152,6 +181,9 @@ fn main() -> Result<()> {
println!("args.line_numbers: {}", args.line_numbers);
println!("args.regex: {}", args.regex);
println!("args.insensitive: {}", args.insensitive);
println!("args.after: {}", args.after);
println!("args.before: {}", args.before);
println!("args.section: {}", args.section);
println!("args.debug: {}", args.debug);
println!("----------------------------");
println!();
Expand All @@ -173,6 +205,17 @@ fn main() -> Result<()> {
}
}

// If section is true and before and after are != 0, print warning and set after and before to 0
if args.section && (args.before != 0 || args.after != 0) {
eprintln!("Section is not compatible with after and or before. Ignoring After and or Before.");
args.after = 0;
args.before = 0;
}
// the section behaviour could print multiple time the same section, this avoid this behavior.
let mut sections_to_print: Vec<usize> = vec![];
// init a found_rows to keep colored lines to be printed with found pattern, a tuple of index and string
let mut found_rows: Vec<(usize, String)> = vec![];

// color must be string to use it in replace
let color = format!("{:?}", args.color);

Expand Down Expand Up @@ -218,8 +261,78 @@ fn main() -> Result<()> {
if args.line_numbers {
colored_line = format!("{}: {}", index+1, colored_line);
}
println!("{}", colored_line);

// Before lines, args.before is the number of lines to print before the match, default 0
if args.before > 0 {
if index >= 1 {
let mut before_indexes = vec![];
for i in 1..=args.before {
if index < i {
break;
}
let tmp_index = index - i;

before_indexes.push(tmp_index);
}
before_indexes.reverse();
for i in before_indexes {
let before_line = content.lines().nth(i).unwrap();
println!("{}", before_line);
}
}
}

if !args.section{
println!("{}", colored_line);
}

// After lines, args.after is the number of lines to print after the match, default 0
if args.after > 0 {
for i in 1..=args.after {
if index + i < content.lines().count() {
let after_line = content.lines().nth(index + i).unwrap();
println!("{}", after_line);
}
}
}

// Section, if true print the section.
// Section is the same indentation or more of the line where the pattern is found.
// Section can start before the finding
if args.section {
// init indentation
let starting_indentation = indentation(&line, args.tabs_c);
sections_to_print.push(index);
// keep the index where pattern is found along with colored string
found_rows.push((index, colored_line));

// scroll backwards indexes, break if indentation is <= starting_indentation
for i in (0..index).rev() {
let tmp_line = content.lines().nth(i).unwrap();
let tmp_indentation = indentation(&tmp_line, args.tabs_c);
if tmp_indentation < starting_indentation {
// if indentation is <= starting_indentation, break
// get the index as head of the section
sections_to_print.push(i);
break;
}
sections_to_print.push(i);
}

// scroll forward indexes, break if indentation is < starting_indentation
for i in index..content.lines().count() {
let tmp_line = content.lines().nth(i).unwrap();
let tmp_indentation = indentation(&tmp_line, args.tabs_c);
if tmp_indentation < starting_indentation {
// if indentation is < starting_indentation, break
break;
}
sections_to_print.push(i);
}

}
}

},
Err(_) => {
let error_message = "Pattern is not a valid regex: ".color("red").bold().to_string();
Expand All @@ -229,5 +342,29 @@ fn main() -> Result<()> {
}
}

if args.section{
// sections_to_print is a list olf indexes to print, but are unordered and maybe duplicate.
// we need to sort and remove duplicates
sections_to_print.sort();
sections_to_print.dedup();

// print all indexes in sections_to_print
for index in sections_to_print {
// if index in found_rows, print the colored line instead of the normal line
if found_rows.iter().any(|x| x.0 == index) {
let colored_line = found_rows.iter().find(|&x| x.0 == index).unwrap().1.clone();
println!("{}", colored_line);
continue;
}

let line = content.lines().nth(index).unwrap();
if args.line_numbers {
println!("{}: {}", index+1, line);
} else {
println!("{}", line);
}
}
}

Ok(())
}
10 changes: 10 additions & 0 deletions test_after_before.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
1
2
3
4
5
6
7
8
9
0
2 changes: 2 additions & 0 deletions test.txt → test_base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ [email protected]
non&[email protected]
[email protected]

ciao ciao ciao ciao

21:46:19.693601 IP 10.10.1.10.60460 > 10.10.1.199.5432: Flags [S], seq 116466344, win 29200, options [mss 1460,sackOK,TS val 3547090332 ecr 0,nop,wscale 7], length 0
21:46:19.693626 IP 10.10.1.10.35470 > 10.10.1.199.513: Flags [S], seq 3400074709, win 29200, options [mss 1460,sackOK,TS val 3547090332 ecr 0,nop,wscale 7], length 0
21:46:19.693762 IP 10.10.1.10.44244 > 10.10.1.199.389: Flags [S], seq 2214070267, win 29200, options [mss 1460,sackOK,TS val 3547090333 ecr 0,nop,wscale 7], length 0
Expand Down
15 changes: 15 additions & 0 deletions test_indentation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
section 1
item abc
item bcd
item cde
subitem xyz
subitem wxy
item def
section 2
item efg
item fgh
item ghi
last
item hik
section 3
section 4

0 comments on commit 3c0e8a0

Please sign in to comment.