|
6 | 6 | "io"
|
7 | 7 | "os"
|
8 | 8 | "strings"
|
9 |
| - "text/tabwriter" |
10 | 9 | "text/template"
|
11 | 10 |
|
12 | 11 | "github.com/chzyer/readline"
|
@@ -184,6 +183,15 @@ type SelectTemplates struct {
|
184 | 183 | // Keywords is a text/template for the search keywords.
|
185 | 184 | Keywords string
|
186 | 185 |
|
| 186 | + // HideLabel sets whether to hide the label. |
| 187 | + HideLabel bool |
| 188 | + |
| 189 | + // ItemsRenderer is a custom rendering visible items function. |
| 190 | + ItemsRenderer func(items []interface{}, idx int) string |
| 191 | + |
| 192 | + // DetailsRenderer is a custom rendering active item function. |
| 193 | + DetailsRenderer func(item interface{}) string |
| 194 | + |
187 | 195 | // FuncMap is a map of helper functions that can be used inside of templates according to the text/template
|
188 | 196 | // documentation.
|
189 | 197 | //
|
@@ -252,6 +260,44 @@ func (s *Select) getKeywords(keywords string) string {
|
252 | 260 | return s.Keywords + " " + keywords
|
253 | 261 | }
|
254 | 262 |
|
| 263 | +func (s *Select) renderItems(items []interface{}, idx int, top rune) []byte { |
| 264 | + last := len(items) - 1 |
| 265 | + |
| 266 | + var buf bytes.Buffer |
| 267 | + w := NewWriter(&buf, 0, 0, 2, ' ', 0) |
| 268 | + for i, item := range items { |
| 269 | + page := " " |
| 270 | + |
| 271 | + switch i { |
| 272 | + case 0: |
| 273 | + if s.list.CanPageUp() { |
| 274 | + page = "↑" |
| 275 | + } else { |
| 276 | + page = string(top) |
| 277 | + } |
| 278 | + case last: |
| 279 | + if s.list.CanPageDown() { |
| 280 | + page = "↓" |
| 281 | + } |
| 282 | + } |
| 283 | + |
| 284 | + output := []byte(page + " ") |
| 285 | + |
| 286 | + if i == idx { |
| 287 | + output = append(output, render(s.Templates.active, item)...) |
| 288 | + } else { |
| 289 | + output = append(output, render(s.Templates.inactive, item)...) |
| 290 | + } |
| 291 | + |
| 292 | + w.Write(output) |
| 293 | + if i != last { |
| 294 | + w.Write([]byte("\n")) |
| 295 | + } |
| 296 | + } |
| 297 | + w.Flush() |
| 298 | + return buf.Bytes() |
| 299 | +} |
| 300 | + |
255 | 301 | func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error) {
|
256 | 302 | c := &readline.Config{
|
257 | 303 | Stdin: s.Stdin,
|
@@ -369,55 +415,27 @@ func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error)
|
369 | 415 | sb.Write(render(s.Templates.keywords, s.Keywords))
|
370 | 416 | }
|
371 | 417 |
|
372 |
| - label := render(s.Templates.label, s.Label) |
373 |
| - sb.Write(label) |
| 418 | + if !s.Templates.HideLabel { |
| 419 | + label := render(s.Templates.label, s.Label) |
| 420 | + sb.WriteLines(label) |
| 421 | + } |
374 | 422 |
|
375 | 423 | items, idx := s.list.Items()
|
376 |
| - last := len(items) - 1 |
377 |
| - |
378 |
| - var buf bytes.Buffer |
379 |
| - w := tabwriter.NewWriter(&buf, 0, 0, 2, ' ', 0) |
380 |
| - for i, item := range items { |
381 |
| - page := " " |
382 |
| - |
383 |
| - switch i { |
384 |
| - case 0: |
385 |
| - if s.list.CanPageUp() { |
386 |
| - page = "↑" |
387 |
| - } else { |
388 |
| - page = string(top) |
389 |
| - } |
390 |
| - case last: |
391 |
| - if s.list.CanPageDown() { |
392 |
| - page = "↓" |
393 |
| - } |
394 |
| - } |
395 |
| - |
396 |
| - output := []byte(page + " ") |
397 |
| - |
398 |
| - if i == idx { |
399 |
| - output = append(output, render(s.Templates.active, item)...) |
400 |
| - } else { |
401 |
| - output = append(output, render(s.Templates.inactive, item)...) |
402 |
| - } |
403 |
| - |
404 |
| - w.Write(output) |
405 |
| - w.Write([]byte("\n")) |
406 |
| - } |
407 |
| - w.Flush() |
408 |
| - for _, d := range bytes.Split(buf.Bytes(), []byte("\n")) { |
409 |
| - sb.Write(d) |
| 424 | + if s.Templates.ItemsRenderer != nil { |
| 425 | + sb.WriteLines([]byte(s.Templates.ItemsRenderer(items, idx))) |
| 426 | + } else { |
| 427 | + sb.WriteLines(s.renderItems(items, idx, top)) |
410 | 428 | }
|
411 | 429 |
|
412 | 430 | if idx == list.NotFound {
|
413 | 431 | sb.WriteString("")
|
414 | 432 | sb.WriteString("No results")
|
415 | 433 | } else {
|
416 | 434 | active := items[idx]
|
417 |
| - |
418 |
| - details := s.renderDetails(active) |
419 |
| - for _, d := range details { |
420 |
| - sb.Write(d) |
| 435 | + if s.Templates.DetailsRenderer != nil { |
| 436 | + sb.WriteLines([]byte(s.Templates.DetailsRenderer(active))) |
| 437 | + } else { |
| 438 | + sb.WriteLines(s.renderDetails(active)) |
421 | 439 | }
|
422 | 440 | }
|
423 | 441 |
|
@@ -508,22 +526,24 @@ func (s *Select) prepareTemplates() error {
|
508 | 526 | tpls.FuncMap = FuncMap
|
509 | 527 | }
|
510 | 528 |
|
511 |
| - if tpls.Label == "" { |
512 |
| - tpls.Label = fmt.Sprintf("%s {{.}}: ", IconInitial) |
513 |
| - } |
| 529 | + if !tpls.HideLabel { |
| 530 | + if tpls.Label == "" { |
| 531 | + tpls.Label = fmt.Sprintf("%s {{.}}: ", IconInitial) |
| 532 | + } |
514 | 533 |
|
515 |
| - tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Label) |
516 |
| - if err != nil { |
517 |
| - return err |
518 |
| - } |
| 534 | + tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Label) |
| 535 | + if err != nil { |
| 536 | + return err |
| 537 | + } |
519 | 538 |
|
520 |
| - tpls.label = tpl |
| 539 | + tpls.label = tpl |
| 540 | + } |
521 | 541 |
|
522 | 542 | if tpls.Active == "" {
|
523 | 543 | tpls.Active = fmt.Sprintf("%s {{ . | underline }}", IconSelect)
|
524 | 544 | }
|
525 | 545 |
|
526 |
| - tpl, err = template.New("").Funcs(tpls.FuncMap).Parse(tpls.Active) |
| 546 | + tpl, err := template.New("").Funcs(tpls.FuncMap).Parse(tpls.Active) |
527 | 547 | if err != nil {
|
528 | 548 | return err
|
529 | 549 | }
|
@@ -699,25 +719,22 @@ func (s *Select) setKeys() {
|
699 | 719 | }
|
700 | 720 | }
|
701 | 721 |
|
702 |
| -func (s *Select) renderDetails(item interface{}) [][]byte { |
| 722 | +func (s *Select) renderDetails(item interface{}) []byte { |
703 | 723 | if s.Templates.details == nil {
|
704 | 724 | return nil
|
705 | 725 | }
|
706 | 726 |
|
707 | 727 | var buf bytes.Buffer
|
708 | 728 |
|
709 |
| - w := tabwriter.NewWriter(&buf, 0, 0, 2, ' ', 0) |
| 729 | + w := NewWriter(&buf, 0, 0, 2, ' ', 0) |
710 | 730 |
|
711 | 731 | err := s.Templates.details.Execute(w, item)
|
712 | 732 | if err != nil {
|
713 | 733 | fmt.Fprintf(w, "%v", item)
|
714 | 734 | }
|
715 | 735 |
|
716 | 736 | w.Flush()
|
717 |
| - |
718 |
| - output := buf.Bytes() |
719 |
| - |
720 |
| - return bytes.Split(output, []byte("\n")) |
| 737 | + return buf.Bytes() |
721 | 738 | }
|
722 | 739 |
|
723 | 740 | func (s *Select) renderHelp(b bool) []byte {
|
|
0 commit comments