Auto merge of #31 - matthiasbeyer:ui-external, r=matthiasbeyer
Ui external Tracking branch for implementation to call external editor and edit file contents with it.
This commit is contained in:
commit
2568c37a25
7 changed files with 122 additions and 0 deletions
12
etc/cli.yml
12
etc/cli.yml
|
@ -22,6 +22,18 @@ args:
|
|||
required: false
|
||||
takes_value: true
|
||||
|
||||
- editor:
|
||||
short: e
|
||||
long: editor
|
||||
help: Set editor, if not set $EDITOR of the system will be asked, else vim
|
||||
required: false
|
||||
takes_value: true
|
||||
|
||||
- editor_opts:
|
||||
long: editor-opts
|
||||
help: Set editor options
|
||||
required: false
|
||||
takes_value: true
|
||||
|
||||
- storename:
|
||||
short: s
|
||||
|
|
11
src/cli.rs
11
src/cli.rs
|
@ -47,6 +47,17 @@ impl<'a> CliConfig<'a> {
|
|||
.and_then(|s| Some(rtp + s))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn editor(&self) -> Option<String> {
|
||||
self.cli_matches.value_of("editor").and_then(|s| Some(String::from(s)))
|
||||
}
|
||||
|
||||
pub fn editor_opts(&self) -> String {
|
||||
self.cli_matches
|
||||
.value_of("editor_opts")
|
||||
.map(|s| String::from(s))
|
||||
.unwrap_or(String::from(""))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Debug for CliConfig<'a> {
|
||||
|
|
|
@ -10,6 +10,8 @@ pub struct Configuration {
|
|||
pub store_sub : String,
|
||||
pub verbose : bool,
|
||||
pub debugging : bool,
|
||||
pub editor : Option<String>,
|
||||
pub editor_opts : String,
|
||||
}
|
||||
|
||||
impl Configuration {
|
||||
|
@ -20,6 +22,8 @@ impl Configuration {
|
|||
let mut verbose = false;
|
||||
let mut debugging = false;
|
||||
let mut store_sub = String::from("/store");
|
||||
let mut editor = None;
|
||||
let mut editor_opts = String::from("");
|
||||
|
||||
if let Some(cfg) = fetch_config(rtp.clone()) {
|
||||
if let Some(v) = cfg.lookup_boolean("verbose") {
|
||||
|
@ -31,6 +35,12 @@ impl Configuration {
|
|||
if let Some(s) = cfg.lookup_str("store") {
|
||||
store_sub = String::from(s);
|
||||
}
|
||||
if let Some(s) = cfg.lookup_str("editor") {
|
||||
editor = Some(String::from(s));
|
||||
}
|
||||
if let Some(s) = cfg.lookup_str("editor-opts") {
|
||||
editor_opts = String::from(s);
|
||||
}
|
||||
}
|
||||
|
||||
let runtimepath = rtp.unwrap_or(String::from("/tmp/"));
|
||||
|
@ -40,12 +50,16 @@ impl Configuration {
|
|||
debug!(" - debugging : {}", debugging);
|
||||
debug!(" - store sub : {}", store_sub);
|
||||
debug!(" - runtimepath: {}", runtimepath);
|
||||
debug!(" - editor : {:?}", editor);
|
||||
debug!(" - editor-opts: {}", editor_opts);
|
||||
|
||||
Configuration {
|
||||
verbose: verbose,
|
||||
debugging: debugging,
|
||||
store_sub: store_sub,
|
||||
rtp: runtimepath,
|
||||
editor: editor,
|
||||
editor_opts: editor_opts,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +79,14 @@ impl Configuration {
|
|||
self.rtp.clone()
|
||||
}
|
||||
|
||||
pub fn editor(&self) -> Option<String> {
|
||||
self.editor.clone()
|
||||
}
|
||||
|
||||
pub fn editor_opts(&self) -> &String {
|
||||
&self.editor_opts
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn rtp_path(config: &CliConfig) -> Option<String> {
|
||||
|
|
|
@ -92,6 +92,20 @@ impl<'a> Runtime<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn editor(&self) -> String {
|
||||
use std::env::var;
|
||||
|
||||
if let Some(editor) = self.config.editor() {
|
||||
editor + &self.config.editor_opts()[..]
|
||||
} else if let Some(editor) = self.configuration.editor() {
|
||||
editor + &self.configuration.editor_opts()[..]
|
||||
} else if let Ok(editor) = var("EDITOR") {
|
||||
editor
|
||||
} else {
|
||||
String::from("vim")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl<'a> Debug for Runtime<'a> {
|
||||
|
|
61
src/ui/external/editor.rs
vendored
Normal file
61
src/ui/external/editor.rs
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
use std::ops::Drop;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::fs::File;
|
||||
use std::error::Error;
|
||||
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::fmt;
|
||||
|
||||
use runtime::Runtime;
|
||||
|
||||
/**
|
||||
* A function which lets the user provide content by editing a temp files which gets removed after
|
||||
* the function got the content from it.
|
||||
*/
|
||||
pub fn let_user_provide_content(rt: &Runtime) -> Option<String> {
|
||||
use std::io::Read;
|
||||
use std::fs::File;
|
||||
use std::process::Command;
|
||||
use std::process::Child;
|
||||
|
||||
let filepath = "/tmp/imag-tmp.md";
|
||||
let file_created = File::create(filepath)
|
||||
.map(|_| true)
|
||||
.unwrap_or(false);
|
||||
|
||||
if !file_created {
|
||||
warn!("Could not create temporary file for user input!");
|
||||
return None;
|
||||
}
|
||||
|
||||
let output = {
|
||||
let mut cmd = Command::new(rt.editor());
|
||||
cmd.arg(filepath);
|
||||
debug!("cmd = {:?}", cmd);
|
||||
cmd.spawn()
|
||||
.and_then(|child| {
|
||||
child.wait_with_output()
|
||||
})
|
||||
};
|
||||
|
||||
let process_out = output.map_err(|e| {
|
||||
error!("Editor call failed");
|
||||
debug!("Editor call failed: {:?}", e);
|
||||
return None as Option<String>;
|
||||
}).unwrap();
|
||||
|
||||
if !process_out.status.success() {
|
||||
error!("Editor call failed");
|
||||
debug!("status = {:?}", process_out.status);
|
||||
debug!("stdout = {:?}", String::from_utf8(process_out.stdout));
|
||||
debug!("stderr = {:?}", String::from_utf8(process_out.stderr));
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut contents = String::new();
|
||||
File::open(filepath).map(|mut file| {
|
||||
file.read_to_string(&mut contents);
|
||||
Some(contents)
|
||||
}).unwrap_or(None)
|
||||
}
|
1
src/ui/external/mod.rs
vendored
Normal file
1
src/ui/external/mod.rs
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod editor;
|
|
@ -1 +1,2 @@
|
|||
pub mod file;
|
||||
pub mod external;
|
||||
|
|
Loading…
Reference in a new issue