MCPcopy
hub / github.com/cli/cli / renderInteractive

Function renderInteractive

pkg/cmd/skills/preview/preview.go:317–373  ·  view source on GitHub ↗

renderInteractive shows the file tree, then a picker to browse individual files.

(opts *PreviewOptions, cs *iostreams.ColorScheme, skill discovery.Skill,
	files []discovery.SkillFile, renderedSkillMD string, extraFiles []discovery.SkillFile,
	apiClient *api.Client, hostname, owner, repo string)

Source from the content-addressed store, hash-verified

315
316// renderInteractive shows the file tree, then a picker to browse individual files.
317func renderInteractive(opts *PreviewOptions, cs *iostreams.ColorScheme, skill discovery.Skill,
318 files []discovery.SkillFile, renderedSkillMD string, extraFiles []discovery.SkillFile,
319 apiClient *api.Client, hostname, owner, repo string) {
320
321 // Show the file tree to stderr so it persists above the prompt
322 fmt.Fprintf(opts.IO.ErrOut, "\n%s\n", cs.Bold(skill.DisplayName()+"/"))
323 renderFileTree(opts.IO.ErrOut, cs, files)
324 fmt.Fprintln(opts.IO.ErrOut)
325
326 // Build choices: SKILL.md first, then extra files
327 choices := make([]string, 0, len(extraFiles)+1)
328 choices = append(choices, "SKILL.md")
329 for _, f := range extraFiles {
330 choices = append(choices, f.Path)
331 }
332
333 // Save original stdout. StopPager closes IO.Out, so we need to
334 // restore a working writer before each StartPager call.
335 originalOut := opts.IO.Out
336
337 for {
338 // Restore original Out before each pager cycle. StartPager replaces
339 // IO.Out with a pipe; StopPager closes that pipe but does not
340 // restore the original. The original writer remains valid.
341 opts.IO.Out = originalOut
342
343 idx, err := opts.Prompter.Select("View a file (Esc to exit):", "", choices)
344 if err != nil {
345 return // Prompter returns error on Esc/Ctrl-C; treat as graceful exit
346 }
347
348 var content string
349
350 if idx == 0 {
351 content = renderedSkillMD
352 } else {
353 selectedFile := extraFiles[idx-1]
354
355 // Fetch on demand; don't hold blob data in memory
356 fileContent, fetchErr := discovery.FetchBlob(apiClient, hostname, owner, repo, selectedFile.SHA)
357 if fetchErr != nil {
358 fmt.Fprintf(opts.IO.ErrOut, "%s could not fetch %s: %v\n", cs.Red("!"), selectedFile.Path, fetchErr)
359 continue
360 }
361 content = renderSelectedFilePreview(opts, selectedFile.Path, fileContent)
362 if !strings.HasSuffix(content, "\n") {
363 content += "\n"
364 }
365 }
366
367 if err := opts.IO.StartPager(); err != nil {
368 fmt.Fprintf(opts.IO.ErrOut, "starting pager failed: %v\n", err)
369 }
370 fmt.Fprint(opts.IO.Out, content)
371 opts.IO.StopPager()
372 }
373}
374

Callers 1

previewRunFunction · 0.85

Calls 9

FetchBlobFunction · 0.92
renderFileTreeFunction · 0.85
BoldMethod · 0.80
RedMethod · 0.80
StartPagerMethod · 0.80
StopPagerMethod · 0.80
DisplayNameMethod · 0.65
SelectMethod · 0.65

Tested by

no test coverage detected