1use std::path::PathBuf;
2
3use clap::Args;
4use eyre::{OptionExt, Result};
5use lux_lib::project::Project;
6use stylua_lib::Config;
7use walkdir::WalkDir;
8
9#[derive(Args)]
10pub struct Fmt {
11 workspace_or_file: Option<PathBuf>,
13}
14
15pub fn format(args: Fmt) -> Result<()> {
17 let project = Project::current()?.ok_or_eyre(
18 "`lx fmt` can only be executed in a lux project! Run `lx new` to create one.",
19 )?;
20
21 let config: Config = std::fs::read_to_string("stylua.toml")
22 .or_else(|_| std::fs::read_to_string(".stylua.toml"))
23 .map(|config: String| toml::from_str(&config).unwrap_or_default())
24 .unwrap_or_default();
25
26 WalkDir::new(project.root().join("src"))
27 .into_iter()
28 .chain(WalkDir::new(project.root().join("lua")))
29 .chain(WalkDir::new(project.root().join("lib")))
30 .filter_map(Result::ok)
31 .filter(|file| {
32 args.workspace_or_file
33 .as_ref()
34 .is_none_or(|workspace_or_file| {
35 file.path().to_path_buf().starts_with(workspace_or_file)
36 })
37 })
38 .try_for_each(|file| {
39 if PathBuf::from(file.file_name())
40 .extension()
41 .is_some_and(|ext| ext == "lua")
42 {
43 let formatted_code = stylua_lib::format_code(
44 &std::fs::read_to_string(file.path())?,
45 config,
46 None,
47 stylua_lib::OutputVerification::Full,
48 )?;
49
50 std::fs::write(file.into_path(), formatted_code)?;
51 };
52 Ok::<_, eyre::Report>(())
53 })?;
54
55 let rockspec = project.root().join("extra.rockspec");
58
59 if rockspec.exists() {
60 let formatted_code = stylua_lib::format_code(
61 &std::fs::read_to_string(&rockspec)?,
62 config,
63 None,
64 stylua_lib::OutputVerification::Full,
65 )?;
66
67 std::fs::write(rockspec, formatted_code)?;
68 }
69
70 Ok(())
71}