diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b57a191ec..501ee5655 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,6 +48,7 @@ CSharp: # required, this will be the name of the enum variant for the language a - "#803788" - "#FFFFFF" chip: "#178600" # required, this is used for the language breakdown bar, its value can be found in linguist (link 2). + icon: '\u{E648}' # optional, the UTF-16 code point of the nerd font icon if supported (link 3). serialization: c# # required only if the Enum name `CSharp` doesn't match the display name `C#` ``` @@ -60,6 +61,7 @@ CSharp: # required, this will be the name of the enum variant for the language a - link 1: https://github.com/XAMPPRocky/tokei#supported-languages - link 2: https://github.com/github/linguist/blob/master/lib/linguist/languages.yml +- link 3: https://www.nerdfonts.com/cheat-sheet ### Adding translation for README.md diff --git a/languages.yaml b/languages.yaml index 6e17047b0..68d19df57 100644 --- a/languages.yaml +++ b/languages.yaml @@ -79,6 +79,7 @@ Ada: - "#0018C9" - "#0C0A7C" chip: "#02F88C" + icon: '\u{E6B5}' Agda: type: programming ascii: | @@ -113,6 +114,7 @@ Arduino: ansi: - cyan chip: "#F34B7D" + icon: '\u{F34B}' Assembly: type: programming ascii: | @@ -138,6 +140,7 @@ Assembly: - yellow - green chip: "#6E4C13" + icon: '\u{E6AB}' AutoHotKey: type: programming ascii: | @@ -185,6 +188,7 @@ Bash: - white - green chip: "#89E051" + icon: '\u{EBCA}' C: type: programming ascii: | @@ -223,6 +227,7 @@ C: - "#00599D" - "#FFFFFF" chip: "#555555" + icon: '\u{E61E}' Ceylon: type: programming ascii: | @@ -281,6 +286,7 @@ Clojure: - cyan - green chip: "#DB5855" + icon: '\u{E768}' CMake: type: programming ascii: | @@ -325,6 +331,7 @@ CoffeeScript: ansi: - red chip: "#244776" + icon: '\u{E751}' ColdFusion: type: programming ascii: | @@ -352,6 +359,7 @@ ColdFusion: - "#E5F3FC" - "#274550" chip: "#ed2cd6" + icon: '\u{E645}' Coq: type: programming ascii: | @@ -418,6 +426,7 @@ Cpp: - "#00599D" - "#FFFFFF" chip: "#F34B7D" + icon: '\u{E61D}' serialization: c++ Crystal: type: programming @@ -447,6 +456,7 @@ Crystal: - white - black chip: "#000100" + icon: '\u{E62F}' CSharp: type: programming ascii: | @@ -485,6 +495,7 @@ CSharp: - "#803788" - "#FFFFFF" chip: "#178600" + icon: '\u{E648}' serialization: c# Css: type: markup @@ -515,6 +526,7 @@ Css: - blue - white chip: "#563D7C" + icon: '\u{E749}' D: type: programming ascii: | @@ -537,6 +549,7 @@ D: ansi: - red chip: "#BA595E" + icon: '\u{E7AF}' Dart: type: programming ascii: | @@ -568,6 +581,7 @@ Dart: - "#42DFCD" - "#01597D" chip: "#00B4AB" + icon: '\u{E64C}' Dockerfile: type: programming ascii: | @@ -585,6 +599,7 @@ Dockerfile: - white - cyan chip: "#384D54" + icon: '\u{F308}' Elisp: type: programming ascii: | @@ -608,6 +623,7 @@ Elisp: - magenta - white chip: "#C065DB" + icon: '\u{E632}' serialization: emacs-lisp Elixir: type: programming @@ -637,6 +653,7 @@ Elixir: ansi: - magenta chip: "#6E4A7E" + icon: '\u{E62D}' Elm: type: programming ascii: | @@ -665,6 +682,7 @@ Elm: - yellow - cyan chip: "#60B5CC" + icon: '\u{E62C}' Emojicode: type: programming ascii: | @@ -703,6 +721,7 @@ Emojicode: - "#AA8DD8" - "#744EAA" chip: "#60B5CC" + icon: '\u{f1044}' Erlang: type: programming ascii: | @@ -722,6 +741,7 @@ Erlang: ansi: - red chip: "#B83998" + icon: '\u{E7B1}' Fish: type: programming ascii: | @@ -745,6 +765,7 @@ Fish: - red - yellow chip: "#4AAE47" + icon: '\u{EE41}' Forth: type: programming ascii: | @@ -772,6 +793,7 @@ Forth: ansi: - red chip: "#341708" + icon: '\u{229E}' FortranLegacy: type: programming ascii: | @@ -801,6 +823,7 @@ FortranLegacy: - yellow - red chip: "#4D41B1" + icon: '\u{f121a}' serialization: fortran FortranModern: type: programming @@ -831,6 +854,7 @@ FortranModern: - yellow - red chip: "#4D41B1" + icon: '\u{f121a}' FSharp: type: programming ascii: | @@ -857,6 +881,7 @@ FSharp: - cyan - cyan chip: "#B845FC" + icon: '\u{E7A7}' serialization: f# GdScript: type: programming @@ -887,6 +912,7 @@ GdScript: - "#458DC0" - "#FFFFFF" chip: "#355570" + icon: '\u{E65F}' Glsl: type: programming ascii: | @@ -954,6 +980,7 @@ Go: - "#FFFFFF" - "#F6D2A2" chip: "#00ADD8" + icon: '\u{E627}' Graphql: type: data ascii: | @@ -982,6 +1009,7 @@ Graphql: ansi: - magenta chip: "#E10098" + icon: '\u{e662}' Groovy: type: programming ascii: | @@ -1013,6 +1041,7 @@ Groovy: - cyan - white chip: "#4298B8" + icon: '\u{E775}' Haskell: type: programming ascii: | @@ -1039,6 +1068,7 @@ Haskell: - "#5E5086" - "#8F4E8B" chip: "#5E5086" + icon: '\u{E777}' Haxe: type: programming ascii: | @@ -1072,6 +1102,7 @@ Haxe: - "#F69912" - "#F47216" chip: "#DF7900" + icon: '\u{E666}' Hcl: type: programming ascii: | @@ -1135,6 +1166,7 @@ Hlsl: - "#00A1F1" - "#FFBB00" chip: "#AACE60" + icon: '\u{229E}' HolyC: type: programming ascii: | @@ -1172,6 +1204,7 @@ HolyC: - "#0B449D" - "#FFFFFF" chip: "#FFEFAF" + icon: '\u{E61E}' Html: type: markup ascii: | @@ -1201,6 +1234,7 @@ Html: - red - white chip: "#E34C26" + icon: '\u{E736}' Idris: type: programming ascii: | @@ -1259,6 +1293,7 @@ Java: - "#F44336" - "#1665C0" chip: "#B07219" + icon: '\u{E738}' JavaScript: type: programming ascii: | @@ -1286,6 +1321,7 @@ JavaScript: hex: - "#ECE653" chip: "#F1E05A" + icon: '\u{F2EE}' Json: type: data ascii: | @@ -1312,6 +1348,7 @@ Json: - white - black chip: "#292929" + icon: '\u{eb0f}' Jsonnet: type: programming ascii: | @@ -1376,6 +1413,7 @@ Jsx: - "#B684D3" - "#FFFFFF" chip: "#F1E05A" + icon: '\u{F2EE}' Julia: type: programming ascii: | @@ -1395,6 +1433,7 @@ Julia: - red - magenta chip: "#A270BA" + icon: '\u{E624}' Jupyter: type: programming ascii: | @@ -1461,6 +1500,7 @@ Kotlin: - yellow - magenta chip: "#A97BFF" + icon: '\u{E634}' Lisp: type: programming ascii: | @@ -1488,6 +1528,7 @@ Lisp: ansi: - white chip: "#3FB68B" + icon: '\u{E6B0}' LLVM: type: programming ascii: | @@ -1546,6 +1587,7 @@ Lua: - "#134074" - "#FFFFFF" chip: "#000080" + icon: '\u{E620}' Makefile: type: programming ascii: | @@ -1577,6 +1619,7 @@ Makefile: - "#FAEC9A" - "#610000" chip: "#427819" + icon: '\u{E673}' Markdown: type: prose ascii: | @@ -1602,6 +1645,7 @@ Markdown: - white - red chip: "#083FA1" + icon: '\u{E73E}' line_types: [code, comments] Nim: type: programming @@ -1629,6 +1673,7 @@ Nim: - yellow - white chip: "#FFC200" + icon: '\u{E677}' Nix: type: programming ascii: | @@ -1656,6 +1701,7 @@ Nix: - cyan - blue chip: "#7E7EFF" + icon: '\u{f313}' ObjectiveC: type: programming ascii: | @@ -1701,6 +1747,7 @@ OCaml: ansi: - yellow chip: "#3BE133" + icon: '\u{E67A}' Odin: type: programming ascii: | @@ -1756,6 +1803,7 @@ Org: - red - white chip: "#77AA99" + icon: '\u{E633}' Oz: type: programming ascii: | @@ -1830,6 +1878,7 @@ Perl: ansi: - cyan chip: "#0298C3" + icon: '\u{E67E}' Perl6: type: programming ascii: | @@ -1887,6 +1936,7 @@ Php: - "#777BB3" - "#FFFFFF" chip: "#4F5D95" + icon: '\u{f031f}' PowerShell: type: programming ascii: | @@ -1908,6 +1958,7 @@ PowerShell: - "#316CB9" - "#FFFFFF" chip: "#012456" + icon: '\u{f0a0a}' Processing: type: programming ascii: | @@ -1960,6 +2011,7 @@ Prolog: ansi: - white chip: "#74283C" + icon: '\u{E7A1}' Protobuf: type: programming ascii: | @@ -1999,6 +2051,7 @@ PureScript: ansi: - white chip: "#1D222D" + icon: '\u{E630}' Python: type: programming ascii: | @@ -2032,6 +2085,7 @@ Python: - "#2F69A2" - "#FFD940" chip: "#3572A5" + icon: '\u{E73C}' Qml: type: programming ascii: | @@ -2087,6 +2141,7 @@ R: - white - blue chip: "#198CE7" + icon: '\u{E68A}' Racket: type: programming ascii: | @@ -2204,6 +2259,7 @@ Ruby: - "#A3170C" - "#971A0D" chip: "#701516" + icon: '\u{E739}' Rust: type: programming ascii: | @@ -2231,6 +2287,7 @@ Rust: - "#E43717" - "#FFFFFF" chip: "#DEA584" + icon: '\u{E7A8}' Sass: type: markup ascii: | @@ -2254,6 +2311,7 @@ Sass: hex: - "#CD6799" chip: "#A53B70" + icon: '\u{E74B}' Scala: type: programming ascii: | @@ -2285,6 +2343,7 @@ Scala: - "#DF3F3D" - "#7F0C1D" chip: "#C22D40" + icon: '\u{E737}' Scheme: type: programming ascii: | @@ -2307,6 +2366,7 @@ Scheme: hex: - "#555555" chip: "#1E4AEC" + icon: '\u{E6B1}' Sh: type: programming ascii: | @@ -2328,6 +2388,7 @@ Sh: ansi: - green chip: "#89E051" + icon: '\u{f1183}' serialization: shell Solidity: type: programming @@ -2388,6 +2449,7 @@ Sql: - cyan - yellow chip: "#E38C00" + icon: '\u{E737}' Svelte: type: markup ascii: | @@ -2420,6 +2482,7 @@ Svelte: - "#FF3C00" - "#FFFFFF" chip: "#FF3E00" + icon: '\u{E697}' Svg: type: data ascii: | @@ -2453,6 +2516,7 @@ Svg: - "#FFFFFF" - "#EBA71F" chip: "#FF9900" + icon: '\u{f0721}' Swift: type: programming ascii: | @@ -2504,6 +2568,7 @@ Swift: - "#FC3224" - "#FD2822" chip: "#F05138" + icon: '\u{E755}' SystemVerilog: type: programming ascii: | @@ -2533,6 +2598,7 @@ SystemVerilog: - blue - white chip: "#DAE1C2" + icon: '\u{F4BC}' Tcl: type: programming ascii: | @@ -2559,6 +2625,7 @@ Tcl: - white - cyan chip: "#E4CC98" + icon: '\u{e7c4}' Tex: type: markup ascii: | @@ -2585,6 +2652,7 @@ Tex: - white - black chip: "#3D6117" + icon: '\u{E69B}' Toml: type: data ascii: | @@ -2614,6 +2682,7 @@ Toml: - "#9C4221" - "#FFFFFF" chip: "#9C4221" + icon: '\u{E6B2}' Tsx: type: programming ascii: | @@ -2645,6 +2714,7 @@ Tsx: - "#8A53A6" - "#FFFFFF" chip: "#2B7489" + icon: '\u{E69D}' TypeScript: type: programming ascii: | @@ -2674,6 +2744,7 @@ TypeScript: - "#007ACC" - "#FFFFFF" chip: "#2B7489" + icon: '\u{E69D}' Vala: type: programming ascii: | @@ -2729,6 +2800,7 @@ Verilog: - white - magenta chip: "#b2b7f8" + icon: '\u{F4BC}' Vhdl: type: programming ascii: | @@ -2751,6 +2823,7 @@ Vhdl: - green - white chip: "#ADB2CB" + icon: '\u{F4BC}' VimScript: type: programming ascii: | @@ -2775,6 +2848,7 @@ VimScript: - black - white chip: "#199F4B" + icon: '\u{E7C5}' VisualBasic: type: programming ascii: | @@ -2828,6 +2902,7 @@ Vue: - green - blue chip: "#199F4B" + icon: '\u{E6A0}' WebAssembly: type: programming ascii: | @@ -2855,6 +2930,7 @@ WebAssembly: - "#654FF0" - "#FFFFFF" chip: "#04133B" + icon: '\u{E6A1}' Wolfram: type: programming ascii: | @@ -2916,6 +2992,7 @@ Xaml: - "#3378CE" - "#FFFFFF" chip: "#0060AC" + icon: '\u{f0673}' Xml: type: data ascii: | @@ -2929,6 +3006,7 @@ Xml: - white - green chip: "#0060AC" + icon: '\u{f05c0}' XSL: type: programming ascii: | @@ -2947,6 +3025,7 @@ XSL: ansi: - cyan chip: "#EB8CEB" + icon: '\u{f05c0}' Yaml: type: data ascii: | @@ -2961,6 +3040,7 @@ Yaml: ansi: - white chip: "#CB171E" + icon: '\u{E6A8}' Zig: type: programming ascii: | @@ -2986,6 +3066,7 @@ Zig: ansi: - yellow chip: "#EC915C" + icon: '\u{E6A9}' Zsh: type: programming ascii: | @@ -3006,3 +3087,4 @@ Zsh: ansi: - white chip: "#89E051" + icon: '\u{f1183}' diff --git a/src/cli.rs b/src/cli.rs index 1dae1eced..df2e481ff 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -206,6 +206,11 @@ pub struct VisualsCliOptions { /// Hides the ascii art or image if provided #[arg(long)] pub no_art: bool, + /// Use Nerd Font icons + /// + /// Replaces language chips with Nerd Font icons + #[arg(long)] + pub nerd_fonts: bool, } #[derive(Clone, Debug, Args, PartialEq, Eq, Default)] diff --git a/src/info/langs/language.rs b/src/info/langs/language.rs index 044e16c0b..11d1952ba 100644 --- a/src/info/langs/language.rs +++ b/src/info/langs/language.rs @@ -23,6 +23,8 @@ pub struct LanguagesInfo { number_of_languages_to_display: usize, #[serde(skip_serializing)] info_color: DynColors, + #[serde(skip_serializing)] + nerd_fonts: bool, } impl LanguagesInfo { @@ -31,6 +33,7 @@ impl LanguagesInfo { true_color: bool, number_of_languages_to_display: usize, info_color: DynColors, + nerd_fonts: bool, ) -> Self { let total: usize = loc_by_language.iter().map(|(_, v)| v).sum(); @@ -56,6 +59,7 @@ impl LanguagesInfo { true_color, number_of_languages_to_display, info_color, + nerd_fonts, } } } @@ -71,17 +75,20 @@ impl std::fmt::Display for LanguagesInfo { DynColors::Ansi(AnsiColors::Cyan), ]; - let languages: Vec<(String, f64, DynColors)> = prepare_languages(self, &color_palette); + let languages: Vec = prepare_languages(self, &color_palette); let mut languages_info = build_language_bar(&languages); - for (i, (language, perc, circle_color)) in languages.iter().enumerate() { - let formatted_number = format!("{:.*}", 1, perc); - let circle = "\u{25CF}".color(*circle_color); + for (i, language_display_data) in languages.iter().enumerate() { + let formatted_number = format!("{:.*}", 1, language_display_data.percentage); + let chip = language_display_data + .chip_icon + .color(language_display_data.chip_color); let language_str = format!( "{} {} ", - circle, - format!("{language} ({formatted_number} %)").color(self.info_color) + chip, + format!("{0} ({formatted_number} %)", language_display_data.language) + .color(self.info_color) ); if i % 2 == 0 { write!( @@ -101,10 +108,18 @@ impl std::fmt::Display for LanguagesInfo { } } +#[derive(Debug, PartialEq)] +struct LanguageDisplayData { + language: String, + percentage: f64, + chip_color: DynColors, + chip_icon: char, +} + fn prepare_languages( languages_info: &LanguagesInfo, color_palette: &[DynColors], -) -> Vec<(String, f64, DynColors)> { +) -> Vec { let mut iter = languages_info .languages_with_percentage .iter() @@ -117,12 +132,20 @@ fn prepare_languages( percentage, }, )| { - let circle_color = if languages_info.true_color { - language.get_circle_color() + let chip_color = if languages_info.true_color { + language.get_chip_color() } else { color_palette[i % color_palette.len()] }; - (language.to_string(), percentage, circle_color) + + let chip_icon = language.get_chip_icon(languages_info.nerd_fonts); + + LanguageDisplayData { + language: language.to_string(), + percentage, + chip_color, + chip_icon, + } }, ); if languages_info.languages_with_percentage.len() @@ -132,30 +155,32 @@ fn prepare_languages( .by_ref() .take(languages_info.number_of_languages_to_display) .collect::>(); - let other_perc = iter.fold(0.0, |acc, x| acc + x.1); - languages.push(( - "Other".to_string(), - other_perc, - DynColors::Ansi(AnsiColors::White), - )); + let other_perc = iter.fold(0.0, |acc, x| acc + x.percentage); + languages.push(LanguageDisplayData { + language: "Other".to_string(), + percentage: other_perc, + chip_color: DynColors::Ansi(AnsiColors::White), + chip_icon: DEFAULT_CHIP_ICON, + }); languages } else { iter.collect() } } -fn build_language_bar(languages: &[(String, f64, DynColors)]) -> String { +fn build_language_bar(languages: &[LanguageDisplayData]) -> String { languages .iter() - .fold(String::new(), |mut output, (_, perc, circle_color)| { + .fold(String::new(), |mut output, language_display_data| { let bar_width = std::cmp::max( - (perc / 100. * LANGUAGES_BAR_LENGTH as f64).round() as usize, + (language_display_data.percentage / 100. * LANGUAGES_BAR_LENGTH as f64).round() + as usize, 1, ); let _ = write!( output, "{: = vec![ - ("Rust".to_string(), 60.0, DynColors::Ansi(AnsiColors::Red)), - ( - "Python".to_string(), - 40.0, - DynColors::Ansi(AnsiColors::Yellow), - ), + let languages: Vec = vec![ + LanguageDisplayData { + language: "Rust".to_string(), + percentage: 60.0, + chip_color: DynColors::Ansi(AnsiColors::Red), + chip_icon: DEFAULT_CHIP_ICON, + }, + LanguageDisplayData { + language: "Python".to_string(), + percentage: 40.0, + chip_color: DynColors::Ansi(AnsiColors::Yellow), + chip_icon: DEFAULT_CHIP_ICON, + }, ]; let result = build_language_bar(&languages); @@ -320,6 +355,7 @@ mod test { true_color: false, number_of_languages_to_display: 2, info_color: DynColors::Ansi(AnsiColors::White), + nerd_fonts: false, }; let color_palette = [ @@ -330,23 +366,38 @@ mod test { let result = prepare_languages(&languages_info, &color_palette); let expected_result = vec![ - ( - Language::Go.to_string(), - 40_f64, - DynColors::Ansi(AnsiColors::Red), - ), - ( - Language::Erlang.to_string(), - 30_f64, - DynColors::Ansi(AnsiColors::Green), - ), - ( - "Other".to_string(), - 30_f64, - DynColors::Ansi(AnsiColors::White), - ), + LanguageDisplayData { + language: Language::Go.to_string(), + percentage: 40_f64, + chip_color: DynColors::Ansi(AnsiColors::Red), + chip_icon: DEFAULT_CHIP_ICON, + }, + LanguageDisplayData { + language: Language::Erlang.to_string(), + percentage: 30_f64, + chip_color: DynColors::Ansi(AnsiColors::Green), + chip_icon: DEFAULT_CHIP_ICON, + }, + LanguageDisplayData { + language: "Other".to_string(), + percentage: 30_f64, + chip_color: DynColors::Ansi(AnsiColors::White), + chip_icon: DEFAULT_CHIP_ICON, + }, ]; assert_eq!(result, expected_result); } + #[rstest] + #[case(Language::Go, true, '\u{e627}')] + #[case(Language::Abap, true, DEFAULT_CHIP_ICON)] // No Nerd Font icon for this language + #[case(Language::Rust, false, DEFAULT_CHIP_ICON)] + fn test_language_get_chip_icon( + #[case] language: Language, + #[case] use_nerd_fonts: bool, + #[case] expected_chip_icon: char, + ) { + let result = language.get_chip_icon(use_nerd_fonts); + assert_eq!(result, expected_chip_icon); + } } diff --git a/src/info/langs/language.tera b/src/info/langs/language.tera index 869fff140..c707dba55 100644 --- a/src/info/langs/language.tera +++ b/src/info/langs/language.tera @@ -11,6 +11,8 @@ pub struct Colors { true_colors: Option>, } +const DEFAULT_CHIP_ICON: char = '\u{25CF}'; + #[derive(Clone, PartialEq, Eq, Debug, clap::ValueEnum)] pub enum LanguageType { Programming, @@ -99,7 +101,7 @@ impl Language { } } - pub fn get_circle_color(&self) -> DynColors { + pub fn get_chip_color(&self) -> DynColors { match self { {% for language, attrs in languages -%} {% set rgb = attrs.colors.chip | hex_to_rgb -%} @@ -107,6 +109,18 @@ impl Language { {% endfor %} } } + + pub fn get_chip_icon(&self, use_nerd_fonts: bool) -> char { + if use_nerd_fonts { + match self { + {% for language, attrs in languages -%} + {% if attrs.icon is defined %}Language::{{ language }} => '{{ attrs.icon }}',{% else %}Language::{{ language }} => DEFAULT_CHIP_ICON,{% endif %} + {% endfor %} + } + } else { + DEFAULT_CHIP_ICON + } + } } fn __loc(language_type: &tokei::LanguageType, language: &tokei::Language) -> usize { @@ -124,9 +138,9 @@ fn __stats_loc(language_type: &tokei::LanguageType, stats: &tokei::CodeStats) -> match language_type { {% for language, attrs in languages -%} {%- set line_types = attrs.line_types | default(value=['code']) -%} - {%- if attrs.line_types -%} + {%- if attrs.line_types -%} tokei::LanguageType::{{ language }} => stats.{{ line_types.0 }}{% for line_type in line_types | slice(start=1) %} + stats.{{ line_type }}{% endfor %}, - {% endif -%} + {% endif -%} {% endfor %} _ => stats.code } diff --git a/src/info/mod.rs b/src/info/mod.rs index a9a48fe9b..1f5def4e0 100644 --- a/src/info/mod.rs +++ b/src/info/mod.rs @@ -191,6 +191,7 @@ pub fn build_info(cli_options: &CliOptions) -> Result { true_color, number_of_languages_to_display, &text_colors, + cli_options, ) .dependencies(manifest.as_ref(), number_separator) .authors( @@ -323,6 +324,7 @@ impl InfoBuilder { true_color: bool, number_of_languages: usize, text_colors: &TextColors, + cli_options: &CliOptions, ) -> Self { if !self.disabled_fields.contains(&InfoType::Languages) { let languages = LanguagesInfo::new( @@ -330,6 +332,7 @@ impl InfoBuilder { true_color, number_of_languages, text_colors.info, + cli_options.visuals.nerd_fonts, ); self.info_fields.push(Box::new(languages)); }