use std::fs;
use std::path::PathBuf;
#[derive(Debug, thiserror::Error)]
pub enum PidError {
#[error("pid file I/O: {0}")]
Io(String),
#[error("pid file content is not a number: {0}")]
Parse(String),
}
pub fn pid_path() -> PathBuf {
runtime_dir().join("hyprcorrect.pid")
}
pub fn action_path() -> PathBuf {
runtime_dir().join("hyprcorrect.action")
}
pub fn chord_socket_path() -> PathBuf {
runtime_dir().join("hyprcorrect-chord.sock")
}
pub fn review_path() -> PathBuf {
runtime_dir().join("hyprcorrect.review")
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ReviewRequest {
pub original: String,
pub corrected: String,
pub trailing: String,
#[serde(default)]
pub chars_before_caret: usize,
#[serde(default)]
pub chars_after_caret: usize,
pub window_address: String,
}
pub fn write_review_request(req: &ReviewRequest) -> Result<(), PidError> {
let json = serde_json::to_string(req).map_err(|e| PidError::Io(e.to_string()))?;
let path = review_path();
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).map_err(|e| PidError::Io(e.to_string()))?;
}
fs::write(&path, json).map_err(|e| PidError::Io(e.to_string()))
}
pub fn read_review_request() -> Result<Option<ReviewRequest>, PidError> {
match fs::read_to_string(review_path()) {
Ok(text) => serde_json::from_str(&text)
.map(Some)
.map_err(|e| PidError::Parse(e.to_string())),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(e) => Err(PidError::Io(e.to_string())),
}
}
pub fn clear_review() {
let _ = fs::remove_file(review_path());
}
pub fn read_action() -> String {
std::fs::read_to_string(action_path())
.map(|s| s.trim().to_string())
.unwrap_or_default()
}
fn runtime_dir() -> PathBuf {
std::env::var_os("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.unwrap_or_else(std::env::temp_dir)
}
pub fn write_self_pid() -> Result<(), PidError> {
let path = pid_path();
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).map_err(|e| PidError::Io(e.to_string()))?;
}
fs::write(&path, std::process::id().to_string()).map_err(|e| PidError::Io(e.to_string()))
}
pub fn clear_pid() {
let _ = fs::remove_file(pid_path());
let _ = fs::remove_file(action_path());
}
pub fn read_daemon_pid() -> Result<Option<i32>, PidError> {
match fs::read_to_string(pid_path()) {
Ok(text) => text
.trim()
.parse::<i32>()
.map(Some)
.map_err(|e| PidError::Parse(e.to_string())),
Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(e) => Err(PidError::Io(e.to_string())),
}
}