@@ -49,6 +49,9 @@ func topCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
4949 return topCmd
5050}
5151
52+ type topHeader map [string ]int // maps a proc title to its output index
53+ type topEntries map [string ]string
54+
5255func runTop (ctx context.Context , dockerCli command.Cli , backend api.Service , opts topOptions , services []string ) error {
5356 projectName , err := opts .toProjectName (ctx , dockerCli )
5457 if err != nil {
@@ -63,30 +66,60 @@ func runTop(ctx context.Context, dockerCli command.Cli, backend api.Service, opt
6366 return containers [i ].Name < containers [j ].Name
6467 })
6568
69+ header , entries := collectTop (containers )
70+ return topPrint (dockerCli .Out (), header , entries )
71+ }
72+
73+ func collectTop (containers []api.ContainerProcSummary ) (topHeader , []topEntries ) {
74+ // map column name to its header (should keep working if backend.Top returns
75+ // varying columns for different containers)
76+ header := topHeader {"SERVICE" : 0 }
77+
78+ // assume one process per container and grow if needed
79+ entries := make ([]topEntries , 0 , len (containers ))
80+
6681 for _ , container := range containers {
67- _ , _ = fmt .Fprintf (dockerCli .Out (), "%s\n " , container .Name )
68- err := psPrinter (dockerCli .Out (), func (w io.Writer ) {
69- for _ , proc := range container .Processes {
70- info := []interface {}{}
71- for _ , p := range proc {
72- info = append (info , p )
73- }
74- _ , _ = fmt .Fprintf (w , strings .Repeat ("%s\t " , len (info ))+ "\n " , info ... )
82+ for _ , proc := range container .Processes {
83+ entry := topEntries {"SERVICE" : container .Name }
7584
85+ for i , title := range container .Titles {
86+ if _ , exists := header [title ]; ! exists {
87+ header [title ] = len (header )
88+ }
89+ entry [title ] = proc [i ]
7690 }
77- _ , _ = fmt .Fprintln (w )
78- },
79- container .Titles ... )
80- if err != nil {
81- return err
91+
92+ entries = append (entries , entry )
8293 }
8394 }
84- return nil
95+ return header , entries
8596}
8697
87- func psPrinter (out io.Writer , printer func (writer io.Writer ), headers ... string ) error {
98+ func topPrint (out io.Writer , headers topHeader , rows []topEntries ) error {
99+ if len (rows ) == 0 {
100+ return nil
101+ }
102+
88103 w := tabwriter .NewWriter (out , 5 , 1 , 3 , ' ' , 0 )
89- _ , _ = fmt .Fprintln (w , strings .Join (headers , "\t " ))
90- printer (w )
104+
105+ // write headers in the order we've encountered them
106+ h := make ([]string , len (headers ))
107+ for title , index := range headers {
108+ h [index ] = title
109+ }
110+ _ , _ = fmt .Fprintln (w , strings .Join (h , "\t " ))
111+
112+ for _ , row := range rows {
113+ // write proc data in header order
114+ r := make ([]string , len (headers ))
115+ for title , index := range headers {
116+ if v , ok := row [title ]; ok {
117+ r [index ] = v
118+ } else {
119+ r [index ] = "-"
120+ }
121+ }
122+ _ , _ = fmt .Fprintln (w , strings .Join (r , "\t " ))
123+ }
91124 return w .Flush ()
92125}
0 commit comments