Skip to main content

Overview

EmmyLua Analyzer implements the Language Server Protocol (LSP), making it compatible with any editor that supports LSP. This guide covers setup for popular editors beyond VS Code, Neovim, and IntelliJ.
Prerequisites:
  • EmmyLua Analyzer installed: cargo install emmylua_ls
  • An LSP client plugin for your editor
  • Basic familiarity with your editor’s configuration

Universal LSP Configuration

All LSP clients need these basic settings:
LSP Client Configuration
{
  "command": "emmylua_ls",
  "args": [],
  "filetypes": ["lua"],
  "rootPatterns": [".emmyrc.json", ".luarc.json", ".git"],
  "settings": {
    "Lua": {
      "runtime": {
        "version": "LuaLatest"
      },
      "diagnostics": {
        "enable": true
      },
      "completion": {
        "enable": true
      }
    }
  }
}

Sublime Text

Setup with LSP Package

1

Install Package Control

If not already installed:
  1. Open Sublime Text
  2. Press Ctrl+Shift+P (Cmd+Shift+P on macOS)
  3. Type “Install Package Control” and press Enter
  4. Wait for installation to complete
2

Install LSP Package

  1. Press Ctrl+Shift+P
  2. Type “Package Control: Install Package”
  3. Search for “LSP”
  4. Install the LSP package
3

Configure EmmyLua LSP

Create LSP client configuration:
  1. Go to Preferences → Package Settings → LSP → Settings
  2. Add to user settings:
LSP.sublime-settings
{
  "clients": {
    "emmylua": {
      "enabled": true,
      "command": ["emmylua_ls"],
      "selector": "source.lua",
      "settings": {
        "Lua": {
          "runtime": {
            "version": "LuaLatest",
            "path": ["?.lua", "?/init.lua"]
          },
          "diagnostics": {
            "enable": true,
            "globals": []
          },
          "completion": {
            "enable": true,
            "callSnippet": "Replace"
          },
          "workspace": {
            "library": [],
            "ignoreDir": [".git", "node_modules"]
          }
        }
      }
    }
  }
}
4

Enable for Lua Files

  1. Open a Lua file
  2. LSP should start automatically
  3. Check status in the status bar (bottom-right)

Keyboard Shortcuts (Sublime Text)

Default.sublime-keymap
[
  { "keys": ["ctrl+." ], "command": "lsp_code_actions" },
  { "keys": ["f12"], "command": "lsp_symbol_definition" },
  { "keys": ["shift+f12"], "command": "lsp_symbol_references" },
  { "keys": ["ctrl+k", "ctrl+r"], "command": "lsp_symbol_rename" },
  { "keys": ["ctrl+k", "ctrl+d"], "command": "lsp_hover" },
  { "keys": ["ctrl+shift+space"], "command": "lsp_signature_help" }
]

Emacs

Setup with lsp-mode

1

Install lsp-mode

Add to your init.el:
init.el
;; Using use-package
(use-package lsp-mode
  :ensure t
  :hook ((lua-mode . lsp))
  :commands lsp
  :config
  (setq lsp-keymap-prefix "C-c l"))

;; Optional: UI improvements
(use-package lsp-ui
  :ensure t
  :commands lsp-ui-mode)

;; Optional: Company mode for completion
(use-package company
  :ensure t
  :config
  (global-company-mode))
2

Configure EmmyLua LSP

Add EmmyLua server configuration:
init.el
(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")
    :major-modes '(lua-mode)
    :server-id 'emmylua-ls
    :initialization-options
    '((runtime ((version . "LuaLatest")))
      (diagnostics ((enable . t)))
      (completion ((enable . t))))
    :priority 1)))
3

Set Keybindings

