Skip to main content

Editor Setup

EmmyLua Analyzer implements the Language Server Protocol (LSP), making it compatible with any editor that supports LSP. This guide covers setup for the most popular editors.
Before proceeding, make sure you have installed the emmylua_ls language server.

Visual Studio Code

VS Code has the best out-of-box experience with EmmyLua Analyzer.
1

Install the Extension

Install the EmmyLua extension from the VS Code Marketplace:Option 1: Using the GUI
  1. Open VS Code
  2. Click the Extensions icon (or press Ctrl+Shift+X)
  3. Search for “EmmyLua”
  4. Click Install on “EmmyLua” by tangzx
Option 2: Using Quick Open
  1. Press Ctrl+P (or Cmd+P on macOS)
  2. Type: ext install tangzx.emmylua
  3. Press Enter
2

Configure the Extension

The extension will automatically detect emmylua_ls in your PATH. If needed, you can specify a custom path:
  1. Open VS Code Settings (Ctrl+, or Cmd+,)
  2. Search for “EmmyLua”
  3. Set “EmmyLua: Language Server” to the path of your emmylua_ls binary
Example settings in settings.json:
{
  "emmylua.languageServer": "/usr/local/bin/emmylua_ls",
  "emmylua.completion.autoRequire": true,
  "emmylua.hint.enable": true,
  "emmylua.hint.paramHint": true
}
3

Create Project Configuration

Create a .emmyrc.json file in your project root:
{
  "$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
  "runtime": {
    "version": "Lua5.4"
  },
  "diagnostics": {
    "enable": true
  },
  "workspace": {
    "library": [],
    "ignoreDir": ["build", "dist"]
  }
}
The $schema field enables auto-completion for the config file!
4

Restart and Test

  1. Reload VS Code window (Ctrl+Shift+P → “Reload Window”)
  2. Open a .lua file
  3. Check the status bar for “EmmyLua” indicator
  4. Try typing code and see completions appear

VS Code Keybindings

Navigation

  • F12 - Go to Definition
  • Shift+F12 - Find All References
  • Ctrl+Shift+O - Go to Symbol
  • Ctrl+T - Go to Symbol in Workspace

Editing

  • F2 - Rename Symbol
  • Ctrl+Space - Trigger Completion
  • Ctrl+Shift+Space - Signature Help
  • Ctrl+. - Quick Fix

Troubleshooting VS Code

Check the Output panel:
  1. View → Output
  2. Select “EmmyLua” from dropdown
  3. Look for error messages
Common issues:
  • emmylua_ls not in PATH
  • Multiple Lua extensions conflicting
  • Workspace not trusted
For large projects, adjust these settings:
{
  "emmylua.workspace.preloadFileSize": 0,
  "emmylua.workspace.ignoreDir": ["node_modules", ".git", "build"]
}

Neovim

Neovim has excellent LSP support built-in (0.5+) or via plugins.

Neovim 0.10+ (Built-in LSP)

For Neovim 0.10 and later, setup is simple:
1

Add to Your Config

Add to your init.lua:
-- Enable EmmyLua language server
vim.lsp.enable("emmylua_ls")
That’s it! Neovim will automatically start emmylua_ls for Lua files.
2

Optional: Configure LSP Keybindings

Add useful keybindings:
-- LSP keybindings
vim.api.nvim_create_autocmd('LspAttach', {
  callback = function(args)
    local opts = { buffer = args.buf }
    vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
    vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
    vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
    vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts)
    vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
    vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, opts)
    vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, opts)
    vim.keymap.set('n', '<leader>ca', vim.lsp.buf.code_action, opts)
    vim.keymap.set('n', '<leader>f', vim.lsp.buf.format, opts)
  end,
})

Neovim with nvim-lspconfig

For Neovim 0.5-0.9 or if you prefer explicit configuration:
1

Install nvim-lspconfig

Using your plugin manager:
{
  'neovim/nvim-lspconfig',
  config = function()
    require('lspconfig').emmylua_ls.setup{}
  end
}
2

Advanced Configuration

