Categories &

Functions List

Function Reference: devtools.lsp

devtools: devtools.lsp ()

Serve the Language Server Protocol on standard input and output.

devtools.lsp () reads Language Server Protocol messages from standard input, answers each one, and writes the answer to standard output. It returns when standard input reaches end of file, and ends the process on an exit notification, with status 0 after shutdown and 1 without, as the protocol asks. It is the entry point an editor launches; it is not meant to be called at an interactive prompt, where it would take the terminal.

Five features are served:

hover
the help of the name under the cursor, as help renders it;
go to definition
the file and line that define it;
document symbols
the outline of a file: its class, properties, methods and functions;
workspace symbols
the functions, classes and methods of the project, by part of their name;
completion
function, keyword and project names, a namespace’s contents after its name and a dot, and a class’s methods and properties after an object and a dot.

The answers come from the interpreter serving them, so they are what this Octave, with these packages loaded, would itself say. The folder the editor opens is the project. Its functions and classes are read from its files and never put on the load path, since adding a folder to the path runs its PKG_ADD; where the project and a loaded package both define a name, the project’s definition is the one answered, the installed copy of a package under development being the stale one.

A method that several classes define is answered only where the class is certain: a call written Class.method, or a method or property used on the object of the method being edited, such as predict (obj, X) or obj.X inside a method whose first parameter is obj. Otherwise hover lists every definition and go to definition offers each. A name’s meaning is otherwise settled only at run time, so there are no diagnostics and no rename.

This server evaluates no code, runs no user function, and writes nothing. Configure an editor to launch it with:

 
 octave-cli -q --no-init-file --eval "pkg load devtools; devtools.lsp ()"

Do not shorten that command. --no-init-file skips ~/.octaverc, whose output would arrive before this function exists and corrupt the stream, as for devtools.mcp. On Windows, name octave-cli.exe in full. The server sees the packages its command loads and no others, so name the ones the project uses:

 
 --eval "pkg load devtools statistics; devtools.lsp ()"

A package’s dependencies need not be named: pkg load loads them too, so this also loads datatypes, which statistics depends on.

For Kate, enable the LSP Client plugin and add to its User Server Settings:

 
 {
   "servers": {
     "octave": {
       "command": ["octave-cli", "-q", "--no-init-file", "--eval",
                   "pkg load devtools; devtools.lsp ()"],
       "rootIndicationFileNames": ["DESCRIPTION", ".git"],
       "highlightingModeRegex": "^(Octave|Matlab)$"
     }
   }
 }

Kate may take a .m file for Objective-C and start its server for that language instead; set the file’s highlighting to Octave, or give the Octave file type the higher priority for *.m.

For Neovim 0.11 and later, in init.lua:

 
 vim.lsp.config ('octave', {
   cmd = {'octave-cli', '-q', '--no-init-file', '--eval',
          'pkg load devtools; devtools.lsp ()'},
   filetypes = {'octave', 'matlab'},
   root_markers = {'DESCRIPTION', '.git'},
 })
 vim.lsp.enable ('octave')

For Emacs with Eglot, in init.el; the first line stops Emacs taking a .m file for Objective-C:

 
 (add-to-list 'auto-mode-alist '("\\.m\\'" . octave-mode))
 (with-eval-after-load 'eglot
   (add-to-list 'eglot-server-programs
                '(octave-mode . ("octave-cli" "-q" "--no-init-file" "--eval"
                                 "pkg load devtools; devtools.lsp ()"))))

Everything diagnostic goes to standard error.

See also: devtools.mcp

Source Code: devtools.lsp