Merge pull request #1597 from ColonelThirtyTwo/fmt-indent
Use indentation settings in dx fmt and vscode extension
This commit is contained in:
24 files changed
+294
-53
No files matched your search
@@ -124,8 +124,6 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: install stable
|
- name: install stable
|
||||||
uses: dtolnay/rust-toolchain@master
|
uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
@@ -141,6 +139,11 @@ jobs:
|
|||||||
workspaces: core -> ../target
|
workspaces: core -> ../target
|
||||||
save-if: ${{ matrix.features.key == 'all' }}
|
save-if: ${{ matrix.features.key == 'all' }}
|
||||||
|
|
||||||
|
- name: Install rustfmt
|
||||||
|
run: rustup component add rustfmt
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: test
|
- name: test
|
||||||
run: |
|
run: |
|
||||||
${{ env.RUST_CARGO_COMMAND }} ${{ matrix.platform.command }} ${{ matrix.platform.args }} --target ${{ matrix.platform.target }}
|
${{ env.RUST_CARGO_COMMAND }} ${{ matrix.platform.command }} ${{ matrix.platform.args }} --target ${{ matrix.platform.target }}
|
||||||
|
|||||||
@@ -8,13 +8,14 @@ use std::fmt::{Result, Write};
|
|||||||
|
|
||||||
use dioxus_rsx::IfmtInput;
|
use dioxus_rsx::IfmtInput;
|
||||||
|
|
||||||
use crate::write_ifmt;
|
use crate::{indent::IndentOptions, write_ifmt};
|
||||||
|
|
||||||
/// The output buffer that tracks indent and string
|
/// The output buffer that tracks indent and string
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
pub buf: String,
|
pub buf: String,
|
||||||
pub indent: usize,
|
pub indent_level: usize,
|
||||||
|
pub indent: IndentOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Buffer {
|
impl Buffer {
|
||||||
@@ -31,16 +32,16 @@ impl Buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn tab(&mut self) -> Result {
|
pub fn tab(&mut self) -> Result {
|
||||||
self.write_tabs(self.indent)
|
self.write_tabs(self.indent_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indented_tab(&mut self) -> Result {
|
pub fn indented_tab(&mut self) -> Result {
|
||||||
self.write_tabs(self.indent + 1)
|
self.write_tabs(self.indent_level + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_tabs(&mut self, num: usize) -> std::fmt::Result {
|
pub fn write_tabs(&mut self, num: usize) -> std::fmt::Result {
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
write!(self.buf, " ")?
|
write!(self.buf, "{}", self.indent.indent_str())?
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ impl Writer<'_> {
|
|||||||
|
|
||||||
// check if we have a lot of attributes
|
// check if we have a lot of attributes
|
||||||
let attr_len = self.is_short_attrs(attributes);
|
let attr_len = self.is_short_attrs(attributes);
|
||||||
let is_short_attr_list = (attr_len + self.out.indent * 4) < 80;
|
let is_short_attr_list = (attr_len + self.out.indent_level * 4) < 80;
|
||||||
let children_len = self.is_short_children(children);
|
let children_len = self.is_short_children(children);
|
||||||
let is_small_children = children_len.is_some();
|
let is_small_children = children_len.is_some();
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ impl Writer<'_> {
|
|||||||
|
|
||||||
// if we have few children and few attributes, make it a one-liner
|
// if we have few children and few attributes, make it a one-liner
|
||||||
if is_short_attr_list && is_small_children {
|
if is_short_attr_list && is_small_children {
|
||||||
if children_len.unwrap() + attr_len + self.out.indent * 4 < 100 {
|
if children_len.unwrap() + attr_len + self.out.indent_level * 4 < 100 {
|
||||||
opt_level = ShortOptimization::Oneliner;
|
opt_level = ShortOptimization::Oneliner;
|
||||||
} else {
|
} else {
|
||||||
opt_level = ShortOptimization::PropsOnTop;
|
opt_level = ShortOptimization::PropsOnTop;
|
||||||
@@ -185,11 +185,11 @@ impl Writer<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while let Some(attr) = attr_iter.next() {
|
while let Some(attr) = attr_iter.next() {
|
||||||
self.out.indent += 1;
|
self.out.indent_level += 1;
|
||||||
if !sameline {
|
if !sameline {
|
||||||
self.write_comments(attr.attr.start())?;
|
self.write_comments(attr.attr.start())?;
|
||||||
}
|
}
|
||||||
self.out.indent -= 1;
|
self.out.indent_level -= 1;
|
||||||
|
|
||||||
if !sameline {
|
if !sameline {
|
||||||
self.out.indented_tabbed_line()?;
|
self.out.indented_tabbed_line()?;
|
||||||
@@ -398,14 +398,14 @@ impl Writer<'_> {
|
|||||||
for idx in start.line..end.line {
|
for idx in start.line..end.line {
|
||||||
let line = &self.src[idx];
|
let line = &self.src[idx];
|
||||||
if line.trim().starts_with("//") {
|
if line.trim().starts_with("//") {
|
||||||
for _ in 0..self.out.indent + 1 {
|
for _ in 0..self.out.indent_level + 1 {
|
||||||
write!(self.out, " ")?
|
write!(self.out, " ")?
|
||||||
}
|
}
|
||||||
writeln!(self.out, "{}", line.trim()).unwrap();
|
writeln!(self.out, "{}", line.trim()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..self.out.indent {
|
for _ in 0..self.out.indent_level {
|
||||||
write!(self.out, " ")?
|
write!(self.out, " ")?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ impl Writer<'_> {
|
|||||||
let first_line = &self.src[start.line - 1];
|
let first_line = &self.src[start.line - 1];
|
||||||
write!(self.out, "{}", &first_line[start.column - 1..].trim_start())?;
|
write!(self.out, "{}", &first_line[start.column - 1..].trim_start())?;
|
||||||
|
|
||||||
let prev_block_indent_level = crate::leading_whitespaces(first_line) / 4;
|
let prev_block_indent_level = self.out.indent.count_indents(first_line);
|
||||||
|
|
||||||
for (id, line) in self.src[start.line..end.line].iter().enumerate() {
|
for (id, line) in self.src[start.line..end.line].iter().enumerate() {
|
||||||
writeln!(self.out)?;
|
writeln!(self.out)?;
|
||||||
@@ -43,9 +43,9 @@ impl Writer<'_> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// trim the leading whitespace
|
// trim the leading whitespace
|
||||||
let previous_indent = crate::leading_whitespaces(line) / 4;
|
let previous_indent = self.out.indent.count_indents(line);
|
||||||
let offset = previous_indent.saturating_sub(prev_block_indent_level);
|
let offset = previous_indent.saturating_sub(prev_block_indent_level);
|
||||||
let required_indent = self.out.indent + offset;
|
let required_indent = self.out.indent_level + offset;
|
||||||
self.out.write_tabs(required_indent)?;
|
self.out.write_tabs(required_indent)?;
|
||||||
|
|
||||||
let line = line.trim_start();
|
let line = line.trim_start();
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
pub enum IndentType {
|
||||||
|
Spaces,
|
||||||
|
Tabs,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct IndentOptions {
|
||||||
|
width: usize,
|
||||||
|
indent_string: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndentOptions {
|
||||||
|
pub fn new(typ: IndentType, width: usize) -> Self {
|
||||||
|
assert_ne!(width, 0, "Cannot have an indent width of 0");
|
||||||
|
Self {
|
||||||
|
width,
|
||||||
|
indent_string: match typ {
|
||||||
|
IndentType::Tabs => "\t".into(),
|
||||||
|
IndentType::Spaces => " ".repeat(width),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a string containing one indent worth of whitespace
|
||||||
|
pub fn indent_str(&self) -> &str {
|
||||||
|
&self.indent_string
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the line length in characters, counting tabs as the indent width.
|
||||||
|
pub fn line_length(&self, line: &str) -> usize {
|
||||||
|
line.chars()
|
||||||
|
.map(|ch| if ch == '\t' { self.width } else { 1 })
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Estimates how many times the line has been indented.
|
||||||
|
pub fn count_indents(&self, mut line: &str) -> usize {
|
||||||
|
let mut indent = 0;
|
||||||
|
while !line.is_empty() {
|
||||||
|
// Try to count tabs
|
||||||
|
let num_tabs = line.chars().take_while(|ch| *ch == '\t').count();
|
||||||
|
if num_tabs > 0 {
|
||||||
|
indent += num_tabs;
|
||||||
|
line = &line[num_tabs..];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to count spaces
|
||||||
|
let num_spaces = line.chars().take_while(|ch| *ch == ' ').count();
|
||||||
|
if num_spaces >= self.width {
|
||||||
|
// Intentionally floor here to take only the amount of space that matches an indent
|
||||||
|
let num_space_indents = num_spaces / self.width;
|
||||||
|
indent += num_space_indents;
|
||||||
|
line = &line[num_space_indents * self.width..];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Line starts with either non-indent characters or an unevent amount of spaces,
|
||||||
|
// so no more indent remains.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
indent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for IndentOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new(IndentType::Spaces, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn count_indents() {
|
||||||
|
assert_eq!(
|
||||||
|
IndentOptions::new(IndentType::Spaces, 4).count_indents("no indentation here!"),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
IndentOptions::new(IndentType::Spaces, 4).count_indents(" v += 2"),
|
||||||
|
1
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
IndentOptions::new(IndentType::Spaces, 4).count_indents(" v += 2"),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
IndentOptions::new(IndentType::Spaces, 4).count_indents(" v += 2"),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
IndentOptions::new(IndentType::Spaces, 4).count_indents("\t\tv += 2"),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
IndentOptions::new(IndentType::Spaces, 4).count_indents("\t\t v += 2"),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
IndentOptions::new(IndentType::Spaces, 2).count_indents(" v += 2"),
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-15
@@ -16,8 +16,11 @@ mod collect_macros;
|
|||||||
mod component;
|
mod component;
|
||||||
mod element;
|
mod element;
|
||||||
mod expr;
|
mod expr;
|
||||||
|
mod indent;
|
||||||
mod writer;
|
mod writer;
|
||||||
|
|
||||||
|
pub use indent::{IndentOptions, IndentType};
|
||||||
|
|
||||||
/// A modification to the original file to be applied by an IDE
|
/// A modification to the original file to be applied by an IDE
|
||||||
///
|
///
|
||||||
/// Right now this re-writes entire rsx! blocks at a time, instead of precise line-by-line changes.
|
/// Right now this re-writes entire rsx! blocks at a time, instead of precise line-by-line changes.
|
||||||
@@ -47,7 +50,7 @@ pub struct FormattedBlock {
|
|||||||
/// back to the file precisely.
|
/// back to the file precisely.
|
||||||
///
|
///
|
||||||
/// Nested blocks of RSX will be handled automatically
|
/// Nested blocks of RSX will be handled automatically
|
||||||
pub fn fmt_file(contents: &str) -> Vec<FormattedBlock> {
|
pub fn fmt_file(contents: &str, indent: IndentOptions) -> Vec<FormattedBlock> {
|
||||||
let mut formatted_blocks = Vec::new();
|
let mut formatted_blocks = Vec::new();
|
||||||
|
|
||||||
let parsed = syn::parse_file(contents).unwrap();
|
let parsed = syn::parse_file(contents).unwrap();
|
||||||
@@ -61,6 +64,7 @@ pub fn fmt_file(contents: &str) -> Vec<FormattedBlock> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut writer = Writer::new(contents);
|
let mut writer = Writer::new(contents);
|
||||||
|
writer.out.indent = indent;
|
||||||
|
|
||||||
// Don't parse nested macros
|
// Don't parse nested macros
|
||||||
let mut end_span = LineColumn { column: 0, line: 0 };
|
let mut end_span = LineColumn { column: 0, line: 0 };
|
||||||
@@ -76,7 +80,10 @@ pub fn fmt_file(contents: &str) -> Vec<FormattedBlock> {
|
|||||||
|
|
||||||
let rsx_start = macro_path.span().start();
|
let rsx_start = macro_path.span().start();
|
||||||
|
|
||||||
writer.out.indent = leading_whitespaces(writer.src[rsx_start.line - 1]) / 4;
|
writer.out.indent_level = writer
|
||||||
|
.out
|
||||||
|
.indent
|
||||||
|
.count_indents(writer.src[rsx_start.line - 1]);
|
||||||
|
|
||||||
write_body(&mut writer, &body);
|
write_body(&mut writer, &body);
|
||||||
|
|
||||||
@@ -159,12 +166,13 @@ pub fn fmt_block_from_expr(raw: &str, expr: ExprMacro) -> Option<String> {
|
|||||||
buf.consume()
|
buf.consume()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt_block(block: &str, indent_level: usize) -> Option<String> {
|
pub fn fmt_block(block: &str, indent_level: usize, indent: IndentOptions) -> Option<String> {
|
||||||
let body = syn::parse_str::<dioxus_rsx::CallBody>(block).unwrap();
|
let body = syn::parse_str::<dioxus_rsx::CallBody>(block).unwrap();
|
||||||
|
|
||||||
let mut buf = Writer::new(block);
|
let mut buf = Writer::new(block);
|
||||||
|
|
||||||
buf.out.indent = indent_level;
|
buf.out.indent = indent;
|
||||||
|
buf.out.indent_level = indent_level;
|
||||||
|
|
||||||
write_body(&mut buf, &body);
|
write_body(&mut buf, &body);
|
||||||
|
|
||||||
@@ -230,14 +238,3 @@ pub(crate) fn write_ifmt(input: &IfmtInput, writable: &mut impl Write) -> std::f
|
|||||||
let display = DisplayIfmt(input);
|
let display = DisplayIfmt(input);
|
||||||
write!(writable, "{}", display)
|
write!(writable, "{}", display)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn leading_whitespaces(input: &str) -> usize {
|
|
||||||
input
|
|
||||||
.chars()
|
|
||||||
.map_while(|c| match c {
|
|
||||||
' ' => Some(1),
|
|
||||||
'\t' => Some(4),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.sum()
|
|
||||||
}
|
|
||||||
@@ -96,11 +96,11 @@ impl<'a> Writer<'a> {
|
|||||||
|
|
||||||
// Push out the indent level and write each component, line by line
|
// Push out the indent level and write each component, line by line
|
||||||
pub fn write_body_indented(&mut self, children: &[BodyNode]) -> Result {
|
pub fn write_body_indented(&mut self, children: &[BodyNode]) -> Result {
|
||||||
self.out.indent += 1;
|
self.out.indent_level += 1;
|
||||||
|
|
||||||
self.write_body_no_indent(children)?;
|
self.write_body_no_indent(children)?;
|
||||||
|
|
||||||
self.out.indent -= 1;
|
self.out.indent_level -= 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ macro_rules! twoway {
|
|||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
fn $name() {
|
||||||
let src = include_str!(concat!("./samples/", stringify!($name), ".rsx"));
|
let src = include_str!(concat!("./samples/", stringify!($name), ".rsx"));
|
||||||
let formatted = dioxus_autofmt::fmt_file(src);
|
let formatted = dioxus_autofmt::fmt_file(src, Default::default());
|
||||||
let out = dioxus_autofmt::apply_formats(src, formatted);
|
let out = dioxus_autofmt::apply_formats(src, formatted);
|
||||||
// normalize line endings
|
// normalize line endings
|
||||||
let out = out.replace("\r", "");
|
let out = out.replace("\r", "");
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
use dioxus_autofmt::{IndentOptions, IndentType};
|
||||||
|
|
||||||
macro_rules! twoway {
|
macro_rules! twoway {
|
||||||
($val:literal => $name:ident) => {
|
($val:literal => $name:ident ($indent:expr)) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
fn $name() {
|
||||||
let src_right = include_str!(concat!("./wrong/", $val, ".rsx"));
|
let src_right = include_str!(concat!("./wrong/", $val, ".rsx"));
|
||||||
let src_wrong = include_str!(concat!("./wrong/", $val, ".wrong.rsx"));
|
let src_wrong = include_str!(concat!("./wrong/", $val, ".wrong.rsx"));
|
||||||
let formatted = dioxus_autofmt::fmt_file(src_wrong);
|
let formatted = dioxus_autofmt::fmt_file(src_wrong, $indent);
|
||||||
let out = dioxus_autofmt::apply_formats(src_wrong, formatted);
|
let out = dioxus_autofmt::apply_formats(src_wrong, formatted);
|
||||||
|
|
||||||
// normalize line endings
|
// normalize line endings
|
||||||
@@ -16,8 +18,11 @@ macro_rules! twoway {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
twoway!("comments" => comments);
|
twoway!("comments-4sp" => comments_4sp (IndentOptions::new(IndentType::Spaces, 4)));
|
||||||
|
twoway!("comments-tab" => comments_tab (IndentOptions::new(IndentType::Tabs, 4)));
|
||||||
|
|
||||||
twoway!("multi" => multi);
|
twoway!("multi-4sp" => multi_4sp (IndentOptions::new(IndentType::Spaces, 4)));
|
||||||
|
twoway!("multi-tab" => multi_tab (IndentOptions::new(IndentType::Tabs, 4)));
|
||||||
|
|
||||||
twoway!("multiexpr" => multiexpr);
|
twoway!("multiexpr-4sp" => multiexpr_4sp (IndentOptions::new(IndentType::Spaces, 4)));
|
||||||
|
twoway!("multiexpr-tab" => multiexpr_tab (IndentOptions::new(IndentType::Tabs, 4)));
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,7 @@
|
|||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
// Comments
|
||||||
|
class: "asdasd",
|
||||||
|
"hello world"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
// Comments
|
||||||
|
class: "asdasd", "hello world" }
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,3 @@
|
|||||||
|
fn app(cx: Scope) -> Element {
|
||||||
|
cx.render(rsx! { div { "hello world" } })
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fn app(cx: Scope) -> Element {
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {"hello world" }
|
||||||
|
})
|
||||||
|
}
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,8 @@
|
|||||||
|
fn ItWroks() {
|
||||||
|
cx.render(rsx! {
|
||||||
|
div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light",
|
||||||
|
left,
|
||||||
|
right
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fn ItWroks() {
|
||||||
|
cx.render(rsx! {
|
||||||
|
div { class: "flex flex-wrap items-center dark:text-white py-16 border-t font-light", left, right }
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use dioxus_autofmt::{IndentOptions, IndentType};
|
||||||
use futures::{stream::FuturesUnordered, StreamExt};
|
use futures::{stream::FuturesUnordered, StreamExt};
|
||||||
use std::{fs, path::Path, process::exit};
|
use std::{fs, path::Path, process::exit};
|
||||||
|
|
||||||
@@ -35,7 +36,8 @@ impl Autoformat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(raw) = self.raw {
|
if let Some(raw) = self.raw {
|
||||||
if let Some(inner) = dioxus_autofmt::fmt_block(&raw, 0) {
|
let indent = indentation_for(".")?;
|
||||||
|
if let Some(inner) = dioxus_autofmt::fmt_block(&raw, 0, indent) {
|
||||||
println!("{}", inner);
|
println!("{}", inner);
|
||||||
} else {
|
} else {
|
||||||
// exit process with error
|
// exit process with error
|
||||||
@@ -46,17 +48,21 @@ impl Autoformat {
|
|||||||
|
|
||||||
// Format single file
|
// Format single file
|
||||||
if let Some(file) = self.file {
|
if let Some(file) = self.file {
|
||||||
let file_content = if file == "-" {
|
let file_content;
|
||||||
|
let indent;
|
||||||
|
if file == "-" {
|
||||||
|
indent = indentation_for(".")?;
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
std::io::stdin().read_to_string(&mut contents)?;
|
std::io::stdin().read_to_string(&mut contents)?;
|
||||||
Ok(contents)
|
file_content = Ok(contents);
|
||||||
} else {
|
} else {
|
||||||
fs::read_to_string(&file)
|
indent = indentation_for(".")?;
|
||||||
|
file_content = fs::read_to_string(&file);
|
||||||
};
|
};
|
||||||
|
|
||||||
match file_content {
|
match file_content {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
let edits = dioxus_autofmt::fmt_file(&s);
|
let edits = dioxus_autofmt::fmt_file(&s, indent);
|
||||||
let out = dioxus_autofmt::apply_formats(&s, edits);
|
let out = dioxus_autofmt::apply_formats(&s, edits);
|
||||||
if file == "-" {
|
if file == "-" {
|
||||||
print!("{}", out);
|
print!("{}", out);
|
||||||
@@ -93,6 +99,12 @@ async fn autoformat_project(check: bool) -> Result<()> {
|
|||||||
let mut files_to_format = vec![];
|
let mut files_to_format = vec![];
|
||||||
collect_rs_files(&crate_config.crate_dir, &mut files_to_format);
|
collect_rs_files(&crate_config.crate_dir, &mut files_to_format);
|
||||||
|
|
||||||
|
if files_to_format.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let indent = indentation_for(&files_to_format[0])?;
|
||||||
|
|
||||||
let counts = files_to_format
|
let counts = files_to_format
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|file| {
|
.filter(|file| {
|
||||||
@@ -104,10 +116,11 @@ async fn autoformat_project(check: bool) -> Result<()> {
|
|||||||
})
|
})
|
||||||
.map(|path| async {
|
.map(|path| async {
|
||||||
let _path = path.clone();
|
let _path = path.clone();
|
||||||
|
let _indent = indent.clone();
|
||||||
let res = tokio::spawn(async move {
|
let res = tokio::spawn(async move {
|
||||||
let contents = tokio::fs::read_to_string(&path).await?;
|
let contents = tokio::fs::read_to_string(&path).await?;
|
||||||
|
|
||||||
let edits = dioxus_autofmt::fmt_file(&contents);
|
let edits = dioxus_autofmt::fmt_file(&contents, _indent.clone());
|
||||||
let len = edits.len();
|
let len = edits.len();
|
||||||
|
|
||||||
if !edits.is_empty() {
|
if !edits.is_empty() {
|
||||||
@@ -151,6 +164,49 @@ async fn autoformat_project(check: bool) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn indentation_for(file_or_dir: impl AsRef<Path>) -> Result<IndentOptions> {
|
||||||
|
let out = std::process::Command::new("cargo")
|
||||||
|
.args(["fmt", "--", "--print-config", "current"])
|
||||||
|
.arg(file_or_dir.as_ref())
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.stderr(std::process::Stdio::inherit())
|
||||||
|
.output()?;
|
||||||
|
if !out.status.success() {
|
||||||
|
return Err(Error::CargoError("cargo fmt failed".into()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = String::from_utf8_lossy(&out.stdout);
|
||||||
|
|
||||||
|
let hard_tabs = config
|
||||||
|
.lines()
|
||||||
|
.find(|line| line.starts_with("hard_tabs "))
|
||||||
|
.and_then(|line| line.split_once('='))
|
||||||
|
.map(|(_, value)| value.trim() == "true")
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::RuntimeError("Could not find hard_tabs option in rustfmt config".into())
|
||||||
|
})?;
|
||||||
|
let tab_spaces = config
|
||||||
|
.lines()
|
||||||
|
.find(|line| line.starts_with("tab_spaces "))
|
||||||
|
.and_then(|line| line.split_once('='))
|
||||||
|
.map(|(_, value)| value.trim().parse::<usize>())
|
||||||
|
.ok_or_else(|| {
|
||||||
|
Error::RuntimeError("Could not find tab_spaces option in rustfmt config".into())
|
||||||
|
})?
|
||||||
|
.map_err(|_| {
|
||||||
|
Error::RuntimeError("Could not parse tab_spaces option in rustfmt config".into())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(IndentOptions::new(
|
||||||
|
if hard_tabs {
|
||||||
|
IndentType::Tabs
|
||||||
|
} else {
|
||||||
|
IndentType::Spaces
|
||||||
|
},
|
||||||
|
tab_spaces,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fn collect_rs_files(folder: &Path, files: &mut Vec<PathBuf>) {
|
fn collect_rs_files(folder: &Path, files: &mut Vec<PathBuf>) {
|
||||||
let Ok(folder) = folder.read_dir() else {
|
let Ok(folder) = folder.read_dir() else {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,17 +1,39 @@
|
|||||||
//! This file exports functions into the vscode extension
|
//! This file exports functions into the vscode extension
|
||||||
|
|
||||||
use dioxus_autofmt::FormattedBlock;
|
use dioxus_autofmt::{FormattedBlock, IndentOptions, IndentType};
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn format_rsx(raw: String) -> String {
|
pub fn format_rsx(raw: String, use_tabs: bool, indent_size: usize) -> String {
|
||||||
let block = dioxus_autofmt::fmt_block(&raw, 0);
|
let block = dioxus_autofmt::fmt_block(
|
||||||
|
&raw,
|
||||||
|
0,
|
||||||
|
IndentOptions::new(
|
||||||
|
if use_tabs {
|
||||||
|
IndentType::Tabs
|
||||||
|
} else {
|
||||||
|
IndentType::Spaces
|
||||||
|
},
|
||||||
|
indent_size,
|
||||||
|
),
|
||||||
|
);
|
||||||
block.unwrap()
|
block.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn format_selection(raw: String) -> String {
|
pub fn format_selection(raw: String, use_tabs: bool, indent_size: usize) -> String {
|
||||||
let block = dioxus_autofmt::fmt_block(&raw, 0);
|
let block = dioxus_autofmt::fmt_block(
|
||||||
|
&raw,
|
||||||
|
0,
|
||||||
|
IndentOptions::new(
|
||||||
|
if use_tabs {
|
||||||
|
IndentType::Tabs
|
||||||
|
} else {
|
||||||
|
IndentType::Spaces
|
||||||
|
},
|
||||||
|
indent_size,
|
||||||
|
),
|
||||||
|
);
|
||||||
block.unwrap()
|
block.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,8 +57,18 @@ impl FormatBlockInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn format_file(contents: String) -> FormatBlockInstance {
|
pub fn format_file(contents: String, use_tabs: bool, indent_size: usize) -> FormatBlockInstance {
|
||||||
let _edits = dioxus_autofmt::fmt_file(&contents);
|
let _edits = dioxus_autofmt::fmt_file(
|
||||||
|
&contents,
|
||||||
|
IndentOptions::new(
|
||||||
|
if use_tabs {
|
||||||
|
IndentType::Tabs
|
||||||
|
} else {
|
||||||
|
IndentType::Spaces
|
||||||
|
},
|
||||||
|
indent_size,
|
||||||
|
),
|
||||||
|
);
|
||||||
let out = dioxus_autofmt::apply_formats(&contents, _edits.clone());
|
let out = dioxus_autofmt::apply_formats(&contents, _edits.clone());
|
||||||
FormatBlockInstance { new: out, _edits }
|
FormatBlockInstance { new: out, _edits }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,13 @@ function fmtDocument(document: vscode.TextDocument) {
|
|||||||
if (!editor) return; // Need an editor to apply text edits.
|
if (!editor) return; // Need an editor to apply text edits.
|
||||||
|
|
||||||
const contents = editor.document.getText();
|
const contents = editor.document.getText();
|
||||||
const formatted = dioxus.format_file(contents);
|
let tabSize: number;
|
||||||
|
if (typeof editor.options.tabSize === 'number') {
|
||||||
|
tabSize = editor.options.tabSize;
|
||||||
|
} else {
|
||||||
|
tabSize = 4;
|
||||||
|
}
|
||||||
|
const formatted = dioxus.format_file(contents, !editor.options.insertSpaces, tabSize);
|
||||||
|
|
||||||
// Replace the entire text document
|
// Replace the entire text document
|
||||||
// Yes, this is a bit heavy handed, but the dioxus side doesn't know the line/col scheme that vscode is using
|
// Yes, this is a bit heavy handed, but the dioxus side doesn't know the line/col scheme that vscode is using
|
||||||
|
|||||||
Reference in new issue
Block a user