Since the last post I changed my approach to something a bit more pretty printing-like - I no longer use the Rope to modify source, but just print it out. It is still driven from the AST rather than token streams. Where I don't yet format, I use existing source. This makes it an incremental approach. It needs some work till it can be used on any Rust code though (for example, we need to properly adjust indent for all items, I currently only do it for blocks and impls).
I am fairly confident that this is a good start towards a working tool. Although the question of tokens vs AST has not been completely settled in my mind.
If anyone is interested in helping I'd really appreciate contributions. The easiest (and probably most interesting) way to get stuck in is to implement formatting for some expression or item. There are a bunch of issues filed on the repo too. (Good regression testing is probably the highest priority 'big ticket' item).
For an idea of what it can do already:
before:
use std::cell::*;
use std::{any, ascii, self, borrow, boxed, char, borrow, boxed, char, borrow, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed, char};
// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff
fn foo(a: isize,
b: u32, /* blah blah */
c: f64) {
}
fn main() {
let rc = Cell::new(42us,42us, Cell::new(42us, remaining_widthremaining_widthremaining_widthremaining_width), 42us);
let rc = RefCell::new(42us,remaining_width, remaining_width); // a comment
let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd abcd abcd \
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd"; }
after:
use std::cell::*;
use std::{self, any, ascii, borrow, boxed, char, borrow, boxed, char, borrow};
use std::{borrow, boxed, char, borrow, boxed, char, borrow, boxed, char, borrow};
use std::{boxed, char, borrow, boxed, char, borrow, boxed, char, borrow, boxed};
use std::{char, borrow, boxed, char};
// sfdgfffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffff
fn foo(a: isize,
b: u32,
c: f64) {
}
fn main() {
let rc = Cell::new(42us,
42us,
Cell::new(42us,
remaining_widthremaining_widthremaining_widthremaining_width),
42us);
let rc = RefCell::new(42us, remaining_width, remaining_width); // a comment
let x = "Hello!!!!!!!!! abcd abcd abcd abcd abcd abcd\n abcd abcd abcd abcd abcd abcd abcd \
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \
abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd abcd \
abcd";
}
Note the imports are tidied, the string literal is adjusted, the nested function calls are handled, and the formal arguments in the function decl are aligned (however, the rest of the function decl is not yet formatted.