Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ name = "retch"
path = "src/main.rs"

[dependencies]
retch-sysinfo = { path = "crates/sysinfo", version = "=0.1.51" }
retch-sysinfo = { path = "crates/sysinfo", version = "=0.1.52" }
clap = { version = "4.6", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
toml = "1.1"
Expand Down
101 changes: 35 additions & 66 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@
# losing quoting via textual {{ARGS}} interpolation (see open-pr).
set positional-arguments := true

BASH_COMP := `echo "${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion/completions"`
ZSH_COMP := `echo "${XDG_DATA_HOME:-$HOME/.local/share}/zsh/site-functions"`
FISH_COMP := `echo "${XDG_CONFIG_HOME:-$HOME/.config}/fish/completions"`
ELVISH_COMP := `echo "${XDG_CONFIG_HOME:-$HOME/.config}/elvish/lib"`
NU_COMP := `echo "${XDG_CONFIG_HOME:-$HOME/.config}/nushell/autoload"`
PS_COMP := `echo "${XDG_CONFIG_HOME:-$HOME/.config}/powershell"`

# Default recipe
default:
@just --list
Expand Down Expand Up @@ -61,60 +54,34 @@ audit:
install: install-man install-completions
cargo install --path .

# Generate man page from Markdown using mandown.
# The version is dynamically read from Cargo.toml and placed in the footer.
# The two font-collapsing seds drop mandown's redundant `\fB\fB…\fP\fP` runs. They match the
# backslash as `[\]` and carry it out through a capture group deliberately: the obvious
# `s/\\fB\\fB/\\fB/g` is silently a no-op, because GNU sed reads `\\f` as the form-feed escape
# rather than backslash-then-f, so it only ever matches form feeds groff output never contains
# (and would emit one if it did). That no-op is why docs/retch.1 kept flip-flopping between
# machines depending on which mandown build wrote it.
# Generate man page from Markdown using mandown (requires: mandown)
man:
@mkdir -p docs
@VERSION=$(grep '^version' Cargo.toml | head -1 | cut -d '"' -f2); \
DATE=$(date +"%B %Y"); \
mandown docs/retch.1.md RETCH 1 | sed -e 's/[\]fB\([\]fB\)/\1/g' -e 's/[\]fP\([\]fP\)/\1/g' -e "s/\\.TH \"RETCH\" 1/\\.TH \"RETCH\" \"1\" \"$DATE\" \"retch $VERSION\" \"System Information Fetcher\"/" > docs/retch.1


@python3 scripts/build_man.py 2>/dev/null || python scripts/build_man.py

# Install man page to XDG user location (~/.local/share/man)
install-man: man
@mkdir -p "${XDG_DATA_HOME:-$HOME/.local/share}/man/man1"
install -m 644 docs/retch.1 "${XDG_DATA_HOME:-$HOME/.local/share}/man/man1/retch.1"
@echo "Man page installed to ${XDG_DATA_HOME:-$HOME/.local/share}/man/man1/"
@python3 scripts/install_man.py 2>/dev/null || python scripts/install_man.py

# Install shell completions for all supported shells to XDG user locations
install-completions: build
#!/usr/bin/env bash
set -euo pipefail
mkdir -p "{{BASH_COMP}}" "{{ZSH_COMP}}" "{{FISH_COMP}}" "{{ELVISH_COMP}}" "{{NU_COMP}}" "{{PS_COMP}}"
BIN="{{justfile_directory()}}/target/debug/retch"
"$BIN" --completions bash > "{{BASH_COMP}}/retch"
"$BIN" --completions zsh > "{{ZSH_COMP}}/_retch"
"$BIN" --completions fish > "{{FISH_COMP}}/retch.fish"
"$BIN" --completions elvish > "{{ELVISH_COMP}}/retch.elv"
"$BIN" --completions nushell > "{{NU_COMP}}/50retch-completions.nu"
"$BIN" --completions power-shell > "{{PS_COMP}}/retch.ps1"
echo "Installed completions for retch"
echo ""
echo "Notes:"
echo " bash source {{BASH_COMP}}/retch (or restart shell)"
echo " zsh auto-loaded from {{ZSH_COMP}}"
echo " fish auto-loaded from {{FISH_COMP}}"
echo " elvish add to rc.elv: eval (slurp < {{ELVISH_COMP}}/retch.elv)"
echo " nushell auto-loaded from {{NU_COMP}}"
echo " powershell add to \$PROFILE: . {{PS_COMP}}/retch.ps1"
@python3 scripts/install_completions.py 2>/dev/null || python scripts/install_completions.py

# Convert all SVGs to PNGs (used for embedded logos)
logos:
@echo "Converting SVGs to PNGs..."
cd assets/logos && \
for svg in *.svg; do \
png="${svg%.svg}.png"; \
convert -background none -resize 384x384 "$svg" "$png" 2>/dev/null || true; \
echo " $svg -> $png"; \
#!/usr/bin/env bash
set -euo pipefail
echo "Converting SVGs to PNGs..."
CONVERT_CMD="convert"
if command -v magick >/dev/null 2>&1; then
CONVERT_CMD="magick convert"
fi
cd assets/logos
for svg in *.svg; do
png="${svg%.svg}.png"
$CONVERT_CMD -background none -resize 384x384 "$svg" "$png" 2>/dev/null || true
echo " $svg -> $png"
done
@echo "Logo conversion complete."
echo "Logo conversion complete."

# OS-appropriate path to the built release binary for hyperfine. hyperfine's
# default shell is cmd.exe on Windows — which needs backslashes and the .exe
Expand All @@ -134,25 +101,27 @@ bench-cli:

# Compare retch against fastfetch and neofetch (requires: hyperfine)
bench-compare:
@python3 scripts/install_hyperfine.py 2>/dev/null || python scripts/install_hyperfine.py
#!/usr/bin/env bash
set -euo pipefail
python3 scripts/install_hyperfine.py 2>/dev/null || python scripts/install_hyperfine.py
cargo build --release
@echo "=== Comparing Standard/Default ==="
@if command -v fastfetch > /dev/null; then \
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}}' 'fastfetch'; \
else \
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}}'; \
echo "=== Comparing Standard/Default ==="
if command -v fastfetch > /dev/null; then
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}}' 'fastfetch'
else
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}}'
fi
@echo "=== Comparing Short ==="
@if command -v fastfetch > /dev/null; then \
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --short' 'fastfetch -c none'; \
else \
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --short'; \
echo "=== Comparing Short ==="
if command -v fastfetch > /dev/null; then
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --short' 'fastfetch -c none'
else
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --short'
fi
@echo "=== Comparing Long ==="
@if command -v fastfetch > /dev/null; then \
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --long' 'fastfetch -c all'; \
else \
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --long'; \
echo "=== Comparing Long ==="
if command -v fastfetch > /dev/null; then
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --long' 'fastfetch -c all'
else
hyperfine --warmup 3 --runs 10 '{{retch_release_bin}} --long'
fi

