mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
Support roc format
to stdout/from stdin
This commit is contained in:
parent
77d2136d00
commit
e442f18e68
3 changed files with 272 additions and 133 deletions
|
@ -1,11 +1,12 @@
|
|||
//! The `roc` binary that brings together all functionality in the Roc toolset.
|
||||
use bumpalo::Bump;
|
||||
use roc_build::link::LinkType;
|
||||
use roc_build::program::{check_file, CodeGenBackend};
|
||||
use roc_cli::{
|
||||
build_app, format, test, BuildConfig, FormatMode, CMD_BUILD, CMD_CHECK, CMD_DEV, CMD_DOCS,
|
||||
CMD_FORMAT, CMD_GEN_STUB_LIB, CMD_GLUE, CMD_REPL, CMD_RUN, CMD_TEST, CMD_VERSION,
|
||||
DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB, FLAG_NO_LINK, FLAG_TARGET, FLAG_TIME,
|
||||
GLUE_DIR, GLUE_SPEC, ROC_FILE,
|
||||
build_app, format_files, format_src, test, BuildConfig, FormatMode, CMD_BUILD, CMD_CHECK,
|
||||
CMD_DEV, CMD_DOCS, CMD_FORMAT, CMD_GEN_STUB_LIB, CMD_GLUE, CMD_REPL, CMD_RUN, CMD_TEST,
|
||||
CMD_VERSION, DIRECTORY_OR_FILES, FLAG_CHECK, FLAG_DEV, FLAG_LIB, FLAG_NO_LINK, FLAG_STDIN,
|
||||
FLAG_STDOUT, FLAG_TARGET, FLAG_TIME, GLUE_DIR, GLUE_SPEC, ROC_FILE,
|
||||
};
|
||||
use roc_docs::generate_docs_html;
|
||||
use roc_error_macros::user_error;
|
||||
|
@ -15,7 +16,7 @@ use roc_load::{FunctionKind, LoadingProblem, Threading};
|
|||
use roc_packaging::cache::{self, RocCacheDir};
|
||||
use roc_target::Target;
|
||||
use std::fs::{self, FileType};
|
||||
use std::io;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use target_lexicon::Triple;
|
||||
|
@ -151,7 +152,7 @@ fn main() -> io::Result<()> {
|
|||
)?)
|
||||
}
|
||||
Some((CMD_CHECK, matches)) => {
|
||||
let arena = bumpalo::Bump::new();
|
||||
let arena = Bump::new();
|
||||
|
||||
let emit_timings = matches.get_flag(FLAG_TIME);
|
||||
let roc_file_path = matches.get_one::<PathBuf>(ROC_FILE).unwrap();
|
||||
|
@ -219,46 +220,102 @@ fn main() -> io::Result<()> {
|
|||
Ok(0)
|
||||
}
|
||||
Some((CMD_FORMAT, matches)) => {
|
||||
let maybe_values = matches.get_many::<OsString>(DIRECTORY_OR_FILES);
|
||||
|
||||
let mut values: Vec<OsString> = Vec::new();
|
||||
|
||||
match maybe_values {
|
||||
None => {
|
||||
let mut os_string_values: Vec<OsString> = Vec::new();
|
||||
read_all_roc_files(
|
||||
&std::env::current_dir()?.as_os_str().to_os_string(),
|
||||
&mut os_string_values,
|
||||
)?;
|
||||
for os_string in os_string_values {
|
||||
values.push(os_string);
|
||||
}
|
||||
let from_stdin = matches.get_flag(FLAG_STDIN);
|
||||
let to_stdout = matches.get_flag(FLAG_STDOUT);
|
||||
let format_mode = if to_stdout {
|
||||
FormatMode::WriteToStdout
|
||||
} else {
|
||||
match matches.get_flag(FLAG_CHECK) {
|
||||
true => FormatMode::CheckOnly,
|
||||
false => FormatMode::WriteToFile,
|
||||
}
|
||||
Some(os_values) => {
|
||||
for os_string in os_values {
|
||||
values.push(os_string.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut roc_files = Vec::new();
|
||||
|
||||
// Populate roc_files
|
||||
for os_str in values {
|
||||
let metadata = fs::metadata(os_str.clone())?;
|
||||
roc_files_recursive(os_str.as_os_str(), metadata.file_type(), &mut roc_files)?;
|
||||
}
|
||||
|
||||
let format_mode = match matches.get_flag(FLAG_CHECK) {
|
||||
true => FormatMode::CheckOnly,
|
||||
false => FormatMode::Format,
|
||||
};
|
||||
|
||||
let format_exit_code = match format(roc_files, format_mode) {
|
||||
Ok(_) => 0,
|
||||
Err(message) => {
|
||||
eprintln!("{message}");
|
||||
1
|
||||
if from_stdin && matches!(format_mode, FormatMode::WriteToFile) {
|
||||
eprintln!("When using the --stdin flag, either the --check or the --stdout flag must also be specified. (Otherwise, it's unclear what filename to write to!)");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let roc_files = {
|
||||
let mut roc_files = Vec::new();
|
||||
|
||||
let mut values: Vec<OsString> = Vec::new();
|
||||
|
||||
match matches.get_many::<OsString>(DIRECTORY_OR_FILES) {
|
||||
Some(os_values) => {
|
||||
for os_string in os_values {
|
||||
values.push(os_string.to_owned());
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let mut os_string_values: Vec<OsString> = Vec::new();
|
||||
|
||||
read_all_roc_files(
|
||||
&std::env::current_dir()?.as_os_str().to_os_string(),
|
||||
&mut os_string_values,
|
||||
)?;
|
||||
|
||||
for os_string in os_string_values {
|
||||
values.push(os_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate roc_files
|
||||
for os_str in values {
|
||||
let metadata = fs::metadata(os_str.clone())?;
|
||||
roc_files_recursive(os_str.as_os_str(), metadata.file_type(), &mut roc_files)?;
|
||||
}
|
||||
|
||||
roc_files
|
||||
};
|
||||
|
||||
let format_exit_code = if from_stdin {
|
||||
let mut buf = Vec::new();
|
||||
let arena = Bump::new();
|
||||
|
||||
io::stdin().read_to_end(&mut buf)?;
|
||||
|
||||
let src = std::str::from_utf8(&buf).unwrap_or_else(|err| {
|
||||
eprintln!("Stdin contained invalid UTF-8 bytes: {err:?}");
|
||||
std::process::exit(1);
|
||||
});
|
||||
|
||||
match format_src(&arena, src) {
|
||||
Ok(formatted_src) => {
|
||||
match format_mode {
|
||||
FormatMode::CheckOnly => {
|
||||
if src == formatted_src {
|
||||
eprintln!("One or more files need to be reformatted.");
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
FormatMode::WriteToStdout => {
|
||||
std::io::stdout().lock().write_all(src.as_bytes()).unwrap();
|
||||
|
||||
0
|
||||
}
|
||||
FormatMode::WriteToFile => {
|
||||
// We would have errored out already if you specified --stdin
|
||||
// without either --stdout or --check specified as well.
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(problem) => {
|
||||
eprintln!("`roc format` failed: {problem:?}");
|
||||
1
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match format_files(roc_files, format_mode) {
|
||||
Ok(()) => 0,
|
||||
Err(message) => {
|
||||
eprintln!("{message}");
|
||||
1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue