this repo has no description

Add human-readable keyword and flag color formatting

- Added functions to format message keywords and flag colors in a human-readable way
- Updated fastmail_list to use these functions for better display of labels
- Enhanced flag_color_test with a demo of the formatting functionality
- Updated AGENT.md to mark task as completed

🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>

+2 -1
AGENT.md
···
also list the JMAP labels associated with each message.
9. DONE Read the mailbox attribute spec in specs/ and add a typed interface to the
JMAP labels defined in there.
-
10. Add an OCaml interface to compose result references together explicitly into a
single request, from reading the specs.
···
also list the JMAP labels associated with each message.
9. DONE Read the mailbox attribute spec in specs/ and add a typed interface to the
JMAP labels defined in there.
+
10. DONE Integrate the human-readable keyword and label printing into fastmail-list.
+
11. Add an OCaml interface to compose result references together explicitly into a
single request, from reading the specs.
+3 -7
bin/fastmail_list.ml
···
(* Format labels/keywords if requested *)
let labels_str =
if show_labels then
-
let active_keywords =
-
List.filter_map (fun (keyword, active) ->
-
if active then Some (Jmap_mail.Json.string_of_keyword keyword) else None
-
) email.keywords
-
in
-
if List.length active_keywords > 0 then
-
" [" ^ String.concat ", " active_keywords ^ "]"
else
""
else
···
(* Format labels/keywords if requested *)
let labels_str =
if show_labels then
+
let formatted = Jmap_mail.Types.format_email_keywords email.keywords in
+
if formatted <> "" then
+
" [" ^ formatted ^ "]"
else
""
else
+23 -1
bin/flag_color_test.ml
···
Printf.printf "\n"
(** Main entry point *)
let () =
demo_flag_colors ();
demo_message_keywords ();
-
demo_mailbox_attributes ()
···
Printf.printf "\n"
+
(** Demonstrate formatting functionality *)
+
let demo_formatting () =
+
Printf.printf "Keyword Formatting Demo:\n";
+
Printf.printf "======================\n";
+
+
(* Create a sample email with various keywords *)
+
let sample_keywords = [
+
(Flagged, true); (* Standard flag *)
+
(Custom "$MailFlagBit0", true); (* Flag color bit *)
+
(Custom "$MailFlagBit2", true); (* Flag color bit *)
+
(Custom "$notify", true); (* Message keyword *)
+
(Custom "$followed", true); (* Message keyword *)
+
(Custom "$hasattachment", true); (* Message keyword *)
+
(Seen, false); (* Inactive keyword *)
+
(Custom "$random", true); (* Unknown keyword *)
+
] in
+
+
(* Test formatted output *)
+
let formatted = format_email_keywords sample_keywords in
+
Printf.printf "Formatted keywords: %s\n\n" formatted
+
(** Main entry point *)
let () =
demo_flag_colors ();
demo_message_keywords ();
+
demo_mailbox_attributes ();
+
demo_formatting ()
+77
lib/jmap_mail.ml
···
| "Scheduled" -> Scheduled
| "Memos" -> Memos
| s -> OtherAttribute s
end
(** {1 JSON serialization} *)
···
| "Scheduled" -> Scheduled
| "Memos" -> Memos
| s -> OtherAttribute s
+
+
(** Get a human-readable representation of a flag color *)
+
let human_readable_flag_color = function
+
| Red -> "Red"
+
| Orange -> "Orange"
+
| Yellow -> "Yellow"
+
| Green -> "Green"
+
| Blue -> "Blue"
+
| Purple -> "Purple"
+
| Gray -> "Gray"
+
+
(** Get a human-readable representation of a message keyword *)
+
let human_readable_message_keyword = function
+
| Notify -> "Notify"
+
| Muted -> "Muted"
+
| Followed -> "Followed"
+
| Memo -> "Memo"
+
| HasMemo -> "Has Memo"
+
| HasAttachment -> "Has Attachment"
+
| HasNoAttachment -> "No Attachment"
+
| AutoSent -> "Auto Sent"
+
| Unsubscribed -> "Unsubscribed"
+
| CanUnsubscribe -> "Can Unsubscribe"
+
| Imported -> "Imported"
+
| IsTrusted -> "Trusted"
+
| MaskedEmail -> "Masked Email"
+
| New -> "New"
+
| MailFlagBit0 | MailFlagBit1 | MailFlagBit2 -> "Flag Bit"
+
| OtherKeyword s -> s
+
+
(** Format email keywords into a human-readable string representation *)
+
let format_email_keywords keywords =
+
(* Get flag color if present *)
+
let color_str =
+
match get_flag_color keywords with
+
| Some color -> human_readable_flag_color color
+
| None -> ""
+
in
+
+
(* Get standard JMAP keywords *)
+
let standard_keywords = List.filter_map (fun (kw, active) ->
+
if not active then None
+
else match kw with
+
| Flagged -> Some "Flagged"
+
| Answered -> Some "Answered"
+
| Draft -> Some "Draft"
+
| Forwarded -> Some "Forwarded"
+
| Phishing -> Some "Phishing"
+
| Junk -> Some "Junk"
+
| NotJunk -> Some "Not Junk"
+
| Seen -> Some "Seen"
+
| Unread -> Some "Unread"
+
| _ -> None
+
) keywords in
+
+
(* Get message keywords *)
+
let message_keywords = List.filter_map (fun (kw, active) ->
+
if not active then None
+
else match kw with
+
| Custom s ->
+
(* Try to parse as message keyword *)
+
let message_kw = message_keyword_of_string s in
+
(match message_kw with
+
| OtherKeyword _ -> None
+
| MailFlagBit0 | MailFlagBit1 | MailFlagBit2 -> None
+
| kw -> Some (human_readable_message_keyword kw))
+
| _ -> None
+
) keywords in
+
+
(* Combine all human-readable labels *)
+
let all_parts =
+
(if color_str <> "" then [color_str] else []) @
+
standard_keywords @
+
message_keywords
+
in
+
+
String.concat ", " all_parts
end
(** {1 JSON serialization} *)
+9
lib/jmap_mail.mli
···
(** Parse a string into a mailbox attribute *)
val mailbox_attribute_of_string : string -> mailbox_attribute
end
(** {1 JSON serialization} *)
···
(** Parse a string into a mailbox attribute *)
val mailbox_attribute_of_string : string -> mailbox_attribute
+
+
(** Get a human-readable representation of a flag color *)
+
val human_readable_flag_color : flag_color -> string
+
+
(** Get a human-readable representation of a message keyword *)
+
val human_readable_message_keyword : message_keyword -> string
+
+
(** Format email keywords into a human-readable string representation *)
+
val format_email_keywords : (keyword * bool) list -> string
end
(** {1 JSON serialization} *)