From b0a2631193d3285c3fa3ede1b793d4f34d48cc42 Mon Sep 17 00:00:00 2001 From: Akemi Izuko Date: Sat, 23 Dec 2023 20:14:05 -0700 Subject: [PATCH] Rewrite: prettify_bash_history --- bin/rewritten_in_rust/.gitignore | 2 + bin/rewritten_in_rust/Cargo.toml | 16 +++ .../src/prettify_bash_history.rs | 101 ++++++++++++++++++ post_install.sh | 67 +++++++++++- 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 bin/rewritten_in_rust/.gitignore create mode 100644 bin/rewritten_in_rust/Cargo.toml create mode 100644 bin/rewritten_in_rust/src/prettify_bash_history.rs diff --git a/bin/rewritten_in_rust/.gitignore b/bin/rewritten_in_rust/.gitignore new file mode 100644 index 0000000..1e7caa9 --- /dev/null +++ b/bin/rewritten_in_rust/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +target/ diff --git a/bin/rewritten_in_rust/Cargo.toml b/bin/rewritten_in_rust/Cargo.toml new file mode 100644 index 0000000..03f4e8b --- /dev/null +++ b/bin/rewritten_in_rust/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "config_scripts" +version = "0.1.0" +edition = "2021" +authors = ["Akemi Izuko"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "prettify_bash_history" +path = "src/prettify_bash_history.rs" + +[dependencies] +clap = { version = "4", features = ["derive"] } +chrono = "0.4" +regex = "1" diff --git a/bin/rewritten_in_rust/src/prettify_bash_history.rs b/bin/rewritten_in_rust/src/prettify_bash_history.rs new file mode 100644 index 0000000..f7fcca2 --- /dev/null +++ b/bin/rewritten_in_rust/src/prettify_bash_history.rs @@ -0,0 +1,101 @@ +use chrono::NaiveDateTime; +use clap::{Parser, ValueEnum}; +use regex::Regex; +use std::fs::File; +use std::io::{self, BufRead, Write}; +use std::path::PathBuf; + +#[derive(Parser)] +#[command(name = "prettify_bash_history", author, version = "0.1.0", long_about = None)] +/// Prints a prettier version of the bash-history with unix timestamps +/// +/// Converts the unix-timestamped lines to human-readable dates and indents everything else +struct Args { + /// Path to bash history file + #[arg(value_name = "FILE")] + history_file: PathBuf, + /// Type of formatting for the output + #[arg(value_enum)] + style: Style, +} + +#[derive(Debug, Copy, Clone, ValueEnum)] +enum Style { + /// Plain text. Readable in vim + Plain, + /// With markdown code blocks + Markdown, + /// With pretty html code blocks + Html, +} + +fn main() -> Result<(), Box> { + let args = Args::parse(); + let timestamp = Regex::new(r"^#[0-9]{8,}$")?; + + let mut wb = io::BufWriter::new(io::stdout()); + + let mut is_first = true; + + let history = File::open(args.history_file)?; + let lines = io::BufReader::new(history).lines().map(|l| l.expect("File is readable")); + + for line in lines { + if timestamp.is_match(&line) { + let time = NaiveDateTime::from_timestamp_opt(line[1..].parse()?, 0).unwrap(); + let fmttime = format!("{}", time); + + let start_line = starting_for_command_line(args.style); + let time_line = format_time_line(&fmttime, args.style); + let end_line = ending_for_command_line(args.style); + + if is_first { + writeln!(&mut wb, "{}{}", time_line, start_line)?; + } else { + writeln!(&mut wb, "{}{}{}", end_line, time_line, start_line)?; + } + + is_first = false; + } else if is_first { + panic!("Improper file format. Must start with unix timestamp comment line"); + } else { + writeln!(&mut wb, "{}", format_command_line(&line, args.style))?; + } + } + + writeln!(&mut wb, "{}", ending_for_command_line(args.style))?; + wb.flush()?; + Ok(()) +} + +fn format_time_line(time: &str, style: Style) -> String { + match style { + Style::Plain => format!("{}", time), + Style::Markdown => format!("## {}\n", time), + Style::Html => format!("

{}

\n", time), + } +} + +fn starting_for_command_line(style: Style) -> &'static str { + match style { + Style::Plain => "", + Style::Markdown => "```bash", + Style::Html => "", + } +} + +fn ending_for_command_line(style: Style) -> &'static str { + match style { + Style::Plain => "", + Style::Markdown => "```\n\n", + Style::Html => "\n\n", + } +} + +fn format_command_line(line: &str, style: Style) -> String { + match style { + Style::Plain => format!(" {}", line), + Style::Markdown => format!("{}", line), + Style::Html => format!("{}", line), + } +} diff --git a/post_install.sh b/post_install.sh index c9e5ab5..3053340 100755 --- a/post_install.sh +++ b/post_install.sh @@ -9,6 +9,7 @@ for a more complete explanation ARGS: help Print this menu and exit status Checks the status of additional installation steps. May need sudo + build Compiles additonal binaries HELP } @@ -36,7 +37,6 @@ configs_pointer_is_setup() { swayland_checks() { check_sway_wallpaper check_swaylock_wallpaper - check_swaytree_compilation check_sway_sounds } @@ -408,6 +408,68 @@ check_sshdconfig() { return $return_code } +#################### +# Rust binaries +#################### +russy_checks() { + check_for_russy_bins +} + +check_for_russy_bins() { + local -i return_code=0 + + local -a bin_names + bin_names=($(awk '/name =/ { split($0, a, "\""); print a[2] }' ~/.configs_pointer/bin/rewritten_in_rust/Cargo.toml)) + + if [[ $? -eq 0 ]]; then + for (( i = 1; i < "${#bin_names[@]}"; i++ )); do + local name="${bin_names[i]}" + + if ! [[ -L "${HOME}/.configs_pointer/bin/${name}" ]] && [[ -e "${HOME}/.configs_pointer/bin/${name}" ]]; then + printf 'ERR: Conflicting file with rust binary `%s` in bin\n' "$name" + printf '\tRemove the conflicting file and rerun this script with `build`\n' + return_code=1 + elif ! [[ -L "${HOME}/.configs_pointer/bin/${name}" ]]; then + printf 'ERR: Missing rust binary `%s` in bin\n' "$name" + printf '\tInstall rust and rerun this script with the `build` argument\n' + return_code=1 + fi + done + fi + + return $return_code +} + +russy_build() { + if command -v cargo &>/dev/null; then + if cargo build --release --manifest-path="$HOME/.configs_pointer/bin/rewritten_in_rust/Cargo.toml"; then + local name + + for exe in $(fd -d1 -tx . ~/.configs_pointer/bin/rewritten_in_rust/target/release); do + name="$(basename "$exe")" + ( + cd ~/.configs_pointer/bin || return 1 + + if ! [[ -e "$name" ]]; then + ln -s "./rewritten_in_rust/target/release/$name" "./$name" + elif ! [[ -L "$name" ]]; then + printf 'ERR: Failed to link rust binary \`%s\`\n' "$name" + printf '\tRemove the conflicting file\n' + fi + ) + done + else + printf 'ERR: Failed to compile rust binaries\n' + printf '\tInstall rust to compile additional scripts\n' + return 1 + fi + else + printf 'ERR: No rust compiler found\n' + printf '\tInstall rust to compile additional scripts\n' + return 1 + fi +} + if [[ "$1" == 'status' && "$(uname -s)" == 'Linux' ]]; then configs_pointer_is_setup || exit 1 @@ -422,6 +484,9 @@ if [[ "$1" == 'status' && "$(uname -s)" == 'Linux' ]]; then aerc_checks git_checks ssh_checks + russy_checks +elif [[ "$1" == 'build' ]]; then + russy_build else print_help fi