open Parser (* Map a param name/type hint to a nushell type *) let nushell_type_of_param = function | "FILE" | "file" | "PATH" | "path" | "DIR" | "dir" | "DIRECTORY" | "FILENAME" | "PATTERNFILE" -> "path" | "NUM" | "N" | "COUNT" | "NUMBER" | "int" | "INT" | "COLS" | "WIDTH" | "LINES" | "DEPTH" | "depth" -> "int" | _ -> "string" (* Escape a nushell string: wrap in double quotes, escape inner quotes *) let escape_nu s = let buf = Buffer.create (String.length s + 2) in String.iter (fun c -> match c with | '"' -> Buffer.add_string buf "\\\"" | '\\' -> Buffer.add_string buf "\\\\" | _ -> Buffer.add_char buf c ) s; Buffer.contents buf (* Format a single flag for nushell extern *) let format_flag entry = let buf = Buffer.create 64 in Buffer.add_string buf " "; (* Flag name *) (match entry.switch with | Both (s, l) -> Buffer.add_string buf (Printf.sprintf "--%s(-%c)" l s) | Long l -> Buffer.add_string buf (Printf.sprintf "--%s" l) | Short s -> Buffer.add_string buf (Printf.sprintf "-%c" s)); (* Type annotation *) (match entry.param with | Some (Mandatory name) -> Buffer.add_string buf ": "; Buffer.add_string buf (nushell_type_of_param name) | Some (Optional name) -> Buffer.add_string buf ": "; Buffer.add_string buf (nushell_type_of_param name) | None -> ()); (* Description as comment *) if String.length entry.desc > 0 then begin (* Pad to align comments *) let current_len = Buffer.length buf in let target = max (current_len + 1) 40 in for _ = current_len to target - 1 do Buffer.add_char buf ' ' done; Buffer.add_string buf "# "; Buffer.add_string buf entry.desc end; Buffer.contents buf (* Generate nushell extern definition for a command *) let generate_extern cmd_name result = let buf = Buffer.create 1024 in (* Main extern with flags *) Buffer.add_string buf (Printf.sprintf "export extern \"%s\" [\n" (escape_nu cmd_name)); List.iter (fun entry -> Buffer.add_string buf (format_flag entry); Buffer.add_char buf '\n' ) result.entries; Buffer.add_string buf "]\n"; (* Subcommand externs *) List.iter (fun (sc : subcommand) -> Buffer.add_string buf (Printf.sprintf "\nexport extern \"%s %s\" [ # %s\n]\n" (escape_nu cmd_name) (escape_nu sc.name) (escape_nu sc.desc)) ) result.subcommands; Buffer.contents buf (* Generate a complete nushell module *) let generate_module cmd_name result = Printf.sprintf "module %s-completions {\n%s}\n" cmd_name (generate_extern cmd_name result) (* Generate from manpage entries (no subcommands) *) let generate_extern_from_entries cmd_name entries = let result = { entries; subcommands = [] } in generate_extern cmd_name result