color.ha (2880B)
1 // SPDX-License-Identifier: GPL-3.0-only 2 // (c) Hare authors <https://harelang.org> 3 4 use fmt; 5 use hare::unparse; 6 use os; 7 use regex; 8 9 // Colors/Renditions with defaults; SGR parameters for ANSI escape sequences. 10 const default_colors = [ 11 "_", // ident 12 "1", // comment 13 "_", // constant 14 "_", // function 15 "_", // global 16 "_", // typedef 17 "_", // import_alias 18 "_", // secondary 19 "94", // keyword 20 "96", // type 21 "33", // attribute 22 "1", // operator 23 "_", // punctuation 24 "91", // rune_string 25 "95", // number 26 "_", // label 27 ]; 28 29 let colors: [len(default_colors)]str = [""...]; 30 let normal_color = ""; 31 let primary_color = ""; 32 33 fn init_colors() (void | error) = { 34 const env_colors = os::tryenv("HAREDOC_COLORS", ""); 35 36 const expr = regex::compile(`([a-z_]+)=(_|[0-9;]*)`)!; 37 defer regex::finish(&expr); 38 39 const matches = regex::findall(&expr, env_colors); 40 defer regex::result_freeall(matches); 41 42 for (let m .. matches) { 43 let (k, v) = (m[1].content, m[2].content); 44 45 let idx = 0z; 46 let out: *str = switch (k) { 47 case "ident" => 48 yield &colors[unparse::synkind::IDENT]; 49 case "comment" => 50 yield &colors[unparse::synkind::COMMENT]; 51 case "constant" => 52 yield &colors[unparse::synkind::CONSTANT]; 53 case "function" => 54 yield &colors[unparse::synkind::FUNCTION]; 55 case "global" => 56 yield &colors[unparse::synkind::GLOBAL]; 57 case "typedef" => 58 yield &colors[unparse::synkind::TYPEDEF]; 59 case "import_alias" => 60 yield &colors[unparse::synkind::IMPORT_ALIAS]; 61 case "secondary" => 62 yield &colors[unparse::synkind::SECONDARY]; 63 case "keyword" => 64 yield &colors[unparse::synkind::KEYWORD]; 65 case "type" => 66 yield &colors[unparse::synkind::TYPE]; 67 case "attribute" => 68 yield &colors[unparse::synkind::ATTRIBUTE]; 69 case "operator" => 70 yield &colors[unparse::synkind::OPERATOR]; 71 case "punctuation" => 72 yield &colors[unparse::synkind::PUNCTUATION]; 73 case "rune_string" => 74 yield &colors[unparse::synkind::RUNE_STRING]; 75 case "number" => 76 yield &colors[unparse::synkind::NUMBER]; 77 case "label" => 78 yield &colors[unparse::synkind::LABEL]; 79 case "normal" => 80 yield &normal_color; 81 case "primary" => 82 yield &primary_color; 83 case => 84 static let err: [64]u8 = [0...]; 85 if (len(k) > len(err)) { 86 return "": haredoc_colors_error; 87 }; 88 return fmt::bsprint(err, k): haredoc_colors_error; 89 }; 90 91 *out = if (v == "_" && k == "normal") "0" else v; 92 }; 93 }; 94 95 fn color(kind: unparse::synkind) str = { 96 const color = if (colors[kind] != "") colors[kind] 97 else default_colors[kind]; 98 if (color != "_") { 99 return color; 100 }; 101 102 if (primary_color != "" && primary_color != "_") { 103 switch (kind) { 104 case unparse::synkind::CONSTANT, 105 unparse::synkind::FUNCTION, 106 unparse::synkind::GLOBAL, 107 unparse::synkind::TYPEDEF => 108 return primary_color; 109 case => void; 110 }; 111 }; 112 113 return if (normal_color == "") "0" else normal_color; 114 };