Skip to content

Commit

Permalink
Enable \n replacement on all platoforms + Move logging to a module
Browse files Browse the repository at this point in the history
  • Loading branch information
melody-rs committed Mar 23, 2024
1 parent a251299 commit dbdecb8
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 65 deletions.
78 changes: 78 additions & 0 deletions src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (C) 2024 Lily Lyons
//
// This file is part of Luminol.
//
// Luminol is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Luminol is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Luminol. If not, see <http://www.gnu.org/licenses/>.
//
// Additional permission under GNU GPL version 3 section 7
//
// If you modify this Program, or any covered work, by linking or combining
// it with Steamworks API by Valve Corporation, containing parts covered by
// terms of the Steamworks API by Valve Corporation, the licensors of this
// Program grant you additional permission to convey the resulting work.

use std::io::Write;
use std::sync::mpsc::Sender;

#[derive(Clone)]
struct LogWriter {
sender: Sender<u8>,
context: egui::Context,
}

impl std::io::Write for LogWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
for &byte in buf {
if byte == b'\n' {
let _ = self.sender.send(b'\r');
}
let _ = self.sender.send(byte);
}

self.context.request_repaint();

Ok(buf.len())
}

fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}

struct CopyWriter<A, B>(A, B);

impl<A, B> Write for CopyWriter<A, B>
where
A: Write,
B: Write,
{
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Ok(self.0.write(buf)?.min(self.1.write(buf)?))
}

fn flush(&mut self) -> std::io::Result<()> {
self.0.flush()?;
self.1.flush()?;
Ok(())
}
}

pub fn initialize_log(sender: Sender<u8>, context: egui::Context) {
let log_writer = LogWriter { sender, context };
tracing_subscriber::fmt()
// we clone + move the log_writer so this closure impls Fn()
// the cost of doing this clone is pretty minimal (in comparison to locking stderr) so this is ok
.with_writer(move || CopyWriter(std::io::stderr(), log_writer.clone()))
.init();
}
70 changes: 5 additions & 65 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ static RESTART_AFTER_PANIC: std::sync::atomic::AtomicBool =
std::sync::atomic::AtomicBool::new(false);

mod app;
#[cfg(not(target_arch = "wasm32"))]
mod log;
mod lumi;

#[cfg(all(feature = "steamworks", target_arch = "wasm32"))]
Expand All @@ -56,60 +58,6 @@ pub fn git_revision() -> &'static str {
option_env!("LUMINOL_VERSION").unwrap_or(git_version::git_version!())
}

#[cfg(not(target_arch = "wasm32"))]
/// A writer that copies whatever is written to it to two other writers.
struct CopyWriter<A, B>(A, B);

#[cfg(not(target_arch = "wasm32"))]
impl<A, B> Write for CopyWriter<A, B>
where
A: Write,
B: Write,
{
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
Ok(self.0.write(buf)?.min(self.1.write(buf)?))
}

fn flush(&mut self) -> std::io::Result<()> {
self.0.flush()?;
self.1.flush()?;
Ok(())
}
}

#[cfg(not(target_arch = "wasm32"))]
static LOG_BYTE_SENDER: once_cell::sync::OnceCell<std::sync::mpsc::Sender<u8>> =
once_cell::sync::OnceCell::new();
#[cfg(not(target_arch = "wasm32"))]
static CONTEXT: once_cell::sync::OnceCell<egui::Context> = once_cell::sync::OnceCell::new();

/// A writer that writes to Luminol's log window.
#[cfg(not(target_arch = "wasm32"))]
struct LogWriter;

#[cfg(not(target_arch = "wasm32"))]
impl std::io::Write for LogWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let sender = LOG_BYTE_SENDER.get().unwrap();
for &byte in buf {
#[cfg(target_os = "linux")]
if byte == b'\n' {
let _ = sender.send(b'\r');
}
let _ = sender.send(byte);
}

if let Some(ctx) = CONTEXT.get() {
ctx.request_repaint();
}

Ok(buf.len())
}

fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
#[cfg(not(target_arch = "wasm32"))]
fn main() {
// Load the panic report from the previous run if it exists
Expand Down Expand Up @@ -257,16 +205,6 @@ fn main() {
}
}));

// Log to stderr as well as Luminol's log.
let (log_byte_tx, log_byte_rx) = std::sync::mpsc::channel();
LOG_BYTE_SENDER.set(log_byte_tx).unwrap();
tracing_subscriber::fmt()
.with_writer(|| CopyWriter(std::io::stderr(), LogWriter))
.init();
// tracing_subscriber::fmt()
// .with_writer(std::io::stdout)
// .init();

let image = image::load_from_memory(ICON).expect("Failed to load Icon data.");

let native_options = luminol_eframe::NativeOptions {
Expand Down Expand Up @@ -302,7 +240,9 @@ fn main() {
"Luminol",
native_options,
Box::new(|cc| {
CONTEXT.set(cc.egui_ctx.clone()).unwrap();
let (log_byte_tx, log_byte_rx) = std::sync::mpsc::channel();
log::initialize_log(log_byte_tx, cc.egui_ctx.clone());

Box::new(app::App::new(
cc,
report,
Expand Down

0 comments on commit dbdecb8

Please sign in to comment.