asimov_module_cli/lib.rs
1// This is free and unencumbered software released into the public domain.
2
3pub mod commands;
4pub mod features;
5pub mod options {}
6pub mod registry;
7
8use clientele::{StandardOptions, SysexitsError};
9
10/// Sorts links from a module's manifest in the order that we'd like to display
11/// them for the command `link` and for choosing the URL to open for the command
12/// `browse`.
13pub(crate) fn sort_links(module_name: &str, links: &mut [impl AsRef<str>]) {
14 use std::cmp::Reverse;
15
16 links.sort_by_cached_key(|link| {
17 let Ok(url) = reqwest::Url::parse(link.as_ref()) else {
18 // it's not even a valid url? put it last
19 return Reverse(0);
20 };
21
22 let Some(host) = url.host_str() else {
23 // it doesn't have a host, put it last
24 return Reverse(0);
25 };
26
27 // give highest priority to github links under our org
28 let our_module = link.as_ref().contains("github.com/asimov-modules/") as i8;
29
30 let host_score =
31 // give priority to github links
32 (host.ends_with("github.com") as i8 * 2)
33 // then any of the package indices
34 + ((host.ends_with("crates.io") ||
35 host.ends_with("pypi.org") ||
36 host.ends_with("rubygems.org") ||
37 host.ends_with("npmjs.com")) as i8);
38
39 let path_score = {
40 let path = url.path();
41 // give highest priority to links which contain the exact module name
42 (path.contains(&format!("asimov-{module_name}-module")) as i8 * 3)
43 // next to links which contain `asimov-`
44 + (((path.contains("asimov-")
45 // and `-module`
46 && path.contains("-module")
47 // but not `/asimov-modules/`
48 && !path.contains("/asimov-modules/")) as i8) * 2)
49 // and finally if the path does contain `/asimov-modules/`
50 + (path.contains("/asimov-modules/") as i8)
51 };
52
53 // add all the scores together, then reverse it because we want the highest scores first (sort is ascending order)
54 // (add 1 to differentiate from the invalid/host-less links that we return early for)
55 Reverse(our_module * 5 + host_score + path_score + 1)
56 });
57}