Customize LSP keybindings:
init.el
(with-eval-after-load 'lsp-mode
  (define-key lsp-mode-map (kbd "C-c l r") 'lsp-rename)
  (define-key lsp-mode-map (kbd "C-c l a") 'lsp-execute-code-action)
  (define-key lsp-mode-map (kbd "C-c l d") 'lsp-describe-thing-at-point)
  (define-key lsp-mode-map (kbd "C-c l f") 'lsp-format-buffer)
  (define-key lsp-mode-map (kbd "C-c l g g") 'lsp-find-definition)
  (define-key lsp-mode-map (kbd "C-c l g r") 'lsp-find-references))

Setup with eglot (Alternative)

init.el
;; Simpler alternative to lsp-mode
(use-package eglot
  :ensure t
  :hook (lua-mode . eglot-ensure)
  :config
  (add-to-list 'eglot-server-programs
               '(lua-mode . ("emmylua_ls"))))

;; Optional: company completion
(use-package company
  :ensure t
  :hook (eglot-managed-mode . company-mode))

Vim (Classic)

Setup with vim-lsp

1

Install Plugin Manager

Using vim-plug, add to .vimrc:
.vimrc
call plug#begin('~/.vim/plugged')

Plug 'prabirshrestha/vim-lsp'
Plug 'mattn/vim-lsp-settings'
Plug 'prabirshrestha/asyncomplete.vim'
Plug 'prabirshrestha/asyncomplete-lsp.vim'

call plug#end()
Then run :PlugInstall
2

Configure EmmyLua LSP

Add to .vimrc:
.vimrc
if executable('emmylua_ls')
  au User lsp_setup call lsp#register_server({
    \ 'name': 'emmylua_ls',
    \ 'cmd': {server_info->['emmylua_ls']},
    \ 'whitelist': ['lua'],
    \ 'workspace_config': {
    \   'Lua': {
    \     'runtime': {'version': 'LuaLatest'},
    \     'diagnostics': {'enable': v:true},
    \     'completion': {'enable': v:true}
    \   }
    \ }
    \ })
endif
3

Set Keybindings

.vimrc
function! s:on_lsp_buffer_enabled() abort
  setlocal omnifunc=lsp#complete
  setlocal signcolumn=yes
  
  nmap <buffer> gd <plug>(lsp-definition)
  nmap <buffer> gr <plug>(lsp-references)
  nmap <buffer> gi <plug>(lsp-implementation)
  nmap <buffer> <leader>rn <plug>(lsp-rename)
  nmap <buffer> K <plug>(lsp-hover)
  nmap <buffer> [g <plug>(lsp-previous-diagnostic)
  nmap <buffer> ]g <plug>(lsp-next-diagnostic)
endfunction

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

Setup with coc.nvim (Also works in Vim)

.vimrc
" Install coc.nvim
Plug 'neoclide/coc.nvim', {'branch': 'release'}

" Configure after plugin installation
" :CocConfig to edit coc-settings.json
coc-settings.json
{
  "languageserver": {
    "emmylua": {
      "command": "emmylua_ls",
      "filetypes": ["lua"],
      "rootPatterns": [".emmyrc.json", ".git"],
      "settings": {
        "Lua": {
          "runtime": {"version": "LuaLatest"},
          "diagnostics": {"enable": true}
        }
      }
    }
  }
}

VSCodium

VSCodium is a free/libre version of VS Code without Microsoft telemetry.

Setup

1

Install EmmyLua Extension

The VS Code extension works in VSCodium:
codium --install-extension tangzx.emmylua
Or download from Open VSX Registry
2

Configure

Follow the same configuration as VS Code setup:
settings.json
{
  "emmylua.languageServer.path": "/path/to/emmylua_ls",
  "emmylua.completion.enable": true,
  "emmylua.diagnostics.enable": true
}

Helix

Setup

Helix has built-in LSP support:
1

Configure Language Server

Edit ~/.config/helix/languages.toml:
languages.toml
[[language]]
name = "lua"
scope = "source.lua"
injection-regex = "lua"
file-types = ["lua"]
roots = [".emmyrc.json", ".luarc.json", ".git"]
comment-token = "--"
indent = { tab-width = 4, unit = "    " }

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

[language-server.emmylua_ls.config.Lua]
runtime = { version = "LuaLatest" }
diagnostics = { enable = true, globals = [] }
completion = { enable = true, callSnippet = "Replace" }
2

Verify Setup

Open a Lua file and check LSP status:
hx test.lua
Press Space + w + d to see diagnostics

Helix Keybindings

ActionKey
Go to definitiongd
Go to referencesgr
HoverSpace + k
RenameSpace + r
Code actionSpace + a
FormatSpace + f

Kate

Setup

1

Enable LSP Plugin

  1. Go to Settings → Configure Kate → Plugins
  2. Enable “LSP Client”
  3. Click OK
2

Configure LSP

  1. Go to Settings → Configure Kate → LSP Client
  2. Click “User Server Settings”
  3. Add configuration:
{
  "servers": {
    "lua": {
      "command": ["emmylua_ls"],
      "rootIndicationFileNames": [".emmyrc.json", ".git"],
      "settings": {
        "Lua": {
          "runtime": {"version": "LuaLatest"},
          "diagnostics": {"enable": true}
        }
      }
    }
  }
}

Lapce

Lapce has built-in LSP support:

Setup

  1. Open Settings (Ctrl+,)
  2. Search for “LSP”
  3. Add Lua configuration:
{
  "lsp": {
    "lua": {
      "command": "emmylua_ls",
      "options": {
        "Lua": {
          "runtime": {"version": "LuaLatest"},
          "diagnostics": {"enable": true}
        }
      }
    }
  }
}

Troubleshooting

Solution:
  1. Verify installation:
    which emmylua_ls
    emmylua_ls --version
    
  2. Add to PATH:
    export PATH="$HOME/.cargo/bin:$PATH"
    
  3. Use absolute path in configuration:
    {
      "command": "/home/user/.cargo/bin/emmylua_ls"
    }
    
Solution:
  1. Check file association (file must be recognized as Lua)
  2. Verify root pattern matches your project:
    • Add .emmyrc.json to project root
    • Or adjust rootPatterns in config
  3. Restart editor and reopen file
  4. Check editor’s LSP logs for errors
Solution:
  1. Verify LSP is running (check status bar/logs)
  2. Ensure completion is enabled:
    {
      "settings": {
        "Lua": {
          "completion": {"enable": true}
        }
      }
    }
    
  3. Check if completion plugin is installed (editor-specific)
  4. Try manual completion trigger (usually Ctrl+Space)
Solution:
  1. Enable diagnostics:
    {
      "settings": {
        "Lua": {
          "diagnostics": {"enable": true}
        }
      }
    }
    
  2. Check if editor displays diagnostics (some require plugins)
  3. Look for errors in LSP logs
  4. Verify file has actual issues to diagnose
Solution:
  1. Restart the language server
  2. Check configuration syntax (JSON/TOML/etc. must be valid)
  3. Create .emmyrc.json in project root:
    {
      "runtime": {"version": "LuaLatest"},
      "diagnostics": {"enable": true}
    }
    
  4. Check if editor-level config overrides project config

Generic LSP Client Configuration

For editors not listed above, use this generic configuration as a starting point:

Minimum Required Settings

{
  "command": "emmylua_ls",
  "args": [],
  "filetypes": ["lua"],
  "rootPatterns": [".emmyrc.json", ".git"]
}

Full Configuration Template

{
  "command": "emmylua_ls",
  "args": [],
  "filetypes": ["lua"],
  "rootPatterns": [".emmyrc.json", ".luarc.json", ".git"],
  "initializationOptions": {},
  "settings": {
    "Lua": {
      "runtime": {
        "version": "LuaLatest",
        "path": ["?.lua", "?/init.lua"]
      },
      "diagnostics": {
        "enable": true,
        "globals": []
      },
      "completion": {
        "enable": true,
        "callSnippet": "Replace",
        "autoRequire": true
      },
      "hover": {
        "enable": true
      },
      "hint": {
        "enable": true,
        "paramHint": true
      },
      "workspace": {
        "library": [],
        "ignoreDir": [".git", "node_modules"]
      },
      "semanticTokens": {
        "enable": true
      }
    }
  }
}

TCP Mode (Remote Development)

For remote development or debugging:

Start Server in TCP Mode

emmylua_ls -c tcp --port 5007

Configure Client

{
  "command": "emmylua_ls",
  "args": ["-c", "tcp", "--port", "5007"],
  "tcp": {
    "host": "localhost",
    "port": 5007
  }
}

Project Configuration

Create .emmyrc.json in your project root for consistent settings across all editors:
.emmyrc.json
{
  "$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"]
  },
  "diagnostics": {
    "enable": true,
    "globals": ["vim", "love"],
    "severity": {
      "unused": "hint"
    }
  },
  "workspace": {
    "library": ["./libs"],
    "ignoreDir": ["build", "test"]
  }
}

Next Steps

Configuration

Explore all configuration options

VS Code

Detailed VS Code setup guide

Neovim

Comprehensive Neovim integration

Annotations

Learn about type annotations

Build docs developers (and LLMs) love