hyper_scripter/list/
mod.rs

1mod list_impl;
2pub use list_impl::*;
3
4mod grid;
5pub use grid::Grid;
6
7mod table_lib;
8mod time_fmt;
9mod tree;
10mod tree_lib;
11
12use crate::color::{Color, StyleObj, Stylize};
13use crate::util::writable::{write_writable, FmtWrite, Writable};
14use crate::{
15    error::{DisplayError, DisplayResult, Result},
16    script::ScriptInfo,
17};
18use serde::Serialize;
19use std::borrow::Cow;
20use std::num::NonZeroUsize;
21use std::str::FromStr;
22
23#[derive(Clone, Copy, Debug)]
24struct LatestTxt(&'static str, &'static str);
25const SHORT_LATEST_TXT: LatestTxt = LatestTxt("*", "");
26const LONG_LATEST_TXT: LatestTxt = LatestTxt(" *", "  ");
27
28fn style_name_w(
29    mut w: impl Writable,
30    plain: bool,
31    is_latest: bool,
32    latest_txt: LatestTxt,
33    color: Color,
34    name: &str,
35) -> Result<usize> {
36    let mut width = name.len();
37    if is_latest && !plain {
38        write_writable!(w, "{}", latest_txt.0.stylize().color(Color::Yellow).bold())?;
39        width += latest_txt.0.len();
40    } else {
41        write_writable!(w, "{}", latest_txt.1)?;
42        width += latest_txt.1.len();
43    }
44    let name = style(plain, name, |s| {
45        s.color(color).bold();
46        if is_latest {
47            s.underline();
48        }
49    });
50    write_writable!(w, "{}", name)?;
51    Ok(width)
52}
53
54fn style_name(
55    plain: bool,
56    is_latest: bool,
57    latest_txt: LatestTxt,
58    color: Color,
59    name: &str,
60) -> Result<(String, usize)> {
61    let mut s = String::new();
62    let width = style_name_w(FmtWrite(&mut s), plain, is_latest, latest_txt, color, name)?;
63    Ok((s, width))
64}
65
66fn extract_help(script: &ScriptInfo) -> String {
67    let mut buff = String::new();
68    fn inner(buff: &mut String, script: &ScriptInfo) -> Result {
69        let script_path = crate::path::open_script(&script.name, &script.ty, Some(true))?;
70        *buff = crate::util::read_file(&script_path)?;
71        Ok(())
72    }
73    match inner(&mut buff, script) {
74        Err(e) => {
75            log::warn!("讀取腳本失敗{},直接回空的幫助字串", e);
76            return String::new();
77        }
78        Ok(()) => (),
79    };
80    let mut helps = crate::extract_msg::extract_help_from_content(&buff);
81    helps.next().unwrap_or_default().to_owned()
82}
83
84fn exec_time_str(script: &ScriptInfo) -> Cow<'static, str> {
85    match &script.exec_time {
86        None => Cow::Borrowed("Never"),
87        Some(t) => Cow::Owned(format!("{} ({})", time_fmt::fmt(t), script.exec_count)),
88    }
89}
90
91#[derive(Debug, Eq, PartialEq)]
92pub enum DisplayStyle<T, U> {
93    Short(String, U),
94    Long(T),
95}
96#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize)]
97pub enum Grouping {
98    Tag,
99    Tree,
100    None,
101}
102impl Grouping {
103    pub fn is_none(self) -> bool {
104        self == Grouping::None
105    }
106}
107impl Default for Grouping {
108    fn default() -> Self {
109        Grouping::None
110    }
111}
112impl FromStr for Grouping {
113    type Err = DisplayError;
114    fn from_str(s: &str) -> DisplayResult<Self> {
115        let g = match s {
116            "tag" => Grouping::Tag,
117            "tree" => Grouping::Tree,
118            "none" => Grouping::None,
119            _ => unreachable!(),
120        };
121        Ok(g)
122    }
123}
124
125#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize)]
126pub enum Note {
127    File,
128    ID,
129    Type,
130    None,
131}
132impl Default for Note {
133    fn default() -> Self {
134        Note::Type
135    }
136}
137impl FromStr for Note {
138    type Err = DisplayError;
139    fn from_str(s: &str) -> DisplayResult<Self> {
140        let g = match s {
141            "file" => Note::File,
142            "id" => Note::ID,
143            "none" => Note::None,
144            _ => unreachable!(),
145        };
146        Ok(g)
147    }
148}
149
150#[derive(Debug)]
151pub struct ListOptions<T = (), U = ()> {
152    pub grouping: Grouping,
153    pub plain: bool,
154    pub limit: Option<NonZeroUsize>,
155    pub display_style: DisplayStyle<T, U>,
156}
157
158#[inline]
159fn style<T: std::fmt::Display, F: for<'a> FnOnce(&'a mut StyleObj<T>)>(
160    plain: bool,
161    s: T,
162    f: F,
163) -> StyleObj<T> {
164    let mut s = s.stylize();
165    if !plain {
166        f(&mut s);
167    }
168    s
169}
170
171pub fn get_screen_width() -> u16 {
172    console::Term::stdout().size_checked().map_or(0, |s| s.1)
173}