mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 03:38:23 +00:00
refactor(cli): give each amy status saved item its own line
A busy account lists six or seven footprint items. Joined with `·` and
wrapped at 78 columns they read as one run-on sentence that has to be
parsed; a column of short lines scans in one pass:
saved: 128 events (newest 2h ago)
3 contacts
2 Marmot groups
a published key package
Drops the wrap machinery (`appendWrapped`, the fixed WIDTH) for a plain
hanging indent. `saved: nothing yet` is unchanged, and so is `--json`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AtKhnNBSr9CWnZyjTWu7dL
This commit is contained in:
@@ -28,16 +28,23 @@ import java.io.File
|
||||
* The terminal rendering of [StatusCommand] — the one command whose answer
|
||||
* the generic key/value renderer buries.
|
||||
*
|
||||
* One block per account, four lines at most:
|
||||
* One block per account — three lines of identity, then one line per
|
||||
* thing the account has saved:
|
||||
*
|
||||
* ```
|
||||
* alice (current)
|
||||
* Alice Jones · alice@example.com
|
||||
* npub1hje47kz5qeneyqrxc9nzgmz06ml6l9lguqv0qtsz4rkwqkmf636qvg4sz3
|
||||
* local key, in the login keychain
|
||||
* saved: 128 events (newest 2h ago) · 3 contacts · 2 Marmot groups
|
||||
* saved: 128 events (newest 2h ago)
|
||||
* 3 contacts
|
||||
* 2 Marmot groups
|
||||
* ```
|
||||
*
|
||||
* The footprint gets a line per item rather than one `·`-joined run: a
|
||||
* busy account lists six or seven of them, and a column of short lines
|
||||
* scans in one pass where a wrapped sentence does not.
|
||||
*
|
||||
* The rule that keeps it short: **absent is silent**. A profile the store
|
||||
* hasn't seen, a footprint an account doesn't have — those lines simply
|
||||
* don't print, instead of printing as `(none)` / `no` / `0`. Only the npub
|
||||
@@ -49,11 +56,8 @@ import java.io.File
|
||||
internal object StatusText {
|
||||
private const val DOT = " · "
|
||||
|
||||
/**
|
||||
* Wrap column for the `saved:` list. Fixed rather than probed: JDK 21
|
||||
* offers no terminal width, and 80 is the floor every terminal honours.
|
||||
*/
|
||||
private const val WIDTH = 78
|
||||
/** Hanging indent for the `saved:` list — the visible width of `" saved: "`. */
|
||||
private val SAVED_INDENT = " ".repeat(" saved: ".length)
|
||||
|
||||
fun render(
|
||||
rootBase: File,
|
||||
@@ -100,46 +104,16 @@ internal object StatusText {
|
||||
out.append(" ").append(signerLine(account.name, account.signer, color)).append('\n')
|
||||
if (account.npub == null) return
|
||||
|
||||
// Line 4 — the footprint, or one honest word when there isn't one.
|
||||
// A busy account can list six things, so it wraps under its label.
|
||||
// Then the footprint — one line per item, hanging off the label — or
|
||||
// one honest word when there isn't one.
|
||||
val label = " " + color.dim("saved:") + " "
|
||||
if (account.saved.isEmpty) {
|
||||
out.append(label).append(color.dim("nothing yet")).append('\n')
|
||||
} else {
|
||||
appendWrapped(out, label, indent = " ", parts = savedParts(account.saved))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Join [parts] with [DOT] across as many lines as it takes to stay inside
|
||||
* [WIDTH], continuing under [indent] (which must be as wide as the visible
|
||||
* [label]). The separator stays at the end of a line, so a wrapped list
|
||||
* still reads as one run-on item rather than a new heading.
|
||||
*/
|
||||
private fun appendWrapped(
|
||||
out: StringBuilder,
|
||||
label: String,
|
||||
indent: String,
|
||||
parts: List<String>,
|
||||
) {
|
||||
out.append(label)
|
||||
var used = indent.length
|
||||
parts.forEachIndexed { i, part ->
|
||||
val isLast = i == parts.lastIndex
|
||||
val piece = if (isLast) part else part + DOT.trimEnd()
|
||||
if (i > 0) {
|
||||
if (used + 1 + piece.length > WIDTH) {
|
||||
out.append('\n').append(indent)
|
||||
used = indent.length
|
||||
} else {
|
||||
out.append(' ')
|
||||
used += 1
|
||||
}
|
||||
savedParts(account.saved).forEachIndexed { i, part ->
|
||||
out.append(if (i == 0) label else SAVED_INDENT).append(part).append('\n')
|
||||
}
|
||||
out.append(piece)
|
||||
used += piece.length
|
||||
}
|
||||
out.append('\n')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,8 +157,8 @@ internal object StatusText {
|
||||
}
|
||||
|
||||
/**
|
||||
* The footprint, most-interesting first, absent items omitted. Reads as
|
||||
* a sentence fragment: `128 events (newest 2h ago) · 3 contacts · …`.
|
||||
* The footprint, most-interesting first, absent items omitted. One
|
||||
* self-contained phrase per entry, since each gets its own line.
|
||||
*/
|
||||
private fun savedParts(saved: StatusReport.Saved): List<String> {
|
||||
val parts = mutableListOf<String>()
|
||||
|
||||
Reference in New Issue
Block a user