Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions cmd/clip/clip.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import (
)

var ClipCmd = &cobra.Command{
Use: "clip",
Short: "Interact with the native clipboard",
Long: "Reach the browser clipboard from the terminal over the workspace IPC socket.",
Use: "clip",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Interact with the native clipboard",
Long: "Reach the browser clipboard from the terminal over the workspace IPC socket.",
}
7 changes: 4 additions & 3 deletions cmd/clip/paste.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
)

var pasteCmd = &cobra.Command{
Use: "paste",
Short: "Paste clipboard content",
Long: "Read the browser clipboard over the workspace IPC socket and write it to stdout — redirect it to a file or pipe it onward. Pairs with the pbcopy/xclip/xsel shims for terminal clipboard access.",
Use: "paste",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Paste clipboard content",
Long: "Read the browser clipboard over the workspace IPC socket and write it to stdout — redirect it to a file or pipe it onward. Pairs with the pbcopy/xclip/xsel shims for terminal clipboard access.",
RunE: func(cmd *cobra.Command, args []string) error {
return clipboard.Paste(cmd.OutOrStdout())
},
Expand Down
20 changes: 20 additions & 0 deletions cmd/commands_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/kloudkit/ws-cli/cmd"
"github.com/kloudkit/ws-cli/internals/docs"
"gopkg.in/yaml.v3"
"gotest.tools/v3/assert"
)

Expand All @@ -20,6 +21,25 @@ func TestCommandsManifestMatchesCommittedFile(t *testing.T) {
assert.Equal(t, string(got), string(want))
}

func TestEveryCommandCarriesVersion(t *testing.T) {
out, err := docs.Serialize(cmd.RootCmd())
assert.NilError(t, err)

var root docs.Command
assert.NilError(t, yaml.Unmarshal(out, &root))

var check func(docs.Command)
check = func(c docs.Command) {
for _, child := range c.Commands {
assert.Assert(t, child.Since != "" || child.Deprecated != "",
"command %q must carry a since or deprecated annotation", child.Name)
check(child)
}
}

check(root)
}

