1515package main
1616
1717import (
18+ "encoding/json"
1819 "errors"
1920 "fmt"
2021 "io/fs"
@@ -51,18 +52,20 @@ type InstallCmd struct {
5152 // URI url.URL `arg:"-u" placeholder:"URL" help:"Base URL for fetching drivers"`
5253 Driver string `arg:"positional,required" help:"Driver to install"`
5354 Level config.ConfigLevel `arg:"-l" help:"Config level to install to (user, system)"`
55+ Json bool `arg:"--json" help:"Output JSON instead of plaintext"`
5456 NoVerify bool `arg:"--no-verify" help:"Allow installation of drivers without a signature file"`
5557}
5658
5759func (c InstallCmd ) GetModelCustom (baseModel baseModel ) tea.Model {
5860 s := spinner .New ()
5961 s .Spinner = spinner .MiniDot
6062 return progressiveInstallModel {
61- Driver : c .Driver ,
62- NoVerify : c .NoVerify ,
63- spinner : s ,
64- cfg : getConfig (c .Level ),
65- baseModel : baseModel ,
63+ Driver : c .Driver ,
64+ NoVerify : c .NoVerify ,
65+ jsonOutput : c .Json ,
66+ spinner : s ,
67+ cfg : getConfig (c .Level ),
68+ baseModel : baseModel ,
6669 p : dbc .NewFileProgress (
6770 progress .WithDefaultGradient (),
6871 progress .WithWidth (20 ),
@@ -147,6 +150,7 @@ type progressiveInstallModel struct {
147150 Driver string
148151 VersionInput * semver.Version
149152 NoVerify bool
153+ jsonOutput bool
150154 cfg config.Config
151155
152156 DriverPackage dbc.PkgInfo
@@ -173,23 +177,55 @@ func (m progressiveInstallModel) Init() tea.Cmd {
173177func (m progressiveInstallModel ) FinalOutput () string {
174178 if m .conflictingInfo .ID != "" && m .conflictingInfo .Version != nil {
175179 if m .conflictingInfo .Version .Equal (m .DriverPackage .Version ) {
180+ if m .jsonOutput {
181+ return fmt .Sprintf (`{"status":"already installed","driver":"%s","version":"%s","location":"%s"}` ,
182+ m .conflictingInfo .ID , m .conflictingInfo .Version , filepath .SplitList (m .cfg .Location )[0 ])
183+ }
176184 return fmt .Sprintf ("\n Driver %s %s already installed at %s\n " ,
177185 m .conflictingInfo .ID , m .conflictingInfo .Version , filepath .SplitList (m .cfg .Location )[0 ])
178186 }
179187 }
180188
181189 var b strings.Builder
182190 if m .state == stDone {
183- if m .conflictingInfo .ID != "" && m .conflictingInfo .Version != nil {
184- b .WriteString (fmt .Sprintf ("\n Removed conflicting driver: %s (version: %s)" ,
185- m .conflictingInfo .ID , m .conflictingInfo .Version ))
191+ var output struct {
192+ Status string `json:"status"`
193+ Driver string `json:"driver"`
194+ Version string `json:"version"`
195+ Location string `json:"location"`
196+ Message string `json:"message,omitempty"`
197+ Conflict string `json:"conflict,omitempty"`
186198 }
187199
188- b .WriteString (fmt .Sprintf ("\n Installed %s %s to %s\n " ,
189- m .Driver , m .DriverPackage .Version , filepath .SplitList (m .cfg .Location )[0 ]))
200+ output .Status = "installed"
201+ output .Driver = m .Driver
202+ output .Version = m .DriverPackage .Version .String ()
203+ output .Location = filepath .SplitList (m .cfg .Location )[0 ]
204+ if m .conflictingInfo .ID != "" && m .conflictingInfo .Version != nil {
205+ output .Conflict = fmt .Sprintf ("%s (version: %s)" , m .conflictingInfo .ID , m .conflictingInfo .Version )
206+ }
190207
191208 if m .postInstallMessage != "" {
192- b .WriteString ("\n " + postMsgStyle .Render (m .postInstallMessage ) + "\n " )
209+ output .Message = m .postInstallMessage
210+ }
211+
212+ if m .jsonOutput {
213+ jsonOutput , err := json .Marshal (output )
214+ if err != nil {
215+ return fmt .Sprintf (`{"status":"error","error":"%s"}` , err .Error ())
216+ }
217+ return string (jsonOutput )
218+ }
219+
220+ if output .Conflict != "" {
221+ fmt .Fprintf (& b , "\n Removed conflicting driver: %s" , output .Conflict )
222+ }
223+
224+ fmt .Fprintf (& b , "\n Installed %s %s to %s\n " ,
225+ output .Driver , output .Version , output .Location )
226+
227+ if output .Message != "" {
228+ b .WriteString ("\n " + postMsgStyle .Render (output .Message ) + "\n " )
193229 }
194230 }
195231 return b .String ()
@@ -303,6 +339,10 @@ func (m progressiveInstallModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
303339 return m , tea .Sequence (func () tea.Msg {
304340 return config .CreateManifest (m .cfg , msg .DriverInfo )
305341 }, tea .Quit )
342+ case error :
343+ if m .jsonOutput {
344+ return m , tea .Sequence (tea .Println (fmt .Sprintf (`{"status":"error","error":"%s"}` , msg .Error ())), tea .Quit )
345+ }
306346 }
307347
308348 base , cmd := m .baseModel .Update (msg )
@@ -320,7 +360,7 @@ func checkbox(label string, checked bool) string {
320360var postMsgStyle = lipgloss .NewStyle ().Foreground (lipgloss .Color ("205" ))
321361
322362func (m progressiveInstallModel ) View () string {
323- if m .status != 0 {
363+ if m .status != 0 || m . jsonOutput {
324364 return ""
325365 }
326366
@@ -333,7 +373,7 @@ func (m progressiveInstallModel) View() string {
333373 var b strings.Builder
334374 for s := range stDone {
335375 if s == m .state {
336- b . WriteString ( fmt .Sprintf ( "[%s] %s..." , m .spinner .View (), s .String () ))
376+ fmt .Fprintf ( & b , "[%s] %s..." , m .spinner .View (), s .String ())
337377 if s == stDownloading {
338378 b .WriteString (" " + m .p .View ())
339379 }
0 commit comments