aboutsummaryrefslogtreecommitdiffstats
path: root/lsp/texlab.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lsp/texlab.lua')
-rw-r--r--lsp/texlab.lua220
1 files changed, 220 insertions, 0 deletions
diff --git a/lsp/texlab.lua b/lsp/texlab.lua
new file mode 100644
index 00000000..74b6e3d8
--- /dev/null
+++ b/lsp/texlab.lua
@@ -0,0 +1,220 @@
+local function client_with_fn(fn)
+ return function()
+ local bufnr = vim.api.nvim_get_current_buf()
+ local client = vim.lsp.get_clients({ bufnr = bufnr, name = 'texlab' })[1]
+ if not client then
+ return vim.notify(('texlab client not found in bufnr %d'):format(bufnr), vim.log.levels.ERROR)
+ end
+ fn(client, bufnr)
+ end
+end
+
+local function buf_build(client, bufnr)
+ local win = vim.api.nvim_get_current_win()
+ local params = vim.lsp.util.make_position_params(win, client.offset_encoding)
+ client.request('textDocument/build', params, function(err, result)
+ if err then
+ error(tostring(err))
+ end
+ local texlab_build_status = {
+ [0] = 'Success',
+ [1] = 'Error',
+ [2] = 'Failure',
+ [3] = 'Cancelled',
+ }
+ vim.notify('Build ' .. texlab_build_status[result.status], vim.log.levels.INFO)
+ end, bufnr)
+end
+
+local function buf_search(client, bufnr)
+ local win = vim.api.nvim_get_current_win()
+ local params = vim.lsp.util.make_position_params(win, client.offset_encoding)
+ client.request('textDocument/forwardSearch', params, function(err, result)
+ if err then
+ error(tostring(err))
+ end
+ local texlab_forward_status = {
+ [0] = 'Success',
+ [1] = 'Error',
+ [2] = 'Failure',
+ [3] = 'Unconfigured',
+ }
+ vim.notify('Search ' .. texlab_forward_status[result.status], vim.log.levels.INFO)
+ end, bufnr)
+end
+
+local function buf_cancel_build(client, bufnr)
+ if vim.fn.has 'nvim-0.11' == 1 then
+ return client:exec_cmd({
+ title = 'cancel',
+ command = 'texlab.cancelBuild',
+ }, { bufnr = bufnr })
+ end
+ vim.lsp.buf.execute_command { command = 'texlab.cancelBuild' }
+ vim.notify('Build cancelled', vim.log.levels.INFO)
+end
+
+local function dependency_graph(client)
+ client.request('workspace/executeCommand', { command = 'texlab.showDependencyGraph' }, function(err, result)
+ if err then
+ return vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
+ end
+ vim.notify('The dependency graph has been generated:\n' .. result, vim.log.levels.INFO)
+ end, 0)
+end
+
+local function command_factory(cmd)
+ local cmd_tbl = {
+ Auxiliary = 'texlab.cleanAuxiliary',
+ Artifacts = 'texlab.cleanArtifacts',
+ CancelBuild = 'texlab.cancelBuild',
+ }
+ return function(client, bufnr)
+ if vim.fn.has 'nvim-0.11' == 1 then
+ return client:exec_cmd({
+ title = ('clean_%s'):format(cmd),
+ command = cmd_tbl[cmd],
+ arguments = { { uri = vim.uri_from_bufnr(bufnr) } },
+ }, { bufnr = bufnr }, function(err, _)
+ if err then
+ vim.notify(('Failed to clean %s files: %s'):format(cmd, err.message), vim.log.levels.ERROR)
+ else
+ vim.notify(('command %s executed successfully'):format(cmd), vim.log.levels.INFO)
+ end
+ end)
+ end
+
+ vim.lsp.buf.execute_command {
+ command = cmd_tbl[cmd],
+ arguments = { { uri = vim.uri_from_bufnr(bufnr) } },
+ }
+ vim.notify(('command %s executed successfully'):format(cmd_tbl[cmd]))
+ end
+end
+
+local function buf_find_envs(client, bufnr)
+ local win = vim.api.nvim_get_current_win()
+ client.request('workspace/executeCommand', {
+ command = 'texlab.findEnvironments',
+ arguments = { vim.lsp.util.make_position_params(win, client.offset_encoding) },
+ }, function(err, result)
+ if err then
+ return vim.notify(err.code .. ': ' .. err.message, vim.log.levels.ERROR)
+ end
+ local env_names = {}
+ local max_length = 1
+ for _, env in ipairs(result) do
+ table.insert(env_names, env.name.text)
+ max_length = math.max(max_length, string.len(env.name.text))
+ end
+ for i, name in ipairs(env_names) do
+ env_names[i] = string.rep(' ', i - 1) .. name
+ end
+ vim.lsp.util.open_floating_preview(env_names, '', {
+ height = #env_names,
+ width = math.max((max_length + #env_names - 1), (string.len 'Environments')),
+ focusable = false,
+ focus = false,
+ border = 'single',
+ title = 'Environments',
+ })
+ end, bufnr)
+end
+
+local function buf_change_env(client, bufnr)
+ local new = vim.fn.input 'Enter the new environment name: '
+ if not new or new == '' then
+ return vim.notify('No environment name provided', vim.log.levels.WARN)
+ end
+ local pos = vim.api.nvim_win_get_cursor(0)
+ if vim.fn.has 'nvim-0.11' == 1 then
+ return client:exec_cmd({
+ title = 'change_environment',
+ command = 'texlab.changeEnvironment',
+ arguments = {
+ {
+ textDocument = { uri = vim.uri_from_bufnr(bufnr) },
+ position = { line = pos[1] - 1, character = pos[2] },
+ newName = tostring(new),
+ },
+ },
+ }, { bufnr = bufnr })
+ end
+
+ vim.lsp.buf.execute_command {
+ command = 'texlab.changeEnvironment',
+ arguments = {
+ {
+ textDocument = { uri = vim.uri_from_bufnr(bufnr) },
+ position = { line = pos[1] - 1, character = pos[2] },
+ newName = tostring(new),
+ },
+ },
+ }
+end
+
+---@brief
+---
+---https://github.com/latex-lsp/texlab
+--
+-- A completion engine built from scratch for (La)TeX.
+--
+-- See https://github.com/latex-lsp/texlab/wiki/Configuration for configuration options.
+return {
+ cmd = { 'texlab' },
+ filetypes = { 'tex', 'plaintex', 'bib' },
+ root_markers = { '.git', '.latexmkrc', '.texlabroot', 'texlabroot', 'Tectonic.toml' },
+ settings = {
+ texlab = {
+ rootDirectory = nil,
+ build = {
+ executable = 'latexmk',
+ args = { '-pdf', '-interaction=nonstopmode', '-synctex=1', '%f' },
+ onSave = false,
+ forwardSearchAfter = false,
+ },
+ forwardSearch = {
+ executable = nil,
+ args = {},
+ },
+ chktex = {
+ onOpenAndSave = false,
+ onEdit = false,
+ },
+ diagnosticsDelay = 300,
+ latexFormatter = 'latexindent',
+ latexindent = {
+ ['local'] = nil, -- local is a reserved keyword
+ modifyLineBreaks = false,
+ },
+ bibtexFormatter = 'texlab',
+ formatterLineLength = 80,
+ },
+ },
+ on_attach = function()
+ vim.api.nvim_buf_create_user_command(0, 'TexlabBuild', client_with_fn(buf_build), {
+ desc = 'Build the current buffer',
+ })
+ vim.api.nvim_buf_create_user_command(0, 'TexlabForward', client_with_fn(buf_search), {
+ desc = 'Forward search from current position',
+ })
+ vim.api.nvim_buf_create_user_command(0, 'TexlabCancelBuild', client_with_fn(buf_cancel_build), {
+ desc = 'Cancel the current build',
+ })
+ vim.api.nvim_buf_create_user_command(0, 'TexlabDependencyGraph', client_with_fn(dependency_graph), {
+ desc = 'Show the dependency graph',
+ })
+ vim.api.nvim_buf_create_user_command(0, 'TexlabCleanArtifacts', client_with_fn(command_factory('Artifacts')), {
+ desc = 'Clean the artifacts',
+ })
+ vim.api.nvim_buf_create_user_command(0, 'TexlabCleanAuxiliary', client_with_fn(command_factory('Auxiliary')), {
+ desc = 'Clean the auxiliary files',
+ })
+ vim.api.nvim_buf_create_user_command(0, 'TexlabFindEnvironments', client_with_fn(buf_find_envs), {
+ desc = 'Find the environments at current position',
+ })
+ vim.api.nvim_buf_create_user_command(0, 'TexlabChangeEnvironment', client_with_fn(buf_change_env), {
+ desc = 'Change the environment at current position',
+ })
+ end,
+}