styles.go

  1// Package styles define styling and theming for the project.
  2package styles
  3
  4import (
  5	"fmt"
  6	"image/color"
  7	"strings"
  8
  9	"charm.land/bubbles/v2/filepicker"
 10	"charm.land/bubbles/v2/help"
 11	"charm.land/bubbles/v2/textarea"
 12	"charm.land/bubbles/v2/textinput"
 13	"charm.land/glamour/v2/ansi"
 14	"charm.land/lipgloss/v2"
 15	"github.com/alecthomas/chroma/v2"
 16	"github.com/charmbracelet/crush/internal/ui/diffview"
 17)
 18
 19const (
 20	CheckIcon       string = "βœ“"
 21	SpinnerIcon     string = "β‹―"
 22	LoadingIcon     string = "⟳"
 23	ModelIcon       string = "β—‡"
 24	HypercreditIcon string = "β—†"
 25
 26	ArrowRightIcon string = "β†’"
 27
 28	ToolPending string = "●"
 29	ToolSuccess string = "βœ“"
 30	ToolError   string = "Γ—"
 31
 32	RadioOn  string = "β—‰"
 33	RadioOff string = "β—‹"
 34
 35	BorderThin  string = "β”‚"
 36	BorderThick string = "β–Œ"
 37
 38	SectionSeparator string = "─"
 39
 40	TodoCompletedIcon  string = "βœ“"
 41	TodoPendingIcon    string = "β€’"
 42	TodoInProgressIcon string = "β†’"
 43
 44	ImageIcon string = "β– "
 45	TextIcon  string = "≑"
 46
 47	ScrollbarThumb string = "┃"
 48	ScrollbarTrack string = "β”‚"
 49
 50	LSPErrorIcon   string = "E"
 51	LSPWarningIcon string = "W"
 52	LSPInfoIcon    string = "I"
 53	LSPHintIcon    string = "H"
 54)
 55
 56const (
 57	defaultMargin     = 2
 58	defaultListIndent = 2
 59)
 60
 61type Styles struct {
 62	// Header
 63	Header struct {
 64		Charm             lipgloss.Style // Style for "Charmβ„’" label
 65		Diagonals         lipgloss.Style // Style for diagonal separators (β•±)
 66		Percentage        lipgloss.Style // Style for context percentage
 67		Keystroke         lipgloss.Style // Style for keystroke hints (e.g., "ctrl+d")
 68		KeystrokeTip      lipgloss.Style // Style for keystroke action text (e.g., "open", "close")
 69		WorkingDir        lipgloss.Style // Style for current working directory
 70		Separator         lipgloss.Style // Style for separator dots (β€’)
 71		Wrapper           lipgloss.Style // Outer container for the entire header row
 72		LogoGradCanvas    lipgloss.Style // Canvas for the compact "CRUSH" gradient
 73		LogoGradFromColor color.Color    // "CRUSH" wordmark gradient start
 74		LogoGradToColor   color.Color    // "CRUSH" wordmark gradient end
 75	}
 76
 77	CompactDetails struct {
 78		View    lipgloss.Style
 79		Version lipgloss.Style
 80		Title   lipgloss.Style
 81	}
 82
 83	// Tool calls
 84	ToolCallSuccess lipgloss.Style
 85
 86	// Text selection
 87	TextSelection lipgloss.Style
 88
 89	// Markdown & Chroma
 90	Markdown      ansi.StyleConfig
 91	QuietMarkdown ansi.StyleConfig
 92
 93	// Inputs
 94	TextInput textinput.Styles
 95
 96	// Help
 97	Help help.Styles
 98
 99	// Diff
100	Diff diffview.Style
101
102	// FilePicker
103	FilePicker filepicker.Styles
104
105	// Buttons
106	Button struct {
107		Focused lipgloss.Style
108		Blurred lipgloss.Style
109	}
110
111	// Editor
112	Editor struct {
113		Textarea textarea.Styles
114
115		// Normal mode prompt (default "::: ").
116		PromptNormalFocused lipgloss.Style
117		PromptNormalBlurred lipgloss.Style
118
119		// YOLO mode prompt (" ! " icon + ":::" dots).
120		PromptYoloIconFocused lipgloss.Style
121		PromptYoloIconBlurred lipgloss.Style
122		PromptYoloDotsFocused lipgloss.Style
123		PromptYoloDotsBlurred lipgloss.Style
124	}
125
126	// Radio
127	Radio struct {
128		On    lipgloss.Style
129		Off   lipgloss.Style
130		Label lipgloss.Style // Text next to a radio button
131	}
132
133	// Background
134	Background color.Color
135
136	// Logo
137	Logo struct {
138		FieldColor         color.Color
139		TitleColorA        color.Color
140		TitleColorB        color.Color
141		CharmColor         color.Color
142		VersionColor       color.Color
143		SmallCharm         lipgloss.Style // "Charmβ„’" label in SmallRender
144		SmallDiagonals     lipgloss.Style // Diagonal line fill in SmallRender
145		GradCanvas         lipgloss.Style // Blank canvas for gradient painting
146		SmallGradFromColor color.Color    // Small "Crush" wordmark gradient start
147		SmallGradToColor   color.Color    // Small "Crush" wordmark gradient end
148	}
149
150	// Working indicator gradient (spinners/shimmers on assistant "thinking",
151	// tool-call pending, CLI generating, startup).
152	WorkingGradFromColor color.Color
153	WorkingGradToColor   color.Color
154	WorkingLabelColor    color.Color // Label text color next to the indicator
155
156	// Section Title
157	Section struct {
158		Title lipgloss.Style
159		Line  lipgloss.Style
160	}
161
162	// Initialize
163	Initialize struct {
164		Header  lipgloss.Style
165		Content lipgloss.Style
166		Accent  lipgloss.Style
167	}
168
169	// LSP
170	LSP struct {
171		ErrorDiagnostic   lipgloss.Style
172		WarningDiagnostic lipgloss.Style
173		HintDiagnostic    lipgloss.Style
174		InfoDiagnostic    lipgloss.Style
175	}
176
177	// Sidebar
178	Sidebar struct {
179		SessionTitle lipgloss.Style // Current session title at top of sidebar
180		WorkingDir   lipgloss.Style // Working directory path (PrettyPath)
181	}
182
183	// ModelInfo (model name, provider, reasoning, token/cost summary)
184	ModelInfo struct {
185		Icon             lipgloss.Style // Model icon (β—‡)
186		Name             lipgloss.Style // Model name text
187		Provider         lipgloss.Style // "via <provider>" text
188		ProviderFallback lipgloss.Style // Provider on its own second line
189		Reasoning        lipgloss.Style // Reasoning effort text
190		TokenCount       lipgloss.Style // "(42K)" token count
191		TokenPercentage  lipgloss.Style // "42%" percent of context window
192		Cost             lipgloss.Style // "$0.42" cost readout
193		HypercreditIcon  lipgloss.Style // Hypercredit icon (β—†)
194		HypercreditText  lipgloss.Style // Remaining Hypercredits text
195	}
196
197	// Resource styles the LSP/MCP/skills sidebar lists: their heading,
198	// each row's status icon, name, status text, and truncation hints.
199	Resource struct {
200		Heading         lipgloss.Style // Section header ("LSPs", "MCPs", "Skills")
201		Name            lipgloss.Style // Resource name (e.g. "gopls")
202		StatusText      lipgloss.Style // Row status description (e.g. "starting...")
203		OfflineIcon     lipgloss.Style // Offline/unstarted/stopped status icon
204		DisabledIcon    lipgloss.Style // Disabled status icon
205		BusyIcon        lipgloss.Style // Busy/starting status icon
206		ErrorIcon       lipgloss.Style // Error status icon
207		OnlineIcon      lipgloss.Style // Online/ready status icon
208		AdditionalText  lipgloss.Style // "None" and "…and N more" text
209		CapabilityCount lipgloss.Style // "N tools" / "N prompts" / "N resources"
210		RowTitleBase    lipgloss.Style // Base style applied over row titles in common.Status
211		RowDescBase     lipgloss.Style // Base style applied over row descriptions in common.Status
212		DefaultTitleFg  color.Color    // Default title color when opt is zero
213		DefaultDescFg   color.Color    // Default description color when opt is zero
214	}
215
216	// Files
217	Files struct {
218		Path           lipgloss.Style
219		Additions      lipgloss.Style
220		Deletions      lipgloss.Style
221		SectionTitle   lipgloss.Style // "Modified Files" heading
222		EmptyMessage   lipgloss.Style // "None" placeholder when no files
223		TruncationHint lipgloss.Style // "…and N more" message
224	}
225
226	// Chat
227	// Messages - chat message item styles
228	Messages struct {
229		UserBlurred      lipgloss.Style
230		UserFocused      lipgloss.Style
231		AssistantBlurred lipgloss.Style
232		AssistantFocused lipgloss.Style
233		NoContent        lipgloss.Style
234		Thinking         lipgloss.Style
235		ErrorTag         lipgloss.Style
236		ErrorTitle       lipgloss.Style
237		ErrorDetails     lipgloss.Style
238		ToolCallFocused  lipgloss.Style
239		ToolCallCompact  lipgloss.Style
240		ToolCallBlurred  lipgloss.Style
241		SectionHeader    lipgloss.Style
242
243		// Thinking section styles
244		ThinkingBox            lipgloss.Style // Background for thinking content
245		ThinkingTruncationHint lipgloss.Style // "… (N lines hidden)" hint
246		ThinkingFooterTitle    lipgloss.Style // "Thought for" text
247		ThinkingFooterDuration lipgloss.Style // Duration value
248		AssistantInfoIcon      lipgloss.Style
249		AssistantInfoModel     lipgloss.Style
250		AssistantInfoProvider  lipgloss.Style
251		AssistantInfoDuration  lipgloss.Style
252		AssistantCanceled      lipgloss.Style // Italic "Canceled" footer
253	}
254
255	// Tool - styles for tool call rendering
256	Tool struct {
257		// Icon styles with tool status
258		IconPending   lipgloss.Style
259		IconSuccess   lipgloss.Style
260		IconError     lipgloss.Style
261		IconCancelled lipgloss.Style
262
263		// Tool name styles
264		NameNormal lipgloss.Style // Top-level tool name
265		NameNested lipgloss.Style // Nested child tool name (inside Agent/Agentic Fetch)
266
267		// Parameter list styles
268		ParamMain lipgloss.Style
269		ParamKey  lipgloss.Style
270
271		// Content rendering styles
272		ContentLine           lipgloss.Style // Individual content line with background and width
273		ContentTruncation     lipgloss.Style // Truncation message "… (N lines)"
274		ContentCodeLine       lipgloss.Style // Code line with background and width
275		ContentCodeTruncation lipgloss.Style // Code truncation message with bgBase
276		ContentCodeBg         color.Color    // Background color for syntax highlighting
277		Body                  lipgloss.Style // Body content padding (PaddingLeft(2))
278
279		// Deprecated - kept for backward compatibility
280		ContentBg         lipgloss.Style // Content background
281		ContentText       lipgloss.Style // Content text
282		ContentLineNumber lipgloss.Style // Line numbers in code
283
284		// State message styles
285		StateWaiting   lipgloss.Style // "Waiting for tool response..."
286		StateCancelled lipgloss.Style // "Canceled."
287
288		// Error styles
289		ErrorTag     lipgloss.Style // ERROR tag
290		ErrorMessage lipgloss.Style // Error message text
291
292		// Diff styles
293		DiffTruncation lipgloss.Style // Diff truncation message with padding
294
295		// Multi-edit note styles
296		NoteTag     lipgloss.Style // NOTE tag (yellow background)
297		NoteMessage lipgloss.Style // Note message text
298
299		// Job header styles (for bash jobs)
300		JobIconPending lipgloss.Style // Pending job icon (green dark)
301		JobIconError   lipgloss.Style // Error job icon (red dark)
302		JobIconSuccess lipgloss.Style // Success job icon (green)
303		JobToolName    lipgloss.Style // Job tool name "Bash" (blue)
304		JobAction      lipgloss.Style // Action text (Start, Output, Kill)
305		JobPID         lipgloss.Style // PID text
306		JobDescription lipgloss.Style // Description text
307
308		// Agent task styles
309		AgentTaskTag lipgloss.Style // Agent task tag (blue background, bold)
310		AgentPrompt  lipgloss.Style // Agent prompt text
311
312		// Agentic fetch styles
313		AgenticFetchPromptTag lipgloss.Style // Agentic fetch prompt tag (green background, bold)
314
315		// Todo styles
316		TodoRatio          lipgloss.Style // Todo ratio (e.g., "2/5")
317		TodoCompletedIcon  lipgloss.Style // Completed todo icon
318		TodoInProgressIcon lipgloss.Style // In-progress todo icon
319		TodoPendingIcon    lipgloss.Style // Pending todo icon
320		TodoStatusNote     lipgloss.Style // " Β· completed N" / " Β· starting task" trailing note
321		TodoItem           lipgloss.Style // Default body text for todo list items
322		TodoJustStarted    lipgloss.Style // Text of the just-started todo in tool-call bodies
323
324		// MCP tools
325		MCPName     lipgloss.Style // The mcp name
326		MCPToolName lipgloss.Style // The mcp tool name
327		MCPArrow    lipgloss.Style // The mcp arrow icon
328
329		// Images and external resources
330		ResourceLoadedText      lipgloss.Style
331		ResourceLoadedIndicator lipgloss.Style
332		ResourceName            lipgloss.Style
333		ResourceSize            lipgloss.Style
334		MediaType               lipgloss.Style
335
336		// Hooks
337		HookLabel        lipgloss.Style // "Hook" label
338		HookName         lipgloss.Style // Hook command name
339		HookMatcher      lipgloss.Style // Matcher regex pattern
340		HookArrow        lipgloss.Style // Arrow indicator
341		HookDetail       lipgloss.Style // Decision detail text
342		HookOK           lipgloss.Style // "OK" status
343		HookDenied       lipgloss.Style // "Denied" status
344		HookDeniedLabel  lipgloss.Style // "Hook" label when denied
345		HookDeniedReason lipgloss.Style // Denied reason text
346		HookRewrote      lipgloss.Style // "Rewrote Input" indicator
347
348		// Action verb colors for tool-call headers.
349		ActionCreate  lipgloss.Style // Constructive actions (e.g. "Add", "Create")
350		ActionDestroy lipgloss.Style // Destructive actions (e.g. "Remove", "Delete")
351
352		// Tool result helpers.
353		ResultEmpty      lipgloss.Style // "No results" placeholder
354		ResultTruncation lipgloss.Style // "… and N more" truncation line
355		ResultItemName   lipgloss.Style // Item name (left column in result lists)
356		ResultItemDesc   lipgloss.Style // Item description (right column)
357	}
358
359	// Dialog styles
360	Dialog struct {
361		Title              lipgloss.Style
362		TitleText          lipgloss.Style
363		TitleError         lipgloss.Style
364		TitleAccent        lipgloss.Style
365		TitleLineBase      lipgloss.Style // Base for the gradient β•±β•±β•± next to dialog titles
366		TitleGradFromColor color.Color    // Default dialog title β•±β•±β•± gradient start
367		TitleGradToColor   color.Color    // Default dialog title β•±β•±β•± gradient end
368		// View is the main content area style.
369		View          lipgloss.Style
370		PrimaryText   lipgloss.Style
371		SecondaryText lipgloss.Style
372		// HelpView is the line that contains the help.
373		HelpView lipgloss.Style
374		Help     struct {
375			Ellipsis       lipgloss.Style
376			ShortKey       lipgloss.Style
377			ShortDesc      lipgloss.Style
378			ShortSeparator lipgloss.Style
379			FullKey        lipgloss.Style
380			FullDesc       lipgloss.Style
381			FullSeparator  lipgloss.Style
382		}
383
384		NormalItem   lipgloss.Style
385		SelectedItem lipgloss.Style
386		InputPrompt  lipgloss.Style
387
388		List lipgloss.Style
389
390		Spinner lipgloss.Style
391
392		// ContentPanel is used for content blocks with subtle background.
393		ContentPanel lipgloss.Style
394
395		// Scrollbar styles for scrollable content.
396		ScrollbarThumb lipgloss.Style
397		ScrollbarTrack lipgloss.Style
398
399		// Arguments
400		Arguments struct {
401			Content                  lipgloss.Style
402			Description              lipgloss.Style
403			InputLabelBlurred        lipgloss.Style
404			InputLabelFocused        lipgloss.Style
405			InputRequiredMarkBlurred lipgloss.Style
406			InputRequiredMarkFocused lipgloss.Style
407		}
408
409		// ListItem styles the info-text rendered alongside list items (commands,
410		// models, reasoning options). Sessions have their own overrides below.
411		ListItem struct {
412			InfoBlurred lipgloss.Style
413			InfoFocused lipgloss.Style
414		}
415
416		Models struct {
417			ConfiguredText lipgloss.Style // "Configured" badge shown on the ModelGroup header
418		}
419
420		Permissions struct {
421			KeyText   lipgloss.Style // Left key cell of a key/value row
422			ValueText lipgloss.Style // Right value cell of a key/value row
423			ParamsBg  color.Color    // Background color behind highlighted JSON parameters
424		}
425
426		Quit struct {
427			Content lipgloss.Style // Wrapper for the quit dialog's inner content
428			Frame   lipgloss.Style // Outer rounded border framing the quit dialog
429		}
430
431		APIKey struct {
432			Spinner lipgloss.Style // Loading spinner while validating the key
433		}
434
435		OAuth struct {
436			Spinner      lipgloss.Style // Loading spinner
437			Instructions lipgloss.Style // Emphasized instruction text
438			UserCode     lipgloss.Style // Prominent user code display
439			Success      lipgloss.Style // Positive status text (e.g. "Authentication successful!")
440			Link         lipgloss.Style // Underlined verification URL
441			Enter        lipgloss.Style // "enter" keyword highlight in instructions
442			ErrorText    lipgloss.Style // Error message when authentication fails
443			StatusText   lipgloss.Style // Narrative status text ("Initializing...", "Verifying...", etc.)
444			UserCodeBg   color.Color    // Background color of the centered user-code box
445		}
446
447		ImagePreview lipgloss.Style
448
449		Sessions struct {
450			// styles for when we are in delete mode
451			DeletingView                   lipgloss.Style
452			DeletingItemFocused            lipgloss.Style
453			DeletingItemBlurred            lipgloss.Style
454			DeletingTitle                  lipgloss.Style
455			DeletingMessage                lipgloss.Style
456			DeletingTitleGradientFromColor color.Color
457			DeletingTitleGradientToColor   color.Color
458
459			// styles for when we are in update mode
460			RenamingView                   lipgloss.Style
461			RenamingingItemFocused         lipgloss.Style
462			RenamingItemBlurred            lipgloss.Style
463			RenamingingTitle               lipgloss.Style
464			RenamingingMessage             lipgloss.Style
465			RenamingTitleGradientFromColor color.Color
466			RenamingTitleGradientToColor   color.Color
467			RenamingPlaceholder            lipgloss.Style
468
469			InfoBlurred lipgloss.Style // Timestamp text on unfocused session items
470			InfoFocused lipgloss.Style // Timestamp text on the focused session item
471		}
472	}
473
474	// Status bar and help
475	Status struct {
476		Help lipgloss.Style
477
478		ErrorIndicator   lipgloss.Style
479		WarnIndicator    lipgloss.Style
480		InfoIndicator    lipgloss.Style
481		UpdateIndicator  lipgloss.Style
482		SuccessIndicator lipgloss.Style
483
484		ErrorMessage   lipgloss.Style
485		WarnMessage    lipgloss.Style
486		InfoMessage    lipgloss.Style
487		UpdateMessage  lipgloss.Style
488		SuccessMessage lipgloss.Style
489	}
490
491	// Completions popup styles
492	Completions struct {
493		Normal  lipgloss.Style
494		Focused lipgloss.Style
495		Match   lipgloss.Style
496	}
497
498	// Attachments styles
499	Attachments struct {
500		Normal   lipgloss.Style
501		Image    lipgloss.Style
502		Text     lipgloss.Style
503		Deleting lipgloss.Style
504	}
505
506	// Pills styles for todo/queue pills
507	Pills struct {
508		Base               lipgloss.Style // Base pill style with padding
509		Focused            lipgloss.Style // Focused pill with visible border
510		Blurred            lipgloss.Style // Blurred pill with hidden border
511		QueueItemPrefix    lipgloss.Style // Prefix for queue list items
512		QueueItemText      lipgloss.Style // Queue list item body text
513		QueueLabel         lipgloss.Style // "N Queued" label text
514		QueueIconBase      lipgloss.Style // Base style for queue gradient triangles
515		QueueGradFromColor color.Color    // Start color for queue indicator gradient
516		QueueGradToColor   color.Color    // End color for queue indicator gradient
517		TodoLabel          lipgloss.Style // "To-Do" label
518		TodoProgress       lipgloss.Style // Todo ratio (e.g. "2/5")
519		TodoCurrentTask    lipgloss.Style // Current in-progress task name
520		TodoSpinner        lipgloss.Style // Todo spinner style
521		HelpKey            lipgloss.Style // Keystroke hint style
522		HelpText           lipgloss.Style // Help action text style
523		Area               lipgloss.Style // Pills area container
524	}
525}
526
527// ChromaTheme converts the current markdown chroma styles to a chroma
528// StyleEntries map.
529func (s *Styles) ChromaTheme() chroma.StyleEntries {
530	rules := s.Markdown.CodeBlock
531
532	return chroma.StyleEntries{
533		chroma.Text:                chromaStyle(rules.Chroma.Text),
534		chroma.Error:               chromaStyle(rules.Chroma.Error),
535		chroma.Comment:             chromaStyle(rules.Chroma.Comment),
536		chroma.CommentPreproc:      chromaStyle(rules.Chroma.CommentPreproc),
537		chroma.Keyword:             chromaStyle(rules.Chroma.Keyword),
538		chroma.KeywordReserved:     chromaStyle(rules.Chroma.KeywordReserved),
539		chroma.KeywordNamespace:    chromaStyle(rules.Chroma.KeywordNamespace),
540		chroma.KeywordType:         chromaStyle(rules.Chroma.KeywordType),
541		chroma.Operator:            chromaStyle(rules.Chroma.Operator),
542		chroma.Punctuation:         chromaStyle(rules.Chroma.Punctuation),
543		chroma.Name:                chromaStyle(rules.Chroma.Name),
544		chroma.NameBuiltin:         chromaStyle(rules.Chroma.NameBuiltin),
545		chroma.NameTag:             chromaStyle(rules.Chroma.NameTag),
546		chroma.NameAttribute:       chromaStyle(rules.Chroma.NameAttribute),
547		chroma.NameClass:           chromaStyle(rules.Chroma.NameClass),
548		chroma.NameConstant:        chromaStyle(rules.Chroma.NameConstant),
549		chroma.NameDecorator:       chromaStyle(rules.Chroma.NameDecorator),
550		chroma.NameException:       chromaStyle(rules.Chroma.NameException),
551		chroma.NameFunction:        chromaStyle(rules.Chroma.NameFunction),
552		chroma.NameOther:           chromaStyle(rules.Chroma.NameOther),
553		chroma.Literal:             chromaStyle(rules.Chroma.Literal),
554		chroma.LiteralNumber:       chromaStyle(rules.Chroma.LiteralNumber),
555		chroma.LiteralDate:         chromaStyle(rules.Chroma.LiteralDate),
556		chroma.LiteralString:       chromaStyle(rules.Chroma.LiteralString),
557		chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
558		chroma.GenericDeleted:      chromaStyle(rules.Chroma.GenericDeleted),
559		chroma.GenericEmph:         chromaStyle(rules.Chroma.GenericEmph),
560		chroma.GenericInserted:     chromaStyle(rules.Chroma.GenericInserted),
561		chroma.GenericStrong:       chromaStyle(rules.Chroma.GenericStrong),
562		chroma.GenericSubheading:   chromaStyle(rules.Chroma.GenericSubheading),
563		chroma.Background:          chromaStyle(rules.Chroma.Background),
564	}
565}
566
567// DialogHelpStyles returns the styles for dialog help.
568func (s *Styles) DialogHelpStyles() help.Styles {
569	return help.Styles(s.Dialog.Help)
570}
571
572// hex returns a pointer to the "#rrggbb" representation of c. It's used to
573// satisfy glamour's string-pointer API when configuring markdown colors
574// from the theme palette.
575func hex(c color.Color) *string {
576	r, g, b, _ := c.RGBA()
577	s := fmt.Sprintf("#%02x%02x%02x", r>>8, g>>8, b>>8)
578	return &s
579}
580
581func chromaStyle(style ansi.StylePrimitive) string {
582	var s strings.Builder
583
584	if style.Color != nil {
585		s.WriteString(*style.Color)
586	}
587	if style.BackgroundColor != nil {
588		if s.Len() > 0 {
589			s.WriteString(" ")
590		}
591		s.WriteString("bg:")
592		s.WriteString(*style.BackgroundColor)
593	}
594	if style.Italic != nil && *style.Italic {
595		if s.Len() > 0 {
596			s.WriteString(" ")
597		}
598		s.WriteString("italic")
599	}
600	if style.Bold != nil && *style.Bold {
601		if s.Len() > 0 {
602			s.WriteString(" ")
603		}
604		s.WriteString("bold")
605	}
606	if style.Underline != nil && *style.Underline {
607		if s.Len() > 0 {
608			s.WriteString(" ")
609		}
610		s.WriteString("underline")
611	}
612
613	return s.String()
614}