-
Notifications
You must be signed in to change notification settings - Fork 899
/
cli.rs
89 lines (79 loc) · 2.99 KB
/
cli.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#![allow(clippy::print_stdout)]
use std::path::{Path, PathBuf};
use anyhow::{format_err, Context, Result};
use clap::{command, Parser, ValueEnum};
use ruff_formatter::SourceCode;
use ruff_python_ast::PySourceType;
use ruff_python_index::tokens_and_ranges;
use ruff_python_parser::{parse_ok_tokens, AsMode};
use ruff_text_size::Ranged;
use crate::comments::collect_comments;
use crate::{format_module_ast, PyFormatOptions};
#[derive(ValueEnum, Clone, Debug)]
pub enum Emit {
/// Write back to the original files
Files,
/// Write to stdout
Stdout,
}
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
pub struct Cli {
/// Python files to format. If there are none, stdin will be used. `-` as stdin is not supported
pub files: Vec<PathBuf>,
#[clap(long)]
pub emit: Option<Emit>,
/// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits with 1 and prints
/// a diff if formatting is required.
#[clap(long)]
pub check: bool,
#[clap(long)]
pub print_ir: bool,
#[clap(long)]
pub print_comments: bool,
}
pub fn format_and_debug_print(source: &str, cli: &Cli, source_path: &Path) -> Result<String> {
let source_type = PySourceType::from(source_path);
let (tokens, comment_ranges) = tokens_and_ranges(source, source_type)
.map_err(|err| format_err!("Source contains syntax errors {err:?}"))?;
// Parse the AST.
let module = parse_ok_tokens(tokens, source, source_type.as_mode(), "<filename>")
.context("Syntax error in input")?;
let options = PyFormatOptions::from_extension(source_path);
let source_code = SourceCode::new(source);
let formatted = format_module_ast(&module, &comment_ranges, source, options)
.context("Failed to format node")?;
if cli.print_ir {
println!("{}", formatted.document().display(source_code));
}
if cli.print_comments {
// Print preceding, following and enclosing nodes
let decorated_comments = collect_comments(&module, source_code, &comment_ranges);
if !decorated_comments.is_empty() {
println!("# Comment decoration: Range, Preceding, Following, Enclosing, Comment");
}
for comment in decorated_comments {
println!(
"{:?}, {:?}, {:?}, {:?}, {:?}",
comment.slice().range(),
comment
.preceding_node()
.map(|node| (node.kind(), node.range())),
comment
.following_node()
.map(|node| (node.kind(), node.range())),
(
comment.enclosing_node().kind(),
comment.enclosing_node().range()
),
comment.slice().text(source_code),
);
}
println!("{:#?}", formatted.context().comments().debug(source_code));
}
Ok(formatted
.print()
.context("Failed to print the formatter IR")?
.as_code()
.to_string())
}