feat: truncate --fields body uniformly (task 0021)
Rule that the `body` extra field truncates at 500 chars like `issue view`, resolving the spec's Principle 3 / Command Surface contradiction. Route the `body` extractor through a new `truncatedBody()` FieldDef so `issue list`, `issue create`, `pr list`, and `search` all present it exactly as the detail views do, and add a `--full` flag to each to suppress truncation, keeping the inline hint's "use --full" promise honest.
This commit was merged in pull request #21.
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
import { BODY_TRUNCATE_LIMIT, truncateBody } from "./body.js";
|
||||
import { axiError } from "./errors.js";
|
||||
import { relativeTime } from "./time.js";
|
||||
|
||||
export interface ExtractContext {
|
||||
now: Date;
|
||||
/** Hostname for `cleanBody`'s Gitea URL normalization when a body is truncated. */
|
||||
host: string;
|
||||
/** When set, `truncatedBody` returns the raw body — the `--full` affordance. */
|
||||
full: boolean;
|
||||
}
|
||||
|
||||
export interface FieldDef<T> {
|
||||
@@ -66,6 +71,26 @@ export function joined<T>(name: string, path: string, key: string): FieldDef<T>
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a `body` field under Principle 3's content truncation — identical to
|
||||
* how `issue view` / `pr view` present a body: over-limit bodies are cleaned and
|
||||
* cut to 500 chars with the inline "... (truncated, N chars total ...)" hint,
|
||||
* while short bodies pass through byte-for-byte. `context.full` (the `--full`
|
||||
* flag) suppresses truncation and returns the raw body. This is the single
|
||||
* ruling applied everywhere `body` is offered via `--fields` (see task 0021):
|
||||
* `issue list --limit 30 --fields body` must not spill 30 full bodies into an
|
||||
* agent's context, the exact cost the truncation principle exists to prevent.
|
||||
*/
|
||||
export function truncatedBody<T>(name: string, path: string = name): FieldDef<T> {
|
||||
return {
|
||||
name,
|
||||
extract: (raw, context) => {
|
||||
const value = String(pluckPath(raw, path) ?? "");
|
||||
return context.full ? value : truncateBody(value, BODY_TRUNCATE_LIMIT, context.host);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function relativeTimeField<T>(name: string, path: string): FieldDef<T> {
|
||||
return {
|
||||
name,
|
||||
|
||||
Reference in New Issue
Block a user