code-moniker 0.4.0

Standalone CLI / linter for the code-moniker symbol graph: file and directory probes, project-wide architecture rules.
Documentation
use anstyle::{AnsiColor, Style};
use code_moniker_core::core::shape::Shape;

use crate::args::{Charset, ExtractArgs};
use crate::color::resolve_color;

pub(super) struct TreeOpts {
	pub(super) glyph: Glyphs,
	pub(super) palette: Palette,
}

impl TreeOpts {
	pub(super) fn from_args(args: &ExtractArgs) -> Self {
		let glyph = match args.charset {
			Charset::Utf8 => Glyphs::utf8(),
			Charset::Ascii => Glyphs::ascii(),
		};
		let palette = if resolve_color(args.color) {
			Palette::ansi()
		} else {
			Palette::none()
		};
		Self { glyph, palette }
	}
}

pub(super) struct Glyphs {
	pub(super) tee: &'static str,
	pub(super) last: &'static str,
	pub(super) skip_mid: &'static str,
	pub(super) skip_last: &'static str,
	pub(super) arrow: &'static str,
}

impl Glyphs {
	fn utf8() -> Self {
		Self {
			tee: "├──",
			last: "└──",
			skip_mid: "",
			skip_last: "    ",
			arrow: "",
		}
	}

	fn ascii() -> Self {
		Self {
			tee: "+--",
			last: "+--",
			skip_mid: "|   ",
			skip_last: "    ",
			arrow: "->",
		}
	}
}

pub(super) struct Palette {
	pub(super) namespace_kind: Style,
	pub(super) type_kind: Style,
	pub(super) callable_kind: Style,
	pub(super) value_kind: Style,
	pub(super) meta_kind: Style,
	pub(super) unknown_kind: Style,
	pub(super) name: Style,
	pub(super) range: Style,
	pub(super) arrow: Style,
	pub(super) ref_kind: Style,
	pub(super) dim: Style,
	pub(super) punct: Style,
	pub(super) arg_name: Style,
	pub(super) arg_type: Style,
}

impl Palette {
	fn none() -> Self {
		Self {
			namespace_kind: plain(),
			type_kind: plain(),
			callable_kind: plain(),
			value_kind: plain(),
			meta_kind: plain(),
			unknown_kind: plain(),
			name: plain(),
			range: plain(),
			arrow: plain(),
			ref_kind: plain(),
			dim: plain(),
			punct: plain(),
			arg_name: plain(),
			arg_type: plain(),
		}
	}

	fn ansi() -> Self {
		Self {
			namespace_kind: fg(AnsiColor::Cyan),
			type_kind: bold_fg(AnsiColor::Blue),
			callable_kind: fg(AnsiColor::Green),
			value_kind: fg(AnsiColor::Yellow),
			meta_kind: dim_fg(AnsiColor::BrightBlack),
			unknown_kind: fg(AnsiColor::Cyan),
			name: bold(),
			range: fg(AnsiColor::Green),
			arrow: dim_fg(AnsiColor::BrightBlack),
			ref_kind: fg(AnsiColor::Magenta),
			dim: dim_fg(AnsiColor::BrightBlack),
			punct: fg(AnsiColor::BrightBlack),
			arg_name: fg(AnsiColor::Yellow),
			arg_type: fg(AnsiColor::Blue),
		}
	}

	pub(super) fn kind_style(&self, shape: Option<Shape>) -> Style {
		match shape {
			Some(Shape::Namespace) => self.namespace_kind,
			Some(Shape::Type) => self.type_kind,
			Some(Shape::Callable) => self.callable_kind,
			Some(Shape::Value) => self.value_kind,
			Some(Shape::Annotation) => self.meta_kind,
			Some(Shape::Ref) => self.ref_kind,
			None => self.unknown_kind,
		}
	}
}

fn plain() -> Style {
	Style::new()
}

fn bold() -> Style {
	plain().bold()
}

fn fg(color: AnsiColor) -> Style {
	plain().fg_color(Some(color.into()))
}

fn bold_fg(color: AnsiColor) -> Style {
	fg(color).bold()
}

fn dim_fg(color: AnsiColor) -> Style {
	fg(color).dimmed()
}