diff --git a/src/codemp.lua b/src/codemp.lua index 984d94e..3808865 100644 --- a/src/codemp.lua +++ b/src/codemp.lua @@ -240,6 +240,16 @@ vim.api.nvim_create_user_command( { nargs = 1 } ) +-- TODO nvim docs say that we should stop all threads before exiting nvim +-- but we like to live dangerously (: +vim.loop.new_thread({}, function() + local _codemp = require("libcodemp_nvim") + local logger = _codemp.setup_tracing() + while true do + print(logger:recv()) + end +end) + return { lib = codemp, utils = { diff --git a/src/lib.rs b/src/lib.rs index e47c7a5..32fc27b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ -use std::{sync::{Arc, Mutex}, fs::File}; +use std::io::Write; +use std::sync::{Arc, Mutex, mpsc}; use codemp::prelude::*; use mlua::prelude::*; @@ -188,14 +189,53 @@ impl LuaUserData for LuaRowCol { // setup library logging to file -fn setup_tracing(_: &Lua, (path, debug): (String, Option)) -> LuaResult<()> { - let log_file = File::create(path)?; +#[derive(Debug, derive_more::From)] +struct LuaLogger(Arc>>); +impl LuaUserData for LuaLogger { + fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_method("recv", |_, this, ()| { + Ok( + this.0 + .lock() + .expect("logger mutex poisoned") + .recv() + .expect("logger channel closed") + ) + }); + } +} + +#[derive(Debug, Clone)] +struct LuaLoggerProducer(mpsc::Sender); +impl Write for LuaLoggerProducer { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.0.send(String::from_utf8_lossy(buf).to_string()) + .expect("could not write on logger channel"); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { Ok(()) } +} + +fn setup_tracing(_: &Lua, (debug,): (Option,)) -> LuaResult { + let (tx, rx) = mpsc::channel(); let level = if debug.unwrap_or(false) { tracing::Level::DEBUG } else {tracing::Level::INFO }; + let format = tracing_subscriber::fmt::format() + .with_level(true) + .with_target(true) + .with_thread_ids(false) + .with_thread_names(false) + .with_ansi(false) + .with_file(false) + .with_line_number(false) + .with_source_location(false) + .compact(); tracing_subscriber::fmt() + .event_format(format) .with_max_level(level) - .with_writer(Mutex::new(log_file)) + .with_writer(Mutex::new(LuaLoggerProducer(tx))) .init(); - Ok(()) + Ok(LuaLogger(Arc::new(Mutex::new(rx)))) }