Add edit subcommand. Fix #171
This commit is contained in:
parent
a89438f3ba
commit
3e98748c54
|
@ -38,7 +38,7 @@ pub(crate) mod runtime;
|
|||
const DEFAULT_CONFIG_FILE_CONTENT : &str = include_str!("../res/config.yml");
|
||||
|
||||
pub const DEFAULT_CONFIG_FILE_NAME : &str = "default.yml";
|
||||
const USER_CONFIGS_FOLDER_NAME: &str = "user";
|
||||
pub const USER_CONFIGS_FOLDER_NAME: &str = "user";
|
||||
|
||||
// Default values for primitives
|
||||
fn default_name() -> String{ "default".to_owned() }
|
||||
|
@ -68,9 +68,16 @@ fn default_exclude_default_entries() -> bool {false}
|
|||
fn default_matches() -> Vec<Match> { Vec::new() }
|
||||
fn default_global_vars() -> Vec<MatchVariable> { Vec::new() }
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn default_editor() -> String{ "/bin/nano".to_owned() }
|
||||
#[cfg(target_os = "macos")]
|
||||
fn default_editor() -> String{ "/usr/bin/nano".to_owned() } // TODO: change
|
||||
#[cfg(target_os = "windows")]
|
||||
fn default_editor() -> String{ "C:\\Windows\\System32\\notepad.exe".to_owned() }
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Configs {
|
||||
#[serde(default = "default_name")]
|
||||
#[serde(default = "default_name")]
|
||||
pub name: String,
|
||||
|
||||
#[serde(default = "default_parent")]
|
||||
|
@ -148,6 +155,9 @@ pub struct Configs {
|
|||
#[serde(default = "default_exclude_default_entries")]
|
||||
pub exclude_default_entries: bool,
|
||||
|
||||
#[serde(default = "default_editor")]
|
||||
pub editor: String,
|
||||
|
||||
#[serde(default = "default_matches")]
|
||||
pub matches: Vec<Match>,
|
||||
|
||||
|
|
48
src/edit.rs
48
src/edit.rs
|
@ -18,44 +18,40 @@
|
|||
*/
|
||||
|
||||
use crate::config::ConfigSet;
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn open_editor(config: &ConfigSet) -> bool {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn open_editor(config: &ConfigSet) -> bool {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn open_editor(config: &ConfigSet) -> bool {
|
||||
pub fn open_editor(config: &ConfigSet, file_path: &Path) -> bool {
|
||||
use std::process::Command;
|
||||
|
||||
// Get the configuration file path
|
||||
let file_path = crate::context::get_config_dir().join(crate::config::DEFAULT_CONFIG_FILE_NAME);
|
||||
// Check if another editor is defined in the environment variables
|
||||
let editor_var = std::env::var_os("EDITOR");
|
||||
let visual_var = std::env::var_os("VISUAL");
|
||||
|
||||
// Prioritize the editors specified by the environment variable, otherwise use the config
|
||||
let editor : String = if let Some(editor_var) = editor_var {
|
||||
editor_var.to_string_lossy().to_string()
|
||||
}else if let Some(visual_var) = visual_var {
|
||||
visual_var.to_string_lossy().to_string()
|
||||
}else{
|
||||
config.default.editor.clone()
|
||||
};
|
||||
|
||||
// Start the editor and wait for its termination
|
||||
let status = Command::new("cmd")
|
||||
.arg("/C")
|
||||
.arg("start")
|
||||
.arg("/wait")
|
||||
.arg("C:\\Windows\\System32\\notepad.exe")
|
||||
let status = Command::new(editor)
|
||||
.arg(file_path)
|
||||
.spawn();
|
||||
|
||||
if let Ok(mut child) = status {
|
||||
// Wait for the user to edit the configuration
|
||||
child.wait();
|
||||
let result = child.wait();
|
||||
|
||||
// TODO: instead of waiting, a file watcher should be started to detect file changes and
|
||||
// after each of them a reload should be issued
|
||||
|
||||
println!("Ok");
|
||||
true
|
||||
if let Ok(exit_status) = result {
|
||||
exit_status.success()
|
||||
}else{
|
||||
false
|
||||
}
|
||||
}else{
|
||||
println!("Error: could not start editor.");
|
||||
println!("Error: could not start editor at: {}", config.default.editor);
|
||||
false
|
||||
}
|
||||
}
|
70
src/main.rs
70
src/main.rs
|
@ -98,7 +98,9 @@ fn main() {
|
|||
.about("Toggle the status of the espanso replacement engine."))
|
||||
)
|
||||
.subcommand(SubCommand::with_name("edit")
|
||||
.about("Open the default text editor to edit config files and reload them automatically when exiting"))
|
||||
.about("Open the default text editor to edit config files and reload them automatically when exiting")
|
||||
.arg(Arg::with_name("config")
|
||||
.help("Defaults to \"default\". The configuration file name to edit (without the .yml extension).")))
|
||||
.subcommand(SubCommand::with_name("dump")
|
||||
.about("Prints all current configuration options."))
|
||||
.subcommand(SubCommand::with_name("detect")
|
||||
|
@ -166,8 +168,8 @@ fn main() {
|
|||
return;
|
||||
}
|
||||
|
||||
if matches.subcommand_matches("edit").is_some() {
|
||||
edit_main(config_set);
|
||||
if let Some(matches) = matches.subcommand_matches("edit") {
|
||||
edit_main(config_set, matches);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -881,8 +883,66 @@ fn path_main(_config_set: ConfigSet, matches: &ArgMatches) {
|
|||
}
|
||||
}
|
||||
|
||||
fn edit_main(config_set: ConfigSet) {
|
||||
crate::edit::open_editor(&config_set);
|
||||
fn edit_main(config_set: ConfigSet, matches: &ArgMatches) {
|
||||
// Determine which is the file to edit
|
||||
let config = matches.value_of("config").unwrap_or("default");
|
||||
|
||||
let config_dir = crate::context::get_config_dir();
|
||||
|
||||
let config_path = match config {
|
||||
"default" => {
|
||||
config_dir.join(crate::config::DEFAULT_CONFIG_FILE_NAME)
|
||||
},
|
||||
name => { // Otherwise, search in the user/ config folder
|
||||
config_dir.join(crate::config::USER_CONFIGS_FOLDER_NAME)
|
||||
.join(name.to_owned() + ".yml")
|
||||
}
|
||||
};
|
||||
|
||||
println!("Editing file: {:?}", &config_path);
|
||||
|
||||
// Based on the fact that the file already exists or not, we should detect in different
|
||||
// ways if a reload is needed
|
||||
let should_reload =if config_path.exists() {
|
||||
// Get the last modified date, so that we can detect if the user actually edits the file
|
||||
// before reloading
|
||||
let metadata = std::fs::metadata(&config_path).expect("cannot gather file metadata");
|
||||
let last_modified = metadata.modified().expect("cannot read file last modified date");
|
||||
|
||||
let result = crate::edit::open_editor(&config_set, &config_path);
|
||||
if result {
|
||||
let new_metadata = std::fs::metadata(&config_path).expect("cannot gather file metadata");
|
||||
let new_last_modified = new_metadata.modified().expect("cannot read file last modified date");
|
||||
|
||||
if last_modified != new_last_modified {
|
||||
println!("File has been modified, reloading configuration");
|
||||
true
|
||||
}else{
|
||||
println!("File has not been modified, avoiding reload");
|
||||
false
|
||||
}
|
||||
}else{
|
||||
false
|
||||
}
|
||||
}else{
|
||||
let result = crate::edit::open_editor(&config_set, &config_path);
|
||||
if result {
|
||||
// If the file has been created, we should reload the espanso config
|
||||
if config_path.exists() {
|
||||
println!("A new file has been created, reloading configuration");
|
||||
true
|
||||
}else{
|
||||
println!("No file has been created, avoiding reload");
|
||||
false
|
||||
}
|
||||
}else{
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
if should_reload {
|
||||
restart_main(config_set)
|
||||
}
|
||||
}
|
||||
|
||||
fn acquire_lock() -> Option<File> {
|
||||
|
|
Loading…
Reference in New Issue
Block a user