Skip to content

Commit

Permalink
feat: support range format in cli
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed Jul 23, 2024
1 parent b27346c commit 0173323
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 12 deletions.
116 changes: 104 additions & 12 deletions src/clang-format-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
import { readFileSync } from "node:fs";
import { readFile, writeFile } from "node:fs/promises";
import { parseArgs } from "node:util";
import init, { format, version } from "./clang-format-node.js";
import init, {
format,
format_byte_range,
format_line_range,
set_fallback_style,
version,
} from "./clang-format-node.js";

await init();

Expand Down Expand Up @@ -71,26 +77,104 @@ for (const token of tokens) {
}
}

let files = positionals;
let fileNames = positionals;
if (values.files) {
const ExternalFileOfFiles = await readFile(values.files, {
encoding: "utf-8",
});
files = files.concat(ExternalFileOfFiles.split("\n").filter(Boolean));
fileNames = fileNames.concat(
ExternalFileOfFiles.split("\n").filter(Boolean),
);
}

if (files.length === 0) {
files = ["-"];
if (fileNames.length === 0) {
fileNames = ["-"];
}

// TODO: handle lines, offset and length
for (const file of files) {
if (file === "-" && values.inplace) {
console.error("error: cannot use -i when reading from stdin.");
process.exit(1);
if (values["fallback-style"]) {
set_fallback_style(values["fallback-style"]);
}

if (
fileNames.length !== 1 &&
(!empty(values.offset) || !empty(values.length) || !empty(values.lines))
) {
console.error(
"error: -offset, -length and -lines can only be used for single file",
);
process.exit(1);
}

if (!empty(values.lines) && (!empty(values.offset) || !empty(values.length))) {
console.error("error: cannot use -lines with -offset/-length");
process.exit(1);
}

if (!empty(values.lines)) {
const [file] = fileNames;
const content = await get_file_or_stdin(file);

const range = [];
for (const line of values.lines) {
const [form_line_text, to_line_text] = line.split(":");
const [from_line, to_line] = [
Number.parseInt(form_line_text, 10),
Number.parseInt(to_line_text, 10),
];
if (!Number.isFinite(from_line) || !Number.isFinite(to_line)) {
console.error("error: invalid <start line>:<end line> pair");
process.exit(1);
}
range.push([from_line, to_line]);
}

const formatted = format_line_range(content, range, file, values.style);

if (values.inplace) {
if (content !== formatted) {
await writeFile(file, formatted, { encoding: "utf-8" });
}
} else {
console.log(formatted);
}
process.exit(0);
}

if (values.offset.length !== values.length.length) {
console.error("error: number of -offset and -length arguments must match");
process.exit(1);
}

if (!empty(values.offset)) {
const [file] = fileNames;
const content = await get_file_or_stdin(file);

const range = [];
for (let i = 0; i < values.offset.length; ++i) {
const offset = Number.parseInt(values.offset[i], 10);
const length = Number.parseInt(values.length[i], 10);
if (!Number.isFinite(offset) || !Number.isFinite(length)) {
console.error("error: invalid <offset>:<length> pair");
process.exit(1);
}
range.push([offset, length]);
}

const content = await getFileOrSTDIN(file);
const formatted = format_byte_range(content, range, file, values.style);

if (values.inplace) {
if (content !== formatted) {
await writeFile(file, formatted, { encoding: "utf-8" });
}
} else {
console.log(formatted);
}

process.exit(0);
}

for (const file of fileNames) {
const content = await get_file_or_stdin(file);
// TODO: search .clang-format on disk if values.style is not set
const formatted = format(content, file, values.style);
if (values.inplace) {
Expand All @@ -102,8 +186,16 @@ for (const file of files) {
}
}

async function getFileOrSTDIN(fileName) {
function empty(array) {
return array.length === 0;
}

async function get_file_or_stdin(fileName) {
if (fileName === "-") {
if (values.inplace) {
console.error("error: cannot use -i when reading from stdin");
process.exit(1);
}
return readFileSync(0, { encoding: "utf-8" });
}
return await readFile(fileName, { encoding: "utf-8" });
Expand Down
2 changes: 2 additions & 0 deletions src/clang-format.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,5 @@ export declare function formatByteRange(
): string;

export declare function version(): string;

export declare function set_fallback_style(style: Style): void;
5 changes: 5 additions & 0 deletions src/lib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ static auto format_line(const std::string str,
return clang::format::format_range(str, assumedFileName, style, true, std::move(ranges));
}

static auto set_fallback_style(const std::string style) -> void {
FallbackStyle = style;
}

using namespace emscripten;

EMSCRIPTEN_BINDINGS(my_module) {
Expand All @@ -285,6 +289,7 @@ EMSCRIPTEN_BINDINGS(my_module) {
"format_byte", &format_byte);
function<Result, const std::string, const std::string, const std::string, const std::vector<unsigned>>(
"format_line", &format_line);
function<void, const std::string>("set_fallback_style", &set_fallback_style);
}

auto main(int argc, const char** argv) -> int {
Expand Down
5 changes: 5 additions & 0 deletions src/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export function version() {
assert_init();
}

export function set_fallback_style(style) {
assert_init();
wasm.set_fallback_style(style);
}

function unwrap(result) {
const { error, content } = result;
if (error) {
Expand Down

0 comments on commit 0173323

Please sign in to comment.