Compare commits
7 Commits
e5b18b17ff
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
659c084a74 | ||
|
|
b7561c16d8 | ||
|
|
9cbfa06c58 | ||
|
|
90454efe9f | ||
|
|
f35d665c19 | ||
|
|
f94a3170b1 | ||
|
|
23d4d59c71 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
# bv (beads viewer) local config and caches
|
# bv (beads viewer) local config and caches
|
||||||
.bv/
|
.bv/
|
||||||
target/
|
target/
|
||||||
|
.DS_Store
|
||||||
|
src/.DS_Store
|
||||||
|
|||||||
@@ -147,7 +147,6 @@
|
|||||||
"enabled": true,
|
"enabled": true,
|
||||||
"priority": 1,
|
"priority": 1,
|
||||||
"min_width": 8,
|
"min_width": 8,
|
||||||
"prefer": "auto",
|
|
||||||
"show_ahead_behind": true,
|
"show_ahead_behind": true,
|
||||||
"show_dirty": true,
|
"show_dirty": true,
|
||||||
"truncate": {
|
"truncate": {
|
||||||
|
|||||||
70
install.sh
70
install.sh
@@ -31,14 +31,40 @@ echo "[ok] jq found"
|
|||||||
# ── Build release binary ─────────────────────────────────────────────
|
# ── Build release binary ─────────────────────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
echo "Building release binary..."
|
echo "Building release binary..."
|
||||||
(cd "$SCRIPT_DIR" && cargo build --release --quiet)
|
if ! (cd "$SCRIPT_DIR" && cargo build --release); then
|
||||||
echo "[ok] Built: $(ls -lh "$SCRIPT_DIR/target/release/$BINARY_NAME" | awk '{print $5}')"
|
echo ""
|
||||||
|
echo "ERROR: cargo build failed. Check the output above for details."
|
||||||
|
echo " Common causes:"
|
||||||
|
echo " - Missing C compiler: sudo apt install build-essential (Debian/Ubuntu)"
|
||||||
|
echo " - Missing libc headers: sudo apt install libc6-dev"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find the binary — respects CARGO_TARGET_DIR, custom target triples, etc.
|
||||||
|
# Use cargo metadata as the source of truth for the target directory.
|
||||||
|
TARGET_DIR=$(cd "$SCRIPT_DIR" && cargo metadata --format-version 1 --no-deps 2>/dev/null | jq -r '.target_directory' 2>/dev/null) || true
|
||||||
|
TARGET_DIR="${TARGET_DIR:-$SCRIPT_DIR/target}"
|
||||||
|
|
||||||
|
BINARY="$TARGET_DIR/release/$BINARY_NAME"
|
||||||
|
if [[ ! -f "$BINARY" ]]; then
|
||||||
|
# Fall back to searching (handles custom target triples like target/<triple>/release/)
|
||||||
|
BINARY=$(find "$TARGET_DIR" -name "$BINARY_NAME" -type f -path "*/release/*" ! -name "*.d" 2>/dev/null | head -1)
|
||||||
|
fi
|
||||||
|
if [[ -z "${BINARY:-}" || ! -f "$BINARY" ]]; then
|
||||||
|
echo "ERROR: Build succeeded but binary not found."
|
||||||
|
echo " Target dir: $TARGET_DIR"
|
||||||
|
echo " Searched: $TARGET_DIR/*/release/$BINARY_NAME"
|
||||||
|
echo " Contents: $(ls "$TARGET_DIR/release/" 2>/dev/null || echo '(empty or missing)')"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[ok] Built: $(ls -lh "$BINARY" | awk '{print $5}')"
|
||||||
|
|
||||||
# ── Install binary ───────────────────────────────────────────────────
|
# ── Install binary ───────────────────────────────────────────────────
|
||||||
mkdir -p "$INSTALL_DIR"
|
mkdir -p "$INSTALL_DIR"
|
||||||
cp "$SCRIPT_DIR/target/release/$BINARY_NAME" "$INSTALL_DIR/$BINARY_NAME"
|
cp "$BINARY" "$INSTALL_DIR/$BINARY_NAME"
|
||||||
chmod +x "$INSTALL_DIR/$BINARY_NAME"
|
chmod +x "$INSTALL_DIR/$BINARY_NAME"
|
||||||
echo "[ok] Installed to $INSTALL_DIR/$BINARY_NAME"
|
BINARY_PATH="$INSTALL_DIR/$BINARY_NAME"
|
||||||
|
echo "[ok] Installed to $BINARY_PATH"
|
||||||
|
|
||||||
# Verify it's on PATH
|
# Verify it's on PATH
|
||||||
if ! command -v "$BINARY_NAME" &>/dev/null; then
|
if ! command -v "$BINARY_NAME" &>/dev/null; then
|
||||||
@@ -46,33 +72,50 @@ if ! command -v "$BINARY_NAME" &>/dev/null; then
|
|||||||
echo " Add to your shell config: export PATH=\"$INSTALL_DIR:\$PATH\""
|
echo " Add to your shell config: export PATH=\"$INSTALL_DIR:\$PATH\""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Smoke test — verify the binary actually runs
|
||||||
|
if "$BINARY_PATH" --test --color=never >/dev/null 2>&1; then
|
||||||
|
echo "[ok] Binary smoke test passed"
|
||||||
|
else
|
||||||
|
echo "[warn] Binary smoke test failed (exit $?). It may still work inside Claude Code."
|
||||||
|
echo " Debug: $BINARY_PATH --test --dump-state=json"
|
||||||
|
fi
|
||||||
|
|
||||||
# ── Configure Claude Code settings.json ──────────────────────────────
|
# ── Configure Claude Code settings.json ──────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
mkdir -p "$CLAUDE_DIR"
|
mkdir -p "$CLAUDE_DIR"
|
||||||
|
|
||||||
BINARY_PATH="$INSTALL_DIR/$BINARY_NAME"
|
|
||||||
|
|
||||||
# The binary runs in a non-TTY context, so force color on.
|
# The binary runs in a non-TTY context, so force color on.
|
||||||
STATUSLINE_CMD="$BINARY_PATH --color=always"
|
STATUSLINE_CMD="$BINARY_PATH --color=always"
|
||||||
|
|
||||||
if [[ -f "$SETTINGS" ]]; then
|
if [[ -f "$SETTINGS" ]]; then
|
||||||
# Update existing settings.json
|
# Update existing settings.json, preserving all other keys
|
||||||
CURRENT_CMD=$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null || true)
|
CURRENT_CMD=$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null || true)
|
||||||
if [[ -n "$CURRENT_CMD" ]]; then
|
if [[ -n "$CURRENT_CMD" ]]; then
|
||||||
echo "[info] Current statusLine command: $CURRENT_CMD"
|
echo "[info] Previous statusLine command: $CURRENT_CMD"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Write updated settings
|
|
||||||
TMP="$SETTINGS.tmp.$$"
|
TMP="$SETTINGS.tmp.$$"
|
||||||
jq --arg cmd "$STATUSLINE_CMD" '.statusLine = {"type": "command", "command": $cmd, "padding": 0}' "$SETTINGS" > "$TMP"
|
if jq --arg cmd "$STATUSLINE_CMD" '.statusLine = {"type": "command", "command": $cmd, "padding": 0}' "$SETTINGS" > "$TMP" 2>/dev/null; then
|
||||||
mv "$TMP" "$SETTINGS"
|
mv "$TMP" "$SETTINGS"
|
||||||
echo "[ok] Updated statusLine in $SETTINGS"
|
echo "[ok] Updated statusLine in $SETTINGS"
|
||||||
|
else
|
||||||
|
rm -f "$TMP"
|
||||||
|
echo "[warn] Failed to update $SETTINGS (invalid JSON?). Creating backup and writing fresh."
|
||||||
|
cp "$SETTINGS" "$SETTINGS.bak"
|
||||||
|
jq -n --arg cmd "$STATUSLINE_CMD" '{"statusLine": {"type": "command", "command": $cmd, "padding": 0}}' > "$SETTINGS"
|
||||||
|
echo "[ok] Wrote fresh $SETTINGS (backup: $SETTINGS.bak)"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# Create minimal settings.json
|
# Create minimal settings.json
|
||||||
jq -n --arg cmd "$STATUSLINE_CMD" '{"statusLine": {"type": "command", "command": $cmd, "padding": 0}}' > "$SETTINGS"
|
jq -n --arg cmd "$STATUSLINE_CMD" '{"statusLine": {"type": "command", "command": $cmd, "padding": 0}}' > "$SETTINGS"
|
||||||
echo "[ok] Created $SETTINGS"
|
echo "[ok] Created $SETTINGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Show what was written so the user can verify
|
||||||
|
echo ""
|
||||||
|
echo " statusLine config:"
|
||||||
|
jq '.statusLine' "$SETTINGS" 2>/dev/null || echo " (could not read settings)"
|
||||||
|
|
||||||
# ── Symlink config ───────────────────────────────────────────────────
|
# ── Symlink config ───────────────────────────────────────────────────
|
||||||
CONFIG_SRC="$SCRIPT_DIR/statusline.json"
|
CONFIG_SRC="$SCRIPT_DIR/statusline.json"
|
||||||
CONFIG_DST="$CLAUDE_DIR/statusline.json"
|
CONFIG_DST="$CLAUDE_DIR/statusline.json"
|
||||||
@@ -103,7 +146,8 @@ fi
|
|||||||
|
|
||||||
# ── Done ─────────────────────────────────────────────────────────────
|
# ── Done ─────────────────────────────────────────────────────────────
|
||||||
echo ""
|
echo ""
|
||||||
echo "Done. Restart Claude Code to see the status line."
|
echo "Done. RESTART Claude Code (exit and reopen) to see the status line."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Quick test: $BINARY_NAME --test --color=always"
|
echo "Verify: $BINARY_PATH --test --color=always"
|
||||||
echo "Debug: $BINARY_NAME --test --dump-state=json"
|
echo "Debug: $BINARY_PATH --test --dump-state=json"
|
||||||
|
echo "Settings: cat $SETTINGS | jq .statusLine"
|
||||||
|
|||||||
11
schema.json
11
schema.json
@@ -188,7 +188,6 @@
|
|||||||
"enum": [
|
"enum": [
|
||||||
"auto",
|
"auto",
|
||||||
"git",
|
"git",
|
||||||
"jj",
|
|
||||||
"none"
|
"none"
|
||||||
],
|
],
|
||||||
"description": "VCS detection mode",
|
"description": "VCS detection mode",
|
||||||
@@ -375,16 +374,6 @@
|
|||||||
"minimum": 0,
|
"minimum": 0,
|
||||||
"default": 8
|
"default": 8
|
||||||
},
|
},
|
||||||
"prefer": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"auto",
|
|
||||||
"git",
|
|
||||||
"jj"
|
|
||||||
],
|
|
||||||
"default": "auto",
|
|
||||||
"description": "VCS preference. auto detects .jj/ first, then .git/"
|
|
||||||
},
|
|
||||||
"show_ahead_behind": {
|
"show_ahead_behind": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": true
|
"default": true
|
||||||
|
|||||||
@@ -303,41 +303,14 @@ fn prefetch_shell_outs(
|
|||||||
|
|
||||||
std::thread::scope(|s| {
|
std::thread::scope(|s| {
|
||||||
let vcs_handle = if needs_vcs {
|
let vcs_handle = if needs_vcs {
|
||||||
let args: Vec<String> = match vcs_type {
|
|
||||||
section::VcsType::Git => vec![
|
|
||||||
"git".into(),
|
|
||||||
"-C".into(),
|
|
||||||
project_dir.into(),
|
|
||||||
"status".into(),
|
|
||||||
"--porcelain=v2".into(),
|
|
||||||
"--branch".into(),
|
|
||||||
],
|
|
||||||
section::VcsType::Jj => vec![
|
|
||||||
"jj".into(),
|
|
||||||
"log".into(),
|
|
||||||
"-r".into(),
|
|
||||||
"@".into(),
|
|
||||||
"--no-graph".into(),
|
|
||||||
"-T".into(),
|
|
||||||
"if(bookmarks, bookmarks.join(\",\"), change_id.shortest(8))".into(),
|
|
||||||
"--color=never".into(),
|
|
||||||
],
|
|
||||||
section::VcsType::None => vec![],
|
|
||||||
};
|
|
||||||
if args.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let dir = if vcs_type == section::VcsType::Jj {
|
|
||||||
Some(project_dir.to_string())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
Some(s.spawn(move || {
|
Some(s.spawn(move || {
|
||||||
let prog = &args[0];
|
shell::exec_gated(
|
||||||
let str_args: Vec<&str> = args[1..].iter().map(|s| s.as_str()).collect();
|
shell_config,
|
||||||
shell::exec_gated(shell_config, prog, &str_args, dir.as_deref())
|
"git",
|
||||||
|
&["-C", project_dir, "status", "--porcelain=v2", "--branch"],
|
||||||
|
None,
|
||||||
|
)
|
||||||
}))
|
}))
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@@ -483,36 +456,14 @@ fn resolve_terminal_palette(cache: &cache::Cache) -> Option<Vec<(u8, u8, u8)>> {
|
|||||||
Some(palette)
|
Some(palette)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn detect_vcs(dir: &str, config: &config::Config) -> section::VcsType {
|
fn detect_vcs(dir: &str, _config: &config::Config) -> section::VcsType {
|
||||||
let prefer = config.sections.vcs.prefer.as_str();
|
|
||||||
let path = std::path::Path::new(dir);
|
let path = std::path::Path::new(dir);
|
||||||
|
|
||||||
match prefer {
|
|
||||||
"jj" => {
|
|
||||||
if path.join(".jj").is_dir() {
|
|
||||||
section::VcsType::Jj
|
|
||||||
} else {
|
|
||||||
section::VcsType::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"git" => {
|
|
||||||
if path.join(".git").is_dir() {
|
if path.join(".git").is_dir() {
|
||||||
section::VcsType::Git
|
section::VcsType::Git
|
||||||
} else {
|
} else {
|
||||||
section::VcsType::None
|
section::VcsType::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
if path.join(".jj").is_dir() {
|
|
||||||
section::VcsType::Jj
|
|
||||||
} else if path.join(".git").is_dir() {
|
|
||||||
section::VcsType::Git
|
|
||||||
} else {
|
|
||||||
section::VcsType::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn dump_state_output(
|
fn dump_state_output(
|
||||||
|
|||||||
@@ -296,7 +296,6 @@ impl Default for TruncateConfig {
|
|||||||
pub struct VcsSection {
|
pub struct VcsSection {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub base: SectionBase,
|
pub base: SectionBase,
|
||||||
pub prefer: String,
|
|
||||||
pub show_ahead_behind: bool,
|
pub show_ahead_behind: bool,
|
||||||
pub show_dirty: bool,
|
pub show_dirty: bool,
|
||||||
pub untracked: String,
|
pub untracked: String,
|
||||||
@@ -314,7 +313,6 @@ impl Default for VcsSection {
|
|||||||
min_width: Some(8),
|
min_width: Some(8),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
prefer: "auto".into(),
|
|
||||||
show_ahead_behind: true,
|
show_ahead_behind: true,
|
||||||
show_dirty: true,
|
show_dirty: true,
|
||||||
untracked: "normal".into(),
|
untracked: "normal".into(),
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use crate::format;
|
|||||||
use crate::layout::ActiveSection;
|
use crate::layout::ActiveSection;
|
||||||
use crate::section::{self, RenderContext};
|
use crate::section::{self, RenderContext};
|
||||||
|
|
||||||
/// Expand the winning flex section to fill remaining terminal width.
|
/// Expand flex sections to fill remaining terminal width.
|
||||||
///
|
///
|
||||||
/// Rules:
|
/// Rules:
|
||||||
/// - Spacers take priority over non-spacer flex sections
|
/// - If multiple spacers exist, distribute extra space proportionally among them
|
||||||
/// - Only one flex section wins per line
|
/// - If only non-spacer flex sections exist, pick one winner (spacer > non-spacer)
|
||||||
/// - Spacer: fill with spaces
|
/// - Spacer: fill with spaces
|
||||||
/// - context_bar: rebuild bar with wider width
|
/// - context_bar: rebuild bar with wider width
|
||||||
/// - Other: pad with trailing spaces
|
/// - Other: pad with trailing spaces
|
||||||
@@ -18,7 +18,34 @@ pub fn flex_expand(active: &mut [ActiveSection], ctx: &RenderContext, separator:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find winning flex section: spacer wins over non-spacer
|
let extra = term_width - current_width;
|
||||||
|
|
||||||
|
// Collect all spacer indices
|
||||||
|
let spacer_indices: Vec<usize> = active
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, s)| s.is_spacer)
|
||||||
|
.map(|(i, _)| i)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// If multiple spacers, distribute extra space among them
|
||||||
|
if spacer_indices.len() > 1 {
|
||||||
|
let per_spacer = extra / spacer_indices.len();
|
||||||
|
let remainder = extra % spacer_indices.len();
|
||||||
|
|
||||||
|
for (i, &idx) in spacer_indices.iter().enumerate() {
|
||||||
|
// First spacers get +1 char from remainder
|
||||||
|
let this_width = per_spacer + if i < remainder { 1 } else { 0 } + 1;
|
||||||
|
let padding = " ".repeat(this_width);
|
||||||
|
active[idx].output = section::SectionOutput {
|
||||||
|
raw: padding.clone(),
|
||||||
|
ansi: padding,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single spacer or non-spacer flex: find winning flex section
|
||||||
let mut flex_idx: Option<usize> = None;
|
let mut flex_idx: Option<usize> = None;
|
||||||
for (i, sec) in active.iter().enumerate() {
|
for (i, sec) in active.iter().enumerate() {
|
||||||
if !sec.is_flex {
|
if !sec.is_flex {
|
||||||
@@ -35,7 +62,6 @@ pub fn flex_expand(active: &mut [ActiveSection], ctx: &RenderContext, separator:
|
|||||||
}
|
}
|
||||||
|
|
||||||
let Some(idx) = flex_idx else { return };
|
let Some(idx) = flex_idx else { return };
|
||||||
let extra = term_width - current_width;
|
|
||||||
|
|
||||||
if active[idx].is_spacer {
|
if active[idx].is_spacer {
|
||||||
let padding = " ".repeat(extra + 1);
|
let padding = " ".repeat(extra + 1);
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ pub type RenderFn = fn(&RenderContext) -> Option<SectionOutput>;
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum VcsType {
|
pub enum VcsType {
|
||||||
Git,
|
Git,
|
||||||
Jj,
|
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ pub fn render(ctx: &RenderContext) -> Option<SectionOutput> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --no-shell: serve stale cache only, skip all git/jj commands
|
// --no-shell: serve stale cache only, skip all git commands
|
||||||
if ctx.no_shell {
|
if ctx.no_shell {
|
||||||
return render_stale_cache(ctx);
|
return render_stale_cache(ctx);
|
||||||
}
|
}
|
||||||
@@ -21,11 +21,7 @@ pub fn render(ctx: &RenderContext) -> Option<SectionOutput> {
|
|||||||
let ttl = &ctx.config.sections.vcs.ttl;
|
let ttl = &ctx.config.sections.vcs.ttl;
|
||||||
let glyphs = &ctx.config.glyphs;
|
let glyphs = &ctx.config.glyphs;
|
||||||
|
|
||||||
match ctx.vcs_type {
|
render_git(ctx, dir, ttl, glyphs)
|
||||||
VcsType::Git => render_git(ctx, dir, ttl, glyphs),
|
|
||||||
VcsType::Jj => render_jj(ctx, dir, ttl, glyphs),
|
|
||||||
VcsType::None => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serve stale cached VCS data without running any commands.
|
/// Serve stale cached VCS data without running any commands.
|
||||||
@@ -158,53 +154,3 @@ fn render_git(
|
|||||||
|
|
||||||
Some(SectionOutput { raw, ansi })
|
Some(SectionOutput { raw, ansi })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_jj(
|
|
||||||
ctx: &RenderContext,
|
|
||||||
dir: &str,
|
|
||||||
ttl: &crate::config::VcsTtl,
|
|
||||||
glyphs: &crate::config::GlyphConfig,
|
|
||||||
) -> Option<SectionOutput> {
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
let branch_ttl = Duration::from_secs(ttl.branch);
|
|
||||||
|
|
||||||
let branch = ctx.cache.get("vcs_branch", branch_ttl).or_else(|| {
|
|
||||||
// Use prefetched result if available, otherwise exec
|
|
||||||
let out = ctx.shell_results.get("vcs").cloned().unwrap_or_else(|| {
|
|
||||||
shell::exec_gated(
|
|
||||||
ctx.shell_config,
|
|
||||||
"jj",
|
|
||||||
&[
|
|
||||||
"log",
|
|
||||||
"-r",
|
|
||||||
"@",
|
|
||||||
"--no-graph",
|
|
||||||
"-T",
|
|
||||||
"if(bookmarks, bookmarks.join(\",\"), change_id.shortest(8))",
|
|
||||||
"--color=never",
|
|
||||||
],
|
|
||||||
Some(dir),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
ctx.cache.set("vcs_branch", &out);
|
|
||||||
Some(out)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let trunc = &ctx.config.sections.vcs.truncate;
|
|
||||||
let branch = if trunc.enabled && trunc.max > 0 {
|
|
||||||
crate::format::truncate(&branch, trunc.max, &trunc.style)
|
|
||||||
} else {
|
|
||||||
branch
|
|
||||||
};
|
|
||||||
|
|
||||||
let branch_glyph = glyph::glyph("branch", glyphs);
|
|
||||||
let raw = format!("{branch_glyph}{branch}");
|
|
||||||
let ansi = if ctx.color_enabled {
|
|
||||||
format!("{}{branch_glyph}{branch}{}", color::GREEN, color::RESET)
|
|
||||||
} else {
|
|
||||||
raw.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(SectionOutput { raw, ansi })
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ pub fn parse_transcript(path: &Path, skip_lines: usize) -> Option<TranscriptStat
|
|||||||
|
|
||||||
// Sort by count descending
|
// Sort by count descending
|
||||||
let mut sorted: Vec<(String, u64)> = counts.into_iter().collect();
|
let mut sorted: Vec<(String, u64)> = counts.into_iter().collect();
|
||||||
sorted.sort_by(|a, b| b.1.cmp(&a.1));
|
sorted.sort_by_key(|item| std::cmp::Reverse(item.1));
|
||||||
stats.tool_counts = sorted;
|
stats.tool_counts = sorted;
|
||||||
|
|
||||||
Some(stats)
|
Some(stats)
|
||||||
|
|||||||
@@ -1,28 +1,34 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./schema.json",
|
|
||||||
"global": {
|
"global": {
|
||||||
"justify": "spread",
|
"justify": "spread",
|
||||||
"theme": "dark",
|
"theme": "dark",
|
||||||
"responsive": true,
|
"responsive": true,
|
||||||
"width": 500,
|
"width": 500,
|
||||||
"width_margin": 20
|
"width_margin": 45
|
||||||
},
|
},
|
||||||
"glyphs": {
|
"glyphs": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"layout": "verbose",
|
"layout": [
|
||||||
|
["model", "provider", "project", "spacer", "context_bar", "context_usage", "spacer", "cost", "cost_velocity"],
|
||||||
|
["vcs", "lines_changed", "spacer", "tokens_raw", "cache_efficiency", "spacer", "beads"]
|
||||||
|
],
|
||||||
"sections": {
|
"sections": {
|
||||||
"context_usage": {
|
"context_usage": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"context_trend": {
|
"context_bar": {
|
||||||
|
"flex": true,
|
||||||
|
"min_width": 12
|
||||||
|
},
|
||||||
|
"tokens_raw": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"cost_trend": {
|
"cache_efficiency": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"load": {
|
"cost_velocity": {
|
||||||
"enabled": false
|
"enabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user