mirror of https://github.com/cirruslabs/tart.git
Add shell completions (#780)
* add VM completion for run command * add VM completion for stop command * create ShellCompletions utilities * add shell completions to some commands * add shell completion for fqn command * run command: fix tiny typo * add shell completion for get command * more shell completions * remove unnecessary `try` * refactor ShellCompletions file
This commit is contained in:
parent
97b7ffef52
commit
da8afa1348
|
|
@ -18,7 +18,7 @@ struct Clone: AsyncParsableCommand {
|
|||
"""
|
||||
)
|
||||
|
||||
@Argument(help: "source VM name")
|
||||
@Argument(help: "source VM name", completion: .custom(completeMachines))
|
||||
var sourceName: String
|
||||
|
||||
@Argument(help: "new VM name")
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import SwiftUI
|
|||
struct Delete: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Delete a VM")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeMachines))
|
||||
var name: [String]
|
||||
|
||||
func run() async throws {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Foundation
|
|||
struct Export: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Export VM to a compressed .tvm file")
|
||||
|
||||
@Argument(help: "Source VM name.")
|
||||
@Argument(help: "Source VM name.", completion: .custom(completeMachines))
|
||||
var name: String
|
||||
|
||||
@Argument(help: "Path to the destination file.")
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import SystemConfiguration
|
|||
struct FQN: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Get a fully-qualified VM name", shouldDisplay: false)
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeMachines))
|
||||
var name: String
|
||||
|
||||
func run() async throws {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ fileprivate struct VMInfo: Encodable {
|
|||
struct Get: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(commandName: "get", abstract: "Get a VM's configuration")
|
||||
|
||||
@Argument(help: "VM name.")
|
||||
@Argument(help: "VM name.", completion: .custom(completeLocalMachines))
|
||||
var name: String
|
||||
|
||||
@Option(help: "Output format: text or json")
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ enum IPResolutionStrategy: String, ExpressibleByArgument, CaseIterable {
|
|||
struct IP: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Get VM's IP address")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeLocalMachines))
|
||||
var name: String
|
||||
|
||||
@Option(help: "Number of seconds to wait for a potential VM booting")
|
||||
|
|
@ -61,7 +61,7 @@ struct IP: AsyncParsableCommand {
|
|||
return ip
|
||||
}
|
||||
case .dhcp:
|
||||
if let leases = try Leases(), let ip = try leases.ResolveMACAddress(macAddress: vmMACAddress) {
|
||||
if let leases = try Leases(), let ip = leases.ResolveMACAddress(macAddress: vmMACAddress) {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import Compression
|
|||
struct Push: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Push a VM to a registry")
|
||||
|
||||
@Argument(help: "local or remote VM name")
|
||||
@Argument(help: "local or remote VM name", completion: .custom(completeMachines))
|
||||
var localName: String
|
||||
|
||||
@Argument(help: "remote VM name(s)")
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Foundation
|
|||
struct Rename: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Rename a VM")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeLocalMachines))
|
||||
var name: String
|
||||
|
||||
@Argument(help: "new VM name")
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ struct IPNotFound: Error {
|
|||
struct Run: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(abstract: "Run a VM")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeLocalMachines))
|
||||
var name: String
|
||||
|
||||
@Flag(help: ArgumentHelp(
|
||||
|
|
@ -54,7 +54,7 @@ struct Run: AsyncParsableCommand {
|
|||
|
||||
#if arch(arm64)
|
||||
@Flag(help: ArgumentHelp(
|
||||
"Use Virtualization.Framework's VNC server instead of the build-in UI.",
|
||||
"Use Virtualization.Framework's VNC server instead of the built-in UI.",
|
||||
discussion: "Useful since this type of VNC is available in recovery mode and in macOS installation.\n"
|
||||
+ "Note that this feature is experimental and there may be bugs present when using VNC."))
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Foundation
|
|||
struct Set: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(commandName: "set", abstract: "Modify VM's configuration")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeLocalMachines))
|
||||
var name: String
|
||||
|
||||
@Option(help: "Number of VM CPUs")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import SwiftDate
|
|||
struct Stop: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(commandName: "stop", abstract: "Stop a VM")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeRunningMachines))
|
||||
var name: String
|
||||
|
||||
@Option(name: [.short, .long], help: "Seconds to wait for graceful termination before forcefully terminating the VM")
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import SwiftDate
|
|||
struct Suspend: AsyncParsableCommand {
|
||||
static var configuration = CommandConfiguration(commandName: "suspend", abstract: "Suspend a VM")
|
||||
|
||||
@Argument(help: "VM name")
|
||||
@Argument(help: "VM name", completion: .custom(completeRunningMachines))
|
||||
var name: String
|
||||
|
||||
func run() async throws {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import Foundation
|
||||
|
||||
fileprivate func normalizeName(_ name: String) -> String {
|
||||
// Colons are misinterpreted by Zsh completion
|
||||
return name.replacingOccurrences(of: ":", with: "\\:")
|
||||
}
|
||||
|
||||
func completeMachines(_ arguments: [String]) -> [String] {
|
||||
let localVMs = (try? VMStorageLocal().list().map { name, _ in
|
||||
normalizeName(name)
|
||||
}) ?? []
|
||||
let ociVMs = (try? VMStorageOCI().list().map { name, _, _ in
|
||||
normalizeName(name)
|
||||
}) ?? []
|
||||
return (localVMs + ociVMs)
|
||||
}
|
||||
|
||||
func completeLocalMachines(_ arguments: [String]) -> [String] {
|
||||
let localVMs = (try? VMStorageLocal().list()) ?? []
|
||||
return localVMs.map { name, _ in normalizeName(name) }
|
||||
}
|
||||
|
||||
func completeRunningMachines(_ arguments: [String]) -> [String] {
|
||||
let localVMs = (try? VMStorageLocal().list()) ?? []
|
||||
return localVMs
|
||||
.filter { _, vmDir in (try? vmDir.state() == .Running) ?? false}
|
||||
.map { name, _ in normalizeName(name) }
|
||||
}
|
||||
Loading…
Reference in New Issue