Skip to content

Commit 7f0c08c

Browse files
authored
Merge pull request #252 from atluft/235-truecolor-define-color
235 truecolor define color
2 parents b7d51f3 + c465eeb commit 7f0c08c

File tree

5 files changed

+199
-87
lines changed

5 files changed

+199
-87
lines changed

Diff for: CONTRIBUTING.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ Adding support for a new Language requires adding a new entry in the `define_lan
5757

5858
**Example**:
5959

60-
`{ CSharp, "csharp.ascii", "C#", vec![Color::Blue, Color::Magenta], "c#" }`
60+
` { CSharp, "csharp.ascii", "C#", define_colors!( [Color::Blue, Color::Magenta] ), "c#" }, `
6161

62-
The first item `CSharp` corresponds to the name of the language as defined in tokei. The second item `csharp.ascii` is the name of the file containing the ascii logo, this file has to be placed in the _./resources_ folder (more info below). The third item `C#` is the display name. Then we have the colors `vec![Color::Blue, Color::Magenta]` used to customize the look of the ascii logo when displayed to the screen. The last item `c#` is required only if the Enum name `CSharp` doesn't match the display name `C#`.
62+
The first item `CSharp` corresponds to the name of the language as defined in tokei. The second item `csharp.ascii` is the name of the file containing the ascii logo, this file has to be placed in the _./resources_ folder (more info below). The third item `C#` is the display name. Then we have the colors used to customize the look of the ascii logo when displayed to the screen. The last item `c#` is required only if the Enum name `CSharp` doesn't match the display name `C#`.
6363

6464
#### Ascii logo
6565

