r3bl_tui 0.5.3

TUI library to build modern apps inspired by Elm, with Flexbox, CSS, editor component, emoji support, and more
Documentation
/*
 *   Copyright (c) 2022 R3BL LLC
 *   All rights reserved.
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

//! This module contains code for converting between syntect styled texts and tui styled texts.
//!
//! A [Vec] or [List] of styled text represents a single line of text in an editor component, which
//! is the output of a syntax highlighter (that takes plain text and returns the styled text).
//!
//! There is a major difference in doing this conversion which is:
//! - tui styled texts are styled unicode strings,
//! - while syntect styled texts are styled plain text strings.
//!
//! This requires the conversion code to perform the following steps:
//! 1. Convert the syntect [SyntectStyleStrSpanLine] into a [StyleUSSpanLine].
//! 2. Then convert [StyleUSSpanLine] into a [TuiStyledTexts].

use syntect::parsing::SyntaxSet;

use crate::*;

pub type SyntectStyle = syntect::highlighting::Style;

/// Span are chunks of a text that have an associated style. There are usually multiple spans in a
/// line of text.
pub type SyntectStyleStrSpan<'a> = (SyntectStyle, &'a str);

/// A line of text is made up of multiple [SyntectStyleStrSpan]s.
pub type SyntectStyleStrSpanLine<'a> = Vec<SyntectStyleStrSpan<'a>>;

pub fn try_get_syntax_ref<'a>(
    syntax_set: &'a SyntaxSet,
    file_extension: &'a str,
) -> Option<&'a syntect::parsing::SyntaxReference> {
    syntax_set.find_syntax_by_extension(file_extension)
}

pub fn from_syntect_to_tui(
    syntect_highlighted_line: SyntectStyleStrSpanLine<'_>,
) -> StyleUSSpanLine {
    let mut it = StyleUSSpanLine::from(syntect_highlighted_line);

    // Remove the background color from each style in the theme.
    it.iter_mut()
        .for_each(|StyleUSSpan { style, text: _ }| style.remove_bg_color());

    it
}

mod syntect_support {
    use super::*;

    impl From<SyntectStyleStrSpanLine<'_>> for TuiStyledTexts {
        fn from(value: SyntectStyleStrSpanLine<'_>) -> Self {
            TuiStyledTexts::from(&value)
        }
    }

    impl From<&SyntectStyleStrSpanLine<'_>> for TuiStyledTexts {
        fn from(syntect_styles: &SyntectStyleStrSpanLine<'_>) -> Self {
            let mut acc = TuiStyledTexts::default();
            for (syntect_style, text) in syntect_styles {
                let my_style = convert_style_from_syntect_to_tui(*syntect_style);
                acc += tui_styled_text!(@style: my_style, @text: text.to_string());
            }
            acc
        }
    }

    impl From<SyntectStyleStrSpanLine<'_>> for StyleUSSpanLine {
        fn from(value: SyntectStyleStrSpanLine<'_>) -> Self {
            pub fn from_vec_styled_str(
                vec_styled_str: &SyntectStyleStrSpanLine<'_>,
            ) -> StyleUSSpanLine {
                let mut it: StyleUSSpanLine = Default::default();

                for (style, text) in vec_styled_str {
                    let my_style = convert_style_from_syntect_to_tui(*style);
                    let unicode_string = US::from(*text);
                    it.push(StyleUSSpan::new(my_style, unicode_string));
                }

                it
            }

            from_vec_styled_str(&value)
        }
    }
}