/****************************************************************************** __ ____ __ / / ___ ____ _/ __/_____________ _/ /__ / / / _ \/ __ `/ /_/ ___/ ___/ __ `/ / _ \ / /___/ __/ /_/ / __(__ ) /__/ /_/ / / __/ /_____/\___/\__,_/_/ /____/\___/\__,_/_/\___/ (C)opyright 2025, Leafscale, LLC - https://www.leafscale.com Project: Zygaena Filename: search.reef Authors: Chris Tusa License: Description: Search command - search for packages by name or description ******************************************************************************/ module commands.search import sys.args import core.str import core.port import core.portindex import core.database import types import util.color import exitcodes as ec export fn execute(): int end export fn execute(): int let argc = args.count() if argc < 3 print_usage() return ec.EXIT_USAGE() end if let search_term = args.get(2) color.print_action("Searching for: " + search_term) println("") mut total = 0 // Try ports index first (fast path) if portindex.port_index_exists() mut results: [portindex.PortIndexEntry] = new [portindex.PortIndexEntry](512) let result_count = portindex.search_ports(search_term, results, 512) mut i = 0 while i < result_count let entry = results[i] print_index_match(entry) total = total + 1 i = i + 1 end while else // Fall back to filesystem scan mut cats: [string] = new [string](32) let cat_count = port.get_categories(cats, 32) mut i = 0 while i < cat_count let category = cats[i] mut ports: [string] = new [string](256) let port_count = port.list_category(category, ports, 256) mut j = 0 while j < port_count let port_name = ports[j] let result = port.find(port_name) if result.success let p = result.port // Check if search term matches name or description if matches_search(p, search_term) print_match(p, category) total = total + 1 end if end if j = j + 1 end while i = i + 1 end while end if if total == 0 color.print_info("No packages found matching: " + search_term) else println("") color.print_info("Found " + int_to_str(total) + " package(s)") end if return ec.EXIT_SUCCESS() end execute fn matches_search(p: types.Port, term: string): bool let lower_term = str.to_lower(term) let lower_name = str.to_lower(p.info.name) let lower_desc = str.to_lower(p.info.description) // Check name if str.contains(lower_name, lower_term) return true end if // Check description if str.contains(lower_desc, lower_term) return true end if return false end matches_search proc print_index_match(entry: portindex.PortIndexEntry) let is_installed = database.is_installed(entry.name) print(entry.category) print("/") print(entry.name) print(" ") print(entry.version) if is_installed print(" [installed]") end if println("") print(" ") println(entry.description) end print_index_match proc print_match(p: types.Port, category: string) // Check if installed let is_installed = database.is_installed(p.info.name) print(category) print("/") print(p.info.name) print(" ") print(p.info.version) if is_installed print(" [installed]") end if println("") print(" ") println(p.info.description) end print_match proc print_usage() println("Usage: coral search ") println("") println("Search for packages by name or description.") println("") println("Arguments:") println(" Search term to look for") println("") println("Examples:") println(" coral search vim") println(" coral search editor") println(" coral search hello") end print_usage // Helper: convert int to string fn int_to_str(n: int): string if n == 0 return "0" end if mut negative = false mut value = n if n < 0 negative = true value = 0 - n end if mut result = "" while value > 0 let digit = value % 10 result = str.concat(str.substring("0123456789", digit, 1), result) value = value / 10 end while if negative result = str.concat("-", result) end if return result end int_to_str end module