Fmt config
This commit is contained in:
Generated
+1
@@ -488,6 +488,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"toml",
|
||||||
"tower-lsp",
|
"tower-lsp",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -22,3 +22,4 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
ropey = "1"
|
ropey = "1"
|
||||||
heck = "0.5.0"
|
heck = "0.5.0"
|
||||||
|
toml = "1.1.2"
|
||||||
|
|||||||
+41
-16
@@ -7,10 +7,11 @@ use std::sync::Arc;
|
|||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
|
||||||
use heck::ToSnakeCase;
|
use heck::ToSnakeCase;
|
||||||
|
use mist_parser::MistFmtConfig;
|
||||||
use mist_parser::error::ParseError;
|
use mist_parser::error::ParseError;
|
||||||
use mist_parser::rev_mapper::{Mapping, MistMap, RustMap};
|
use mist_parser::rev_mapper::{Mapping, MistMap, RustMap};
|
||||||
use ropey::Rope;
|
use ropey::Rope;
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tower_lsp::lsp_types::{self, *};
|
use tower_lsp::lsp_types::{self, *};
|
||||||
@@ -1357,7 +1358,17 @@ impl LanguageServer for Backend {
|
|||||||
.get(&mist_path)
|
.get(&mist_path)
|
||||||
.map_or_else(|| Err(tower_lsp::jsonrpc::Error::internal_error()), Ok)?;
|
.map_or_else(|| Err(tower_lsp::jsonrpc::Error::internal_error()), Ok)?;
|
||||||
|
|
||||||
let new_text = format_mist(&old_text.to_string())
|
let ws = match &*self.workspace_folder.lock().await {
|
||||||
|
Some(p) => p.clone(),
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_text = format_mist(
|
||||||
|
&old_text.to_string(),
|
||||||
|
read_mist_fmt(&ws).unwrap_or_else(|| MistFmtConfig {
|
||||||
|
allman_bracket_style: true,
|
||||||
|
}),
|
||||||
|
)
|
||||||
.map_err(|_| tower_lsp::jsonrpc::Error::internal_error())?;
|
.map_err(|_| tower_lsp::jsonrpc::Error::internal_error())?;
|
||||||
|
|
||||||
Ok(Some(vec![TextEdit {
|
Ok(Some(vec![TextEdit {
|
||||||
@@ -1820,24 +1831,38 @@ fn read_mist_package(workspace_root: &Path) -> String {
|
|||||||
let toml_path = workspace_root.join("Mist.toml");
|
let toml_path = workspace_root.join("Mist.toml");
|
||||||
let content = match std::fs::read_to_string(&toml_path) {
|
let content = match std::fs::read_to_string(&toml_path) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(_) => return "main.mist".to_string(),
|
Err(_) => {
|
||||||
|
return "main.mist".to_string();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
for line in content.lines() {
|
|
||||||
let line = line.trim();
|
toml::from_str::<MistConfig>(&content)
|
||||||
if let Some(rest) = line.strip_prefix("package") {
|
.ok()
|
||||||
if let Some(eq_pos) = rest.find('=') {
|
.and_then(|v| v.package.to_str().map(String::from))
|
||||||
let val = rest[eq_pos + 1..]
|
.unwrap_or_else(|| "main.mist".to_string())
|
||||||
.trim()
|
|
||||||
.trim_matches('"')
|
|
||||||
.trim()
|
|
||||||
.to_string();
|
|
||||||
if !val.is_empty() {
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct MistConfig {
|
||||||
|
pub package: PathBuf,
|
||||||
|
pub packages: Vec<PathBuf>,
|
||||||
|
pub fmt: Option<MistFmtConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_mist_fmt(workspace_root: &Path) -> Option<MistFmtConfig> {
|
||||||
|
let toml_path = workspace_root.join("Mist.toml");
|
||||||
|
let content = match std::fs::read_to_string(&toml_path) {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(_) => {
|
||||||
|
return Some(MistFmtConfig {
|
||||||
|
allman_bracket_style: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
"main.mist".to_string()
|
|
||||||
|
toml::from_str::<MistConfig>(&content)
|
||||||
|
.ok()
|
||||||
|
.and_then(|v| v.fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_mod_decls(
|
fn compute_mod_decls(
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use mist_codegen::fmt::MistCodegen;
|
|
||||||
use mist_codegen::RustCodegen;
|
use mist_codegen::RustCodegen;
|
||||||
use mist_parser::parse;
|
use mist_codegen::fmt::MistCodegen;
|
||||||
use mist_parser::rev_mapper::Mapping;
|
use mist_parser::rev_mapper::Mapping;
|
||||||
|
use mist_parser::{MistFmtConfig, parse};
|
||||||
|
|
||||||
pub struct TranspiledFile {
|
pub struct TranspiledFile {
|
||||||
pub mist_path: PathBuf,
|
pub mist_path: PathBuf,
|
||||||
@@ -85,10 +85,10 @@ pub fn transpile_mist_no_sem(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format_mist(source: &str) -> Result<String, String> {
|
pub fn format_mist(source: &str, config: MistFmtConfig) -> Result<String, String> {
|
||||||
let parsed = parse(source).map_err(|e| format!("parse error: {e:?}"))?;
|
let parsed = parse(source).map_err(|e| format!("parse error: {e:?}"))?;
|
||||||
|
|
||||||
let mut codegen = MistCodegen::new();
|
let mut codegen = MistCodegen::new(config);
|
||||||
codegen.generate(parsed.mod_attributes);
|
codegen.generate(parsed.mod_attributes);
|
||||||
let output = codegen.generate(parsed.items);
|
let output = codegen.generate(parsed.items);
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,23 @@ pub mod expr;
|
|||||||
pub mod statement;
|
pub mod statement;
|
||||||
pub mod top_level;
|
pub mod top_level;
|
||||||
|
|
||||||
use mist_parser::ast::*;
|
use mist_parser::{MistFmtConfig, ast::*};
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub expr_ensure_semicolon: bool,
|
pub expr_ensure_semicolon: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MistCodegen {
|
pub struct MistCodegen {
|
||||||
|
config: MistFmtConfig,
|
||||||
indent_amount: u8,
|
indent_amount: u8,
|
||||||
output: String,
|
output: String,
|
||||||
indent: usize,
|
indent: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MistCodegen {
|
impl MistCodegen {
|
||||||
pub fn new() -> Self {
|
pub fn new(config: MistFmtConfig) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
config,
|
||||||
output: String::new(),
|
output: String::new(),
|
||||||
indent: 0,
|
indent: 0,
|
||||||
indent_amount: 4,
|
indent_amount: 4,
|
||||||
@@ -47,13 +49,21 @@ impl MistCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_indent(&mut self) {
|
pub fn start_indent(&mut self) {
|
||||||
|
if self.config.allman_bracket_style {
|
||||||
self.addln("");
|
self.addln("");
|
||||||
self.add_indented("");
|
self.add_indented("");
|
||||||
|
} else {
|
||||||
|
self.add(" ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_bracket(&mut self) {
|
pub fn start_bracket(&mut self) {
|
||||||
|
if self.config.allman_bracket_style {
|
||||||
self.addln("");
|
self.addln("");
|
||||||
self.add_indentedln("{");
|
self.add_indentedln("{");
|
||||||
|
} else {
|
||||||
|
self.add(" {");
|
||||||
|
}
|
||||||
|
|
||||||
self.indent += 1;
|
self.indent += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ pub struct Program {
|
|||||||
pub items: Vec<TopLevel>,
|
pub items: Vec<TopLevel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct MistFmtConfig {
|
||||||
|
pub allman_bracket_style: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse<'a>(source: &'a str) -> Result<Program, ParseError<'a>> {
|
pub fn parse<'a>(source: &'a str) -> Result<Program, ParseError<'a>> {
|
||||||
let mut pairs = MistParser::parse(Rule::program, source)?;
|
let mut pairs = MistParser::parse(Rule::program, source)?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user