Skip to content

Commit

Permalink
Made improvements to litho-cli.
Browse files Browse the repository at this point in the history
  • Loading branch information
cutsoy committed Dec 28, 2022
1 parent 2a151d8 commit 7026116
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 104 deletions.
1 change: 1 addition & 0 deletions litho-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ litho-language = { path = "../litho-language" }
ariadne = "0.1.5"
glob = "0.3.0"
smol_str = "0.1.23"
yansi = "0.5.1"

[build-dependencies]
vergen = "7.4.4"
105 changes: 2 additions & 103 deletions litho-cli/src/bin/litho.rs
Original file line number Diff line number Diff line change
@@ -1,108 +1,7 @@
use std::collections::HashMap;
use std::env::args;
use std::fmt::Display;
use std::fs::read_to_string;
use std::process::ExitCode;

use ariadne::{Cache, Label, Report, ReportKind, Source};
use glob::glob;
use litho_compiler::{builtins, Compiler};
use litho_language::lex::{SourceId, SourceMap, Span};
use smol_str::SmolStr;

#[derive(Default)]
pub struct Sources(HashMap<SourceId, (String, Source)>);

impl Sources {
pub fn insert(&mut self, source_id: SourceId, path: String, source: Source) {
self.0.insert(source_id, (path, source));
}
}

impl Cache<SourceId> for Sources {
fn display<'a>(&self, id: &'a SourceId) -> Option<Box<dyn Display + 'a>> {
self.0
.get(id)
.map(|(path, _)| Box::new(path.clone()) as Box<dyn Display>)
}

fn fetch(&mut self, id: &SourceId) -> Result<&Source, Box<dyn std::fmt::Debug + '_>> {
self.0.get(id).map(|(_, text)| Ok(text)).unwrap()
}
}
use litho_cli::cli;

pub fn main() -> ExitCode {
let mut inputs = vec![];
let mut args = args().skip(1);

while let Some(arg) = args.next() {
match arg.as_str() {
"--version" | "-v" | "version" => {
println!(
"litho {} ({} {})",
env!("CARGO_PKG_VERSION"),
env!("VERGEN_GIT_SHA_SHORT"),
env!("VERGEN_GIT_COMMIT_DATE")
);

return ExitCode::SUCCESS;
}
arg => inputs.extend(
glob(&arg)
.into_iter()
.flatten()
.map(IntoIterator::into_iter)
.flatten()
.map(|path| path.to_string_lossy().into_owned()),
),
}
}

let mut compiler = Compiler::<SmolStr>::new();
let mut source_map = SourceMap::new();
let mut sources = Sources::default();

for (path, text) in builtins().into_iter().copied() {
let source_id = source_map.get_or_insert(path.to_owned());
sources.insert(source_id, path.to_owned(), Source::from(&text));
compiler.add_document(source_id, &text, true);
}

for input in inputs.iter() {
let source_id = source_map.get_or_insert(input.clone());
let text = read_to_string(input.clone()).unwrap();
sources.insert(source_id, input.clone(), Source::from(&text));
compiler.add_document(source_id, &text, true);
}

compiler.rebuild();

let mut code = ExitCode::SUCCESS;

for input in inputs.iter() {
let Some(source_id) = source_map.get(&input) else {
continue
};

let diagnostics = compiler.diagnostics(source_id);

for diagnostic in diagnostics {
let span = diagnostic.span();
let mut builder = Report::<Span>::build(ReportKind::Error, span.source_id, span.start)
.with_code(diagnostic.code())
.with_message(diagnostic.message());
builder.add_labels(
diagnostic
.labels()
.into_iter()
.map(|(span, message)| Label::new(span).with_message(message)),
);
builder.finish().eprint(&mut sources).unwrap();
eprintln!("");

code = ExitCode::FAILURE;
}
}

code
cli()
}
16 changes: 16 additions & 0 deletions litho-cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use std::env::args;
use std::process::ExitCode;

use super::commands;

pub fn cli() -> ExitCode {
let command = args().skip(1).next();

match command.as_deref() {
Some("generate") => {}
Some("--version" | "-v" | "version") => return commands::version(),
_ => {}
}

commands::generate()
}
96 changes: 96 additions & 0 deletions litho-cli/src/commands/generate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use std::env::args;
use std::fs::{metadata, write};
use std::process::ExitCode;

use ariadne::{Label, Report, ReportKind};
use litho_language::fmt::Format;
use litho_language::lex::Span;
use yansi::Paint;

use crate::Workspace;

#[derive(Default)]
pub struct Options {
fix: bool,
format: bool,
}

pub enum FormattingError {
Unformatted,
Changed,
}

pub fn generate() -> ExitCode {
let mut inputs = vec![];
let mut options = Options::default();

for arg in args().skip(1) {
match arg.as_str() {
"--fix" => options.fix = true,
"--fmt" | "--format" => options.format = true,
_ => inputs.push(arg),
}
}

let workspace = Workspace::new(inputs);

let mut files = workspace.files().collect::<Vec<_>>();
files.sort_by_key(|file| file.path);

let mut sources = workspace.to_sources();

let mut code = ExitCode::SUCCESS;

for file in files {
let formatted = file.document.format_to_string(80);
if &formatted != file.text {
let formatting_error = if options.fix {
let modified = metadata(file.path).and_then(|metadata| metadata.modified());

if file.modified.as_ref().ok() != modified.as_ref().ok() {
Some(FormattingError::Changed)
} else {
write(file.path, formatted).unwrap();
None
}
} else {
Some(FormattingError::Unformatted)
};

if let Some(diagnostic) = formatting_error {
eprintln!(
"{} {}\n {}{}{}\n",
Paint::red("[E0000] Error:"),
match diagnostic {
FormattingError::Changed => "File has changed on disk while formatting.",
FormattingError::Unformatted => "File must be formatted.",
},
Paint::new("──[").dimmed(),
file.path,
Paint::new("]").dimmed(),
);

code = ExitCode::FAILURE;
}
}

for diagnostic in workspace.compiler().diagnostics(file.source_id).cloned() {
let span = diagnostic.span();
let mut builder = Report::<Span>::build(ReportKind::Error, span.source_id, span.start)
.with_code(diagnostic.code())
.with_message(diagnostic.message());
builder.add_labels(
diagnostic
.labels()
.into_iter()
.map(|(span, message)| Label::new(span).with_message(message)),
);
builder.finish().eprint(&mut sources).unwrap();
eprintln!("");

code = ExitCode::FAILURE;
}
}

code
}
5 changes: 5 additions & 0 deletions litho-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod generate;
mod version;

pub use generate::generate;
pub use version::version;
12 changes: 12 additions & 0 deletions litho-cli/src/commands/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use std::process::ExitCode;

pub fn version() -> ExitCode {
println!(
"litho {} ({} {})",
env!("CARGO_PKG_VERSION"),
env!("VERGEN_GIT_SHA_SHORT"),
env!("VERGEN_GIT_COMMIT_DATE")
);

ExitCode::SUCCESS
}
6 changes: 6 additions & 0 deletions litho-cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
mod cli;
pub mod commands;
mod workspace;

pub use cli::cli;
pub use workspace::Workspace;
Loading

0 comments on commit 7026116

Please sign in to comment.