1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::{Ctx, EndpointHandle};
use colored::Colorize;
use std::path::PathBuf;

#[derive(clap::Args, Debug)]
pub struct Args {
    /// Set a limit for how deep the listing goes in sub-handles
    #[arg(long, value_name = "N")]
    depth: Option<usize>,
}

pub fn cmd(ctx: &Ctx, args: Args) {
    let max_depth = args.depth.unwrap_or(usize::MAX).max(1);
    let mut current = PathBuf::new();

    if let Some(handle) = EndpointHandle::from_state(ctx) {
        current = handle.dir(ctx)
    }

    // This code is a mess.
    // I'm sorry.
    // It will be refactored sometime.
    struct TraverseEndpoints<'s> {
        f: &'s dyn Fn(&TraverseEndpoints, Vec<EndpointHandle>),
    }
    let traverse_handles = TraverseEndpoints {
        f: &|recurse, handles| {
            for handle in handles {
                let children = handle.children(ctx);

                if !handle.path.is_empty() {
                    let (annotation, method, display_handle) = {
                        let mut ann = " ";
                        let mut m = "---".dimmed();
                        let mut h = handle.handle().normal();

                        if current == handle.dir(ctx) {
                            ann = "*";
                            h = h.green();
                        }

                        if let Some(endpoint) = handle.endpoint(ctx) {
                            m = endpoint.colored_method().bold();
                        }

                        (ann, m, h)
                    };

                    print!("{}  {: >5} {}", annotation, method, display_handle);
                }

                if !children.is_empty() {
                    if handle.path.len() < max_depth {
                        // Avoid extra newline from Specification::QUARTZ usage
                        if !handle.path.is_empty() {
                            println!();
                        }

                        (recurse.f)(recurse, children);
                    } else {
                        println!("{}", " +".dimmed());
                    }
                } else {
                    println!();
                }
            }
        },
    };

    (traverse_handles.f)(&traverse_handles, vec![EndpointHandle::QUARTZ]);
}