fix style

This commit is contained in:
Simon Klee
2026-04-17 23:26:59 +02:00
parent 6208f49750
commit a91c49390b
4 changed files with 104 additions and 45 deletions

View File

@@ -182,37 +182,37 @@ export class RunScrollbackStream {
const renderable =
body.type === "text"
? new TextRenderable(surface.renderContext, {
id,
content: "",
width: "100%",
wrapMode: "word",
fg: look(commit, this.theme.entry).fg,
attributes: look(commit, this.theme.entry).attrs,
})
id,
content: "",
width: "100%",
wrapMode: "word",
fg: look(commit, this.theme.entry).fg,
attributes: look(commit, this.theme.entry).attrs,
})
: body.type === "code"
? new CodeRenderable(surface.renderContext, {
id,
content: "",
filetype: body.filetype,
syntaxStyle: syntaxFor(commit, this.theme),
width: "100%",
wrapMode: "word",
drawUnstyledText: false,
streaming: true,
fg: entryColor(commit, this.theme),
treeSitterClient: this.treeSitterClient,
})
id,
content: "",
filetype: body.filetype,
syntaxStyle: syntaxFor(commit, this.theme),
width: "100%",
wrapMode: "word",
drawUnstyledText: false,
streaming: true,
fg: entryColor(commit, this.theme),
treeSitterClient: this.treeSitterClient,
})
: new MarkdownRenderable(surface.renderContext, {
id,
content: "",
syntaxStyle: syntaxFor(commit, this.theme),
width: "100%",
streaming: true,
internalBlockMode: "top-level",
tableOptions: { widthMode: "content" },
fg: entryColor(commit, this.theme),
treeSitterClient: this.treeSitterClient,
})
id,
content: "",
syntaxStyle: syntaxFor(commit, this.theme),
width: "100%",
streaming: true,
internalBlockMode: "top-level",
tableOptions: { widthMode: "content" },
fg: entryColor(commit, this.theme),
treeSitterClient: this.treeSitterClient,
})
surface.root.add(renderable)

View File

@@ -103,21 +103,6 @@ function entryColor(commit: StreamCommit, theme: RunTheme): ColorInput {
return look(commit, theme.entry).fg
}
function blankWriter(): ScrollbackWriter {
return (ctx) => ({
root: new TextRenderable(ctx.renderContext, {
id: "run-scrollback-spacer",
width: Math.max(1, Math.trunc(ctx.width)),
height: 1,
content: "",
}),
width: Math.max(1, Math.trunc(ctx.width)),
height: 1,
startOnNewLine: true,
trailingNewline: true,
})
}
function todoText(item: { status: string; content: string }): string {
if (item.status === "completed") {
return `[x] ${item.content}`
@@ -359,5 +344,16 @@ export function entryWriter(input: {
}
export function spacerWriter(): ScrollbackWriter {
return blankWriter()
return (ctx) => ({
root: new TextRenderable(ctx.renderContext, {
id: "run-scrollback-spacer",
width: Math.max(1, Math.trunc(ctx.width)),
height: 1,
content: "",
}),
width: Math.max(1, Math.trunc(ctx.width)),
height: 1,
startOnNewLine: true,
trailingNewline: true,
})
}

View File

@@ -99,8 +99,42 @@ function fade(color: RGBA, base: RGBA, fallback: number, scale: number, limit: n
)
}
function blend(color: RGBA, bg: RGBA): RGBA {
if (color.a >= 1) {
return color
}
return RGBA.fromValues(
bg.r + (color.r - bg.r) * color.a,
bg.g + (color.g - bg.g) * color.a,
bg.b + (color.b - bg.b) * color.a,
1,
)
}
export function opaqueSyntaxStyle(style: SyntaxStyle | undefined, bg: RGBA): SyntaxStyle | undefined {
if (!style) {
return
}
return SyntaxStyle.fromStyles(
Object.fromEntries(
[...style.getAllStyles()].map(([name, value]) => [
name,
{
...value,
fg: value.fg ? blend(value.fg, bg) : value.fg,
bg: value.bg ? blend(value.bg, bg) : value.bg,
},
]),
),
)
}
function map(theme: TuiThemeCurrent, syntax?: SyntaxStyle, subtleSyntax?: SyntaxStyle): RunTheme {
const bg = theme.background
const opaqueSubtleSyntax = opaqueSyntaxStyle(subtleSyntax, bg)
subtleSyntax?.destroy()
const pane = theme.backgroundElement
const shade = fade(pane, bg, 0.12, 0.56, 0.72)
const surface = fade(pane, bg, 0.18, 0.76, 0.9)
@@ -146,7 +180,7 @@ function map(theme: TuiThemeCurrent, syntax?: SyntaxStyle, subtleSyntax?: Syntax
text: theme.text,
muted: theme.textMuted,
syntax,
subtleSyntax,
subtleSyntax: opaqueSubtleSyntax,
diffAdded: theme.diffAdded,
diffRemoved: theme.diffRemoved,
diffAddedBg: theme.diffAddedBg,

View File

@@ -0,0 +1,29 @@
import { describe, expect, test } from "bun:test"
import { RGBA, SyntaxStyle } from "@opentui/core"
import { opaqueSyntaxStyle } from "../../../src/cli/cmd/run/theme"
describe("run theme", () => {
test("flattens subtle syntax alpha against the run background", () => {
const syntax = SyntaxStyle.fromStyles({
default: {
fg: RGBA.fromInts(169, 177, 214, 153),
},
emphasis: {
fg: RGBA.fromInts(224, 175, 104, 153),
italic: true,
bold: true,
},
})
const subtle = opaqueSyntaxStyle(syntax, RGBA.fromInts(42, 43, 61))
try {
expect(subtle?.getStyle("default")?.fg?.toInts()).toEqual([118, 123, 153, 255])
expect(subtle?.getStyle("emphasis")?.fg?.toInts()).toEqual([151, 122, 87, 255])
expect(subtle?.getStyle("emphasis")?.italic).toBe(true)
expect(subtle?.getStyle("emphasis")?.bold).toBe(true)
} finally {
syntax.destroy()
subtle?.destroy()
}
})
})