github.com/whyrusleeping/gx@v0.14.3/ui.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/json"
     6  	"fmt"
     7  	"os"
     8  	"strconv"
     9  	"strings"
    10  	"text/tabwriter"
    11  
    12  	gx "github.com/whyrusleeping/gx/gxutil"
    13  	. "github.com/whyrusleeping/stump"
    14  )
    15  
    16  func promptUser(query string) string {
    17  	fmt.Printf("%s ", query)
    18  	scan := bufio.NewScanner(os.Stdin)
    19  	scan.Scan()
    20  	return scan.Text()
    21  }
    22  
    23  func yesNoPrompt(prompt string, def bool) bool {
    24  	opts := "[y/N]"
    25  	if def {
    26  		opts = "[Y/n]"
    27  	}
    28  
    29  	fmt.Printf("%s %s ", prompt, opts)
    30  	scan := bufio.NewScanner(os.Stdin)
    31  	for scan.Scan() {
    32  		val := strings.ToLower(scan.Text())
    33  		switch val {
    34  		case "":
    35  			return def
    36  		case "y":
    37  			return true
    38  		case "n":
    39  			return false
    40  		default:
    41  			fmt.Println("please type 'y' or 'n'")
    42  		}
    43  	}
    44  
    45  	panic("unexpected termination of stdin")
    46  }
    47  
    48  func jsonPrint(i interface{}) {
    49  	out, _ := json.MarshalIndent(i, "", "  ")
    50  	outs, err := strconv.Unquote(string(out)) // for printing out raw strings
    51  	if err != nil {
    52  		outs = string(out)
    53  	}
    54  	Log(outs)
    55  }
    56  
    57  type depTreeNode struct {
    58  	this     *gx.Dependency
    59  	children []*depTreeNode
    60  }
    61  
    62  func genDepsTree(pm *gx.PM, pkg *gx.Package) (*depTreeNode, error) {
    63  
    64  	complete := make(map[string]*depTreeNode)
    65  
    66  	var rec func(pkg *gx.Package) (*depTreeNode, error)
    67  	rec = func(pkg *gx.Package) (*depTreeNode, error) {
    68  		cur := new(depTreeNode)
    69  		cur.this = new(gx.Dependency)
    70  		cur.this.Name = pkg.Name
    71  
    72  		err := pkg.ForEachDep(func(dep *gx.Dependency, dpkg *gx.Package) error {
    73  			sub := complete[dep.Hash]
    74  			if sub == nil {
    75  				var err error
    76  				sub, err = rec(dpkg)
    77  				if err != nil {
    78  					return err
    79  				}
    80  				complete[dep.Hash] = sub
    81  			}
    82  
    83  			sub.this = dep
    84  			cur.children = append(cur.children, sub)
    85  
    86  			return nil
    87  		})
    88  
    89  		return cur, err
    90  	}
    91  
    92  	return rec(pkg)
    93  }
    94  
    95  func (dtn *depTreeNode) matches(filter string) bool {
    96  	if filter == "" {
    97  		return true
    98  	}
    99  
   100  	if dtn.this.Hash == filter || dtn.this.Name == filter {
   101  		return true
   102  	}
   103  
   104  	for _, c := range dtn.children {
   105  		if c.matches(filter) {
   106  			return true
   107  		}
   108  	}
   109  	return false
   110  }
   111  
   112  const (
   113  	tBar  = "│"
   114  	tEnd  = "└"
   115  	tDash = "─"
   116  	tTree = "├"
   117  )
   118  
   119  func (dtn *depTreeNode) printFiltered(filter string, quiet, collapse bool) {
   120  	tabw := tabwriter.NewWriter(os.Stdout, 12, 4, 1, ' ', 0)
   121  
   122  	printed := make(map[string]bool)
   123  	var rec func(*depTreeNode, string)
   124  	rec = func(p *depTreeNode, prefix string) {
   125  		if len(p.children) == 0 {
   126  			return
   127  		}
   128  
   129  		var toprint []*depTreeNode
   130  		for _, n := range p.children {
   131  			if n.matches(filter) {
   132  				toprint = append(toprint, n)
   133  			}
   134  		}
   135  		if printed[p.this.Hash] && collapse {
   136  			toprint = []*depTreeNode{
   137  				{
   138  					this: &gx.Dependency{
   139  						Name: "...",
   140  					},
   141  				},
   142  			}
   143  		}
   144  		for i, n := range toprint {
   145  			last := i == len(toprint)-1
   146  			dep := n.this
   147  			label := dep.Hash
   148  			if !quiet {
   149  				pref := tTree
   150  				if last {
   151  					pref = tEnd
   152  				}
   153  
   154  				label = fmt.Sprintf("%s%s \033[1m%s\033[0m\t%s\t%s", pref, tDash, dep.Name, dep.Hash, dep.Version)
   155  			}
   156  
   157  			fmt.Fprintln(tabw, prefix+label)
   158  
   159  			nextPref := prefix + tBar + "  "
   160  			if last {
   161  				nextPref = prefix + "   "
   162  			}
   163  			rec(n, nextPref)
   164  		}
   165  
   166  		printed[p.this.Hash] = true
   167  	}
   168  
   169  	rec(dtn, "")
   170  
   171  	tabw.Flush()
   172  }