Scope key prefixes to backlog in list and show views
Global prefix computation made keys longer than necessary when
viewing a single backlog. Scoping to backlog-local keys produces
shorter, more readable prefixes in context.

Assisted-by: Claude Opus 4.6 via pi
change yorloszqtruyvploqyvsoooyruopqrvy
commit 1428e8108edc90aa6e488312219ea3298bf9a525
author Alpha Chen <alpha@kejadlen.dev>
date
parent nmrnmqlq
diff --git a/src/bin/ranger/commands/backlog.rs b/src/bin/ranger/commands/backlog.rs
index 7874ef4..5b54561 100644
--- a/src/bin/ranger/commands/backlog.rs
+++ b/src/bin/ranger/commands/backlog.rs
@@ -68,8 +68,8 @@ pub async fn run(pool: &SqlitePool, command: BacklogCommands, json: bool) -> Res
                 });
                 println!("{}", serde_json::to_string_pretty(&detail).unwrap());
             } else {
-                let all_keys = ops::task::all_keys(&mut conn).await?;
-                let prefixes = key::unique_prefix_lengths(&all_keys);
+                let backlog_keys = ops::task::keys_for_backlog(&mut conn, backlog.id).await?;
+                let prefixes = key::unique_prefix_lengths(&backlog_keys);
 
                 print_backlog_detail(&backlog);
 
diff --git a/src/bin/ranger/commands/task.rs b/src/bin/ranger/commands/task.rs
index 417694f..892618a 100644
--- a/src/bin/ranger/commands/task.rs
+++ b/src/bin/ranger/commands/task.rs
@@ -178,15 +178,16 @@ pub async fn run(pool: &SqlitePool, command: TaskCommands, json: bool) -> Result
             let mut conn = pool.acquire().await?;
             let state = state.map(|s| s.parse::<State>()).transpose()?;
 
-            let all_keys = ops::task::all_keys(&mut conn).await?;
-            let prefixes = key::unique_prefix_lengths(&all_keys);
-
             if let Some(backlog_name) = &backlog {
                 let bl = ops::backlog::get_by_name(&mut conn, backlog_name).await?;
+                let backlog_keys = ops::task::keys_for_backlog(&mut conn, bl.id).await?;
+                let prefixes = key::unique_prefix_lengths(&backlog_keys);
                 let tasks = ops::task::list(&mut conn, bl.id, state).await?;
                 output::print_list(&tasks, json, |t| print_task(t, &prefixes));
             } else {
                 // List all tasks (no backlog filter)
+                let all_keys = ops::task::all_keys(&mut conn).await?;
+                let prefixes = key::unique_prefix_lengths(&all_keys);
                 let backlogs = ops::backlog::list(&mut conn).await?;
                 let mut all_tasks = Vec::new();
                 for bl in &backlogs {
diff --git a/src/ops/task.rs b/src/ops/task.rs
index 2e881df..d059ace 100644
--- a/src/ops/task.rs
+++ b/src/ops/task.rs
@@ -91,6 +91,17 @@ pub async fn all_keys(conn: &mut SqliteConnection) -> Result<Vec<String>, Ranger
     Ok(rows.into_iter().map(|(k,)| k).collect())
 }
 
+pub async fn keys_for_backlog(
+    conn: &mut SqliteConnection,
+    backlog_id: i64,
+) -> Result<Vec<String>, RangerError> {
+    let rows: Vec<(String,)> = sqlx::query_as("SELECT key FROM tasks WHERE backlog_id = ?")
+        .bind(backlog_id)
+        .fetch_all(&mut *conn)
+        .await?;
+    Ok(rows.into_iter().map(|(k,)| k).collect())
+}
+
 pub async fn get_by_id(conn: &mut SqliteConnection, id: i64) -> Result<Task, RangerError> {
     let query = format!("SELECT {TASK_COLUMNS} FROM tasks WHERE id = ?");
     let task = sqlx::query_as::<_, Task>(&query)
@@ -1202,4 +1213,47 @@ mod tests {
         let count = rebalance(&mut conn, bl.id).await.unwrap();
         assert_eq!(count, 0);
     }
+
+    #[tokio::test]
+    async fn keys_for_backlog_scoped_to_backlog() {
+        let pool = test_pool().await;
+        let mut conn = pool.acquire().await.unwrap();
+        let bl1 = backlog::create(&mut conn, "Alpha").await.unwrap();
+        let bl2 = backlog::create(&mut conn, "Beta").await.unwrap();
+
+        let t1 = create(
+            &mut conn,
+            CreateTask {
+                title: "Task in Alpha",
+                backlog_id: bl1.id,
+                state: None,
+                parent_id: None,
+                description: None,
+            },
+        )
+        .await
+        .unwrap();
+
+        let t2 = create(
+            &mut conn,
+            CreateTask {
+                title: "Task in Beta",
+                backlog_id: bl2.id,
+                state: None,
+                parent_id: None,
+                description: None,
+            },
+        )
+        .await
+        .unwrap();
+
+        let alpha_keys = keys_for_backlog(&mut conn, bl1.id).await.unwrap();
+        assert_eq!(alpha_keys, vec![t1.key.clone()]);
+
+        let beta_keys = keys_for_backlog(&mut conn, bl2.id).await.unwrap();
+        assert_eq!(beta_keys, vec![t2.key.clone()]);
+
+        let global_keys = all_keys(&mut conn).await.unwrap();
+        assert_eq!(global_keys.len(), 2);
+    }
 }