Rewrite: prettify_bash_history
This commit is contained in:
parent
98dd6df2eb
commit
4fbfe9d6d6
2
bin/rewritten_in_rust/.gitignore
vendored
Normal file
2
bin/rewritten_in_rust/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
Cargo.lock
|
||||
target/
|
16
bin/rewritten_in_rust/Cargo.toml
Normal file
16
bin/rewritten_in_rust/Cargo.toml
Normal 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"
|
101
bin/rewritten_in_rust/src/prettify_bash_history.rs
Normal file
101
bin/rewritten_in_rust/src/prettify_bash_history.rs
Normal 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),
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue