Skip to main content

asimov_cli/
lib.rs

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