mirror of
https://github.com/RGBCube/alejandra
synced 2025-07-30 12:07:46 +00:00
feat: get strings done right
This commit is contained in:
parent
e081ba1b4e
commit
08b9b84b14
8 changed files with 253 additions and 101 deletions
64
Cargo.lock
generated
64
Cargo.lock
generated
|
@ -8,6 +8,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"clap",
|
||||
"indoc",
|
||||
"rand",
|
||||
"rayon",
|
||||
"rnix",
|
||||
"rowan 0.15.3",
|
||||
|
@ -129,6 +130,17 @@ version = "1.6.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
|
@ -230,6 +242,52 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
|
@ -372,6 +430,12 @@ dependencies = [
|
|||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[dependencies]
|
||||
clap = "3"
|
||||
rand = "0.8"
|
||||
rayon = "1.5"
|
||||
rnix = "0.10"
|
||||
rowan = "0.15"
|
||||
|
|
10
README.md
10
README.md
|
@ -55,13 +55,6 @@
|
|||
Coverage is currently 80%,
|
||||
and we'll have 💯% soon.
|
||||
|
||||
- ✔️ **Developer aware**
|
||||
|
||||
Syntax errors are gracefully handled
|
||||
by leaving that specific zone unformatted.
|
||||
|
||||
The rest of the file will be formatted normally.
|
||||
|
||||
- ✔️ **Reproducible**
|
||||
|
||||
Formatting many times yields the same results.
|
||||
|
@ -70,9 +63,6 @@
|
|||
|
||||
Beauty is subjective, right?
|
||||
|
||||
Yet there are a few improvements to implement like:
|
||||
- Multiline strings indentation is missing `'' ... ''`.
|
||||
|
||||
Style is negotiable at this moment.
|
||||
|
||||
## Getting started
|
||||
|
|
|
@ -123,7 +123,7 @@ fn build_step(
|
|||
add_token(
|
||||
builder,
|
||||
build_ctx,
|
||||
rnix::SyntaxKind::TOKEN_COMMA,
|
||||
rnix::SyntaxKind::TOKEN_WHITESPACE,
|
||||
&format!("{0:<1$}", "", 2 * build_ctx.indentation),
|
||||
);
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ fn format(
|
|||
}
|
||||
rnix::SyntaxKind::NODE_ROOT => crate::rules::root::rule,
|
||||
rnix::SyntaxKind::NODE_SELECT => crate::rules::select::rule,
|
||||
rnix::SyntaxKind::NODE_STRING => crate::rules::default,
|
||||
rnix::SyntaxKind::NODE_STRING => crate::rules::string::rule,
|
||||
rnix::SyntaxKind::NODE_STRING_INTERPOL => {
|
||||
crate::rules::string_interpol::rule
|
||||
}
|
||||
|
|
|
@ -65,6 +65,17 @@ impl Children {
|
|||
child
|
||||
}
|
||||
|
||||
pub fn get_remaining(&mut self) -> Vec<Child> {
|
||||
if self.current_index < self.children.len() {
|
||||
let remaining =
|
||||
&self.children[self.current_index..self.children.len()];
|
||||
self.current_index = self.children.len();
|
||||
remaining.to_vec()
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_next(&self) -> bool {
|
||||
self.current_index < self.children.len()
|
||||
}
|
||||
|
|
|
@ -26,82 +26,113 @@ pub fn rule(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let indentation = get_double_quoted_string_indentation(&node);
|
||||
let placeholder = get_placeholder();
|
||||
|
||||
while let Some(child) = children.peek_next() {
|
||||
match child.element.kind() {
|
||||
let elements: Vec<rnix::SyntaxElement> = children
|
||||
.get_remaining()
|
||||
.iter()
|
||||
.map(|child| child.element.clone())
|
||||
.collect();
|
||||
|
||||
let mut interpolations = elements
|
||||
.iter()
|
||||
.filter(|e| e.kind() != rnix::SyntaxKind::TOKEN_STRING_CONTENT);
|
||||
|
||||
let mut lines: Vec<String> = elements[0..elements.len() - 1]
|
||||
.iter()
|
||||
.map(|element| match element.kind() {
|
||||
rnix::SyntaxKind::TOKEN_STRING_CONTENT => {
|
||||
let child_token = child.element.into_token().unwrap();
|
||||
let lines: Vec<&str> =
|
||||
child_token.text().split('\n').collect();
|
||||
let token = element.clone().into_token().unwrap();
|
||||
token.text().to_string()
|
||||
}
|
||||
_ => placeholder.to_string(),
|
||||
})
|
||||
.collect::<String>()
|
||||
.split('\n')
|
||||
.map(|line| line.trim_end().to_string())
|
||||
.collect();
|
||||
|
||||
children.move_next();
|
||||
for (index, line) in lines.iter().enumerate() {
|
||||
if index + 1 == lines.len() && line.trim().len() == 0 {
|
||||
if let rnix::SyntaxKind::TOKEN_STRING_END =
|
||||
children.peek_next().unwrap().element.kind()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// eprintln!("0: {:?}", lines);
|
||||
|
||||
steps.push_back(crate::builder::Step::Token(
|
||||
rnix::SyntaxKind::TOKEN_STRING_CONTENT,
|
||||
if indentation >= line.len() {
|
||||
line.to_string()
|
||||
} else {
|
||||
line[indentation..line.len()].to_string()
|
||||
},
|
||||
let mut indentation: usize = usize::MAX;
|
||||
for line in lines.iter() {
|
||||
let line = line.trim_end();
|
||||
|
||||
if line.len() > 0 {
|
||||
indentation = usize::min(
|
||||
indentation,
|
||||
line.len() - line.trim_start().len(),
|
||||
);
|
||||
}
|
||||
}
|
||||
if indentation == usize::MAX {
|
||||
indentation = 0;
|
||||
};
|
||||
|
||||
// Dedent everything as much as possible
|
||||
lines = lines
|
||||
.iter()
|
||||
.map(|line| {
|
||||
if indentation < line.len() {
|
||||
line[indentation..line.len()].to_string()
|
||||
} else {
|
||||
line.to_string()
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// eprintln!("1: ''{}''", lines.join("\n"));
|
||||
// eprintln!("indentation={}, placeholder={}", indentation, placeholder);
|
||||
|
||||
for (index, line) in lines.iter().enumerate() {
|
||||
let portions: Vec<String> = line
|
||||
.split(&placeholder)
|
||||
.map(|portion| portion.to_string())
|
||||
.collect();
|
||||
|
||||
if portions.len() == 1 {
|
||||
steps.push_back(crate::builder::Step::Pad);
|
||||
steps.push_back(crate::builder::Step::Token(
|
||||
rnix::SyntaxKind::TOKEN_STRING_CONTENT,
|
||||
portions[0].to_string(),
|
||||
));
|
||||
} else {
|
||||
steps.push_back(crate::builder::Step::Pad);
|
||||
for (index, portion) in portions.iter().enumerate() {
|
||||
steps.push_back(crate::builder::Step::Token(
|
||||
rnix::SyntaxKind::TOKEN_STRING_CONTENT,
|
||||
portion.to_string(),
|
||||
));
|
||||
|
||||
if index + 1 != portions.len() {
|
||||
steps.push_back(crate::builder::Step::FormatWider(
|
||||
interpolations.next().unwrap().clone(),
|
||||
));
|
||||
|
||||
if index == 0 && lines.len() > 1 {
|
||||
steps.push_back(crate::builder::Step::NewLine);
|
||||
steps.push_back(crate::builder::Step::Pad);
|
||||
} else if index + 1 < lines.len()
|
||||
&& lines[index + 1].trim().len() == 0
|
||||
{
|
||||
steps.push_back(crate::builder::Step::NewLine);
|
||||
steps.push_back(crate::builder::Step::Pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
rnix::SyntaxKind::TOKEN_STRING_END => {
|
||||
steps
|
||||
.push_back(crate::builder::Step::Format(child.element));
|
||||
children.move_next();
|
||||
}
|
||||
_ => {
|
||||
steps.push_back(crate::builder::Step::FormatWider(
|
||||
child.element,
|
||||
));
|
||||
children.move_next();
|
||||
}
|
||||
}
|
||||
|
||||
if index + 1 < lines.len() {
|
||||
steps.push_back(crate::builder::Step::NewLine);
|
||||
}
|
||||
}
|
||||
|
||||
for interpolation in interpolations {
|
||||
steps.push_back(crate::builder::Step::FormatWider(
|
||||
interpolation.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// steps = crate::rules::default(build_ctx, node);
|
||||
steps
|
||||
}
|
||||
|
||||
fn get_double_quoted_string_indentation(node: &rnix::SyntaxNode) -> usize {
|
||||
let mut indentation: usize = usize::MAX;
|
||||
fn get_placeholder() -> String {
|
||||
use rand::RngCore;
|
||||
|
||||
let text: String = node
|
||||
.children_with_tokens()
|
||||
.filter(|child| child.kind() == rnix::SyntaxKind::TOKEN_STRING_CONTENT)
|
||||
.map(|child| child.into_token().unwrap())
|
||||
.map(|token| token.text().to_string())
|
||||
.collect();
|
||||
let mut bytes = [0u8; 32];
|
||||
|
||||
for line in text.split('\n') {
|
||||
let line = line.trim_end();
|
||||
rand::thread_rng().fill_bytes(&mut bytes);
|
||||
|
||||
if line.len() > 0 {
|
||||
indentation =
|
||||
usize::min(indentation, line.len() - line.trim_start().len());
|
||||
}
|
||||
}
|
||||
|
||||
if indentation == usize::MAX { 0 } else { indentation }
|
||||
bytes.iter().map(|byte| format!("{:02X}", byte)).collect()
|
||||
}
|
||||
|
|
|
@ -1,40 +1,62 @@
|
|||
[
|
||||
""
|
||||
|
||||
###
|
||||
"
|
||||
"
|
||||
|
||||
###
|
||||
"a
|
||||
${x}
|
||||
b
|
||||
"
|
||||
|
||||
###
|
||||
''''
|
||||
|
||||
|
||||
###
|
||||
''a''
|
||||
|
||||
###
|
||||
''${""}''
|
||||
###
|
||||
''${""}
|
||||
|
||||
''
|
||||
###
|
||||
''a
|
||||
''
|
||||
###
|
||||
''a
|
||||
|
||||
''
|
||||
###
|
||||
'' a
|
||||
''
|
||||
###
|
||||
|
||||
''a
|
||||
''
|
||||
###
|
||||
''
|
||||
a
|
||||
${""}
|
||||
${""}
|
||||
b
|
||||
${""}
|
||||
c ${""} d
|
||||
e
|
||||
''
|
||||
|
||||
###
|
||||
''
|
||||
''
|
||||
|
||||
###
|
||||
''
|
||||
declare -a makefiles=(./*.mak)
|
||||
sed -i -f ${makefile-sed} "''${makefiles[@]}"
|
||||
# assign Makefile variables eagerly & change backticks to `$(shell …)`
|
||||
### assign Makefile variables eagerly & change backticks to `$(shell …)`
|
||||
sed -i -e 's/ = `\([^`]\+\)`/ := $(shell \1)/' \
|
||||
-e 's/`\([^`]\+\)`/$(shell \1)/' \
|
||||
"''${makefiles[@]}"
|
||||
''
|
||||
|
||||
###
|
||||
''
|
||||
[${ mkSectionName sectName }]
|
||||
''
|
||||
###
|
||||
''-couch_ini ${ cfg.package }/etc/default.ini ${ configFile } ${ pkgs.writeText "couchdb-extra.ini" cfg.extraConfig } ${ cfg.configFile }''
|
||||
]
|
||||
|
|
|
@ -1,30 +1,63 @@
|
|||
[
|
||||
""
|
||||
###
|
||||
"
|
||||
"
|
||||
###
|
||||
"a
|
||||
${ x }
|
||||
b
|
||||
"
|
||||
''''
|
||||
''a''
|
||||
''${ "" }''
|
||||
###
|
||||
'' ''
|
||||
###
|
||||
'' a''
|
||||
###
|
||||
'' ${ "" }''
|
||||
###
|
||||
'' ${ "" }
|
||||
|
||||
''
|
||||
a
|
||||
${ "" }
|
||||
b
|
||||
${ "" }
|
||||
c ${ "" } d
|
||||
e
|
||||
''
|
||||
###
|
||||
'' a
|
||||
''
|
||||
###
|
||||
'' a
|
||||
|
||||
''
|
||||
###
|
||||
'' a
|
||||
''
|
||||
declare -a makefiles=(./*.mak)
|
||||
sed -i -f ${ makefile-sed } "''${makefiles[@]}"
|
||||
# assign Makefile variables eagerly & change backticks to `$(shell …)`
|
||||
sed -i -e 's/ = `\([^`]\+\)`/ := $(shell \1)/' \
|
||||
-e 's/`\([^`]\+\)`/$(shell \1)/' \
|
||||
"''${makefiles[@]}"
|
||||
''
|
||||
###
|
||||
'' a
|
||||
''
|
||||
###
|
||||
''
|
||||
a
|
||||
${ "" }
|
||||
b
|
||||
${ "" }
|
||||
c ${ "" } d
|
||||
e
|
||||
''
|
||||
###
|
||||
''
|
||||
''
|
||||
###
|
||||
''
|
||||
declare -a makefiles=(./*.mak)
|
||||
sed -i -f ${ makefile-sed } "''${makefiles[@]}"
|
||||
### assign Makefile variables eagerly & change backticks to `$(shell …)`
|
||||
sed -i -e 's/ = `\([^`]\+\)`/ := $(shell \1)/' \
|
||||
-e 's/`\([^`]\+\)`/$(shell \1)/' \
|
||||
"''${makefiles[@]}"
|
||||
''
|
||||
###
|
||||
''
|
||||
[${ mkSectionName sectName }]
|
||||
''
|
||||
###
|
||||
'' -couch_ini ${ cfg.package }/etc/default.ini ${ configFile } ${
|
||||
pkgs.writeText "couchdb-extra.ini" cfg.extraConfig
|
||||
} ${ cfg.configFile }''
|
||||
]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue