Repository: nanotee/sqls.nvim Branch: main Commit: dfc304f10fe3 Files: 9 Total size: 18.2 KB Directory structure: gitextract_17645tf3/ ├── .editorconfig ├── .luarc.json ├── LICENSE ├── README.md ├── autoload/ │ └── sqls_nvim.vim ├── doc/ │ └── sqls-nvim.txt ├── ftplugin/ │ └── sqls_output.vim ├── lsp/ │ └── sqls.lua └── lua/ └── sqls/ └── commands.lua ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ [*] charset = utf-8 end_of_line = lf indent_size = 4 indent_style = space insert_final_newline = true trim_trailing_whitespace = true [doc/*.txt] max_line_length = 78 ================================================ FILE: .luarc.json ================================================ { "$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json", "runtime": { "version": "LuaJIT" }, "workspace": { "library": [ "lua", "$VIMRUNTIME", "${3rd}/luv/library" ], "checkThirdParty": false } } ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2021 Timothée Sterle Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # sqls.nvim Neovim plugin for [sqls](https://github.com/lighttiger2505/sqls) that leverages the built-in LSP client. Loosely based on the code from [sqls.vim](https://github.com/lighttiger2505/sqls.vim). Requires Neovim 0.11.0+ ## Installation - [packer.nvim](https://github.com/wbthomason/packer.nvim) ```lua use 'nanotee/sqls.nvim' ``` - [paq-nvim](https://github.com/savq/paq-nvim) ```lua paq 'nanotee/sqls.nvim' ``` - [vim-plug](https://github.com/junegunn/vim-plug) ```vim Plug 'nanotee/sqls.nvim' ``` ## Usage Enable the configuration with [`vim.lsp.enable()`](https://neovim.io/doc/user/lsp.html#vim.lsp.enable()) and [`vim.lsp.config()`](https://neovim.io/doc/user/lsp.html#vim.lsp.config()) ```lua vim.lsp.config('sqls', { -- your custom client configuration }) vim.lsp.enable('sqls') ``` See also: [`lsp-config`](https://neovim.io/doc/user/lsp.html#lsp-config) ## Commands See [sqls-nvim-commands](doc/sqls-nvim.txt#L14) ## Mappings See [sqls-nvim-maps](doc/sqls-nvim.txt#L54) ## Events See [sqls-nvim-events](doc/sqls-nvim.txt#L66) ================================================ FILE: autoload/sqls_nvim.vim ================================================ function! sqls_nvim#query(type, client_id) call v:lua.require'sqls.commands'.query(a:type, a:client_id) endfunction function! sqls_nvim#query_vertical(type, client_id) call v:lua.require'sqls.commands'.query_vertical(a:type, a:client_id) endfunction ================================================ FILE: doc/sqls-nvim.txt ================================================ *sqls-nvim.txt* Neovim plugin for the sqls language server SETUP *sqls-nvim-setup* Enable the configuration with |vim.lsp.enable()| and |vim.lsp.config()| >lua vim.lsp.config('sqls', { -- your custom client configuration }) vim.lsp.enable('sqls') < See also: |lsp-config| ============================================================================== COMMANDS *sqls-nvim-commands* *:SqlsExecuteQuery* :SqlsExecuteQuery In normal mode, executes the query in the current buffer. In visual mode, executes the selected query (only works line-wise). Shows the results in a |preview-window|. *:SqlsExecuteQueryVertical* :SqlsExecuteQueryVertical Same as `:SqlsExecuteQuery`, but the results are displayed vertically. *:SqlsShowDatabases* :SqlsShowDatabases Shows a list of available databases in a |preview-window|. *:SqlsShowSchemas* :SqlsShowSchemas Shows a list of available schemas in a |preview-window|. *:SqlsShowConnections* :SqlsShowConnections Shows a list of available database connections in a |preview-window|. *:SqlsSwitchDatabase* :SqlsSwitchDatabase {database_name} Switches to a different database. If {database_name} is omitted, displays an interactive prompt with |vim.ui.select()| to select a database. *:SqlsSwitchConnection* :SqlsSwitchConnection {connection_index} Switches to a different database connection. If {connection_index} is omitted, displays an interactive prompt with |vim.ui.select()| to select a connection. ============================================================================== MAPS *sqls-nvim-maps* *(sqls-execute-query)* (sqls-execute-query) In visual mode, executes the selected range. In normal mode, executes a motion (like |ip| or |aw|) *(sqls-execute-query-vertical)* (sqls-execute-query-vertical) same as |(sqls-execute-query)|, but the results are displayed vertically ============================================================================== EVENTS *sqls-nvim-events* sqls.nvim dispatches custom |User| events that can be subscribed to using |autocommand|s. It exposes custom data via the `data` key in Lua callbacks (see |nvim_create_autocmd()|): >lua vim.api.nvim_create_autocmd('User', { pattern = 'SqlsConnectionChoice', callback = function(event) vim.notify(event.data.choice) end, }) < *User_SqlsDatabaseChoice* User SqlsDatabaseChoice After switching databases. Callback data: • choice: (string) the chosen database *User_SqlsConnectionChoice* User SqlsConnectionChoice After switching connections. Callback data: • choice: (string) the chosen connection vim:tw=78:et:ft=help:norl: ================================================ FILE: ftplugin/sqls_output.vim ================================================ setlocal nowrap setlocal nobuflisted setlocal nomodifiable setlocal nomodified setlocal readonly ================================================ FILE: lsp/sqls.lua ================================================ local api = vim.api return { cmd = { 'sqls' }, filetypes = { 'sql', 'mysql' }, single_file_support = true, commands = { executeQuery = function(_, client) require('sqls.commands').exec(client.client_id, 'executeQuery') end, showDatabases = function(_, client) require('sqls.commands').exec(client.client_id, 'showDatabases') end, showSchemas = function(_, client) require('sqls.commands').exec(client.client_id, 'showSchemas') end, showConnections = function(_, client) require('sqls.commands').exec(client.client_id, 'showConnections') end, showTables = function(_, client) require('sqls.commands').exec(client.client_id, 'showTables') end, describeTable = function(_, client) require('sqls.commands').exec(client.client_id, 'describeTable') end, switchConnections = function(_, client) require('sqls.commands').switch_connection(client.client_id) end, switchDatabase = function(_, client) require('sqls.commands').switch_database(client.client_id) end, }, on_attach = function(client, bufnr) local client_id = client.id api.nvim_buf_create_user_command(bufnr, 'SqlsExecuteQuery', function(args) require('sqls.commands').exec( client_id, 'executeQuery', args.smods, args.range ~= 0, nil, args.line1, args.line2 ) end, { range = true }) api.nvim_buf_create_user_command(bufnr, 'SqlsExecuteQueryVertical', function(args) require('sqls.commands').exec( client_id, 'executeQuery', args.smods, args.range ~= 0, '-show-vertical', args.line1, args.line2 ) end, { range = true }) api.nvim_buf_create_user_command(bufnr, 'SqlsShowDatabases', function(args) require('sqls.commands').exec(client_id, 'showDatabases', args.smods) end, {}) api.nvim_buf_create_user_command(bufnr, 'SqlsShowSchemas', function(args) require('sqls.commands').exec(client_id, 'showSchemas', args.smods) end, {}) api.nvim_buf_create_user_command(bufnr, 'SqlsShowConnections', function(args) require('sqls.commands').exec(client_id, 'showConnections', args.smods) end, {}) api.nvim_buf_create_user_command(bufnr, 'SqlsShowTables', function(args) require('sqls.commands').exec(client_id, 'showTables', args.smods) end, {}) -- Not yet supported by the language server: -- api.nvim_buf_create_user_command(bufnr, 'SqlsDescribeTable', function(args) -- require('sqls.commands').exec(client_id, 'describeTable', args.smods) -- end, {}) api.nvim_buf_create_user_command(bufnr, 'SqlsSwitchDatabase', function(args) require('sqls.commands').switch_database(client_id, args.args ~= '' and args.args or nil) end, { nargs = '?' }) api.nvim_buf_create_user_command(bufnr, 'SqlsSwitchConnection', function(args) require('sqls.commands').switch_connection(client_id, args.args ~= '' and args.args or nil) end, { nargs = '?' }) api.nvim_buf_set_keymap( bufnr, 'n', '(sqls-execute-query)', "let &opfunc='{type -> sqls_nvim#query(type, " .. client_id .. ")}'g@", { silent = true } ) api.nvim_buf_set_keymap( bufnr, 'x', '(sqls-execute-query)', "let &opfunc='{type -> sqls_nvim#query(type, " .. client_id .. ")}'g@", { silent = true } ) api.nvim_buf_set_keymap( bufnr, 'n', '(sqls-execute-query-vertical)', "let &opfunc='{type -> sqls_nvim#query_vertical(type, " .. client_id .. ")}'g@", { silent = true } ) api.nvim_buf_set_keymap( bufnr, 'x', '(sqls-execute-query-vertical)', "let &opfunc='{type -> sqls_nvim#query_vertical(type, " .. client_id .. ")}'g@", { silent = true } ) end, } ================================================ FILE: lua/sqls/commands.lua ================================================ local api = vim.api local fn = vim.fn local nvim_exec_autocmds = api.nvim_exec_autocmds local M = {} ---@param smods? vim.api.keyset.cmd.mods ---@return lsp.Handler local function make_show_results_handler(smods) return function(err, result, _) if err then vim.notify('sqls: ' .. err.message, vim.log.levels.ERROR) return end if not result then return end local tempfile = fn.tempname() .. '.sqls_output' local bufnr = fn.bufnr(tempfile, true) api.nvim_buf_set_lines(bufnr, 0, 1, false, vim.split(result, '\n')) vim.cmd.pedit({ args = { tempfile }, mods = smods or {}, }) api.nvim_set_option_value('filetype', 'sqls_output', { buf = bufnr }) end end ---@param client_id integer ---@param command string ---@param smods? vim.api.keyset.cmd.mods ---@param range_given? boolean ---@param show_vertical? '-show-vertical' ---@param line1? integer ---@param line2? integer function M.exec(client_id, command, smods, range_given, show_vertical, line1, line2) local client = assert(vim.lsp.get_client_by_id(client_id)) local range if range_given then range = vim.lsp.util.make_given_range_params( { line1, 0 }, { line2, math.huge }, 0, client.offset_encoding ).range range['end'].character = range['end'].character - 1 end client:request( 'workspace/executeCommand', { command = command, arguments = { vim.uri_from_bufnr(0), show_vertical }, range = range, }, make_show_results_handler(smods) ) end ---@alias sqls_operatorfunc fun(type: 'block'|'line'|'char', client_id: integer) ---@param show_vertical? '-show-vertical' ---@return sqls_operatorfunc local function make_query_mapping(show_vertical) return function(type, client_id) local range local _, lnum1, col1, _ = unpack(fn.getpos("'[")) local _, lnum2, col2, _ = unpack(fn.getpos("']")) if type == 'block' then vim.notify('sqls does not support block-wise ranges!', vim.log.levels.ERROR) return end local client = assert(vim.lsp.get_client_by_id(client_id)) if type == 'line' then range = vim.lsp.util.make_given_range_params( { lnum1, 0 }, { lnum2, math.huge }, 0, client.offset_encoding ).range range['end'].character = range['end'].character - 1 elseif type == 'char' then range = vim.lsp.util.make_given_range_params( { lnum1, col1 - 1 }, { lnum2, col2 - 1 }, 0, client.offset_encoding ).range end client:request( 'workspace/executeCommand', { command = 'executeQuery', arguments = { vim.uri_from_bufnr(0), show_vertical }, range = range, }, make_show_results_handler() ) end end M.query = make_query_mapping() M.query_vertical = make_query_mapping('-show-vertical') ---@alias sqls_switch_function fun(client_id: integer, query: string) ---@alias sqls_prompt_function fun(client_id: integer, switch_function: sqls_switch_function, query?: string) ---@alias sqls_answer_formatter fun(answer: string): string ---@alias sqls_switcher fun(client_id: integer, query?: string) ---@alias sqls_event_name ---| 'SqlsDatabaseChoice' ---| 'SqlsConnectionChoice' ---@param client_id integer ---@param switch_function sqls_switch_function ---@param answer_formatter sqls_answer_formatter ---@param event_name sqls_event_name ---@param query? string ---@return lsp.Handler local function make_choice_handler(client_id, switch_function, answer_formatter, event_name, query) return function(err, result, _) if err then vim.notify('sqls: ' .. err.message, vim.log.levels.ERROR) return end if not result then return end if result == '' then vim.notify('sqls: No choices available') return end local choices = vim.split(result, '\n') local function switch_callback(answer) if not answer then return end switch_function(client_id, answer_formatter(answer)) nvim_exec_autocmds('User', { pattern = event_name, data = { choice = answer }, }) end if query then local answer = choices[tonumber(query)] switch_callback(answer) return end vim.ui.select(choices, { prompt = 'sqls.nvim' }, switch_callback) end end ---@type lsp.Handler local function switch_handler(err, _, _) if err then vim.notify('sqls: ' .. err.message, vim.log.levels.ERROR) end end ---@param command string ---@return sqls_switch_function local function make_switch_function(command) return function(client_id, query) local client = assert(vim.lsp.get_client_by_id(client_id)) client:request( 'workspace/executeCommand', { command = command, arguments = { query }, }, switch_handler ) end end ---@param command string ---@param answer_formatter sqls_answer_formatter ---@param event_name sqls_event_name ---@return sqls_prompt_function local function make_prompt_function(command, answer_formatter, event_name) return function(client_id, switch_function, query) local client = assert(vim.lsp.get_client_by_id(client_id)) client:request( 'workspace/executeCommand', { command = command, }, make_choice_handler(client_id, switch_function, answer_formatter, event_name, query) ) end end ---@type sqls_answer_formatter local function format_database_answer(answer) return answer end ---@type sqls_answer_formatter local function format_connection_answer(answer) return vim.split(answer, ' ')[1] end local database_switch_function = make_switch_function('switchDatabase') local connection_switch_function = make_switch_function('switchConnections') local database_prompt_function = make_prompt_function( 'showDatabases', format_database_answer, 'SqlsDatabaseChoice' ) local connection_prompt_function = make_prompt_function( 'showConnections', format_connection_answer, 'SqlsConnectionChoice' ) ---@param prompt_function sqls_prompt_function ---@param switch_function sqls_switch_function ---@return sqls_switcher local function make_switcher(prompt_function, switch_function) return function(client_id, query) prompt_function(client_id, switch_function, query) end end M.switch_database = make_switcher(database_prompt_function, database_switch_function) M.switch_connection = make_switcher(connection_prompt_function, connection_switch_function) return M