z_mirror/pesticide
git clone https://git.raiguard.me/z_mirror/pesticide
388f8ba
trunk
1package ui 2 3import ( 4"fmt" 5 6 tea"github.com/charmbracelet/bubbletea" 7"github.com/google/go-dap" 8"codeberg.org/raiguard/pesticide/adapter" 9"codeberg.org/raiguard/pesticide/command" 10) 11 12func (m * Model )handleCommand (cmd command.Command ) tea.Cmd { 13switch cmd := cmd .(type ) { 14case command.Backtrace : 15return m .handleBacktraceCommand (cmd ) 16case command.Break : 17return m .handleBreakCommand (cmd ) 18case command.Continue : 19return m .handleContinueCommand (cmd ) 20case command.Down : 21return m .handleStackFrameCommand (- int (cmd )) 22case command.Evaluate : 23return m .handleEvaluateCommand (cmd ) 24case command.Launch : 25return m .handleLaunchCommand (cmd ) 26case command.Next : 27return m .handleNextCommand (cmd ) 28case command.Pause : 29return m .handlePauseCommand (cmd ) 30case command.Quit : 31return m .handleQuitCommand (cmd ) 32case command.Step : 33return m .handleStepCommand (cmd ) 34case command.StepOut : 35return m .handleStepOutCommand (cmd ) 36case command.Up : 37return m .handleStackFrameCommand (int (cmd )) 38 } 39return nil 40} 41 42func (m * Model )handleBacktraceCommand (cmd command.Backtrace ) tea.Cmd { 43a := m .focusedAdapter 44if a == nil { 45return tea .Println ("No adapter in focus" ) 46 } 47var output string 48for _ ,frame := range a .StackFrames [a .FocusedThread ] { 49output += fmt .Sprintf ("%s:%d\n" ,frame .Source .Path ,frame .Line ) 50 } 51return tea .Printf ("%s" ,output ) 52} 53 54func (m * Model )handleBreakCommand (cmd command.Break ) tea.Cmd { 55a := m .focusedAdapter 56if a == nil { 57return tea .Println ("No adapter in focus" ) 58 } 59if _ ,ok := a .Breakpoints [cmd .File ];! ok { 60a .Breakpoints [cmd .File ]= []dap.SourceBreakpoint {} 61 } 62// TODO: Deduplicate 63a .Breakpoints [cmd .File ]= append (a .Breakpoints [cmd .File ], dap.SourceBreakpoint {Line :cmd .Line }) 64m .sendSetBreakpointsRequest (a ) 65return nil 66} 67 68func (m * Model )handleContinueCommand (cmd command.Continue ) tea.Cmd { 69a := m .focusedAdapter 70if a == nil { 71return tea .Println ("No adapter in focus" ) 72 } 73a .Send (& dap.ContinueRequest {Request :a .NewRequest ("continue" )}) 74return nil 75} 76 77func (m * Model )handleEvaluateCommand (cmd command.Evaluate ) tea.Cmd { 78a := m .focusedAdapter 79if a == nil { 80return tea .Println ("No adapter in focus" ) 81 } 82if a .State != adapter .Stopped { 83return tea .Println ("Cannot evaluate expressions while running" ) 84 } 85a .Send (& dap.EvaluateRequest { 86Request :a .NewRequest ("evaluate" ), 87Arguments : dap.EvaluateArguments { 88Expression :cmd .Expr , 89FrameId :a .FocusedStackFrame .Id , 90Context :"repl" , 91 }, 92 }) 93return nil 94} 95 96func (m * Model )handleLaunchCommand (cmd command.Launch ) tea.Cmd { 97adapterConfig ,ok := m .config .Adapters [cmd .Name ] 98if ! ok { 99return tea .Printf ("Unknown debug adapter %s" ,cmd .Name ) 100 } 101a ,err := adapter .New (adapterConfig ) 102if err != nil { 103return tea .Println (err ) 104 } 105m .adapters [a .ID ]= a 106m .focusedAdapter = a 107a .Send (& dap.InitializeRequest { 108Request :a .NewRequest ("initialize" ), 109Arguments : dap.InitializeRequestArguments { 110ClientID :"pesticide" , 111ClientName :"Pesticide" , 112Locale :"en-US" , 113PathFormat :"path" , 114LinesStartAt1 :true , 115ColumnsStartAt1 :true , 116 }, 117 }) 118return func () tea.Msg {return a .Receive () } 119} 120 121func (m * Model )handlePauseCommand (cmd command.Pause ) tea.Cmd { 122a := m .focusedAdapter 123if a == nil { 124return tea .Println ("No adapter in focus" ) 125 } 126a .Send (& dap.PauseRequest { 127Request :a .NewRequest ("pause" ), 128 }) 129return nil 130 131} 132 133func (m * Model )handleQuitCommand (cmd command.Quit ) tea.Cmd { 134a := m .focusedAdapter 135if a == nil { 136// TODO: Clean up unfocused adapters 137return tea .Quit 138 } 139// TODO: Store whether terminate has been sent and send disconnect in that case 140if a .Capabilities .SupportsTerminateRequest { 141a .Send (& dap.TerminateRequest {Request :a .NewRequest ("terminate" )}) 142 }else { 143a .Send (& dap.DisconnectRequest { 144Request :a .NewRequest ("disconnect" ), 145Arguments :& dap.DisconnectArguments { 146TerminateDebuggee :true , 147 }, 148 }) 149// TODO: Force-remove the adapter from the adapters list 150 } 151return nil 152} 153 154func (m * Model )handleStackFrameCommand (delta int ) tea.Cmd { 155a := m .focusedAdapter 156if a == nil { 157return tea .Println ("No adapter in focus" ) 158 } 159return m .travelStackFrame (a ,delta ) 160} 161 162func (m * Model )handleStepCommand (cmd command.Step ) tea.Cmd { 163a := m .focusedAdapter 164if a == nil { 165return tea .Println ("No adapter in focus" ) 166 } 167a .Send (& dap.StepInRequest { 168Request :a .NewRequest ("stepIn" ), 169Arguments : dap.StepInArguments {ThreadId :a .FocusedThread }, 170 }) 171return nil 172} 173 174func (m * Model )handleStepOutCommand (cmd command.StepOut ) tea.Cmd { 175a := m .focusedAdapter 176if a == nil { 177return tea .Println ("No adapter in focus" ) 178 } 179a .Send (& dap.StepOutRequest { 180Request :a .NewRequest ("stepOut" ), 181Arguments : dap.StepOutArguments {ThreadId :a .FocusedThread }, 182 }) 183return nil 184} 185 186func (m * Model )handleNextCommand (cmd command.Next ) tea.Cmd { 187a := m .focusedAdapter 188if a == nil { 189return tea .Println ("No adapter in focus" ) 190 } 191a .Send (& dap.NextRequest { 192Request :a .NewRequest ("next" ), 193Arguments : dap.NextArguments {ThreadId :a .FocusedThread }, 194 }) 195return nil 196}