1package styles
2
3import (
4 "image/color"
5
6 "charm.land/bubbles/v2/filepicker"
7 "charm.land/bubbles/v2/help"
8 "charm.land/bubbles/v2/textarea"
9 "charm.land/bubbles/v2/textinput"
10 tea "charm.land/bubbletea/v2"
11 "charm.land/lipgloss/v2"
12 "github.com/charmbracelet/crush/internal/tui/exp/diffview"
13 "github.com/charmbracelet/glamour/v2/ansi"
14 "github.com/charmbracelet/x/exp/charmtone"
15)
16
17const (
18 CheckIcon string = "✓"
19 ErrorIcon string = "×"
20 WarningIcon string = "⚠"
21 InfoIcon string = "ⓘ"
22 HintIcon string = "∵"
23 SpinnerIcon string = "..."
24 LoadingIcon string = "⟳"
25 DocumentIcon string = "🖼"
26 ModelIcon string = "◇"
27
28 ToolPending string = "●"
29 ToolSuccess string = "✓"
30 ToolError string = "×"
31
32 BorderThin string = "│"
33 BorderThick string = "▌"
34
35 SectionSeparator string = "─"
36)
37
38const (
39 defaultMargin = 2
40 defaultListIndent = 2
41)
42
43type Styles struct {
44 WindowTooSmall lipgloss.Style
45
46 // Reusable text styles
47 Base lipgloss.Style
48 Muted lipgloss.Style
49 Subtle lipgloss.Style
50
51 // Tags
52 TagBase lipgloss.Style
53 TagError lipgloss.Style
54 TagInfo lipgloss.Style
55
56 // Headers
57 HeaderTool lipgloss.Style
58 HeaderToolNested lipgloss.Style
59
60 // Panels
61 PanelMuted lipgloss.Style
62 PanelBase lipgloss.Style
63
64 // Line numbers for code blocks
65 LineNumber lipgloss.Style
66
67 // Message borders
68 FocusedMessageBorder lipgloss.Border
69
70 // Tool calls
71 ToolCallPending lipgloss.Style
72 ToolCallError lipgloss.Style
73 ToolCallSuccess lipgloss.Style
74 ToolCallCancelled lipgloss.Style
75 EarlyStateMessage lipgloss.Style
76
77 // Text selection
78 TextSelection lipgloss.Style
79
80 // LSP and MCP status indicators
81 ItemOfflineIcon lipgloss.Style
82 ItemBusyIcon lipgloss.Style
83 ItemErrorIcon lipgloss.Style
84 ItemOnlineIcon lipgloss.Style
85
86 // Markdown & Chroma
87 Markdown ansi.StyleConfig
88
89 // Inputs
90 TextInput textinput.Styles
91 TextArea textarea.Styles
92
93 // Help
94 Help help.Styles
95
96 // Diff
97 Diff diffview.Style
98
99 // FilePicker
100 FilePicker filepicker.Styles
101
102 // Buttons
103 ButtonFocus lipgloss.Style
104 ButtonBlur lipgloss.Style
105
106 // Borders
107 BorderFocus lipgloss.Style
108 BorderBlur lipgloss.Style
109
110 // Editor
111 EditorPromptNormalFocused lipgloss.Style
112 EditorPromptNormalBlurred lipgloss.Style
113 EditorPromptYoloIconFocused lipgloss.Style
114 EditorPromptYoloIconBlurred lipgloss.Style
115 EditorPromptYoloDotsFocused lipgloss.Style
116 EditorPromptYoloDotsBlurred lipgloss.Style
117
118 // Background
119 Background color.Color
120 // Logo
121 LogoFieldColor color.Color
122 LogoTitleColorA color.Color
123 LogoTitleColorB color.Color
124 LogoCharmColor color.Color
125 LogoVersionColor color.Color
126
127 // Section Title
128 Section struct {
129 Title lipgloss.Style
130 Line lipgloss.Style
131 }
132
133 // Initialize
134 Initialize struct {
135 Header lipgloss.Style
136 Content lipgloss.Style
137 Accent lipgloss.Style
138 }
139
140 // LSP
141 LSP struct {
142 ErrorDiagnostic lipgloss.Style
143 WarningDiagnostic lipgloss.Style
144 HintDiagnostic lipgloss.Style
145 InfoDiagnostic lipgloss.Style
146 }
147
148 // Files
149 Files struct {
150 Path lipgloss.Style
151 Additions lipgloss.Style
152 Deletions lipgloss.Style
153 }
154
155 // Chat
156 Chat struct {
157 UserMessageBlurred lipgloss.Style
158 UserMessageFocused lipgloss.Style
159 AssistantMessageBlurred lipgloss.Style
160 AssistantMessageFocused lipgloss.Style
161 NoContentMessage lipgloss.Style
162 ThinkingMessage lipgloss.Style
163
164 ErrorTag lipgloss.Style
165 ErrorTitle lipgloss.Style
166 ErrorDetails lipgloss.Style
167 }
168}
169
170func DefaultStyles() Styles {
171 var (
172 primary = charmtone.Charple
173 secondary = charmtone.Dolly
174 tertiary = charmtone.Bok
175 // accent = charmtone.Zest
176
177 // Backgrounds
178 bgBase = charmtone.Pepper
179 bgBaseLighter = charmtone.BBQ
180 bgSubtle = charmtone.Charcoal
181 bgOverlay = charmtone.Iron
182
183 // Foregrounds
184 fgBase = charmtone.Ash
185 fgMuted = charmtone.Squid
186 fgHalfMuted = charmtone.Smoke
187 fgSubtle = charmtone.Oyster
188 // fgSelected = charmtone.Salt
189
190 // Borders
191 border = charmtone.Charcoal
192 borderFocus = charmtone.Charple
193
194 // Status
195 warning = charmtone.Zest
196 info = charmtone.Malibu
197
198 // Colors
199 white = charmtone.Butter
200
201 blueLight = charmtone.Sardine
202 blue = charmtone.Malibu
203
204 // yellow = charmtone.Mustard
205 // citron = charmtone.Citron
206
207 green = charmtone.Julep
208 greenDark = charmtone.Guac
209 // greenLight = charmtone.Bok
210
211 red = charmtone.Coral
212 redDark = charmtone.Sriracha
213 // redLight = charmtone.Salmon
214 // cherry = charmtone.Cherry
215 )
216
217 normalBorder := lipgloss.NormalBorder()
218
219 base := lipgloss.NewStyle().Foreground(fgBase)
220
221 s := Styles{}
222
223 s.Background = bgBase
224
225 s.TextInput = textinput.Styles{
226 Focused: textinput.StyleState{
227 Text: base,
228 Placeholder: base.Foreground(fgSubtle),
229 Prompt: base.Foreground(tertiary),
230 Suggestion: base.Foreground(fgSubtle),
231 },
232 Blurred: textinput.StyleState{
233 Text: base.Foreground(fgMuted),
234 Placeholder: base.Foreground(fgSubtle),
235 Prompt: base.Foreground(fgMuted),
236 Suggestion: base.Foreground(fgSubtle),
237 },
238 Cursor: textinput.CursorStyle{
239 Color: secondary,
240 Shape: tea.CursorBar,
241 Blink: true,
242 },
243 }
244
245 s.TextArea = textarea.Styles{
246 Focused: textarea.StyleState{
247 Base: base,
248 Text: base,
249 LineNumber: base.Foreground(fgSubtle),
250 CursorLine: base,
251 CursorLineNumber: base.Foreground(fgSubtle),
252 Placeholder: base.Foreground(fgSubtle),
253 Prompt: base.Foreground(tertiary),
254 },
255 Blurred: textarea.StyleState{
256 Base: base,
257 Text: base.Foreground(fgMuted),
258 LineNumber: base.Foreground(fgMuted),
259 CursorLine: base,
260 CursorLineNumber: base.Foreground(fgMuted),
261 Placeholder: base.Foreground(fgSubtle),
262 Prompt: base.Foreground(fgMuted),
263 },
264 Cursor: textarea.CursorStyle{
265 Color: secondary,
266 Shape: tea.CursorBar,
267 Blink: true,
268 },
269 }
270
271 s.Markdown = ansi.StyleConfig{
272 Document: ansi.StyleBlock{
273 StylePrimitive: ansi.StylePrimitive{
274 // BlockPrefix: "\n",
275 // BlockSuffix: "\n",
276 Color: stringPtr(charmtone.Smoke.Hex()),
277 },
278 // Margin: uintPtr(defaultMargin),
279 },
280 BlockQuote: ansi.StyleBlock{
281 StylePrimitive: ansi.StylePrimitive{},
282 Indent: uintPtr(1),
283 IndentToken: stringPtr("│ "),
284 },
285 List: ansi.StyleList{
286 LevelIndent: defaultListIndent,
287 },
288 Heading: ansi.StyleBlock{
289 StylePrimitive: ansi.StylePrimitive{
290 BlockSuffix: "\n",
291 Color: stringPtr(charmtone.Malibu.Hex()),
292 Bold: boolPtr(true),
293 },
294 },
295 H1: ansi.StyleBlock{
296 StylePrimitive: ansi.StylePrimitive{
297 Prefix: " ",
298 Suffix: " ",
299 Color: stringPtr(charmtone.Zest.Hex()),
300 BackgroundColor: stringPtr(charmtone.Charple.Hex()),
301 Bold: boolPtr(true),
302 },
303 },
304 H2: ansi.StyleBlock{
305 StylePrimitive: ansi.StylePrimitive{
306 Prefix: "## ",
307 },
308 },
309 H3: ansi.StyleBlock{
310 StylePrimitive: ansi.StylePrimitive{
311 Prefix: "### ",
312 },
313 },
314 H4: ansi.StyleBlock{
315 StylePrimitive: ansi.StylePrimitive{
316 Prefix: "#### ",
317 },
318 },
319 H5: ansi.StyleBlock{
320 StylePrimitive: ansi.StylePrimitive{
321 Prefix: "##### ",
322 },
323 },
324 H6: ansi.StyleBlock{
325 StylePrimitive: ansi.StylePrimitive{
326 Prefix: "###### ",
327 Color: stringPtr(charmtone.Guac.Hex()),
328 Bold: boolPtr(false),
329 },
330 },
331 Strikethrough: ansi.StylePrimitive{
332 CrossedOut: boolPtr(true),
333 },
334 Emph: ansi.StylePrimitive{
335 Italic: boolPtr(true),
336 },
337 Strong: ansi.StylePrimitive{
338 Bold: boolPtr(true),
339 },
340 HorizontalRule: ansi.StylePrimitive{
341 Color: stringPtr(charmtone.Charcoal.Hex()),
342 Format: "\n--------\n",
343 },
344 Item: ansi.StylePrimitive{
345 BlockPrefix: "• ",
346 },
347 Enumeration: ansi.StylePrimitive{
348 BlockPrefix: ". ",
349 },
350 Task: ansi.StyleTask{
351 StylePrimitive: ansi.StylePrimitive{},
352 Ticked: "[✓] ",
353 Unticked: "[ ] ",
354 },
355 Link: ansi.StylePrimitive{
356 Color: stringPtr(charmtone.Zinc.Hex()),
357 Underline: boolPtr(true),
358 },
359 LinkText: ansi.StylePrimitive{
360 Color: stringPtr(charmtone.Guac.Hex()),
361 Bold: boolPtr(true),
362 },
363 Image: ansi.StylePrimitive{
364 Color: stringPtr(charmtone.Cheeky.Hex()),
365 Underline: boolPtr(true),
366 },
367 ImageText: ansi.StylePrimitive{
368 Color: stringPtr(charmtone.Squid.Hex()),
369 Format: "Image: {{.text}} →",
370 },
371 Code: ansi.StyleBlock{
372 StylePrimitive: ansi.StylePrimitive{
373 Prefix: " ",
374 Suffix: " ",
375 Color: stringPtr(charmtone.Coral.Hex()),
376 BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
377 },
378 },
379 CodeBlock: ansi.StyleCodeBlock{
380 StyleBlock: ansi.StyleBlock{
381 StylePrimitive: ansi.StylePrimitive{
382 Color: stringPtr(charmtone.Charcoal.Hex()),
383 },
384 Margin: uintPtr(defaultMargin),
385 },
386 Chroma: &ansi.Chroma{
387 Text: ansi.StylePrimitive{
388 Color: stringPtr(charmtone.Smoke.Hex()),
389 },
390 Error: ansi.StylePrimitive{
391 Color: stringPtr(charmtone.Butter.Hex()),
392 BackgroundColor: stringPtr(charmtone.Sriracha.Hex()),
393 },
394 Comment: ansi.StylePrimitive{
395 Color: stringPtr(charmtone.Oyster.Hex()),
396 },
397 CommentPreproc: ansi.StylePrimitive{
398 Color: stringPtr(charmtone.Bengal.Hex()),
399 },
400 Keyword: ansi.StylePrimitive{
401 Color: stringPtr(charmtone.Malibu.Hex()),
402 },
403 KeywordReserved: ansi.StylePrimitive{
404 Color: stringPtr(charmtone.Pony.Hex()),
405 },
406 KeywordNamespace: ansi.StylePrimitive{
407 Color: stringPtr(charmtone.Pony.Hex()),
408 },
409 KeywordType: ansi.StylePrimitive{
410 Color: stringPtr(charmtone.Guppy.Hex()),
411 },
412 Operator: ansi.StylePrimitive{
413 Color: stringPtr(charmtone.Salmon.Hex()),
414 },
415 Punctuation: ansi.StylePrimitive{
416 Color: stringPtr(charmtone.Zest.Hex()),
417 },
418 Name: ansi.StylePrimitive{
419 Color: stringPtr(charmtone.Smoke.Hex()),
420 },
421 NameBuiltin: ansi.StylePrimitive{
422 Color: stringPtr(charmtone.Cheeky.Hex()),
423 },
424 NameTag: ansi.StylePrimitive{
425 Color: stringPtr(charmtone.Mauve.Hex()),
426 },
427 NameAttribute: ansi.StylePrimitive{
428 Color: stringPtr(charmtone.Hazy.Hex()),
429 },
430 NameClass: ansi.StylePrimitive{
431 Color: stringPtr(charmtone.Salt.Hex()),
432 Underline: boolPtr(true),
433 Bold: boolPtr(true),
434 },
435 NameDecorator: ansi.StylePrimitive{
436 Color: stringPtr(charmtone.Citron.Hex()),
437 },
438 NameFunction: ansi.StylePrimitive{
439 Color: stringPtr(charmtone.Guac.Hex()),
440 },
441 LiteralNumber: ansi.StylePrimitive{
442 Color: stringPtr(charmtone.Julep.Hex()),
443 },
444 LiteralString: ansi.StylePrimitive{
445 Color: stringPtr(charmtone.Cumin.Hex()),
446 },
447 LiteralStringEscape: ansi.StylePrimitive{
448 Color: stringPtr(charmtone.Bok.Hex()),
449 },
450 GenericDeleted: ansi.StylePrimitive{
451 Color: stringPtr(charmtone.Coral.Hex()),
452 },
453 GenericEmph: ansi.StylePrimitive{
454 Italic: boolPtr(true),
455 },
456 GenericInserted: ansi.StylePrimitive{
457 Color: stringPtr(charmtone.Guac.Hex()),
458 },
459 GenericStrong: ansi.StylePrimitive{
460 Bold: boolPtr(true),
461 },
462 GenericSubheading: ansi.StylePrimitive{
463 Color: stringPtr(charmtone.Squid.Hex()),
464 },
465 Background: ansi.StylePrimitive{
466 BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
467 },
468 },
469 },
470 Table: ansi.StyleTable{
471 StyleBlock: ansi.StyleBlock{
472 StylePrimitive: ansi.StylePrimitive{},
473 },
474 },
475 DefinitionDescription: ansi.StylePrimitive{
476 BlockPrefix: "\n ",
477 },
478 }
479
480 s.Help = help.Styles{
481 ShortKey: base.Foreground(fgMuted),
482 ShortDesc: base.Foreground(fgSubtle),
483 ShortSeparator: base.Foreground(border),
484 Ellipsis: base.Foreground(border),
485 FullKey: base.Foreground(fgMuted),
486 FullDesc: base.Foreground(fgSubtle),
487 FullSeparator: base.Foreground(border),
488 }
489
490 s.Diff = diffview.Style{
491 DividerLine: diffview.LineStyle{
492 LineNumber: lipgloss.NewStyle().
493 Foreground(fgHalfMuted).
494 Background(bgBaseLighter),
495 Code: lipgloss.NewStyle().
496 Foreground(fgHalfMuted).
497 Background(bgBaseLighter),
498 },
499 MissingLine: diffview.LineStyle{
500 LineNumber: lipgloss.NewStyle().
501 Background(bgBaseLighter),
502 Code: lipgloss.NewStyle().
503 Background(bgBaseLighter),
504 },
505 EqualLine: diffview.LineStyle{
506 LineNumber: lipgloss.NewStyle().
507 Foreground(fgMuted).
508 Background(bgBase),
509 Code: lipgloss.NewStyle().
510 Foreground(fgMuted).
511 Background(bgBase),
512 },
513 InsertLine: diffview.LineStyle{
514 LineNumber: lipgloss.NewStyle().
515 Foreground(lipgloss.Color("#629657")).
516 Background(lipgloss.Color("#2b322a")),
517 Symbol: lipgloss.NewStyle().
518 Foreground(lipgloss.Color("#629657")).
519 Background(lipgloss.Color("#323931")),
520 Code: lipgloss.NewStyle().
521 Background(lipgloss.Color("#323931")),
522 },
523 DeleteLine: diffview.LineStyle{
524 LineNumber: lipgloss.NewStyle().
525 Foreground(lipgloss.Color("#a45c59")).
526 Background(lipgloss.Color("#312929")),
527 Symbol: lipgloss.NewStyle().
528 Foreground(lipgloss.Color("#a45c59")).
529 Background(lipgloss.Color("#383030")),
530 Code: lipgloss.NewStyle().
531 Background(lipgloss.Color("#383030")),
532 },
533 }
534
535 s.FilePicker = filepicker.Styles{
536 DisabledCursor: base.Foreground(fgMuted),
537 Cursor: base.Foreground(fgBase),
538 Symlink: base.Foreground(fgSubtle),
539 Directory: base.Foreground(primary),
540 File: base.Foreground(fgBase),
541 DisabledFile: base.Foreground(fgMuted),
542 DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
543 Permission: base.Foreground(fgMuted),
544 Selected: base.Background(primary).Foreground(fgBase),
545 FileSize: base.Foreground(fgMuted),
546 EmptyDirectory: base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
547 }
548
549 // borders
550 s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
551
552 // text presets
553 s.Base = lipgloss.NewStyle().Foreground(fgBase)
554 s.Muted = lipgloss.NewStyle().Foreground(fgMuted)
555 s.Subtle = lipgloss.NewStyle().Foreground(fgSubtle)
556
557 s.WindowTooSmall = s.Muted
558
559 // tag presets
560 s.TagBase = lipgloss.NewStyle().Padding(0, 1).Foreground(white)
561 s.TagError = s.TagBase.Background(redDark)
562 s.TagInfo = s.TagBase.Background(blueLight)
563
564 // headers
565 s.HeaderTool = lipgloss.NewStyle().Foreground(blue)
566 s.HeaderToolNested = lipgloss.NewStyle().Foreground(fgHalfMuted)
567
568 // panels
569 s.PanelMuted = s.Muted.Background(bgBaseLighter)
570 s.PanelBase = lipgloss.NewStyle().Background(bgBase)
571
572 // code line number
573 s.LineNumber = lipgloss.NewStyle().Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
574
575 // Tool calls
576 s.ToolCallPending = lipgloss.NewStyle().Foreground(greenDark).SetString(ToolPending)
577 s.ToolCallError = lipgloss.NewStyle().Foreground(redDark).SetString(ToolError)
578 s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
579 // Cancelled uses muted tone but same glyph as pending
580 s.ToolCallCancelled = s.Muted.SetString(ToolPending)
581 s.EarlyStateMessage = s.Subtle.PaddingLeft(2)
582
583 // Buttons
584 s.ButtonFocus = lipgloss.NewStyle().Foreground(white).Background(secondary)
585 s.ButtonBlur = s.Base.Background(bgSubtle)
586
587 // Borders
588 s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
589
590 // Editor
591 s.EditorPromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
592 s.EditorPromptNormalBlurred = s.EditorPromptNormalFocused.Foreground(fgMuted)
593 s.EditorPromptYoloIconFocused = lipgloss.NewStyle().Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
594 s.EditorPromptYoloIconBlurred = s.EditorPromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
595 s.EditorPromptYoloDotsFocused = lipgloss.NewStyle().Foreground(charmtone.Zest).SetString(":::")
596 s.EditorPromptYoloDotsBlurred = s.EditorPromptYoloDotsFocused.Foreground(charmtone.Squid)
597
598 // Logo colors
599 s.LogoFieldColor = primary
600 s.LogoTitleColorA = secondary
601 s.LogoTitleColorB = primary
602 s.LogoCharmColor = secondary
603 s.LogoVersionColor = primary
604
605 // Section
606 s.Section.Title = s.Subtle
607 s.Section.Line = s.Base.Foreground(charmtone.Charcoal)
608
609 // Initialize
610 s.Initialize.Header = s.Base
611 s.Initialize.Content = s.Muted
612 s.Initialize.Accent = s.Base.Foreground(greenDark)
613
614 // LSP and MCP status.
615 s.ItemOfflineIcon = lipgloss.NewStyle().Foreground(charmtone.Squid).SetString("●")
616 s.ItemBusyIcon = s.ItemOfflineIcon.Foreground(charmtone.Citron)
617 s.ItemErrorIcon = s.ItemOfflineIcon.Foreground(charmtone.Coral)
618 s.ItemOnlineIcon = s.ItemOfflineIcon.Foreground(charmtone.Guac)
619
620 // LSP
621 s.LSP.ErrorDiagnostic = s.Base.Foreground(redDark)
622 s.LSP.WarningDiagnostic = s.Base.Foreground(warning)
623 s.LSP.HintDiagnostic = s.Base.Foreground(fgHalfMuted)
624 s.LSP.InfoDiagnostic = s.Base.Foreground(info)
625
626 // Files
627 s.Files.Path = s.Muted
628 s.Files.Additions = s.Base.Foreground(greenDark)
629 s.Files.Deletions = s.Base.Foreground(redDark)
630
631 // Chat
632 messageFocussedBorder := lipgloss.Border{
633 Left: "▌",
634 }
635
636 s.Chat.NoContentMessage = lipgloss.NewStyle().Foreground(fgBase)
637 s.Chat.UserMessageBlurred = s.Chat.NoContentMessage.PaddingLeft(1).BorderLeft(true).
638 BorderForeground(primary).BorderStyle(normalBorder)
639 s.Chat.UserMessageFocused = s.Chat.NoContentMessage.PaddingLeft(1).BorderLeft(true).
640 BorderForeground(primary).BorderStyle(messageFocussedBorder)
641 s.Chat.AssistantMessageBlurred = s.Chat.NoContentMessage.PaddingLeft(2)
642 s.Chat.AssistantMessageFocused = s.Chat.NoContentMessage.PaddingLeft(1).BorderLeft(true).
643 BorderForeground(greenDark).BorderStyle(messageFocussedBorder)
644 s.Chat.ThinkingMessage = lipgloss.NewStyle().MaxHeight(10)
645 s.Chat.ErrorTag = lipgloss.NewStyle().Padding(0, 1).
646 Background(red).Foreground(white)
647 s.Chat.ErrorTitle = lipgloss.NewStyle().Foreground(fgHalfMuted)
648 s.Chat.ErrorDetails = lipgloss.NewStyle().Foreground(fgSubtle)
649
650 // Text selection.
651 s.TextSelection = lipgloss.NewStyle().Foreground(charmtone.Salt).Background(charmtone.Charple)
652
653 return s
654}
655
656// Helper functions for style pointers
657func boolPtr(b bool) *bool { return &b }
658func stringPtr(s string) *string { return &s }
659func uintPtr(u uint) *uint { return &u }