feat: Implement config file

This commit is contained in:
Lucas Schwiderski 2023-04-13 20:06:50 +02:00
parent 4438a11437
commit 402513b11d
Signed by: lucas
GPG key ID: AA12679AAA6DF4D8
4 changed files with 72 additions and 12 deletions

View file

@ -7,7 +7,7 @@ use color_eyre::Result;
use crate::Request; use crate::Request;
pub fn handle(runtime_dir: PathBuf) -> Result<()> { pub fn handle(runtime_dir: PathBuf, session: String) -> Result<()> {
let mut buf = String::new(); let mut buf = String::new();
stdin() stdin()
.read_to_string(&mut buf) .read_to_string(&mut buf)
@ -17,7 +17,7 @@ pub fn handle(runtime_dir: PathBuf) -> Result<()> {
tracing::trace!("Received request: {:?}", req); tracing::trace!("Received request: {:?}", req);
let path = runtime_dir.join(&req.session).with_extension("s"); let path = runtime_dir.join(session).with_extension("s");
tracing::debug!(path = %path.display()); tracing::debug!(path = %path.display());
let mut socket = UnixStream::connect(&path) let mut socket = UnixStream::connect(&path)

51
src/config.rs Normal file
View file

@ -0,0 +1,51 @@
use std::io::ErrorKind;
use std::path::PathBuf;
use std::{env, fs};
use color_eyre::eyre::Context;
use color_eyre::Result;
use serde::Deserialize;
#[derive(Copy, Clone, Debug, Deserialize)]
pub struct Config {
/// The number of worker threads to spawn
pub workers: u8,
}
impl Config {
pub fn load(path: Option<PathBuf>) -> Result<Self> {
let buf = if let Some(path) = path {
tracing::debug!("Reading config file '{}'", path.display());
fs::read(&path).wrap_err_with(|| format!("Failed to read file '{}'", path.display()))?
} else {
let path = default_config_path();
tracing::debug!("Reading config file '{}'", path.display());
match fs::read(&path) {
Ok(data) => data,
Err(err) if err.kind() == ErrorKind::NotFound => {
tracing::debug!("Default config file does not exist, using default values");
return Ok(Config::default());
}
Err(err) => {
return Err(err)
.wrap_err_with(|| format!("Failed to read file '{}'", path.display()))
}
}
};
let buf = String::from_utf8_lossy(&buf);
toml::from_str(&buf).wrap_err("Failed to deserialize config")
}
}
impl Default for Config {
fn default() -> Self {
Self { workers: 2 }
}
}
fn default_config_path() -> PathBuf {
env::var("XDG_CONFIG_HOME")
.map(PathBuf::from)
.unwrap_or_else(|_| PathBuf::from(env::var("HOME").unwrap()).join(".config"))
.join("kak-highlight.toml")
}

View file

@ -11,6 +11,7 @@ use signal_hook::consts::{SIGINT, TERM_SIGNALS};
use signal_hook::flag; use signal_hook::flag;
use signal_hook::iterator::Signals; use signal_hook::iterator::Signals;
use crate::config::Config;
use crate::daemon::worker::TaskScheduler; use crate::daemon::worker::TaskScheduler;
use self::listener::Listener; use self::listener::Listener;
@ -19,7 +20,7 @@ mod listener;
mod worker; mod worker;
#[tracing::instrument] #[tracing::instrument]
pub fn handle(runtime_dir: PathBuf, session: String, workers: u8) -> Result<()> { pub fn handle(runtime_dir: PathBuf, config_path: Option<PathBuf>, session: String) -> Result<()> {
// Ensure that sending a termination signal twice will immediately kill // Ensure that sending a termination signal twice will immediately kill
{ {
let term_now = Arc::new(AtomicBool::new(false)); let term_now = Arc::new(AtomicBool::new(false));
@ -29,6 +30,9 @@ pub fn handle(runtime_dir: PathBuf, session: String, workers: u8) -> Result<()>
} }
} }
let config = Config::load(config_path).wrap_err("Failed to load config")?;
tracing::debug!(?config);
let rx_signals = { let rx_signals = {
let mut signals = Signals::new([SIGINT])?; let mut signals = Signals::new([SIGINT])?;
let (tx, rx) = bounded(1); let (tx, rx) = bounded(1);
@ -42,10 +46,13 @@ pub fn handle(runtime_dir: PathBuf, session: String, workers: u8) -> Result<()>
}) })
.wrap_err("Failed to start signal handler")?; .wrap_err("Failed to start signal handler")?;
tracing::trace!("Started signal handler");
rx rx
}; };
let mut scheduler = TaskScheduler::new(workers).wrap_err("Failed to create task scheduler")?; let mut scheduler =
TaskScheduler::new(config.workers).wrap_err("Failed to create task scheduler")?;
let listener = Listener::new(runtime_dir, session).wrap_err("Failed to create listener")?; let listener = Listener::new(runtime_dir, session).wrap_err("Failed to create listener")?;
loop { loop {

View file

@ -12,6 +12,7 @@ use tracing_subscriber::fmt;
use tracing_subscriber::prelude::*; use tracing_subscriber::prelude::*;
mod client; mod client;
mod config;
mod daemon; mod daemon;
mod kakoune; mod kakoune;
@ -24,6 +25,9 @@ struct Cli {
/// File to write log events to /// File to write log events to
#[arg(long, value_name = "FILENAME")] #[arg(long, value_name = "FILENAME")]
log: Option<PathBuf>, log: Option<PathBuf>,
/// Config file. Defaults to `$XDG_CONFIG_HOME/kak-highlight.toml`.
#[arg(short, long, value_name = "FILENAME")]
config: Option<PathBuf>,
/// The command to run /// The command to run
#[command(subcommand)] #[command(subcommand)]
command: Command, command: Command,
@ -32,21 +36,19 @@ struct Cli {
#[derive(Subcommand)] #[derive(Subcommand)]
enum Command { enum Command {
/// Send a request payload to a running daemon and wait for the response /// Send a request payload to a running daemon and wait for the response
Request, Request {
/// The Kakoune session this daemon belongs to
session: String,
},
/// Start a daemon /// Start a daemon
Daemon { Daemon {
/// The Kakoune session this daemon belongs to /// The Kakoune session this daemon belongs to
session: String, session: String,
/// The number of worker threads to spawn
#[arg(short = 'n', long, default_value = "2", action = clap::ArgAction::Count)]
workers: u8,
}, },
} }
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
struct Request { struct Request {
/// The Kakoune session this request came from
session: String,
/// The command FIFO provided by Kakoune /// The command FIFO provided by Kakoune
fifo: String, fifo: String,
} }
@ -91,7 +93,7 @@ fn main() -> Result<()> {
.join("kak-highlight"); .join("kak-highlight");
match cli.command { match cli.command {
Command::Daemon { session, workers } => daemon::handle(runtime_dir, session, workers), Command::Daemon { session } => daemon::handle(runtime_dir, cli.config, session),
Command::Request => client::handle(runtime_dir), Command::Request { session } => client::handle(runtime_dir, session),
} }
} }