From 457385c68a37b6712a417a0a030022ac9c516a0e Mon Sep 17 00:00:00 2001 From: Daniel Cardona Rojas Date: Mon, 20 Apr 2026 23:59:37 -0500 Subject: [PATCH] Improve output json --- src/cli/handlers.rs | 10 +++++++--- src/cli/output.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/cli/handlers.rs b/src/cli/handlers.rs index b301818..9a3f231 100644 --- a/src/cli/handlers.rs +++ b/src/cli/handlers.rs @@ -5,8 +5,8 @@ use clap::CommandFactory; use clap_complete::generate; use crate::cli::output::{ - self, ByteLocation, HealOutput, HealUpdate, OutputMode, short_id, write_bookmark_markdown, - write_heal_output, write_json_success, write_success, + self, ByteLocation, CollectionWithCount, HealOutput, HealUpdate, OutputMode, short_id, + write_bookmark_markdown, write_heal_output, write_json_success, write_success, }; use crate::cli::*; use crate::config::Config; @@ -2226,7 +2226,11 @@ fn handle_collection_list(cli: &Cli, mode: &OutputMode, args: &CollectionListArg } match mode { - OutputMode::Json => write_json_success(&collections)?, + OutputMode::Json => { + let with_counts: Vec = + collections.iter().map(CollectionWithCount::from).collect(); + write_json_success(&with_counts)? + } OutputMode::Table => { let mut table = comfy_table::Table::new(); table.set_header(vec!["Name", "Bookmarks", "Description", "Created"]); diff --git a/src/cli/output.rs b/src/cli/output.rs index 14df8e7..9fadf7d 100644 --- a/src/cli/output.rs +++ b/src/cli/output.rs @@ -8,7 +8,48 @@ use comfy_table::{Cell, Table}; use is_terminal::IsTerminal; use serde::Serialize; -use crate::engine::bookmark::{Bookmark, Resolution}; +use crate::engine::bookmark::{Bookmark, Collection, Resolution}; + +// --- Collection output formatting --- + +/// A collection with its associated bookmark count for list output. +#[derive(Debug, Serialize)] +pub struct CollectionWithCount { + pub id: String, + pub name: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub description: Option, + pub created_at: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub created_by: Option, + pub bookmark_count: usize, +} + +impl From<&(Collection, usize)> for CollectionWithCount { + fn from((collection, count): &(Collection, usize)) -> Self { + Self { + id: collection.id.clone(), + name: collection.name.clone(), + description: collection.description.clone(), + created_at: collection.created_at.clone(), + created_by: collection.created_by.clone(), + bookmark_count: *count, + } + } +} + +impl From<(Collection, usize)> for CollectionWithCount { + fn from((collection, count): (Collection, usize)) -> Self { + Self { + id: collection.id, + name: collection.name, + description: collection.description, + created_at: collection.created_at, + created_by: collection.created_by, + bookmark_count: count, + } + } +} /// Helper function to get the first annotation's notes from a bookmark. fn get_first_note(bm: &Bookmark) -> &str {