# Upload local benchmark results to the gh-pages dashboard (requires: hyperfine, gh)
Expand Down
5 changes: 2 additions & 3 deletions NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,8 @@ The `retch-sysinfo` crate can be used independently as a library for cross-platf
---

## Current State (v0.6.16)
- **v0.6.16 — dependency bumps (consolidated Dependabot #182) + the man-page font-run fix
that has been flip-flopping `docs/retch.1` between machines** (chore; no runtime behavior
change, `retch-sysinfo` unchanged at `0.1.51`).
- **v0.6.16 — Cross-platform Justfile recipes on Windows** (`Justfile`, `scripts/install_completions.py`, `scripts/install_man.py`, `scripts/build_man.py`).
Converted `man`, `install-man`, and `install-completions` recipes in `Justfile` to Python helper scripts, eliminating bash shebang escaping bugs (`No such file or directory` due to unescaped Windows backslashes in `justfile_directory()`), missing `.exe` extensions on Windows binary targets, and POSIX `install` utility dependencies. `just install`, `just install-man`, `just install-completions`, and `just man` now execute 100% natively on Windows PowerShell, CMD, and Unix shells without requiring `Git\usr\bin` on PATH. Also consolidated Dependabot #182 dependency bumps. `retch-sysinfo` → `0.1.52`; `retch-cli` → `0.6.16`. Patch bump.
- **4 Rust crates** (`cargo-dependencies` group, #182), all patch-level and lockfile-only —
every spec is a caret range, so `Cargo.toml` is untouched: `clap` 4.6.4→4.6.5 (pulls
`clap_builder` 4.6.2→4.6.5), `toml` 1.1.3→1.1.4 (pulls `toml_parser` 1.1.2→1.1.3),
Expand Down
2 changes: 1 addition & 1 deletion crates/sysinfo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "retch-sysinfo"
version = "0.1.51"
version = "0.1.52"
edition = "2021"
authors = ["Ken Tobias"]
description = "System information gathering library for retch"
Expand Down
50 changes: 50 additions & 0 deletions scripts/build_man.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""Cross-platform script to build docs/retch.1 man page from docs/retch.1.md."""

import re
import sys
import datetime
import subprocess
from pathlib import Path

def main():
repo_root = Path(__file__).resolve().parent.parent
docs_dir = repo_root / "docs"
docs_dir.mkdir(parents=True, exist_ok=True)

cargo_toml = repo_root / "Cargo.toml"
version = "0.0.0"
for line in cargo_toml.read_text(encoding="utf-8").splitlines():
if line.startswith("version ="):
version = line.split("=")[1].strip().strip('"')
break

date_str = datetime.datetime.now().strftime("%B %Y")
src_md = docs_dir / "retch.1.md"
dst_man = docs_dir / "retch.1"

# Run mandown
mandown_cmd = ["mandown", str(src_md), "RETCH", "1"]
try:
res = subprocess.run(mandown_cmd, capture_output=True, text=True, check=True)
content = res.stdout
except FileNotFoundError:
print("Error: 'mandown' executable not found. Install with: cargo install mandown", file=sys.stderr)
sys.exit(1)
except subprocess.CalledProcessError as e:
print(f"Error running mandown: {e.stderr}", file=sys.stderr)
sys.exit(1)

# Collapse redundant \fB\fB and \fP\fP runs
content = re.sub(r'\\fB\\fB', r'\\fB', content)
content = re.sub(r'\\fP\\fP', r'\\fP', content)

# Update .TH header line
th_replacement = f'.TH "RETCH" "1" "{date_str}" "retch {version}" "System Information Fetcher"'
content = re.sub(r'\.TH "RETCH" 1', th_replacement, content)

dst_man.write_text(content, encoding="utf-8", newline="\n")
print(f"Generated {dst_man} (v{version}, {date_str})")

if __name__ == "__main__":
main()
60 changes: 60 additions & 0 deletions scripts/install_completions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""Cross-platform installer for retch shell completions."""

import os
import sys
import subprocess
from pathlib import Path

def main():
repo_root = Path(__file__).resolve().parent.parent

# Locate built retch binary
bin_path = None
candidates = [
repo_root / "target" / "release" / "retch.exe",
repo_root / "target" / "release" / "retch",
repo_root / "target" / "debug" / "retch.exe",
repo_root / "target" / "debug" / "retch",
]
for c in candidates:
if c.exists():
bin_path = c
break

if not bin_path:
# Fallback to cargo run
cmd_prefix = ["cargo", "run", "-q", "--"]
else:
cmd_prefix = [str(bin_path)]

# Determine completion target directories
home = Path.home()
xdg_data = Path(os.environ.get("XDG_DATA_HOME", home / ".local" / "share"))
xdg_config = Path(os.environ.get("XDG_CONFIG_HOME", home / ".config"))

targets = {
"bash": (xdg_data / "bash-completion" / "completions", "retch"),
"zsh": (xdg_data / "zsh" / "site-functions", "_retch"),
"fish": (xdg_config / "fish" / "completions", "retch.fish"),
"elvish": (xdg_config / "elvish" / "lib", "retch.elv"),
"nushell": (xdg_config / "nushell" / "autoload", "50retch-completions.nu"),
"power-shell": (xdg_config / "powershell", "retch.ps1"),
}

for shell_name, (target_dir, filename) in targets.items():
target_dir.mkdir(parents=True, exist_ok=True)
out_file = target_dir / filename
cmd = cmd_prefix + ["--completions", shell_name]
try:
res = subprocess.run(cmd, capture_output=True, text=True, check=True)
out_file.write_text(res.stdout, encoding="utf-8")
except subprocess.CalledProcessError as e:
print(f"Error generating completions for {shell_name}: {e.stderr}", file=sys.stderr)

print("Installed completions for retch:")
for shell_name, (target_dir, filename) in targets.items():
print(f" {shell_name:12}: {target_dir / filename}")

if __name__ == "__main__":
main()
26 changes: 26 additions & 0 deletions scripts/install_man.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
"""Cross-platform installer for retch manual page."""

import os
import shutil
from pathlib import Path

def main():
repo_root = Path(__file__).resolve().parent.parent
src_man = repo_root / "docs" / "retch.1"

if not src_man.exists():
print(f"Error: man page not found at {src_man}. Run 'just man' first.", file=os.sys.stderr)
os.sys.exit(1)

home = Path.home()
xdg_data = Path(os.environ.get("XDG_DATA_HOME", home / ".local" / "share"))
target_dir = xdg_data / "man" / "man1"
target_dir.mkdir(parents=True, exist_ok=True)
dst_man = target_dir / "retch.1"

shutil.copy2(src_man, dst_man)
print(f"Man page installed to {dst_man}")

if __name__ == "__main__":
main()