headson 0.7.0__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of headson might be problematic. Click here for more details.
- {headson-0.7.0 → headson-0.7.1}/Cargo.lock +1 -1
- {headson-0.7.0 → headson-0.7.1}/Cargo.toml +1 -1
- {headson-0.7.0 → headson-0.7.1}/PKG-INFO +4 -2
- {headson-0.7.0 → headson-0.7.1}/README.md +3 -1
- headson-0.7.1/docs/assets/tapes/demo.gif +0 -0
- {headson-0.7.0 → headson-0.7.1}/pyproject.toml +1 -1
- {headson-0.7.0 → headson-0.7.1}/python/Cargo.lock +2 -2
- {headson-0.7.0 → headson-0.7.1}/python/Cargo.toml +1 -1
- {headson-0.7.0 → headson-0.7.1}/python/src/lib.rs +1 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/text/mod.rs +1 -0
- {headson-0.7.0 → headson-0.7.1}/src/lib.rs +59 -44
- {headson-0.7.0 → headson-0.7.1}/src/main.rs +7 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/fileset.rs +50 -15
- {headson-0.7.0 → headson-0.7.1}/src/serialization/mod.rs +19 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/types.rs +2 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/measure.rs +15 -3
- headson-0.7.0/docs/assets/tapes/demo.gif +0 -0
- {headson-0.7.0 → headson-0.7.1}/docs/assets/algorithm.svg +0 -0
- {headson-0.7.0 → headson-0.7.1}/docs/assets/logo.png +0 -0
- {headson-0.7.0 → headson-0.7.1}/docs/assets/logo.svg +0 -0
- {headson-0.7.0 → headson-0.7.1}/python/README.md +0 -0
- {headson-0.7.0 → headson-0.7.1}/python/headson/__init__.py +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/debug.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/format.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/fileset.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/json/builder.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/json/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/json/samplers/default.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/json/samplers/head.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/json/samplers/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/json/samplers/tail.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/formats/yaml/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/ingest/sampling/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/order/build.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/order/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/order/scoring.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/order/snapshots/headson__order__build__tests__order_empty_array_order.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/order/snapshots/headson__order__build__tests__order_single_string_array_order.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/order/types.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/color.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/highlight.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/output.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__arena_render_empty.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__arena_render_empty_yaml.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__arena_render_single.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__arena_render_single_yaml.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__array_internal_gaps_yaml.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__array_omitted_js_head.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__array_omitted_js_tail.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__array_omitted_pseudo_head.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__array_omitted_pseudo_tail.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__array_omitted_yaml_head.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__array_omitted_yaml_tail.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__inline_open_array_in_object_json.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/snapshots/headson__serialization__tests__inline_open_array_in_object_yaml.snap +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/code.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/core.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/js.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/json.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/pseudo.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/text.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/serialization/templates/yaml.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/extensions.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/graph.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/json.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/mod.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/search.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/text.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/src/utils/tree_arena.rs +0 -0
- {headson-0.7.0 → headson-0.7.1}/tests/fixtures/json/JSONTestSuite/LICENSE +0 -0
- {headson-0.7.0 → headson-0.7.1}/tests/fixtures/json/JSONTestSuite/README.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: headson
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Classifier: Programming Language :: Python
|
|
5
5
|
Classifier: Programming Language :: Python :: 3
|
|
6
6
|
Classifier: Programming Language :: Rust
|
|
@@ -83,6 +83,7 @@ Common flags:
|
|
|
83
83
|
- `-i, --input-format <json|yaml|text>`: ingestion format (default: `json`). For filesets in `auto` format, ingestion is chosen by extensions.
|
|
84
84
|
- `-m, --compact`: no indentation, no spaces, no newlines
|
|
85
85
|
- `--no-newline`: single line output
|
|
86
|
+
- `--no-header`: suppress fileset section headers (useful when embedding output in scripts)
|
|
86
87
|
- `--no-space`: no space after `:` in objects
|
|
87
88
|
- `--indent <STR>`: indentation unit (default: two spaces)
|
|
88
89
|
- `--string-cap <N>`: max graphemes to consider per string (default: 500)
|
|
@@ -92,7 +93,7 @@ Common flags:
|
|
|
92
93
|
Notes:
|
|
93
94
|
|
|
94
95
|
- Multiple inputs:
|
|
95
|
-
- With newlines enabled, file sections are rendered with human‑readable headers. In compact/single‑line modes, headers are omitted.
|
|
96
|
+
- With newlines enabled, file sections are rendered with human‑readable headers (pass `--no-header` to suppress them). In compact/single‑line modes, headers are omitted.
|
|
96
97
|
- In `--format auto`, each file uses its own best format: JSON family for `.json`, YAML for `.yaml`/`.yml`.
|
|
97
98
|
- Unknown extensions are treated as Text (raw lines) — safe for logs and `.txt` files.
|
|
98
99
|
- `--global-bytes` may truncate or omit entire files to respect the total budget.
|
|
@@ -114,6 +115,7 @@ Notes:
|
|
|
114
115
|
- Caps the number of lines in the output.
|
|
115
116
|
- Incompatible with `--no-newline`.
|
|
116
117
|
- Multiple inputs: defaults to `<LINES> * number_of_inputs`; `--global-lines` caps the total.
|
|
118
|
+
- Fileset headers, blank separators, and summary lines do not count toward the line cap; only actual content lines are considered.
|
|
117
119
|
|
|
118
120
|
- Interactions and precedence
|
|
119
121
|
- All active budgets are enforced simultaneously. The render must satisfy all of: bytes (if set), chars (if set), and lines (if set). The strictest cap wins.
|
|
@@ -69,6 +69,7 @@ Common flags:
|
|
|
69
69
|
- `-i, --input-format <json|yaml|text>`: ingestion format (default: `json`). For filesets in `auto` format, ingestion is chosen by extensions.
|
|
70
70
|
- `-m, --compact`: no indentation, no spaces, no newlines
|
|
71
71
|
- `--no-newline`: single line output
|
|
72
|
+
- `--no-header`: suppress fileset section headers (useful when embedding output in scripts)
|
|
72
73
|
- `--no-space`: no space after `:` in objects
|
|
73
74
|
- `--indent <STR>`: indentation unit (default: two spaces)
|
|
74
75
|
- `--string-cap <N>`: max graphemes to consider per string (default: 500)
|
|
@@ -78,7 +79,7 @@ Common flags:
|
|
|
78
79
|
Notes:
|
|
79
80
|
|
|
80
81
|
- Multiple inputs:
|
|
81
|
-
- With newlines enabled, file sections are rendered with human‑readable headers. In compact/single‑line modes, headers are omitted.
|
|
82
|
+
- With newlines enabled, file sections are rendered with human‑readable headers (pass `--no-header` to suppress them). In compact/single‑line modes, headers are omitted.
|
|
82
83
|
- In `--format auto`, each file uses its own best format: JSON family for `.json`, YAML for `.yaml`/`.yml`.
|
|
83
84
|
- Unknown extensions are treated as Text (raw lines) — safe for logs and `.txt` files.
|
|
84
85
|
- `--global-bytes` may truncate or omit entire files to respect the total budget.
|
|
@@ -100,6 +101,7 @@ Notes:
|
|
|
100
101
|
- Caps the number of lines in the output.
|
|
101
102
|
- Incompatible with `--no-newline`.
|
|
102
103
|
- Multiple inputs: defaults to `<LINES> * number_of_inputs`; `--global-lines` caps the total.
|
|
104
|
+
- Fileset headers, blank separators, and summary lines do not count toward the line cap; only actual content lines are considered.
|
|
103
105
|
|
|
104
106
|
- Interactions and precedence
|
|
105
107
|
- All active budgets are enforced simultaneously. The render must satisfy all of: bytes (if set), chars (if set), and lines (if set). The strictest cap wins.
|
|
Binary file
|
|
@@ -291,7 +291,7 @@ dependencies = [
|
|
|
291
291
|
|
|
292
292
|
[[package]]
|
|
293
293
|
name = "headson"
|
|
294
|
-
version = "0.7.
|
|
294
|
+
version = "0.7.1"
|
|
295
295
|
dependencies = [
|
|
296
296
|
"anyhow",
|
|
297
297
|
"clap",
|
|
@@ -307,7 +307,7 @@ dependencies = [
|
|
|
307
307
|
|
|
308
308
|
[[package]]
|
|
309
309
|
name = "headson-python"
|
|
310
|
-
version = "0.7.
|
|
310
|
+
version = "0.7.1"
|
|
311
311
|
dependencies = [
|
|
312
312
|
"anyhow",
|
|
313
313
|
"headson",
|
|
@@ -187,52 +187,20 @@ fn find_largest_render_under_budgets(
|
|
|
187
187
|
if total == 0 {
|
|
188
188
|
return String::new();
|
|
189
189
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
let hi = match budgets.byte_budget {
|
|
195
|
-
Some(c) => total.min(c.max(1)),
|
|
196
|
-
None => total,
|
|
197
|
-
};
|
|
198
|
-
// Reuse render-inclusion flags across render attempts to avoid clearing the vector.
|
|
199
|
-
// A node participates in the current render attempt when inclusion_flags[id] == render_set_id.
|
|
200
|
-
let mut inclusion_flags: Vec<u32> = vec![0; total];
|
|
201
|
-
// Each render attempt bumps this non-zero identifier to create a fresh inclusion set.
|
|
202
|
-
let mut render_set_id: u32 = 1;
|
|
203
|
-
// Measure length without color so ANSI escapes do not count toward the
|
|
204
|
-
// byte budget. Then render once more with the requested color setting.
|
|
205
|
-
let mut best_k: Option<usize> = None;
|
|
190
|
+
let root_is_fileset = order_build
|
|
191
|
+
.object_type
|
|
192
|
+
.get(crate::order::ROOT_PQ_ID)
|
|
193
|
+
.is_some_and(|t| *t == crate::order::ObjectType::Fileset);
|
|
206
194
|
let mut measure_cfg = config.clone();
|
|
207
195
|
measure_cfg.color_enabled = false;
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
);
|
|
217
|
-
render_set_id = render_set_id.wrapping_add(1).max(1);
|
|
218
|
-
// Measure output using a unified stats helper and enforce
|
|
219
|
-
// all provided caps (chars and/or lines).
|
|
220
|
-
let stats = crate::utils::measure::count_output_stats(
|
|
221
|
-
&s,
|
|
222
|
-
budgets.char_budget.is_some(),
|
|
223
|
-
);
|
|
224
|
-
let fits_bytes = budgets.byte_budget.is_none_or(|c| stats.bytes <= c);
|
|
225
|
-
let fits_chars = budgets.char_budget.is_none_or(|c| stats.chars <= c);
|
|
226
|
-
let fits_lines = budgets.line_budget.is_none_or(|l| stats.lines <= l);
|
|
227
|
-
if fits_bytes && fits_chars && fits_lines {
|
|
228
|
-
best_k = Some(mid);
|
|
229
|
-
true
|
|
230
|
-
} else {
|
|
231
|
-
false
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
let k = best_k.unwrap_or(1);
|
|
196
|
+
if budgets.line_budget.is_some()
|
|
197
|
+
&& config.show_fileset_headers
|
|
198
|
+
&& root_is_fileset
|
|
199
|
+
{
|
|
200
|
+
measure_cfg.show_fileset_headers = false;
|
|
201
|
+
}
|
|
202
|
+
let (k, mut inclusion_flags, render_set_id) =
|
|
203
|
+
select_best_k(order_build, &measure_cfg, budgets);
|
|
236
204
|
|
|
237
205
|
// Prepare final inclusion set once and optionally build debug JSON.
|
|
238
206
|
crate::serialization::prepare_render_set_top_k_and_ancestors(
|
|
@@ -295,6 +263,53 @@ fn find_largest_render_under_budgets(
|
|
|
295
263
|
)
|
|
296
264
|
}
|
|
297
265
|
|
|
266
|
+
fn select_best_k(
|
|
267
|
+
order_build: &PriorityOrder,
|
|
268
|
+
measure_cfg: &RenderConfig,
|
|
269
|
+
budgets: Budgets,
|
|
270
|
+
) -> (usize, Vec<u32>, u32) {
|
|
271
|
+
let total = order_build.total_nodes;
|
|
272
|
+
// Each included node contributes at least some output; cap hi by budget.
|
|
273
|
+
let lo = 1usize;
|
|
274
|
+
// For the upper bound, when a byte budget is present, we can safely cap by it;
|
|
275
|
+
// otherwise, cap by total.
|
|
276
|
+
let hi = match budgets.byte_budget {
|
|
277
|
+
Some(c) => total.min(c.max(1)),
|
|
278
|
+
None => total,
|
|
279
|
+
};
|
|
280
|
+
// Reuse render-inclusion flags across render attempts to avoid clearing the vector.
|
|
281
|
+
let mut inclusion_flags: Vec<u32> = vec![0; total];
|
|
282
|
+
// Each render attempt bumps this non-zero identifier to create a fresh inclusion set.
|
|
283
|
+
let mut render_set_id: u32 = 1;
|
|
284
|
+
let mut best_k: Option<usize> = None;
|
|
285
|
+
let measure_chars = budgets.char_budget.is_some();
|
|
286
|
+
let _ = crate::utils::search::binary_search_max(lo, hi, |mid| {
|
|
287
|
+
let current_render_id = render_set_id;
|
|
288
|
+
let s = crate::serialization::render_top_k(
|
|
289
|
+
order_build,
|
|
290
|
+
mid,
|
|
291
|
+
&mut inclusion_flags,
|
|
292
|
+
current_render_id,
|
|
293
|
+
measure_cfg,
|
|
294
|
+
);
|
|
295
|
+
let stats =
|
|
296
|
+
crate::utils::measure::count_output_stats(&s, measure_chars);
|
|
297
|
+
let fits_bytes = budgets.byte_budget.is_none_or(|c| stats.bytes <= c);
|
|
298
|
+
let fits_chars = budgets.char_budget.is_none_or(|c| stats.chars <= c);
|
|
299
|
+
let fits_lines =
|
|
300
|
+
budgets.line_budget.is_none_or(|cap| stats.lines <= cap);
|
|
301
|
+
render_set_id = render_set_id.wrapping_add(1).max(1);
|
|
302
|
+
if fits_bytes && fits_chars && fits_lines {
|
|
303
|
+
best_k = Some(mid);
|
|
304
|
+
true
|
|
305
|
+
} else {
|
|
306
|
+
false
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
let k = best_k.unwrap_or(1);
|
|
310
|
+
(k, inclusion_flags, render_set_id)
|
|
311
|
+
}
|
|
312
|
+
|
|
298
313
|
// (removed) render_final helper was inlined to centralize optional debug dump
|
|
299
314
|
|
|
300
315
|
// Optional new public API that accepts both budgets explicitly.
|
|
@@ -64,6 +64,12 @@ struct Cli {
|
|
|
64
64
|
help = "Do not add newlines in the output. Incompatible with --lines/--global-lines."
|
|
65
65
|
)]
|
|
66
66
|
no_newline: bool,
|
|
67
|
+
#[arg(
|
|
68
|
+
long = "no-header",
|
|
69
|
+
default_value_t = false,
|
|
70
|
+
help = "Suppress fileset section headers in the output"
|
|
71
|
+
)]
|
|
72
|
+
no_header: bool,
|
|
67
73
|
#[arg(
|
|
68
74
|
short = 'm',
|
|
69
75
|
long = "compact",
|
|
@@ -525,6 +531,7 @@ fn get_render_config_from(cli: &Cli) -> headson::RenderConfig {
|
|
|
525
531
|
string_free_prefix_graphemes: None,
|
|
526
532
|
debug: cli.debug,
|
|
527
533
|
primary_source_name: None,
|
|
534
|
+
show_fileset_headers: !cli.no_header,
|
|
528
535
|
}
|
|
529
536
|
}
|
|
530
537
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use super::RenderScope;
|
|
2
2
|
use crate::format::Format;
|
|
3
|
-
use crate::order::{ObjectType, ROOT_PQ_ID};
|
|
3
|
+
use crate::order::{NodeId, ObjectType, ROOT_PQ_ID};
|
|
4
4
|
use crate::serialization::types::OutputTemplate;
|
|
5
5
|
|
|
6
6
|
impl<'a> RenderScope<'a> {
|
|
@@ -19,26 +19,68 @@ impl<'a> RenderScope<'a> {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
fn render_fileset_sections(&mut self, depth: usize) -> String {
|
|
22
|
-
let mut out = String::new();
|
|
23
22
|
let Some(children_ids) = self.order.children.get(ROOT_PQ_ID) else {
|
|
24
|
-
return
|
|
23
|
+
return String::new();
|
|
25
24
|
};
|
|
25
|
+
let show_headers = self.should_render_fileset_headers();
|
|
26
|
+
let mut out = String::new();
|
|
27
|
+
let kept = self.render_fileset_children(
|
|
28
|
+
children_ids,
|
|
29
|
+
depth,
|
|
30
|
+
show_headers,
|
|
31
|
+
&mut out,
|
|
32
|
+
);
|
|
33
|
+
if show_headers {
|
|
34
|
+
self.render_fileset_summary(children_ids, depth, kept, &mut out);
|
|
35
|
+
}
|
|
36
|
+
out
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fn fileset_push_section_gap(&self, out: &mut String) {
|
|
40
|
+
let nl = &self.config.newline;
|
|
41
|
+
out.push_str(nl);
|
|
42
|
+
out.push_str(nl);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fn should_render_fileset_headers(&self) -> bool {
|
|
46
|
+
self.config.show_fileset_headers && !self.config.newline.is_empty()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fn render_fileset_children(
|
|
50
|
+
&mut self,
|
|
51
|
+
children_ids: &[NodeId],
|
|
52
|
+
depth: usize,
|
|
53
|
+
show_headers: bool,
|
|
54
|
+
out: &mut String,
|
|
55
|
+
) -> usize {
|
|
26
56
|
let mut kept = 0usize;
|
|
27
|
-
for &child_id in children_ids
|
|
57
|
+
for &child_id in children_ids {
|
|
28
58
|
if self.inclusion_flags[child_id.0] != self.render_set_id {
|
|
29
59
|
continue;
|
|
30
60
|
}
|
|
31
|
-
if kept > 0 {
|
|
32
|
-
self.fileset_push_section_gap(
|
|
61
|
+
if kept > 0 && show_headers {
|
|
62
|
+
self.fileset_push_section_gap(out);
|
|
33
63
|
}
|
|
34
64
|
kept += 1;
|
|
35
65
|
let raw_key =
|
|
36
66
|
self.order.nodes[child_id.0].key_in_object().unwrap_or("");
|
|
37
|
-
|
|
67
|
+
if show_headers {
|
|
68
|
+
out.push_str(&self.fileset_header_line(depth, raw_key));
|
|
69
|
+
}
|
|
38
70
|
let rendered =
|
|
39
71
|
self.fileset_render_child(child_id.0, depth, raw_key);
|
|
40
72
|
out.push_str(&rendered);
|
|
41
73
|
}
|
|
74
|
+
kept
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fn render_fileset_summary(
|
|
78
|
+
&self,
|
|
79
|
+
children_ids: &[NodeId],
|
|
80
|
+
depth: usize,
|
|
81
|
+
kept: usize,
|
|
82
|
+
out: &mut String,
|
|
83
|
+
) {
|
|
42
84
|
let total = self
|
|
43
85
|
.order
|
|
44
86
|
.metrics
|
|
@@ -46,16 +88,9 @@ impl<'a> RenderScope<'a> {
|
|
|
46
88
|
.and_then(|m| m.object_len)
|
|
47
89
|
.unwrap_or(children_ids.len());
|
|
48
90
|
if total > kept && !self.config.newline.is_empty() {
|
|
49
|
-
self.fileset_push_section_gap(
|
|
91
|
+
self.fileset_push_section_gap(out);
|
|
50
92
|
out.push_str(&self.fileset_summary_line(depth, total - kept));
|
|
51
93
|
}
|
|
52
|
-
out
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
fn fileset_push_section_gap(&self, out: &mut String) {
|
|
56
|
-
let nl = &self.config.newline;
|
|
57
|
-
out.push_str(nl);
|
|
58
|
-
out.push_str(nl);
|
|
59
94
|
}
|
|
60
95
|
|
|
61
96
|
fn fileset_header_line(&self, depth: usize, key: &str) -> String {
|
|
@@ -936,6 +936,7 @@ mod tests {
|
|
|
936
936
|
string_free_prefix_graphemes: None,
|
|
937
937
|
debug: false,
|
|
938
938
|
primary_source_name: None,
|
|
939
|
+
show_fileset_headers: true,
|
|
939
940
|
},
|
|
940
941
|
);
|
|
941
942
|
assert_snapshot!("arena_render_empty", out);
|
|
@@ -974,6 +975,7 @@ mod tests {
|
|
|
974
975
|
string_free_prefix_graphemes: None,
|
|
975
976
|
debug: false,
|
|
976
977
|
primary_source_name: None,
|
|
978
|
+
show_fileset_headers: true,
|
|
977
979
|
},
|
|
978
980
|
);
|
|
979
981
|
// Sanity: output should contain CRLF newlines and render the object child across lines.
|
|
@@ -1014,6 +1016,7 @@ mod tests {
|
|
|
1014
1016
|
string_free_prefix_graphemes: None,
|
|
1015
1017
|
debug: false,
|
|
1016
1018
|
primary_source_name: None,
|
|
1019
|
+
show_fileset_headers: true,
|
|
1017
1020
|
},
|
|
1018
1021
|
);
|
|
1019
1022
|
assert_snapshot!("arena_render_single", out);
|
|
@@ -1055,6 +1058,7 @@ mod tests {
|
|
|
1055
1058
|
string_free_prefix_graphemes: None,
|
|
1056
1059
|
debug: false,
|
|
1057
1060
|
primary_source_name: None,
|
|
1061
|
+
show_fileset_headers: true,
|
|
1058
1062
|
},
|
|
1059
1063
|
);
|
|
1060
1064
|
assert_snapshot!("array_omitted_pseudo_head", out_head);
|
|
@@ -1077,6 +1081,7 @@ mod tests {
|
|
|
1077
1081
|
string_free_prefix_graphemes: None,
|
|
1078
1082
|
debug: false,
|
|
1079
1083
|
primary_source_name: None,
|
|
1084
|
+
show_fileset_headers: true,
|
|
1080
1085
|
},
|
|
1081
1086
|
);
|
|
1082
1087
|
assert_snapshot!("array_omitted_pseudo_tail", out_tail);
|
|
@@ -1116,6 +1121,7 @@ mod tests {
|
|
|
1116
1121
|
string_free_prefix_graphemes: None,
|
|
1117
1122
|
debug: false,
|
|
1118
1123
|
primary_source_name: None,
|
|
1124
|
+
show_fileset_headers: true,
|
|
1119
1125
|
},
|
|
1120
1126
|
);
|
|
1121
1127
|
assert_snapshot!("array_omitted_js_head", out_head);
|
|
@@ -1137,6 +1143,7 @@ mod tests {
|
|
|
1137
1143
|
string_free_prefix_graphemes: None,
|
|
1138
1144
|
debug: false,
|
|
1139
1145
|
primary_source_name: None,
|
|
1146
|
+
show_fileset_headers: true,
|
|
1140
1147
|
},
|
|
1141
1148
|
);
|
|
1142
1149
|
assert_snapshot!("array_omitted_js_tail", out_tail);
|
|
@@ -1176,6 +1183,7 @@ mod tests {
|
|
|
1176
1183
|
string_free_prefix_graphemes: None,
|
|
1177
1184
|
debug: false,
|
|
1178
1185
|
primary_source_name: None,
|
|
1186
|
+
show_fileset_headers: true,
|
|
1179
1187
|
},
|
|
1180
1188
|
);
|
|
1181
1189
|
assert_yaml_valid(&out_head);
|
|
@@ -1198,6 +1206,7 @@ mod tests {
|
|
|
1198
1206
|
string_free_prefix_graphemes: None,
|
|
1199
1207
|
debug: false,
|
|
1200
1208
|
primary_source_name: None,
|
|
1209
|
+
show_fileset_headers: true,
|
|
1201
1210
|
},
|
|
1202
1211
|
);
|
|
1203
1212
|
assert_yaml_valid(&out_tail);
|
|
@@ -1234,6 +1243,7 @@ mod tests {
|
|
|
1234
1243
|
string_free_prefix_graphemes: None,
|
|
1235
1244
|
debug: false,
|
|
1236
1245
|
primary_source_name: None,
|
|
1246
|
+
show_fileset_headers: true,
|
|
1237
1247
|
},
|
|
1238
1248
|
);
|
|
1239
1249
|
assert_yaml_valid(&out);
|
|
@@ -1270,6 +1280,7 @@ mod tests {
|
|
|
1270
1280
|
string_free_prefix_graphemes: None,
|
|
1271
1281
|
debug: false,
|
|
1272
1282
|
primary_source_name: None,
|
|
1283
|
+
show_fileset_headers: true,
|
|
1273
1284
|
},
|
|
1274
1285
|
);
|
|
1275
1286
|
assert_yaml_valid(&out);
|
|
@@ -1304,6 +1315,7 @@ mod tests {
|
|
|
1304
1315
|
string_free_prefix_graphemes: None,
|
|
1305
1316
|
debug: false,
|
|
1306
1317
|
primary_source_name: None,
|
|
1318
|
+
show_fileset_headers: true,
|
|
1307
1319
|
},
|
|
1308
1320
|
);
|
|
1309
1321
|
assert_yaml_valid(&out);
|
|
@@ -1366,6 +1378,7 @@ mod tests {
|
|
|
1366
1378
|
string_free_prefix_graphemes: None,
|
|
1367
1379
|
debug: false,
|
|
1368
1380
|
primary_source_name: None,
|
|
1381
|
+
show_fileset_headers: true,
|
|
1369
1382
|
},
|
|
1370
1383
|
);
|
|
1371
1384
|
assert_yaml_valid(&out);
|
|
@@ -1439,6 +1452,7 @@ mod tests {
|
|
|
1439
1452
|
string_free_prefix_graphemes: None,
|
|
1440
1453
|
debug: false,
|
|
1441
1454
|
primary_source_name: None,
|
|
1455
|
+
show_fileset_headers: true,
|
|
1442
1456
|
},
|
|
1443
1457
|
);
|
|
1444
1458
|
// Expect the first 5 characters plus an ellipsis, as a valid JSON string literal.
|
|
@@ -1475,6 +1489,7 @@ mod tests {
|
|
|
1475
1489
|
string_free_prefix_graphemes: None,
|
|
1476
1490
|
debug: false,
|
|
1477
1491
|
primary_source_name: None,
|
|
1492
|
+
show_fileset_headers: true,
|
|
1478
1493
|
},
|
|
1479
1494
|
);
|
|
1480
1495
|
assert_yaml_valid(&out);
|
|
@@ -1518,6 +1533,7 @@ mod tests {
|
|
|
1518
1533
|
string_free_prefix_graphemes: None,
|
|
1519
1534
|
debug: false,
|
|
1520
1535
|
primary_source_name: None,
|
|
1536
|
+
show_fileset_headers: true,
|
|
1521
1537
|
};
|
|
1522
1538
|
let scope = RenderScope {
|
|
1523
1539
|
order: &build,
|
|
@@ -1560,6 +1576,7 @@ mod tests {
|
|
|
1560
1576
|
string_free_prefix_graphemes: None,
|
|
1561
1577
|
debug: false,
|
|
1562
1578
|
primary_source_name: None,
|
|
1579
|
+
show_fileset_headers: true,
|
|
1563
1580
|
},
|
|
1564
1581
|
);
|
|
1565
1582
|
assert_snapshot!("inline_open_array_in_object_json", out);
|
|
@@ -1597,6 +1614,7 @@ mod tests {
|
|
|
1597
1614
|
string_free_prefix_graphemes: None,
|
|
1598
1615
|
debug: false,
|
|
1599
1616
|
primary_source_name: None,
|
|
1617
|
+
show_fileset_headers: true,
|
|
1600
1618
|
},
|
|
1601
1619
|
);
|
|
1602
1620
|
// Should be a valid JS object with one property and an omitted summary.
|
|
@@ -1649,6 +1667,7 @@ mod tests {
|
|
|
1649
1667
|
string_free_prefix_graphemes: None,
|
|
1650
1668
|
debug: false,
|
|
1651
1669
|
primary_source_name: None,
|
|
1670
|
+
show_fileset_headers: true,
|
|
1652
1671
|
}
|
|
1653
1672
|
}
|
|
1654
1673
|
|
|
@@ -43,6 +43,8 @@ pub struct RenderConfig {
|
|
|
43
43
|
// a single logical input outside of filesets. Used by code-specific
|
|
44
44
|
// features such as syntax highlighting.
|
|
45
45
|
pub primary_source_name: Option<String>,
|
|
46
|
+
// When false, suppress fileset section headers and summary lines.
|
|
47
|
+
pub show_fileset_headers: bool,
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
@@ -10,8 +10,16 @@ fn count_lines_from_bytes(b: &[u8]) -> usize {
|
|
|
10
10
|
if b.is_empty() {
|
|
11
11
|
return 0;
|
|
12
12
|
}
|
|
13
|
-
let mut
|
|
13
|
+
let mut lines = count_line_breaks(b).saturating_add(1);
|
|
14
|
+
if ends_with_break(b) && lines > 0 {
|
|
15
|
+
lines -= 1;
|
|
16
|
+
}
|
|
17
|
+
lines
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fn count_line_breaks(b: &[u8]) -> usize {
|
|
14
21
|
let mut breaks = 0usize;
|
|
22
|
+
let mut i = 0usize;
|
|
15
23
|
while i < b.len() {
|
|
16
24
|
match b[i] {
|
|
17
25
|
b'\n' => {
|
|
@@ -21,7 +29,7 @@ fn count_lines_from_bytes(b: &[u8]) -> usize {
|
|
|
21
29
|
b'\r' => {
|
|
22
30
|
breaks += 1;
|
|
23
31
|
if i + 1 < b.len() && b[i + 1] == b'\n' {
|
|
24
|
-
i += 2;
|
|
32
|
+
i += 2;
|
|
25
33
|
} else {
|
|
26
34
|
i += 1;
|
|
27
35
|
}
|
|
@@ -29,7 +37,11 @@ fn count_lines_from_bytes(b: &[u8]) -> usize {
|
|
|
29
37
|
_ => i += 1,
|
|
30
38
|
}
|
|
31
39
|
}
|
|
32
|
-
breaks
|
|
40
|
+
breaks
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fn ends_with_break(b: &[u8]) -> bool {
|
|
44
|
+
b.ends_with(b"\n") || (b.ends_with(b"\r") && !b.ends_with(b"\r\n"))
|
|
33
45
|
}
|
|
34
46
|
|
|
35
47
|
/// Count bytes and logical lines in a string, normalizing CRLF/CR/LF.
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|