Colorize log output #97
9 changed files with 214 additions and 38 deletions
100
Cargo.lock
generated
100
Cargo.lock
generated
|
@ -38,6 +38,16 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi-parser"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bcb2392079bf27198570d6af79ecbd9ec7d8f16d3ec6b60933922fdb66287127"
|
||||||
|
dependencies = [
|
||||||
|
"heapless",
|
||||||
|
"nom 4.2.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.69"
|
version = "1.0.69"
|
||||||
|
@ -62,6 +72,18 @@ version = "0.7.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "as-slice"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array 0.12.4",
|
||||||
|
"generic-array 0.13.3",
|
||||||
|
"generic-array 0.14.6",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "associative-cache"
|
name = "associative-cache"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -191,7 +213,7 @@ version = "0.10.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -321,7 +343,7 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -614,7 +636,7 @@ version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array 0.14.6",
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -807,6 +829,7 @@ dependencies = [
|
||||||
name = "dtmm"
|
name = "dtmm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ansi-parser",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
@ -1272,6 +1295,24 @@ dependencies = [
|
||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.6"
|
version = "0.14.6"
|
||||||
|
@ -1279,7 +1320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
"version_check",
|
"version_check 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1480,12 +1521,33 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hash32"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heapless"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "74911a68a1658cfcfb61bc0ccfbd536e3b6e906f8c2f7883ee50157e3e2184f1"
|
||||||
|
dependencies = [
|
||||||
|
"as-slice",
|
||||||
|
"generic-array 0.13.3",
|
||||||
|
"hash32",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -1609,7 +1671,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"sized-chunks",
|
"sized-chunks",
|
||||||
"typenum",
|
"typenum",
|
||||||
"version_check",
|
"version_check 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2023,6 +2085,16 @@ version = "1.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "4.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"version_check 0.1.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
|
@ -2576,7 +2648,7 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
"version_check",
|
"version_check 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2587,7 +2659,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"version_check",
|
"version_check 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3091,6 +3163,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "steamid-ng"
|
name = "steamid-ng"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -3634,7 +3712,7 @@ version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"version_check",
|
"version_check 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3768,6 +3846,12 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
|
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
|
@ -31,3 +31,4 @@ lazy_static = "1.4.0"
|
||||||
colors-transform = "0.2.11"
|
colors-transform = "0.2.11"
|
||||||
usvg = "0.25.0"
|
usvg = "0.25.0"
|
||||||
druid-widget-nursery = "0.1"
|
druid-widget-nursery = "0.1"
|
||||||
|
ansi-parser = "0.8.0"
|
||||||
|
|
|
@ -174,7 +174,7 @@ async fn handle_action(
|
||||||
|
|
||||||
async fn handle_log(
|
async fn handle_log(
|
||||||
event_sink: Arc<RwLock<ExtEventSink>>,
|
event_sink: Arc<RwLock<ExtEventSink>>,
|
||||||
log_queue: Arc<RwLock<UnboundedReceiver<String>>>,
|
log_queue: Arc<RwLock<UnboundedReceiver<Vec<u8>>>>,
|
||||||
) {
|
) {
|
||||||
while let Some(line) = log_queue.write().await.recv().await {
|
while let Some(line) = log_queue.write().await.recv().await {
|
||||||
let event_sink = event_sink.clone();
|
let event_sink = event_sink.clone();
|
||||||
|
@ -189,7 +189,7 @@ async fn handle_log(
|
||||||
pub(crate) fn work_thread(
|
pub(crate) fn work_thread(
|
||||||
event_sink: Arc<RwLock<ExtEventSink>>,
|
event_sink: Arc<RwLock<ExtEventSink>>,
|
||||||
action_queue: Arc<RwLock<UnboundedReceiver<AsyncAction>>>,
|
action_queue: Arc<RwLock<UnboundedReceiver<AsyncAction>>>,
|
||||||
log_queue: Arc<RwLock<UnboundedReceiver<String>>>,
|
log_queue: Arc<RwLock<UnboundedReceiver<Vec<u8>>>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let rt = Runtime::new()?;
|
let rt = Runtime::new()?;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ use crate::ui::theme;
|
||||||
mod controller;
|
mod controller;
|
||||||
mod state;
|
mod state;
|
||||||
mod util {
|
mod util {
|
||||||
|
pub mod ansi;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod log;
|
pub mod log;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use druid::im::{HashMap, Vector};
|
use druid::im::{HashMap, Vector};
|
||||||
|
use druid::text::RichText;
|
||||||
use druid::{Data, ImageBuf, Lens, WindowHandle, WindowId};
|
use druid::{Data, ImageBuf, Lens, WindowHandle, WindowId};
|
||||||
use dtmt_shared::ModConfig;
|
use dtmt_shared::ModConfig;
|
||||||
use nexusmods::Mod as NexusMod;
|
use nexusmods::Mod as NexusMod;
|
||||||
|
@ -157,7 +158,7 @@ pub(crate) struct State {
|
||||||
pub nexus_api_key: Arc<String>,
|
pub nexus_api_key: Arc<String>,
|
||||||
|
|
||||||
#[data(ignore)]
|
#[data(ignore)]
|
||||||
pub log: Arc<String>,
|
pub log: Vector<RichText>,
|
||||||
// True, when the initial loading of configuration and mods is still in progress
|
// True, when the initial loading of configuration and mods is still in progress
|
||||||
pub loading: bool,
|
pub loading: bool,
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ impl State {
|
||||||
game_dir: Arc::new(PathBuf::new()),
|
game_dir: Arc::new(PathBuf::new()),
|
||||||
data_dir: Arc::new(PathBuf::new()),
|
data_dir: Arc::new(PathBuf::new()),
|
||||||
nexus_api_key: Arc::new(String::new()),
|
nexus_api_key: Arc::new(String::new()),
|
||||||
log: Arc::new(String::new()),
|
log: Vector::new(),
|
||||||
windows: HashMap::new(),
|
windows: HashMap::new(),
|
||||||
loading: true,
|
loading: true,
|
||||||
}
|
}
|
||||||
|
@ -223,9 +224,4 @@ impl State {
|
||||||
pub fn can_move_mod_up(&self) -> bool {
|
pub fn can_move_mod_up(&self) -> bool {
|
||||||
self.selected_mod_index.map(|i| i > 0).unwrap_or(false)
|
self.selected_mod_index.map(|i| i > 0).unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_log_line(&mut self, line: String) {
|
|
||||||
let log = Arc::make_mut(&mut self.log);
|
|
||||||
log.push_str(&line);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
use std::{path::PathBuf, sync::Arc};
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use color_eyre::Report;
|
use color_eyre::Report;
|
||||||
|
use druid::im::Vector;
|
||||||
use druid::{
|
use druid::{
|
||||||
im::Vector, AppDelegate, Command, DelegateCtx, Env, FileInfo, Handled, Selector, SingleUse,
|
AppDelegate, Command, DelegateCtx, Env, FileInfo, Handled, Selector, SingleUse, Target,
|
||||||
Target, WindowHandle, WindowId,
|
WindowHandle, WindowId,
|
||||||
};
|
};
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
|
use crate::util::ansi::ansi_to_rich_text;
|
||||||
use crate::{ui::window, util::config::Config};
|
use crate::{ui::window, util::config::Config};
|
||||||
|
|
||||||
use super::{ModInfo, State};
|
use super::{ModInfo, State};
|
||||||
|
@ -32,7 +34,7 @@ pub(crate) const ACTION_ADD_MOD: Selector<FileInfo> = Selector::new("dtmm.action
|
||||||
pub(crate) const ACTION_FINISH_ADD_MOD: Selector<SingleUse<Arc<ModInfo>>> =
|
pub(crate) const ACTION_FINISH_ADD_MOD: Selector<SingleUse<Arc<ModInfo>>> =
|
||||||
Selector::new("dtmm.action.finish-add-mod");
|
Selector::new("dtmm.action.finish-add-mod");
|
||||||
|
|
||||||
pub(crate) const ACTION_LOG: Selector<SingleUse<String>> = Selector::new("dtmm.action.log");
|
pub(crate) const ACTION_LOG: Selector<SingleUse<Vec<u8>>> = Selector::new("dtmm.action.log");
|
||||||
|
|
||||||
pub(crate) const ACTION_START_SAVE_SETTINGS: Selector =
|
pub(crate) const ACTION_START_SAVE_SETTINGS: Selector =
|
||||||
Selector::new("dtmm.action.start-save-settings");
|
Selector::new("dtmm.action.start-save-settings");
|
||||||
|
@ -252,7 +254,8 @@ impl AppDelegate<State> for Delegate {
|
||||||
.get(ACTION_LOG)
|
.get(ACTION_LOG)
|
||||||
.expect("command type matched but didn't contain the expected value");
|
.expect("command type matched but didn't contain the expected value");
|
||||||
if let Some(line) = line.take() {
|
if let Some(line) = line.take() {
|
||||||
state.add_log_line(line);
|
let line = String::from_utf8_lossy(&line);
|
||||||
|
state.log.push_back(ansi_to_rich_text(&line));
|
||||||
}
|
}
|
||||||
Handled::Yes
|
Handled::Yes
|
||||||
}
|
}
|
||||||
|
|
|
@ -451,17 +451,18 @@ fn build_main() -> impl Widget<State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_log_view() -> impl Widget<State> {
|
fn build_log_view() -> impl Widget<State> {
|
||||||
let font = FontDescriptor::new(FontFamily::MONOSPACE);
|
let list = List::new(|| {
|
||||||
let label = Label::raw()
|
Label::raw()
|
||||||
.with_font(font)
|
.with_font(FontDescriptor::new(FontFamily::MONOSPACE))
|
||||||
.with_line_break_mode(LineBreaking::WordWrap)
|
.with_line_break_mode(LineBreaking::WordWrap)
|
||||||
|
})
|
||||||
.lens(State::log)
|
.lens(State::log)
|
||||||
.padding(4.)
|
.padding(4.)
|
||||||
.scroll()
|
.scroll()
|
||||||
.vertical()
|
.vertical()
|
||||||
.controller(AutoScrollController);
|
.controller(AutoScrollController);
|
||||||
|
|
||||||
let inner = Border::new(label)
|
let inner = Border::new(list)
|
||||||
.with_color(theme::COLOR_FG2)
|
.with_color(theme::COLOR_FG2)
|
||||||
.with_top_border(1.);
|
.with_top_border(1.);
|
||||||
|
|
||||||
|
|
93
crates/dtmm/src/util/ansi.rs
Normal file
93
crates/dtmm/src/util/ansi.rs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
use ansi_parser::{AnsiParser, AnsiSequence, Output};
|
||||||
|
use druid::text::{RichText, RichTextBuilder};
|
||||||
|
use druid::{Color, FontStyle, FontWeight};
|
||||||
|
|
||||||
|
use crate::ui::theme;
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct TextState {
|
||||||
|
color: Option<Color>,
|
||||||
|
dim: bool,
|
||||||
|
bold: bool,
|
||||||
|
underline: bool,
|
||||||
|
strikethrough: bool,
|
||||||
|
italic: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ansi_to_rich_text(input: &str) -> RichText {
|
||||||
|
let mut builder = RichTextBuilder::new();
|
||||||
|
|
||||||
|
let mut state = TextState::default();
|
||||||
|
|
||||||
|
for token in input.ansi_parse() {
|
||||||
|
match token {
|
||||||
|
Output::TextBlock(text) => {
|
||||||
|
dbg!(&state);
|
||||||
|
dbg!(&text);
|
||||||
|
|
||||||
|
let mut attr = builder.push(text);
|
||||||
|
attr.underline(state.underline);
|
||||||
|
attr.strikethrough(state.strikethrough);
|
||||||
|
|
||||||
|
if state.bold {
|
||||||
|
attr.weight(FontWeight::BOLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.italic {
|
||||||
|
attr.style(FontStyle::Italic);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(color) = state.color {
|
||||||
|
attr.text_color(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Output::Escape(AnsiSequence::SetGraphicsMode(values)) => {
|
||||||
|
for v in values {
|
||||||
|
match v {
|
||||||
|
0 => {
|
||||||
|
state = Default::default();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
1 => state.bold = true,
|
||||||
|
2 => state.dim = true,
|
||||||
|
3 => state.italic = true,
|
||||||
|
4 => state.underline = true,
|
||||||
|
9 => state.strikethrough = true,
|
||||||
|
22 => {
|
||||||
|
state.bold = false;
|
||||||
|
state.dim = false;
|
||||||
|
}
|
||||||
|
23 => state.italic = false,
|
||||||
|
24 => state.underline = false,
|
||||||
|
29 => state.underline = false,
|
||||||
|
30..=40 | 90..=100 => {
|
||||||
|
let mut col = v - 30;
|
||||||
|
if col > 9 {
|
||||||
|
state.bold = true;
|
||||||
|
col -= 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.color = match col {
|
||||||
|
// This escape code is usually called 'black', but is actually used
|
||||||
|
// as "foreground color", in regards to light themes.
|
||||||
|
1 => Some(theme::COLOR_FG),
|
||||||
|
2 => Some(theme::COLOR_RED_LIGHT),
|
||||||
|
3 => Some(theme::COLOR_GREEN_LIGHT),
|
||||||
|
4 => Some(theme::COLOR_YELLOW_LIGHT),
|
||||||
|
5 => Some(theme::COLOR_BLUE_LIGHT),
|
||||||
|
6 => Some(theme::COLOR_PURPLE_LIGHT),
|
||||||
|
7 => Some(theme::COLOR_AQUA_LIGHT),
|
||||||
|
9 => None,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Output::Escape(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.build()
|
||||||
|
}
|
|
@ -8,11 +8,11 @@ use tracing_subscriber::prelude::*;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
pub struct ChannelWriter {
|
pub struct ChannelWriter {
|
||||||
tx: UnboundedSender<String>,
|
tx: UnboundedSender<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelWriter {
|
impl ChannelWriter {
|
||||||
pub fn new(tx: UnboundedSender<String>) -> Self {
|
pub fn new(tx: UnboundedSender<Vec<u8>>) -> Self {
|
||||||
Self { tx }
|
Self { tx }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,9 @@ impl ChannelWriter {
|
||||||
impl std::io::Write for ChannelWriter {
|
impl std::io::Write for ChannelWriter {
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
let tx = self.tx.clone();
|
let tx = self.tx.clone();
|
||||||
let stripped = strip_ansi_escapes::strip(buf)?;
|
|
||||||
let string = String::from_utf8_lossy(&stripped).to_string();
|
|
||||||
|
|
||||||
// The `send` errors when the receiving end has closed.
|
// The `send` errors when the receiving end has closed.
|
||||||
// But there's not much we can do at that point, so we just ignore it.
|
// But there's not much we can do at that point, so we just ignore it.
|
||||||
let _ = tx.send(string);
|
let _ = tx.send(buf.to_vec());
|
||||||
|
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
}
|
||||||
|
@ -35,7 +32,7 @@ impl std::io::Write for ChannelWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_tracing_subscriber(tx: UnboundedSender<String>) {
|
pub fn create_tracing_subscriber(tx: UnboundedSender<Vec<u8>>) {
|
||||||
let env_layer = if cfg!(debug_assertions) {
|
let env_layer = if cfg!(debug_assertions) {
|
||||||
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"))
|
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"))
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Reference in a new issue