Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement 'roc format <dir_or_files>' command #2066

Merged
merged 2 commits into from
Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions cli/src/format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::path::PathBuf;

use bumpalo::collections::String;
use bumpalo::Bump;
use roc_fmt::def::fmt_def;
use roc_fmt::module::fmt_module;
use roc_parse::{
module::{self, module_defs},
parser::{Parser, State},
};
use roc_reporting::user_error;

pub fn format(files: Vec<PathBuf>) {
for file in files {
let arena = Bump::new();

let src = std::fs::read_to_string(&file).unwrap();

match module::parse_header(&arena, State::new(src.as_bytes())) {
Ok((result, state)) => {
let mut buf = String::new_in(&arena);

fmt_module(&mut buf, &result);

match module_defs().parse(&arena, state) {
Ok((_, loc_defs, _)) => {
for loc_def in loc_defs {
fmt_def(&mut buf, arena.alloc(loc_def.value), 0);
}
}
Err(error) => user_error!("Unexpected parse failure when parsing this for defs formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", src, error)
}

std::fs::write(&file, buf).unwrap();
}
Err(error) => user_error!("Unexpected parse failure when parsing this for module header formatting:\n\n{:?}\n\nParse error was:\n\n{:?}\n\n", src, error)
};
}
}
15 changes: 14 additions & 1 deletion cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,25 @@ use roc_load::file::LoadingProblem;
use roc_mono::ir::OptLevel;
use std::env;
use std::io;
use std::path::{Path, PathBuf};
use std::path::Path;
use std::path::PathBuf;
use std::process;
use std::process::Command;
use target_lexicon::BinaryFormat;
use target_lexicon::{Architecture, OperatingSystem, Triple, X86_32Architecture};

pub mod build;
mod format;
pub mod repl;
pub use format::format;

pub const CMD_BUILD: &str = "build";
pub const CMD_REPL: &str = "repl";
pub const CMD_EDIT: &str = "edit";
pub const CMD_DOCS: &str = "docs";
pub const CMD_CHECK: &str = "check";
pub const CMD_VERSION: &str = "version";
pub const CMD_FORMAT: &str = "format";

pub const FLAG_DEBUG: &str = "debug";
pub const FLAG_DEV: &str = "dev";
Expand All @@ -35,6 +39,7 @@ pub const FLAG_LINK: &str = "roc-linker";
pub const FLAG_PRECOMPILED: &str = "precompiled-host";
pub const FLAG_VALGRIND: &str = "valgrind";
pub const ROC_FILE: &str = "ROC_FILE";
pub const ROC_DIR: &str = "ROC_DIR";
pub const BACKEND: &str = "BACKEND";
pub const DIRECTORY_OR_FILES: &str = "DIRECTORY_OR_FILES";
pub const ARGS_FOR_APP: &str = "ARGS_FOR_APP";
Expand Down Expand Up @@ -111,6 +116,14 @@ pub fn build_app<'a>() -> App<'a> {
.subcommand(App::new(CMD_REPL)
.about("Launch the interactive Read Eval Print Loop (REPL)")
)
.subcommand(App::new(CMD_FORMAT)
.about("Format Roc code")
.arg(
Arg::new(DIRECTORY_OR_FILES)
.index(1)
.multiple_values(true)
.required(false))
)
.subcommand(App::new(CMD_VERSION)
.about("Print version information")
)
Expand Down
47 changes: 44 additions & 3 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use roc_cli::build::check_file;
use roc_cli::{
build_app, docs, repl, BuildConfig, CMD_BUILD, CMD_CHECK, CMD_DOCS, CMD_EDIT, CMD_REPL,
CMD_VERSION, DIRECTORY_OR_FILES, FLAG_TIME, ROC_FILE,
build_app, docs, format, repl, BuildConfig, CMD_BUILD, CMD_CHECK, CMD_DOCS, CMD_EDIT,
CMD_FORMAT, CMD_REPL, CMD_VERSION, DIRECTORY_OR_FILES, FLAG_TIME, ROC_FILE,
};
use roc_load::file::LoadingProblem;
use std::fs::{self, FileType};
Expand Down Expand Up @@ -101,7 +101,10 @@ fn main() -> io::Result<()> {
match maybe_values {
None => {
let mut os_string_values: Vec<OsString> = Vec::new();
read_all_roc_files(&OsStr::new("./").to_os_string(), &mut os_string_values)?;
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);
}
Expand All @@ -125,6 +128,44 @@ fn main() -> io::Result<()> {

Ok(0)
}
Some(CMD_FORMAT) => {
let maybe_values = matches
.subcommand_matches(CMD_FORMAT)
.unwrap()
.values_of_os(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);
}
}
Some(os_values) => {
for os_str in os_values {
values.push(os_str.to_os_string());
}
}
}

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)?;
}

format(roc_files);

Ok(0)
}
Some(CMD_VERSION) => {
println!("roc {}", concatcp!(include_str!("../../version.txt"), "\n"));

Expand Down