mirror of
https://github.com/RGBCube/alejandra
synced 2025-07-31 12:37:45 +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 = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"indoc",
|
"indoc",
|
||||||
|
"rand",
|
||||||
"rayon",
|
"rayon",
|
||||||
"rnix",
|
"rnix",
|
||||||
"rowan 0.15.3",
|
"rowan 0.15.3",
|
||||||
|
@ -129,6 +130,17 @@ version = "1.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
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]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
|
@ -230,6 +242,52 @@ dependencies = [
|
||||||
"memchr",
|
"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]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
|
@ -372,6 +430,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"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]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "3"
|
clap = "3"
|
||||||
|
rand = "0.8"
|
||||||
rayon = "1.5"
|
rayon = "1.5"
|
||||||
rnix = "0.10"
|
rnix = "0.10"
|
||||||
rowan = "0.15"
|
rowan = "0.15"
|
||||||
|
|
10
README.md
10
README.md
|
@ -55,13 +55,6 @@
|
||||||
Coverage is currently 80%,
|
Coverage is currently 80%,
|
||||||
and we'll have 💯% soon.
|
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**
|
- ✔️ **Reproducible**
|
||||||
|
|
||||||
Formatting many times yields the same results.
|
Formatting many times yields the same results.
|
||||||
|
@ -70,9 +63,6 @@
|
||||||
|
|
||||||
Beauty is subjective, right?
|
Beauty is subjective, right?
|
||||||
|
|
||||||
Yet there are a few improvements to implement like:
|
|
||||||
- Multiline strings indentation is missing `'' ... ''`.
|
|
||||||
|
|
||||||
Style is negotiable at this moment.
|
Style is negotiable at this moment.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
|
@ -123,7 +123,7 @@ fn build_step(
|
||||||
add_token(
|
add_token(
|
||||||
builder,
|
builder,
|
||||||
build_ctx,
|
build_ctx,
|
||||||
rnix::SyntaxKind::TOKEN_COMMA,
|
rnix::SyntaxKind::TOKEN_WHITESPACE,
|
||||||
&format!("{0:<1$}", "", 2 * build_ctx.indentation),
|
&format!("{0:<1$}", "", 2 * build_ctx.indentation),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ fn format(
|
||||||
}
|
}
|
||||||
rnix::SyntaxKind::NODE_ROOT => crate::rules::root::rule,
|
rnix::SyntaxKind::NODE_ROOT => crate::rules::root::rule,
|
||||||
rnix::SyntaxKind::NODE_SELECT => crate::rules::select::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 => {
|
rnix::SyntaxKind::NODE_STRING_INTERPOL => {
|
||||||
crate::rules::string_interpol::rule
|
crate::rules::string_interpol::rule
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,17 @@ impl Children {
|
||||||
child
|
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 {
|
pub fn has_next(&self) -> bool {
|
||||||
self.current_index < self.children.len()
|
self.current_index < self.children.len()
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,82 +26,113 @@ pub fn rule(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let indentation = get_double_quoted_string_indentation(&node);
|
let placeholder = get_placeholder();
|
||||||
|
|
||||||
while let Some(child) = children.peek_next() {
|
let elements: Vec<rnix::SyntaxElement> = children
|
||||||
match child.element.kind() {
|
.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 => {
|
rnix::SyntaxKind::TOKEN_STRING_CONTENT => {
|
||||||
let child_token = child.element.into_token().unwrap();
|
let token = element.clone().into_token().unwrap();
|
||||||
let lines: Vec<&str> =
|
token.text().to_string()
|
||||||
child_token.text().split('\n').collect();
|
}
|
||||||
|
_ => placeholder.to_string(),
|
||||||
|
})
|
||||||
|
.collect::<String>()
|
||||||
|
.split('\n')
|
||||||
|
.map(|line| line.trim_end().to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
children.move_next();
|
// eprintln!("0: {:?}", lines);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
steps.push_back(crate::builder::Step::Token(
|
let mut indentation: usize = usize::MAX;
|
||||||
rnix::SyntaxKind::TOKEN_STRING_CONTENT,
|
for line in lines.iter() {
|
||||||
if indentation >= line.len() {
|
let line = line.trim_end();
|
||||||
line.to_string()
|
|
||||||
} else {
|
if line.len() > 0 {
|
||||||
line[indentation..line.len()].to_string()
|
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
|
steps
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_double_quoted_string_indentation(node: &rnix::SyntaxNode) -> usize {
|
fn get_placeholder() -> String {
|
||||||
let mut indentation: usize = usize::MAX;
|
use rand::RngCore;
|
||||||
|
|
||||||
let text: String = node
|
let mut bytes = [0u8; 32];
|
||||||
.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();
|
|
||||||
|
|
||||||
for line in text.split('\n') {
|
rand::thread_rng().fill_bytes(&mut bytes);
|
||||||
let line = line.trim_end();
|
|
||||||
|
|
||||||
if line.len() > 0 {
|
bytes.iter().map(|byte| format!("{:02X}", byte)).collect()
|
||||||
indentation =
|
|
||||||
usize::min(indentation, line.len() - line.trim_start().len());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if indentation == usize::MAX { 0 } else { indentation }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,62 @@
|
||||||
[
|
[
|
||||||
""
|
""
|
||||||
|
###
|
||||||
"
|
"
|
||||||
"
|
"
|
||||||
|
###
|
||||||
"a
|
"a
|
||||||
${x}
|
${x}
|
||||||
b
|
b
|
||||||
"
|
"
|
||||||
|
###
|
||||||
''''
|
''''
|
||||||
|
###
|
||||||
|
|
||||||
''a''
|
''a''
|
||||||
|
###
|
||||||
''${""}''
|
''${""}''
|
||||||
|
###
|
||||||
|
''${""}
|
||||||
|
|
||||||
|
''
|
||||||
|
###
|
||||||
|
''a
|
||||||
|
''
|
||||||
|
###
|
||||||
|
''a
|
||||||
|
|
||||||
|
''
|
||||||
|
###
|
||||||
|
'' a
|
||||||
|
''
|
||||||
|
###
|
||||||
|
|
||||||
|
''a
|
||||||
|
''
|
||||||
|
###
|
||||||
''
|
''
|
||||||
a
|
a
|
||||||
${""}
|
${""}
|
||||||
b
|
b
|
||||||
${""}
|
${""}
|
||||||
c ${""} d
|
c ${""} d
|
||||||
e
|
e
|
||||||
''
|
''
|
||||||
|
###
|
||||||
''
|
''
|
||||||
''
|
''
|
||||||
|
###
|
||||||
''
|
''
|
||||||
declare -a makefiles=(./*.mak)
|
declare -a makefiles=(./*.mak)
|
||||||
sed -i -f ${makefile-sed} "''${makefiles[@]}"
|
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)/' \
|
sed -i -e 's/ = `\([^`]\+\)`/ := $(shell \1)/' \
|
||||||
-e 's/`\([^`]\+\)`/$(shell \1)/' \
|
-e 's/`\([^`]\+\)`/$(shell \1)/' \
|
||||||
"''${makefiles[@]}"
|
"''${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
|
"a
|
||||||
${ x }
|
${ x }
|
||||||
b
|
b
|
||||||
"
|
"
|
||||||
''''
|
###
|
||||||
''a''
|
'' ''
|
||||||
''${ "" }''
|
###
|
||||||
|
'' a''
|
||||||
|
###
|
||||||
|
'' ${ "" }''
|
||||||
|
###
|
||||||
|
'' ${ "" }
|
||||||
|
|
||||||
''
|
''
|
||||||
a
|
###
|
||||||
${ "" }
|
'' a
|
||||||
b
|
|
||||||
${ "" }
|
|
||||||
c ${ "" } d
|
|
||||||
e
|
|
||||||
''
|
|
||||||
''
|
''
|
||||||
|
###
|
||||||
|
'' a
|
||||||
|
|
||||||
''
|
''
|
||||||
|
###
|
||||||
|
'' a
|
||||||
''
|
''
|
||||||
declare -a makefiles=(./*.mak)
|
###
|
||||||
sed -i -f ${ makefile-sed } "''${makefiles[@]}"
|
'' a
|
||||||
# assign Makefile variables eagerly & change backticks to `$(shell …)`
|
''
|
||||||
sed -i -e 's/ = `\([^`]\+\)`/ := $(shell \1)/' \
|
###
|
||||||
-e 's/`\([^`]\+\)`/$(shell \1)/' \
|
''
|
||||||
"''${makefiles[@]}"
|
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