1use std::env;
2use std::fs::{self};
3use std::io::{self, Write};
4use std::process::{Command, Stdio};
5use tempfile::NamedTempFile;
6
7use atty::is as is_atty;
9
10const VERSION: &str = "1.0.0";
14
15pub fn run() -> Result<(), Box<dyn std::error::Error>> {
16 let args: Vec<String> = env::args().collect();
17 if args.len() > 1 {
18 match args[1].as_str() {
19 "-a" => {
20 println!("about:");
22 println!(" https://github.com/madx/moreutils.git");
23 println!(" https://raw.githubusercontent.com/madx/moreutils/refs/heads/master/vipe");
24 println!(" https://github.com/juliangruber/vipe.git");
25 println!(" https://raw.githubusercontent.com/juliangruber/vipe/refs/heads/master/vipe.sh");
26 return Ok(());
27 }
28 "--about" => {
29 println!("about:");
31 println!(" https://github.com/madx/moreutils.git");
32 println!(" https://raw.githubusercontent.com/madx/moreutils/refs/heads/master/vipe");
33 println!(" https://github.com/juliangruber/vipe.git");
34 println!(" https://raw.githubusercontent.com/juliangruber/vipe/refs/heads/master/vipe.sh");
35 return Ok(());
36 }
37 "-h" => {
38 println!("usage: vipe [-ahV]");
40 return Ok(());
41 }
42 "--help" => {
43 println!("usage: vipe [-ahV]");
45 return Ok(());
46 }
47 "-V" => {
48 println!("{}", VERSION);
50 return Ok(());
51 }
52 "--version" => {
53 println!("{}", VERSION);
55 return Ok(());
56 }
57 _ => {
58 eprintln!("unknown option: \"{}\"", args[1]);
60 eprintln!("usage: vipe [-hV]");
61 std::process::exit(1);
62 }
63 }
64 }
65
66 let editor = env::var("EDITOR").unwrap_or_else(|_| {
67 if cfg!(windows) {
68 "notepad.exe".to_string()
69 } else {
70 "vi".to_string()
71 }
72 });
73
74 let mut temp_file = NamedTempFile::new()?;
75 let temp_path = temp_file.path().to_owned();
76 if !is_atty(atty::Stream::Stdin) {
77 let mut stdin = io::stdin();
78 io::copy(&mut stdin, &mut temp_file)?;
79 }
80
81 temp_file.flush()?;
82
83 let status = Command::new(&editor)
84 .arg(&temp_path)
85 .stdin(Stdio::inherit())
86 .stdout(Stdio::inherit())
87 .stderr(Stdio::inherit())
88 .status()?;
89
90 if !status.success() {
91 eprintln!("Editor exited with non-zero status: {:?}", status.code());
92 std::process::exit(status.code().unwrap_or(1));
93 }
94
95 let content = fs::read_to_string(&temp_path)?;
96
97 print!("{}", content);
98
99 Ok(())
100}