Customize the LSP server:
require('lspconfig').emmylua_ls.setup{
  cmd = {'emmylua_ls'},  -- Or full path
  filetypes = {'lua'},
  root_dir = require('lspconfig.util').root_pattern('.emmyrc.json', '.luarc.json', '.git'),
  settings = {
    emmylua = {
      completion = {
        enable = true,
        autoRequire = true,
        callSnippet = true,
      },
      diagnostics = {
        enable = true,
        globals = {'vim'},  -- For Neovim config
      },
      hint = {
        enable = true,
        paramHint = true,
      },
    },
  },
  on_attach = function(client, bufnr)
    -- Keybindings and other setup
    local opts = { buffer = bufnr }
    vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
    vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
    vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, opts)
  end,
}
Enhance your Lua development with these plugins:
-- nvim-cmp for completion
use 'hrsh7th/nvim-cmp'
use 'hrsh7th/cmp-nvim-lsp'
use 'hrsh7th/cmp-buffer'
use 'hrsh7th/cmp-path'
use 'L3MON4D3/LuaSnip'

require('cmp').setup({
  sources = {
    { name = 'nvim_lsp' },
    { name = 'buffer' },
    { name = 'path' },
  },
})

Neovim Configuration for Plugin Development

If you’re developing Neovim plugins:
require('lspconfig').emmylua_ls.setup{
  settings = {
    emmylua = {
      runtime = {
        version = 'LuaJIT',  -- Neovim uses LuaJIT
      },
      diagnostics = {
        globals = {'vim'},  -- Recognize 'vim' global
      },
      workspace = {
        library = vim.api.nvim_get_runtime_file("", true),  -- Include Neovim runtime
        checkThirdParty = false,
      },
    },
  },
}

IntelliJ IDEA / WebStorm

JetBrains IDEs have plugin support for EmmyLua.
1

Install the Plugin

  1. Open IntelliJ IDEA / WebStorm
  2. Go to File → Settings → Plugins (or Preferences → Plugins on macOS)
  3. Click “Marketplace” tab
  4. Search for “EmmyLua2”
  5. Click Install
  6. Restart the IDE
2

Configure the Plugin

After restart:
  1. Go to File → Settings → Languages & Frameworks → Lua
  2. Set “Language Server” to the path of your emmylua_ls binary
  3. Set “Lua Version” to match your project
3

Create Configuration File

Create .emmyrc.json in your project root:
{
  "runtime": {
    "version": "Lua5.4"
  },
  "workspace": {
    "library": []
  }
}

Emacs

Emacs users can use LSP via lsp-mode or eglot.

Using lsp-mode

1

Install lsp-mode

Add to your config:
(use-package lsp-mode
  :hook (lua-mode . lsp)
  :commands lsp)
2

Register EmmyLua

