├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── assets ├── demo.gif └── icon.svg └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "anstream" 22 | version = "0.6.18" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 25 | dependencies = [ 26 | "anstyle", 27 | "anstyle-parse", 28 | "anstyle-query", 29 | "anstyle-wincon", 30 | "colorchoice", 31 | "is_terminal_polyfill", 32 | "utf8parse", 33 | ] 34 | 35 | [[package]] 36 | name = "anstyle" 37 | version = "1.0.10" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 40 | 41 | [[package]] 42 | name = "anstyle-parse" 43 | version = "0.2.6" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 46 | dependencies = [ 47 | "utf8parse", 48 | ] 49 | 50 | [[package]] 51 | name = "anstyle-query" 52 | version = "1.1.2" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 55 | dependencies = [ 56 | "windows-sys 0.59.0", 57 | ] 58 | 59 | [[package]] 60 | name = "anstyle-wincon" 61 | version = "3.0.7" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 64 | dependencies = [ 65 | "anstyle", 66 | "once_cell", 67 | "windows-sys 0.59.0", 68 | ] 69 | 70 | [[package]] 71 | name = "anyhow" 72 | version = "1.0.95" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" 75 | 76 | [[package]] 77 | name = "autocfg" 78 | version = "1.4.0" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 81 | 82 | [[package]] 83 | name = "backtrace" 84 | version = "0.3.74" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 87 | dependencies = [ 88 | "addr2line", 89 | "cfg-if", 90 | "libc", 91 | "miniz_oxide", 92 | "object", 93 | "rustc-demangle", 94 | "windows-targets", 95 | ] 96 | 97 | [[package]] 98 | name = "bitflags" 99 | version = "2.8.0" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" 102 | 103 | [[package]] 104 | name = "bytes" 105 | version = "1.10.0" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" 108 | 109 | [[package]] 110 | name = "camino" 111 | version = "1.1.9" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" 114 | dependencies = [ 115 | "serde", 116 | ] 117 | 118 | [[package]] 119 | name = "cargo-debugger" 120 | version = "0.1.1" 121 | dependencies = [ 122 | "anyhow", 123 | "cargo_metadata", 124 | "clap", 125 | "serde", 126 | "serde_json", 127 | "tokio", 128 | "urlencoding", 129 | ] 130 | 131 | [[package]] 132 | name = "cargo-platform" 133 | version = "0.1.9" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" 136 | dependencies = [ 137 | "serde", 138 | ] 139 | 140 | [[package]] 141 | name = "cargo_metadata" 142 | version = "0.19.1" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "8769706aad5d996120af43197bf46ef6ad0fda35216b4505f926a365a232d924" 145 | dependencies = [ 146 | "camino", 147 | "cargo-platform", 148 | "semver", 149 | "serde", 150 | "serde_json", 151 | "thiserror", 152 | ] 153 | 154 | [[package]] 155 | name = "cfg-if" 156 | version = "1.0.0" 157 | source = "registry+https://github.com/rust-lang/crates.io-index" 158 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 159 | 160 | [[package]] 161 | name = "clap" 162 | version = "4.5.28" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff" 165 | dependencies = [ 166 | "clap_builder", 167 | "clap_derive", 168 | ] 169 | 170 | [[package]] 171 | name = "clap_builder" 172 | version = "4.5.27" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" 175 | dependencies = [ 176 | "anstream", 177 | "anstyle", 178 | "clap_lex", 179 | "strsim", 180 | ] 181 | 182 | [[package]] 183 | name = "clap_derive" 184 | version = "4.5.28" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" 187 | dependencies = [ 188 | "heck", 189 | "proc-macro2", 190 | "quote", 191 | "syn", 192 | ] 193 | 194 | [[package]] 195 | name = "clap_lex" 196 | version = "0.7.4" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 199 | 200 | [[package]] 201 | name = "colorchoice" 202 | version = "1.0.3" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 205 | 206 | [[package]] 207 | name = "gimli" 208 | version = "0.31.1" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 211 | 212 | [[package]] 213 | name = "heck" 214 | version = "0.5.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 217 | 218 | [[package]] 219 | name = "is_terminal_polyfill" 220 | version = "1.70.1" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 223 | 224 | [[package]] 225 | name = "itoa" 226 | version = "1.0.14" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" 229 | 230 | [[package]] 231 | name = "libc" 232 | version = "0.2.169" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 235 | 236 | [[package]] 237 | name = "lock_api" 238 | version = "0.4.12" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 241 | dependencies = [ 242 | "autocfg", 243 | "scopeguard", 244 | ] 245 | 246 | [[package]] 247 | name = "memchr" 248 | version = "2.7.4" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 251 | 252 | [[package]] 253 | name = "miniz_oxide" 254 | version = "0.8.3" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" 257 | dependencies = [ 258 | "adler2", 259 | ] 260 | 261 | [[package]] 262 | name = "mio" 263 | version = "1.0.3" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" 266 | dependencies = [ 267 | "libc", 268 | "wasi", 269 | "windows-sys 0.52.0", 270 | ] 271 | 272 | [[package]] 273 | name = "object" 274 | version = "0.36.7" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 277 | dependencies = [ 278 | "memchr", 279 | ] 280 | 281 | [[package]] 282 | name = "once_cell" 283 | version = "1.20.2" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 286 | 287 | [[package]] 288 | name = "parking_lot" 289 | version = "0.12.3" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 292 | dependencies = [ 293 | "lock_api", 294 | "parking_lot_core", 295 | ] 296 | 297 | [[package]] 298 | name = "parking_lot_core" 299 | version = "0.9.10" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 302 | dependencies = [ 303 | "cfg-if", 304 | "libc", 305 | "redox_syscall", 306 | "smallvec", 307 | "windows-targets", 308 | ] 309 | 310 | [[package]] 311 | name = "pin-project-lite" 312 | version = "0.2.16" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 315 | 316 | [[package]] 317 | name = "proc-macro2" 318 | version = "1.0.93" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" 321 | dependencies = [ 322 | "unicode-ident", 323 | ] 324 | 325 | [[package]] 326 | name = "quote" 327 | version = "1.0.38" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" 330 | dependencies = [ 331 | "proc-macro2", 332 | ] 333 | 334 | [[package]] 335 | name = "redox_syscall" 336 | version = "0.5.8" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" 339 | dependencies = [ 340 | "bitflags", 341 | ] 342 | 343 | [[package]] 344 | name = "rustc-demangle" 345 | version = "0.1.24" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 348 | 349 | [[package]] 350 | name = "ryu" 351 | version = "1.0.19" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" 354 | 355 | [[package]] 356 | name = "scopeguard" 357 | version = "1.2.0" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 360 | 361 | [[package]] 362 | name = "semver" 363 | version = "1.0.25" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" 366 | dependencies = [ 367 | "serde", 368 | ] 369 | 370 | [[package]] 371 | name = "serde" 372 | version = "1.0.217" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" 375 | dependencies = [ 376 | "serde_derive", 377 | ] 378 | 379 | [[package]] 380 | name = "serde_derive" 381 | version = "1.0.217" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" 384 | dependencies = [ 385 | "proc-macro2", 386 | "quote", 387 | "syn", 388 | ] 389 | 390 | [[package]] 391 | name = "serde_json" 392 | version = "1.0.138" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" 395 | dependencies = [ 396 | "itoa", 397 | "memchr", 398 | "ryu", 399 | "serde", 400 | ] 401 | 402 | [[package]] 403 | name = "signal-hook-registry" 404 | version = "1.4.2" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 407 | dependencies = [ 408 | "libc", 409 | ] 410 | 411 | [[package]] 412 | name = "smallvec" 413 | version = "1.13.2" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 416 | 417 | [[package]] 418 | name = "socket2" 419 | version = "0.5.8" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" 422 | dependencies = [ 423 | "libc", 424 | "windows-sys 0.52.0", 425 | ] 426 | 427 | [[package]] 428 | name = "strsim" 429 | version = "0.11.1" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 432 | 433 | [[package]] 434 | name = "syn" 435 | version = "2.0.98" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" 438 | dependencies = [ 439 | "proc-macro2", 440 | "quote", 441 | "unicode-ident", 442 | ] 443 | 444 | [[package]] 445 | name = "thiserror" 446 | version = "2.0.11" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" 449 | dependencies = [ 450 | "thiserror-impl", 451 | ] 452 | 453 | [[package]] 454 | name = "thiserror-impl" 455 | version = "2.0.11" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" 458 | dependencies = [ 459 | "proc-macro2", 460 | "quote", 461 | "syn", 462 | ] 463 | 464 | [[package]] 465 | name = "tokio" 466 | version = "1.43.0" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" 469 | dependencies = [ 470 | "backtrace", 471 | "bytes", 472 | "libc", 473 | "mio", 474 | "parking_lot", 475 | "pin-project-lite", 476 | "signal-hook-registry", 477 | "socket2", 478 | "tokio-macros", 479 | "windows-sys 0.52.0", 480 | ] 481 | 482 | [[package]] 483 | name = "tokio-macros" 484 | version = "2.5.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 487 | dependencies = [ 488 | "proc-macro2", 489 | "quote", 490 | "syn", 491 | ] 492 | 493 | [[package]] 494 | name = "unicode-ident" 495 | version = "1.0.16" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" 498 | 499 | [[package]] 500 | name = "urlencoding" 501 | version = "2.1.3" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" 504 | 505 | [[package]] 506 | name = "utf8parse" 507 | version = "0.2.2" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 510 | 511 | [[package]] 512 | name = "wasi" 513 | version = "0.11.0+wasi-snapshot-preview1" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 516 | 517 | [[package]] 518 | name = "windows-sys" 519 | version = "0.52.0" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 522 | dependencies = [ 523 | "windows-targets", 524 | ] 525 | 526 | [[package]] 527 | name = "windows-sys" 528 | version = "0.59.0" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 531 | dependencies = [ 532 | "windows-targets", 533 | ] 534 | 535 | [[package]] 536 | name = "windows-targets" 537 | version = "0.52.6" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 540 | dependencies = [ 541 | "windows_aarch64_gnullvm", 542 | "windows_aarch64_msvc", 543 | "windows_i686_gnu", 544 | "windows_i686_gnullvm", 545 | "windows_i686_msvc", 546 | "windows_x86_64_gnu", 547 | "windows_x86_64_gnullvm", 548 | "windows_x86_64_msvc", 549 | ] 550 | 551 | [[package]] 552 | name = "windows_aarch64_gnullvm" 553 | version = "0.52.6" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 556 | 557 | [[package]] 558 | name = "windows_aarch64_msvc" 559 | version = "0.52.6" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 562 | 563 | [[package]] 564 | name = "windows_i686_gnu" 565 | version = "0.52.6" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 568 | 569 | [[package]] 570 | name = "windows_i686_gnullvm" 571 | version = "0.52.6" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 574 | 575 | [[package]] 576 | name = "windows_i686_msvc" 577 | version = "0.52.6" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 580 | 581 | [[package]] 582 | name = "windows_x86_64_gnu" 583 | version = "0.52.6" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 586 | 587 | [[package]] 588 | name = "windows_x86_64_gnullvm" 589 | version = "0.52.6" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 592 | 593 | [[package]] 594 | name = "windows_x86_64_msvc" 595 | version = "0.52.6" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 598 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cargo-debugger" 3 | version = "0.1.1" 4 | edition = "2021" 5 | authors = ["Jonathan Kelley"] 6 | license = "MIT" 7 | description = "Launch your cargo build with the vscode debugger attached" 8 | repository = "https://github.com/jkelleyrtp/cargo-debugger" 9 | 10 | [[bin]] 11 | name = "cargo-debugger" 12 | path = "src/main.rs" 13 | 14 | [dependencies] 15 | anyhow = "1.0.95" 16 | cargo_metadata = "0.19.1" 17 | # krates = "0.17.5" 18 | clap = { version = "4.5.28", features = ["derive"] } 19 | serde = { version = "1.0.217", features = ["derive"] } 20 | serde_json = "1.0.138" 21 | tokio = { version = "1.43.0", features = ["full"] } 22 | # tracing = "0.1.41" 23 | urlencoding = "2.1.3" 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cargo-debugger: easily launch rust executables with vscode's debugger 2 | 3 | `cargo-debugger` is a simple CLI tool that launches your cargo build with the vscode debugger attached. 4 | 5 | ![demo.gif](https://github.com/jkelleyrtp/cargo-debugger/raw/main/assets/demo.gif) 6 | 7 | ## Installation 8 | 9 | ```sh 10 | cargo install cargo-debugger 11 | ``` 12 | 13 | ## Usage 14 | cdb is an alias to `cargo rustc --message-format json-diagnostic-rendered-ansi ...` - so simply pass normal cargo arguments to cdb. 15 | 16 | Any extra args after `--` will be passed to the executable under debug. 17 | 18 | ```sh 19 | cargo debugger --bin dioxus-cli -- serve --verbose --experimental-bundle-split --trace --release 20 | ``` 21 | 22 | This will launch your cargo build with the vscode debugger attached. 23 | 24 | Currently, we only support `cargo rustc` equivalents. We also only launch with the code-lldb debugger for vscode. If you'd like to use another editor or debugger, feel free to contribute! 25 | 26 | ## Tips 27 | 28 | - Make sure your target executable has debug symbols. Release builds won't have them. Some custom profiles won't either. 29 | - You can create aliases to cargo-debugger configurations your `.zshrc` or `.bashrc` to make it easier to launch your executables. 30 | - We use the format outlined here for deep-link urls. https://github.com/vadimcn/codelldb/blob/master/MANUAL.md#debugging-externally-launched-code 31 | 32 | ## Future Ideas 33 | 34 | - Support more cargo commands (test, bench, etc) 35 | - Attach to a running process (https://github.com/vadimcn/codelldb/blob/master/MANUAL.md#attaching-debugger-to-the-current-process-c) 36 | - WASM support 37 | - More editors and debuggers 38 | 39 | ## License 40 | 41 | MIT 42 | -------------------------------------------------------------------------------- /assets/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jkelleyrtp/cargo-debugger/db565b0eb325aa530614f3aba8d9c2fedc91a65a/assets/demo.gif -------------------------------------------------------------------------------- /assets/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | 3 | use anyhow::Context; 4 | use std::{env::current_dir, process::Stdio}; 5 | use tokio::io::AsyncBufReadExt; 6 | 7 | #[tokio::main] 8 | async fn main() -> anyhow::Result<()> { 9 | run().await 10 | } 11 | 12 | // cargo debugger --package dioxus-cli --bin dioxus-bin -- serve --verbose --experimental-bundle-split --trace --release 13 | 14 | /// Run any of your workspace's binaries with the debugger attached. 15 | /// 16 | /// cdb serve 17 | async fn run() -> anyhow::Result<()> { 18 | let mut all_args: Vec = std::env::args().collect(); 19 | 20 | // if running as cargo debugger, then remove the debugger arg 21 | if all_args.get(1) == Some(&"debugger".to_string()) { 22 | all_args.remove(1); 23 | } 24 | 25 | let mut parsing_cargo_args = true; 26 | let mut parsing_env_args = true; 27 | let mut cargo_args = vec![]; 28 | let mut process_env_args = vec![]; 29 | let mut rest_args = vec![]; 30 | 31 | println!("all args: {:?}", all_args); 32 | 33 | for arg in all_args.iter().skip(1) { 34 | // Switch to parsing the rest of the args 35 | if arg == "--" && parsing_cargo_args { 36 | parsing_cargo_args = false; 37 | continue; 38 | } 39 | 40 | // Attempt to parse env pairs 41 | if parsing_env_args && !parsing_cargo_args { 42 | if let Some((left, right)) = arg.split_once('=') { 43 | if left.is_empty() || right.is_empty() { 44 | return Err(anyhow::anyhow!("Invalid argument: {}", arg)); 45 | } 46 | 47 | process_env_args.push((left.to_string(), right.to_string())); 48 | } else { 49 | parsing_env_args = false; 50 | rest_args.push(arg.to_string()); 51 | } 52 | continue; 53 | } 54 | 55 | // Attempt to parse cargo args 56 | if parsing_cargo_args { 57 | cargo_args.push(arg.to_string()); 58 | continue; 59 | } 60 | 61 | // Attempt to parse rest args 62 | rest_args.push(arg.to_string()); 63 | } 64 | 65 | if cargo_args.iter().any(|arg| arg == "--help") { 66 | println!("cargo debugger [cargo args] -- [env1=val1 env2=val2] [executable args]"); 67 | return Ok(()); 68 | } 69 | 70 | let mut child = tokio::process::Command::new("cargo") 71 | .arg("rustc") 72 | .args(cargo_args) 73 | .arg("--message-format") 74 | .arg("json-diagnostic-rendered-ansi") 75 | .stdout(Stdio::piped()) 76 | .stderr(Stdio::piped()) 77 | .spawn() 78 | .context("Failed to spawn cargo process")?; 79 | 80 | let stdout = tokio::io::BufReader::new(child.stdout.take().unwrap()); 81 | let stderr = tokio::io::BufReader::new(child.stderr.take().unwrap()); 82 | let mut output_location = None; 83 | let mut stdout = stdout.lines(); 84 | let mut stderr = stderr.lines(); 85 | 86 | loop { 87 | use cargo_metadata::Message; 88 | 89 | let line = tokio::select! { 90 | Ok(Some(line)) = stdout.next_line() => line, 91 | Ok(Some(line)) = stderr.next_line() => line, 92 | else => break, 93 | }; 94 | 95 | let Some(Ok(message)) = Message::parse_stream(std::io::Cursor::new(line)).next() else { 96 | continue; 97 | }; 98 | 99 | match message { 100 | Message::CompilerArtifact(artifact) => { 101 | if let Some(i) = artifact.executable { 102 | output_location = Some(i) 103 | } 104 | } 105 | Message::CompilerMessage(compiler_message) => { 106 | if let Some(rendered) = compiler_message.message.rendered { 107 | println!("{rendered}"); 108 | } 109 | } 110 | Message::BuildScriptExecuted(_build_script) => {} 111 | Message::BuildFinished(build_finished) => { 112 | if !build_finished.success { 113 | // assuming we received a message from the compiler, so we can exit 114 | return Ok(()); 115 | } 116 | } 117 | Message::TextLine(word) => println!("{word}"), 118 | _ => {} 119 | } 120 | } 121 | 122 | let output_location = 123 | output_location.context("Failed to find output location. Build must've failed.")?; 124 | 125 | let cur_dir = current_dir().context("Failed to get current directory")?; 126 | 127 | let args = rest_args 128 | .iter() 129 | .map(|arg| format!("'{}'", urlencoding::encode(arg))) 130 | .collect::>() 131 | .join(", "); 132 | 133 | let env = process_env_args 134 | .iter() 135 | .map(|(k, v)| format!("'{}': '{}'", k, urlencoding::encode(v))) 136 | .collect::>() 137 | .join(", "); 138 | 139 | let url = format!( 140 | "vscode://vadimcn.vscode-lldb/launch/config?{{ 'cwd': {cwd}, 'program': {program}, 'args': [{args}], 'env': {{ {env} }} }}", 141 | cwd = cur_dir.canonicalize()?.to_str().unwrap(), 142 | program = output_location, 143 | args = args, 144 | env = env 145 | ); 146 | 147 | tokio::process::Command::new(if cfg!(target_os = "windows") { 148 | "code.cmd" 149 | } else { 150 | "code" 151 | }) 152 | .args(["--open-url", &url]) 153 | .output() 154 | .await 155 | .context("Failed to launch code")?; 156 | 157 | Ok(()) 158 | } 159 | --------------------------------------------------------------------------------