cursive_open_editor/
lib.rs1pub mod strategy;
2
3use std::{
4 ffi::OsString,
5 fs::File,
6 io::{self, Read},
7 path::PathBuf,
8 process::{Command, ExitStatus},
9};
10
11use cursive::Cursive;
12use strategy::{EditPathStrategy, EditPathStrategyOut, FindEditorStrategy};
13
14pub struct CursiveOpenEditorOptions {
16 pub editor_strategy: FindEditorStrategy,
20 pub additional_args: Vec<OsString>,
24 pub edit_path_strategy: EditPathStrategy,
27}
28
29impl Default for CursiveOpenEditorOptions {
30 fn default() -> Self {
31 Self {
32 editor_strategy: FindEditorStrategy::default(),
33 edit_path_strategy: EditPathStrategy::default(),
34 additional_args: Vec::new(),
35 }
36 }
37}
38
39pub fn open_editor(
42 siv: &mut Cursive,
43 options: CursiveOpenEditorOptions,
44) -> io::Result<EditorOpened> {
45 let editor_path = options.editor_strategy.editor_path().ok_or_else(|| {
46 io::Error::new(
47 io::ErrorKind::NotFound,
48 "could not find an editor to launch",
49 )
50 })?;
51 let edit_path = options.edit_path_strategy.file_path()?;
52
53 let dump = siv.dump();
54 siv.clear();
55
56 let mut cmd_builder = Command::new(editor_path);
57 cmd_builder.args(&options.additional_args);
58 cmd_builder.arg(&edit_path.path());
59
60 let mut kid = cmd_builder.spawn()?;
62 let status = kid.wait()?;
63
64 siv.restore(dump);
65 Ok(EditorOpened {
66 status,
67 edited_path: edit_path,
68 })
69}
70
71pub struct EditorOpened {
73 pub status: ExitStatus,
74 pub edited_path: EditPathStrategyOut,
75}
76
77impl EditorOpened {
78 pub fn status_ok(&self) -> io::Result<()> {
84 if self.status.success() {
85 Ok(())
86 } else {
87 Err(io::Error::other(format!("non-OK exit: {}", &self.status)))
88 }
89 }
90
91 pub fn edited_file(&self) -> io::Result<File> {
93 let path = self.edited_path.path();
94 File::open(&path)
95 }
96
97 pub fn edited_path(&self) -> PathBuf {
99 self.edited_path.path()
100 }
101
102 pub fn read_to_string(&self) -> io::Result<String> {
104 let mut s = String::new();
105 self.edited_file()?.read_to_string(&mut s)?;
106 Ok(s)
107 }
108}