mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-17 09:34:21 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4ff8dd205 | ||
|
|
0e035b3115 | ||
|
|
b855511d9a | ||
|
|
783faf554d | ||
|
|
bfd4269d7d | ||
|
|
25f78b053b | ||
|
|
87f260ee17 | ||
|
|
12931a869d | ||
|
|
f759e1804d |
@@ -116,7 +116,7 @@ $ bun run src/index.ts
|
||||
|
||||
### FAQ
|
||||
|
||||
#### How do I use this with OpenRou?ter
|
||||
#### How do I use this with OpenRouter
|
||||
|
||||
OpenRouter is not yet in the models.dev database but you can configure it manually.
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
"baseURL": "http://localhost:11434/v1"
|
||||
},
|
||||
"models": {
|
||||
"llama2": {
|
||||
"name": "llama2"
|
||||
}
|
||||
"qwen3": {},
|
||||
"deepseek-r1": {},
|
||||
"llama2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,19 @@
|
||||
- **Naming**: camelCase for variables/functions, PascalCase for classes/namespaces
|
||||
- **Error handling**: Use Result patterns, avoid throwing exceptions in tools
|
||||
- **File structure**: Namespace-based organization (e.g., `Tool.define()`, `Session.create()`)
|
||||
|
||||
## IMPORTANT
|
||||
|
||||
- Try to keep things in one function unless composable or reusable
|
||||
- DO NOT do unnecessary destructuring of variables
|
||||
- DO NOT use else statements unless necessary
|
||||
- DO NOT use try catch if it can be avoided
|
||||
- AVOID try catch where possible
|
||||
- AVOID else statements
|
||||
- AVOID using `any` type
|
||||
- AVOID let statements
|
||||
- PREFER single word variable names where possible
|
||||
- Use as many bun apis as possible like Bun.file()
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -27,4 +37,3 @@
|
||||
- **Validation**: All inputs validated with Zod schemas
|
||||
- **Logging**: Use `Log.create({ service: "name" })` pattern
|
||||
- **Storage**: Use `Storage` namespace for persistence
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ if (!snapshot) {
|
||||
.filter((x: string) => {
|
||||
const lower = x.toLowerCase()
|
||||
return (
|
||||
!lower.includes("chore:") &&
|
||||
!lower.includes("ignore:") &&
|
||||
!lower.includes("ci:") &&
|
||||
!lower.includes("docs:") &&
|
||||
!lower.includes("doc:")
|
||||
|
||||
@@ -111,8 +111,12 @@ export const AuthLoginCommand = cmd({
|
||||
// some weird bug where program exits without this
|
||||
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||
const { url, verifier } = await AuthAnthropic.authorize()
|
||||
prompts.note("Opening browser...")
|
||||
await open(url)
|
||||
prompts.note("Trying to open browser...")
|
||||
try {
|
||||
await open(url)
|
||||
} catch (e) {
|
||||
prompts.log.error("Failed to open browser perhaps you are running without a display or X server, please open the following URL in your browser:")
|
||||
}
|
||||
prompts.log.info(url)
|
||||
|
||||
const code = await prompts.text({
|
||||
|
||||
@@ -115,6 +115,9 @@ export const RunCommand = {
|
||||
})
|
||||
|
||||
const { providerID, modelID } = await Provider.defaultModel()
|
||||
setTimeout(() => {
|
||||
Session.abort(session.id)
|
||||
}, 8000)
|
||||
await Session.chat({
|
||||
sessionID: session.id,
|
||||
providerID,
|
||||
|
||||
@@ -3,11 +3,8 @@ import { App } from "./app/app"
|
||||
import { Server } from "./server/server"
|
||||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
|
||||
import { Share } from "./share/share"
|
||||
|
||||
import { Global } from "./global"
|
||||
|
||||
import yargs from "yargs"
|
||||
import { hideBin } from "yargs/helpers"
|
||||
import { RunCommand } from "./cli/cmd/run"
|
||||
|
||||
@@ -6,13 +6,13 @@ import { Log } from "../util/log"
|
||||
import {
|
||||
generateText,
|
||||
LoadAPIKeyError,
|
||||
convertToCoreMessages,
|
||||
streamText,
|
||||
tool,
|
||||
type Tool as AITool,
|
||||
type LanguageModelUsage,
|
||||
type CoreMessage,
|
||||
type UserContent,
|
||||
type AssistantContent,
|
||||
type UIMessage,
|
||||
} from "ai"
|
||||
import { z, ZodSchema } from "zod"
|
||||
import { Decimal } from "decimal.js"
|
||||
@@ -236,10 +236,13 @@ export namespace Session {
|
||||
content: x,
|
||||
}),
|
||||
),
|
||||
{
|
||||
role: "user",
|
||||
content: toUserContent(input.parts),
|
||||
},
|
||||
...convertToCoreMessages([
|
||||
{
|
||||
role: "user",
|
||||
content: "",
|
||||
parts: toParts(input.parts),
|
||||
},
|
||||
]),
|
||||
],
|
||||
model: model.language,
|
||||
})
|
||||
@@ -402,7 +405,7 @@ export namespace Session {
|
||||
await updateMessage(next)
|
||||
},
|
||||
onError(err) {
|
||||
log.error("error", err)
|
||||
log.error("callback error", err)
|
||||
switch (true) {
|
||||
case LoadAPIKeyError.isInstance(err.error):
|
||||
next.metadata.error = new Provider.AuthError(
|
||||
@@ -446,26 +449,9 @@ export namespace Session {
|
||||
content: x,
|
||||
}),
|
||||
),
|
||||
...msgs.flatMap((msg): CoreMessage[] => {
|
||||
switch (msg.role) {
|
||||
case "user":
|
||||
return [
|
||||
{
|
||||
role: "user",
|
||||
content: toUserContent(msg.parts),
|
||||
},
|
||||
]
|
||||
case "assistant":
|
||||
return [
|
||||
{
|
||||
role: "assistant",
|
||||
content: toAssistantContent(msg.parts),
|
||||
},
|
||||
]
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}),
|
||||
...convertToCoreMessages(
|
||||
msgs.map(toUIMessage).filter((x) => x.parts.length > 0),
|
||||
),
|
||||
],
|
||||
temperature: model.info.id === "codex-mini-latest" ? undefined : 0,
|
||||
tools: {
|
||||
@@ -474,108 +460,132 @@ export namespace Session {
|
||||
},
|
||||
model: model.language,
|
||||
})
|
||||
for await (const value of result.fullStream) {
|
||||
l.info("part", {
|
||||
type: value.type,
|
||||
})
|
||||
switch (value.type) {
|
||||
case "step-start":
|
||||
next.parts.push({
|
||||
type: "step-start",
|
||||
})
|
||||
break
|
||||
case "text-delta":
|
||||
if (!text) {
|
||||
text = {
|
||||
type: "text",
|
||||
text: value.textDelta,
|
||||
}
|
||||
next.parts.push(text)
|
||||
try {
|
||||
for await (const value of result.fullStream) {
|
||||
l.info("part", {
|
||||
type: value.type,
|
||||
})
|
||||
switch (value.type) {
|
||||
case "step-start":
|
||||
next.parts.push({
|
||||
type: "step-start",
|
||||
})
|
||||
break
|
||||
case "text-delta":
|
||||
if (!text) {
|
||||
text = {
|
||||
type: "text",
|
||||
text: value.textDelta,
|
||||
}
|
||||
next.parts.push(text)
|
||||
break
|
||||
} else text.text += value.textDelta
|
||||
break
|
||||
} else text.text += value.textDelta
|
||||
break
|
||||
|
||||
case "tool-call": {
|
||||
const [match] = next.parts.flatMap((p) =>
|
||||
p.type === "tool-invocation" &&
|
||||
p.toolInvocation.toolCallId === value.toolCallId
|
||||
? [p]
|
||||
: [],
|
||||
)
|
||||
if (!match) break
|
||||
match.toolInvocation.args = value.args
|
||||
match.toolInvocation.state = "call"
|
||||
Bus.publish(Message.Event.PartUpdated, {
|
||||
part: match,
|
||||
messageID: next.id,
|
||||
sessionID: next.metadata.sessionID,
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
case "tool-call-streaming-start":
|
||||
next.parts.push({
|
||||
type: "tool-invocation",
|
||||
toolInvocation: {
|
||||
state: "partial-call",
|
||||
toolName: value.toolName,
|
||||
toolCallId: value.toolCallId,
|
||||
args: {},
|
||||
},
|
||||
})
|
||||
Bus.publish(Message.Event.PartUpdated, {
|
||||
part: next.parts[next.parts.length - 1],
|
||||
messageID: next.id,
|
||||
sessionID: next.metadata.sessionID,
|
||||
})
|
||||
break
|
||||
|
||||
case "tool-call-delta":
|
||||
break
|
||||
|
||||
// for some reason ai sdk claims to not send this part but it does
|
||||
// @ts-expect-error
|
||||
case "tool-result":
|
||||
const match = next.parts.find(
|
||||
(p) =>
|
||||
case "tool-call": {
|
||||
const [match] = next.parts.flatMap((p) =>
|
||||
p.type === "tool-invocation" &&
|
||||
// @ts-expect-error
|
||||
p.toolInvocation.toolCallId === value.toolCallId,
|
||||
)
|
||||
if (match && match.type === "tool-invocation") {
|
||||
match.toolInvocation = {
|
||||
// @ts-expect-error
|
||||
args: value.args,
|
||||
// @ts-expect-error
|
||||
toolCallId: value.toolCallId,
|
||||
// @ts-expect-error
|
||||
toolName: value.toolName,
|
||||
state: "result",
|
||||
// @ts-expect-error
|
||||
result: value.result as string,
|
||||
}
|
||||
p.toolInvocation.toolCallId === value.toolCallId
|
||||
? [p]
|
||||
: [],
|
||||
)
|
||||
if (!match) break
|
||||
match.toolInvocation.args = value.args
|
||||
match.toolInvocation.state = "call"
|
||||
Bus.publish(Message.Event.PartUpdated, {
|
||||
part: match,
|
||||
messageID: next.id,
|
||||
sessionID: next.metadata.sessionID,
|
||||
})
|
||||
break
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
l.info("unhandled", {
|
||||
type: value.type,
|
||||
})
|
||||
case "tool-call-streaming-start":
|
||||
next.parts.push({
|
||||
type: "tool-invocation",
|
||||
toolInvocation: {
|
||||
state: "partial-call",
|
||||
toolName: value.toolName,
|
||||
toolCallId: value.toolCallId,
|
||||
args: {},
|
||||
},
|
||||
})
|
||||
Bus.publish(Message.Event.PartUpdated, {
|
||||
part: next.parts[next.parts.length - 1],
|
||||
messageID: next.id,
|
||||
sessionID: next.metadata.sessionID,
|
||||
})
|
||||
break
|
||||
|
||||
case "tool-call-delta":
|
||||
break
|
||||
|
||||
// for some reason ai sdk claims to not send this part but it does
|
||||
// @ts-expect-error
|
||||
case "tool-result":
|
||||
const match = next.parts.find(
|
||||
(p) =>
|
||||
p.type === "tool-invocation" &&
|
||||
// @ts-expect-error
|
||||
p.toolInvocation.toolCallId === value.toolCallId,
|
||||
)
|
||||
if (match && match.type === "tool-invocation") {
|
||||
match.toolInvocation = {
|
||||
// @ts-expect-error
|
||||
args: value.args,
|
||||
// @ts-expect-error
|
||||
toolCallId: value.toolCallId,
|
||||
// @ts-expect-error
|
||||
toolName: value.toolName,
|
||||
state: "result",
|
||||
// @ts-expect-error
|
||||
result: value.result as string,
|
||||
}
|
||||
Bus.publish(Message.Event.PartUpdated, {
|
||||
part: match,
|
||||
messageID: next.id,
|
||||
sessionID: next.metadata.sessionID,
|
||||
})
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
l.info("unhandled", {
|
||||
type: value.type,
|
||||
})
|
||||
}
|
||||
await updateMessage(next)
|
||||
}
|
||||
await updateMessage(next)
|
||||
} catch (e: any) {
|
||||
log.error("stream error", {
|
||||
error: e,
|
||||
})
|
||||
switch (true) {
|
||||
case LoadAPIKeyError.isInstance(e):
|
||||
next.metadata.error = new Provider.AuthError(
|
||||
{
|
||||
providerID: input.providerID,
|
||||
message: e.message,
|
||||
},
|
||||
{ cause: e },
|
||||
).toObject()
|
||||
break
|
||||
case e instanceof Error:
|
||||
next.metadata.error = new NamedError.Unknown(
|
||||
{ message: e.toString() },
|
||||
{ cause: e },
|
||||
).toObject()
|
||||
break
|
||||
default:
|
||||
next.metadata.error = new NamedError.Unknown(
|
||||
{ message: JSON.stringify(e) },
|
||||
{ cause: e },
|
||||
)
|
||||
}
|
||||
Bus.publish(Event.Error, {
|
||||
error: next.metadata.error,
|
||||
})
|
||||
}
|
||||
await result.consumeStream({
|
||||
onError: (err) => {
|
||||
log.error("stream error", {
|
||||
err,
|
||||
})
|
||||
},
|
||||
})
|
||||
next.metadata!.time.completed = Date.now()
|
||||
for (const part of next.parts) {
|
||||
if (
|
||||
@@ -647,14 +657,15 @@ export namespace Session {
|
||||
content: x,
|
||||
}),
|
||||
),
|
||||
...convertToCoreMessages(filtered.map(toUIMessage)),
|
||||
{
|
||||
role: "user",
|
||||
content: toUserContent([
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "Provide a detailed but concise summary of our conversation above. Focus on information that would be helpful for continuing the conversation, including what we did, what we're doing, which files we're working on, and what we're going to do next.",
|
||||
},
|
||||
]),
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -726,8 +737,30 @@ export namespace Session {
|
||||
}
|
||||
}
|
||||
|
||||
function toAssistantContent(parts: Message.Part[]): AssistantContent {
|
||||
const result: AssistantContent = []
|
||||
function toUIMessage(msg: Message.Info): UIMessage {
|
||||
if (msg.role === "assistant") {
|
||||
return {
|
||||
id: msg.id,
|
||||
role: "assistant",
|
||||
content: "",
|
||||
parts: toParts(msg.parts),
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.role === "user") {
|
||||
return {
|
||||
id: msg.id,
|
||||
role: "user",
|
||||
content: "",
|
||||
parts: toParts(msg.parts),
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("not implemented")
|
||||
}
|
||||
|
||||
function toParts(parts: Message.Part[]): UIMessage["parts"] {
|
||||
const result: UIMessage["parts"] = []
|
||||
for (const part of parts) {
|
||||
switch (part.type) {
|
||||
case "text":
|
||||
@@ -736,17 +769,19 @@ function toAssistantContent(parts: Message.Part[]): AssistantContent {
|
||||
case "file":
|
||||
result.push({
|
||||
type: "file",
|
||||
data: new URL(part.url),
|
||||
data: part.url,
|
||||
mimeType: part.mediaType,
|
||||
filename: part.filename,
|
||||
})
|
||||
break
|
||||
case "tool-invocation":
|
||||
result.push({
|
||||
type: "tool-call",
|
||||
args: part.toolInvocation.args,
|
||||
toolName: part.toolInvocation.toolName,
|
||||
toolCallId: part.toolInvocation.toolCallId,
|
||||
type: "tool-invocation",
|
||||
toolInvocation: part.toolInvocation,
|
||||
})
|
||||
break
|
||||
case "step-start":
|
||||
result.push({
|
||||
type: "step-start",
|
||||
})
|
||||
break
|
||||
default:
|
||||
@@ -755,25 +790,3 @@ function toAssistantContent(parts: Message.Part[]): AssistantContent {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function toUserContent(parts: Message.Part[]): UserContent {
|
||||
const result: UserContent = []
|
||||
for (const part of parts) {
|
||||
switch (part.type) {
|
||||
case "text":
|
||||
return [{ type: "text", text: part.text }]
|
||||
case "file":
|
||||
return [
|
||||
{
|
||||
type: "file",
|
||||
filename: part.filename,
|
||||
data: new URL(part.url),
|
||||
mimeType: part.mediaType,
|
||||
},
|
||||
]
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -124,11 +124,6 @@ func (m *editorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
case "ctrl+d":
|
||||
if m.textarea.Value() != "" {
|
||||
return m, nil
|
||||
}
|
||||
return m, tea.Quit
|
||||
case "shift+enter":
|
||||
value := m.textarea.Value()
|
||||
m.textarea.SetValue(value + "\n")
|
||||
|
||||
276
packages/tui/internal/theme/ayu.go
Normal file
276
packages/tui/internal/theme/ayu.go
Normal file
@@ -0,0 +1,276 @@
|
||||
package theme
|
||||
|
||||
import (
|
||||
"github.com/charmbracelet/lipgloss/v2"
|
||||
"github.com/charmbracelet/lipgloss/v2/compat"
|
||||
)
|
||||
|
||||
// AyuTheme implements the Theme interface with Ayu Dark colors.
|
||||
// It provides a modern dark theme inspired by the Ayu color scheme.
|
||||
type AyuTheme struct {
|
||||
BaseTheme
|
||||
}
|
||||
|
||||
// NewAyuTheme creates a new instance of the Ayu Dark theme.
|
||||
func NewAyuTheme() *AyuTheme {
|
||||
// Ayu Dark color palette
|
||||
// Base background colors
|
||||
darkBg := "#0B0E14" // App background
|
||||
darkBgAlt := "#0D1017" // Editor background
|
||||
darkLine := "#11151C" // UI line separators
|
||||
darkPanel := "#0F131A" // UI panel background
|
||||
|
||||
// Text colors
|
||||
darkFg := "#BFBDB6" // Primary text
|
||||
darkFgMuted := "#565B66" // Muted text
|
||||
darkGutter := "#6C7380" // Gutter text
|
||||
|
||||
// Syntax highlighting colors
|
||||
darkTag := "#39BAE6" // Tags and attributes
|
||||
darkFunc := "#FFB454" // Functions
|
||||
darkEntity := "#59C2FF" // Entities and variables
|
||||
darkString := "#AAD94C" // Strings
|
||||
darkRegexp := "#95E6CB" // Regular expressions
|
||||
darkMarkup := "#F07178" // Markup elements
|
||||
darkKeyword := "#FF8F40" // Keywords
|
||||
darkSpecial := "#E6B673" // Special characters
|
||||
darkComment := "#ACB6BF" // Comments
|
||||
darkConstant := "#D2A6FF" // Constants
|
||||
darkOperator := "#F29668" // Operators
|
||||
|
||||
// Version control colors
|
||||
darkAdded := "#7FD962" // Added lines
|
||||
darkRemoved := "#F26D78" // Removed lines
|
||||
|
||||
// Accent colors
|
||||
darkAccent := "#E6B450" // Primary accent
|
||||
darkError := "#D95757" // Error color
|
||||
|
||||
// Active state colors
|
||||
darkIndentActive := "#6C7380" // Active indent guides
|
||||
|
||||
theme := &AyuTheme{}
|
||||
|
||||
// Base colors
|
||||
theme.PrimaryColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkEntity),
|
||||
Light: lipgloss.Color(darkEntity),
|
||||
}
|
||||
theme.SecondaryColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkConstant),
|
||||
Light: lipgloss.Color(darkConstant),
|
||||
}
|
||||
theme.AccentColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkAccent),
|
||||
Light: lipgloss.Color(darkAccent),
|
||||
}
|
||||
|
||||
// Status colors
|
||||
theme.ErrorColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkError),
|
||||
Light: lipgloss.Color(darkError),
|
||||
}
|
||||
theme.WarningColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkSpecial),
|
||||
Light: lipgloss.Color(darkSpecial),
|
||||
}
|
||||
theme.SuccessColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkAdded),
|
||||
Light: lipgloss.Color(darkAdded),
|
||||
}
|
||||
theme.InfoColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkTag),
|
||||
Light: lipgloss.Color(darkTag),
|
||||
}
|
||||
|
||||
// Text colors
|
||||
theme.TextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkFg),
|
||||
Light: lipgloss.Color(darkFg),
|
||||
}
|
||||
theme.TextMutedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkFgMuted),
|
||||
Light: lipgloss.Color(darkFgMuted),
|
||||
}
|
||||
|
||||
// Background colors
|
||||
theme.BackgroundColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkBg),
|
||||
Light: lipgloss.Color(darkBg),
|
||||
}
|
||||
theme.BackgroundSubtleColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkBgAlt),
|
||||
Light: lipgloss.Color(darkBgAlt),
|
||||
}
|
||||
theme.BackgroundElementColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkPanel),
|
||||
Light: lipgloss.Color(darkPanel),
|
||||
}
|
||||
|
||||
// Border colors
|
||||
theme.BorderColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkGutter),
|
||||
Light: lipgloss.Color(darkGutter),
|
||||
}
|
||||
theme.BorderActiveColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkIndentActive),
|
||||
Light: lipgloss.Color(darkIndentActive),
|
||||
}
|
||||
theme.BorderSubtleColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkLine),
|
||||
Light: lipgloss.Color(darkLine),
|
||||
}
|
||||
|
||||
// Diff view colors
|
||||
theme.DiffAddedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkAdded),
|
||||
Light: lipgloss.Color(darkAdded),
|
||||
}
|
||||
theme.DiffRemovedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkRemoved),
|
||||
Light: lipgloss.Color(darkRemoved),
|
||||
}
|
||||
theme.DiffContextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkFgMuted),
|
||||
Light: lipgloss.Color(darkFgMuted),
|
||||
}
|
||||
theme.DiffHunkHeaderColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkGutter),
|
||||
Light: lipgloss.Color(darkGutter),
|
||||
}
|
||||
theme.DiffHighlightAddedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkAdded),
|
||||
Light: lipgloss.Color(darkAdded),
|
||||
}
|
||||
theme.DiffHighlightRemovedColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkRemoved),
|
||||
Light: lipgloss.Color(darkRemoved),
|
||||
}
|
||||
theme.DiffAddedBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#1a2b1a"),
|
||||
Light: lipgloss.Color("#1a2b1a"),
|
||||
}
|
||||
theme.DiffRemovedBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#2b1a1a"),
|
||||
Light: lipgloss.Color("#2b1a1a"),
|
||||
}
|
||||
theme.DiffContextBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkBgAlt),
|
||||
Light: lipgloss.Color(darkBgAlt),
|
||||
}
|
||||
theme.DiffLineNumberColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkGutter),
|
||||
Light: lipgloss.Color(darkGutter),
|
||||
}
|
||||
theme.DiffAddedLineNumberBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#152b15"),
|
||||
Light: lipgloss.Color("#152b15"),
|
||||
}
|
||||
theme.DiffRemovedLineNumberBgColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color("#2b1515"),
|
||||
Light: lipgloss.Color("#2b1515"),
|
||||
}
|
||||
|
||||
// Markdown colors
|
||||
theme.MarkdownTextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkFg),
|
||||
Light: lipgloss.Color(darkFg),
|
||||
}
|
||||
theme.MarkdownHeadingColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkFunc),
|
||||
Light: lipgloss.Color(darkFunc),
|
||||
}
|
||||
theme.MarkdownLinkColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkTag),
|
||||
Light: lipgloss.Color(darkTag),
|
||||
}
|
||||
theme.MarkdownLinkTextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkEntity),
|
||||
Light: lipgloss.Color(darkEntity),
|
||||
}
|
||||
theme.MarkdownCodeColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkString),
|
||||
Light: lipgloss.Color(darkString),
|
||||
}
|
||||
theme.MarkdownBlockQuoteColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkSpecial),
|
||||
Light: lipgloss.Color(darkSpecial),
|
||||
}
|
||||
theme.MarkdownEmphColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkKeyword),
|
||||
Light: lipgloss.Color(darkKeyword),
|
||||
}
|
||||
theme.MarkdownStrongColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkMarkup),
|
||||
Light: lipgloss.Color(darkMarkup),
|
||||
}
|
||||
theme.MarkdownHorizontalRuleColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkGutter),
|
||||
Light: lipgloss.Color(darkGutter),
|
||||
}
|
||||
theme.MarkdownListItemColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkOperator),
|
||||
Light: lipgloss.Color(darkOperator),
|
||||
}
|
||||
theme.MarkdownListEnumerationColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkConstant),
|
||||
Light: lipgloss.Color(darkConstant),
|
||||
}
|
||||
theme.MarkdownImageColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkRegexp),
|
||||
Light: lipgloss.Color(darkRegexp),
|
||||
}
|
||||
theme.MarkdownImageTextColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkEntity),
|
||||
Light: lipgloss.Color(darkEntity),
|
||||
}
|
||||
theme.MarkdownCodeBlockColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkString),
|
||||
Light: lipgloss.Color(darkString),
|
||||
}
|
||||
|
||||
// Syntax highlighting colors
|
||||
theme.SyntaxCommentColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkComment),
|
||||
Light: lipgloss.Color(darkComment),
|
||||
}
|
||||
theme.SyntaxKeywordColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkKeyword),
|
||||
Light: lipgloss.Color(darkKeyword),
|
||||
}
|
||||
theme.SyntaxFunctionColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkFunc),
|
||||
Light: lipgloss.Color(darkFunc),
|
||||
}
|
||||
theme.SyntaxVariableColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkEntity),
|
||||
Light: lipgloss.Color(darkEntity),
|
||||
}
|
||||
theme.SyntaxStringColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkString),
|
||||
Light: lipgloss.Color(darkString),
|
||||
}
|
||||
theme.SyntaxNumberColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkConstant),
|
||||
Light: lipgloss.Color(darkConstant),
|
||||
}
|
||||
theme.SyntaxTypeColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkSpecial),
|
||||
Light: lipgloss.Color(darkSpecial),
|
||||
}
|
||||
theme.SyntaxOperatorColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkOperator),
|
||||
Light: lipgloss.Color(darkOperator),
|
||||
}
|
||||
theme.SyntaxPunctuationColor = compat.AdaptiveColor{
|
||||
Dark: lipgloss.Color(darkFg),
|
||||
Light: lipgloss.Color(darkFg),
|
||||
}
|
||||
|
||||
return theme
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Register the Ayu theme with the theme manager
|
||||
RegisterTheme("ayu", NewAyuTheme())
|
||||
}
|
||||
Reference in New Issue
Block a user