mosheavni/yaml-companion.nvim

github github
programming-languages-supportyaml
stars 13
issues 0
subscribers 0
forks 0
CREATED

UPDATED


yaml-companion.nvim

Build Lint Neovim

statusbar

⚡️ Requirements

✨ Features

  • Builtin Kubernetes manifest autodetection
  • Get/Set specific JSON schema per buffer
  • Extendable autodetection + Schema Store support
  • CRD modeline support with Datree CRD catalog integration
  • Auto-detect Custom Resource Definitions and add schema modelines
  • Key navigation: Browse all YAML keys in quickfix, get key/value at cursor

📦 Installation

Install the plugin with your preferred package manager:

lazy.nvim

{
  "mosheavni/yaml-companion.nvim",
}

⚙️ Configuration

yaml-companion comes with the following defaults:

{
  -- Built in file matchers
  builtin_matchers = {
    -- Detects Kubernetes files based on content
    kubernetes = { enabled = true },
    cloud_init = { enabled = true }
  },

  -- Additional schemas available in the picker
  schemas = {
    --{
      --name = "Kubernetes 1.32.1",
      --uri = "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.32.1-standalone-strict/all.json",
    --},
  },

  -- Pass any additional options that will be merged in the final LSP config
  lspconfig = {
    flags = {
      debounce_text_changes = 150,
    },
    settings = {
      redhat = { telemetry = { enabled = false } },
      yaml = {
        validate = true,
        format = { enable = true },
        hover = true,
        schemaStore = {
          enable = true,
          url = "https://www.schemastore.org/api/json/catalog.json",
        },
        schemaDownload = { enable = true },
        schemas = {},
        trace = { server = "debug" },
      },
    },
  },
}

Setup (Neovim 0.11+ required)

local cfg = require("yaml-companion").setup({
  -- Add any options here, or leave empty to use the default settings
  -- lspconfig = {
  --   settings = { ... }
  -- },
})
vim.lsp.config("yamlls", cfg)
vim.lsp.enable("yamlls")

🚀 Usage

Select a schema for the current buffer

No mappings included, you need to map it yourself or call it manually:

require("yaml-companion").open_ui_select()

This uses vim.ui.select so you can use the picker of your choice (e.g., with dressing.nvim).

Get the schema name for the current buffer

You can show the current schema in your statusline using a function like:

local function get_schema()
  local schema = require("yaml-companion").get_buf_schema(0)
  if schema.result[1].name == "none" then
    return ""
  end
  return schema.result[1].name
end

Key Navigation

Navigate YAML keys using treesitter. Requires the YAML treesitter parser (:TSInstall yaml).

Quickfix List

Get all YAML keys in a quickfix list for easy navigation:

-- Open quickfix with all keys
require("yaml-companion").get_keys_quickfix()

-- Or use the command
:YamlKeys

Each entry shows the full dotted key path:

  • .metadata.name
  • .spec.containers[0].image
  • .spec.replicas

Get Key at Cursor (API)

Get the YAML key and value at the current cursor position:

local info = require("yaml-companion").get_key_at_cursor()
if info then
  print(info.key)    -- ".spec.containers[0].name"
  print(info.value)  -- "my-container"
  print(info.human)  -- ".spec.containers[0].name = my-container"
  print(info.line)   -- 15
  print(info.col)    -- 5
end

This API is useful for building custom integrations. For example, to copy the current key path to clipboard:

vim.keymap.set("n", "<leader>yk", function()
  local info = require("yaml-companion").get_key_at_cursor()
  if info then
    vim.fn.setreg("+", info.key)
    vim.notify("Copied: " .. info.key)
  end
end, { desc = "Copy YAML key path" })

-- Or to copy the value:
vim.keymap.set("n", "<leader>yv", function()
  local info = require("yaml-companion").get_key_at_cursor()
  if info and info.value then
    vim.fn.setreg("+", info.value)
    vim.notify("Copied: " .. info.value)
  end
end, { desc = "Copy YAML value" })

Key Navigation Configuration

require("yaml-companion").setup({
  keys = {
    enabled = true,          -- Enable key navigation features (creates :YamlKeys command)
    include_values = false,  -- Show values in quickfix entries (default: false)
    max_value_length = 50,   -- Truncate long values in display (when include_values = true)
  },
})

Note: Treesitter with YAML parser is required. Check with :checkhealth yaml-companion.

Modeline Features

yaml-companion provides tools for working with YAML modelines (# yaml-language-server: $schema=...) to provide schema support for Custom Resource Definitions (CRDs).

Datree CRD Schema Picker

Browse the datreeio/CRDs-catalog and add a modeline to the current buffer:

require("yaml-companion").open_datree_crd_select()

This fetches the catalog from GitHub (cached for 1 hour) and presents a picker to select a CRD schema. When selected, a modeline is added at the top of your file:

# yaml-language-server: $schema=https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/argoproj.io/application_v1alpha1.json
apiVersion: argoproj.io/v1alpha1
kind: Application

Auto-detect CRDs

Detect Custom Resource Definitions in the current buffer and add schema modelines automatically:

-- Add modelines for all detected CRDs
require("yaml-companion").add_crd_modelines()

-- Preview what would be added (dry run)
require("yaml-companion").add_crd_modelines(0, { dry_run = true })

-- Overwrite existing modelines
require("yaml-companion").add_crd_modelines(0, { overwrite = true })

This parses the buffer for kind: and apiVersion: fields, identifies non-core Kubernetes resources, and adds modelines pointing to the appropriate schema in the Datree CRD catalog.

Core Kubernetes resources (Deployments, Services, ConfigMaps, etc.) are skipped since they're handled by the builtin kubernetes matcher.

Modeline Configuration

require("yaml-companion").setup({
  -- Modeline features
  modeline = {
    auto_add = {
      on_attach = false, -- Auto-add modelines when yamlls attaches
      on_save = false, -- Auto-add modelines before saving
    },
    overwrite_existing = false, -- Whether to overwrite existing modelines
    validate_urls = false, -- Check if schema URL exists (slower)
    notify = true, -- Show notifications when modelines are added
  },

  -- Datree CRD catalog settings
  datree = {
    cache_ttl = 3600, -- Cache catalog for 1 hour (0 = no cache)
    raw_content_base = "https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/",
  },

  -- Customize which API groups are considered "core" (skipped by CRD detection)
  -- These are handled by the builtin kubernetes matcher
  core_api_groups = {
    [""] = true,
    ["apps"] = true,
    ["batch"] = true,
    ["networking.k8s.io"] = true,
    -- ... add or remove as needed
  },
})