open-standards/wai/wai-quantum-cli/src/fmt.rs
Transaction Science c52c83d2fd wai-quantum: the language service and server for editors, and fmt
The engine gains `engine::editor`, the language service an editor needs,
pure and with no protocol in it:

- diagnostics: the reader's refusal on its line (one mapping function,
  `reader_diagnostic`, where stable codes and exact spans plug in), and
  the critique's smells on theirs, with their kind as the code; a
  generator is read at the given inputs, or 4;
- completion of keywords, the standard gates (with parameter
  placeholders), and the registers, gates, subroutines and variables in
  scope, by what the cursor's place takes; snippets, and sample programs
  in an empty file;
- hover: each standard gate's matrix written exactly, held entry by entry
  to the engine's own matrix under all 46 names the reader accepts; a
  user gate's matrix from the engine's matrices of its gates; each gate's
  cost as the engine counts it (two-qubit gates, T count, depth), at the
  call's angles or at generic ones, said which; a register's size;
- definition, references, highlights and rename over an index of
  declarations and scopes that reads the whole of OpenQASM 3, and a
  half-typed program; symbols, folding (blocks, comments, held blocks);
- a formatter with one layout, refusing a program whose brackets do not
  match, checked to keep every token, and tested stable and
  meaning-preserving (the engine reads the formatted program to the same
  circuit) on a corpus in every part of the language;
- lenses for Run, Plan, Critique, Shortcuts and Receipt.

The command line gains two verbs. `wai-quantum lsp` serves it over
standard input and output, UTF-16 or UTF-8 positions as agreed, the
commands run in-process on a thread of their own and signed with the
user's key; `wai-quantum fmt` formats, `--check`s and `--write`s.
tests/lsp.rs drives the binary through a scripted session from
initialize to exit.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-27 19:51:34 -04:00

93 lines
2.9 KiB
Rust

//! `wai-quantum fmt`: programs in the one layout the language server formats
//! to ([`wai_quantum::engine::editor::format`]). A program whose brackets do
//! not match, or that holds a character the language has no use for, is left
//! as it is, with its line.
use std::path::{Path, PathBuf};
/// Formats `files` (standard input for none or `-`): printed for one program,
/// listed when not formatted with `check`, written back with `write`. The exit
/// status: 0, or 1 when a program is not formatted (`check`) or is left as it is.
pub fn main(files: &[PathBuf], check: bool, write: bool) -> i32 {
let stdin = files.is_empty() || (files.len() == 1 && files[0] == Path::new("-"));
if stdin {
if write {
eprintln!("wai-quantum: --write needs the files to write");
return 1;
}
let src = match crate::read_text(None) {
Ok(s) => s,
Err(e) => {
eprintln!("wai-quantum: {e}");
return 1;
}
};
return match wai_quantum::engine::editor::format(&src) {
Ok(f) if check => {
if f == src {
0
} else {
println!("<stdin>");
1
}
}
Ok(f) => {
print!("{f}");
0
}
Err(e) => {
eprintln!("{}", located("<stdin>", &e));
1
}
};
}
if files.len() > 1 && !check && !write {
eprintln!("wai-quantum: give --write or --check to format more than one file");
return 1;
}
let mut status = 0;
for p in files {
let name = p.display();
let src = match std::fs::read_to_string(p) {
Ok(s) => s,
Err(e) => {
eprintln!("{name}: {e}");
status = 1;
continue;
}
};
match wai_quantum::engine::editor::format(&src) {
Ok(f) if f == src => {
if !check && !write {
print!("{f}");
}
}
Ok(_) if check => {
println!("{name}");
status = 1;
}
Ok(f) if write => {
if let Err(e) = std::fs::write(p, &f) {
eprintln!("{name}: {e}");
status = 1;
} else {
eprintln!("formatted {name}");
}
}
Ok(f) => print!("{f}"),
Err(e) => {
eprintln!("{}", located(&name.to_string(), &e));
status = 1;
}
}
}
status
}
/// A refusal as `file:line: problem`, or `file: problem` when it names no line.
fn located(name: &str, e: &str) -> String {
match e.strip_prefix("line ") {
Some(rest) => format!("{name}:{rest}"),
None => format!("{name}: {e}"),
}
}