func TestSerializeIsDeterministic(t *testing.T) {
first, err := docs.Serialize(cmd.RootCmd())
assert.NilError(t, err)
Expand Down
7 changes: 4 additions & 3 deletions cmd/editor/diagnostics.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import (
)

var diagnosticsCmd = &cobra.Command{
Use: "diagnostics",
Short: "Show language diagnostics for the workspace (or a single file)",
Long: "Pull language-server diagnostics (errors, warnings) from the editor over the IPC socket, across the whole workspace or a single file with --uri. Styled table by default, --raw for the JSON.",
Use: "diagnostics",
Annotations: map[string]string{"since": "next"},
Short: "Show language diagnostics for the workspace (or a single file)",
Long: "Pull language-server diagnostics (errors, warnings) from the editor over the IPC socket, across the whole workspace or a single file with --uri. Styled table by default, --raw for the JSON.",
RunE: func(cmd *cobra.Command, args []string) error {
uri, _ := cmd.Flags().GetString("uri")

Expand Down
7 changes: 4 additions & 3 deletions cmd/editor/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ var errNoEditorOverSSH = errors.New(
)

var EditorCmd = &cobra.Command{
Use: "editor",
Short: "Inspect and drive the active editor session",
Long: "Query and control the running VS Code / code-server window over the workspace IPC socket — list open tabs, read diagnostics and the current selection, or open a file. Blocked over SSH, where there is no browser editor to reach.",
Use: "editor",
Annotations: map[string]string{"since": "next"},
Short: "Inspect and drive the active editor session",
Long: "Query and control the running VS Code / code-server window over the workspace IPC socket — list open tabs, read diagnostics and the current selection, or open a file. Blocked over SSH, where there is no browser editor to reach.",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if env.IsSSHSession() {
return errNoEditorOverSSH
Expand Down
7 changes: 4 additions & 3 deletions cmd/editor/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import (
)

var listCmd = &cobra.Command{
Use: "list",
Short: "List the currently open editor tabs",
Long: "List the editor's open tabs over the IPC socket, with each tab's path, language, and active or dirty state.",
Use: "list",
Annotations: map[string]string{"since": "next"},
Short: "List the currently open editor tabs",
Long: "List the editor's open tabs over the IPC socket, with each tab's path, language, and active or dirty state.",
RunE: func(cmd *cobra.Command, args []string) error {
body, err := editoripc.FetchEditors()
if err != nil {
Expand Down
9 changes: 5 additions & 4 deletions cmd/editor/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
)

var openCmd = &cobra.Command{
Use: "open <file>",
Short: "Open a file in the editor",
Long: "Open a file in the running editor window over the workspace IPC socket — a tab in the current window by default, a separate one with --new-window, jumping to a range with --selection. Fails fast over SSH, where there is no browser editor to open into.",
Args: cobra.ExactArgs(1),
Use: "open <file>",
Annotations: map[string]string{"since": "next"},
Short: "Open a file in the editor",
Long: "Open a file in the running editor window over the workspace IPC socket — a tab in the current window by default, a separate one with --new-window, jumping to a range with --selection. Fails fast over SSH, where there is no browser editor to open into.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
newWindow, _ := cmd.Flags().GetBool("new-window")
preview, _ := cmd.Flags().GetBool("preview")
Expand Down
7 changes: 4 additions & 3 deletions cmd/editor/selection.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import (
)

var selectionCmd = &cobra.Command{
Use: "selection",
Short: "Show the active editor's current selection",
Long: "Report the active editor's current selection — file, range, and selected text — over the IPC socket. Empty when nothing is selected.",
Use: "selection",
Annotations: map[string]string{"since": "next"},
Short: "Show the active editor's current selection",
Long: "Report the active editor's current selection — file, range, and selected text — over the IPC socket. Empty when nothing is selected.",
RunE: func(cmd *cobra.Command, args []string) error {
body, err := editoripc.FetchSelection()
if err != nil {
Expand Down
7 changes: 4 additions & 3 deletions cmd/feature/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
)

var FeatureCmd = &cobra.Command{
Use: "feature",
Short: "Install additional pre-configured features",
Long: "Install and inspect optional workspace features — Ansible playbooks that add tools on top of the base image. Ships a curated set; --root points at your own under ~/.ws/features.d.",
Use: "feature",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Install additional pre-configured features",
Long: "Install and inspect optional workspace features — Ansible playbooks that add tools on top of the base image. Ships a curated set; --root points at your own under ~/.ws/features.d.",
}

func featureDirs(cmd *cobra.Command) []string {
Expand Down
9 changes: 5 additions & 4 deletions cmd/feature/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import (
)

var infoCmd = &cobra.Command{
Use: "info <name>",
Short: "Show detailed information about a feature",
Long: "Show a feature's description and the variables it accepts, so you know what --opt values install will take.",
Args: cobra.ExactArgs(1),
Use: "info <name>",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Show detailed information about a feature",
Long: "Show a feature's description and the variables it accepts, so you know what --opt values install will take.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
featureName := args[0]

Expand Down
9 changes: 5 additions & 4 deletions cmd/feature/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ var skippableSections = []struct {
}

var installCmd = &cobra.Command{
Use: "install",
Short: "Install additional pre-configured features",
Long: "Run a feature's playbook to install it. Pass variables with --opt KEY=VAL, and skip parts you do not want with --skip-extensions, --skip-completion, or --skip-repository.",
Args: cobra.ExactArgs(1),
Use: "install",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Install additional pre-configured features",
Long: "Run a feature's playbook to install it. Pass variables with --opt KEY=VAL, and skip parts you do not want with --skip-extensions, --skip-completion, or --skip-repository.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
featureName := args[0]

Expand Down
9 changes: 5 additions & 4 deletions cmd/feature/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import (
)

var listCmd = &cobra.Command{
Use: "list",
Short: "List available features that can be installed",
Long: "List the features you can install, marking where each comes from — the shipped set, a workspace override, or your own ~/.ws/features.d.",
Aliases: []string{"ls"},
Use: "list",
Annotations: map[string]string{"since": "0.2.0"},
Short: "List available features that can be installed",
Long: "List the features you can install, marking where each comes from — the shipped set, a workspace override, or your own ~/.ws/features.d.",
Aliases: []string{"ls"},
RunE: func(cmd *cobra.Command, args []string) error {
result, err := features.ListFeatures(featureDirs(cmd))
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions cmd/feature/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ const scaffoldTemplate = `---
`

var newCmd = &cobra.Command{
Use: "new [name]",
Short: "Print boilerplate for a custom feature playbook",
Use: "new [name]",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Print boilerplate for a custom feature playbook",
Long: `Print a starter feature playbook to stdout.

Redirect it into ~/.ws/features.d/<name>.yaml, then extend it and install
Expand Down
7 changes: 4 additions & 3 deletions cmd/feature/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
)

var storeCmd = &cobra.Command{
Use: "store",
Short: "List packages available in the feature store",
Long: "List the artifacts published to the feature store (WS_FEATURES_STORE_URL) — the offline mirror features install from when the network is locked down.",
Use: "store",
Annotations: map[string]string{"since": "0.2.0"},
Short: "List packages available in the feature store",
Long: "List the artifacts published to the feature store (WS_FEATURES_STORE_URL) — the offline mirror features install from when the network is locked down.",
RunE: func(cmd *cobra.Command, args []string) error {
storeURL, _ := config.Resolve("features", "store_url")
if storeURL == "" {
Expand Down
7 changes: 4 additions & 3 deletions cmd/info/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ func showEnvironment(writer io.Writer) {
}

var envCmd = &cobra.Command{
Use: "env",
Short: "Display effective workspace environment variables",
Long: "Print every WS_* variable in effect, sorted — the resolved environment the workspace booted with.",
Use: "env",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Display effective workspace environment variables",
Long: "Print every WS_* variable in effect, sorted — the resolved environment the workspace booted with.",
RunE: func(cmd *cobra.Command, args []string) error {
showEnvironment(cmd.OutOrStdout())
return nil
Expand Down
7 changes: 4 additions & 3 deletions cmd/info/extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
)

var extensionsCmd = &cobra.Command{
Use: "extensions",
Short: "Display installed extensions",
Long: "List the installed VS Code extensions with their versions.",
Use: "extensions",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Display installed extensions",
Long: "List the installed VS Code extensions with their versions.",
RunE: func(cmd *cobra.Command, args []string) error {
extensions, _ := config.GetExtensions()

Expand Down
14 changes: 8 additions & 6 deletions cmd/info/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,17 @@ func showVersion(writer io.Writer) {
}

var InfoCmd = &cobra.Command{
Use: "info",
Short: "Display workspace information",
Long: "Report facts about the running workspace — version, effective environment, installed extensions, live resource metrics, and uptime.",
Use: "info",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Display workspace information",
Long: "Report facts about the running workspace — version, effective environment, installed extensions, live resource metrics, and uptime.",
}

var showVersionCmd = &cobra.Command{
Use: "version",
Short: "Display installed workspace version",
Long: "Print the workspace version. --all expands to the full table — workspace, ws-cli, and VS Code.",
Use: "version",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Display installed workspace version",
Long: "Print the workspace version. --all expands to the full table — workspace, ws-cli, and VS Code.",
Run: func(cmd *cobra.Command, args []string) {
if all, _ := cmd.Flags().GetBool("all"); all {
showVersion(cmd.OutOrStdout())
Expand Down
7 changes: 4 additions & 3 deletions cmd/info/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
)

var metricsCmd = &cobra.Command{
Use: "metrics",
Short: "Display workspace metrics",
Long: "Show live resource usage — CPU, memory, disk, and file descriptors, plus GPU with --gpu.",
Use: "metrics",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Display workspace metrics",
Long: "Show live resource usage — CPU, memory, disk, and file descriptors, plus GPU with --gpu.",
RunE: func(cmd *cobra.Command, args []string) error {
includeGPU, _ := cmd.Flags().GetBool("gpu")

Expand Down
7 changes: 4 additions & 3 deletions cmd/info/uptime.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import (
)

var uptimeCmd = &cobra.Command{
Use: "uptime",
Short: "Display the workspace uptime",
Long: "Show when the workspace session started and how long it has been running.",
Use: "uptime",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Display the workspace uptime",
Long: "Show when the workspace session started and how long it has been running.",
RunE: func(cmd *cobra.Command, args []string) error {
started, running, err := config.GetSessionInfo()

Expand Down
27 changes: 15 additions & 12 deletions cmd/log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,22 @@ import (
)

var LogCmd = &cobra.Command{
Use: "log",
Short: "Log messages",
Long: "Emit styled, level-tagged log lines — the same formatting the startup scripts use. --pipe runs each line of piped input through the logger.",
Use: "log",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Log messages",
Long: "Emit styled, level-tagged log lines — the same formatting the startup scripts use. --pipe runs each line of piped input through the logger.",
}

var debugCmd = createCommand("debug", "debugging")
var errorCmd = createCommand("error", "error")
var infoCmd = createCommand("info", "information")
var warnCmd = createCommand("warn", "warning")
var stampCmd = &cobra.Command{
Use: "stamp",
Short: "Log the current timestamp",
Long: "Print just the current timestamp in the workspace log style — handy for marking phases in a startup log.",
Args: cobra.NoArgs,
Use: "stamp",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Log the current timestamp",
Long: "Print just the current timestamp in the workspace log style — handy for marking phases in a startup log.",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
withPipe, _ := cmd.Flags().GetBool("pipe")

Expand All @@ -36,11 +38,12 @@ var stampCmd = &cobra.Command{

func createCommand(short, long string) *cobra.Command {
cmd := &cobra.Command{
Use: fmt.Sprintf("%s message", short),
Short: fmt.Sprintf("Log %s messages", long),
Long: fmt.Sprintf("Emit a log line at %s level in the workspace style — the same formatting the startup scripts use. --indent nests it under a preceding line, --stamp prefixes a timestamp.", short),
Args: validate,
RunE: execute(short),
Use: fmt.Sprintf("%s message", short),
Annotations: map[string]string{"since": "0.2.0"},
Short: fmt.Sprintf("Log %s messages", long),
Long: fmt.Sprintf("Emit a log line at %s level in the workspace style — the same formatting the startup scripts use. --indent nests it under a preceding line, --stamp prefixes a timestamp.", short),
Args: validate,
RunE: execute(short),
}

cmd.Flags().IntP("indent", "i", 0, "Desired prefixed indentation")
Expand Down
11 changes: 6 additions & 5 deletions cmd/logs/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ var validLogLevels = []string{"debug", "info", "warn", "error"}
var validLogTargets = []string{"main", "metrics", "docker", "auth_proxy", "cloudflared"}

var LogsCmd = &cobra.Command{
Use: "logs",
Short: "Retrieve workspace logs",
Long: "Read a workspace daemon's log — the main log by default, or --target metrics|docker|auth_proxy|cloudflared. Filter by --level, limit with --tail, or stream live with --follow.",
Args: cobra.NoArgs,
RunE: execute,
Use: "logs",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Retrieve workspace logs",
Long: "Read a workspace daemon's log — the main log by default, or --target metrics|docker|auth_proxy|cloudflared. Filter by --level, limit with --tail, or stream live with --follow.",
Args: cobra.NoArgs,
RunE: execute,
}

func execute(cmd *cobra.Command, args []string) error {
Expand Down
9 changes: 5 additions & 4 deletions cmd/secrets/decrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import (
)

var decryptCmd = &cobra.Command{
Use: "decrypt <encrypted|->",
Short: "Decrypt an encrypted value",
Long: "Decrypt a value produced by encrypt, under the master key. Reads from the argument or stdin (-); writes the plaintext to stdout, or a file with --output.",
Args: cobra.ExactArgs(1),
Use: "decrypt <encrypted|->",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Decrypt an encrypted value",
Long: "Decrypt a value produced by encrypt, under the master key. Reads from the argument or stdin (-); writes the plaintext to stdout, or a file with --output.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cfg := getOutputConfig(cmd)
masterKeyFlag, _ := cmd.Flags().GetString("master")
Expand Down
9 changes: 5 additions & 4 deletions cmd/secrets/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
)

var encryptCmd = &cobra.Command{
Use: "encrypt <plaintext|->",
Short: "Encrypt a plaintext value",
Long: "Encrypt a value under the master key. Reads the plaintext from the argument or stdin (-); writes the ciphertext to stdout, or a file with --output.",
Args: cobra.ExactArgs(1),
Use: "encrypt <plaintext|->",
Annotations: map[string]string{"since": "0.2.0"},
Short: "Encrypt a plaintext value",
Long: "Encrypt a value under the master key. Reads the plaintext from the argument or stdin (-); writes the ciphertext to stdout, or a file with --output.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cfg := getOutputConfig(cmd)
masterKeyFlag, _ := cmd.Flags().GetString("master")
Expand Down
Loading
Loading