1use crate::core::code::UnOptCode;
2use crate::core::parse;
3use crate::number::number::Num;
4use crate::util::error::Error;
5use crate::util::io;
6use crate::util::option::HyeongOption;
7use std::io::Write;
8use std::io::{BufRead, BufReader};
9use std::path::PathBuf;
10use std::process::{Command, Stdio};
11use termcolor::StandardStream;
12
13pub fn path_to_string(path: &PathBuf) -> Result<String, Error> {
24 path.clone().into_os_string().into_string().map_err(|_| {
25 Error::new(
26 "error on OsString to String conversion",
27 "maybe the path is not correct",
28 )
29 })
30}
31
32pub fn parse_file(
48 stdout: &mut StandardStream,
49 path: &PathBuf,
50 option: &HyeongOption,
51) -> Result<Vec<UnOptCode>, Error> {
52 let raw_code = io::read_file(path)?;
53 io::print_log(stdout, format!("parsing {}", path_to_string(path)?))?;
54 let un_opt_code = parse::parse(raw_code);
55 if option.verbose {
56 io::print_log(stdout, format!("⮑ total {} commands", un_opt_code.len()))?;
57 }
58 Ok(un_opt_code)
59}
60
61pub fn num_to_unicode(num: &Num) -> Result<char, Error> {
76 let n = num.floor().to_int();
77 std::char::from_u32(n).ok_or(Error::new(
78 "utf-8 encoding error",
79 format!("number {} is not valid unicode", n),
80 ))
81}
82
83#[cfg(not(tarpaulin_include))]
85pub fn execute_command_stdout(w: &mut StandardStream, command: &str) -> Result<(), Error> {
86 let mut cmd = if cfg!(target_os = "windows") {
87 Command::new("cmd")
88 .arg("/C")
89 .arg(command)
90 .stdout(Stdio::piped())
91 .spawn()?
92 } else {
93 Command::new("bash")
94 .arg("-c")
95 .arg(command)
96 .stdout(Stdio::piped())
97 .spawn()?
98 };
99
100 let stdout = cmd.stdout.as_mut().unwrap();
101 let stdout_reader = BufReader::new(stdout);
102
103 for line in stdout_reader.lines() {
104 write!(w, "{}\n", line?)?;
105 }
106
107 let e = cmd.wait()?;
108
109 if e.success() {
110 Ok(())
111 } else {
112 match e.code() {
113 Some(code) => Err(Error::new(
114 format!("command {} failed with exit code {}", command, code),
115 "",
116 )),
117 None => Err(Error::new(
118 format!("command {} terminated by signal", command),
119 "",
120 )),
121 }
122 }
123}
124
125#[cfg(not(tarpaulin_include))]
127pub fn execute_command_stderr(w: &mut StandardStream, command: &str) -> Result<(), Error> {
128 let mut cmd = if cfg!(target_os = "windows") {
129 Command::new("cmd")
130 .arg("/C")
131 .arg(command)
132 .stderr(Stdio::piped())
133 .spawn()?
134 } else {
135 Command::new("bash")
136 .arg("-c")
137 .arg(command)
138 .stderr(Stdio::piped())
139 .spawn()?
140 };
141
142 let stdout = cmd.stderr.as_mut().unwrap();
143 let stdout_reader = BufReader::new(stdout);
144
145 for line in stdout_reader.lines() {
146 write!(w, "{}\n", line?)?;
147 }
148
149 let e = cmd.wait()?;
150
151 if e.success() {
152 Ok(())
153 } else {
154 match e.code() {
155 Some(code) => Err(Error::new(
156 format!("command {} failed with exit code {}", command, code),
157 "",
158 )),
159 None => Err(Error::new(
160 format!("command {} terminated by signal", command),
161 "",
162 )),
163 }
164 }
165}