1- use std:: fs;
2- use zed:: { CodeLabel , CodeLabelSpan , LanguageServerId , Result , lsp:: CompletionKind } ;
3- use zed_extension_api:: { self as zed} ;
1+ use std:: path:: PathBuf ;
2+ use std:: str:: FromStr ;
3+ use std:: { env, fs} ;
4+ use zed:: lsp:: CompletionKind ;
5+ use zed:: { CodeLabel , CodeLabelSpan , LanguageServerId } ;
6+ use zed_extension_api:: { self as zed, Result , serde_json:: Value } ;
47
58struct EmmyLuaExtension {
69 cached_binary_path : Option < String > ,
10+ cached_dap_binary_path : Option < String > ,
711}
812
913impl EmmyLuaExtension {
@@ -15,11 +19,14 @@ impl EmmyLuaExtension {
1519 if let Ok ( lsp_settings) = zed:: settings:: LspSettings :: for_worktree ( "emmylua" , worktree) {
1620 if let Some ( binary) = lsp_settings. binary {
1721 if let Some ( path) = binary. path {
18- return Ok ( path) ;
22+ if !fs:: metadata ( & path) . map_or ( false , |stat| stat. is_file ( ) ) {
23+ return Ok ( path) ;
24+ }
1925 }
2026 }
2127 }
2228
29+ // First check if emmylua is in PATH
2330 if let Some ( path) = worktree. which ( "emmylua_ls" ) {
2431 return Ok ( path) ;
2532 }
@@ -109,8 +116,12 @@ impl EmmyLuaExtension {
109116 fs:: read_dir ( "." ) . map_err ( |e| format ! ( "failed to list working directory {e}" ) ) ?;
110117 for entry in entries {
111118 let entry = entry. map_err ( |e| format ! ( "failed to load directory entry {e}" ) ) ?;
112- if entry. file_name ( ) . to_str ( ) != Some ( & version_dir) {
113- fs:: remove_dir_all ( entry. path ( ) ) . ok ( ) ;
119+ if let Some ( file_name) = entry. file_name ( ) . to_str ( ) {
120+ if file_name. starts_with ( "emmylua-" ) {
121+ if entry. file_name ( ) . to_str ( ) != Some ( & version_dir) {
122+ fs:: remove_dir_all ( entry. path ( ) ) . ok ( ) ;
123+ }
124+ }
114125 }
115126 }
116127 }
@@ -124,6 +135,7 @@ impl zed::Extension for EmmyLuaExtension {
124135 fn new ( ) -> Self {
125136 Self {
126137 cached_binary_path : None ,
138+ cached_dap_binary_path : None ,
127139 }
128140 }
129141
@@ -267,6 +279,187 @@ impl zed::Extension for EmmyLuaExtension {
267279
268280 Ok ( Some ( settings) )
269281 }
282+
283+ // DAP Support for EmmyLua debugger
284+ fn get_dap_binary (
285+ & mut self ,
286+ adapter_name : String ,
287+ config : zed:: DebugTaskDefinition ,
288+ user_provided_debug_adapter_path : Option < String > ,
289+ worktree : & zed:: Worktree ,
290+ ) -> std:: result:: Result < zed:: DebugAdapterBinary , String > {
291+ if adapter_name != "emmylua_new" {
292+ return Err ( format ! ( "Unknown debug adapter: {}" , adapter_name) ) ;
293+ }
294+
295+ let default_request_args = zed:: StartDebuggingRequestArguments {
296+ configuration : config. config . clone ( ) ,
297+ request : self . dap_request_kind (
298+ adapter_name,
299+ Value :: from_str ( config. config . as_str ( ) )
300+ . map_err ( |e| format ! ( "Invalid JSON configuration: {e}" ) ) ?,
301+ ) ?,
302+ } ;
303+
304+ let cwd = Some ( worktree. root_path ( ) ) ;
305+
306+ // Check if user provided a custom path
307+ if let Some ( path) = user_provided_debug_adapter_path {
308+ if !fs:: metadata ( & path) . map_or ( false , |stat| stat. is_file ( ) ) {
309+ self . cached_dap_binary_path = Some ( path. clone ( ) ) ;
310+ return Ok ( zed:: DebugAdapterBinary {
311+ command : Some ( path) ,
312+ arguments : vec ! [ ] ,
313+ envs : vec ! [ ] ,
314+ cwd,
315+ connection : None ,
316+ request_args : default_request_args,
317+ } ) ;
318+ }
319+ }
320+
321+ // Try to find emmylua_dap in PATH
322+ if let Some ( path) = worktree. which ( "emmylua_dap" ) {
323+ return Ok ( zed:: DebugAdapterBinary {
324+ command : Some ( path) ,
325+ arguments : vec ! [ ] ,
326+ envs : vec ! [ ] ,
327+ cwd,
328+ connection : None ,
329+ request_args : default_request_args,
330+ } ) ;
331+ }
332+
333+ // Check cached path
334+ if let Some ( path) = & self . cached_dap_binary_path {
335+ if fs:: metadata ( path) . map_or ( false , |stat| stat. is_file ( ) ) {
336+ return Ok ( zed:: DebugAdapterBinary {
337+ command : Some ( path. clone ( ) ) ,
338+ arguments : vec ! [ ] ,
339+ envs : vec ! [ ] ,
340+ cwd,
341+ connection : None ,
342+ request_args : default_request_args,
343+ } ) ;
344+ }
345+ }
346+
347+ // Try to download from GitHub releases
348+ let release = zed:: latest_github_release (
349+ "EmmyLuaLs/emmylua_dap" ,
350+ zed:: GithubReleaseOptions {
351+ require_assets : true ,
352+ pre_release : false ,
353+ } ,
354+ )
355+ . map_err ( |e| format ! ( "Failed to get latest release: {}" , e) ) ?;
356+
357+ let ( platform, arch) = zed:: current_platform ( ) ;
358+ let asset_name = format ! (
359+ "emmylua_dap-{os}-{arch}{glibc}.{extension}" ,
360+ os = match platform {
361+ zed:: Os :: Mac => "darwin" ,
362+ zed:: Os :: Linux => "linux" ,
363+ zed:: Os :: Windows => "win32" ,
364+ } ,
365+ arch = match arch {
366+ zed:: Architecture :: Aarch64 => match platform {
367+ zed:: Os :: Linux => "aarch64" ,
368+ zed:: Os :: Windows | zed:: Os :: Mac => "arm64" ,
369+ } ,
370+ zed:: Architecture :: X8664 => "x64" ,
371+ zed:: Architecture :: X86 => return Err ( "unsupported platform x86" . into( ) ) ,
372+ } ,
373+ glibc = match platform {
374+ zed:: Os :: Linux => "-glibc.2.17" ,
375+ zed:: Os :: Windows | zed:: Os :: Mac => "" ,
376+ } ,
377+ extension = match platform {
378+ zed:: Os :: Mac | zed:: Os :: Linux => "tar.gz" ,
379+ zed:: Os :: Windows => "zip" ,
380+ } ,
381+ ) ;
382+
383+ let asset = release
384+ . assets
385+ . iter ( )
386+ . find ( |asset| asset. name . contains ( & asset_name) )
387+ . ok_or_else ( || format ! ( "No asset found matching pattern: {}" , asset_name) ) ?;
388+
389+ let version_dir = format ! ( "emmylua_dap-{}" , release. version) ;
390+ let binary_name = format ! (
391+ "emmylua_dap{}" ,
392+ match platform {
393+ zed:: Os :: Mac | zed:: Os :: Linux => "" ,
394+ zed:: Os :: Windows => ".exe" ,
395+ }
396+ ) ;
397+ let binary_path = format ! ( "{}/{}" , version_dir, binary_name) ;
398+
399+ if !fs:: metadata ( & binary_path) . map_or ( false , |stat| stat. is_file ( ) ) {
400+ zed:: download_file (
401+ & asset. download_url ,
402+ & version_dir,
403+ match platform {
404+ zed:: Os :: Mac | zed:: Os :: Linux => zed:: DownloadedFileType :: GzipTar ,
405+ zed:: Os :: Windows => zed:: DownloadedFileType :: Zip ,
406+ } ,
407+ )
408+ . map_err ( |e| format ! ( "Failed to download DAP binary: {}" , e) ) ?;
409+
410+ let entries =
411+ fs:: read_dir ( "." ) . map_err ( |e| format ! ( "failed to list working directory {e}" ) ) ?;
412+ for entry in entries {
413+ let entry = entry. map_err ( |e| format ! ( "failed to load directory entry {e}" ) ) ?;
414+ if let Some ( file_name) = entry. file_name ( ) . to_str ( ) {
415+ if file_name. starts_with ( "emmylua_dap-" ) {
416+ if entry. file_name ( ) . to_str ( ) != Some ( & version_dir) {
417+ fs:: remove_dir_all ( entry. path ( ) ) . ok ( ) ;
418+ }
419+ }
420+ }
421+ }
422+ }
423+
424+ let path = match env:: current_dir ( ) {
425+ Ok ( current_dir) => current_dir. join ( binary_path) . to_string_lossy ( ) . to_string ( ) ,
426+ Err ( e) => {
427+ eprintln ! ( "Error: {}" , e) ;
428+ PathBuf :: from ( binary_path) . to_string_lossy ( ) . to_string ( )
429+ }
430+ } ;
431+
432+ self . cached_dap_binary_path = Some ( path. clone ( ) ) ;
433+ Ok ( zed:: DebugAdapterBinary {
434+ command : Some ( path) ,
435+ arguments : vec ! [ ] ,
436+ envs : vec ! [ ] ,
437+ cwd,
438+ connection : None ,
439+ request_args : default_request_args,
440+ } )
441+ }
442+
443+ fn dap_request_kind (
444+ & mut self ,
445+ adapter_name : String ,
446+ config : Value ,
447+ ) -> std:: result:: Result < zed:: StartDebuggingRequestArgumentsRequest , String > {
448+ if adapter_name != "emmylua_new" {
449+ return Err ( format ! ( "Unknown debug adapter: {}" , adapter_name) ) ;
450+ }
451+
452+ let request_type = config
453+ . get ( "request" )
454+ . and_then ( |v| v. as_str ( ) )
455+ . unwrap_or ( "launch" ) ;
456+
457+ match request_type {
458+ "launch" => Ok ( zed:: StartDebuggingRequestArgumentsRequest :: Launch ) ,
459+ "attach" => Ok ( zed:: StartDebuggingRequestArgumentsRequest :: Attach ) ,
460+ _ => Err ( format ! ( "Unknown request type: {}" , request_type) ) ,
461+ }
462+ }
270463}
271464
272465zed:: register_extension!( EmmyLuaExtension ) ;
0 commit comments