@@ -90,6 +90,16 @@ Remarks:
9090
- You can use `{N}` to color the ascii which will utilize the vec! of colors defined in `define_language!`
9191
- Make sure to trim any unnecessary trailing whitespaces
9292
- See example here [Ascii Art From Image File Using Python Image Library](https://github.com/o2sh/onefetch/wiki/ASCII-Art-From-Image-Using-Python-Image-Library)
93+
- You must always provide an array of basic colors
94+
- Optionally, you may provide true colors in a second array of colors separated from the first array by a colon
95+
- One last approach allows you to define colors using the Colors structure itself
96+
- Make sure if you use true colors that the number of true colors matches the number of basic colors
97+
- For example, the following are equivalent:
98+
```
99+
{ CSharp, "csharp.ascii", "C#", define_colors!( [Color::Blue, Color::Magenta] ), "c#" },
100+
{ CSharp, "csharp.ascii", "C#", define_colors!( [Color::Blue, Color::Magenta] : [Color::TrueColor{ r:0, g:255, b:255 }, Color::TrueColor{ r:255, g:0, b:255 } ] ), "c#" },
101+
{ CSharp, "csharp.ascii", "C#", define_colors!( Colors { basic_colors: vec![Color::Blue, Color::Magenta] , true_colors: Some(vec![Color::TrueColor{ r:0, g:255, b:255 }, Color::TrueColor{ r:255, g:0, b:255 } ] ) } ), "c#" },
102+
```
93103

94104
### Project-specific notes
95105

Diff for: resources/swift.ascii

+22-22
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
{0} :
22
{0} ::
3-
{0} :::
4-
{0} : ::::
5-
{0} : : ::::
6-
{0} : :: :::::
7-
{0} :: ::: :::::
8-
{0} ::: ::: ::::::
9-
{0} ::: ::: :::::::
10-
{0} :::: :::: :::::::
11-
{0} ::::::::::: ::::::::
12-
{0} ::::::::::: :::::::::
13-
{0} ::::::::::::::::::::::
14-
{0} :::::::::::::::::::::
15-
{0} :::::::::::::::::::
16-
{0}: :::::::::::::::::
17-
{0} :: ::::::::::::::
18-
{0} :::: ::::::::::::::::
19-
{0} ::::::::::::::::::::::::::::::::::
20-
{0} :::::::::::::::::::::::::::::::::
21-
{0} :::::::::::::::::::::::::::::::
22-
{0} :::::::::::::::::::::: :::::
23-
{0} .::::::::::::::. ::
24-
{0}
3+
{1} :::
4+
{1} : ::::
5+
{2} : : ::::
6+
{2} : :: :::::
7+
{3} :: ::: :::::
8+
{3} ::: ::: ::::::
9+
{4} ::: ::: :::::::
10+
{4} :::: :::: :::::::
11+
{5} ::::::::::: ::::::::
12+
{5} ::::::::::: :::::::::
13+
{5} ::::::::::::::::::::::
14+
{6} :::::::::::::::::::::
15+
{6} :::::::::::::::::::
16+
{6}: :::::::::::::::::
17+
{7} :: ::::::::::::::
18+
{7} :::: ::::::::::::::::
19+
{7} ::::::::::::::::::::::::::::::::::
20+
{8} :::::::::::::::::::::::::::::::::
21+
{8} :::::::::::::::::::::::::::::::
22+
{8} :::::::::::::::::::::: :::::
23+
{9} .::::::::::::::. ::
24+
{9}

Diff for: src/onefetch/cli.rs

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct Cli {
2121
pub number_of_authors: usize,
2222
pub excluded: Vec<String>,
2323
pub print_languages: bool,
24+
pub true_color: bool,
2425
}
2526

2627
impl Cli {
@@ -157,6 +158,7 @@ impl Cli {
157158
let no_merges = matches.is_present("no-merge-commits");
158159
let no_color_blocks = matches.is_present("no-color-blocks");
159160
let print_languages = matches.is_present("languages");
161+
let true_color = is_truecolor_terminal();
160162

161163
let fields_to_hide: Vec<String> = if let Some(values) = matches.values_of("disable-fields")
162164
{
@@ -221,6 +223,7 @@ impl Cli {
221223
number_of_authors,
222224
excluded,
223225
print_languages,
226+
true_color,
224227
})
225228
}
226229

@@ -234,3 +237,9 @@ impl Cli {
234237
Ok(())
235238
}
236239
}
240+
241+
fn is_truecolor_terminal() -> bool {
242+
env::var("COLORTERM")
243+
.map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
244+
.unwrap_or(false)
245+
}

Diff for: src/onefetch/info.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ impl Info {
701701
&self.config.ascii_language
702702
};
703703

704-
let colors = language.get_colors();
704+
let colors = language.get_colors(self.config.true_color);
705705

706706
let colors: Vec<Color> = colors
707707
.iter()

Diff for: src/onefetch/language.rs

+155-62
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,21 @@ use {
33
colored::Color,
44
regex::Regex,
55
std::collections::HashMap,
6+
std::env,
67
strum::{EnumIter, EnumString, IntoStaticStr},
78
};
89

10+
pub struct Colors {
11+
basic_colors: Vec<Color>,
12+
true_colors: Option<Vec<Color>>,
13+
}
14+
15+
macro_rules! define_colors {
16+
( [ $($color:expr),+ ] ) => { Colors { basic_colors: vec![$($color),+], true_colors: None } };
17+
( [ $($bc:expr),+ ] : [ $($tc:expr),+ ] ) => { Colors { basic_colors: vec![$($bc),+], true_colors: Some(vec![$($tc),+]) } };
18+
( $color:expr ) => { $color };
19+
}
20+
921
macro_rules! define_languages {
1022
($( { $name:ident, $ascii:literal, $display:literal, $colors:expr $(, $serialize:literal )? } ),* ,) => {
1123

@@ -45,12 +57,14 @@ macro_rules! define_languages {
4557
}
4658
}
4759

48-
pub fn get_colors(&self) -> Vec<Color> {
49-
match *self {
50-
$(
51-
Language::$name => $colors,
52-
)*
53-
Language::Unknown => vec![Color::White],
60+
pub fn get_colors(&self, true_color: bool) -> Vec<Color> {
61+
let colors = match *self {
62+
$( Language::$name => $colors, )*
63+
Language::Unknown => define_colors!( [Color::White] ),
64+
};
65+
match colors.true_colors {
66+
Some( true_colors ) if true_color => true_colors,
67+
_ => colors.basic_colors,
5468
}
5569
}
5670
}
@@ -59,6 +73,61 @@ macro_rules! define_languages {
5973
vec![ $( tokei::LanguageType::$name ,)* ]
6074
}
6175

76+
#[cfg(test)]
77+
mod true_colors {
78+
79+
use std::fmt;
80+
use super::*;
81+
use paste::paste;
82+
83+
impl fmt::Display for Colors {
84+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85+
let mut output = String::new();
86+
output += "Colors {\n";
87+
output += " basic_colors: vec![\n";
88+
for (color_index, bc) in self.basic_colors.iter().enumerate() {
89+
output += &format!( " Color::{:?}, // {}\n", bc, color_index );
90+
}
91+
output += " ], \n";
92+
if let Some(tcs) = &self.true_colors {
93+
output += " true_colors: vec![\n";
94+
for (color_index,tc) in tcs.iter().enumerate() {
95+
output += &format!( " Color::{:?}, // {}\n", tc, color_index );
96+
}
97+
} else {
98+
output += " true_colors: None\n";
99+
};
100+
output += " ], \n";
101+
output += "}\n";
102+
write!( f, "{}", output )
103+
}
104+
}
105+
106+
$(
107+
paste! {
108+
#[test]
109+
fn [<$name:lower _basic_color_test>] () {
110+
let colors = $colors;
111+
for (color_index, bc) in colors.basic_colors.iter().enumerate() {
112+
let color_str = &format!( "Color::{:?}", bc );
113+
if let Color::TrueColor { .. } = bc {
114+
panic!( "TrueColor found in basic_colors for {} at index {} found {}", stringify!( $name ), color_index, color_str );
115+
}
116+
}
117+
}
118+
119+
#[test]
120+
fn [<$name:lower _color_vector_length_test>] () {
121+
let colors = $colors;
122+
let bc_count = colors.basic_colors.len();
123+
if let Some(tcs) = &colors.true_colors {
124+
assert_eq!( bc_count, tcs.len(), " left (basic) color length do not match right (true) color length.\n{}", colors );
125+
}
126+
}
127+
}
128+
)*
129+
}
130+
62131
#[cfg(test)]
63132
mod ascii_size {
64133
use lazy_static::lazy_static;
@@ -99,62 +168,86 @@ macro_rules! define_languages {
99168
}
100169

101170
define_languages! {
102-
{ Assembly, "assembly.ascii", "Assembly", vec![Color::Cyan] },
103-
{ C, "c.ascii", "C", vec![Color::Cyan, Color::Blue] },
104-
{ Clojure, "clojure.ascii", "Clojure", vec![Color::Cyan, Color::Green] },
105-
{ CMake, "cmake.ascii", "CMake", vec![Color::Blue, Color::Green, Color::Red, Color::Black] },
106-
{ CoffeeScript, "coffeescript.ascii", "CoffeeScript", vec![Color::Red] },
107-
{ Cpp, "cpp.ascii", "C++", vec![Color::Cyan, Color::Blue], "c++" },
108-
{ Crystal, "crystal.ascii", "Crystal", vec![Color::White, Color::Black] },
109-
{ CSharp, "csharp.ascii", "C#", vec![Color::Blue, Color::Magenta], "c#" },
110-
{ Css, "css.ascii", "CSS", vec![Color::Blue, Color::White] },
111-
{ D, "d.ascii", "D", vec![Color::Red] },
112-
{ Dart, "dart.ascii", "Dart", vec![Color::Cyan, Color::Blue] },
113-
{ Dockerfile, "dockerfile.ascii", "Dockerfile", vec![Color::Cyan, Color::White, Color::Cyan] },
114-
{ Elisp, "emacslisp.ascii", "EmacsLisp", vec![Color::Magenta, Color::White], "emacslisp" },
115-
{ Elixir, "elixir.ascii", "Elixir", vec![Color::Magenta] },
116-
{ Elm, "elm.ascii", "Elm", vec![Color::Blue, Color::Green, Color::Yellow, Color::Cyan] },
117-
{ Erlang, "erlang.ascii", "Erlang", vec![Color::Red] },
118-
{ Fish, "fish.ascii", "Fish", vec![Color::Red, Color::Yellow] },
119-
{ Forth, "forth.ascii", "Forth", vec![Color::Red] },
120-
{ FortranModern, "f90.ascii", "Fortran", vec![Color::White, Color::Green, Color::Cyan, Color::Yellow, Color::Red], "fortran" },
121-
{ FSharp, "fsharp.ascii", "F#", vec![Color::Cyan, Color::Cyan], "f#" },
122-
{ Go, "go.ascii", "Go", vec![Color::Cyan, Color::White, Color::Yellow] },
123-
{ Groovy, "groovy.ascii", "Groovy", vec![Color::Cyan, Color::White] },
124-
{ Haskell, "haskell.ascii", "Haskell", vec![Color::Cyan, Color::Magenta, Color::Blue] },
125-
{ Html, "html.ascii", "HTML", vec![Color::Red, Color::White] },
126-
{ Idris, "idris.ascii", "Idris", vec![Color::Red] },
127-
{ Java, "java.ascii", "Java", vec![Color::Cyan, Color::Red] },
128-
{ JavaScript, "javascript.ascii", "JavaScript", vec![Color::Yellow] },
129-
{ Julia, "julia.ascii", "Julia", vec![Color::White, Color::Blue, Color::Green, Color::Red, Color::Magenta] },
130-
{ Jupyter, "jupyter.ascii", "Jupyter-Notebooks", vec![Color::White, Color::Yellow, Color::White], "jupyter-notebooks" },
131-
{ Kotlin, "kotlin.ascii", "Kotlin", vec![Color::Blue, Color::Yellow, Color::Magenta] },
132-
{ Lisp, "lisp.ascii", "Lisp", vec![Color::White] },
133-
{ Lua, "lua.ascii", "Lua", vec![Color::Blue, Color::White] },
134-
{ Markdown, "markdown.ascii", "Markdown", vec![Color::White, Color::Red] },
135-
{ Nim, "nim.ascii", "Nim", vec![Color::Yellow, Color::White] },
136-
{ Nix, "nix.ascii", "Nix", vec![Color::Cyan, Color::Blue] },
137-
{ ObjectiveC, "objectivec.ascii", "Objective-C", vec![Color::Cyan, Color::Blue], "objective-c" },
138-
{ OCaml, "ocaml.ascii", "OCaml", vec![Color::Yellow] },
139-
{ Org, "org.ascii", "Org", vec![Color::Green, Color::Red, Color::White] },
140-
{ Perl, "perl.ascii", "Perl", vec![Color::Cyan] },
141-
{ Php, "php.ascii", "Php", vec![Color::Magenta, Color::Blue, Color::Cyan, Color::White] },
142-
{ Prolog, "prolog.ascii", "Prolog", vec![Color::White] },
143-
{ PureScript, "purescript.ascii", "PureScript", vec![Color::White] },
144-
{ Python, "python.ascii", "Python", vec![Color::Blue, Color::Yellow] },
145-
{ R, "r.ascii", "R", vec![Color::White, Color::Blue] },
146-
{ Racket, "racket.ascii", "Racket", vec![Color::Red, Color::White, Color::Blue] },
147-
{ Ruby, "ruby.ascii", "Ruby", vec![Color::Magenta] },
148-
{ Rust, "rust.ascii", "Rust", vec![Color::Red, Color::White] },
149-
{ Scala, "scala.ascii", "Scala", vec![Color::Blue] },
150-
{ Sh, "shell.ascii", "Shell", vec![Color::Green], "shell" },
151-
{ Swift, "swift.ascii", "Swift", vec![Color::Red] },
152-
{ Tcl, "tcl.ascii", "Tcl", vec![Color::Blue, Color::White, Color::Cyan] },
153-
{ Tex, "tex.ascii", "Tex", vec![Color::White, Color::Black] },
154-
{ TypeScript, "typescript.ascii", "TypeScript", vec![Color::Cyan] },
155-
{ Vue, "vue.ascii", "Vue", vec![Color::Green, Color::Blue] },
156-
{ Xml, "xml.ascii", "XML", vec![Color::Yellow, Color::White, Color::Green] },
157-
{ Zig, "zig.ascii", "Zig", vec![Color::Yellow] },
171+
{ Assembly, "assembly.ascii", "Assembly", define_colors!( [Color::Cyan] ) },
172+
{ C, "c.ascii", "C", define_colors!( [Color::Cyan, Color::Blue] ) },
173+
{ Clojure, "clojure.ascii", "Clojure", define_colors!( [Color::Cyan, Color::Green] ) },
174+
{ CMake, "cmake.ascii", "CMake", define_colors!( [Color::Blue, Color::Green, Color::Red, Color::Black] ) },
175+
{ CoffeeScript, "coffeescript.ascii", "CoffeeScript", define_colors!( [Color::Red] ) },
176+
{ Cpp, "cpp.ascii", "C++", define_colors!( [Color::Cyan, Color::Blue] ), "c++" },
177+
{ Crystal, "crystal.ascii", "Crystal", define_colors!( [Color::White, Color::Black] ) },
178+
{ CSharp, "csharp.ascii", "C#", define_colors!( [Color::Blue, Color::Magenta] ), "c#" },
179+
{ Css, "css.ascii", "CSS", define_colors!( [Color::Blue, Color::White] ) },
180+
{ D, "d.ascii", "D", define_colors!( [Color::Red] ) },
181+
{ Dart, "dart.ascii", "Dart", define_colors!( [Color::Cyan, Color::Blue] ) },
182+
{ Dockerfile, "dockerfile.ascii", "Dockerfile", define_colors!( [Color::Cyan, Color::White, Color::Cyan] ) },
183+
{ Elisp, "emacslisp.ascii", "EmacsLisp", define_colors!( [Color::Magenta, Color::White] ), "emacslisp" },
184+
{ Elixir, "elixir.ascii", "Elixir", define_colors!( [Color::Magenta] ) },
185+
{ Elm, "elm.ascii", "Elm", define_colors!( [Color::Blue, Color::Green, Color::Yellow, Color::Cyan] ) },
186+
{ Erlang, "erlang.ascii", "Erlang", define_colors!( [Color::Red] ) },
187+
{ Fish, "fish.ascii", "Fish", define_colors!( [Color::Red, Color::Yellow] ) },
188+
{ Forth, "forth.ascii", "Forth", define_colors!( [Color::Red] ) },
189+
{ FortranModern, "f90.ascii", "Fortran", define_colors!( [Color::White, Color::Green, Color::Cyan, Color::Yellow, Color::Red] ), "fortran" },
190+
{ FSharp, "fsharp.ascii", "F#", define_colors!( [Color::Cyan, Color::Cyan] ), "f#" },
191+
{ Go, "go.ascii", "Go", define_colors!( [Color::White] ) },
192+
{ Groovy, "groovy.ascii", "Groovy", define_colors!( [Color::Cyan, Color::White] ) },
193+
{ Haskell, "haskell.ascii", "Haskell", define_colors!( [Color::Cyan, Color::Magenta, Color::Blue] ) },
194+
{ Html, "html.ascii", "HTML", define_colors!( [Color::Red, Color::White] ) },
195+
{ Idris, "idris.ascii", "Idris", define_colors!( [Color::Red] ) },
196+
{ Java, "java.ascii", "Java", define_colors!( [Color::Cyan, Color::Red] ) },
197+
{ JavaScript, "javascript.ascii", "JavaScript", define_colors!( [Color::Yellow] ) },
198+
{ Julia, "julia.ascii", "Julia", define_colors!( [Color::White, Color::Blue, Color::Green, Color::Red, Color::Magenta] ) },
199+
{ Jupyter, "jupyter.ascii", "Jupyter-Notebooks", define_colors!( [Color::White, Color::Yellow, Color::White] ), "jupyter-notebooks" },
200+
{ Kotlin, "kotlin.ascii", "Kotlin", define_colors!( [Color::Blue, Color::Yellow, Color::Magenta] ) },
201+
{ Lisp, "lisp.ascii", "Lisp", define_colors!( [Color::White] ) },
202+
{ Lua, "lua.ascii", "Lua", define_colors!( [Color::Blue, Color::White] ) },
203+
{ Markdown, "markdown.ascii", "Markdown", define_colors!( [Color::White, Color::Red] ) },
204+
{ Nim, "nim.ascii", "Nim", define_colors!( [Color::Yellow, Color::White] ) },
205+
{ Nix, "nix.ascii", "Nix", define_colors!( [Color::Cyan, Color::Blue] ) },
206+
{ ObjectiveC, "objectivec.ascii", "Objective-C", define_colors!( [Color::Cyan, Color::Blue] ), "objective-c" },
207+
{ OCaml, "ocaml.ascii", "OCaml", define_colors!( [Color::Yellow] ) },
208+
{ Org, "org.ascii", "Org", define_colors!( [Color::Green, Color::Red, Color::White] ) },
209+
{ Perl, "perl.ascii", "Perl", define_colors!( [Color::Cyan] ) },
210+
{ Php, "php.ascii", "Php", define_colors!( [Color::Magenta, Color::Blue, Color::Cyan, Color::White] ) },
211+
{ Prolog, "prolog.ascii", "Prolog", define_colors!( [Color::White] ) },
212+
{ PureScript, "purescript.ascii", "PureScript", define_colors!( [Color::White] ) },
213+
{ Python, "python.ascii", "Python", define_colors!( [Color::Blue, Color::Yellow] ) },
214+
{ R, "r.ascii", "R", define_colors!( [Color::White, Color::Blue] ) },
215+
{ Racket, "racket.ascii", "Racket", define_colors!( [Color::Red, Color::White, Color::Blue] ) },
216+
{ Ruby, "ruby.ascii", "Ruby", define_colors!( [Color::Magenta] ) },
217+
{ Rust, "rust.ascii", "Rust", define_colors!( [Color::Red, Color::White] ) },
218+
{ Scala, "scala.ascii", "Scala", define_colors!( [Color::Blue] ) },
219+
{ Sh, "shell.ascii", "Shell", define_colors!( [Color::Green] ), "shell" },
220+
{
221+
Swift, "swift.ascii", "Swift", define_colors!( [
222+
Color::Red,
223+
Color::Red,
224+
Color::Red,
225+
Color::Red,
226+
Color::Red,
227+
Color::Red,
228+
Color::Red,
229+
Color::Red,
230+
Color::Red,
231+
Color::Red
232+
] : [
233+
Color::TrueColor{ r:248, g:129, b:052 },
234+
Color::TrueColor{ r:249, g:119, b:050 },
235+
Color::TrueColor{ r:249, g:109, b:048 },
236+
Color::TrueColor{ r:250, g:099, b:046 },
237+
Color::TrueColor{ r:250, g:089, b:044 },
238+
Color::TrueColor{ r:251, g:080, b:042 },
239+
Color::TrueColor{ r:251, g:070, b:040 },
240+
Color::TrueColor{ r:252, g:060, b:038 },
241+
Color::TrueColor{ r:252, g:050, b:036 },
242+
Color::TrueColor{ r:253, g:040, b:034 }
243+
] )
244+
},
245+
{ Tcl, "tcl.ascii", "Tcl", define_colors!( [Color::Blue, Color::White, Color::Cyan] ) },
246+
{ Tex, "tex.ascii", "Tex", define_colors!( [Color::White, Color::Black] ) },
247+
{ TypeScript, "typescript.ascii", "TypeScript", define_colors!( [Color::Cyan] ) },
248+
{ Vue, "vue.ascii", "Vue", define_colors!( [Color::Green, Color::Blue] ) },
249+
{ Xml, "xml.ascii", "XML", define_colors!( [Color::Yellow, Color::White, Color::Green] ) },
250+
{ Zig, "zig.ascii", "Zig", define_colors!( [Color::Yellow] ) },
158251
}
159252

160253
impl Language {

0 commit comments

Comments
 (0)