From b4cb5b235562ef8919e9a1e9e563d68643fc229d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan?= Date: Fri, 17 Feb 2023 18:27:01 +0100 Subject: [PATCH] support windows --- scripts/completion.zsh | 3 -- src/commands/completions.zig | 26 +++++++++++----- src/parser.zig | 8 +++++ src/scripts/completions.ps1 | 60 ++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 10 deletions(-) delete mode 100644 scripts/completion.zsh create mode 100644 src/scripts/completions.ps1 diff --git a/scripts/completion.zsh b/scripts/completion.zsh deleted file mode 100644 index 7e8e887..0000000 --- a/scripts/completion.zsh +++ /dev/null @@ -1,3 +0,0 @@ -#compdef zvm - -complete -C "zvm completions" zvm diff --git a/src/commands/completions.zig b/src/commands/completions.zig index 95ead95..e73c320 100644 --- a/src/commands/completions.zig +++ b/src/commands/completions.zig @@ -9,18 +9,23 @@ const ansi = @import("ansi"); const config = @import("config.zig"); pub fn gen_completions_cmd(ctx: ArgParser.RunContext) !void { + const shell = ctx.getOption("shell").?; + if (std.mem.eql(u8, shell, "zsh")) { + try zvm_completions(ctx); + } else if (std.mem.eql(u8, shell, "powershell")) { + try powershell_completions(ctx); + } else { + std.debug.panic("Shell not supported: {s}", .{shell}); + } +} + +fn zvm_completions(ctx: ArgParser.RunContext) !void { const stdout = std.io.getStdOut().writer(); var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var arena = std.heap.ArenaAllocator.init(gpa.allocator()); var allocator = arena.allocator(); - defer arena.deinit(); - const shell = ctx.getOption("shell"); - if (shell) |s| { - std.log.debug("shell: {s}", .{s}); - } else { - std.log.debug("no shell", .{}); - } + defer arena.deinit(); var root = ctx.command; while (root.parent) |parent| { root = parent; @@ -296,3 +301,10 @@ fn writePositinalCompleters(allocator: std.mem.Allocator, cmd: *Command, stdout: try writePositinalCompleters(allocator, c, stdout); } } + +fn powershell_completions(ctx: ArgParser.RunContext) !void { + _ = ctx; + const stdout = std.io.getStdOut().writer(); + + _ = try stdout.write(@embedFile("../scripts/completions.ps1")); +} diff --git a/src/parser.zig b/src/parser.zig index d905f00..5b1f990 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -132,6 +132,14 @@ pub inline fn createParser(allocator: std.mem.Allocator) !ArgParser { .description = "Generate shell completions", .handler = &gen_completions_cmd, .hidden = true, + .options = &[_]Command.Option{ + .{ + .name = 's', + .long_name = "shell", + .description = "the shell to generate completions for", + .default_value = "zsh", + }, + }, }); _ = try parser.addCommand(.{ .name = "spawn", diff --git a/src/scripts/completions.ps1 b/src/scripts/completions.ps1 new file mode 100644 index 0000000..e2357e6 --- /dev/null +++ b/src/scripts/completions.ps1 @@ -0,0 +1,60 @@ +function Split-String { + # Parameter help description + param( + [Parameter(Mandatory = $true, Position = 0, HelpMessage = "The string to split")] + [string]$inputString + ) + + $splitString = @() + $inQuote = $false + $buffer = "" + + for ($i = 0; $i -lt $inputString.Length; $i++) { + $char = $inputString[$i] + if ($char -eq "'") { + $inQuote = !$inQuote + } + elseif ($char -eq " " -and !$inQuote) { + if ($buffer) { + $splitString += $buffer + $buffer = "" + } + } + else { + $buffer += $char + } + } + + if ($buffer) { + $splitString += $buffer + } + + return $splitString +} + +$scriptblock = { + param($wordToComplete, $commandAst, $cursorPosition) + + $argv = @("complete") + $argv += $commandAst.ToString().Split(" ") + $res = zvm $argv + + # so we need to use a regex to split on spaces outside of quotes + $split = Split-String $res + $split | ForEach-Object { + $completion = $_ + if ($completion.StartsWith("'") -and $completion.EndsWith("'")) { + $completion = $completion.Substring(1, $completion.Length - 2) + } + + $parts = $completion.Split(":") + $description = $completion + if ($parts.Length -gt 1) { + $completion = $parts[0] + $description = $parts[1] + } + + [System.Management.Automation.CompletionResult]::new($completion, $description, 'ParameterValue', $description) + } +} +Register-ArgumentCompleter -Native -CommandName zvm -ScriptBlock $scriptblock