Add EmmyLua language server:
(with-eval-after-load 'lsp-mode
  (add-to-list 'lsp-language-id-configuration '(lua-mode . "lua"))
  (lsp-register-client
   (make-lsp-client
    :new-connection (lsp-stdio-connection "emmylua_ls")
    :activation-fn (lsp-activate-on "lua")
    :server-id 'emmylua-ls)))
3

Optional: Install UI packages

(use-package lsp-ui :commands lsp-ui-mode)
(use-package company-lsp :commands company-lsp)

Using eglot

1

Install eglot

(use-package eglot
  :hook (lua-mode . eglot-ensure))
2

Register EmmyLua

(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
               '(lua-mode . ("emmylua_ls"))))

Sublime Text

Sublime Text 4 has LSP support via the LSP package.
1

Install Package Control

If you haven’t already, install Package Control.
2

Install LSP Package

  1. Press Ctrl+Shift+P (or Cmd+Shift+P)
  2. Type “Install Package”
  3. Search for “LSP”
  4. Install “LSP” package
3

Configure EmmyLua

Go to Preferences → Package Settings → LSP → Settings and add:
{
  "clients": {
    "emmylua": {
      "enabled": true,
      "command": ["emmylua_ls"],
      "selector": "source.lua"
    }
  }
}

Helix

Helix has built-in LSP support.
1

Add to languages.toml

Create or edit ~/.config/helix/languages.toml:
[[language]]
name = "lua"
language-servers = ["emmylua_ls"]

[language-server.emmylua_ls]
command = "emmylua_ls"
2

Restart Helix

Restart Helix and open a Lua file. The language server should start automatically.

Vim (with vim-lsp)

For classic Vim with LSP support:
1

Install vim-lsp

Using vim-plug:
Plug 'prabirshrestha/vim-lsp'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'
2

Configure EmmyLua

Add to your .vimrc:
if executable('emmylua_ls')
  au User lsp_setup call lsp#register_server({
    \ 'name': 'emmylua_ls',
    \ 'cmd': {server_info->['emmylua_ls']},
    \ 'allowlist': ['lua'],
    \ })
endif

function! s:on_lsp_buffer_enabled() abort
  setlocal omnifunc=lsp#complete
  nmap <buffer> gd <plug>(lsp-definition)
  nmap <buffer> gr <plug>(lsp-references)
  nmap <buffer> K <plug>(lsp-hover)
  nmap <buffer> <leader>rn <plug>(lsp-rename)
endfunction

augroup lsp_install
  au!
  autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END

Project Configuration

Regardless of your editor, create a .emmyrc.json file in your project root for project-specific settings:
{
  "$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
  "runtime": {
    "version": "Lua5.4",
    "requireLikeFunction": ["require", "import"],
    "extensions": [".lua", ".lua.txt"]
  },
  "diagnostics": {
    "enable": true,
    "globals": ["love", "vim"],
    "severity": {
      "unused": "hint",
      "undefined-global": "warning"
    }
  },
  "workspace": {
    "library": ["lib", "third_party"],
    "ignoreDir": ["build", "dist", ".git", "node_modules"]
  },
  "completion": {
    "enable": true,
    "autoRequire": true,
    "callSnippet": true
  },
  "hint": {
    "enable": true,
    "paramHint": true,
    "localHint": false
  }
}
See the Configuration Guide for all available options.

Common Workflows

Framework-Specific Setup

{
  "runtime": {
    "version": "LuaJIT",
    "frameworkVersions": ["love2d"]
  },
  "diagnostics": {
    "globals": ["love"]
  },
  "workspace": {
    "library": ["~/.local/share/love"]
  }
}

Language Server Options

You can pass command-line options to emmylua_ls:
emmylua_ls [OPTIONS]

Options:
  -c, --communication <MODE>   Communication mode: stdio (default) or tcp
      --port <PORT>            TCP port when using tcp mode [default: 5007]
      --log-level <LEVEL>      Logging level: debug, info, warn, error
      --log-path <PATH>        Directory for log files
  -h, --help                   Print help information
  -V, --version                Print version information

TCP Mode (for debugging)

Start the language server in TCP mode:
emmylua_ls -c tcp --port 5007 --log-level debug --log-path ./logs
Then configure your editor to connect to localhost:5007.

Troubleshooting

Ensure emmylua_ls is in your PATH:
which emmylua_ls  # macOS/Linux
where emmylua_ls  # Windows
If not found, add to PATH:
export PATH="$HOME/.cargo/bin:$PATH"
Check if the language server is running:
  • Look for LSP status in your editor’s status bar
  • Check editor logs for errors
  • Try restarting the language server
Enable debug logging:
emmylua_ls --log-level debug --log-path ./logs
Optimize your configuration:
{
  "workspace": {
    "ignoreDir": ["node_modules", ".git", "build"],
    "ignoreGlobs": ["**/*.min.lua"],
    "preloadFileSize": 0
  }
}
Disable other Lua language servers:
  • VS Code: Disable “Lua” extension if you have it
  • Neovim: Ensure only one LSP client is attached
  • Check editor logs for conflicts

Next Steps

Configuration Guide

Learn about all configuration options

Annotation Reference

Master EmmyLua annotations

CLI Tools

Use static analysis and doc generation

Examples

See real-world examples

Build docs developers (and LLMs) love