Next Generation WASM Microkernel Operating System
wasm os rust microkernel
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at pr/477 239 lines 5.0 kB view raw
1// Copyright 2025 Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8use core::fmt; 9 10pub trait SetColor { 11 fn set_fg_color(&mut self, color: Color); 12 fn fg_color(&self) -> Color; 13 14 /// Sets bold text. 15 /// 16 /// This may brighten a text color if bold text is not supported. 17 fn set_bold(&mut self, bold: bool); 18 19 fn with_bold(&mut self) -> WithBold<'_, Self> 20 where 21 Self: fmt::Write + Sized, 22 { 23 self.set_bold(true); 24 WithBold { writer: self } 25 } 26 27 #[must_use] 28 fn with_fg_color(&mut self, color: Color) -> WithFgColor<'_, Self> 29 where 30 Self: fmt::Write + Sized, 31 { 32 let prev_color = self.fg_color(); 33 self.set_fg_color(color); 34 WithFgColor { 35 writer: self, 36 prev_color, 37 } 38 } 39} 40 41#[derive(Copy, Clone, Debug, Eq, PartialEq)] 42#[repr(usize)] 43pub enum Color { 44 Black = 0, 45 Red, 46 Green, 47 Yellow, 48 Blue, 49 Magenta, 50 Cyan, 51 White, 52 Default, 53 BrightBlack, 54 BrightRed, 55 BrightGreen, 56 BrightYellow, 57 BrightBlue, 58 BrightMagenta, 59 BrightCyan, 60 BrightWhite, 61} 62 63#[derive(Debug, Eq, PartialEq)] 64pub struct WithFgColor<'writer, W> 65where 66 W: fmt::Write + SetColor, 67{ 68 writer: &'writer mut W, 69 prev_color: Color, 70} 71 72#[derive(Debug, Eq, PartialEq)] 73pub struct WithBold<'writer, W> 74where 75 W: fmt::Write + SetColor, 76{ 77 writer: &'writer mut W, 78} 79 80#[derive(Copy, Clone, Debug, Eq, PartialEq)] 81pub struct AnsiEscapes<W> { 82 writer: W, 83 current_fg: Color, 84} 85 86impl<W: SetColor> SetColor for &'_ mut W { 87 #[inline] 88 fn set_fg_color(&mut self, color: Color) { 89 W::set_fg_color(self, color); 90 } 91 92 #[inline] 93 fn fg_color(&self) -> Color { 94 W::fg_color(self) 95 } 96 97 #[inline] 98 fn set_bold(&mut self, bold: bool) { 99 W::set_bold(self, bold); 100 } 101} 102 103// === impl WithFgColor === 104 105impl<W> fmt::Write for WithFgColor<'_, W> 106where 107 W: fmt::Write + SetColor, 108{ 109 #[inline] 110 fn write_str(&mut self, s: &str) -> fmt::Result { 111 self.writer.write_str(s) 112 } 113 114 #[inline] 115 fn write_char(&mut self, c: char) -> fmt::Result { 116 self.writer.write_char(c) 117 } 118 119 #[inline] 120 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { 121 self.writer.write_fmt(args) 122 } 123} 124 125impl<W> Drop for WithFgColor<'_, W> 126where 127 W: fmt::Write + SetColor, 128{ 129 fn drop(&mut self) { 130 self.writer.set_fg_color(self.prev_color); 131 } 132} 133 134// === impl WithBold === 135 136impl<W> fmt::Write for WithBold<'_, W> 137where 138 W: fmt::Write + SetColor, 139{ 140 #[inline] 141 fn write_str(&mut self, s: &str) -> fmt::Result { 142 self.writer.write_str(s) 143 } 144 145 #[inline] 146 fn write_char(&mut self, c: char) -> fmt::Result { 147 self.writer.write_char(c) 148 } 149 150 #[inline] 151 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { 152 self.writer.write_fmt(args) 153 } 154} 155 156impl<W> Drop for WithBold<'_, W> 157where 158 W: fmt::Write + SetColor, 159{ 160 fn drop(&mut self) { 161 self.writer.set_bold(false); 162 } 163} 164 165// === impl AnsiEscapes === 166 167impl<W> AnsiEscapes<W> { 168 pub const fn new(writer: W) -> Self { 169 Self { 170 writer, 171 current_fg: Color::Default, 172 } 173 } 174} 175 176impl<W> fmt::Write for AnsiEscapes<W> 177where 178 W: fmt::Write, 179{ 180 #[inline] 181 fn write_str(&mut self, s: &str) -> fmt::Result { 182 self.writer.write_str(s) 183 } 184 185 #[inline] 186 fn write_char(&mut self, c: char) -> fmt::Result { 187 self.writer.write_char(c) 188 } 189 190 #[inline] 191 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result { 192 self.writer.write_fmt(args) 193 } 194} 195 196impl<W> AnsiEscapes<W> { 197 const ANSI_FG_COLOR_TABLE: [&'static str; 17] = [ 198 "30", // black 199 "31", // red 200 "32", // green 201 "33", // yellow 202 "34", // blue 203 "35", // magenta 204 "36", // cyan 205 "37", // white 206 "39", // default 207 "90", // bright black 208 "91", // bright red 209 "92", // bright green 210 "93", // bright yellow 211 "94", // bright blue 212 "95", // bright magenta 213 "96", // bright cyan 214 "97", // bright white 215 ]; 216 217 fn fg_code(&self) -> &'static str { 218 Self::ANSI_FG_COLOR_TABLE[self.current_fg as usize] 219 } 220} 221 222impl<W: fmt::Write> SetColor for AnsiEscapes<W> { 223 fn set_fg_color(&mut self, color: Color) { 224 self.current_fg = color; 225 let _ = write!(self.writer, "\x1b[{}m", self.fg_code()); 226 } 227 228 fn fg_color(&self) -> Color { 229 self.current_fg 230 } 231 232 fn set_bold(&mut self, bold: bool) { 233 let _ = if bold { 234 self.writer.write_str("\x1b[1m") 235 } else { 236 self.writer.write_str("\x1b[22m") 237 }; 238 } 239}