Refactor LSP configuration and remove Kite plugin. Updated key mappings for comments and added Python-specific tab settings. Enhanced Treesitter installation list and integrated Ruff LSP for Python. Cleaned up Kite-related files and configurations.
This commit is contained in:
parent
de2d52b4dc
commit
643789d616
92
init.lua
92
init.lua
|
|
@ -151,12 +151,12 @@ require('lazy').setup({
|
|||
'numToStr/Comment.nvim',
|
||||
opts = {
|
||||
toggler = {
|
||||
line = '<leader>/', -- Changed from <gc>
|
||||
block = '<leader>b', -- Changed from <gb>
|
||||
line = 'gc',
|
||||
block = 'gb',
|
||||
},
|
||||
opleader = {
|
||||
line = '<leader>/', -- Optional
|
||||
block = '<leader>B', -- Optional
|
||||
line = 'gc',
|
||||
block = 'gb',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
@ -216,6 +216,15 @@ vim.o.softtabstop = 2
|
|||
vim.o.shiftwidth = 2
|
||||
vim.o.expandtab = true
|
||||
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'python' },
|
||||
callback = function()
|
||||
vim.bo.tabstop = 4
|
||||
vim.bo.softtabstop = 4
|
||||
vim.bo.shiftwidth = 4
|
||||
end,
|
||||
})
|
||||
|
||||
-- Basic keymaps
|
||||
vim.keymap.set({ 'n', 'v' }, '<Space>', '<Nop>', { silent = true })
|
||||
vim.keymap.set('n', 'k', "v:count == 0 ? 'gk' : 'k'", { expr = true, silent = true })
|
||||
|
|
@ -257,7 +266,27 @@ end, { desc = '[/] Fuzzily search in current buffer' })
|
|||
-- Treesitter configuration
|
||||
vim.defer_fn(function()
|
||||
require('nvim-treesitter.configs').setup {
|
||||
ensure_installed = { 'c', 'cpp', 'go', 'lua', 'python', 'rust', 'tsx', 'javascript', 'typescript', 'vimdoc', 'vim', 'bash' },
|
||||
ensure_installed = {
|
||||
'c',
|
||||
'cpp',
|
||||
'go',
|
||||
'lua',
|
||||
'python',
|
||||
'rust',
|
||||
'tsx',
|
||||
'javascript',
|
||||
'typescript',
|
||||
'vimdoc',
|
||||
'vim',
|
||||
'bash',
|
||||
'html',
|
||||
'css',
|
||||
'json',
|
||||
'toml',
|
||||
'yaml',
|
||||
'dockerfile',
|
||||
'htmldjango',
|
||||
},
|
||||
auto_install = false,
|
||||
highlight = { enable = true },
|
||||
indent = { enable = true },
|
||||
|
|
@ -357,12 +386,54 @@ end
|
|||
|
||||
require('mason').setup()
|
||||
require('mason-lspconfig').setup()
|
||||
local servers = { lua_ls = { Lua = { workspace = { checkThirdParty = false }, telemetry = { enable = false } } } }
|
||||
local lspconfig = require 'lspconfig'
|
||||
local servers = {
|
||||
pyright = {
|
||||
python = {
|
||||
analysis = {
|
||||
autoSearchPaths = true,
|
||||
diagnosticMode = 'openFilesOnly',
|
||||
useLibraryCodeForTypes = true,
|
||||
},
|
||||
},
|
||||
},
|
||||
lua_ls = {
|
||||
Lua = {
|
||||
workspace = { checkThirdParty = false },
|
||||
telemetry = { enable = false },
|
||||
},
|
||||
},
|
||||
}
|
||||
local capabilities = require('cmp_nvim_lsp').default_capabilities(vim.lsp.protocol.make_client_capabilities())
|
||||
local mason_lspconfig = require 'mason-lspconfig'
|
||||
mason_lspconfig.setup { ensure_installed = vim.tbl_keys(servers) }
|
||||
mason_lspconfig.setup_handlers { function(server_name) require('lspconfig')[server_name].setup { capabilities = capabilities, on_attach = on_attach, settings = servers[server_name], filetypes = (servers[server_name] or {}).filetypes, } end }
|
||||
|
||||
-- Ruff installation via Mason can fail on some Python setups.
|
||||
-- If a system ruff binary exists, attach Ruff LSP directly.
|
||||
local ruff_server = nil
|
||||
if lspconfig.ruff then
|
||||
ruff_server = 'ruff'
|
||||
elseif lspconfig.ruff_lsp then
|
||||
ruff_server = 'ruff_lsp'
|
||||
end
|
||||
|
||||
if vim.fn.executable 'ruff' == 1 and ruff_server then
|
||||
lspconfig[ruff_server].setup {
|
||||
capabilities = capabilities,
|
||||
on_attach = on_attach,
|
||||
}
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
callback = function(args)
|
||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||
if client and (client.name == 'ruff' or client.name == 'ruff_lsp') then
|
||||
client.server_capabilities.hoverProvider = false
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- CMP setup
|
||||
local cmp = require 'cmp'
|
||||
local luasnip = require 'luasnip'
|
||||
|
|
@ -408,13 +479,10 @@ cmp.setup {
|
|||
{ name = 'nvim_lsp' },
|
||||
{ name = 'luasnip' },
|
||||
},
|
||||
}
|
||||
|
||||
require("cmp").setup({
|
||||
formatting = {
|
||||
format = require("tailwindcss-colorizer-cmp").formatter
|
||||
}
|
||||
})
|
||||
format = require('tailwindcss-colorizer-cmp').formatter,
|
||||
},
|
||||
}
|
||||
|
||||
require("colorizer").setup {
|
||||
user_default_options = {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,6 @@
|
|||
-- See the kickstart.nvim README for more information
|
||||
|
||||
return {
|
||||
{
|
||||
'neovim/nvim-lspconfig',
|
||||
config = function()
|
||||
require('custom.plugins.lspconfig') -- This simply loads the lspconfig.lua file
|
||||
end,
|
||||
},
|
||||
|
||||
-- nvim-autopairs configuration
|
||||
{
|
||||
"windwp/nvim-autopairs",
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@
|
|||
-- Adds additional commands as well to manage the behavior
|
||||
|
||||
return {
|
||||
'neovim/nvim-lspconfig',
|
||||
'jose-elias-alvarez/null-ls.nvim',
|
||||
'stevearc/conform.nvim',
|
||||
event = { 'BufReadPre', 'BufNewFile' },
|
||||
cmd = { 'ConformInfo' },
|
||||
config = function()
|
||||
-- Force .html files to be recognized as htmldjango for Jinja compatibility
|
||||
vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, {
|
||||
pattern = "*.html",
|
||||
vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, {
|
||||
pattern = '*.html',
|
||||
callback = function()
|
||||
vim.bo.filetype = "htmldjango"
|
||||
vim.bo.filetype = 'htmldjango'
|
||||
end,
|
||||
})
|
||||
|
||||
-- Switch for controlling whether you want autoformatting.
|
||||
-- Use :KickstartFormatToggle to toggle autoformatting on or off
|
||||
local format_is_enabled = true
|
||||
vim.api.nvim_create_user_command('KickstartFormatToggle', function()
|
||||
|
|
@ -23,71 +23,28 @@ return {
|
|||
print('Setting autoformatting to: ' .. tostring(format_is_enabled))
|
||||
end, {})
|
||||
|
||||
-- Create an augroup that is used for managing our formatting autocmds.
|
||||
-- We need one augroup per client to make sure that multiple clients
|
||||
-- can attach to the same buffer without interfering with each other.
|
||||
local _augroups = {}
|
||||
local get_augroup = function(client)
|
||||
if not _augroups[client.id] then
|
||||
local group_name = 'kickstart-lsp-format-' .. client.name
|
||||
local id = vim.api.nvim_create_augroup(group_name, { clear = true })
|
||||
_augroups[client.id] = id
|
||||
end
|
||||
|
||||
return _augroups[client.id]
|
||||
end
|
||||
|
||||
-- Whenever an LSP attaches to a buffer, we will run this function.
|
||||
--
|
||||
-- See `:help LspAttach` for more information about this autocmd event.
|
||||
vim.api.nvim_create_autocmd('LspAttach', {
|
||||
group = vim.api.nvim_create_augroup('kickstart-lsp-attach-format', { clear = true }),
|
||||
-- This is where we attach the autoformatting for reasonable clients
|
||||
callback = function(args)
|
||||
local client_id = args.data.client_id
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
local bufnr = args.buf
|
||||
|
||||
-- Only attach to clients that support document formatting
|
||||
if not client.server_capabilities.documentFormattingProvider then
|
||||
return
|
||||
end
|
||||
|
||||
-- Tsserver usually works poorly. Sorry you work with bad languages
|
||||
-- You can remove this line if you know what you're doing :)
|
||||
if client.name == 'tsserver' then
|
||||
return
|
||||
end
|
||||
|
||||
-- Create an autocmd that will run *before* we save the buffer.
|
||||
-- Run the formatting command for the LSP that has just attached.
|
||||
vim.api.nvim_create_autocmd('BufWritePre', {
|
||||
group = get_augroup(client),
|
||||
buffer = bufnr,
|
||||
callback = function()
|
||||
require('conform').setup {
|
||||
formatters_by_ft = {
|
||||
python = { 'ruff_organize_imports', 'ruff_format' },
|
||||
htmldjango = { 'djlint' },
|
||||
html = { 'prettier' },
|
||||
css = { 'prettier' },
|
||||
javascript = { 'prettier' },
|
||||
json = { 'prettier' },
|
||||
yaml = { 'prettier' },
|
||||
},
|
||||
format_on_save = function(bufnr)
|
||||
if not format_is_enabled then
|
||||
return
|
||||
return nil
|
||||
end
|
||||
|
||||
vim.lsp.buf.format {
|
||||
async = false,
|
||||
filter = function(c)
|
||||
return c.id == client.id
|
||||
return {
|
||||
timeout_ms = 1000,
|
||||
lsp_format = 'fallback',
|
||||
bufnr = bufnr,
|
||||
}
|
||||
end,
|
||||
}
|
||||
end,
|
||||
})
|
||||
end,
|
||||
})
|
||||
|
||||
-- Set up null-ls for additional formatting needs
|
||||
null_ls.setup({
|
||||
sources = {
|
||||
null_ls.builtins.formatting.prettier.with({
|
||||
filetypes = { "html", "jinja", "htmldjango" },
|
||||
}),
|
||||
},
|
||||
})
|
||||
end,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ return {
|
|||
|
||||
-- Add your own debuggers here
|
||||
'leoluz/nvim-dap-go',
|
||||
'mfussenegger/nvim-dap-python',
|
||||
},
|
||||
config = function()
|
||||
local dap = require 'dap'
|
||||
|
|
@ -39,6 +40,7 @@ return {
|
|||
ensure_installed = {
|
||||
-- Update this to ensure that you have the debuggers for the langs you want
|
||||
'delve',
|
||||
'debugpy',
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -83,5 +85,6 @@ return {
|
|||
|
||||
-- Install golang specific config
|
||||
require('dap-go').setup()
|
||||
require('dap-python').setup(vim.fn.exepath 'python3')
|
||||
end,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
dist: trusty
|
||||
|
||||
env:
|
||||
global:
|
||||
- DEPS=$HOME/deps
|
||||
- PATH=$DEPS/bin:$PATH
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install python-pip
|
||||
- pip install --user awscli
|
||||
- export PATH="$PATH:$HOME/.local/bin"
|
||||
- curl --silent -L "https://s3-us-west-1.amazonaws.com/kite-data/tensorflow/libtensorflow-cpu-linux-x86_64-1.9.0.tar.gz" | tar -C $HOME -xz
|
||||
- curl --silent --compressed --output "$HOME/kited-test" "https://s3-us-west-1.amazonaws.com/kited-test/linux/kited-test"
|
||||
- chmod u+x "$HOME/kited-test"
|
||||
|
||||
install: |
|
||||
git config --global user.email "you@example.com"
|
||||
git config --global user.name "Your Name"
|
||||
C_OPTS="--prefix=$DEPS --with-features=huge --disable-gui "
|
||||
git clone --depth 1 https://github.com/vim/vim
|
||||
cd vim
|
||||
export PATH=/usr/bin:$PATH
|
||||
./configure $C_OPTS
|
||||
make
|
||||
make install
|
||||
cd -
|
||||
export PATH=$DEPS/bin:$PATH
|
||||
export VIM="$(which vim)"
|
||||
|
||||
|
||||
script:
|
||||
- vim --version
|
||||
- cd test && bash test
|
||||
- export LD_LIBRARY_PATH="$HOME/lib:$LD_LIBRARY_PATH"
|
||||
- echo "Running tests with kited-local --------------" && $HOME/kited-test > ~/kite.log 2>&1 & sleep 20 && bash editor_tests && killall kited-test
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
Copyright (c) 2017 Manhattan Engineering, Inc - All Rights Reserved
|
||||
|
||||
Reproduction of this material is strictly forbidden unless prior written
|
||||
permission is obtained from Manhattan Engineering, Inc.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
function! kite#docs#docs()
|
||||
if &filetype != 'python'
|
||||
call kite#utils#warn('Docs are only available for Python')
|
||||
return
|
||||
endif
|
||||
|
||||
if empty(expand('<cword>')) | return | endif
|
||||
|
||||
let b:kite_id = ''
|
||||
|
||||
call kite#hover#hover()
|
||||
|
||||
while b:kite_id == ''
|
||||
sleep 5m
|
||||
endwhile
|
||||
|
||||
if b:kite_id == -1
|
||||
call kite#utils#info('No documentation available.')
|
||||
return
|
||||
endif
|
||||
|
||||
call kite#client#docs(b:kite_id)
|
||||
endfunction
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
let s:events_pending = 0
|
||||
|
||||
function! kite#events#any_events_pending()
|
||||
return s:events_pending > 0
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#events#event(action)
|
||||
let filename = kite#utils#filepath(0)
|
||||
|
||||
if wordcount().bytes < kite#max_file_size()
|
||||
let action = a:action
|
||||
let text = kite#utils#buffer_contents()
|
||||
else
|
||||
let action = 'skip'
|
||||
let text = ''
|
||||
endif
|
||||
|
||||
let [sel_start, sel_end] = kite#utils#selected_region_characters()
|
||||
if [sel_start, sel_end] == [-1, -1]
|
||||
return
|
||||
endif
|
||||
let selections = [{ 'start': sel_start, 'end': sel_end, 'encoding': 'utf-32' }]
|
||||
|
||||
let json = json_encode({
|
||||
\ 'source': 'vim',
|
||||
\ 'filename': filename,
|
||||
\ 'text': text,
|
||||
\ 'action': action,
|
||||
\ 'selections': selections,
|
||||
\ 'editor_version': kite#utils#vim_version(),
|
||||
\ 'plugin_version': kite#utils#plugin_version()
|
||||
\ })
|
||||
|
||||
let s:events_pending += 1
|
||||
|
||||
call kite#client#post_event(json, function('kite#events#handler', [bufnr('')]))
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#events#handler(bufnr, response)
|
||||
let s:events_pending -= 1
|
||||
|
||||
call setbufvar(a:bufnr, 'kite_skip', (a:response.status == 0 || a:response.status == 403))
|
||||
endfunction
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
let s:languages_supported_by_kited = []
|
||||
|
||||
" Returns true if we want Kite completions for the current buffer, false otherwise.
|
||||
function! kite#languages#supported_by_plugin()
|
||||
" Return false if the file extension is not recognised by kited.
|
||||
let recognised_extensions = [
|
||||
\ 'c',
|
||||
\ 'cc',
|
||||
\ 'cpp',
|
||||
\ 'cs',
|
||||
\ 'css',
|
||||
\ 'go',
|
||||
\ 'h',
|
||||
\ 'hpp',
|
||||
\ 'html',
|
||||
\ 'java',
|
||||
\ 'js',
|
||||
\ 'jsx',
|
||||
\ 'kt',
|
||||
\ 'less',
|
||||
\ 'm',
|
||||
\ 'php',
|
||||
\ 'py',
|
||||
\ 'pyw',
|
||||
\ 'rb',
|
||||
\ 'scala',
|
||||
\ 'sh',
|
||||
\ 'ts',
|
||||
\ 'tsx',
|
||||
\ 'vue',
|
||||
\ ]
|
||||
if index(recognised_extensions, expand('%:e')) == -1
|
||||
return 0
|
||||
endif
|
||||
|
||||
if g:kite_supported_languages == ['*']
|
||||
return 1
|
||||
endif
|
||||
|
||||
" Return false if the buffer's language is not one for which we want Kite completions.
|
||||
if index(g:kite_supported_languages, &filetype) == -1
|
||||
return 0
|
||||
endif
|
||||
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
|
||||
" Returns true if the current buffer's language is supported by kited, false otherwise.
|
||||
function! kite#languages#supported_by_kited()
|
||||
" Only check kited's languages once.
|
||||
if empty(s:languages_supported_by_kited)
|
||||
" A list of language names, e.g. ['bash', 'c', 'javascript', 'ruby', ...]
|
||||
let s:languages_supported_by_kited = kite#client#languages(function('kite#languages#handler'))
|
||||
endif
|
||||
|
||||
return index(s:languages_supported_by_kited, &filetype) != -1
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#languages#handler(response)
|
||||
if a:response.status != 200 | return [] | endif
|
||||
|
||||
return json_decode(a:response.body)
|
||||
endfunction
|
||||
|
|
@ -1,209 +0,0 @@
|
|||
let s:completion_counter = 0
|
||||
|
||||
function! kite#signature#increment_completion_counter()
|
||||
let s:completion_counter = s:completion_counter + 1
|
||||
endfunction
|
||||
|
||||
function! kite#signature#completion_counter()
|
||||
return s:completion_counter
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#signature#handler(counter, startcol, response) abort
|
||||
call kite#utils#log('signature: '.a:response.status)
|
||||
|
||||
" Ignore old completion results.
|
||||
if a:counter != s:completion_counter
|
||||
return
|
||||
endif
|
||||
|
||||
if a:response.status != 200
|
||||
return
|
||||
endif
|
||||
|
||||
let json = json_decode(a:response.body)
|
||||
let call = g:kite#document#Document.New(json.calls[0])
|
||||
|
||||
let function_name = call.dig('func_name', '')
|
||||
if empty(function_name)
|
||||
let function_name = call.dig('callee.repr', '')
|
||||
endif
|
||||
let function_name = split(function_name, '\.')[-1]
|
||||
|
||||
let spacer = {'word': '', 'empty': 1, 'dup': 1}
|
||||
let indent = ' '
|
||||
let completions = []
|
||||
let wrap_width = 50
|
||||
|
||||
|
||||
"
|
||||
" Signature
|
||||
"
|
||||
let parameters = []
|
||||
let return_type = ''
|
||||
let [current_arg, in_kwargs] = [call.dig('arg_index', 0), call.dig('language_details.python.in_kwargs', 0)]
|
||||
let kind = call.dig('callee.kind', '')
|
||||
|
||||
" 1. Name of function with parameters.
|
||||
if kind ==# 'function'
|
||||
" 1.b.1. Parameters
|
||||
for parameter in call.dig('callee.details.function.parameters', [])
|
||||
" 1.b.1.a. Name
|
||||
let name = parameter.name
|
||||
" 1.b.1.b. Default value
|
||||
if kite#utils#present(parameter.language_details.python, 'default_value')
|
||||
let name .= '='.parameter.language_details.python.default_value[0].repr
|
||||
endif
|
||||
" 2. Highlight current argument
|
||||
if !in_kwargs && len(parameters) == current_arg
|
||||
let name = '*'.name.'*'
|
||||
endif
|
||||
call add(parameters, name)
|
||||
endfor
|
||||
" 1.b.2. vararg indicator
|
||||
let vararg = call.dig('callee.details.function.language_details.python.vararg', {})
|
||||
if !empty(vararg)
|
||||
call add(parameters, '*'.vararg.name)
|
||||
endif
|
||||
" 1.b.3. keyword arguments indicator
|
||||
let kwarg = call.dig('callee.details.function.language_details.python.kwarg', {})
|
||||
if !empty(kwarg)
|
||||
call add(parameters, '**'.kwarg.name)
|
||||
endif
|
||||
" 1.b.4. Return type
|
||||
let return_value = call.dig('callee.details.function.return_value', [])
|
||||
if !empty(return_value)
|
||||
let return_type = ' -> '.return_value[0].type
|
||||
endif
|
||||
|
||||
elseif kind ==# 'type'
|
||||
" 1.c.1. Parameters
|
||||
for parameter in call.dig('callee.details.type.language_details.python.constructor.parameters', [])
|
||||
" 1.c.1.a. Name
|
||||
let name = parameter.name
|
||||
" 1.c.1.b. Default value
|
||||
if kite#utils#present(parameter.language_details.python, 'default_value')
|
||||
let name .= '='.parameter.language_details.python.default_value[0].repr
|
||||
endif
|
||||
" 2. Highlight current argument
|
||||
if !in_kwargs && len(parameters) == current_arg
|
||||
let name = '*'.name.'*'
|
||||
endif
|
||||
call add(parameters, name)
|
||||
endfor
|
||||
" 1.c.2. vararg indicator
|
||||
let vararg = call.dig('callee.details.type.language_details.python.constructor.language_details.python.vararg', {})
|
||||
if !empty(vararg)
|
||||
call add(parameters, '*'.vararg.name)
|
||||
endif
|
||||
" 1.c.3. keyword arguments indicator
|
||||
let kwarg = call.dig('callee.details.type.language_details.python.constructor.language_details.python.kwarg', {})
|
||||
if !empty(kwarg)
|
||||
call add(parameters, '*'.kwarg.name)
|
||||
endif
|
||||
" 1.c.4. Return type
|
||||
let return_type = ' -> '.function_name
|
||||
endif
|
||||
|
||||
" The completion popup does not wrap long lines so we wrap manually.
|
||||
for line in kite#utils#wrap(kite#symbol().' '.function_name.'('.join(parameters, ', ').')'.return_type, wrap_width, 4)
|
||||
let completion = {
|
||||
\ 'word': '',
|
||||
\ 'abbr': line,
|
||||
\ 'empty': 1,
|
||||
\ 'dup': 1
|
||||
\ }
|
||||
call add(completions, completion)
|
||||
endfor
|
||||
|
||||
|
||||
" 3. Keyword arguments
|
||||
let kwarg_parameters = call.dig('callee.details.function.kwarg_parameters', [])
|
||||
if !empty(kwarg_parameters)
|
||||
call add(completions, spacer)
|
||||
call add(completions, s:heading('**kw'))
|
||||
|
||||
for kwarg in kwarg_parameters
|
||||
let name = kwarg.name
|
||||
let types = kite#utils#map_join(kwarg.inferred_value, 'repr', '|')
|
||||
if empty(types)
|
||||
let types = ''
|
||||
endif
|
||||
|
||||
call add(completions, {
|
||||
\ 'word': name.'=',
|
||||
\ 'abbr': indent.name,
|
||||
\ 'menu': types,
|
||||
\ 'empty': 1,
|
||||
\ 'dup': 1
|
||||
\ })
|
||||
endfor
|
||||
endif
|
||||
|
||||
|
||||
" 4. Popular patterns
|
||||
if kite#signature#should_show_popular_patterns()
|
||||
let signatures = call.dig('signatures', [])
|
||||
if len(signatures) > 0
|
||||
call add(completions, spacer)
|
||||
call add(completions, s:heading('How Others Used This'))
|
||||
endif
|
||||
|
||||
for signature in signatures
|
||||
let sigdoc = g:kite#document#Document.New(signature)
|
||||
|
||||
" b. Arguments
|
||||
let arguments = []
|
||||
for arg in sigdoc.dig('args', [])
|
||||
call add(arguments, arg.name)
|
||||
endfor
|
||||
|
||||
" c. Keyword arguments
|
||||
for kwarg in sigdoc.dig('language_details.python.kwargs', [])
|
||||
let name = kwarg.name
|
||||
let examples = kite#utils#coerce(kwarg.types[0], 'examples', [])
|
||||
if len(examples) > 0
|
||||
let name .= '='.examples[0]
|
||||
endif
|
||||
call add(arguments, name)
|
||||
endfor
|
||||
|
||||
|
||||
for line in kite#utils#wrap(function_name.'('.join(arguments, ', ').')', wrap_width, 2)
|
||||
let completion = {
|
||||
\ 'word': '',
|
||||
\ 'abbr': indent.line,
|
||||
\ 'empty': 1,
|
||||
\ 'equal': 1,
|
||||
\ 'dup': 1
|
||||
\ }
|
||||
call add(completions, completion)
|
||||
endfor
|
||||
endfor
|
||||
endif
|
||||
|
||||
if mode(1) ==# 'i'
|
||||
call complete(a:startcol+1, completions)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#signature#should_show_popular_patterns()
|
||||
return kite#utils#get_setting('show_popular_patterns', 0)
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
function! kite#signature#show_popular_patterns()
|
||||
call kite#utils#set_setting('show_popular_patterns', 1)
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#signature#hide_popular_patterns()
|
||||
call kite#utils#set_setting('show_popular_patterns', 0)
|
||||
endfunction
|
||||
|
||||
|
||||
function s:heading(text)
|
||||
return {'abbr': a:text.':', 'word': '', 'empty': 1, 'dup': 1}
|
||||
endfunction
|
||||
|
|
@ -1,413 +0,0 @@
|
|||
function! s:setup_stack()
|
||||
if exists('b:kite_stack') | return | endif
|
||||
|
||||
" stack:
|
||||
" [
|
||||
" { index: 0, placeholders: { ... } }, <-- depth 0
|
||||
" { index: 0, placeholders: { ... } }, <-- depth 1
|
||||
" ... <-- depth n
|
||||
" ]
|
||||
"
|
||||
" index - the currently active placeholder at that depth
|
||||
let b:kite_stack = {'stack': []}
|
||||
|
||||
function! b:kite_stack.pop()
|
||||
return remove(self.stack, -1)
|
||||
endfunction
|
||||
|
||||
function! b:kite_stack.peek()
|
||||
return get(self.stack, -1)
|
||||
endfunction
|
||||
|
||||
function! b:kite_stack.push(item)
|
||||
call add(self.stack, a:item)
|
||||
endfunction
|
||||
|
||||
function! b:kite_stack.is_empty()
|
||||
return empty(self.stack)
|
||||
endfunction
|
||||
|
||||
function! b:kite_stack.empty()
|
||||
let self.stack = []
|
||||
endfunction
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#snippet#complete_done()
|
||||
if empty(v:completed_item) | return | endif
|
||||
call s:setup_stack()
|
||||
|
||||
if has_key(v:completed_item, 'user_data') && !empty(v:completed_item.user_data)
|
||||
let placeholders = json_decode(v:completed_item.user_data).placeholders
|
||||
elseif exists('b:kite_completions') && has_key(b:kite_completions, v:completed_item.word)
|
||||
let placeholders = json_decode(b:kite_completions[v:completed_item.word]).placeholders
|
||||
let b:kite_completions = {}
|
||||
else
|
||||
return
|
||||
endif
|
||||
|
||||
" Send the edit event. Normally this is sent automatically on TextChanged(I).
|
||||
" But for some reason this doesn't fire when a completion has a snippet placeholder.
|
||||
call kite#events#event('edit')
|
||||
|
||||
if empty(placeholders)
|
||||
if b:kite_stack.is_empty()
|
||||
return
|
||||
else
|
||||
call kite#snippet#next_placeholder()
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
let b:kite_linenr = line('.')
|
||||
let b:kite_line_length = col('$')
|
||||
|
||||
call s:setup_maps()
|
||||
call s:setup_autocmds()
|
||||
|
||||
" Calculate column number (col_begin) of start of each placeholder, and placeholder length.
|
||||
let inserted_text = v:completed_item.word
|
||||
let insertion_start = col('.') - strdisplaywidth(inserted_text)
|
||||
let b:kite_insertion_end = col('.')
|
||||
|
||||
for ph in placeholders
|
||||
let ph.col_begin = insertion_start + ph.begin
|
||||
let ph.length = ph.end - ph.begin
|
||||
unlet ph.begin ph.end
|
||||
endfor
|
||||
|
||||
" Update placeholder locations.
|
||||
"
|
||||
" todo move this into the push() function?
|
||||
" note this is very similar to s:update_placeholder_locations()
|
||||
if !b:kite_stack.is_empty()
|
||||
" current placeholder which has just been completed
|
||||
let level = b:kite_stack.peek()
|
||||
let ph = level.placeholders[level.index]
|
||||
let ph_new_length = col('.') - ph.col_begin
|
||||
let ph_length_delta = ph_new_length - ph.length
|
||||
let ph.length = ph_new_length
|
||||
let marker = ph.col_begin
|
||||
|
||||
" following placeholders at same level
|
||||
for ph in level.placeholders[level.index+1:]
|
||||
let ph.col_begin += ph_length_delta
|
||||
endfor
|
||||
|
||||
" placeholders at outer levels
|
||||
for level in b:kite_stack.stack[:-2]
|
||||
for ph in level.placeholders
|
||||
if ph.col_begin > marker
|
||||
let ph.col_begin += ph_length_delta
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
endif
|
||||
|
||||
call b:kite_stack.push({'placeholders': placeholders, 'index': 0})
|
||||
|
||||
" Move to first placeholder.
|
||||
call s:placeholder(0)
|
||||
endfunction
|
||||
|
||||
|
||||
" Go to next placeholder at current level, if there is one, or first placeholder at next level otherwise.
|
||||
function! kite#snippet#next_placeholder()
|
||||
call s:update_placeholder_locations()
|
||||
call s:placeholder(b:kite_stack.peek().index + 1)
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
function! kite#snippet#previous_placeholder(...)
|
||||
call s:placeholder(b:kite_stack.peek().index - 1 - (a:0 ? a:1 : 0))
|
||||
endfunction
|
||||
|
||||
|
||||
" Move to the placeholder at index and select its text.
|
||||
function! s:placeholder(index)
|
||||
let index = a:index
|
||||
|
||||
let level = b:kite_stack.peek()
|
||||
let placeholders = level.placeholders
|
||||
|
||||
" Clear highlights before we pop the stack.
|
||||
call s:clear_all_placeholder_highlights()
|
||||
|
||||
if index < 0
|
||||
" If no other levels in stack
|
||||
if len(b:kite_stack.stack) == 1
|
||||
" Stay with first placeholder and proceed
|
||||
let index = 0
|
||||
else
|
||||
call b:kite_stack.pop()
|
||||
call s:placeholder(b:kite_stack.peek().index - 1)
|
||||
return
|
||||
endif
|
||||
endif
|
||||
|
||||
" if navigating forward from last placeholder of current level
|
||||
if index == len(placeholders)
|
||||
" If no other levels in stack
|
||||
if len(b:kite_stack.stack) == 1
|
||||
call s:goto_initial_completion_end()
|
||||
else
|
||||
call b:kite_stack.pop()
|
||||
call s:placeholder(b:kite_stack.peek().index + 1)
|
||||
endif
|
||||
return
|
||||
endif
|
||||
|
||||
call s:highlight_current_level_placeholders()
|
||||
|
||||
let level.index = index
|
||||
let ph = placeholders[index]
|
||||
|
||||
" store line length before placeholder gets changed by user
|
||||
" let b:kite_line_length = col('$')
|
||||
|
||||
if ph.length == 0
|
||||
normal! h
|
||||
return
|
||||
endif
|
||||
|
||||
" insert mode -> normal mode
|
||||
stopinsert
|
||||
|
||||
let linenr = line('.')
|
||||
call setpos("'<", [0, linenr, ph.col_begin])
|
||||
call setpos("'>", [0, linenr, ph.col_begin + ph.length - (mode() == 'n' ? 1 : 0)])
|
||||
" normal mode -> visual mode -> select mode
|
||||
execute "normal! gv\<C-G>"
|
||||
if mode() ==# 'S'
|
||||
execute "normal! \<C-O>gh"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:goto_initial_completion_end()
|
||||
" call setpos('.', [0, b:kite_linenr, b:kite_insertion_end + col('$') - b:kite_line_length - 1])
|
||||
call setpos('.', [0, b:kite_linenr, col('$')])
|
||||
startinsert!
|
||||
call s:teardown()
|
||||
endfunction
|
||||
|
||||
|
||||
" Adjust current and subsequent placeholders for the amount of text entered
|
||||
" at the placeholder we are leaving.
|
||||
function! s:update_placeholder_locations()
|
||||
if !exists('b:kite_line_length') | return | endif
|
||||
|
||||
let line_length_delta = col('$') - b:kite_line_length
|
||||
|
||||
" current placeholder
|
||||
let level = b:kite_stack.peek()
|
||||
let ph = level.placeholders[level.index]
|
||||
let marker = ph.col_begin
|
||||
let ph.length += line_length_delta
|
||||
|
||||
" subsequent placeholders at current level
|
||||
for ph in level.placeholders[level.index+1:]
|
||||
let ph.col_begin += line_length_delta
|
||||
endfor
|
||||
|
||||
" placeholders at outer levels
|
||||
for level in b:kite_stack.stack[:-2]
|
||||
for ph in level.placeholders
|
||||
if ph.col_begin > marker
|
||||
let ph.col_begin += line_length_delta
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
|
||||
let b:kite_line_length = col('$')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:highlight_current_level_placeholders()
|
||||
let group = s:highlight_group_for_placeholders()
|
||||
if empty(group) | return | endif
|
||||
|
||||
let linenr = line('.')
|
||||
for ph in b:kite_stack.peek().placeholders
|
||||
let ph.matchid = matchaddpos(group, [[linenr, ph.col_begin, ph.length]])
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
|
||||
" Clears highlights of placeholders in the stack.
|
||||
"
|
||||
" Note: if we need a way to clear highlights of placeholders which are no
|
||||
" longer in the stack (because they have been popped) we could use a custom
|
||||
" highlight group (e.g. KiteUnderline linked to Underline), call getmatches(),
|
||||
" and remove all matches using the custom highlight group.
|
||||
function! s:clear_all_placeholder_highlights()
|
||||
for level in b:kite_stack.stack
|
||||
for ph in level.placeholders
|
||||
if has_key(ph, 'matchid')
|
||||
call matchdelete(ph.matchid)
|
||||
unlet ph.matchid
|
||||
endif
|
||||
endfor
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
|
||||
" Many plugins use vmap for visual-mode mappings but vmap maps both
|
||||
" visual-mode and select-mode (they should use xmap instead). Assume any
|
||||
" visual-mode mappings for printable characters are not wanted and remove them
|
||||
" (but remember them so we can restore them afterwards). Similarly for map.
|
||||
" Assume any select-only-mode maps are deliberate.
|
||||
"
|
||||
" :help mapmode-s
|
||||
" :help Select-mode-mapping
|
||||
function! s:remove_smaps_for_printable_characters()
|
||||
let b:kite_maps = []
|
||||
let printable_keycodes = [
|
||||
\ '<Space>',
|
||||
\ '<Bslash>',
|
||||
\ '<Tab>',
|
||||
\ '<C-Tab>',
|
||||
\ '<NL>',
|
||||
\ '<CR>',
|
||||
\ '<BS>',
|
||||
\ '<Leader>',
|
||||
\ '<LocalLeader>'
|
||||
\ ]
|
||||
|
||||
" Get a list of maps active in select mode.
|
||||
for scope in ['<buffer>', '']
|
||||
redir => maps | silent execute 'smap' scope | redir END
|
||||
|
||||
let mappings = split(maps, "\n")
|
||||
|
||||
" 'No mapping found' or localised equivalent (starts with capital letter).
|
||||
if len(mappings) == 1 && mappings[0][0] =~ '\u' | continue | endif
|
||||
|
||||
" Assume select-mode maps are deliberate and ignore them.
|
||||
call filter(mappings, 'v:val[0:2] !~# "s"')
|
||||
|
||||
for mapping in mappings
|
||||
let lhs = matchlist(mapping, '\v^...(\S+)\s.*')[1]
|
||||
" ^^^ ^^^
|
||||
" mode lhs
|
||||
|
||||
" Ignore keycodes for non-printable characters, e.g. <Left>
|
||||
if lhs[0] == '<' && index(printable_keycodes, lhs) == -1 | continue | endif
|
||||
|
||||
" Remember the mapping so we can restore it later.
|
||||
call add(b:kite_maps, maparg(lhs, 's', 0, 1))
|
||||
|
||||
" Remove the mapping.
|
||||
silent! execute 'sunmap' scope lhs
|
||||
endfor
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:restore_smaps()
|
||||
for mapping in b:kite_maps
|
||||
silent! execute mapping.mode . (mapping.noremap ? 'nore' : '') . 'map '
|
||||
\ . (mapping.buffer ? '<buffer> ' : '')
|
||||
\ . (mapping.expr ? '<expr> ' : '')
|
||||
\ . (mapping.nowait ? '<nowait> ' : '')
|
||||
\ . (mapping.silent ? '<silent> ' : '')
|
||||
\ . mapping.lhs . ' '
|
||||
\ . substitute(mapping.rhs, '<SID>', '<SNR>'.mapping.sid.'_', 'g')
|
||||
endfor
|
||||
|
||||
unlet! b:kite_maps
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:setup_maps()
|
||||
execute 'inoremap <buffer> <silent> <expr>' g:kite_next_placeholder 'pumvisible() ? "<C-Y>" : "<C-\><C-O>:call kite#snippet#next_placeholder()<CR>"'
|
||||
execute 'inoremap <buffer> <silent> <expr>' g:kite_previous_placeholder 'pumvisible() ? "<C-Y><C-G>:<C-U>call kite#snippet#previous_placeholder(2)<CR>" : "<C-\><C-O>:call kite#snippet#previous_placeholder()<CR>"'
|
||||
execute 'snoremap <buffer> <silent>' g:kite_next_placeholder '<Esc>:call kite#snippet#next_placeholder()<CR>'
|
||||
execute 'snoremap <buffer> <silent>' g:kite_previous_placeholder '<Esc>:call kite#snippet#previous_placeholder()<CR>'
|
||||
|
||||
call s:remove_smaps_for_printable_characters()
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#snippet#teardown_maps()
|
||||
execute 'silent! iunmap <buffer>' g:kite_next_placeholder
|
||||
execute 'silent! iunmap <buffer>' g:kite_previous_placeholder
|
||||
execute 'silent! sunmap <buffer>' g:kite_next_placeholder
|
||||
execute 'silent! sunmap <buffer>' g:kite_previous_placeholder
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:setup_autocmds()
|
||||
augroup KiteSnippets
|
||||
autocmd! * <buffer>
|
||||
|
||||
autocmd CursorMovedI <buffer>
|
||||
\ call s:update_placeholder_locations() |
|
||||
\ call s:clear_all_placeholder_highlights() |
|
||||
\ call s:highlight_current_level_placeholders()
|
||||
autocmd CursorMoved,CursorMovedI <buffer> call s:cursormoved()
|
||||
autocmd InsertLeave <buffer> call s:insertleave()
|
||||
augroup END
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:teardown_autocmds()
|
||||
autocmd! KiteSnippets * <buffer>
|
||||
endfunction
|
||||
|
||||
|
||||
" Called to deactivate all placeholders.
|
||||
function! s:teardown()
|
||||
call s:clear_all_placeholder_highlights()
|
||||
call kite#snippet#teardown_maps()
|
||||
call s:teardown_autocmds()
|
||||
call s:restore_smaps()
|
||||
call b:kite_stack.empty()
|
||||
unlet! b:kite_linenr b:kite_line_length b:kite_insertion_end
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:highlight_group_for_placeholders()
|
||||
for group in ['Special', 'SpecialKey', 'Underline', 'DiffChange']
|
||||
if hlexists(group)
|
||||
return group
|
||||
endif
|
||||
endfor
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:cursormoved()
|
||||
if !exists('b:kite_linenr') | return | endif
|
||||
if b:kite_linenr == line('.') | return | endif
|
||||
|
||||
" TODO check whether the cursor is outside the bounds of the completion?
|
||||
|
||||
call s:teardown()
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:insertleave()
|
||||
" Modes established by experimentation.
|
||||
if mode(1) !=# 's' && mode(1) !=# ((has('patch-8.1.0225') || has('nvim-0.4.0')) ? 'niI' : 'n')
|
||||
call s:teardown()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:debug_stack()
|
||||
if b:kite_stack.is_empty()
|
||||
echom 'stack empty'
|
||||
return
|
||||
endif
|
||||
let i = 0
|
||||
for level in b:kite_stack.stack
|
||||
echom 'level' i
|
||||
echom ' index' level.index
|
||||
for pholder in level.placeholders
|
||||
echom ' '.string(pholder)
|
||||
endfor
|
||||
let i += 1
|
||||
endfor
|
||||
endfunction
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
" Updates the status of the current buffer.
|
||||
"
|
||||
" Optional argument is a timer id (when called by a timer).
|
||||
function! kite#status#status(...)
|
||||
if !s:status_in_status_line() | return | endif
|
||||
|
||||
let buf = bufnr('')
|
||||
let msg = 'NOT SET'
|
||||
|
||||
" Check kited status (installed / running) every 10 file status checks.
|
||||
let counter = getbufvar(buf, 'kite_status_counter', 0)
|
||||
if counter == 0
|
||||
if !kite#utils#kite_running()
|
||||
let msg = 'Kite: not running'
|
||||
if !kite#utils#kite_installed()
|
||||
let msg = 'Kite: not installed'
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
call setbufvar(buf, 'kite_status_counter', (counter + 1) % 10)
|
||||
|
||||
if wordcount().bytes > kite#max_file_size()
|
||||
let msg = 'Kite: file too large'
|
||||
endif
|
||||
|
||||
if msg !=# 'NOT SET'
|
||||
if msg !=# getbufvar(buf, 'kite_status')
|
||||
call setbufvar(buf, 'kite_status', msg)
|
||||
redrawstatus
|
||||
endif
|
||||
return
|
||||
endif
|
||||
|
||||
let filename = kite#utils#filepath(0)
|
||||
call kite#client#status(filename, function('kite#status#handler', [buf]))
|
||||
endfunction
|
||||
|
||||
|
||||
function! kite#status#handler(buffer, response)
|
||||
call kite#utils#log('kite status status: '.a:response.status.', body: '.a:response.body)
|
||||
if a:response.status != 200 | return | endif
|
||||
|
||||
let json = json_decode(a:response.body)
|
||||
|
||||
let msg = ''
|
||||
|
||||
let suffix = get(json, 'short', 'FIELD MISSING')
|
||||
if suffix !=# 'FIELD MISSING'
|
||||
let msg = join(['Kite: ', suffix], '')
|
||||
endif
|
||||
|
||||
if msg !=# getbufvar(a:buffer, 'kite_status')
|
||||
call setbufvar(a:buffer, 'kite_status', msg)
|
||||
redrawstatus
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:status_in_status_line()
|
||||
return stridx(&statusline, 'kite#statusline()') != -1
|
||||
endfunction
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
*kite.txt* Kite for VIM
|
||||
|
||||
|
||||
Kite for VIM
|
||||
============
|
||||
|
||||
VIM is now integrated with Kite! To get a taste of what Kite can do, open a
|
||||
saved Python file and start coding away.
|
||||
|
||||
1. Autocompletions
|
||||
|
||||
As you code, Kite will provide autocompletion suggestions ranked by popularity
|
||||
using all the open source code on GitHub.
|
||||
|
||||
2. Documentation
|
||||
|
||||
Press |K| when your cursor is over a identifier to open a split window with
|
||||
documentation about the identifier. In addition to documentation, Kite also
|
||||
provides information about where you've used the identifier in your codebase,
|
||||
as well as curated code examples showing you how to use the identifier.
|
||||
|
||||
3. Goto Definition
|
||||
|
||||
Press |C-]| to jump to a method's defintion.
|
||||
|
||||
4. Copilot integration
|
||||
|
||||
While you code in VIM, the Copilot will automatically show you information
|
||||
about the code that you're currently working with. To open the Copilot, click
|
||||
on the Kite menubar icon and select "Open Copilot".
|
||||
|
||||
To learn more about Kite and how to use the VIM plugin, visit our [help
|
||||
page](http://help.kite.com).
|
||||
|
||||
vim:tw=78:et:ft=help:norl
|
||||
Loading…
Reference in New Issue