#[cfg(any(windows, target_os = "macos"))] use std::env; use std::path::{Path, PathBuf}; use anyhow::Result; use directories::BaseDirs; use crate::execution_context::ExecutionContext; use crate::terminal::print_separator; use crate::utils::{require, require_option, PathExt}; use crate::Step; const EMACS_UPGRADE: &str = include_str!("emacs.el"); #[cfg(windows)] const DOOM_PATH: &str = "bin/doom.cmd"; #[cfg(unix)] const DOOM_PATH: &str = "bin/doom"; pub struct Emacs { directory: Option, doom: Option, } impl Emacs { fn directory_path(base_dirs: &BaseDirs) -> Option { #[cfg(unix)] cfg_if::cfg_if! { if #[cfg(target_os = "macos")] { let emacs_xdg_dir = env::var("XDG_CONFIG_HOME") .ok() .and_then(|config| PathBuf::from(config).join("emacs").if_exists()) .or_else(|| base_dirs.home_dir().join(".config/emacs").if_exists()); } else { let emacs_xdg_dir = base_dirs.config_dir().join("emacs").if_exists(); } } #[cfg(unix)] return base_dirs.home_dir().join(".emacs.d").if_exists().or(emacs_xdg_dir); #[cfg(windows)] return env::var("HOME") .ok() .and_then(|home| { PathBuf::from(&home) .join(".emacs.d") .if_exists() .or_else(|| PathBuf::from(&home).join(".config\\emacs").if_exists()) }) .or_else(|| base_dirs.data_dir().join(".emacs.d").if_exists()); } pub fn new(base_dirs: &BaseDirs) -> Self { let directory = Emacs::directory_path(base_dirs); let doom = directory.as_ref().and_then(|d| d.join(DOOM_PATH).if_exists()); Self { directory, doom } } pub fn is_doom(&self) -> bool { self.doom.is_some() } pub fn directory(&self) -> Option<&PathBuf> { self.directory.as_ref() } fn update_doom(doom: &Path, ctx: &ExecutionContext) -> Result<()> { print_separator("Doom Emacs"); let mut command = ctx.run_type().execute(doom); if ctx.config().yes(Step::Emacs) { command.arg("--force"); } command.args(["upgrade"]); command.check_run() } pub fn upgrade(&self, ctx: &ExecutionContext) -> Result<()> { let emacs = require("emacs")?; if let Some(doom) = &self.doom { Emacs::update_doom(doom, ctx)?; } let init_file = require_option(self.directory.as_ref(), String::from("Emacs directory does not exist"))? .join("init.el") .require()?; print_separator("Emacs"); let mut command = ctx.run_type().execute(emacs); command .args(["--batch", "--debug-init", "-l"]) .arg(init_file) .arg("--eval"); #[cfg(unix)] command.arg( EMACS_UPGRADE .chars() .map(|c| if c.is_whitespace() { '\u{00a0}' } else { c }) .collect::(), ); #[cfg(not(unix))] command.arg(EMACS_UPGRADE); command.check_run() } }