Skip to content

Commit

Permalink
refactoring with GPT-4
Browse files Browse the repository at this point in the history
  • Loading branch information
bronvic committed Mar 23, 2023
1 parent 806d2dc commit dfa40ea
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 117 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "emphasize"
version = "0.1.1"
authors = ["Voronwe <voronwe.s@protonmail.com>"]
version = "0.1.2"
authors = ["Voronwe <mail@voronwe.me>"]
edition = "2021"

[dependencies]
Expand Down
97 changes: 84 additions & 13 deletions src/context.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
extern crate term;

use std::{collections::HashMap, str::FromStr, fs::File};
use regex::Regex;
use crate::options;
use regex::Regex;
use std::{
collections::HashMap,
fs::File,
io::{self, BufRead, BufReader, Stdout},
str::FromStr,
};
use term::Terminal;

pub struct Context {
// It would be great to have such generic iterator here, as commented below
// We could store there iterator over stdin or file and iterate like this:
// for line in context.input {

// Unfortunately, it seems impossible. And it is very very sad.
// https://stackoverflow.com/questions/55314607/how-to-store-an-iterator-over-stdin-in-a-structure#55314945

// TODO: become rust guru and resolve this problem

// pub input: Box<Iterator<Item = io::Result<String>>>

pub struct Context {
pub input_filename: String,
pub match_value: String,
pub is_regexp: bool,
Expand Down Expand Up @@ -146,6 +142,81 @@ impl Context {

context
}

pub fn get_input(&self) -> Box<dyn Iterator<Item = std::io::Result<String>>> {
if self.input_filename.is_empty() {
Box::new(io::stdin().lock().lines())
} else {
let file = File::open(&self.input_filename).expect("Can't open file");
Box::new(BufReader::new(file).lines())
}
}

pub fn match_line(&self, line: &str) -> bool {
if self.is_regexp {
Regex::new(&self.match_value).unwrap().is_match(line)
} else {
line.contains(&self.match_value)
}
}

pub fn print_emphasized_line(&self, line: &str, terminal: &mut Box<dyn Terminal<Output = Stdout> + Send>) {
for _ in 0..self.indent { println!(""); };

if self.with_color { terminal.fg(self.text_color).unwrap(); };

match self.frame_mode {
FrameMode::None => {
println!("{}", line);
},
FrameMode::Frame => {
println!("{}", self.emphasize_line(line.len()));
println!("{}", line);
println!("{}", self.emphasize_line(line.len()));
},
FrameMode::Prefix => {
println!("{}", self.prefix_line(line));
},
FrameMode::All => {
println!("{}", self.emphasize_line(line.len() + 4));
println!("{}", self.wrapped_line(line));
println!("{}", self.emphasize_line(line.len() + 4));
},
}

terminal.reset().unwrap();
for _ in 0..self.indent { println!(""); };
}

fn emphasize_line(&self, length: usize) -> String {
let mut emphasized_line = String::new();

for _ in 0..length {
emphasized_line.push(self.emphasizer);
}

emphasized_line
}

pub fn wrapped_line(&self, line: &str) -> String {
let prefix_line = self.prefix_line(line);

let mut wrapped_line = String::with_capacity(prefix_line.len() + 2);
wrapped_line.push_str(&prefix_line);
wrapped_line.push(' ');
wrapped_line.push(self.emphasizer);

wrapped_line
}

pub fn prefix_line(&self, line: &str) -> String {
let mut prefix_line = String::with_capacity(line.len() + 2);
prefix_line.push(self.emphasizer);
prefix_line.push(' ');
prefix_line.push_str(line);

prefix_line
}
}

pub enum FrameMode {
Expand Down
130 changes: 28 additions & 102 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,125 +1,51 @@
extern crate term;
extern crate getopts;
extern crate regex;

mod context;
mod options;

use std::io::{self, BufRead, BufReader};
use std::{env, fs::File};
use regex::Regex;
use crate::context::Context;
use crate::{context::Context, options::{new as new_options, print_usage}};
use std::{env, io::Stdout};
use term::{stdout, Terminal};


fn main() {
let args: Vec<String> = env::args().collect();
let program_name = args[0].clone();
let mut terminal = term::stdout().unwrap();

let context = Context::from_args(&args[1..]);
if context.print_help {
if !context.error_text.is_empty() {
terminal.fg(term::color::BRIGHT_RED).unwrap();
print!("{}\n\n", context.error_text);
terminal.reset().unwrap();
}

options::print_usage(&program_name, options::new());
print_help_text(&context.error_text, &program_name);
return;
}

// hack due to https://stackoverflow.com/questions/55314607/how-to-store-an-iterator-over-stdin-in-a-structure
let stdin;
let mut stdin_lines;
let mut file_lines;
let file;
let input: &mut dyn Iterator<Item = _> = match context.input_filename.is_empty() {
true => {
stdin = io::stdin();
stdin_lines = stdin.lock().lines();
&mut stdin_lines
}
false => {
file = match File::open(context.input_filename.clone()) {
Ok(file) => file,
Err(msg) => panic!("Can't open {}. Reason: {}", context.input_filename, msg),
};
file_lines = BufReader::new(file).lines();
&mut file_lines
}
};
let input = context.get_input();
process_input(input, &context);
}

fn print_help_text(error_text: &str, program_name: &str) {
let mut terminal: Box<dyn Terminal<Output = Stdout> + Send> = stdout().unwrap_or_else(|| {
eprintln!("Failed to initialize terminal.");
std::process::exit(1);
});

if !error_text.is_empty() {
terminal.fg(term::color::BRIGHT_RED).unwrap();
print!("{}\n\n", error_text);
terminal.reset().unwrap();
}

print_usage(&program_name.to_string(), new_options());
}

fn process_input(input: Box<dyn Iterator<Item = std::io::Result<String>>>, context: &Context) {
let mut terminal = term::stdout().unwrap();

for line in input {
let unwrapped_line = line.unwrap();
let matches: bool;

if context.is_regexp {
matches = Regex::new(&context.match_value).unwrap().is_match(&unwrapped_line);
} else {
matches = unwrapped_line.contains(&context.match_value);
}
let matches = context.match_line(&unwrapped_line);

if !matches {
println!("{}", unwrapped_line);
} else {
// indent before
for _ in 0..context.indent { println!(""); };
// color settings
if context.with_color { terminal.fg(context.text_color).unwrap(); };

// text framing
match context.frame_mode {
context::FrameMode::None => {
println!("{}", unwrapped_line);
},
context::FrameMode::Frame => {
println!("{}", emphasize_line(context.emphasizer, unwrapped_line.len()));
println!("{}", unwrapped_line);
println!("{}", emphasize_line(context.emphasizer, unwrapped_line.len()));
},
context::FrameMode::Prefix => {
println!("{}", prefix_line(&unwrapped_line, context.emphasizer));
},
context::FrameMode::All => {
println!("{}", emphasize_line(context.emphasizer, unwrapped_line.len() + 4));
println!("{}", wrapped_line(&unwrapped_line, context.emphasizer));
println!("{}", emphasize_line(context.emphasizer, unwrapped_line.len() + 4));
},
}

// Reset after color change
// TODO: most likely logs can have there own terminal settings and want not reset, but turn them back. check it
terminal.reset().unwrap();
// indent after
for _ in 0..context.indent { println!(""); };
context.print_emphasized_line(&unwrapped_line, &mut terminal);
}
}
}

fn emphasize_line(emphasizer: char, length: usize) -> String {
let mut emphasize_line = String::with_capacity(length);
for _ in 0..length {
emphasize_line.push(emphasizer);
}

emphasize_line
}

fn prefix_line(line: &String, prefix: char) -> String {
let mut prefix_line = String::with_capacity(line.len() + 2);
prefix_line.push(prefix);
prefix_line.push(' ');
prefix_line.push_str(line);

prefix_line
}

fn wrapped_line(line: &String, wrapper: char) -> String {
let prefix_line = prefix_line(line, wrapper);

let mut wrapped_line = String::with_capacity(prefix_line.len() + 2);
wrapped_line.push_str(&prefix_line);
wrapped_line.push(' ');
wrapped_line.push(wrapper);

wrapped_line
}

0 comments on commit dfa40ea

Please sign in to comment.