Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  internal.rs   Sprache: unbekannt

 
use crate::tree_config::{tree_config, TreeConfig};
use std::cmp::max;
use std::sync::{Arc, Mutex};

/// Tree that holds `text` for the current leaf and a list of `children` that are the branches.
#[derive(Debug)]
pub struct Tree {
    pub text: Option<String>,
    pub children: Vec<Tree>,
}

/// Position of the element relative to its siblings
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Position {
    Inside,
    First,
    Last,
    Only,
}

impl Tree {
    /// Create a new tree with some optional text.
    pub fn new(text: Option<&str>) -> Tree {
        Tree {
            text: text.map(|x| x.to_string()),
            children: Vec::new(),
        }
    }

    /// Navigate to the branch at the given `path` relative to this tree.
    /// If a valid branch is found by following the path, it is returned.
    pub fn at_mut(&mut self, path: &[usize]) -> Option<&mut Tree> {
        match path.first() {
            Some(&i) => match self.children.get_mut(i) {
                Some(x) => x.at_mut(&path[1..]),
                _ => None,
            },
            _ => Some(self),
        }
    }

    /// "Render" this tree as a list of `String`s.
    /// Each string represents a line in the tree.
    /// `does_continue` is a bool for each column indicating whether the tree continues.
    pub fn lines(
        &self,
        does_continue: &Vec<bool>,
        index: usize,
        pool_size: usize,
        config: &TreeConfig,
    ) -> Vec<String> {
        let does_continue = if config.show_first_level && does_continue.is_empty() {
            vec![true]
        } else {
            does_continue.clone()
        };
        let position = match index {
            _ if pool_size == 1 => Position::Only,
            _ if (index + 1) == pool_size => Position::Last,
            0 => Position::First,
            _ => Position::Inside,
        };
        let mut next_continue = does_continue.clone();
        next_continue.push(match position {
            Position::Inside | Position::First => true,
            Position::Last | Position::Only => false,
        });

        let mut txt = String::new();
        let pad: String;
        if does_continue.len() > 1 {
            for &i in &does_continue[2..] {
                txt.push_str(&format!(
                    "{}{:indent$}",
                    if i { config.symbols.continued } else { " " },
                    "",
                    indent = max(config.indent, 1) - 1
                ));
            }
            pad = txt.clone();
            let branch_size = max(config.indent, 2usize) - 2;
            let branch = match config.symbols.branch.len() {
                0 => "-".repeat(branch_size),
                1 => config.symbols.branch.repeat(branch_size),
                _n => config
                    .symbols
                    .branch
                    .repeat(branch_size)
                    .chars()
                    .take(branch_size)
                    .collect::<String>(),
            };

            let is_multiline = self
                .text
                .as_ref()
                .map(|x| x.contains("\n"))
                .unwrap_or(false);

            let first_leaf = match (is_multiline, config.symbols.multiline_first) {
                (true, Some(x)) => x,
                _ => config.symbols.leaf,
            };
            txt.push_str(&format!(
                "{}{}{}",
                match position {
                    Position::Only => config.symbols.join_only,
                    Position::First => config.symbols.join_first,
                    Position::Last => config.symbols.join_last,
                    Position::Inside => config.symbols.join_inner,
                },
                branch,
                first_leaf,
            ));

            let s = match &self.text {
                Some(x) => match is_multiline {
                    true => format!(
                        "{}",
                        x.replace(
                            "\n",
                            &format!(
                                "\n{}{}{}{}",
                                &pad,
                                match position {
                                    Position::Only | Position::Last =>
                                        " ".repeat(config.symbols.continued.chars().count()),
                                    _ => config.symbols.continued.to_string(),
                                },
                                " ".repeat(branch_size),
                                match &config.symbols.multiline_continued {
                                    Some(multi) => multi.to_string(),
                                    _ => " ".repeat(first_leaf.chars().count()),
                                }
                            ),
                        )
                    ),
                    false => x.clone(),
                },
                _ => String::new(),
            };
            txt.push_str(&s);
        } else {
            if let Some(x) = &self.text {
                txt.push_str(&x);
            }
        }
        let mut ret = vec![txt];
        for (index, x) in self.children.iter().enumerate() {
            for line in x.lines(&next_continue, index, self.children.len(), config) {
                ret.push(line);
            }
        }
        ret
    }
}

/// Holds the current state of the tree, including the path to the branch.
/// Multiple trees may point to the same data.
#[derive(Debug, Clone)]
pub(crate) struct TreeBuilderBase {
    data: Arc<Mutex<Tree>>,
    path: Vec<usize>,
    dive_count: usize,
    config: Option<TreeConfig>,
    is_enabled: bool,
}

impl TreeBuilderBase {
    /// Create a new state
    pub fn new() -> TreeBuilderBase {
        TreeBuilderBase {
            data: Arc::new(Mutex::new(Tree::new(None))),
            path: vec![],
            dive_count: 1,
            config: None,
            is_enabled: true,
        }
    }

    pub fn set_enabled(&mut self, enabled: bool) {
        self.is_enabled = enabled;
    }
    pub fn is_enabled(&self) -> bool {
        self.is_enabled
    }

    pub fn add_leaf(&mut self, text: &str) {
        let &dive_count = &self.dive_count;
        if dive_count > 0 {
            for i in 0..dive_count {
                let mut n = 0;
                if let Some(x) = self.data.lock().unwrap().at_mut(&self.path) {
                    x.children.push(Tree::new(if i == max(1, dive_count) - 1 {
                        Some(&text)
                    } else {
                        None
                    }));
                    n = x.children.len() - 1;
                }
                self.path.push(n);
            }
            self.dive_count = 0;
        } else {
            if let Some(x) = self
                .data
                .lock()
                .unwrap()
                .at_mut(&self.path[..max(1, self.path.len()) - 1])
            {
                x.children.push(Tree::new(Some(&text)));
                let n = match self.path.last() {
                    Some(&x) => x + 1,
                    _ => 0,
                };
                self.path.last_mut().map(|x| *x = n);
            }
        }
    }

    pub fn set_config_override(&mut self, config: Option<TreeConfig>) {
        self.config = config;
    }

    pub fn config_override(&self) -> &Option<TreeConfig> {
        &self.config
    }
    pub fn config_override_mut(&mut self) -> &mut Option<TreeConfig> {
        &mut self.config
    }

    pub fn enter(&mut self) {
        self.dive_count += 1;
    }

    /// Try stepping up to the parent tree branch.
    /// Returns false if already at the top branch.
    pub fn exit(&mut self) -> bool {
        if self.dive_count > 0 {
            self.dive_count -= 1;
            true
        } else {
            if self.path.len() > 1 {
                self.path.pop();
                true
            } else {
                false
            }
        }
    }

    pub fn depth(&self) -> usize {
        max(1, self.path.len() + self.dive_count) - 1
    }

    pub fn peek_print(&self) {
        println!("{}", self.peek_string());
    }

    pub fn print(&mut self) {
        self.peek_print();
        self.clear();
    }
    pub fn clear(&mut self) {
        *self = Self::new();
    }

    pub fn string(&mut self) -> String {
        let s = self.peek_string();
        self.clear();
        s
    }

    pub fn peek_string(&self) -> String {
        let config = self
            .config_override()
            .clone()
            .unwrap_or_else(|| tree_config().clone());
        (&self.data.lock().unwrap().lines(&vec![], 0, 1, &config)[1..]).join("\n")
    }
}

[ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge