增加内核日志功能 #3
|
@ -46,7 +46,6 @@ metaverse.elf: kernel libk rust metaverse.lds
|
||||||
@echo -e "\e[1;33mld\e[0m \e[1;32m$@\e[0m \e[34m<--\e[0m \e[32m${SUBOBJS}\e[0m"
|
@echo -e "\e[1;33mld\e[0m \e[1;32m$@\e[0m \e[34m<--\e[0m \e[32m${SUBOBJS}\e[0m"
|
||||||
@ld -T metaverse.lds -Map=metaverse.map -unresolved-symbols=ignore-all -o $@ ${SUBOBJS} ${RUST_LIBS} \
|
@ld -T metaverse.lds -Map=metaverse.map -unresolved-symbols=ignore-all -o $@ ${SUBOBJS} ${RUST_LIBS} \
|
||||||
2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
|
2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow"
|
||||||
@strip $@
|
|
||||||
|
|
||||||
.PHONY: kernel libk all clear postproc rust
|
.PHONY: kernel libk all clear postproc rust
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use core::{cmp::Ordering, ops::Sub, time::Duration};
|
use core::{cmp::Ordering, ops::Sub, time::Duration};
|
||||||
|
|
||||||
use alloc::{format, string::ToString};
|
use alloc::string::ToString;
|
||||||
|
|
||||||
|
use crate::format;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn system_time_get() -> usize;
|
fn system_time_get() -> usize;
|
||||||
|
@ -96,7 +98,7 @@ impl ToString for SystemTime {
|
||||||
let milisec = second % second_dur;
|
let milisec = second % second_dur;
|
||||||
second /= second_dur;
|
second /= second_dur;
|
||||||
format!(
|
format!(
|
||||||
"[{:02}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}]",
|
"[ {}-{}-{} {}:{}:{}.{} ]",
|
||||||
year, month, day, hour, minute, second, milisec
|
year, month, day, hour, minute, second, milisec
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use alloc::{format, vec::Vec};
|
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
clock::time::SystemTime,
|
clock::time::SystemTime,
|
||||||
|
@ -40,125 +40,157 @@ impl KernelLogger {
|
||||||
|
|
||||||
pub fn fatal(&mut self, msg: Message) {
|
pub fn fatal(&mut self, msg: Message) {
|
||||||
let msg = MessageBuilder::new()
|
let msg = MessageBuilder::new()
|
||||||
.message("Fatal: ".to_string())
|
.message("Fatal: ")
|
||||||
.foreground_color(Color(0xee, 0xa, 0xa))
|
.foreground_color(Color(0xee, 0xa, 0xa))
|
||||||
.append(MessageBuilder::from_message(&msg))
|
.append(MessageBuilder::from_message(msg))
|
||||||
.build();
|
.build();
|
||||||
self.fatal_queue.push((SystemTime::now(), msg));
|
self.fatal_queue.push((SystemTime::now(), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(&mut self, msg: Message) {
|
pub fn error(&mut self, msg: Message) {
|
||||||
let msg = MessageBuilder::new()
|
let msg = MessageBuilder::new()
|
||||||
.message("Error: ".to_string())
|
.message("Error: ")
|
||||||
.foreground_color(Color(0xaa, 0x22, 0x22))
|
.foreground_color(Color(0xaa, 0x22, 0x22))
|
||||||
.append(MessageBuilder::from_message(&msg))
|
.append(MessageBuilder::from_message(msg))
|
||||||
.build();
|
.build();
|
||||||
self.error_queue.push((SystemTime::now(), msg));
|
self.error_queue.push((SystemTime::now(), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn warning(&mut self, msg: Message) {
|
pub fn warning(&mut self, msg: Message) {
|
||||||
let msg = MessageBuilder::new()
|
let msg = MessageBuilder::new()
|
||||||
.message("Warning: ".to_string())
|
.message("Warning: ")
|
||||||
.foreground_color(Color(0xaa, 0xa, 0xaa))
|
.foreground_color(Color(0xaa, 0xa, 0xaa))
|
||||||
.append(MessageBuilder::from_message(&msg))
|
.append(MessageBuilder::from_message(msg))
|
||||||
.build();
|
.build();
|
||||||
self.warning_queue.push((SystemTime::now(), msg));
|
self.warning_queue.push((SystemTime::now(), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn info(&mut self, msg: Message) {
|
pub fn info(&mut self, msg: Message) {
|
||||||
let msg = MessageBuilder::new()
|
let msg = MessageBuilder::new()
|
||||||
.message("Info: ".to_string())
|
.message("Info: ")
|
||||||
.foreground_color(Color(0xa, 0xee, 0xa))
|
.foreground_color(Color(0xa, 0xee, 0xa))
|
||||||
.append(MessageBuilder::from_message(&msg))
|
.append(MessageBuilder::from_message(msg))
|
||||||
.build();
|
.build();
|
||||||
self.info_queue.push((SystemTime::now(), msg));
|
self.info_queue.push((SystemTime::now(), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug(&mut self, msg: Message) {
|
pub fn debug(&mut self, msg: Message) {
|
||||||
let msg = MessageBuilder::new()
|
let msg = MessageBuilder::new()
|
||||||
.message("Debug: ".to_string())
|
.message("Debug: ")
|
||||||
.foreground_color(Color(0xee, 0xee, 0xee))
|
.foreground_color(Color(0xee, 0xee, 0xee))
|
||||||
.append(MessageBuilder::from_message(&msg))
|
.append(MessageBuilder::from_message(msg))
|
||||||
.build();
|
.build();
|
||||||
self.debug_queue.push((SystemTime::now(), msg));
|
self.debug_queue.push((SystemTime::now(), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trace(&mut self, msg: Message) {
|
pub fn trace(&mut self, msg: Message) {
|
||||||
let msg = MessageBuilder::new()
|
let msg = MessageBuilder::new()
|
||||||
.message("Trace: ".to_string())
|
.message("Trace: ")
|
||||||
.foreground_color(Color(0xee, 0xee, 0xee))
|
.foreground_color(Color(0xee, 0xee, 0xee))
|
||||||
.append(MessageBuilder::from_message(&msg))
|
.append(MessageBuilder::from_message(msg))
|
||||||
.build();
|
.build();
|
||||||
self.trace_queue.push((SystemTime::now(), msg));
|
self.trace_queue.push((SystemTime::now(), msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self, level: LoggerLevel) -> LogIterator {
|
pub fn iter(&self, level: LoggerLevel) -> LogIterator {
|
||||||
let mut logs = vec![];
|
let mut logs = vec![];
|
||||||
if level == LoggerLevel::Fatal {
|
match level {
|
||||||
logs.push(&self.fatal_queue);
|
LoggerLevel::Fatal => {
|
||||||
}
|
logs.push(&self.fatal_queue);
|
||||||
if level == LoggerLevel::Fatal || level == LoggerLevel::Error {
|
}
|
||||||
logs.push(&self.error_queue);
|
LoggerLevel::Error => {
|
||||||
}
|
logs.push(&self.fatal_queue);
|
||||||
if level == LoggerLevel::Fatal
|
logs.push(&self.error_queue);
|
||||||
|| level == LoggerLevel::Error
|
}
|
||||||
|| level == LoggerLevel::Warning
|
LoggerLevel::Warning => {
|
||||||
{
|
logs.push(&self.fatal_queue);
|
||||||
logs.push(&self.warning_queue);
|
logs.push(&self.error_queue);
|
||||||
}
|
logs.push(&self.warning_queue);
|
||||||
if level == LoggerLevel::Fatal
|
}
|
||||||
|| level == LoggerLevel::Error
|
LoggerLevel::Info => {
|
||||||
|| level == LoggerLevel::Warning
|
logs.push(&self.fatal_queue);
|
||||||
|| level == LoggerLevel::Info
|
logs.push(&self.error_queue);
|
||||||
{
|
logs.push(&self.warning_queue);
|
||||||
logs.push(&self.info_queue);
|
logs.push(&self.info_queue);
|
||||||
}
|
}
|
||||||
if level == LoggerLevel::Fatal
|
LoggerLevel::Debug => {
|
||||||
|| level == LoggerLevel::Error
|
logs.push(&self.fatal_queue);
|
||||||
|| level == LoggerLevel::Warning
|
logs.push(&self.error_queue);
|
||||||
|| level == LoggerLevel::Info
|
logs.push(&self.warning_queue);
|
||||||
|| level == LoggerLevel::Debug
|
logs.push(&self.info_queue);
|
||||||
{
|
logs.push(&self.debug_queue);
|
||||||
logs.push(&self.debug_queue);
|
}
|
||||||
}
|
LoggerLevel::Trace => {
|
||||||
if level == LoggerLevel::Fatal
|
logs.push(&self.fatal_queue);
|
||||||
|| level == LoggerLevel::Error
|
logs.push(&self.error_queue);
|
||||||
|| level == LoggerLevel::Warning
|
logs.push(&self.warning_queue);
|
||||||
|| level == LoggerLevel::Info
|
logs.push(&self.info_queue);
|
||||||
|| level == LoggerLevel::Debug
|
logs.push(&self.debug_queue);
|
||||||
|| level == LoggerLevel::Trace
|
logs.push(&self.trace_queue);
|
||||||
{
|
}
|
||||||
logs.push(&self.trace_queue);
|
|
||||||
}
|
}
|
||||||
let mut res = vec![];
|
let mut res = vec![];
|
||||||
while let Some(msg) = {
|
let mut indeces = Vec::new();
|
||||||
logs.iter_mut()
|
for _ in 0..logs.len() {
|
||||||
.filter_map(|&mut l| l.first().cloned())
|
indeces.push(0usize);
|
||||||
.min_by_key(|&(syst, _)| syst)
|
}
|
||||||
} {
|
let all_end = |indeces: &Vec<usize>, logs: &Vec<&Vec<(SystemTime, Message)>>| {
|
||||||
res.push(msg);
|
for i in 0..indeces.len() {
|
||||||
|
if indeces[i] < logs.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
while !all_end(&indeces, &logs) {
|
||||||
|
let mut min_ind = None;
|
||||||
|
let mut min = None;
|
||||||
|
for i in 0..indeces.len() {
|
||||||
|
if indeces[i] >= logs[i].len() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let Some(minx) = min.as_mut() {
|
||||||
|
if logs[i][indeces[i]].0 < *minx {
|
||||||
|
*minx = logs[i][indeces[i]].0;
|
||||||
|
min_ind = Some(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
min = Some(logs[i][indeces[i]].0);
|
||||||
|
min_ind = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mini) = min_ind {
|
||||||
|
res.push(&logs[mini][indeces[mini]]);
|
||||||
|
indeces[mini] += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LogIterator { logs: res }
|
LogIterator { logs: res }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LogIterator {
|
pub struct LogIterator<'a> {
|
||||||
logs: Vec<(SystemTime, Message)>,
|
logs: Vec<&'a (SystemTime, Message)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for LogIterator {
|
impl<'a> Iterator for LogIterator<'a> {
|
||||||
type Item = Message;
|
type Item = Message;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if let Some((time, msg)) = self.logs.first() {
|
let res = if let Some((time, msg)) = self.logs.first() {
|
||||||
Some(
|
Some(
|
||||||
MessageBuilder::new()
|
MessageBuilder::new()
|
||||||
.message(format!("{}", time.to_string()))
|
.message(&time.to_string())
|
||||||
.append(MessageBuilder::from_message(msg))
|
.append(MessageBuilder::from_message(msg.clone()))
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
};
|
||||||
|
if let Some(_) = res {
|
||||||
|
self.logs.remove(0);
|
||||||
}
|
}
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
|
use crate::message;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
klog::{KernelLogger, LoggerLevel},
|
klog::{KernelLogger, LoggerLevel},
|
||||||
tty::tty::{Color, ColorPair, Message, Tty},
|
tty::tty::{BuilderFunctions::*, Color, Tty},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn kmain_rust() {
|
extern "C" fn kmain_rust() -> ! {
|
||||||
let mut logger = KernelLogger::new();
|
|
||||||
logger.info(Message::from(format!(
|
|
||||||
"Hello, {:?}Metaverse{:?}!",
|
|
||||||
ColorPair::color(Color(0xa, 0xee, 0xa), Color(0, 0, 0)),
|
|
||||||
ColorPair::Reset
|
|
||||||
)));
|
|
||||||
let tty = Tty::from_id(0).unwrap();
|
let tty = Tty::from_id(0).unwrap();
|
||||||
|
tty.enable();
|
||||||
|
let mut logger = KernelLogger::new();
|
||||||
|
logger.info(message!(
|
||||||
|
Msg("Hello, "),
|
||||||
|
Msg("Metaverse"),
|
||||||
|
FgColor(Color(0xa, 0xee, 0xa)),
|
||||||
|
Msg("!\n")
|
||||||
|
));
|
||||||
for msg in logger.iter(LoggerLevel::Info) {
|
for msg in logger.iter(LoggerLevel::Info) {
|
||||||
tty.print(msg);
|
tty.print(msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,7 +405,7 @@ u64 font[256][64] = {
|
||||||
0b00000000,
|
0b00000000,
|
||||||
0b00011000, ///
|
0b00011000, ///
|
||||||
0b00101000,
|
0b00101000,
|
||||||
0b01001000,
|
0b00001000,
|
||||||
0b00001000,
|
0b00001000,
|
||||||
0b00001000,
|
0b00001000,
|
||||||
0b00001000,
|
0b00001000,
|
||||||
|
|
|
@ -1 +1,46 @@
|
||||||
pub mod tty;
|
pub mod tty;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! message_msg {
|
||||||
|
() => {};
|
||||||
|
( $builder : expr, $e : expr) => {
|
||||||
|
$builder.message_mut($e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! message_fgc {
|
||||||
|
() => {};
|
||||||
|
( $builder : expr, $e : expr) => {
|
||||||
|
$builder.foreground_color_mut($e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! message_bgc {
|
||||||
|
() => {};
|
||||||
|
( $builder : expr, $e : expr ) => {
|
||||||
|
$builder.background_color_mut($e);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! message {
|
||||||
|
( $( $e : expr ),* ) => {{
|
||||||
|
use crate::{
|
||||||
|
kernel::tty::tty::{MessageBuilder, BuilderFunctions},
|
||||||
|
message_msg, message_fgc, message_bgc
|
||||||
|
};
|
||||||
|
let mut tmp_builder = MessageBuilder::new();
|
||||||
|
$(
|
||||||
|
if let BuilderFunctions::Msg(e) = $e {
|
||||||
|
message_msg!(tmp_builder, e);
|
||||||
|
} else if let BuilderFunctions::FgColor(c) = $e {
|
||||||
|
message_fgc!(tmp_builder, c);
|
||||||
|
} else if let BuilderFunctions::BgColor(c) = $e {
|
||||||
|
message_bgc!(tmp_builder, c);
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
tmp_builder.build()
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use core::ptr::null_mut;
|
use core::ptr::null_mut;
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{
|
||||||
format,
|
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
|
@ -145,38 +144,6 @@ impl Tty {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Color(pub u8, pub u8, pub u8);
|
pub struct Color(pub u8, pub u8, pub u8);
|
||||||
|
|
||||||
impl ToString for Color {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
format!("{:02x}{:02x}{:02x}", self.0, self.1, self.2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum ColorPair {
|
|
||||||
Reset,
|
|
||||||
Color { fore: Color, back: Color },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ColorPair {
|
|
||||||
pub fn reset() -> Self {
|
|
||||||
ColorPair::Reset
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn color(fore: Color, back: Color) -> Self {
|
|
||||||
ColorPair::Color { fore, back }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToString for ColorPair {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
match self {
|
|
||||||
ColorPair::Reset => format!("\x1b{{}}"),
|
|
||||||
ColorPair::Color { fore, back } => {
|
|
||||||
format!("\x1b{{{}{}}}", fore.to_string(), back.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Color> for u32 {
|
impl From<Color> for u32 {
|
||||||
fn from(value: Color) -> Self {
|
fn from(value: Color) -> Self {
|
||||||
let res = (value.0 as u32) << 16 | (value.1 as u32) << 8 | (value.2 as u32);
|
let res = (value.0 as u32) << 16 | (value.1 as u32) << 8 | (value.2 as u32);
|
||||||
|
@ -196,71 +163,46 @@ pub struct MessageSection {
|
||||||
bgcolor: Color,
|
bgcolor: Color,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ## Message
|
||||||
|
///
|
||||||
|
/// 用`MessageBuilder`构造一个`Message`对象
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Message(Vec<MessageSection>);
|
pub struct Message(Vec<MessageSection>);
|
||||||
|
|
||||||
impl From<String> for Message {
|
/// ## MessageBuilder
|
||||||
fn from(value: String) -> Self {
|
///
|
||||||
let mut res = MessageBuilder::new();
|
/// 使用链式调用模式构造一个消息.
|
||||||
let mut msg = String::new();
|
///
|
||||||
let mut color = ColorPair::Reset;
|
/// 一个`Message`包含多个`MessageSection`,每个`MessageSection`以`message()`调用开始,
|
||||||
let mut coloring = false;
|
/// `message()`调用后可接0个或多个属性设置。
|
||||||
|
///
|
||||||
let mut colorp_str = String::new();
|
/// ```rust
|
||||||
|
/// MessageBuilder::new()
|
||||||
for c in value.as_bytes() {
|
/// .message("Hello, ")
|
||||||
if *c as char == '\x1b' {
|
/// .message("Metaverse").foreground_color(Color(0xa, 0xee, 0xa))
|
||||||
coloring = true;
|
/// .message("!\n")
|
||||||
res.message_mut(msg.clone());
|
/// .build();
|
||||||
msg.clear();
|
/// ```
|
||||||
if let ColorPair::Color { fore, back } = color {
|
///
|
||||||
res.foreground_color_mut(fore);
|
/// 对于特殊情况可以使用非链式调用:
|
||||||
res.background_color_mut(back);
|
/// ```rust
|
||||||
}
|
/// let mut msg = MessageBuilder::new();
|
||||||
continue;
|
/// msg.message_mut("Hello, ");
|
||||||
}
|
/// msg.message_mut("Metaverse");
|
||||||
if coloring {
|
/// msg.foreground_color(Color(0xa, 0xee, 0xa));
|
||||||
if *c as char == '{' {
|
/// msg.message_mut("!\n");
|
||||||
colorp_str.clear();
|
/// let msg = msg.build();
|
||||||
} else if *c as char == '}' {
|
/// ```
|
||||||
if colorp_str.is_empty() {
|
|
||||||
color = ColorPair::Reset;
|
|
||||||
} else {
|
|
||||||
let bts = colorp_str.as_bytes();
|
|
||||||
let r = bts[0] << 4 + bts[1];
|
|
||||||
let g = bts[2] << 4 + bts[3];
|
|
||||||
let b = bts[4] << 4 + bts[5];
|
|
||||||
let fore = Color(r, g, b);
|
|
||||||
let r = bts[6] << 4 + bts[7];
|
|
||||||
let g = bts[8] << 4 + bts[9];
|
|
||||||
let b = bts[10] << 4 + bts[11];
|
|
||||||
let back = Color(r, g, b);
|
|
||||||
color = ColorPair::Color { fore, back };
|
|
||||||
}
|
|
||||||
coloring = false;
|
|
||||||
} else {
|
|
||||||
colorp_str.push(*c as char);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
msg.push(*c as char);
|
|
||||||
}
|
|
||||||
if !msg.is_empty() {
|
|
||||||
res.message_mut(msg.clone());
|
|
||||||
msg.clear();
|
|
||||||
if let ColorPair::Color { fore, back } = color {
|
|
||||||
res.foreground_color_mut(fore);
|
|
||||||
res.background_color_mut(back);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MessageBuilder {
|
pub struct MessageBuilder {
|
||||||
msg: Message,
|
msg: Message,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum BuilderFunctions<'a> {
|
||||||
|
Msg(&'a str),
|
||||||
|
FgColor(Color),
|
||||||
|
BgColor(Color),
|
||||||
|
}
|
||||||
|
|
||||||
impl MessageBuilder {
|
impl MessageBuilder {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -268,22 +210,22 @@ impl MessageBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_message(msg: &Message) -> Self {
|
pub fn from_message(msg: Message) -> Self {
|
||||||
Self { msg: msg.clone() }
|
Self { msg }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message(mut self, msg: String) -> Self {
|
pub fn message(mut self, msg: &str) -> Self {
|
||||||
self.msg.0.push(MessageSection {
|
self.msg.0.push(MessageSection {
|
||||||
msg,
|
msg: msg.to_string(),
|
||||||
fgcolor: Color(0xee, 0xee, 0xee),
|
fgcolor: Color(0xee, 0xee, 0xee),
|
||||||
bgcolor: Color(0, 0, 0),
|
bgcolor: Color(0, 0, 0),
|
||||||
});
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message_mut(&mut self, msg: String) {
|
pub fn message_mut(&mut self, msg: &str) {
|
||||||
self.msg.0.push(MessageSection {
|
self.msg.0.push(MessageSection {
|
||||||
msg,
|
msg: msg.to_string(),
|
||||||
fgcolor: Color(0xee, 0xee, 0xee),
|
fgcolor: Color(0xee, 0xee, 0xee),
|
||||||
bgcolor: Color(0, 0, 0),
|
bgcolor: Color(0, 0, 0),
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod string;
|
|
@ -0,0 +1,38 @@
|
||||||
|
use alloc::string::{String, ToString};
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! format {
|
||||||
|
( $s : expr, $( $e : expr ),* ) => {{
|
||||||
|
use crate::libk::string::format::Format;
|
||||||
|
let mut res = $s.to_string();
|
||||||
|
$(
|
||||||
|
res.format($e);
|
||||||
|
)*
|
||||||
|
res
|
||||||
|
}};
|
||||||
|
() => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Format<T: ToString> {
|
||||||
|
fn format(&mut self, f: T);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ToString> Format<T> for String {
|
||||||
|
fn format(&mut self, f: T) {
|
||||||
|
let mut res = String::new();
|
||||||
|
let mut formatting = false;
|
||||||
|
for c in self.chars().into_iter() {
|
||||||
|
if c == '{' {
|
||||||
|
formatting = true;
|
||||||
|
res += &f.to_string();
|
||||||
|
} else if c == '}' {
|
||||||
|
formatting = false;
|
||||||
|
}
|
||||||
|
if !formatting {
|
||||||
|
res.push(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.clear();
|
||||||
|
self.push_str(&res);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod format;
|
Reference in New Issue