Rewrite: prettify_bash_history

This commit is contained in:
Akemi Izuko 2022-12-20 16:06:22 -07:00
parent 98dd6df2eb
commit 4fbfe9d6d6
No known key found for this signature in database
GPG key ID: 905D444F6A5E4BE4
4 changed files with 185 additions and 1 deletions

2
bin/rewritten_in_rust/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
Cargo.lock
target/

View file

@ -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"

View file

@ -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<dyn std::error::Error>> {
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!("<h2>{}</h2>\n", time),
}
}
fn starting_for_command_line(style: Style) -> &'static str {
match style {
Style::Plain => "",
Style::Markdown => "```bash",
Style::Html => "<code>",
}
}
fn ending_for_command_line(style: Style) -> &'static str {
match style {
Style::Plain => "",
Style::Markdown => "```\n\n",
Style::Html => "</code>\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),
}
}

View file

@ -9,6 +9,7 @@ for a more complete explanation
ARGS: ARGS:
help Print this menu and exit help Print this menu and exit
status Checks the status of additional installation steps. May need sudo status Checks the status of additional installation steps. May need sudo
build Compiles additonal binaries
HELP HELP
} }
@ -36,7 +37,6 @@ configs_pointer_is_setup() {
swayland_checks() { swayland_checks() {
check_sway_wallpaper check_sway_wallpaper
check_swaylock_wallpaper check_swaylock_wallpaper
check_swaytree_compilation
check_sway_sounds check_sway_sounds
} }
@ -408,6 +408,68 @@ check_sshdconfig() {
return $return_code 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 if [[ "$1" == 'status' && "$(uname -s)" == 'Linux' ]]; then
configs_pointer_is_setup || exit 1 configs_pointer_is_setup || exit 1
@ -422,6 +484,9 @@ if [[ "$1" == 'status' && "$(uname -s)" == 'Linux' ]]; then
aerc_checks aerc_checks
git_checks git_checks
ssh_checks ssh_checks
russy_checks
elif [[ "$1" == 'build' ]]; then
russy_build
else else
print_help print_help
fi fi