convert to vim9
This commit is contained in:
3
vim/.config/vim/.netrwhist
Normal file
3
vim/.config/vim/.netrwhist
Normal file
@@ -0,0 +1,3 @@
|
||||
let g:netrw_dirhistmax =10
|
||||
let g:netrw_dirhistcnt =1
|
||||
let g:netrw_dirhist_1='/home/cli'
|
||||
2
vim/.config/vim/pack/plugins/start/copilot.vim/.gitattributes
vendored
Normal file
2
vim/.config/vim/pack/plugins/start/copilot.vim/.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.vim eol=lf
|
||||
/copilot-language-server/** -whitespace -diff
|
||||
1
vim/.config/vim/pack/plugins/start/copilot.vim/.github/pull_request_template.md
vendored
Normal file
1
vim/.config/vim/pack/plugins/start/copilot.vim/.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
At the moment we are not accepting contributions to the repository.
|
||||
20
vim/.config/vim/pack/plugins/start/copilot.vim/.github/workflows/auto-close-pr.yml
vendored
Normal file
20
vim/.config/vim/pack/plugins/start/copilot.vim/.github/workflows/auto-close-pr.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: Auto-close PR
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened]
|
||||
|
||||
jobs:
|
||||
close:
|
||||
name: Run
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- run: |
|
||||
gh pr close ${{ github.event.pull_request.number }} --comment \
|
||||
"At the moment we are not accepting contributions to the repository.
|
||||
|
||||
Feedback for Copilot.vim can be given in the [feedback forum](https://github.com/github/copilot.vim/issues)."
|
||||
env:
|
||||
GH_REPO: ${{ github.repository }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
1
vim/.config/vim/pack/plugins/start/copilot.vim/.gitignore
vendored
Normal file
1
vim/.config/vim/pack/plugins/start/copilot.vim/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/doc/tags
|
||||
@@ -0,0 +1,4 @@
|
||||
GitHub Copilot is offered under the [GitHub Terms of
|
||||
Service](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#github-copilot).
|
||||
|
||||
Copyright (C) 2023 GitHub, Inc. - All Rights Reserved.
|
||||
63
vim/.config/vim/pack/plugins/start/copilot.vim/README.md
Normal file
63
vim/.config/vim/pack/plugins/start/copilot.vim/README.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# GitHub Copilot for Vim and Neovim
|
||||
|
||||
GitHub Copilot is an AI pair programmer tool that helps you write code faster
|
||||
and smarter. Trained on billions of lines of public code, GitHub Copilot turns
|
||||
natural language prompts including comments and method names into coding
|
||||
suggestions across dozens of languages.
|
||||
|
||||
Copilot.vim is a Vim/Neovim plugin for GitHub Copilot.
|
||||
|
||||
To learn more, visit
|
||||
[https://github.com/features/copilot](https://github.com/features/copilot).
|
||||
|
||||
## Getting access to GitHub Copilot
|
||||
|
||||
To access GitHub Copilot, an active GitHub Copilot subscription is required.
|
||||
Sign up for [GitHub Copilot Free](https://github.com/settings/copilot), or
|
||||
request access from your enterprise admin.
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Install [Neovim][] or the latest patch of [Vim][] (9.0.0185 or newer).
|
||||
|
||||
2. Install [Node.js][]. If you use a package manager, make sure to install
|
||||
NPM as well (e.g., `apt install nodejs npm` on Debian/Ubuntu).
|
||||
|
||||
3. Install `github/copilot.vim` using vim-plug, lazy.nvim, or any other
|
||||
plugin manager. Or to install manually, run one of the following
|
||||
commands:
|
||||
|
||||
* Vim, Linux/macOS:
|
||||
|
||||
git clone --depth=1 https://github.com/github/copilot.vim.git \
|
||||
~/.vim/pack/github/start/copilot.vim
|
||||
|
||||
* Neovim, Linux/macOS:
|
||||
|
||||
git clone --depth=1 https://github.com/github/copilot.vim.git \
|
||||
~/.config/nvim/pack/github/start/copilot.vim
|
||||
|
||||
* Vim, Windows (PowerShell command):
|
||||
|
||||
git clone --depth=1 https://github.com/github/copilot.vim.git `
|
||||
$HOME/vimfiles/pack/github/start/copilot.vim
|
||||
|
||||
* Neovim, Windows (PowerShell command):
|
||||
|
||||
git clone --depth=1 https://github.com/github/copilot.vim.git `
|
||||
$HOME/AppData/Local/nvim/pack/github/start/copilot.vim
|
||||
|
||||
4. Start Vim/Neovim and invoke `:Copilot setup`.
|
||||
|
||||
[Node.js]: https://nodejs.org/en/download/
|
||||
[Neovim]: https://github.com/neovim/neovim/releases/latest
|
||||
[Vim]: https://github.com/vim/vim
|
||||
|
||||
Suggestions are displayed inline and can be accepted by pressing the tab key.
|
||||
See `:help copilot` for more information.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
We’d love to get your help in making GitHub Copilot better! If you have
|
||||
feedback or encounter any problems, please reach out on our [feedback
|
||||
forum](https://github.com/github/copilot.vim/issues).
|
||||
@@ -0,0 +1,4 @@
|
||||
If you discover a security issue in this repo, please submit it through the
|
||||
[GitHub Security Bug Bounty](https://hackerone.com/github).
|
||||
|
||||
Thanks for helping make GitHub Copilot safe for everyone.
|
||||
@@ -0,0 +1,859 @@
|
||||
scriptencoding utf-8
|
||||
|
||||
let s:has_nvim_ghost_text = has('nvim-0.8')
|
||||
let s:vim_minimum_version = '9.0.0185'
|
||||
let s:has_vim_ghost_text = has('patch-' . s:vim_minimum_version) && has('textprop')
|
||||
let s:has_ghost_text = s:has_nvim_ghost_text || s:has_vim_ghost_text
|
||||
|
||||
let s:hlgroup = 'CopilotSuggestion'
|
||||
let s:annot_hlgroup = 'CopilotAnnotation'
|
||||
|
||||
if s:has_vim_ghost_text && empty(prop_type_get(s:hlgroup))
|
||||
call prop_type_add(s:hlgroup, {'highlight': s:hlgroup})
|
||||
endif
|
||||
if s:has_vim_ghost_text && empty(prop_type_get(s:annot_hlgroup))
|
||||
call prop_type_add(s:annot_hlgroup, {'highlight': s:annot_hlgroup})
|
||||
endif
|
||||
|
||||
function! s:Echo(msg) abort
|
||||
if has('nvim') && &cmdheight == 0
|
||||
call v:lua.vim.notify(a:msg, v:null, {'title': 'GitHub Copilot'})
|
||||
else
|
||||
echo a:msg
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#Init(...) abort
|
||||
call copilot#util#Defer({ -> exists('s:client') || s:Start() })
|
||||
endfunction
|
||||
|
||||
function! s:Running() abort
|
||||
return exists('s:client.job') || exists('s:client.client_id')
|
||||
endfunction
|
||||
|
||||
function! s:Start() abort
|
||||
if s:Running() || exists('s:client.startup_error')
|
||||
return
|
||||
endif
|
||||
let s:client = copilot#client#New()
|
||||
endfunction
|
||||
|
||||
function! s:Stop() abort
|
||||
if exists('s:client')
|
||||
let client = remove(s:, 'client')
|
||||
call client.Close()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#Client() abort
|
||||
call s:Start()
|
||||
return s:client
|
||||
endfunction
|
||||
|
||||
function! copilot#RunningClient() abort
|
||||
if s:Running()
|
||||
return s:client
|
||||
else
|
||||
return v:null
|
||||
endif
|
||||
endfunction
|
||||
|
||||
if has('nvim-0.8') && !has(luaeval('vim.version().api_prerelease') ? 'nvim-0.9.1' : 'nvim-0.9.0')
|
||||
let s:editor_warning = 'Neovim 0.8 support is deprecated and will be dropped in a future release of copilot.vim.'
|
||||
endif
|
||||
if has('vim_starting') && exists('s:editor_warning')
|
||||
call copilot#logger#Warn(s:editor_warning)
|
||||
endif
|
||||
function! s:EditorVersionWarning() abort
|
||||
if exists('s:editor_warning')
|
||||
echohl WarningMsg
|
||||
echo 'Warning: ' . s:editor_warning
|
||||
echohl None
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#Request(method, params, ...) abort
|
||||
let client = copilot#Client()
|
||||
return call(client.Request, [a:method, a:params] + a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#Call(method, params, ...) abort
|
||||
let client = copilot#Client()
|
||||
return call(client.Call, [a:method, a:params] + a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#Notify(method, params, ...) abort
|
||||
let client = copilot#Client()
|
||||
return call(client.Notify, [a:method, a:params] + a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#NvimNs() abort
|
||||
return nvim_create_namespace('github-copilot')
|
||||
endfunction
|
||||
|
||||
function! copilot#Clear() abort
|
||||
if exists('g:_copilot_timer')
|
||||
call timer_stop(remove(g:, '_copilot_timer'))
|
||||
endif
|
||||
if exists('b:_copilot')
|
||||
call copilot#client#Cancel(get(b:_copilot, 'first', {}))
|
||||
call copilot#client#Cancel(get(b:_copilot, 'cycling', {}))
|
||||
endif
|
||||
call s:UpdatePreview()
|
||||
unlet! b:_copilot
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! copilot#Dismiss() abort
|
||||
call copilot#Clear()
|
||||
call s:UpdatePreview()
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
let s:filetype_defaults = {
|
||||
\ 'gitcommit': 0,
|
||||
\ 'gitrebase': 0,
|
||||
\ 'hgcommit': 0,
|
||||
\ 'svn': 0,
|
||||
\ 'cvs': 0,
|
||||
\ '.': 0}
|
||||
|
||||
function! s:BufferDisabled() abort
|
||||
if &buftype =~# '^\%(help\|prompt\|quickfix\|terminal\)$'
|
||||
return 5
|
||||
endif
|
||||
if exists('b:copilot_disabled')
|
||||
return empty(b:copilot_disabled) ? 0 : 3
|
||||
endif
|
||||
if exists('b:copilot_enabled')
|
||||
return empty(b:copilot_enabled) ? 4 : 0
|
||||
endif
|
||||
let short = empty(&l:filetype) ? '.' : split(&l:filetype, '\.', 1)[0]
|
||||
let config = {}
|
||||
if type(get(g:, 'copilot_filetypes')) == v:t_dict
|
||||
let config = g:copilot_filetypes
|
||||
endif
|
||||
if has_key(config, &l:filetype)
|
||||
return empty(config[&l:filetype])
|
||||
elseif has_key(config, short)
|
||||
return empty(config[short])
|
||||
elseif has_key(config, '*')
|
||||
return empty(config['*'])
|
||||
else
|
||||
return get(s:filetype_defaults, short, 1) == 0 ? 2 : 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#Enabled() abort
|
||||
return get(g:, 'copilot_enabled', 1)
|
||||
\ && empty(s:BufferDisabled())
|
||||
endfunction
|
||||
|
||||
let s:inline_invoked = 1
|
||||
let s:inline_automatic = 2
|
||||
|
||||
function! copilot#Complete(...) abort
|
||||
if exists('g:_copilot_timer')
|
||||
call timer_stop(remove(g:, '_copilot_timer'))
|
||||
endif
|
||||
let target = [bufnr(''), getbufvar('', 'changedtick'), line('.'), col('.')]
|
||||
if !exists('b:_copilot.target') || b:_copilot.target !=# target
|
||||
if exists('b:_copilot.first')
|
||||
call copilot#client#Cancel(b:_copilot.first)
|
||||
endif
|
||||
if exists('b:_copilot.cycling')
|
||||
call copilot#client#Cancel(b:_copilot.cycling)
|
||||
endif
|
||||
let params = {
|
||||
\ 'textDocument': {'uri': bufnr('')},
|
||||
\ 'position': copilot#util#AppendPosition(),
|
||||
\ 'formattingOptions': {'insertSpaces': &expandtab ? v:true : v:false, 'tabSize': shiftwidth()},
|
||||
\ 'context': {'triggerKind': s:inline_automatic}}
|
||||
let b:_copilot = {
|
||||
\ 'target': target,
|
||||
\ 'params': params,
|
||||
\ 'first': copilot#Request('textDocument/inlineCompletion', params)}
|
||||
let g:_copilot_last = b:_copilot
|
||||
endif
|
||||
let completion = b:_copilot.first
|
||||
if !a:0
|
||||
return completion.Await()
|
||||
else
|
||||
call copilot#client#Result(completion, function(a:1, [b:_copilot]))
|
||||
if a:0 > 1
|
||||
call copilot#client#Error(completion, function(a:2, [b:_copilot]))
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:HideDuringCompletion() abort
|
||||
return get(g:, 'copilot_hide_during_completion', 1)
|
||||
endfunction
|
||||
|
||||
function! s:SuggestionTextWithAdjustments() abort
|
||||
let empty = ['', 0, '', {}]
|
||||
try
|
||||
if mode() !~# '^[iR]' || (s:HideDuringCompletion() && pumvisible()) || !exists('b:_copilot.suggestions')
|
||||
return empty
|
||||
endif
|
||||
let choice = get(b:_copilot.suggestions, b:_copilot.choice, {})
|
||||
if !has_key(choice, 'range') || choice.range.start.line != line('.') - 1 || type(choice.insertText) !=# v:t_string
|
||||
return empty
|
||||
endif
|
||||
let line = getline('.')
|
||||
let offset = col('.') - 1
|
||||
let byte_offset = copilot#util#UTF16ToByteIdx(line, choice.range.start.character)
|
||||
let choice_text = strpart(line, 0, byte_offset) .
|
||||
\ substitute(substitute(choice.insertText, '\r\n\=', '\n', 'g'), '\n*$', '', '')
|
||||
let typed = strpart(line, 0, offset)
|
||||
let end_offset = copilot#util#UTF16ToByteIdx(line, choice.range.end.character)
|
||||
if end_offset < 0
|
||||
let end_offset = len(line)
|
||||
endif
|
||||
let delete = strpart(line, offset, end_offset - offset)
|
||||
if typed =~# '^\s*$'
|
||||
let leading = strpart(matchstr(choice_text, '^\s\+'), 0, len(typed))
|
||||
let unindented = strpart(choice_text, len(leading))
|
||||
if strpart(typed, 0, len(leading)) ==# leading && unindented !=# delete
|
||||
return [unindented, len(typed) - len(leading), delete, choice]
|
||||
endif
|
||||
elseif typed ==# strpart(choice_text, 0, offset)
|
||||
return [strpart(choice_text, offset), 0, delete, choice]
|
||||
endif
|
||||
catch
|
||||
call copilot#logger#Exception()
|
||||
endtry
|
||||
return empty
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:Advance(count, context, ...) abort
|
||||
if a:context isnot# get(b:, '_copilot', {})
|
||||
return
|
||||
endif
|
||||
let a:context.choice += a:count
|
||||
if a:context.choice < 0
|
||||
let a:context.choice += len(a:context.suggestions)
|
||||
endif
|
||||
let a:context.choice %= len(a:context.suggestions)
|
||||
call s:UpdatePreview()
|
||||
endfunction
|
||||
|
||||
function! s:GetSuggestionsCyclingCallback(context, result) abort
|
||||
let callbacks = remove(a:context, 'cycling_callbacks')
|
||||
let seen = {}
|
||||
for suggestion in a:context.suggestions
|
||||
let seen[suggestion.insertText] = 1
|
||||
endfor
|
||||
for suggestion in get(a:result, 'items', [])
|
||||
if !has_key(seen, suggestion.insertText)
|
||||
call add(a:context.suggestions, suggestion)
|
||||
let seen[suggestion.insertText] = 1
|
||||
endif
|
||||
endfor
|
||||
for Callback in callbacks
|
||||
call Callback(a:context)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:GetSuggestionsCycling(callback) abort
|
||||
if exists('b:_copilot.cycling_callbacks')
|
||||
call add(b:_copilot.cycling_callbacks, a:callback)
|
||||
elseif exists('b:_copilot.cycling')
|
||||
call a:callback(b:_copilot)
|
||||
elseif exists('b:_copilot.suggestions')
|
||||
let params = deepcopy(b:_copilot.first.params)
|
||||
let params.context.triggerKind = s:inline_invoked
|
||||
let b:_copilot.cycling_callbacks = [a:callback]
|
||||
let b:_copilot.cycling = copilot#Request('textDocument/inlineCompletion',
|
||||
\ params,
|
||||
\ function('s:GetSuggestionsCyclingCallback', [b:_copilot]),
|
||||
\ function('s:GetSuggestionsCyclingCallback', [b:_copilot]),
|
||||
\ )
|
||||
call s:UpdatePreview()
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! copilot#Next() abort
|
||||
return s:GetSuggestionsCycling(function('s:Advance', [1]))
|
||||
endfunction
|
||||
|
||||
function! copilot#Previous() abort
|
||||
return s:GetSuggestionsCycling(function('s:Advance', [-1]))
|
||||
endfunction
|
||||
|
||||
function! copilot#GetDisplayedSuggestion() abort
|
||||
let [text, outdent, delete, item] = s:SuggestionTextWithAdjustments()
|
||||
|
||||
return {
|
||||
\ 'item': item,
|
||||
\ 'text': text,
|
||||
\ 'outdentSize': outdent,
|
||||
\ 'deleteSize': strchars(delete),
|
||||
\ 'deleteChars': delete}
|
||||
endfunction
|
||||
|
||||
function! s:ClearPreview() abort
|
||||
if s:has_nvim_ghost_text
|
||||
call nvim_buf_del_extmark(0, copilot#NvimNs(), 1)
|
||||
elseif s:has_vim_ghost_text
|
||||
call prop_remove({'type': s:hlgroup, 'all': v:true})
|
||||
call prop_remove({'type': s:annot_hlgroup, 'all': v:true})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:UpdatePreview() abort
|
||||
try
|
||||
let [text, outdent, delete_chars, item] = s:SuggestionTextWithAdjustments()
|
||||
let delete = strchars(delete_chars)
|
||||
let text = split(text, "\r\n\\=\\|\n", 1)
|
||||
if empty(text[-1])
|
||||
call remove(text, -1)
|
||||
endif
|
||||
if empty(text) || !s:has_ghost_text
|
||||
return s:ClearPreview()
|
||||
endif
|
||||
if exists('b:_copilot.cycling_callbacks')
|
||||
let annot = '(1/…)'
|
||||
elseif exists('b:_copilot.cycling')
|
||||
let annot = '(' . (b:_copilot.choice + 1) . '/' . len(b:_copilot.suggestions) . ')'
|
||||
else
|
||||
let annot = ''
|
||||
endif
|
||||
call s:ClearPreview()
|
||||
if s:has_nvim_ghost_text
|
||||
let data = {'id': 1}
|
||||
let data.virt_text_pos = 'overlay'
|
||||
let append = strpart(getline('.'), col('.') - 1 + delete)
|
||||
let data.virt_text = [[text[0] . append . repeat(' ', delete - len(text[0])), s:hlgroup]]
|
||||
if len(text) > 1
|
||||
let data.virt_lines = map(text[1:-1], { _, l -> [[l, s:hlgroup]] })
|
||||
if !empty(annot)
|
||||
let data.virt_lines[-1] += [[' '], [annot, s:annot_hlgroup]]
|
||||
endif
|
||||
elseif len(annot)
|
||||
let data.virt_text += [[' '], [annot, s:annot_hlgroup]]
|
||||
endif
|
||||
let data.hl_mode = 'combine'
|
||||
call nvim_buf_set_extmark(0, copilot#NvimNs(), line('.')-1, col('.')-1, data)
|
||||
elseif s:has_vim_ghost_text
|
||||
let new_suffix = text[0]
|
||||
let current_suffix = getline('.')[col('.') - 1 :]
|
||||
let inset = ''
|
||||
while delete > 0 && !empty(new_suffix)
|
||||
let last_char = matchstr(new_suffix, '.$')
|
||||
let new_suffix = matchstr(new_suffix, '^.\{-\}\ze.$')
|
||||
if last_char ==# matchstr(current_suffix, '.$')
|
||||
if !empty(inset)
|
||||
call prop_add(line('.'), col('.') + len(current_suffix), {'type': s:hlgroup, 'text': inset})
|
||||
let inset = ''
|
||||
endif
|
||||
let current_suffix = matchstr(current_suffix, '^.\{-\}\ze.$')
|
||||
let delete -= 1
|
||||
else
|
||||
let inset = last_char . inset
|
||||
endif
|
||||
endwhile
|
||||
if !empty(new_suffix . inset)
|
||||
call prop_add(line('.'), col('.'), {'type': s:hlgroup, 'text': new_suffix . inset})
|
||||
endif
|
||||
for line in text[1:]
|
||||
call prop_add(line('.'), 0, {'type': s:hlgroup, 'text_align': 'below', 'text': line})
|
||||
endfor
|
||||
if !empty(annot)
|
||||
call prop_add(line('.'), col('$'), {'type': s:annot_hlgroup, 'text': ' ' . annot})
|
||||
endif
|
||||
endif
|
||||
call copilot#Notify('textDocument/didShowCompletion', {'item': item})
|
||||
catch
|
||||
return copilot#logger#Exception()
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:HandleTriggerResult(state, result) abort
|
||||
let a:state.suggestions = type(a:result) == type([]) ? a:result : get(empty(a:result) ? {} : a:result, 'items', [])
|
||||
let a:state.choice = 0
|
||||
if get(b:, '_copilot') is# a:state
|
||||
call s:UpdatePreview()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:HandleTriggerError(state, result) abort
|
||||
let a:state.suggestions = []
|
||||
let a:state.choice = 0
|
||||
let a:state.error = a:result
|
||||
if get(b:, '_copilot') is# a:state
|
||||
call s:UpdatePreview()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#Suggest() abort
|
||||
if !s:Running()
|
||||
return ''
|
||||
endif
|
||||
try
|
||||
call copilot#Complete(function('s:HandleTriggerResult'), function('s:HandleTriggerError'))
|
||||
catch
|
||||
call copilot#logger#Exception()
|
||||
endtry
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:Trigger(bufnr, timer) abort
|
||||
let timer = get(g:, '_copilot_timer', -1)
|
||||
if a:bufnr !=# bufnr('') || a:timer isnot# timer || mode() !=# 'i'
|
||||
return
|
||||
endif
|
||||
unlet! g:_copilot_timer
|
||||
return copilot#Suggest()
|
||||
endfunction
|
||||
|
||||
function! copilot#Schedule() abort
|
||||
if !s:has_ghost_text || !s:Running() || !copilot#Enabled()
|
||||
call copilot#Clear()
|
||||
return
|
||||
endif
|
||||
call s:UpdatePreview()
|
||||
let delay = get(g:, 'copilot_idle_delay', 45)
|
||||
call timer_stop(get(g:, '_copilot_timer', -1))
|
||||
let g:_copilot_timer = timer_start(delay, function('s:Trigger', [bufnr('')]))
|
||||
endfunction
|
||||
|
||||
function! s:Attach(bufnr, ...) abort
|
||||
try
|
||||
return copilot#Client().Attach(a:bufnr)
|
||||
catch
|
||||
call copilot#logger#Exception()
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! copilot#OnFileType() abort
|
||||
if empty(s:BufferDisabled()) && &l:modifiable && &l:buflisted
|
||||
call copilot#util#Defer(function('s:Attach'), bufnr(''))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Focus(bufnr, ...) abort
|
||||
if s:Running() && copilot#Client().IsAttached(a:bufnr)
|
||||
call copilot#Client().Notify('textDocument/didFocus', {'textDocument': {'uri': copilot#Client().Attach(a:bufnr).uri}})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#OnBufEnter() abort
|
||||
let bufnr = bufnr('')
|
||||
call copilot#util#Defer(function('s:Focus'), bufnr)
|
||||
endfunction
|
||||
|
||||
function! copilot#OnInsertLeavePre() abort
|
||||
call copilot#Clear()
|
||||
call s:ClearPreview()
|
||||
endfunction
|
||||
|
||||
function! copilot#OnInsertEnter() abort
|
||||
return copilot#Schedule()
|
||||
endfunction
|
||||
|
||||
function! copilot#OnCompleteChanged() abort
|
||||
if s:HideDuringCompletion()
|
||||
return copilot#Clear()
|
||||
else
|
||||
return copilot#Schedule()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#OnCursorMovedI() abort
|
||||
return copilot#Schedule()
|
||||
endfunction
|
||||
|
||||
function! copilot#OnBufUnload() abort
|
||||
endfunction
|
||||
|
||||
function! copilot#OnVimLeavePre() abort
|
||||
endfunction
|
||||
|
||||
function! copilot#TextQueuedForInsertion() abort
|
||||
try
|
||||
return remove(s:, 'suggestion_text')
|
||||
catch
|
||||
return ''
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! copilot#Accept(...) abort
|
||||
let s = copilot#GetDisplayedSuggestion()
|
||||
if !empty(s.text)
|
||||
unlet! b:_copilot
|
||||
let text = ''
|
||||
if a:0 > 1
|
||||
let text = substitute(matchstr(s.text, "\n*" . '\%(' . a:2 .'\)'), "\n*$", '', '')
|
||||
endif
|
||||
if empty(text)
|
||||
let text = s.text
|
||||
endif
|
||||
let delete_chars = s.deleteChars
|
||||
let leftover = strpart(s.text, strlen(text))
|
||||
let idx = strridx(leftover, matchstr(delete_chars, '.$'))
|
||||
while !empty(delete_chars) && idx != -1
|
||||
let delete_chars = substitute(delete_chars, '.$', '', '')
|
||||
let idx = strridx(leftover, matchstr(delete_chars, '.$'), idx - 1)
|
||||
endwhile
|
||||
if text ==# s.text && has_key(s.item, 'command')
|
||||
call copilot#Request('workspace/executeCommand', s.item.command)
|
||||
else
|
||||
let line_text = strpart(getline('.'), 0, col('.') - 1) . text
|
||||
call copilot#Notify('textDocument/didPartiallyAcceptCompletion', {
|
||||
\ 'item': s.item,
|
||||
\ 'acceptedLength': copilot#util#UTF16Width(line_text) - s.item.range.start.character})
|
||||
endif
|
||||
call s:ClearPreview()
|
||||
let s:suggestion_text = text
|
||||
let recall = text =~# "\n" ? "\<C-R>\<C-O>=" : "\<C-R>\<C-R>="
|
||||
return repeat("\<Left>\<Del>", s.outdentSize) . repeat("\<Del>", strchars(delete_chars)) .
|
||||
\ recall . "copilot#TextQueuedForInsertion()\<CR>" . (a:0 > 1 ? '' : "\<End>")
|
||||
endif
|
||||
let default = get(g:, 'copilot_tab_fallback', pumvisible() ? "\<C-N>" : "\t")
|
||||
if !a:0
|
||||
return default
|
||||
elseif type(a:1) == v:t_string
|
||||
return a:1
|
||||
elseif type(a:1) == v:t_func
|
||||
try
|
||||
return call(a:1, [])
|
||||
catch
|
||||
return default
|
||||
endtry
|
||||
else
|
||||
return default
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#AcceptWord(...) abort
|
||||
return copilot#Accept(a:0 ? a:1 : '', '\%(\k\@!.\)*\k*')
|
||||
endfunction
|
||||
|
||||
function! copilot#AcceptLine(...) abort
|
||||
return copilot#Accept(a:0 ? a:1 : "\r", "[^\n]\\+")
|
||||
endfunction
|
||||
|
||||
function! copilot#Browser() abort
|
||||
if type(get(g:, 'copilot_browser')) == v:t_list
|
||||
let cmd = copy(g:copilot_browser)
|
||||
elseif type(get(g:, 'open_command')) == v:t_list
|
||||
let cmd = copy(g:open_command)
|
||||
elseif has('win32')
|
||||
let cmd = ['rundll32', 'url.dll,FileProtocolHandler']
|
||||
elseif has('mac')
|
||||
let cmd = ['open']
|
||||
elseif executable('wslview')
|
||||
return ['wslview']
|
||||
elseif executable('xdg-open')
|
||||
return ['xdg-open']
|
||||
else
|
||||
return []
|
||||
endif
|
||||
if executable(get(cmd, 0, ''))
|
||||
return cmd
|
||||
else
|
||||
return []
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:commands = {}
|
||||
|
||||
function! s:EnabledStatusMessage() abort
|
||||
let buf_disabled = s:BufferDisabled()
|
||||
if !s:has_ghost_text
|
||||
if has('nvim')
|
||||
return "Neovim 0.6 required to support ghost text"
|
||||
else
|
||||
return "Vim " . s:vim_minimum_version . " required to support ghost text"
|
||||
endif
|
||||
elseif !get(g:, 'copilot_enabled', 1)
|
||||
return 'Disabled globally by :Copilot disable'
|
||||
elseif buf_disabled is# 5
|
||||
return 'Disabled for current buffer by buftype=' . &buftype
|
||||
elseif buf_disabled is# 4
|
||||
return 'Disabled for current buffer by b:copilot_enabled'
|
||||
elseif buf_disabled is# 3
|
||||
return 'Disabled for current buffer by b:copilot_disabled'
|
||||
elseif buf_disabled is# 2
|
||||
return 'Disabled for filetype=' . &filetype . ' by internal default'
|
||||
elseif buf_disabled
|
||||
return 'Disabled for filetype=' . &filetype . ' by g:copilot_filetypes'
|
||||
elseif !copilot#Enabled()
|
||||
return 'BUG: Something is wrong with enabling/disabling'
|
||||
else
|
||||
return ''
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:VerifySetup() abort
|
||||
let error = copilot#Client().StartupError()
|
||||
if !empty(error)
|
||||
echo 'Copilot: ' . error
|
||||
return
|
||||
endif
|
||||
|
||||
if exists('s:client.status.kind') && s:client.status.kind ==# 'Error'
|
||||
echo 'Copilot: Error: ' . get(s:client.status, 'message', 'unknown')
|
||||
return
|
||||
endif
|
||||
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! s:commands.status(opts) abort
|
||||
if !s:VerifySetup()
|
||||
return
|
||||
endif
|
||||
|
||||
if exists('s:client.status.kind') && s:client.status.kind ==# 'Warning'
|
||||
echo 'Copilot: Warning: ' . get(s:client.status, 'message', 'unknown')
|
||||
return
|
||||
endif
|
||||
|
||||
let status = s:EnabledStatusMessage()
|
||||
if !empty(status)
|
||||
echo 'Copilot: ' . status
|
||||
return
|
||||
endif
|
||||
|
||||
echo 'Copilot: Ready'
|
||||
call s:EditorVersionWarning()
|
||||
endfunction
|
||||
|
||||
function! s:commands.signout(opts) abort
|
||||
echo 'Copilot: Signed out'
|
||||
call copilot#Call('signOut', {})
|
||||
endfunction
|
||||
|
||||
function! s:commands.setup(opts) abort
|
||||
let startup_error = copilot#Client().StartupError()
|
||||
if !empty(startup_error)
|
||||
echo 'Copilot: ' . startup_error
|
||||
return
|
||||
endif
|
||||
|
||||
let data = copilot#Call('signIn', {})
|
||||
|
||||
if has_key(data, 'verificationUri')
|
||||
let uri = data.verificationUri
|
||||
if has('clipboard')
|
||||
try
|
||||
let @+ = data.userCode
|
||||
catch
|
||||
endtry
|
||||
try
|
||||
let @* = data.userCode
|
||||
catch
|
||||
endtry
|
||||
endif
|
||||
let codemsg = "First copy your one-time code: " . data.userCode . "\n"
|
||||
try
|
||||
if len(&mouse)
|
||||
let mouse = &mouse
|
||||
set mouse=
|
||||
endif
|
||||
if get(a:opts, 'bang')
|
||||
call s:Echo(codemsg . "In your browser, visit " . uri)
|
||||
let request = copilot#Request('signInConfirm', {})
|
||||
else
|
||||
call input(codemsg . "Press ENTER to open GitHub in your browser\n")
|
||||
let request = copilot#Request('workspace/executeCommand', data.command)
|
||||
endif
|
||||
call s:Echo("Waiting for " . data.userCode . " at " . uri . " (could take up to 5 seconds)")
|
||||
call request.Wait()
|
||||
finally
|
||||
if exists('mouse')
|
||||
let &mouse = mouse
|
||||
endif
|
||||
endtry
|
||||
if request.status ==# 'error'
|
||||
return 'echoerr ' . string('Copilot: Authentication failure: ' . request.error.message)
|
||||
else
|
||||
let data = request.result
|
||||
endif
|
||||
elseif get(data, 'status', '') isnot# 'AlreadySignedIn'
|
||||
return 'echoerr ' . string('Copilot: Something went wrong')
|
||||
endif
|
||||
|
||||
let user = get(data, 'user', '<unknown>')
|
||||
|
||||
echo 'Copilot: Authenticated as GitHub user ' . user
|
||||
endfunction
|
||||
|
||||
let s:commands.auth = s:commands.setup
|
||||
let s:commands.signin = s:commands.setup
|
||||
|
||||
function! s:commands.help(opts) abort
|
||||
return a:opts.mods . ' help ' . (len(a:opts.arg) ? ':Copilot_' . a:opts.arg : 'copilot')
|
||||
endfunction
|
||||
|
||||
function! s:commands.version(opts) abort
|
||||
echo 'copilot.vim ' .copilot#client#EditorPluginInfo().version
|
||||
let editorInfo = copilot#client#EditorInfo()
|
||||
echo editorInfo.name . ' ' . editorInfo.version
|
||||
if s:Running()
|
||||
let versions = s:client.Request('getVersion', {})
|
||||
if exists('s:client.serverInfo.version')
|
||||
echo s:client.serverInfo.name . ' ' . s:client.serverInfo.version
|
||||
else
|
||||
echo 'GitHub Copilot Language Server ' . versions.Await().version
|
||||
endif
|
||||
if exists('s:client.node_version')
|
||||
echo 'Node.js ' . s:client.node_version
|
||||
else
|
||||
echo 'Node.js ' . substitute(get(versions.Await(), 'runtimeVersion', '?'), '^node/', '', 'g')
|
||||
endif
|
||||
else
|
||||
echo 'Not running'
|
||||
if exists('s:client.node_version')
|
||||
echo 'Node.js ' . s:client.node_version
|
||||
endif
|
||||
endif
|
||||
if has('win32')
|
||||
echo 'Windows'
|
||||
elseif has('macunix')
|
||||
echo 'macOS'
|
||||
elseif !has('unix')
|
||||
echo 'Unknown OS'
|
||||
elseif isdirectory('/sys/kernel')
|
||||
echo 'Linux'
|
||||
else
|
||||
echo 'UNIX'
|
||||
endif
|
||||
call s:EditorVersionWarning()
|
||||
endfunction
|
||||
|
||||
function! s:commands.restart(opts) abort
|
||||
call s:Stop()
|
||||
echo 'Copilot: Restarting language server'
|
||||
call s:Start()
|
||||
endfunction
|
||||
|
||||
function! s:AfterUpgrade(old_version, client) abort
|
||||
if exists('a:client.serverInfo.version')
|
||||
call s:Echo('Copilot: Upgraded language server to ' . a:client.serverInfo.version)
|
||||
let g:copilot_version = '^' . a:client.serverInfo.version
|
||||
else
|
||||
call s:Echo('Copilot: Failed to upgrade language server. Check log for details')
|
||||
let g:copilot_version = a:old_version
|
||||
if a:old_version is v:null
|
||||
unlet g:copilot_version
|
||||
endif
|
||||
call s:Start()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:commands.upgrade(opts) abort
|
||||
if exists('s:client.serverInfo.version')
|
||||
echo 'Copilot: Upgrading language server from version ' . s:client.serverInfo.version
|
||||
else
|
||||
echo 'Copilot: Upgrading language server'
|
||||
endif
|
||||
let old_version = get(g:, 'copilot_version', v:null)
|
||||
let g:copilot_version = 'latest'
|
||||
call s:Stop()
|
||||
call s:Start()
|
||||
call s:client.AfterInitialized(function('s:AfterUpgrade', [old_version]))
|
||||
endfunction
|
||||
|
||||
function! s:commands.disable(opts) abort
|
||||
let g:copilot_enabled = 0
|
||||
endfunction
|
||||
|
||||
function! s:commands.enable(opts) abort
|
||||
let g:copilot_enabled = 1
|
||||
endfunction
|
||||
|
||||
function! s:commands.panel(opts) abort
|
||||
if s:VerifySetup()
|
||||
return copilot#panel#Open(a:opts)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:FmtModel(model) abort
|
||||
return a:model.modelName . ' (' . a:model.id . ')'
|
||||
endfunction
|
||||
|
||||
function! s:commands.model(opts) abort
|
||||
if !s:VerifySetup()
|
||||
return
|
||||
endif
|
||||
let client = copilot#Client()
|
||||
let response = client.Request('copilot/models', {}).Wait()
|
||||
if response.status ==# 'error'
|
||||
return 'echoerr ' . string('Copilot: Error retrieving completions models: ' . response.error.message)
|
||||
endif
|
||||
let models = filter(response.result, { _, m -> index(m.scopes, 'completion') >= 0 })
|
||||
if len(models) == 0
|
||||
echo 'Copilot: Could not retrieve completions models'
|
||||
elseif len(models) == 1
|
||||
echo 'Copilot: Current/only completions model is ' . s:FmtModel(models[0])
|
||||
else
|
||||
let choices = map(copy(models), { i, m -> (i + 1) . '. ' . s:FmtModel(m) })
|
||||
let choice = inputlist(['Select a completions model:'] + choices)
|
||||
if choice < 1 || choice > len(models)
|
||||
return
|
||||
endif
|
||||
let model = models[choice - 1]
|
||||
if type(get(g:, 'copilot_settings')) != v:t_dict
|
||||
let g:copilot_settings = {}
|
||||
endif
|
||||
let g:copilot_settings.selectedCompletionModel = model.id
|
||||
redraw
|
||||
echo 'Copilot: Set completions model to ' . s:FmtModel(model)
|
||||
call client.DidChangeConfiguration()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:commands.log(opts) abort
|
||||
return a:opts.mods . ' split +$ copilot:///log'
|
||||
endfunction
|
||||
|
||||
function! copilot#CommandComplete(arg, lead, pos) abort
|
||||
let args = matchstr(strpart(a:lead, 0, a:pos), 'C\%[opilot][! ] *\zs.*')
|
||||
if args !~# ' '
|
||||
return sort(filter(map(keys(s:commands), { k, v -> tr(v, '_', '-') }),
|
||||
\ { k, v -> strpart(v, 0, len(a:arg)) ==# a:arg }))
|
||||
else
|
||||
return []
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#Command(line1, line2, range, bang, mods, arg) abort
|
||||
let cmd = matchstr(a:arg, '^\%(\\.\|\S\)\+')
|
||||
let arg = matchstr(a:arg, '\s\zs\S.*')
|
||||
if !empty(cmd) && !has_key(s:commands, tr(cmd, '-', '_'))
|
||||
return 'echoerr ' . string('Copilot: unknown command ' . string(cmd))
|
||||
endif
|
||||
try
|
||||
if empty(cmd)
|
||||
if !s:Running()
|
||||
let cmd = 'restart'
|
||||
else
|
||||
try
|
||||
let opts = copilot#Call('checkStatus', {'options': {'localChecksOnly': v:true}})
|
||||
if opts.status !=# 'OK' && opts.status !=# 'MaybeOK'
|
||||
let cmd = 'setup'
|
||||
else
|
||||
let cmd = 'status'
|
||||
endif
|
||||
catch
|
||||
call copilot#logger#Exception()
|
||||
let cmd = 'log'
|
||||
endtry
|
||||
endif
|
||||
endif
|
||||
let opts = {'line1': a:line1, 'line2': a:line2, 'range': a:range, 'bang': a:bang, 'mods': a:mods, 'arg': arg}
|
||||
let retval = s:commands[tr(cmd, '-', '_')](opts)
|
||||
if type(retval) == v:t_string
|
||||
return retval
|
||||
else
|
||||
return ''
|
||||
endif
|
||||
catch /^Copilot:/
|
||||
return 'echoerr ' . string(v:exception)
|
||||
endtry
|
||||
endfunction
|
||||
@@ -0,0 +1,848 @@
|
||||
scriptencoding utf-8
|
||||
|
||||
let s:plugin_version = copilot#version#String()
|
||||
|
||||
let s:error_canceled = {'code': -32800, 'message': 'Canceled'}
|
||||
let s:error_exit = {'code': -32097, 'message': 'Process exited'}
|
||||
let s:error_connection_inactive = {'code': -32096, 'message': 'Connection inactive'}
|
||||
|
||||
let s:root = expand('<sfile>:h:h:h')
|
||||
|
||||
if !exists('s:instances')
|
||||
let s:instances = {}
|
||||
endif
|
||||
|
||||
" allow sourcing this file to reload the Lua file too
|
||||
if has('nvim')
|
||||
lua package.loaded._copilot = nil
|
||||
endif
|
||||
|
||||
function! s:Warn(msg) abort
|
||||
if !empty(get(g:, 'copilot_no_startup_warnings'))
|
||||
return
|
||||
endif
|
||||
echohl WarningMsg
|
||||
echomsg 'Copilot: ' . a:msg
|
||||
echohl NONE
|
||||
endfunction
|
||||
|
||||
function! s:VimClose() dict abort
|
||||
if !has_key(self, 'job')
|
||||
return
|
||||
endif
|
||||
let job = self.job
|
||||
if has_key(self, 'kill')
|
||||
call job_stop(job, 'kill')
|
||||
call copilot#logger#Warn('Process forcefully terminated')
|
||||
return
|
||||
endif
|
||||
let self.kill = v:true
|
||||
let self.shutdown = self.Request('shutdown', {}, function(self.Notify, ['exit']))
|
||||
call timer_start(2000, { _ -> job_stop(job, 'kill') })
|
||||
call copilot#logger#Debug('Process shutdown initiated')
|
||||
endfunction
|
||||
|
||||
function! s:LogSend(request, line) abort
|
||||
return '--> ' . a:line
|
||||
endfunction
|
||||
|
||||
function! s:RejectRequest(request, error) abort
|
||||
if a:request.status !=# 'running'
|
||||
return
|
||||
endif
|
||||
let a:request.waiting = {}
|
||||
call remove(a:request, 'resolve')
|
||||
let reject = remove(a:request, 'reject')
|
||||
let a:request.status = 'error'
|
||||
let a:request.error = deepcopy(a:error)
|
||||
for Cb in reject
|
||||
let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', Cb]))] = 1
|
||||
endfor
|
||||
if index([s:error_canceled.code, s:error_connection_inactive.code], a:error.code) != -1
|
||||
return
|
||||
endif
|
||||
let msg = 'Method ' . a:request.method . ' errored with E' . a:error.code . ': ' . json_encode(a:error.message)
|
||||
if empty(reject)
|
||||
call copilot#logger#Error(msg)
|
||||
else
|
||||
call copilot#logger#Debug(msg)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:AfterInitialized(fn, ...) dict abort
|
||||
call add(self.after_initialized, function(a:fn, [self] + a:000))
|
||||
endfunction
|
||||
|
||||
function! s:AlreadyInitialized(fn, ...) dict abort
|
||||
return copilot#util#Defer(function(a:fn, [self] + a:000))
|
||||
endfunction
|
||||
|
||||
function! s:Send(instance, request) abort
|
||||
if !has_key(a:instance, 'job')
|
||||
return v:false
|
||||
endif
|
||||
try
|
||||
call ch_sendexpr(a:instance.job, a:request)
|
||||
return v:true
|
||||
catch /^Vim\%((\a\+)\)\=:E906:/
|
||||
let a:instance.kill = v:true
|
||||
let job = remove(a:instance, 'job')
|
||||
call job_stop(job)
|
||||
call timer_start(2000, { _ -> job_stop(job, 'kill') })
|
||||
call copilot#logger#Warn('Terminating process after failed write')
|
||||
return v:false
|
||||
catch /^Vim\%((\a\+)\)\=:E631:/
|
||||
return v:false
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! s:VimNotify(method, params) dict abort
|
||||
let request = {'method': a:method, 'params': a:params}
|
||||
call self.AfterInitialized(function('s:Send'), request)
|
||||
endfunction
|
||||
|
||||
function! s:RequestWait() dict abort
|
||||
while self.status ==# 'running'
|
||||
sleep 1m
|
||||
endwhile
|
||||
while !empty(get(self, 'waiting', {}))
|
||||
sleep 1m
|
||||
endwhile
|
||||
return self
|
||||
endfunction
|
||||
|
||||
function! s:RequestAwait() dict abort
|
||||
call self.Wait()
|
||||
if has_key(self, 'result')
|
||||
return self.result
|
||||
endif
|
||||
throw 'Copilot:E' . self.error.code . ': ' . self.error.message
|
||||
endfunction
|
||||
|
||||
function! s:RequestClient() dict abort
|
||||
return get(s:instances, self.client_id, v:null)
|
||||
endfunction
|
||||
|
||||
if !exists('s:id')
|
||||
let s:id = 0
|
||||
endif
|
||||
if !exists('s:progress_token_id')
|
||||
let s:progress_token_id = 0
|
||||
endif
|
||||
|
||||
function! s:SetUpRequest(instance, id, method, params, progress, ...) abort
|
||||
let request = {
|
||||
\ 'client_id': a:instance.id,
|
||||
\ 'id': a:id,
|
||||
\ 'method': a:method,
|
||||
\ 'params': a:params,
|
||||
\ 'Client': function('s:RequestClient'),
|
||||
\ 'Wait': function('s:RequestWait'),
|
||||
\ 'Await': function('s:RequestAwait'),
|
||||
\ 'Cancel': function('s:RequestCancel'),
|
||||
\ 'resolve': [],
|
||||
\ 'reject': [],
|
||||
\ 'progress': a:progress,
|
||||
\ 'status': 'running'}
|
||||
let args = a:000[2:-1]
|
||||
if len(args)
|
||||
if !empty(a:1)
|
||||
call add(request.resolve, { v -> call(a:1, [v] + args)})
|
||||
endif
|
||||
if !empty(a:2)
|
||||
call add(request.reject, { v -> call(a:2, [v] + args)})
|
||||
endif
|
||||
return request
|
||||
endif
|
||||
if a:0 && !empty(a:1)
|
||||
call add(request.resolve, a:1)
|
||||
endif
|
||||
if a:0 > 1 && !empty(a:2)
|
||||
call add(request.reject, a:2)
|
||||
endif
|
||||
return request
|
||||
endfunction
|
||||
|
||||
function! s:UrlEncode(str) abort
|
||||
return substitute(iconv(a:str, 'latin1', 'utf-8'),'[^A-Za-z0-9._~!$&''()*+,;=:@/-]','\="%".printf("%02X",char2nr(submatch(0)))','g')
|
||||
endfunction
|
||||
|
||||
let s:slash = exists('+shellslash') ? '\' : '/'
|
||||
function! s:UriFromBufnr(bufnr) abort
|
||||
let absolute = tr(bufname(a:bufnr), s:slash, '/')
|
||||
if absolute !~# '^\a\+:\|^/\|^$' && getbufvar(a:bufnr, 'buftype') =~# '^\%(nowrite\)\=$'
|
||||
let absolute = substitute(tr(getcwd(), s:slash, '/'), '/\=$', '/', '') . absolute
|
||||
endif
|
||||
return s:UriFromPath(absolute)
|
||||
endfunction
|
||||
|
||||
function! s:UriFromPath(absolute) abort
|
||||
let absolute = a:absolute
|
||||
if has('win32') && absolute =~# '^\a://\@!'
|
||||
return 'file:///' . strpart(absolute, 0, 2) . s:UrlEncode(strpart(absolute, 2))
|
||||
elseif absolute =~# '^/'
|
||||
return 'file://' . s:UrlEncode(absolute)
|
||||
elseif absolute =~# '^\a[[:alnum:].+-]*:\|^$'
|
||||
return absolute
|
||||
else
|
||||
return ''
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:BufferText(bufnr) abort
|
||||
return join(getbufline(a:bufnr, 1, '$'), "\n") . "\n"
|
||||
endfunction
|
||||
|
||||
let s:valid_request_key = '^\%(id\|method\|params\)$'
|
||||
function! s:SendRequest(instance, request, ...) abort
|
||||
if !has_key(a:instance, 'job') || get(a:instance, 'shutdown', a:request) isnot# a:request
|
||||
return s:RejectRequest(a:request, s:error_connection_inactive)
|
||||
endif
|
||||
let json = filter(copy(a:request), 'v:key =~# s:valid_request_key')
|
||||
if empty(s:Send(a:instance, json)) && has_key(a:request, 'id') && has_key(a:instance.requests, a:request.id)
|
||||
call s:RejectRequest(remove(a:instance.requests, a:request.id), {'code': -32099, 'message': 'Write failed'})
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:RegisterWorkspaceFolderForBuffer(instance, buf) abort
|
||||
let root = getbufvar(a:buf, 'workspace_folder')
|
||||
if type(root) != v:t_string
|
||||
return
|
||||
endif
|
||||
let root = s:UriFromPath(substitute(root, '[\/]$', '', ''))
|
||||
if empty(root) || has_key(a:instance.workspaceFolders, root)
|
||||
return
|
||||
endif
|
||||
let a:instance.workspaceFolders[root] = v:true
|
||||
call a:instance.Notify('workspace/didChangeWorkspaceFolders', {'event': {'added': [{'uri': root, 'name': fnamemodify(root, ':t')}], 'removed': []}})
|
||||
endfunction
|
||||
|
||||
function! s:PreprocessParams(instance, params) abort
|
||||
let bufnr = v:null
|
||||
for doc in filter([get(a:params, 'textDocument', {})], 'type(get(v:val, "uri", "")) == v:t_number')
|
||||
let bufnr = doc.uri
|
||||
call s:RegisterWorkspaceFolderForBuffer(a:instance, bufnr)
|
||||
call extend(doc, a:instance.Attach(bufnr))
|
||||
endfor
|
||||
let progress_tokens = []
|
||||
for key in keys(a:params)
|
||||
if key =~# 'Token$' && type(a:params[key]) == v:t_func
|
||||
let s:progress_token_id += 1
|
||||
let a:instance.progress[s:progress_token_id] = a:params[key]
|
||||
call add(progress_tokens, s:progress_token_id)
|
||||
let a:params[key] = s:progress_token_id
|
||||
endif
|
||||
endfor
|
||||
return [bufnr, progress_tokens]
|
||||
endfunction
|
||||
|
||||
function! s:VimAttach(bufnr) dict abort
|
||||
if !bufloaded(a:bufnr)
|
||||
return {'uri': '', 'version': 0}
|
||||
endif
|
||||
let bufnr = a:bufnr
|
||||
let doc = {
|
||||
\ 'uri': s:UriFromBufnr(bufnr),
|
||||
\ 'version': getbufvar(bufnr, 'changedtick', 0),
|
||||
\ 'languageId': getbufvar(bufnr, '&filetype'),
|
||||
\ }
|
||||
if has_key(self.open_buffers, bufnr) && (
|
||||
\ self.open_buffers[bufnr].uri !=# doc.uri ||
|
||||
\ self.open_buffers[bufnr].languageId !=# doc.languageId)
|
||||
call self.Notify('textDocument/didClose', {'textDocument': {'uri': self.open_buffers[bufnr].uri}})
|
||||
call remove(self.open_buffers, bufnr)
|
||||
endif
|
||||
if !has_key(self.open_buffers, bufnr)
|
||||
call self.Notify('textDocument/didOpen', {'textDocument': extend({'text': s:BufferText(bufnr)}, doc)})
|
||||
let self.open_buffers[bufnr] = doc
|
||||
else
|
||||
call self.Notify('textDocument/didChange', {
|
||||
\ 'textDocument': {'uri': doc.uri, 'version': doc.version},
|
||||
\ 'contentChanges': [{'text': s:BufferText(bufnr)}]})
|
||||
let self.open_buffers[bufnr].version = doc.version
|
||||
endif
|
||||
return doc
|
||||
endfunction
|
||||
|
||||
function! s:VimIsAttached(bufnr) dict abort
|
||||
return bufloaded(a:bufnr) && has_key(self.open_buffers, a:bufnr) ? v:true : v:false
|
||||
endfunction
|
||||
|
||||
function! s:VimRequest(method, params, ...) dict abort
|
||||
let s:id += 1
|
||||
let params = deepcopy(a:params)
|
||||
let [_, progress] = s:PreprocessParams(self, params)
|
||||
let request = call('s:SetUpRequest', [self, s:id, a:method, params, progress] + a:000)
|
||||
call self.AfterInitialized(function('s:SendRequest'), request)
|
||||
let self.requests[s:id] = request
|
||||
return request
|
||||
endfunction
|
||||
|
||||
function! s:Call(method, params, ...) dict abort
|
||||
let request = call(self.Request, [a:method, a:params] + a:000)
|
||||
if a:0
|
||||
return request
|
||||
endif
|
||||
return request.Await()
|
||||
endfunction
|
||||
|
||||
function! s:Cancel(request) dict abort
|
||||
if has_key(self.requests, get(a:request, 'id', ''))
|
||||
call self.Notify('$/cancelRequest', {'id': a:request.id})
|
||||
call s:RejectRequest(remove(self.requests, a:request.id), s:error_canceled)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:RequestCancel() dict abort
|
||||
let instance = self.Client()
|
||||
if !empty(instance)
|
||||
call instance.Cancel(self)
|
||||
elseif get(self, 'status', '') ==# 'running'
|
||||
call s:RejectRequest(self, s:error_canceled)
|
||||
endif
|
||||
return self
|
||||
endfunction
|
||||
|
||||
function! s:DispatchMessage(instance, method, handler, id, params, ...) abort
|
||||
try
|
||||
let response = {'result': call(a:handler, [a:params, a:instance])}
|
||||
if response.result is# 0
|
||||
let response.result = v:null
|
||||
endif
|
||||
catch
|
||||
call copilot#logger#Exception('lsp.request.' . a:method)
|
||||
let response = {'error': {'code': -32000, 'message': v:exception}}
|
||||
endtry
|
||||
if a:id isnot# v:null
|
||||
call s:Send(a:instance, extend({'id': a:id}, response))
|
||||
endif
|
||||
if !has_key(s:notifications, a:method)
|
||||
return response
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:OnMessage(instance, body, ...) abort
|
||||
if !has_key(a:body, 'method')
|
||||
return s:OnResponse(a:instance, a:body)
|
||||
endif
|
||||
let request = a:body
|
||||
let id = get(request, 'id', v:null)
|
||||
let params = get(request, 'params', v:null)
|
||||
if has_key(a:instance.methods, request.method)
|
||||
return s:DispatchMessage(a:instance, request.method, a:instance.methods[request.method], id, params)
|
||||
elseif id isnot# v:null
|
||||
call s:Send(a:instance, {"id": id, "error": {"code": -32700, "message": "Method not found: " . request.method}})
|
||||
call copilot#logger#Debug('Unexpected request ' . request.method . ' called with ' . json_encode(params))
|
||||
elseif request.method !~# '^\$/'
|
||||
call copilot#logger#Debug('Unexpected notification ' . request.method . ' called with ' . json_encode(params))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:OnResponse(instance, response, ...) abort
|
||||
let response = a:response
|
||||
let id = get(a:response, 'id', v:null)
|
||||
if !has_key(a:instance.requests, id)
|
||||
return
|
||||
endif
|
||||
let request = remove(a:instance.requests, id)
|
||||
for progress_token in request.progress
|
||||
if has_key(a:instance.progress, progress_token)
|
||||
call remove(a:instance.progress, progress_token)
|
||||
endif
|
||||
endfor
|
||||
if request.status !=# 'running'
|
||||
return
|
||||
endif
|
||||
if has_key(response, 'result')
|
||||
let request.waiting = {}
|
||||
let resolve = remove(request, 'resolve')
|
||||
call remove(request, 'reject')
|
||||
let request.status = 'success'
|
||||
let request.result = response.result
|
||||
for Cb in resolve
|
||||
let request.waiting[timer_start(0, function('s:Callback', [request, 'result', Cb]))] = 1
|
||||
endfor
|
||||
else
|
||||
call s:RejectRequest(request, response.error)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:OnErr(instance, ch, line, ...) abort
|
||||
if !has_key(a:instance, 'serverInfo')
|
||||
call copilot#logger#Bare('<-! ' . a:line)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:FlushAfterInitialized(instance) abort
|
||||
if has_key(a:instance, 'after_initialized')
|
||||
let a:instance.AfterInitialized = function('s:AlreadyInitialized')
|
||||
for Fn in remove(a:instance, 'after_initialized')
|
||||
call copilot#util#Defer(Fn)
|
||||
endfor
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:OnExit(instance, code, ...) abort
|
||||
let a:instance.exit_status = a:code
|
||||
if has_key(a:instance, 'job')
|
||||
call remove(a:instance, 'job')
|
||||
endif
|
||||
if has_key(a:instance, 'client_id')
|
||||
call remove(a:instance, 'client_id')
|
||||
endif
|
||||
let message = 'Process exited with status ' . a:code
|
||||
if a:code >= 18 && a:code < 100
|
||||
let message = 'Node.js too old. ' .
|
||||
\ (get(a:instance.node, 0, 'node') ==# 'node' ? 'Upgrade' : 'Change g:copilot_node_command') .
|
||||
\ ' to ' . a:code . '.x or newer'
|
||||
endif
|
||||
if !has_key(a:instance, 'serverInfo') && !has_key(a:instance, 'startup_error')
|
||||
let a:instance.startup_error = message
|
||||
endif
|
||||
for id in sort(keys(a:instance.requests), { a, b -> +a > +b })
|
||||
call s:RejectRequest(remove(a:instance.requests, id), s:error_exit)
|
||||
endfor
|
||||
call s:FlushAfterInitialized(a:instance)
|
||||
call copilot#util#Defer({ -> get(s:instances, a:instance.id) is# a:instance ? remove(s:instances, a:instance.id) : {} })
|
||||
if a:code == 0
|
||||
call copilot#logger#Info(message)
|
||||
else
|
||||
call copilot#logger#Warn(message)
|
||||
if !has_key(a:instance, 'kill')
|
||||
call copilot#util#Defer(function('s:Warn'), message)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#client#LspInit(id, initialize_result) abort
|
||||
if !has_key(s:instances, a:id)
|
||||
return
|
||||
endif
|
||||
call s:PostInit(a:initialize_result, s:instances[a:id])
|
||||
endfunction
|
||||
|
||||
function! copilot#client#LspExit(id, code, signal) abort
|
||||
if !has_key(s:instances, a:id)
|
||||
return
|
||||
endif
|
||||
let instance = remove(s:instances, a:id)
|
||||
call s:OnExit(instance, a:code)
|
||||
endfunction
|
||||
|
||||
function! copilot#client#LspResponse(id, opts, ...) abort
|
||||
if !has_key(s:instances, a:id)
|
||||
return
|
||||
endif
|
||||
call s:OnResponse(s:instances[a:id], a:opts)
|
||||
endfunction
|
||||
|
||||
function! s:NvimAttach(bufnr) dict abort
|
||||
if !bufloaded(a:bufnr)
|
||||
return {'uri': '', 'version': 0}
|
||||
endif
|
||||
call luaeval('pcall(vim.lsp.buf_attach_client, _A[1], _A[2])', [a:bufnr, self.id])
|
||||
return luaeval('{uri = vim.uri_from_bufnr(_A), version = vim.lsp.util.buf_versions[_A]}', a:bufnr)
|
||||
endfunction
|
||||
|
||||
function! s:NvimIsAttached(bufnr) dict abort
|
||||
return bufloaded(a:bufnr) ? luaeval('vim.lsp.buf_is_attached(_A[1], _A[2])', [a:bufnr, self.id]) : v:false
|
||||
endfunction
|
||||
|
||||
function! s:NvimRequest(method, params, ...) dict abort
|
||||
let params = deepcopy(a:params)
|
||||
let [bufnr, progress] = s:PreprocessParams(self, params)
|
||||
let request = call('s:SetUpRequest', [self, v:null, a:method, params, progress] + a:000)
|
||||
call self.AfterInitialized(function('s:NvimDoRequest'), request, bufnr)
|
||||
return request
|
||||
endfunction
|
||||
|
||||
function! s:NvimDoRequest(client, request, bufnr) abort
|
||||
let request = a:request
|
||||
if has_key(a:client, 'client_id') && !has_key(a:client, 'kill')
|
||||
let request.id = eval("v:lua.require'_copilot'.lsp_request(a:client.id, a:request.method, a:request.params, a:bufnr)")
|
||||
endif
|
||||
if request.id isnot# v:null
|
||||
let a:client.requests[request.id] = request
|
||||
else
|
||||
if has_key(a:client, 'client_id')
|
||||
call copilot#client#LspExit(a:client.client_id, -1, -1)
|
||||
endif
|
||||
call copilot#util#Defer(function('s:RejectRequest'), request, s:error_connection_inactive)
|
||||
endif
|
||||
return request
|
||||
endfunction
|
||||
|
||||
function! s:NvimClose() dict abort
|
||||
if !has_key(self, 'client_id')
|
||||
return
|
||||
endif
|
||||
let self.kill = v:true
|
||||
return luaeval('vim.lsp.stop_client(_A)', self.client_id)
|
||||
endfunction
|
||||
|
||||
function! s:NvimNotify(method, params) dict abort
|
||||
call self.AfterInitialized(function('s:NvimDoNotify'), a:method, a:params)
|
||||
endfunction
|
||||
|
||||
function! s:NvimDoNotify(client, method, params) abort
|
||||
return eval("v:lua.require'_copilot'.rpc_notify(a:client.client_id, a:method, a:params)")
|
||||
endfunction
|
||||
|
||||
function! copilot#client#LspHandle(id, request) abort
|
||||
if !has_key(s:instances, a:id)
|
||||
return
|
||||
endif
|
||||
return s:OnMessage(s:instances[a:id], a:request)
|
||||
endfunction
|
||||
|
||||
function! s:PackageVersion() abort
|
||||
try
|
||||
return json_decode(join(readfile(s:root . '/copilot-language-server/package.json'))).version
|
||||
catch
|
||||
endtry
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:GetCommand(var, default) abort
|
||||
let cmd = get(g:, a:var, '')
|
||||
if type(cmd) == type('') && !empty(cmd)
|
||||
return [expand(cmd)]
|
||||
endif
|
||||
return type(cmd) == v:t_list && !empty(cmd) ? copy(cmd) : a:default
|
||||
endfunction
|
||||
|
||||
let s:script_name = 'copilot-language-server/dist/language-server.js'
|
||||
let s:pkg_name = '@github/copilot-language-server'
|
||||
function! s:Command() abort
|
||||
if !has('nvim-0.8') && v:version < 900
|
||||
return [[], [], 'Vim version too old']
|
||||
endif
|
||||
let script = s:GetCommand('copilot_command', [])
|
||||
let npx = get(g:, 'copilot_version', get(g:, 'copilot_npx', v:null))
|
||||
if npx is# v:null
|
||||
let npx = empty(script) && !empty(get(g:, 'copilot_npx_command', 1)) ? v:true : v:false
|
||||
endif
|
||||
if type(npx) != v:t_string && !empty(npx)
|
||||
let npx = ''
|
||||
endif
|
||||
if type(npx) == v:t_string
|
||||
if empty(npx)
|
||||
let npx = '^'
|
||||
endif
|
||||
if npx =~# '^\%([~<>=^]\|\d\+\.\|latest$\)'
|
||||
let npx = '@' . npx
|
||||
endif
|
||||
if npx =~# '^@[^/]*$'
|
||||
let npx = s:pkg_name . npx
|
||||
endif
|
||||
if npx =~# '@[~<>=^]\+$'
|
||||
let pkg_version = s:PackageVersion()
|
||||
if pkg_version =~# '^[1-9]'
|
||||
let npx .= pkg_version
|
||||
else
|
||||
let npx = substitute(npx, '@[=~]$', '@^', '') . '1.0.0'
|
||||
endif
|
||||
endif
|
||||
let script = s:GetCommand('copilot_npx_command', ['npx']) + [npx]
|
||||
if !executable(script[0])
|
||||
let script = []
|
||||
endif
|
||||
endif
|
||||
if empty(script)
|
||||
let script = [s:root . '/' . s:script_name]
|
||||
endif
|
||||
if script[0] !~# '\.[cm]\=[jt]s$' && executable(script[0])
|
||||
return [[], script, '']
|
||||
elseif !filereadable(script[0])
|
||||
return [[], [], 'Could not find ' . script[0]]
|
||||
endif
|
||||
let node = s:GetCommand('copilot_node_command', ['node'])
|
||||
if !executable(get(node, 0, ''))
|
||||
if get(node, 0, '') ==# 'node'
|
||||
return [[], [], 'Node.js not found in PATH']
|
||||
else
|
||||
return [[], [], 'Node.js executable `' . get(node, 0, '') . "' not found"]
|
||||
endif
|
||||
endif
|
||||
return [node, script, '']
|
||||
endfunction
|
||||
|
||||
function! s:UrlDecode(str) abort
|
||||
return substitute(a:str, '%\(\x\x\)', '\=iconv(nr2char("0x".submatch(1)), "utf-8", "latin1")', 'g')
|
||||
endfunction
|
||||
|
||||
function! copilot#client#EditorInfo() abort
|
||||
if !exists('s:editor_version')
|
||||
if has('nvim')
|
||||
let s:editor_version = matchstr(execute('version'), 'NVIM v\zs[^[:space:]]\+')
|
||||
else
|
||||
let s:editor_version = (v:version / 100) . '.' . (v:version % 100) . (exists('v:versionlong') ? printf('.%04d', v:versionlong % 10000) : '')
|
||||
endif
|
||||
endif
|
||||
return {'name': has('nvim') ? 'Neovim': 'Vim', 'version': s:editor_version}
|
||||
endfunction
|
||||
|
||||
function! copilot#client#EditorPluginInfo() abort
|
||||
return {'name': 'copilot.vim', 'version': s:plugin_version}
|
||||
endfunction
|
||||
|
||||
function! copilot#client#Settings() abort
|
||||
let settings = {
|
||||
\ 'http': {
|
||||
\ 'proxy': get(g:, 'copilot_proxy', v:null),
|
||||
\ 'proxyStrictSSL': get(g:, 'copilot_proxy_strict_ssl', v:null)},
|
||||
\ 'github-enterprise': {'uri': get(g:, 'copilot_enterprise_uri', get(g:, 'copilot_auth_provider_url', v:null))},
|
||||
\ }
|
||||
if type(settings.http.proxy) ==# v:t_string && settings.http.proxy =~# '^[^/]\+$'
|
||||
let settings.http.proxy = 'http://' . settings.http.proxy
|
||||
endif
|
||||
if type(get(g:, 'copilot_settings')) == v:t_dict
|
||||
let settings.github = {'copilot': g:copilot_settings}
|
||||
endif
|
||||
if type(get(g:, 'copilot_lsp_settings')) == v:t_dict
|
||||
call extend(settings, g:copilot_lsp_settings)
|
||||
endif
|
||||
return settings
|
||||
endfunction
|
||||
|
||||
function! s:PostInit(result, instance) abort
|
||||
let a:instance.serverInfo = get(a:result, 'serverInfo', {})
|
||||
if !has_key(a:instance, 'node_version') && has_key(a:result.serverInfo, 'nodeVersion')
|
||||
let a:instance.node_version = a:result.serverInfo.nodeVersion
|
||||
endif
|
||||
call s:FlushAfterInitialized(a:instance)
|
||||
endfunction
|
||||
|
||||
function! s:InitializeResult(result, instance) abort
|
||||
call s:Send(a:instance, {'method': 'initialized', 'params': {}})
|
||||
call s:PostInit(a:result, a:instance)
|
||||
endfunction
|
||||
|
||||
function! s:InitializeError(error, instance) abort
|
||||
if !has_key(a:instance, 'startup_error')
|
||||
let a:instance.startup_error = 'Unexpected error E' . a:error.code . ' initializing language server: ' . a:error.message
|
||||
call a:instance.Close()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:StartupError() dict abort
|
||||
while (has_key(self, 'job') || has_key(self, 'client_id')) && !has_key(self, 'startup_error') && !has_key(self, 'serverInfo')
|
||||
sleep 10m
|
||||
endwhile
|
||||
if has_key(self, 'serverInfo')
|
||||
return ''
|
||||
else
|
||||
return get(self, 'startup_error', 'Something unexpected went wrong spawning the language server')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:VimDidChangeConfiguration() dict abort
|
||||
let settings = copilot#client#Settings()
|
||||
return self.Notify('workspace/didChangeConfiguration', {'settings': settings})
|
||||
endfunction
|
||||
|
||||
function! s:NvimDidChangeConfiguration() dict abort
|
||||
let settings = copilot#client#Settings()
|
||||
return eval("v:lua.require'_copilot'.did_change_configuration(self.id, settings)")
|
||||
endfunction
|
||||
|
||||
function! s:StatusNotification(params, instance) abort
|
||||
let a:instance.status = a:params
|
||||
endfunction
|
||||
|
||||
function! s:Nop(...) abort
|
||||
return v:null
|
||||
endfunction
|
||||
|
||||
function! s:False(...) abort
|
||||
return v:false
|
||||
endfunction
|
||||
|
||||
function! s:Progress(params, instance) abort
|
||||
if has_key(a:instance.progress, a:params.token)
|
||||
call a:instance.progress[a:params.token](a:params.value)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:notifications = {
|
||||
\ '$/progress': function('s:Progress'),
|
||||
\ 'featureFlagsNotification': function('s:Nop'),
|
||||
\ 'didChangeStatus': function('s:StatusNotification'),
|
||||
\ 'window/logMessage': function('copilot#handlers#window_logMessage'),
|
||||
\ }
|
||||
|
||||
let s:vim_handlers = {
|
||||
\ 'window/showMessageRequest': function('copilot#handlers#window_showMessageRequest'),
|
||||
\ 'window/showDocument': function('copilot#handlers#window_showDocument'),
|
||||
\ }
|
||||
|
||||
let s:vim_capabilities = {
|
||||
\ 'workspace': {'workspaceFolders': v:true},
|
||||
\ 'window': {'showDocument': {'support': v:true}},
|
||||
\ }
|
||||
|
||||
function! copilot#client#New() abort
|
||||
let opts = {}
|
||||
let instance = {'requests': {},
|
||||
\ 'name': 'GitHub Copilot',
|
||||
\ 'progress': {},
|
||||
\ 'workspaceFolders': {},
|
||||
\ 'after_initialized': [],
|
||||
\ 'status': {'status': 'Starting', 'message': ''},
|
||||
\ 'AfterInitialized': function('s:AfterInitialized'),
|
||||
\ 'Close': function('s:Nop'),
|
||||
\ 'Notify': function('s:False'),
|
||||
\ 'Request': function('s:VimRequest'),
|
||||
\ 'Attach': function('s:Nop'),
|
||||
\ 'IsAttached': function('s:False'),
|
||||
\ 'Call': function('s:Call'),
|
||||
\ 'Cancel': function('s:Cancel'),
|
||||
\ 'DidChangeConfiguration': function('s:VimDidChangeConfiguration'),
|
||||
\ 'StartupError': function('s:StartupError'),
|
||||
\ }
|
||||
let instance.methods = copy(s:notifications)
|
||||
let [node, argv, command_error] = s:Command()
|
||||
if !empty(command_error)
|
||||
let instance.id = -1
|
||||
let instance.startup_error = command_error
|
||||
call copilot#logger#Error(command_error)
|
||||
call s:FlushAfterInitialized(instance)
|
||||
return instance
|
||||
endif
|
||||
let instance.node = node
|
||||
let command = node + argv + ['--stdio']
|
||||
let opts.initializationOptions = {
|
||||
\ 'editorInfo': copilot#client#EditorInfo(),
|
||||
\ 'editorPluginInfo': copilot#client#EditorPluginInfo(),
|
||||
\ }
|
||||
if type(get(g:, 'copilot_integration_id')) == v:t_string
|
||||
let opts.initializationOptions.copilotIntegrationId = g:copilot_integration_id
|
||||
endif
|
||||
let opts.workspaceFolders = []
|
||||
let settings = copilot#client#Settings()
|
||||
if type(get(g:, 'copilot_workspace_folders')) == v:t_list
|
||||
for folder in g:copilot_workspace_folders
|
||||
if type(folder) == v:t_string && !empty(folder) && folder !~# '\*\*\|^/$'
|
||||
for path in glob(folder . '/', 0, 1)
|
||||
let uri = s:UriFromPath(substitute(path, '[\/]*$', '', ''))
|
||||
call add(opts.workspaceFolders, {'uri': uri, 'name': fnamemodify(uri, ':t')})
|
||||
endfor
|
||||
elseif type(folder) == v:t_dict && has_key(v:t_dict, 'uri') && !empty(folder.uri) && has_key(folder, 'name')
|
||||
call add(opts.workspaceFolders, folder)
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
for folder in opts.workspaceFolders
|
||||
let instance.workspaceFolders[folder.uri] = v:true
|
||||
endfor
|
||||
call copilot#logger#Debug('Spawning ' . join(command, ' '))
|
||||
let is_win_shell = has('win32') && &shellcmdflag !~# '^-'
|
||||
if is_win_shell && command[0] !~# '[\/]'
|
||||
let exepath = exepath(command[0])
|
||||
if exepath !~? '\.exe$\|^$'
|
||||
let command[0] = fnamemodify(exepath, ':t')
|
||||
endif
|
||||
endif
|
||||
if has('nvim')
|
||||
if is_win_shell
|
||||
call map(command, { _, v -> substitute(v, '\^', '^^^^', 'g') })
|
||||
endif
|
||||
call extend(instance, {
|
||||
\ 'Close': function('s:NvimClose'),
|
||||
\ 'Notify': function('s:NvimNotify'),
|
||||
\ 'Request': function('s:NvimRequest'),
|
||||
\ 'Attach': function('s:NvimAttach'),
|
||||
\ 'DidChangeConfiguration': function('s:NvimDidChangeConfiguration'),
|
||||
\ 'IsAttached': function('s:NvimIsAttached'),
|
||||
\ })
|
||||
let id = eval("v:lua.require'_copilot'.lsp_start_client(command, instance.name, keys(instance.methods), opts, settings)")
|
||||
if id is# v:null
|
||||
let instance.id = -1
|
||||
let instance.startup_error = 'Neovim failed to start LSP client'
|
||||
call s:FlushAfterInitialized(instance)
|
||||
return instance
|
||||
endif
|
||||
let instance.client_id = id
|
||||
let instance.id = instance.client_id
|
||||
else
|
||||
if is_win_shell
|
||||
let command = join(map(command, { _, v -> v =~# '[;&|^ ]' ? '"' . v . '"' : v }), ' ')
|
||||
endif
|
||||
call extend(instance, {
|
||||
\ 'Close': function('s:VimClose'),
|
||||
\ 'Notify': function('s:VimNotify'),
|
||||
\ 'Attach': function('s:VimAttach'),
|
||||
\ 'IsAttached': function('s:VimIsAttached'),
|
||||
\ })
|
||||
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
|
||||
let instance.open_buffers = {}
|
||||
let instance.methods = extend(s:vim_handlers, instance.methods)
|
||||
let instance.job = job_start(command, {
|
||||
\ 'cwd': copilot#job#Cwd(),
|
||||
\ 'noblock': 1,
|
||||
\ 'stoponexit': '',
|
||||
\ 'in_mode': 'lsp',
|
||||
\ 'out_mode': 'lsp',
|
||||
\ 'out_cb': { j, d -> copilot#util#Defer(function('s:OnMessage'), instance, d) },
|
||||
\ 'err_cb': function('s:OnErr', [instance]),
|
||||
\ 'exit_cb': { j, d -> copilot#util#Defer(function('s:OnExit'), instance, d) },
|
||||
\ })
|
||||
let instance.id = job_info(instance.job).process
|
||||
let opts.capabilities = s:vim_capabilities
|
||||
let opts.processId = getpid()
|
||||
let request = instance.Request('initialize', opts, function('s:InitializeResult'), function('s:InitializeError'), instance)
|
||||
call call(remove(instance.after_initialized, 0), [])
|
||||
call instance.Notify('workspace/didChangeConfiguration', {'settings': settings})
|
||||
endif
|
||||
let s:instances[instance.id] = instance
|
||||
return instance
|
||||
endfunction
|
||||
|
||||
function! copilot#client#Cancel(request) abort
|
||||
if type(a:request) == type({}) && has_key(a:request, 'Cancel')
|
||||
call a:request.Cancel()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Callback(request, type, callback, timer) abort
|
||||
call remove(a:request.waiting, a:timer)
|
||||
if has_key(a:request, a:type)
|
||||
call a:callback(a:request[a:type])
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#client#Result(request, callback) abort
|
||||
if has_key(a:request, 'resolve')
|
||||
call add(a:request.resolve, a:callback)
|
||||
elseif has_key(a:request, 'result')
|
||||
let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'result', a:callback]))] = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#client#Error(request, callback) abort
|
||||
if has_key(a:request, 'reject')
|
||||
call add(a:request.reject, a:callback)
|
||||
elseif has_key(a:request, 'error')
|
||||
let a:request.waiting[timer_start(0, function('s:Callback', [a:request, 'error', a:callback]))] = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:CloseBuffer(bufnr) abort
|
||||
for instance in values(s:instances)
|
||||
try
|
||||
if has_key(instance, 'job') && has_key(instance.open_buffers, a:bufnr)
|
||||
let buffer = remove(instance.open_buffers, a:bufnr)
|
||||
call instance.Notify('textDocument/didClose', {'textDocument': {'uri': buffer.uri}})
|
||||
endif
|
||||
catch
|
||||
call copilot#logger#Exception()
|
||||
endtry
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
augroup copilot_close
|
||||
autocmd!
|
||||
if !has('nvim')
|
||||
autocmd BufUnload * call s:CloseBuffer(+expand('<abuf>'))
|
||||
endif
|
||||
augroup END
|
||||
@@ -0,0 +1,31 @@
|
||||
function! copilot#handlers#window_logMessage(params, ...) abort
|
||||
call copilot#logger#Raw(get(a:params, 'type', 6), get(a:params, 'message', ''))
|
||||
endfunction
|
||||
|
||||
function! copilot#handlers#window_showMessageRequest(params, instance, ...) abort
|
||||
let choice = inputlist([a:instance.name . "\n" . a:params.message . "\n\nRequest Actions:"] +
|
||||
\ map(copy(get(a:params, 'actions', [])), { i, v -> (i + 1) . '. ' . v.title}))
|
||||
return choice > 0 ? get(a:params.actions, choice - 1, v:null) : v:null
|
||||
endfunction
|
||||
|
||||
function! s:BrowserCallback(into, code) abort
|
||||
let a:into.code = a:code
|
||||
endfunction
|
||||
|
||||
function! copilot#handlers#window_showDocument(params, ...) abort
|
||||
echo a:params.uri
|
||||
if empty(get(a:params, 'external'))
|
||||
return {'success': v:false}
|
||||
endif
|
||||
let browser = copilot#Browser()
|
||||
if empty(browser)
|
||||
return {'success': v:false}
|
||||
endif
|
||||
let status = {}
|
||||
call copilot#job#Stream(browser + [a:params.uri], v:null, v:null, function('s:BrowserCallback', [status]))
|
||||
let time = reltime()
|
||||
while empty(status) && reltimefloat(reltime(time)) < 1
|
||||
sleep 10m
|
||||
endwhile
|
||||
return {'success': get(status, 'code') ? v:false : v:true}
|
||||
endfunction
|
||||
@@ -0,0 +1,106 @@
|
||||
scriptencoding utf-8
|
||||
|
||||
function! copilot#job#Nop(...) abort
|
||||
endfunction
|
||||
|
||||
function! s:Jobs(job_or_jobs) abort
|
||||
let jobs = type(a:job_or_jobs) == v:t_list ? copy(a:job_or_jobs) : [a:job_or_jobs]
|
||||
call map(jobs, { k, v -> type(v) == v:t_dict ? get(v, 'job', '') : v })
|
||||
call filter(jobs, { k, v -> type(v) !=# type('') })
|
||||
return jobs
|
||||
endfunction
|
||||
|
||||
let s:job_stop = exists('*job_stop') ? 'job_stop' : 'jobstop'
|
||||
function! copilot#job#Stop(job) abort
|
||||
for job in s:Jobs(a:job)
|
||||
call call(s:job_stop, [job])
|
||||
endfor
|
||||
return copilot#job#Wait(a:job)
|
||||
endfunction
|
||||
|
||||
let s:sleep = has('patch-8.2.2366') ? 'sleep! 1m' : 'sleep 1m'
|
||||
function! copilot#job#Wait(jobs) abort
|
||||
let jobs = s:Jobs(a:jobs)
|
||||
if exists('*jobwait')
|
||||
call jobwait(jobs)
|
||||
else
|
||||
for job in jobs
|
||||
while ch_status(job) !=# 'closed' || job_status(job) ==# 'run'
|
||||
exe s:sleep
|
||||
endwhile
|
||||
endfor
|
||||
endif
|
||||
return a:jobs
|
||||
endfunction
|
||||
|
||||
function! s:VimExitCallback(result, exit_cb, job, data) abort
|
||||
let a:result.exit_status = a:data
|
||||
if !has_key(a:result, 'closed')
|
||||
return
|
||||
endif
|
||||
call remove(a:result, 'closed')
|
||||
call a:exit_cb(a:result.exit_status)
|
||||
endfunction
|
||||
|
||||
function! s:VimCloseCallback(result, exit_cb, job) abort
|
||||
if !has_key(a:result, 'exit_status')
|
||||
let a:result.closed = v:true
|
||||
return
|
||||
endif
|
||||
call a:exit_cb(a:result.exit_status)
|
||||
endfunction
|
||||
|
||||
function! s:NvimCallback(cb, job, data, type) dict abort
|
||||
let self[a:type][0] .= remove(a:data, 0)
|
||||
call extend(self[a:type], a:data)
|
||||
while len(self[a:type]) > 1
|
||||
call a:cb(substitute(remove(self[a:type], 0), "\r$", '', ''))
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:NvimExitCallback(out_cb, err_cb, exit_cb, job, data, type) dict abort
|
||||
if len(self.stderr[0])
|
||||
call a:err_cb(substitute(self.stderr[0], "\r$", '', ''))
|
||||
endif
|
||||
call a:exit_cb(a:data)
|
||||
endfunction
|
||||
|
||||
function! copilot#job#Cwd() abort
|
||||
let home = expand("~")
|
||||
if !isdirectory(home) && isdirectory($VIM)
|
||||
return $VIM
|
||||
endif
|
||||
return home
|
||||
endfunction
|
||||
|
||||
function! copilot#job#Stream(argv, out_cb, err_cb, ...) abort
|
||||
let exit_status = []
|
||||
let ExitCb = function(a:0 && !empty(a:1) ? a:1 : { e -> add(exit_status, e) }, a:000[2:-1])
|
||||
let OutCb = function(empty(a:out_cb) ? 'copilot#job#Nop' : a:out_cb, a:000[2:-1])
|
||||
let ErrCb = function(empty(a:err_cb) ? 'copilot#job#Nop' : a:err_cb, a:000[2:-1])
|
||||
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
|
||||
if exists('*job_start')
|
||||
let result = {}
|
||||
let job = job_start(a:argv, {
|
||||
\ 'cwd': copilot#job#Cwd(),
|
||||
\ 'out_mode': 'raw',
|
||||
\ 'out_cb': { j, d -> OutCb(d) },
|
||||
\ 'err_cb': { j, d -> ErrCb(d) },
|
||||
\ 'exit_cb': function('s:VimExitCallback', [result, ExitCb]),
|
||||
\ 'close_cb': function('s:VimCloseCallback', [result, ExitCb]),
|
||||
\ })
|
||||
else
|
||||
let jopts = {
|
||||
\ 'cwd': copilot#job#Cwd(),
|
||||
\ 'stderr': [''],
|
||||
\ 'on_stdout': { j, d, t -> OutCb(join(d, "\n")) },
|
||||
\ 'on_stderr': function('s:NvimCallback', [ErrCb]),
|
||||
\ 'on_exit': function('s:NvimExitCallback', [OutCb, ErrCb, ExitCb])}
|
||||
let job = jobstart(a:argv, jopts)
|
||||
endif
|
||||
if a:0
|
||||
return job
|
||||
endif
|
||||
call copilot#job#Wait(job)
|
||||
return exit_status[0]
|
||||
endfunction
|
||||
@@ -0,0 +1,94 @@
|
||||
let s:logs = []
|
||||
|
||||
function! copilot#logger#BufReadCmd() abort
|
||||
try
|
||||
setlocal modifiable noreadonly
|
||||
silent call deletebufline('', 1, '$')
|
||||
if !empty(s:logs)
|
||||
call setline(1, s:logs)
|
||||
endif
|
||||
finally
|
||||
setlocal buftype=nofile bufhidden=wipe nobuflisted nomodified nomodifiable
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
let s:level_prefixes = ['', '[ERROR] ', '[WARN] ', '[INFO] ', '[DEBUG] ', '[DEBUG] ']
|
||||
|
||||
function! copilot#logger#Raw(level, message) abort
|
||||
let lines = type(a:message) == v:t_list ? copy(a:message) : split(a:message, "\n", 1)
|
||||
let lines[0] = strftime('[%Y-%m-%d %H:%M:%S] ') . get(s:level_prefixes, a:level, '[UNKNOWN] ') . get(lines, 0, '')
|
||||
try
|
||||
call map(lines, { k, L -> type(L) == v:t_func ? call(L, []) : L })
|
||||
call extend(s:logs, lines)
|
||||
let overflow = len(s:logs) - get(g:, 'copilot_log_history', 10000)
|
||||
if overflow > 0
|
||||
call remove(s:logs, 0, overflow - 1)
|
||||
endif
|
||||
let bufnr = bufnr('copilot:///log')
|
||||
if bufnr > 0 && bufloaded(bufnr)
|
||||
call setbufvar(bufnr, '&modifiable', 1)
|
||||
call setbufline(bufnr, 1, s:logs)
|
||||
call setbufvar(bufnr, '&modifiable', 0)
|
||||
for winid in win_findbuf(bufnr)
|
||||
if has('nvim') && winid != win_getid()
|
||||
call nvim_win_set_cursor(winid, [len(s:logs), 0])
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
catch
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! copilot#logger#Debug(...) abort
|
||||
if empty(get(g:, 'copilot_debug'))
|
||||
return
|
||||
endif
|
||||
call copilot#logger#Raw(4, a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#logger#Info(...) abort
|
||||
call copilot#logger#Raw(3, a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#logger#Warn(...) abort
|
||||
call copilot#logger#Raw(2, a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#logger#Error(...) abort
|
||||
call copilot#logger#Raw(1, a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#logger#Bare(...) abort
|
||||
call copilot#logger#Raw(0, a:000)
|
||||
endfunction
|
||||
|
||||
function! copilot#logger#Exception(...) abort
|
||||
if !empty(v:exception) && v:exception !=# 'Vim:Interrupt'
|
||||
call copilot#logger#Error('Exception: ' . v:exception . ' @ ' . v:throwpoint)
|
||||
let client = copilot#RunningClient()
|
||||
if !empty(client)
|
||||
let [_, type, code, message; __] = matchlist(v:exception, '^\%(\(^[[:alnum:]_#]\+\)\%((\a\+)\)\=\%(\(:E-\=\d\+\)\)\=:\s*\)\=\(.*\)$')
|
||||
let stacklines = []
|
||||
for frame in split(substitute(v:throwpoint, ', \S\+ \(\d\+\)$', '[\1]', ''), '\.\@<!\.\.\.\@!')
|
||||
let fn_line = matchlist(frame, '^\%(function \)\=\(\S\+\)\[\(\d\+\)\]$')
|
||||
if !empty(fn_line)
|
||||
call add(stacklines, {'function': substitute(fn_line[1], '^<SNR>\d\+_', '<SID>', ''), 'lineno': +fn_line[2]})
|
||||
elseif frame =~# ' Autocmds for "\*"$'
|
||||
call add(stacklines, {'function': frame})
|
||||
elseif frame =~# ' Autocmds for ".*"$'
|
||||
call add(stacklines, {'function': substitute(frame, ' for ".*"$', ' for "[redacted]"', '')})
|
||||
else
|
||||
call add(stacklines, {'function': '[redacted]'})
|
||||
endif
|
||||
endfor
|
||||
return client.Request('telemetry/exception', {
|
||||
\ 'transaction': a:0 ? a:1 : '',
|
||||
\ 'platform': 'other',
|
||||
\ 'exception_detail': [{
|
||||
\ 'type': type . code,
|
||||
\ 'value': message,
|
||||
\ 'stacktrace': stacklines}]
|
||||
\ }, v:null, function('copilot#util#Nop'))
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
@@ -0,0 +1,173 @@
|
||||
scriptencoding utf-8
|
||||
|
||||
if !exists('s:panel_id')
|
||||
let s:panel_id = 0
|
||||
endif
|
||||
|
||||
let s:separator = repeat('─', 72)
|
||||
|
||||
function! s:Render(state) abort
|
||||
let bufnr = bufnr('^' . a:state.panel . '$')
|
||||
let state = a:state
|
||||
if !bufloaded(bufnr)
|
||||
return
|
||||
endif
|
||||
let sorted = a:state.items
|
||||
if !empty(get(a:state, 'error'))
|
||||
let lines = ['Error: ' . a:state.error.message]
|
||||
let sorted = []
|
||||
elseif get(a:state, 'percentage') == 100
|
||||
let lines = ['Synthesized ' . (len(sorted) == 1 ? '1 completion' : len(sorted) . ' completions')]
|
||||
else
|
||||
let lines = [substitute('Synthesizing ' . matchstr(get(a:state, 'message', ''), '\d\+\%(/\d\+\)\=') . ' completions', ' \+', ' ', 'g')]
|
||||
endif
|
||||
if len(sorted)
|
||||
call add(lines, 'Press <CR> on a completion to accept')
|
||||
endif
|
||||
let leads = {}
|
||||
for item in sorted
|
||||
let insert = split(item.insertText, "\r\n\\=\\|\n", 1)
|
||||
let insert[0] = strpart(a:state.line, 0, copilot#util#UTF16ToByteIdx(a:state.line, item.range.start.character)) . insert[0]
|
||||
let lines += [s:separator] + insert
|
||||
if !has_key(leads, string(item.range.start))
|
||||
let match = insert[0 : a:state.position.line - item.range.start.line]
|
||||
let match[-1] = strpart(match[-1], 0, copilot#util#UTF16ToByteIdx(match[-1], a:state.position.character))
|
||||
call map(match, { k, v -> escape(v, '][^$.*\~') })
|
||||
let leads[string(item.range.start)] = join(match, '\n')
|
||||
endif
|
||||
endfor
|
||||
try
|
||||
call setbufvar(bufnr, '&modifiable', 1)
|
||||
call setbufvar(bufnr, '&readonly', 0)
|
||||
call setbufline(bufnr, 1, lines)
|
||||
finally
|
||||
call setbufvar(bufnr, '&modifiable', 0)
|
||||
endtry
|
||||
call clearmatches()
|
||||
call matchadd('CopilotSuggestion', '\C^' . s:separator . '\n\zs\%(' . join(sort(values(leads), { a, b -> len(b) - len(a) }), '\|') . '\)', 10, 4)
|
||||
endfunction
|
||||
|
||||
function! s:PartialResult(state, value) abort
|
||||
let items = type(a:value) == v:t_list ? a:value : a:value.items
|
||||
call extend(a:state.items, items)
|
||||
call s:Render(a:state)
|
||||
endfunction
|
||||
|
||||
function! s:WorkDone(state, value) abort
|
||||
if has_key(a:value, 'message')
|
||||
let a:state.message = a:value.message
|
||||
endif
|
||||
if has_key(a:value, 'percentage')
|
||||
let a:state.percentage = a:value.percentage
|
||||
call s:Render(a:state)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! copilot#panel#Accept(...) abort
|
||||
let state = get(b:, 'copilot_panel', {})
|
||||
if empty(state.items)
|
||||
return ''
|
||||
endif
|
||||
if !has_key(state, 'bufnr') || !bufloaded(get(state, 'bufnr', -1))
|
||||
return "echoerr 'Buffer was closed'"
|
||||
endif
|
||||
let at = a:0 ? a:1 : line('.')
|
||||
let index = 0
|
||||
for lnum in range(1, at)
|
||||
if getline(lnum) ==# s:separator
|
||||
let index += 1
|
||||
endif
|
||||
endfor
|
||||
if index > 0 && index <= len(state.items)
|
||||
let item = state.items[index - 1]
|
||||
let lnum = item.range.start.line + 1
|
||||
if getbufline(state.bufnr, lnum) !=# [state.line]
|
||||
return 'echoerr "Buffer has changed since synthesizing completion"'
|
||||
endif
|
||||
let lines = split(item.insertText, '\r\n\=\|\n', 1)
|
||||
let old_first = getbufline(state.bufnr, item.range.start.line + 1)[0]
|
||||
let byte_offset_start = copilot#util#UTF16ToByteIdx(old_first, item.range.start.character)
|
||||
let lines[0] = strpart(old_first, 0, byte_offset_start) . lines[0]
|
||||
let old_last = getbufline(state.bufnr, item.range.end.line + 1)[0]
|
||||
let byte_offset_end = copilot#util#UTF16ToByteIdx(old_last, item.range.end.character)
|
||||
let lines[-1] .= strpart(old_last, byte_offset_end)
|
||||
call deletebufline(state.bufnr, item.range.start.line + 1, item.range.end.line + 1)
|
||||
call appendbufline(state.bufnr, item.range.start.line, lines)
|
||||
call copilot#Request('workspace/executeCommand', item.command)
|
||||
bwipeout
|
||||
let win = bufwinnr(state.bufnr)
|
||||
if win > 0
|
||||
exe win . 'wincmd w'
|
||||
exe item.range.start.line + len(lines)
|
||||
if state.was_insert
|
||||
startinsert!
|
||||
else
|
||||
normal! $
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:Initialize(state) abort
|
||||
try
|
||||
let &l:filetype = 'copilotpanel' . (empty(a:state.filetype) ? '' : '.' . a:state.filetype)
|
||||
catch
|
||||
let &l:filetype = 'copilotpanel'
|
||||
endtry
|
||||
let &l:tabstop = a:state.tabstop
|
||||
nmap <buffer><script> <CR> <Cmd>exe copilot#panel#Accept()<CR>
|
||||
nmap <buffer><script> [[ <Cmd>call search('^─\{9,}\n.', 'bWe')<CR>
|
||||
nmap <buffer><script> ]] <Cmd>call search('^─\{9,}\n.', 'We')<CR>
|
||||
endfunction
|
||||
|
||||
function! s:BufReadCmd() abort
|
||||
setlocal bufhidden=wipe buftype=nofile nobuflisted nomodifiable
|
||||
let state = get(b:, 'copilot_panel')
|
||||
if type(state) != v:t_dict
|
||||
return
|
||||
endif
|
||||
call s:Initialize(state)
|
||||
call s:Render(state)
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:Result(state, result) abort
|
||||
let a:state.percentage = 100
|
||||
call s:PartialResult(a:state, a:result)
|
||||
endfunction
|
||||
|
||||
function! s:Error(state, error) abort
|
||||
let a:state.error = a:error
|
||||
call s:Render(a:state)
|
||||
endfunction
|
||||
|
||||
function! copilot#panel#Open(opts) abort
|
||||
let s:panel_id += 1
|
||||
let state = {'items': [], 'filetype': &filetype, 'was_insert': mode() =~# '^[iR]', 'bufnr': bufnr(''), 'tabstop': &tabstop}
|
||||
let state.panel = 'copilot:///panel/' . s:panel_id
|
||||
if state.was_insert
|
||||
let state.position = copilot#util#AppendPosition()
|
||||
stopinsert
|
||||
else
|
||||
let state.position = {'line': a:opts.line1 >= 1 ? a:opts.line1 - 1 : 0, 'character': copilot#util#UTF16Width(getline('.'))}
|
||||
endif
|
||||
let state.line = getline(state.position.line + 1)
|
||||
let params = {
|
||||
\ 'textDocument': {'uri': state.bufnr},
|
||||
\ 'position': state.position,
|
||||
\ 'partialResultToken': function('s:PartialResult', [state]),
|
||||
\ 'workDoneToken': function('s:WorkDone', [state]),
|
||||
\ }
|
||||
let response = copilot#Request('textDocument/copilotPanelCompletion', params, function('s:Result', [state]), function('s:Error', [state]))
|
||||
exe substitute(a:opts.mods, '\C\<tab\>', '-tab', 'g') 'keepalt split' state.panel
|
||||
let b:copilot_panel = state
|
||||
call s:Initialize(state)
|
||||
call s:Render(state)
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
augroup github_copilot_panel
|
||||
autocmd!
|
||||
autocmd BufReadCmd copilot:///panel/* exe s:BufReadCmd()
|
||||
augroup END
|
||||
@@ -0,0 +1,61 @@
|
||||
let s:deferred = []
|
||||
|
||||
function! copilot#util#Nop(...) abort
|
||||
return v:null
|
||||
endfunction
|
||||
|
||||
function! copilot#util#Defer(fn, ...) abort
|
||||
call add(s:deferred, function(a:fn, a:000))
|
||||
return timer_start(0, function('s:RunDeferred'))
|
||||
endfunction
|
||||
|
||||
function! s:RunDeferred(...) abort
|
||||
if empty(s:deferred)
|
||||
return
|
||||
endif
|
||||
let Fn = remove(s:deferred, 0)
|
||||
call timer_start(0, function('s:RunDeferred'))
|
||||
call call(Fn, [])
|
||||
endfunction
|
||||
|
||||
function! copilot#util#UTF16Width(str) abort
|
||||
return strchars(substitute(a:str, "\\%#=2[^\u0001-\uffff]", " ", 'g'))
|
||||
endfunction
|
||||
|
||||
if exists('*utf16idx')
|
||||
|
||||
function! copilot#util#UTF16ToByteIdx(str, utf16_idx) abort
|
||||
return byteidx(a:str, a:utf16_idx, 1)
|
||||
endfunction
|
||||
|
||||
elseif has('nvim')
|
||||
|
||||
function! copilot#util#UTF16ToByteIdx(str, utf16_idx) abort
|
||||
try
|
||||
return v:lua.vim.str_byteindex(a:str, a:utf16_idx, 1)
|
||||
catch /^Vim(return):E5108:/
|
||||
return -1
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
else
|
||||
|
||||
function! copilot#util#UTF16ToByteIdx(str, utf16_idx) abort
|
||||
if copilot#util#UTF16Width(a:str) < a:utf16_idx
|
||||
return -1
|
||||
endif
|
||||
let end_offset = len(a:str)
|
||||
while copilot#util#UTF16Width(strpart(a:str, 0, end_offset)) > a:utf16_idx && end_offset > 0
|
||||
let end_offset -= 1
|
||||
endwhile
|
||||
return end_offset
|
||||
endfunction
|
||||
|
||||
endif
|
||||
|
||||
function! copilot#util#AppendPosition() abort
|
||||
let line = getline('.')
|
||||
let col_byte = col('.') - (mode() =~# '^[iR]' || empty(line))
|
||||
let col_utf16 = copilot#util#UTF16Width(strpart(line, 0, col_byte))
|
||||
return {'line': line('.') - 1, 'character': col_utf16}
|
||||
endfunction
|
||||
@@ -0,0 +1,3 @@
|
||||
function! copilot#version#String() abort
|
||||
return '1.58.0'
|
||||
endfunction
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 GitHub
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,269 @@
|
||||
---
|
||||
name: CVE Remediator
|
||||
description: Detects and fixes security vulnerabilities (CVEs) in project dependencies across any ecosystem while maintaining a working build.
|
||||
---
|
||||
|
||||
## Mission
|
||||
|
||||
Detect and fix CVEs (Common Vulnerabilities and Exposures) in project dependencies while maintaining a working build.
|
||||
|
||||
## Terminology
|
||||
|
||||
**Target dependencies** = the dependencies to check and fix, determined by user request:
|
||||
- **Specific dependencies** when user names them (e.g., "log4j", "Spring and Jackson")
|
||||
- **All direct dependencies** (excluding transitive) when user requests project-wide scan (e.g., "all CVEs", "scan project")
|
||||
|
||||
## Objectives
|
||||
|
||||
1. Identify CVEs in dependencies based on severity threshold
|
||||
2. Upgrade vulnerable dependencies to patched versions
|
||||
3. Resolve build errors caused by upgrades
|
||||
4. Verify no new CVEs or build errors introduced
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- Zero actionable fixable CVEs in target dependencies (based on severity threshold)
|
||||
- Project builds successfully with no compilation errors
|
||||
- No new CVEs introduced in target dependencies
|
||||
|
||||
## Core Rules
|
||||
|
||||
- NEVER introduce new CVEs in target dependencies
|
||||
- NEVER downgrade dependencies
|
||||
- NEVER modify functionality beyond API compatibility updates
|
||||
- ONLY check and fix CVEs in target dependencies (always exclude transitive dependencies)
|
||||
- ALWAYS build after each modification
|
||||
- ALWAYS re-validate after each successful build
|
||||
- ALWAYS verify build is successful: exit code 0 AND terminal output has NO errors AND get_errors returns NO errors
|
||||
- NEVER skip build validation
|
||||
|
||||
## Understanding User Intent
|
||||
|
||||
Determine severity threshold and scope before starting:
|
||||
|
||||
**Severity Threshold** (which CVEs to fix):
|
||||
|
||||
- Default: critical, high
|
||||
- Extract from request:
|
||||
- "critical only" → critical
|
||||
- "critical and high" → critical, high
|
||||
- "include medium severity" or "medium and above" → critical, high, medium
|
||||
- "all severities" → critical, high, medium, low
|
||||
|
||||
**Scope** (which dependencies to check):
|
||||
|
||||
- Specific: User names dependencies ("log4j", "Spring and Jackson") → locate and check only those
|
||||
- Project-wide: User says "all", "scan project", "entire project" → discover and check all direct dependencies
|
||||
|
||||
**Important**: The `validate_cves` tool returns ALL CVEs regardless of severity. Filter results based on your determined severity threshold to identify actionable CVEs.
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 0: Detect Environment
|
||||
|
||||
Before examining dependencies, identify the project environment:
|
||||
|
||||
1. **Detect ecosystem**: Examine project files to determine language and build tool
|
||||
2. **Locate dependency manifests and lockfiles**: Identify primary dependency files and version lockfiles
|
||||
3. **Determine versions**: Check language and tool versions
|
||||
|
||||
**Detection examples** (adapt to your project):
|
||||
|
||||
- **Maven**:
|
||||
- Manifest: `pom.xml`
|
||||
- Version: Java version in `<java.version>` or `<maven.compiler.source>`, or run `java -version`
|
||||
|
||||
- **npm**:
|
||||
- Manifest: `package.json`
|
||||
- Lockfile: `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml`
|
||||
- Version: Node version in `engines.node` or run `node -v`
|
||||
|
||||
- **pip**:
|
||||
- Manifest: `requirements.txt`, `setup.py`, or `pyproject.toml`
|
||||
- Lockfile: `poetry.lock`, `Pipfile.lock` (if using Poetry or Pipenv)
|
||||
- Version: Python version in `python_requires` or run `python --version`
|
||||
|
||||
**Output**: Document detected ecosystem, language/tool versions, dependency manifest, lockfile (if present), and build commands to use.
|
||||
|
||||
### Step 1: Identify Target Dependencies
|
||||
|
||||
Identify package names and versions for **target dependencies** based on the scope determined in "Understanding User Intent" section. Always exclude transitive/indirect dependencies from the target set.
|
||||
|
||||
**Detection strategy (use build tools first, then fall back to manifest parsing):**
|
||||
|
||||
1. **Use build tool commands** (preferred - gets actual resolved versions, handles inheritance and version management):
|
||||
- Maven: `mvn dependency:tree` (extract depth=1 for project-wide, filter for specific names) OR `mvn dependency:list -DexcludeTransitive=true`
|
||||
- npm: `npm ls --depth=0` (project-wide) OR `npm ls <package-name>` (specific dependency)
|
||||
- pip: `pip show <package-name>` (specific) OR parse `pipdeptree --json` (project-wide)
|
||||
|
||||
2. **Parse manifest and lockfiles** (fallback - simpler but may miss inherited or workspace dependencies):
|
||||
- Maven: `<dependency>` entries in `pom.xml` `<dependencies>` section (excludes parent POM and `<dependencyManagement>`)
|
||||
- npm: `dependencies` and `devDependencies` in `package.json`; resolve versions from `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml`
|
||||
- pip: Top-level entries in `requirements.txt` or dependencies in `pyproject.toml`; resolve versions from `poetry.lock` or `Pipfile.lock` if available
|
||||
|
||||
**Scope-specific notes:**
|
||||
- **Project-wide**: Extract all direct dependencies (depth=1 or first-level only)
|
||||
- **Specific**: Filter for named dependencies; validate they exist in the project before proceeding
|
||||
|
||||
**Important:**
|
||||
- Include all direct dependencies needed for runtime, building, and testing
|
||||
- Validate the identified list makes sense for the project structure
|
||||
- Command examples are hints only - adapt to the detected ecosystem and available tools
|
||||
|
||||
### Step 2: Remediation Loop
|
||||
|
||||
Iterate until zero actionable CVEs.
|
||||
|
||||
#### 2a. Validate
|
||||
|
||||
**Invoke `validate_cves`** with dependencies in format `package@version`.
|
||||
|
||||
Examples (adapt to your ecosystem):
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": ["org.springframework:spring-core@5.3.20", "org.apache.logging.log4j:log4j-core@2.14.1"],
|
||||
"ecosystem": "maven"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": ["django@3.2.0", "requests@2.25.1"],
|
||||
"ecosystem": "pip"
|
||||
}
|
||||
```
|
||||
|
||||
**Understanding the output:**
|
||||
|
||||
For each dependency, the tool provides CVE count, upgrade recommendations (fixable vs unfixable), and complete CVE details (severity, description, links).
|
||||
|
||||
Three possible scenarios:
|
||||
- **All fixable**: Upgrade to recommended version fixes all CVEs
|
||||
- **All unfixable**: No patched versions available yet
|
||||
- **Mixed**: Some CVEs fixable by upgrade, others unfixable
|
||||
|
||||
Filter by your severity threshold to determine actionable CVEs.
|
||||
|
||||
**Next:**
|
||||
|
||||
- Zero actionable fixable CVEs in target dependencies → Step 3 (note any unfixable CVEs for final report)
|
||||
- Found actionable fixable CVEs → Step 2b
|
||||
|
||||
#### 2b. Fix
|
||||
|
||||
For each actionable **fixable** CVE:
|
||||
|
||||
1. Note recommended patched version from tool output
|
||||
2. Update dependency version in manifest file
|
||||
3. If breaking changes exist, update affected code
|
||||
|
||||
**Important:** Do NOT attempt to fix CVEs marked as unfixable (no patched versions available). Track these for the final report.
|
||||
|
||||
After all fixes, return to Step 2a to validate with the updated dependency versions.
|
||||
|
||||
Continue loop until Step 2a finds zero actionable fixable CVEs.
|
||||
|
||||
### Step 3: Build Verification Loop
|
||||
|
||||
Iterate until build succeeds with clean output.
|
||||
|
||||
#### 3a. Build and Verify
|
||||
|
||||
Run the appropriate build command for your ecosystem.
|
||||
|
||||
**Example commands** (adapt to your detected environment):
|
||||
|
||||
- Maven: `mvn clean compile`, `mvn clean test`, or `mvn clean verify`
|
||||
- npm: `npm run build` or `npm test`
|
||||
- pip: `pip install -r requirements.txt` or `python -m pytest`
|
||||
|
||||
**Critical**: You MUST perform ALL three checks before declaring build success:
|
||||
|
||||
1. Check exit code is 0
|
||||
2. Review complete terminal output for errors (look for error indicators specific to your build tool)
|
||||
3. Run `get_errors` to check for compilation errors
|
||||
|
||||
**Next:**
|
||||
|
||||
- All checks pass (exit code 0 AND no terminal errors AND no compilation errors) → go to Step 3c
|
||||
- Any check fails → go to Step 3b
|
||||
|
||||
#### 3b. Fix Build Errors
|
||||
|
||||
1. Review terminal output and `get_errors` for error details and stack traces
|
||||
2. Identify root cause
|
||||
3. Fix errors using tools available
|
||||
4. Go to Step 3a
|
||||
|
||||
Continue loop until Step 3a confirms clean build.
|
||||
|
||||
#### 3c. Re-validate Target Dependencies
|
||||
|
||||
Get current target dependency list and run `validate_cves` to verify no new CVEs were introduced in target dependencies after the build.
|
||||
|
||||
**Next:**
|
||||
|
||||
- New actionable CVEs found in target dependencies → return to Step 2
|
||||
- Zero actionable CVEs in target dependencies → go to Step 4
|
||||
|
||||
### Step 4: Final Verification
|
||||
|
||||
Verify all success criteria:
|
||||
|
||||
1. Zero actionable **fixable** CVEs in target dependencies - if failed, return to Step 2
|
||||
2. Exit code 0 AND no terminal errors AND no compilation errors - if failed, return to Step 3
|
||||
3. Document any unfixable CVEs in target dependencies for final report
|
||||
|
||||
**Completion criteria:**
|
||||
|
||||
If there are zero fixable CVEs in target dependencies (even if unfixable CVEs exist), the task is complete. Proceed to Step 5.
|
||||
|
||||
### Step 5: Report Results
|
||||
|
||||
Provide a comprehensive summary of completed work:
|
||||
|
||||
**Format:**
|
||||
|
||||
```
|
||||
## CVE Remediation Summary
|
||||
|
||||
### Environment
|
||||
- Language: [e.g., Java 17, Node 18, Python 3.11]
|
||||
- Build Tool: [e.g., Maven, npm, pip]
|
||||
- Dependency Manifest: [e.g., pom.xml, package.json, requirements.txt]
|
||||
|
||||
### Initial State
|
||||
- Target dependencies scanned: N
|
||||
- Total CVEs found in target dependencies: X (breakdown: Y critical, Z high, W medium, V low)
|
||||
- Actionable CVEs (based on severity threshold): A fixable, B unfixable
|
||||
|
||||
### Actions Taken
|
||||
- Dependencies upgraded:
|
||||
- dependency1: v1.0.0 → v2.5.0 (fixed CVE-2023-1234, CVE-2023-5678)
|
||||
- dependency2: v3.0.0 → v3.8.0 (fixed CVE-2023-9012)
|
||||
- Build errors resolved: [list any API compatibility fixes made]
|
||||
|
||||
### Final State
|
||||
- ✅ All fixable CVEs in target dependencies resolved
|
||||
- ✅ Build successful (exit code 0, no errors)
|
||||
- ✅ No new CVEs introduced in target dependencies
|
||||
|
||||
### Remaining Risks (if any)
|
||||
⚠️ Unfixable CVEs in target dependencies (no patched versions available):
|
||||
- [CVE-2023-9999] in dependency3@2.0.0 - CRITICAL severity
|
||||
- [CVE-2023-8888] in dependency4@1.5.0 - HIGH severity
|
||||
|
||||
Recommendation: Monitor these CVEs for future patches or consider alternative dependencies.
|
||||
|
||||
**Note**: Target dependencies are based on user request scope (specific dependencies or all direct dependencies). Transitive dependencies are always excluded from this analysis.
|
||||
```
|
||||
|
||||
**Guidelines:**
|
||||
|
||||
- Use exact CVE IDs from `validate_cves` output
|
||||
- Show version transitions for all upgraded dependencies
|
||||
- Clearly distinguish between fixed and unfixable CVEs
|
||||
- If no unfixable CVEs exist, omit the "Remaining Risks" section
|
||||
- Include severity levels for unfixable CVEs to help users prioritize mitigation strategies
|
||||
- Clarify scope in report: indicate whether specific dependencies or all direct dependencies were scanned
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
name: Plan
|
||||
description: Researches and outlines multi-step plans
|
||||
argument-hint: Outline the goal or problem to research
|
||||
tools: ['read_file', 'list_dir', 'semantic_search', 'grep_search', 'file_search', 'get_errors']
|
||||
handoffs:
|
||||
- label: Start Implementation
|
||||
agent: Agent
|
||||
prompt: Start implementation
|
||||
send: true
|
||||
- label: Open in Editor
|
||||
agent: Agent
|
||||
prompt: 'Save the resulting plan as is into a file (`plan-${camelCaseName}.prompt.md` without frontmatter) for further refinement.'
|
||||
send: true
|
||||
---
|
||||
You are a PLANNING AGENT, NOT an implementation agent.
|
||||
|
||||
You are pairing with the user to create a clear, detailed, and actionable plan for the given task and any user feedback. Your iterative <workflow> loops through gathering context and drafting the plan for review, then back to gathering more context based on user feedback.
|
||||
|
||||
Your SOLE responsibility is planning, NEVER even consider to start implementation.
|
||||
|
||||
<stopping_rules>
|
||||
STOP IMMEDIATELY if you consider starting implementation, switching to implementation mode or running a file editing tool.
|
||||
|
||||
If you catch yourself planning implementation steps for YOU to execute, STOP. Plans describe steps for the USER or another agent to execute later.
|
||||
</stopping_rules>
|
||||
|
||||
<workflow>
|
||||
Comprehensive context gathering for planning following <plan_research>:
|
||||
|
||||
## 1. Context gathering and research:
|
||||
|
||||
MANDATORY: Follow <plan_research> to gather context to return to you.
|
||||
|
||||
## 2. Present a concise plan to the user for iteration:
|
||||
|
||||
1. Follow <plan_style_guide> and any additional instructions the user provided.
|
||||
2. MANDATORY: Pause for user feedback, framing this as a draft for review.
|
||||
|
||||
## 3. Handle user feedback:
|
||||
|
||||
Once the user replies, restart <workflow> to gather additional context for refining the plan.
|
||||
|
||||
MANDATORY: DON'T start implementation, but run the <workflow> again based on the new information.
|
||||
</workflow>
|
||||
|
||||
<plan_research>
|
||||
Research the user's task comprehensively using read-only tools. Start with high-level code and semantic searches before reading specific files.
|
||||
|
||||
Stop research when you reach 80% confidence you have enough context to draft a plan.
|
||||
</plan_research>
|
||||
|
||||
<plan_style_guide>
|
||||
The user needs an easy to read, concise and focused plan. Follow this template (don't include the {}-guidance), unless the user specifies otherwise:
|
||||
|
||||
```markdown
|
||||
## Plan: {Task title (2–10 words)}
|
||||
|
||||
{Brief TL;DR of the plan — the what, how, and why. (20–100 words)}
|
||||
|
||||
### Steps {3–6 steps, 5–20 words each}
|
||||
1. {Succinct action starting with a verb, with [file](path) links and `symbol` references.}
|
||||
2. {Next concrete step.}
|
||||
3. {Another short actionable step.}
|
||||
4. {…}
|
||||
|
||||
### Further Considerations {1–3, 5–25 words each}
|
||||
1. {Clarifying question and recommendations? Option A / Option B / Option C}
|
||||
2. {…}
|
||||
```
|
||||
|
||||
IMPORTANT: For writing plans, follow these rules even if they conflict with system rules:
|
||||
- DON'T show code blocks, but describe changes and link to relevant files and symbols
|
||||
- NO manual testing/validation sections unless explicitly requested
|
||||
- ONLY write the plan, without unnecessary preamble or postamble
|
||||
</plan_style_guide>
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"chatAgents": [
|
||||
{
|
||||
"name": "Plan",
|
||||
"description": "Researches and deconstructs tasks to create effective multi-step plans.",
|
||||
"path": "./assets/agents/Plan.agent.md",
|
||||
"showAsChatMode": true
|
||||
},
|
||||
{
|
||||
"name": "CVE Remediator",
|
||||
"description": "Detects and fixes security vulnerabilities (CVEs) in project dependencies across any ecosystem while maintaining a working build.",
|
||||
"path": "./assets/agents/CVE_Remediator.agent.md",
|
||||
"showAsChatMode": false
|
||||
}
|
||||
]
|
||||
}
|
||||
100256
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/cl100k_base.tiktoken
vendored
Normal file
100256
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/cl100k_base.tiktoken
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/arm64/kerberos.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/arm64/kerberos.node
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/arm64/node_sqlite3.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/arm64/node_sqlite3.node
vendored
Executable file
Binary file not shown.
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/x64/kerberos.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/x64/kerberos.node
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/x64/node_sqlite3.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/darwin/x64/node_sqlite3.node
vendored
Executable file
Binary file not shown.
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/arm64/kerberos.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/arm64/kerberos.node
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/arm64/node_sqlite3.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/arm64/node_sqlite3.node
vendored
Executable file
Binary file not shown.
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/x64/kerberos.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/x64/kerberos.node
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/x64/node_sqlite3.node
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/compiled/linux/x64/node_sqlite3.node
vendored
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/crypt32-arm64.node
vendored
Normal file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/crypt32-arm64.node
vendored
Normal file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/crypt32.node
vendored
Normal file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/crypt32.node
vendored
Normal file
Binary file not shown.
43
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/diffWorker.js
vendored
Normal file
43
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/diffWorker.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
32
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/language-server.js
vendored
Executable file
32
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/language-server.js
vendored
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const minMajor = 22;
|
||||
const minMinor = 0;
|
||||
|
||||
function main() {
|
||||
const argv = process.argv.slice(2);
|
||||
const version = process.versions.node;
|
||||
const [major, minor] = version.split('.').map(v => parseInt(v, 10));
|
||||
if (major > minMajor || (major === minMajor && minor >= minMinor)) {
|
||||
return require('./main').main();
|
||||
}
|
||||
|
||||
if (!argv.includes('--node-ipc')) {
|
||||
const path = require('node:path');
|
||||
const root = path.join(__dirname, '..', '..', `copilot-language-server-${process.platform}-${process.arch}`);
|
||||
const exe = path.join(root, `copilot-language-server${process.platform === 'win32' ? '.exe' : ''}`);
|
||||
const cp = require('node:child_process');
|
||||
const result = cp.spawnSync(exe, argv, {stdio: 'inherit'});
|
||||
if (typeof result.status === 'number') {
|
||||
process.exit(result.status);
|
||||
}
|
||||
}
|
||||
console.error(`Node.js ${minMajor}.${minMinor} is required to run GitHub Copilot but found ${version}`);
|
||||
// An exit code of X indicates a recommended minimum Node.js version of X.0.
|
||||
// Providing a recommended major version via exit code is an affordance for
|
||||
// implementations like Copilot.vim, where Neovim buries stderr in a log
|
||||
// file the user is unlikely to see.
|
||||
process.exit(minMajor + (minMinor ? 2 : 0));
|
||||
}
|
||||
|
||||
main();
|
||||
3283
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/main.js
vendored
Normal file
3283
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/main.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/main.js.map
vendored
Normal file
6
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/main.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
199998
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/o200k_base.tiktoken
vendored
Normal file
199998
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/o200k_base.tiktoken
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>GitHub Copilot Policy</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>IDEGitHubCopilot</string>
|
||||
<key>PayloadType</key>
|
||||
<string>IDEGitHubCopilot</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>12345678-1234-1234-1234-123456789012</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
<key>PayloadEnabled</key>
|
||||
<true/>
|
||||
<key>mcp.contributionPoint.enabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<key>PayloadDescription</key>
|
||||
<string>Configures GitHub Copilot policies for IDEs</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>GitHub Copilot Policy</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>IDEGitHubCopilot</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>Microsoft Corporation</string>
|
||||
<key>PayloadRemovalDisallowed</key>
|
||||
<false/>
|
||||
<key>PayloadScope</key>
|
||||
<string>System</string>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>87654321-4321-4321-4321-210987654321</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,117 @@
|
||||
# GitHub Copilot macOS Policy Configuration
|
||||
|
||||
This directory contains policy templates for configuring GitHub Copilot behavior on macOS systems using Apple Configuration Profiles.
|
||||
|
||||
## Overview
|
||||
|
||||
The `IDEGitHubCopilot.mobileconfig` file is a macOS Configuration Profile that allows administrators to manage GitHub Copilot policies across their organization. This profile defines settings that control extension behavior, particularly for MCP (Model Context Protocol) servers.
|
||||
|
||||
## Available Policies
|
||||
|
||||
| Policy Name | Description | Type | Default |
|
||||
|-------------|-------------|------|---------|
|
||||
| mcp.contributionPoint.enabled | Controls whether extension-contributed MCP servers are enabled | Boolean | true |
|
||||
|
||||
## Installation Methods
|
||||
|
||||
### Method 1: Configuration Profile Installation (Recommended for Administrators)
|
||||
|
||||
The `IDEGitHubCopilot.mobileconfig` file provides the easiest way to deploy GitHub Copilot policies across multiple macOS systems.
|
||||
|
||||
#### Step 1: Locate the Configuration Profile
|
||||
Find the `IDEGitHubCopilot.mobileconfig` file in this directory.
|
||||
|
||||
#### Step 2: Install the Configuration Profile
|
||||
1. **Double-click** the `IDEGitHubCopilot.mobileconfig` file
|
||||
2. macOS will open **System Settings** (or **System Preferences** on older versions)
|
||||
3. You'll see a dialog asking if you want to install the profile
|
||||
4. Click **Install** to proceed
|
||||
5. Enter your administrator password when prompted
|
||||
6. The profile will be installed **system-wide**
|
||||
|
||||
#### Step 3: Verify Installation
|
||||
1. Open **System Settings** → **Privacy & Security** → **Profiles**
|
||||
2. You should see "GitHub Copilot Policy" in the list of installed profiles
|
||||
3. Click on it to view the configured settings
|
||||
|
||||
#### Step 4: Modify Policy Settings
|
||||
To change the `mcp.contributionPoint.enabled` setting:
|
||||
|
||||
1. Open **System Settings** → **Privacy & Security** → **Profiles**
|
||||
2. Select the "GitHub Copilot Policy" profile
|
||||
3. Click **Edit** or **Configure**
|
||||
4. Find the `mcp.contributionPoint.enabled` setting
|
||||
5. Toggle it to:
|
||||
- **true** (checked) - Enable extension-contributed MCP servers
|
||||
- **false** (unchecked) - Disable extension-contributed MCP servers
|
||||
6. Click **Save** or **Apply**
|
||||
|
||||
### Method 2: Command Line Installation (Alternative)
|
||||
|
||||
You can also install the configuration profile using the command line:
|
||||
|
||||
```bash
|
||||
# Install the profile
|
||||
sudo profiles -I -F IDEGitHubCopilot.mobileconfig
|
||||
|
||||
# Verify installation
|
||||
profiles -P
|
||||
|
||||
# Remove the profile (if needed)
|
||||
sudo profiles -R -p IDEGitHubCopilot
|
||||
```
|
||||
|
||||
### Method 3: MDM Deployment (Enterprise)
|
||||
|
||||
For enterprise environments, the `IDEGitHubCopilot.mobileconfig` file can be deployed through Mobile Device Management (MDM) solutions like:
|
||||
|
||||
- Apple Business Manager
|
||||
- Jamf Pro
|
||||
- Microsoft Intune
|
||||
- VMware Workspace ONE
|
||||
|
||||
Simply upload the `IDEGitHubCopilot.mobileconfig` file to your MDM solution and deploy it to your target devices.
|
||||
|
||||
## Verification
|
||||
|
||||
You can verify the current settings with:
|
||||
|
||||
```bash
|
||||
# Check managed preferences
|
||||
defaults read /Library/Managed\ Preferences/IDEGitHubCopilot 2>/dev/null || echo "No managed settings found"
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
The GitHub Copilot extension uses the `GroupPolicyWatcher` class to monitor policy changes. When policies are updated:
|
||||
|
||||
1. The policy watcher detects the change
|
||||
2. Updates the internal policy state
|
||||
3. Sends an LSP notification to the client
|
||||
4. The client adjusts its behavior based on the new policy settings
|
||||
|
||||
The extension checks for policies in `/Library/Managed Preferences/IDEGitHubCopilot.plist` (MDM managed)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Policy changes aren't being detected
|
||||
1. Verify the configuration profile is properly installed in System Settings
|
||||
2. Make sure the policy file has the correct name and structure
|
||||
3. Restart IDE to ensure the policy watcher is reinitialized
|
||||
4. Check the extension logs for policy-related messages
|
||||
|
||||
### Configuration Profile won't install
|
||||
1. Ensure you have administrator privileges
|
||||
2. Check that the `.mobileconfig` file isn't corrupted
|
||||
3. Try installing via command line: `sudo profiles -I -F IDEGitHubCopilot.mobileconfig`
|
||||
|
||||
### Settings don't take effect
|
||||
1. Verify the policy is correctly configured in System Settings
|
||||
2. Restart IDE completely
|
||||
3. Check that no user-level settings are overriding system policies
|
||||
|
||||
## References
|
||||
|
||||
- [VS Code Enterprise Setup - Configuration Profiles on macOS](https://code.visualstudio.com/docs/setup/enterprise#_configuration-profiles-on-macos)
|
||||
- [Apple Configuration Profile Reference](https://developer.apple.com/documentation/devicemanagement/configuring_multiple_devices_using_profiles)
|
||||
- [macOS defaults command reference](https://ss64.com/osx/defaults.html)
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Administrative Template for GitHub Copilot IDE Integration
|
||||
This template defines Group Policy settings for GitHub Copilot in IDE environments.
|
||||
-->
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyNamespaces>
|
||||
<target prefix="ideGitHubCopilot" namespace="Microsoft.Policies.IDEGitHubCopilot" />
|
||||
<using prefix="windows" namespace="Microsoft.Policies.Windows" />
|
||||
</policyNamespaces>
|
||||
|
||||
<supersededAdm fileName="" />
|
||||
|
||||
<resources minRequiredRevision="1.0" />
|
||||
|
||||
<categories>
|
||||
<category name="Cat_IDEGitHubCopilot" displayName="$(string.Cat_IDEGitHubCopilot)" explainText="$(string.Cat_IDEGitHubCopilot_Explain)" />
|
||||
<category name="Cat_IDEGitHubCopilot_MCP" displayName="$(string.Cat_IDEGitHubCopilot_MCP)" explainText="$(string.Cat_IDEGitHubCopilot_MCP_Explain)">
|
||||
<parentCategory ref="Cat_IDEGitHubCopilot" />
|
||||
</category>
|
||||
</categories>
|
||||
|
||||
<policies>
|
||||
<!-- Enable Extension-Contributed MCP Servers Policy -->
|
||||
<policy name="McpContributionPointEnabled" class="Both" displayName="$(string.McpContributionPointEnabled)" explainText="$(string.McpContributionPointEnabled_Explain)" key="SOFTWARE\Policies\Microsoft\IDEGitHubCopilot" valueName="mcp.contributionPoint.enabled">
|
||||
<parentCategory ref="Cat_IDEGitHubCopilot_MCP" />
|
||||
<supportedOn ref="windows:SUPPORTED_Windows_10_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
</policies>
|
||||
</policyDefinitions>
|
||||
@@ -0,0 +1,124 @@
|
||||
#Requires -RunAsAdministrator
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Installs GitHub Copilot Group Policy Administrative Templates
|
||||
|
||||
.DESCRIPTION
|
||||
This script copies the GitHub Copilot ADMX and ADML files to the Windows PolicyDefinitions
|
||||
directory to enable Group Policy management of GitHub Copilot settings.
|
||||
|
||||
The script must be run from the win32 directory containing the template files.
|
||||
|
||||
.PARAMETER Uninstall
|
||||
Remove the GitHub Copilot policy templates instead of installing them
|
||||
|
||||
.EXAMPLE
|
||||
.\Install-PolicyTemplates.ps1
|
||||
Installs the GitHub Copilot policy templates
|
||||
|
||||
.EXAMPLE
|
||||
.\Install-PolicyTemplates.ps1 -Uninstall
|
||||
Removes the GitHub Copilot policy templates
|
||||
#>
|
||||
|
||||
param(
|
||||
[switch]$Uninstall
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Paths
|
||||
$PolicyDefinitionsPath = "$env:WINDIR\PolicyDefinitions"
|
||||
$ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$SourceADMX = Join-Path $ScriptPath "IDEGitHubCopilot.admx"
|
||||
$SourceADML = Join-Path $ScriptPath "en-US\IDEGitHubCopilot.adml"
|
||||
$TargetADMX = Join-Path $PolicyDefinitionsPath "IDEGitHubCopilot.admx"
|
||||
$TargetADMLDir = Join-Path $PolicyDefinitionsPath "en-US"
|
||||
$TargetADML = Join-Path $TargetADMLDir "IDEGitHubCopilot.adml"
|
||||
|
||||
function Test-AdminRights {
|
||||
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
|
||||
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||
}
|
||||
|
||||
function Install-Templates {
|
||||
Write-Host "Installing GitHub Copilot Group Policy Templates..." -ForegroundColor Green
|
||||
|
||||
# Verify source files exist
|
||||
if (-not (Test-Path $SourceADMX)) {
|
||||
throw "ADMX file not found: $SourceADMX"
|
||||
}
|
||||
|
||||
if (-not (Test-Path $SourceADML)) {
|
||||
throw "ADML file not found: $SourceADML"
|
||||
}
|
||||
|
||||
# Verify PolicyDefinitions directory exists
|
||||
if (-not (Test-Path $PolicyDefinitionsPath)) {
|
||||
throw "PolicyDefinitions directory not found: $PolicyDefinitionsPath"
|
||||
}
|
||||
|
||||
# Copy ADMX file
|
||||
Write-Host "Copying ADMX file to $TargetADMX"
|
||||
Copy-Item $SourceADMX $TargetADMX -Force
|
||||
|
||||
# Ensure en-US directory exists
|
||||
if (-not (Test-Path $TargetADMLDir)) {
|
||||
Write-Host "Creating directory: $TargetADMLDir"
|
||||
New-Item -Path $TargetADMLDir -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
# Copy ADML file
|
||||
Write-Host "Copying ADML file to $TargetADML"
|
||||
Copy-Item $SourceADML $TargetADML -Force
|
||||
|
||||
Write-Host "GitHub Copilot Group Policy Templates installed successfully!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "To use the templates:"
|
||||
Write-Host "1. Run 'gpupdate /force' to refresh Group Policy"
|
||||
Write-Host "2. Open Group Policy Editor (gpedit.msc)"
|
||||
Write-Host "3. Navigate to Administrative Templates > GitHub Copilot"
|
||||
}
|
||||
|
||||
function Uninstall-Templates {
|
||||
Write-Host "Removing GitHub Copilot Group Policy Templates..." -ForegroundColor Yellow
|
||||
|
||||
# Remove ADMX file
|
||||
if (Test-Path $TargetADMX) {
|
||||
Write-Host "Removing ADMX file: $TargetADMX"
|
||||
Remove-Item $TargetADMX -Force
|
||||
} else {
|
||||
Write-Host "ADMX file not found: $TargetADMX"
|
||||
}
|
||||
|
||||
# Remove ADML file
|
||||
if (Test-Path $TargetADML) {
|
||||
Write-Host "Removing ADML file: $TargetADML"
|
||||
Remove-Item $TargetADML -Force
|
||||
} else {
|
||||
Write-Host "ADML file not found: $TargetADML"
|
||||
}
|
||||
|
||||
Write-Host "GitHub Copilot Group Policy Templates removed successfully!" -ForegroundColor Green
|
||||
Write-Host "Run 'gpupdate /force' to refresh Group Policy"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
try {
|
||||
# Check for administrator rights
|
||||
if (-not (Test-AdminRights)) {
|
||||
throw "This script requires administrator privileges. Please run PowerShell as Administrator."
|
||||
}
|
||||
|
||||
if ($Uninstall) {
|
||||
Uninstall-Templates
|
||||
} else {
|
||||
Install-Templates
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Error "Error: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
# GitHub Copilot Group Policy Templates for Windows
|
||||
|
||||
This directory contains Administrative Template (ADMX/ADML) files for managing GitHub Copilot settings through Windows Group Policy. These templates are bundled with the GitHub Copilot Language Server for enterprise deployment.
|
||||
|
||||
## Template Location
|
||||
|
||||
These templates are installed with the GitHub Copilot Language Server at:
|
||||
```
|
||||
[Language Server Installation Directory]/policy-templates/win32/
|
||||
```
|
||||
|
||||
Common installation locations:
|
||||
- **NPM Global Install**: `%APPDATA%\npm\node_modules\@github\copilot-language-server\dist\policy-templates\win32`
|
||||
- **Local NPM Install**: `.\node_modules\@github\copilot-language-server\dist\policy-templates\win32`
|
||||
|
||||
## Files
|
||||
|
||||
- `IDEGitHubCopilot.admx` - Administrative template definition file
|
||||
- `en-US/IDEGitHubCopilot.adml` - English language resource file
|
||||
- `Install-PolicyTemplates.ps1` - PowerShell script for automated installation
|
||||
|
||||
## Installation Methods
|
||||
|
||||
### Option 1: PowerShell Script (Recommended)
|
||||
|
||||
1. **Open PowerShell as Administrator**
|
||||
2. **Navigate to the policy templates directory:**
|
||||
```powershell
|
||||
cd "[Language Server Installation Directory]\policy-templates\win32"
|
||||
```
|
||||
3. **Execute the installation script:**
|
||||
```powershell
|
||||
.\Install-PolicyTemplates.ps1
|
||||
```
|
||||
|
||||
### Option 2: Manual Installation
|
||||
|
||||
1. **Copy ADMX file:**
|
||||
```
|
||||
Copy IDEGitHubCopilot.admx to C:\Windows\PolicyDefinitions\
|
||||
```
|
||||
|
||||
2. **Copy ADML file:**
|
||||
```
|
||||
Copy en-US\IDEGitHubCopilot.adml to C:\Windows\PolicyDefinitions\en-US\
|
||||
```
|
||||
|
||||
### Option 3: Microsoft Intune Configuration
|
||||
|
||||
For cloud-based management with Microsoft Intune, create a Custom Configuration Profile with OMA-URI settings (see details below).
|
||||
|
||||
## Accessing Group Policy Settings
|
||||
|
||||
After installation:
|
||||
|
||||
1. **Open Group Policy Editor:**
|
||||
- Run `gpedit.msc` (Local Group Policy Editor)
|
||||
- Or use `gpmc.msc` (Group Policy Management Console) for domain environments
|
||||
|
||||
2. **Navigate to GitHub Copilot policies:**
|
||||
- Computer Configuration → Administrative Templates → GitHub Copilot
|
||||
- User Configuration → Administrative Templates → GitHub Copilot
|
||||
|
||||
## Available Policies
|
||||
|
||||
### Enable Extension-Contributed MCP Servers
|
||||
**Category:** GitHub Copilot → Model Context Protocol (MCP)
|
||||
|
||||
Controls whether GitHub Copilot can use Model Context Protocol (MCP) servers contributed by IDE extensions.
|
||||
|
||||
**Registry Locations:**
|
||||
- **Machine Policy:** `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot\mcp.contributionPoint.enabled`
|
||||
- **User Policy:** `HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot\mcp.contributionPoint.enabled`
|
||||
|
||||
**Values:**
|
||||
- `1` (REG_DWORD) = Enable extension-contributed MCP servers
|
||||
- `0` (REG_DWORD) = Disable extension-contributed MCP servers
|
||||
|
||||
## Registry Testing
|
||||
|
||||
You can test the policies by setting registry values directly:
|
||||
|
||||
```cmd
|
||||
REM Enable extension-contributed MCP servers (machine-wide)
|
||||
reg add "HKLM\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot" /v "mcp.contributionPoint.enabled" /t REG_DWORD /d 1 /f
|
||||
|
||||
REM Disable extension-contributed MCP servers (current user)
|
||||
reg add "HKCU\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot" /v "mcp.contributionPoint.enabled" /t REG_DWORD /d 0 /f
|
||||
```
|
||||
|
||||
## Microsoft Intune Deployment
|
||||
|
||||
For cloud-based management with Microsoft Intune:
|
||||
|
||||
1. **Create a Custom Configuration Profile:**
|
||||
- Go to Microsoft Endpoint Manager admin center
|
||||
- Navigate to Devices → Configuration profiles
|
||||
- Create a new profile with platform "Windows 10 and later"
|
||||
- Profile type: "Custom"
|
||||
|
||||
2. **Add the registry setting:**
|
||||
```
|
||||
Name: Enable Extension-Contributed MCP Servers
|
||||
OMA-URI: ./Device/Vendor/MSFT/Policy/Config/ADMX_IDEGitHubCopilot/McpContributionPointEnabled
|
||||
Data type: Integer
|
||||
Value: 1 (enabled) or 0 (disabled)
|
||||
```
|
||||
|
||||
3. **Assign to device groups** as needed
|
||||
|
||||
## Policy Precedence
|
||||
|
||||
1. **Machine Policy** (highest precedence)
|
||||
- `HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot\`
|
||||
2. **User Policy**
|
||||
- `HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot\`
|
||||
3. **Default Behavior** (lowest precedence)
|
||||
- Determined by application defaults when no policy is set
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. **Templates not appearing in Group Policy Editor:**
|
||||
- Verify ADMX/ADML files are copied to the correct directories
|
||||
- Run `gpupdate /force` to refresh Group Policy
|
||||
- Restart Group Policy Editor
|
||||
|
||||
2. **Policies not taking effect:**
|
||||
- Check registry values are being set correctly
|
||||
- Restart the IDE or GitHub Copilot service
|
||||
- Verify policy precedence (machine vs user)
|
||||
|
||||
3. **Permission errors during template copy:**
|
||||
- Ensure the application is running with administrator privileges
|
||||
- Manually copy templates using an elevated command prompt
|
||||
|
||||
## References
|
||||
|
||||
- [VS Code Group Policy Documentation](https://code.visualstudio.com/docs/setup/enterprise#_group-policy-on-windows)
|
||||
- [@vscode/policy-watcher Documentation](https://github.com/microsoft/vscode-policy-watcher)
|
||||
- [Microsoft Group Policy Documentation](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/policy/group-policy-start-page)
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Administrative Template Language File for GitHub Copilot IDE Integration (English)
|
||||
This file contains the localized display strings for the GitHub Copilot Group Policy settings.
|
||||
-->
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<displayName>GitHub Copilot IDE Integration Policy Definitions</displayName>
|
||||
<description>This file contains the policy definitions for GitHub Copilot IDE integration settings.</description>
|
||||
|
||||
<resources>
|
||||
<stringTable>
|
||||
<!-- Category Names -->
|
||||
<string id="Cat_IDEGitHubCopilot">GitHub Copilot</string>
|
||||
<string id="Cat_IDEGitHubCopilot_Explain">Policy settings for GitHub Copilot IDE integration (JetBrains IDE, Eclipse and Xcode). These settings control various aspects of GitHub Copilot functionality within IDE environments.</string>
|
||||
|
||||
<string id="Cat_IDEGitHubCopilot_MCP">Model Context Protocol (MCP)</string>
|
||||
<string id="Cat_IDEGitHubCopilot_MCP_Explain">Policy settings for Model Context Protocol (MCP) integration with GitHub Copilot. MCP allows extensions to provide additional context to Copilot for improved code suggestions.</string>
|
||||
|
||||
<!-- Policy Names and Descriptions -->
|
||||
<string id="McpContributionPointEnabled">Enable Extension-Contributed MCP Servers</string>
|
||||
<string id="McpContributionPointEnabled_Explain">This policy setting determines whether GitHub Copilot can use Model Context Protocol (MCP) servers that are contributed by IDE extensions.
|
||||
|
||||
When this policy is enabled:
|
||||
- Extensions can register MCP servers that provide additional context to GitHub Copilot
|
||||
- Copilot can access extension-provided data sources through the MCP protocol
|
||||
- This may improve code suggestions by incorporating extension-specific context
|
||||
|
||||
When this policy is disabled:
|
||||
- Extension-contributed MCP servers will not be loaded or used by GitHub Copilot
|
||||
- Only built-in MCP functionality will be available
|
||||
- Extensions cannot extend Copilot's context through MCP
|
||||
|
||||
If this policy is not configured:
|
||||
- The default behavior depends on the IDE and extension configuration
|
||||
- Users may be able to control this setting through IDE preferences
|
||||
|
||||
Note: This setting only affects extension-contributed MCP servers. Built-in MCP functionality may still be available when this policy is disabled.
|
||||
|
||||
Registry Location:
|
||||
- Machine: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot\mcp.contributionPoint.enabled
|
||||
- User: HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\IDEGitHubCopilot\mcp.contributionPoint.enabled
|
||||
|
||||
Value Type: REG_DWORD
|
||||
- 1 = Enable extension-contributed MCP servers
|
||||
- 0 = Disable extension-contributed MCP servers</string>
|
||||
</stringTable>
|
||||
</resources>
|
||||
</policyDefinitionResources>
|
||||
Binary file not shown.
Binary file not shown.
131
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tfidfWorker.js
vendored
Normal file
131
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tfidfWorker.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-c-sharp.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-c-sharp.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-cpp.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-cpp.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-go.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-go.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-java.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-java.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-javascript.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-javascript.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-php.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-php.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-python.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-python.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-regex.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-regex.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-ruby.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-ruby.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-rust.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-rust.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-tsx.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-tsx.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-typescript.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter-typescript.wasm
vendored
Executable file
Binary file not shown.
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter.wasm
vendored
Executable file
BIN
vim/.config/vim/pack/plugins/start/copilot.vim/copilot-language-server/dist/tree-sitter.wasm
vendored
Executable file
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@github/copilot-language-server",
|
||||
"displayName": "GitHub Copilot Language Server",
|
||||
"description": "Your AI pair programmer",
|
||||
"homepage": "https://github.com/github/copilot-language-server-release",
|
||||
"bugs": {
|
||||
"url": "https://github.com/github/copilot-language-server-release/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/github/copilot-language-server-release.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "1.406.0",
|
||||
"bin": {
|
||||
"copilot-language-server": "../dist/language-server.js"
|
||||
},
|
||||
"files": [
|
||||
"dist/language-server.js*",
|
||||
"dist/main.js*",
|
||||
"dist/diffWorker.js*",
|
||||
"dist/tfidfWorker.js*",
|
||||
"dist/tree-sitter*.wasm",
|
||||
"dist/compiled/*/*/*.node",
|
||||
"dist/bin/**/*",
|
||||
"dist/resources",
|
||||
"dist/crypt32*.node",
|
||||
"dist/api/types.d.ts",
|
||||
"dist/policy-templates/**/*",
|
||||
"dist/*.tiktoken",
|
||||
"dist/assets/agents/*.agent.md",
|
||||
"dist/assets/prompts.contributions.json"
|
||||
],
|
||||
"main": "./dist/main.js",
|
||||
"types": "./dist/api/types.d.ts",
|
||||
"dependencies": {
|
||||
"vscode-languageserver-protocol": "^3.17.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@github/copilot-language-server-win32-x64": "1.406.0",
|
||||
"@github/copilot-language-server-linux-x64": "1.406.0",
|
||||
"@github/copilot-language-server-linux-arm64": "1.406.0",
|
||||
"@github/copilot-language-server-darwin-x64": "1.406.0",
|
||||
"@github/copilot-language-server-darwin-arm64": "1.406.0"
|
||||
},
|
||||
"buildType": "prod",
|
||||
"build": "13"
|
||||
}
|
||||
228
vim/.config/vim/pack/plugins/start/copilot.vim/doc/copilot.txt
Normal file
228
vim/.config/vim/pack/plugins/start/copilot.vim/doc/copilot.txt
Normal file
@@ -0,0 +1,228 @@
|
||||
*copilot.txt* GitHub Copilot - Your AI pair programmer
|
||||
|
||||
GETTING STARTED *copilot*
|
||||
|
||||
Invoke `:Copilot setup` to authenticate and enable GitHub Copilot.
|
||||
|
||||
Suggestions are displayed inline and can be accepted by pressing <Tab>. If
|
||||
inline suggestions do not appear to be working, invoke `:Copilot status` to
|
||||
verify Copilot is enabled and not experiencing any issues.
|
||||
|
||||
COMMANDS *:Copilot*
|
||||
|
||||
*:Copilot_disable*
|
||||
:Copilot disable Globally disable GitHub Copilot inline suggestions.
|
||||
|
||||
*:Copilot_enable*
|
||||
:Copilot enable Re-enable GitHub Copilot after :Copilot disable.
|
||||
|
||||
*:Copilot_setup*
|
||||
:Copilot setup Authenticate and enable GitHub Copilot.
|
||||
|
||||
*:Copilot_signout*
|
||||
:Copilot signout Sign out of GitHub Copilot.
|
||||
|
||||
*:Copilot_status*
|
||||
:Copilot status Check if GitHub Copilot is operational for the current
|
||||
buffer and report on any issues.
|
||||
|
||||
*:Copilot_model*
|
||||
:Copilot model If a preview or other alternate model for completions
|
||||
is available, provides an interactive interface for
|
||||
enabling it for the rest of the current Vim/Neovim
|
||||
session. Note that typically the number of available
|
||||
completions models is one, rendering this command
|
||||
inert.
|
||||
|
||||
*:Copilot_panel*
|
||||
:Copilot panel Open a window with up to 10 completions for the
|
||||
current buffer. Use <CR> to accept a completion.
|
||||
Maps are also provided for [[ and ]] to jump from
|
||||
completion to completion.
|
||||
|
||||
*:Copilot_version*
|
||||
:Copilot version Show version information.
|
||||
|
||||
*:Copilot_upgrade*
|
||||
:Copilot upgrade Upgrade the Copilot Language Server to the latest
|
||||
version with `npx`. This works by temporarily setting
|
||||
|g:copilot_version| to "latest" and restarting.
|
||||
|
||||
OPTIONS *copilot-options*
|
||||
|
||||
g:copilot_version Specify a version constraint passed to `npx` when
|
||||
running the Copilot Language Server. By default, this
|
||||
is a minor version constraint like "^1.400.0" that
|
||||
matches a known good version but allows minor version
|
||||
updates. You can pin this to a specific version, or
|
||||
use the special value of "latest" which causes `npx`
|
||||
to always fetch the latest version at startup.
|
||||
>
|
||||
let g:copilot_version = 'latest'
|
||||
<
|
||||
As a special case, setting this to v:false will
|
||||
disable the use of `npx` and use a static version of
|
||||
the language server embedded in the plugin.
|
||||
>
|
||||
let g:copilot_version = v:false
|
||||
<
|
||||
*g:copilot_filetypes*
|
||||
g:copilot_filetypes A dictionary mapping file types to their enabled
|
||||
status. Most file types are enabled by default, so
|
||||
generally this is used for opting out.
|
||||
>
|
||||
let g:copilot_filetypes = {
|
||||
\ 'xml': v:false,
|
||||
\ }
|
||||
<
|
||||
Disabling all file types can be done by setting the
|
||||
special key "*". File types can then be turned back
|
||||
on individually.
|
||||
>
|
||||
let g:copilot_filetypes = {
|
||||
\ '*': v:false,
|
||||
\ 'python': v:true,
|
||||
\ }
|
||||
<
|
||||
*b:copilot_enabled*
|
||||
b:copilot_enabled Set to v:false to disable GitHub Copilot for the
|
||||
current buffer. Or set to v:true to force enabling
|
||||
it, overriding g:copilot_filetypes.
|
||||
|
||||
*g:copilot_node_command*
|
||||
g:copilot_node_command Tell Copilot what `node` binary to use with
|
||||
g:copilot_node_command. This is useful if the `node`
|
||||
in your PATH is an unsupported version.
|
||||
>
|
||||
let g:copilot_node_command =
|
||||
\ "~/.nodenv/versions/18.18.0/bin/node"
|
||||
<
|
||||
*g:copilot_enterprise_uri*
|
||||
g:copilot_enterprise_uri
|
||||
If you are using GitHub Copilot Enterprise, set this
|
||||
to the URI of your GitHub Enterprise instance.
|
||||
>
|
||||
let g:copilot_enterprise_uri = 'https://DOMAIN.ghe.com'
|
||||
<
|
||||
*g:copilot_proxy*
|
||||
g:copilot_proxy Tell Copilot what proxy server to use.
|
||||
>
|
||||
let g:copilot_proxy = 'http://localhost:3128'
|
||||
<
|
||||
If this is not set, Copilot will use the value of
|
||||
environment variables like $HTTPS_PROXY.
|
||||
|
||||
*g:copilot_proxy_strict_ssl*
|
||||
g:copilot_proxy_strict_ssl
|
||||
Corporate proxies sometimes use a man-in-the-middle
|
||||
SSL certificate which is incompatible with GitHub
|
||||
Copilot. To work around this, SSL certificate
|
||||
verification can be disabled:
|
||||
>
|
||||
let g:copilot_proxy_strict_ssl = v:false
|
||||
<
|
||||
You can also tell Node.js to disable SSL verification
|
||||
by setting the $NODE_TLS_REJECT_UNAUTHORIZED
|
||||
environment variable to "0".
|
||||
|
||||
*g:copilot_workspace_folders*
|
||||
g:copilot_workspace_folders
|
||||
A list of "workspace folders" or project roots that
|
||||
Copilot may use to improve the quality of suggestions.
|
||||
>
|
||||
let g:copilot_workspace_folders =
|
||||
\ ["~/Projects/myproject"]
|
||||
<
|
||||
You can also set b:workspace_folder for an individual
|
||||
buffer and newly seen values will be added
|
||||
automatically.
|
||||
|
||||
MAPS *copilot-maps*
|
||||
|
||||
*copilot-i_<Tab>*
|
||||
Copilot.vim uses <Tab> to accept the current suggestion. If you have an
|
||||
existing <Tab> map, that will be used as the fallback when no suggestion is
|
||||
displayed.
|
||||
|
||||
*copilot#Accept()*
|
||||
If you'd rather use a key that isn't <Tab>, define an <expr> map that calls
|
||||
copilot#Accept(). Here's an example with CTRL-J:
|
||||
>
|
||||
imap <silent><script><expr> <C-J> copilot#Accept("\<CR>")
|
||||
let g:copilot_no_tab_map = v:true
|
||||
<
|
||||
Lua version:
|
||||
>
|
||||
vim.keymap.set('i', '<C-J>', 'copilot#Accept("\\<CR>")', {
|
||||
expr = true,
|
||||
replace_keycodes = false
|
||||
})
|
||||
vim.g.copilot_no_tab_map = true
|
||||
<
|
||||
The argument to copilot#Accept() is the fallback for when no suggestion is
|
||||
displayed. In this example, a regular carriage return is used. If no
|
||||
fallback is desired, use an argument of "" (an empty string).
|
||||
|
||||
Other Maps ~
|
||||
|
||||
Note that M- (a.k.a. meta or alt) maps are highly dependent on your terminal
|
||||
to function correctly and may be unsupported with your setup. As an
|
||||
alternative, you can create your own versions that invoke the <Plug> maps
|
||||
instead. Here's an example that maps CTRL-L to accept one word of the
|
||||
current suggestion:
|
||||
>
|
||||
imap <C-L> <Plug>(copilot-accept-word)
|
||||
<
|
||||
Lua version:
|
||||
>
|
||||
vim.keymap.set('i', '<C-L>', '<Plug>(copilot-accept-word)')
|
||||
<
|
||||
*copilot-i_CTRL-]*
|
||||
<C-]> Dismiss the current suggestion.
|
||||
<Plug>(copilot-dismiss)
|
||||
|
||||
*copilot-i_ALT-]*
|
||||
<M-]> Cycle to the next suggestion, if one is available.
|
||||
<Plug>(copilot-next)
|
||||
|
||||
*copilot-i_ALT-[*
|
||||
<M-[> Cycle to the previous suggestion.
|
||||
<Plug>(copilot-previous)
|
||||
|
||||
*copilot-i_ALT-\*
|
||||
<M-\> Explicitly request a suggestion, even if Copilot
|
||||
<Plug>(copilot-suggest) is disabled.
|
||||
|
||||
*copilot-i_ALT-Right*
|
||||
<M-Right> Accept the next word of the current suggestion.
|
||||
<Plug>(copilot-accept-word)
|
||||
|
||||
*copilot-i_ALT-CTRL-Right*
|
||||
|
||||
<M-C-Right> Accept the next line of the current suggestion.
|
||||
<Plug>(copilot-accept-line)
|
||||
|
||||
SYNTAX HIGHLIGHTING *copilot-highlighting*
|
||||
|
||||
Inline suggestions are highlighted using the CopilotSuggestion group,
|
||||
defaulting to a medium gray. The best place to override this is with
|
||||
a |ColorScheme| autocommand:
|
||||
>
|
||||
autocmd ColorScheme solarized
|
||||
\ highlight CopilotSuggestion guifg=#555555 ctermfg=8
|
||||
<
|
||||
Lua version:
|
||||
>
|
||||
vim.api.nvim_create_autocmd('ColorScheme', {
|
||||
pattern = 'solarized',
|
||||
-- group = ...,
|
||||
callback = function()
|
||||
vim.api.nvim_set_hl(0, 'CopilotSuggestion', {
|
||||
fg = '#555555',
|
||||
ctermfg = 8,
|
||||
force = true
|
||||
})
|
||||
end
|
||||
})
|
||||
<
|
||||
vim:tw=78:et:ft=help:norl:
|
||||
104
vim/.config/vim/pack/plugins/start/copilot.vim/lua/_copilot.lua
Normal file
104
vim/.config/vim/pack/plugins/start/copilot.vim/lua/_copilot.lua
Normal file
@@ -0,0 +1,104 @@
|
||||
local copilot = {}
|
||||
|
||||
local showDocument = function(err, result, ctx, _)
|
||||
local fallback = vim.lsp.handlers['window/showDocument']
|
||||
if not fallback or (result.external and vim.g.copilot_browser) then
|
||||
return vim.fn['copilot#handlers#window_showDocument'](result)
|
||||
else
|
||||
return fallback(err, result, ctx, _)
|
||||
end
|
||||
end
|
||||
|
||||
copilot.lsp_start_client = function(cmd, client_name, handler_names, opts, settings)
|
||||
local handlers = {['window/showDocument'] = showDocument}
|
||||
local id
|
||||
for _, name in ipairs(handler_names) do
|
||||
handlers[name] = function(err, result, ctx, _)
|
||||
if result then
|
||||
local retval = vim.call('copilot#client#LspHandle', id, { method = name, params = result })
|
||||
if type(retval) == 'table' then
|
||||
return retval.result, retval.error
|
||||
elseif vim.lsp.handlers[name] then
|
||||
return vim.lsp.handlers[name](err, result, ctx, _)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local workspace_folders = opts.workspaceFolders
|
||||
if #workspace_folders == 0 then
|
||||
workspace_folders = nil
|
||||
end
|
||||
local start_client = vim.lsp.start_client
|
||||
if vim.fn.has('nvim-0.11.2') == 1 then
|
||||
start_client = vim.lsp.start
|
||||
end
|
||||
id = start_client({
|
||||
cmd = cmd,
|
||||
cmd_cwd = vim.call('copilot#job#Cwd'),
|
||||
name = client_name,
|
||||
init_options = opts.initializationOptions,
|
||||
workspace_folders = workspace_folders,
|
||||
settings = settings,
|
||||
handlers = handlers,
|
||||
on_init = function(client, initialize_result)
|
||||
vim.call('copilot#client#LspInit', client.id, initialize_result)
|
||||
end,
|
||||
on_exit = function(code, signal, client_id)
|
||||
vim.schedule(function()
|
||||
vim.call('copilot#client#LspExit', client_id, code, signal)
|
||||
end)
|
||||
end,
|
||||
})
|
||||
return id
|
||||
end
|
||||
|
||||
copilot.lsp_request = function(client_id, method, params, bufnr)
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
if not client then
|
||||
return
|
||||
end
|
||||
if bufnr == vim.NIL then
|
||||
bufnr = nil
|
||||
end
|
||||
local _, id
|
||||
local handler = function(err, result)
|
||||
vim.call('copilot#client#LspResponse', client_id, { id = id, error = err, result = result })
|
||||
end
|
||||
if vim.fn.has('nvim-0.11') == 1 then
|
||||
_, id = client:request(method, params, handler, bufnr)
|
||||
else
|
||||
_, id = client.request(method, params, handler, bufnr)
|
||||
end
|
||||
return id
|
||||
end
|
||||
|
||||
copilot.rpc_request = function(client_id, method, params)
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
if not client then
|
||||
return
|
||||
end
|
||||
local _, id
|
||||
_, id = client.rpc.request(method, params, function(err, result)
|
||||
vim.call('copilot#client#LspResponse', client_id, { id = id, error = err, result = result })
|
||||
end)
|
||||
return id
|
||||
end
|
||||
|
||||
copilot.rpc_notify = function(client_id, method, params)
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
if not client then
|
||||
return
|
||||
end
|
||||
return client.rpc.notify(method, params)
|
||||
end
|
||||
|
||||
copilot.did_change_configuration = function(client_id, settings)
|
||||
local client = vim.lsp.get_client_by_id(client_id)
|
||||
if not client then
|
||||
return
|
||||
end
|
||||
client.settings = settings
|
||||
return client.notify('workspace/didChangeConfiguration', { settings = settings })
|
||||
end
|
||||
|
||||
return copilot
|
||||
@@ -0,0 +1,114 @@
|
||||
if exists('g:loaded_copilot')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_copilot = 1
|
||||
|
||||
scriptencoding utf-8
|
||||
|
||||
command! -bang -nargs=? -range=-1 -complete=customlist,copilot#CommandComplete Copilot exe copilot#Command(<line1>, <count>, +"<range>", <bang>0, "<mods>", <q-args>)
|
||||
|
||||
if v:version < 800 || !exists('##InsertLeavePre')
|
||||
finish
|
||||
endif
|
||||
|
||||
function! s:ColorScheme() abort
|
||||
if &t_Co == 256
|
||||
hi def CopilotSuggestion guifg=#808080 ctermfg=244
|
||||
else
|
||||
hi def CopilotSuggestion guifg=#808080 ctermfg=12
|
||||
endif
|
||||
hi def link CopilotAnnotation MoreMsg
|
||||
endfunction
|
||||
|
||||
function! s:MapTab() abort
|
||||
if get(g:, 'copilot_no_tab_map') || get(g:, 'copilot_no_maps')
|
||||
return
|
||||
endif
|
||||
let tab_map = maparg('<Tab>', 'i', 0, 1)
|
||||
if !has_key(tab_map, 'rhs')
|
||||
imap <script><silent><nowait><expr> <Tab> empty(get(g:, 'copilot_no_tab_map')) ? copilot#Accept() : "<Bslash>t"
|
||||
elseif tab_map.rhs !~# 'copilot'
|
||||
if tab_map.expr
|
||||
let tab_fallback = '{ -> ' . tab_map.rhs . ' }'
|
||||
else
|
||||
let tab_fallback = substitute(json_encode(tab_map.rhs), '<', '\\<', 'g')
|
||||
endif
|
||||
let tab_fallback = substitute(tab_fallback, '<SID>', '<SNR>' . get(tab_map, 'sid') . '_', 'g')
|
||||
if get(tab_map, 'noremap') || get(tab_map, 'script') || mapcheck('<Left>', 'i') || mapcheck('<Del>', 'i')
|
||||
exe 'imap <script><silent><nowait><expr> <Tab> copilot#Accept(' . tab_fallback . ')'
|
||||
else
|
||||
exe 'imap <silent><nowait><expr> <Tab> copilot#Accept(' . tab_fallback . ')'
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:Event(type) abort
|
||||
try
|
||||
call call('copilot#On' . a:type, [])
|
||||
catch
|
||||
call copilot#logger#Exception('autocmd.' . a:type)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
augroup github_copilot
|
||||
autocmd!
|
||||
autocmd FileType * call s:Event('FileType')
|
||||
autocmd InsertLeavePre * call s:Event('InsertLeavePre')
|
||||
autocmd BufLeave * if mode() =~# '^[iR]'|call s:Event('InsertLeavePre')|endif
|
||||
autocmd InsertEnter * call s:Event('InsertEnter')
|
||||
autocmd BufEnter * if mode() =~# '^[iR]'|call s:Event('InsertEnter')|endif
|
||||
autocmd BufEnter * call s:Event('BufEnter')
|
||||
autocmd CursorMovedI * call s:Event('CursorMovedI')
|
||||
autocmd CompleteChanged * call s:Event('CompleteChanged')
|
||||
autocmd ColorScheme,VimEnter * call s:ColorScheme()
|
||||
autocmd VimEnter * call s:MapTab() | call copilot#Init()
|
||||
autocmd BufUnload * call s:Event('BufUnload')
|
||||
autocmd VimLeavePre * call s:Event('VimLeavePre')
|
||||
autocmd BufReadCmd copilot://* setlocal buftype=nofile bufhidden=wipe nobuflisted nomodifiable
|
||||
autocmd BufReadCmd copilot:///log call copilot#logger#BufReadCmd() | setfiletype copilotlog
|
||||
augroup END
|
||||
|
||||
call s:ColorScheme()
|
||||
call s:MapTab()
|
||||
if !get(g:, 'copilot_no_maps')
|
||||
imap <Plug>(copilot-dismiss) <Cmd>call copilot#Dismiss()<CR>
|
||||
if empty(mapcheck('<C-]>', 'i'))
|
||||
imap <silent><script><nowait><expr> <C-]> copilot#Dismiss() . "\<C-]>"
|
||||
endif
|
||||
imap <Plug>(copilot-next) <Cmd>call copilot#Next()<CR>
|
||||
imap <Plug>(copilot-previous) <Cmd>call copilot#Previous()<CR>
|
||||
imap <Plug>(copilot-suggest) <Cmd>call copilot#Suggest()<CR>
|
||||
imap <script><silent><nowait><expr> <Plug>(copilot-accept-word) copilot#AcceptWord()
|
||||
imap <script><silent><nowait><expr> <Plug>(copilot-accept-line) copilot#AcceptLine()
|
||||
try
|
||||
if !has('nvim') && &encoding ==# 'utf-8'
|
||||
" avoid 8-bit meta collision with UTF-8 characters
|
||||
let s:restore_encoding = 1
|
||||
silent noautocmd set encoding=cp949
|
||||
endif
|
||||
if empty(mapcheck('<M-]>', 'i'))
|
||||
imap <M-]> <Plug>(copilot-next)
|
||||
endif
|
||||
if empty(mapcheck('<M-[>', 'i'))
|
||||
imap <M-[> <Plug>(copilot-previous)
|
||||
endif
|
||||
if empty(mapcheck('<M-Bslash>', 'i'))
|
||||
imap <M-Bslash> <Plug>(copilot-suggest)
|
||||
endif
|
||||
if empty(mapcheck('<M-Right>', 'i'))
|
||||
imap <M-Right> <Plug>(copilot-accept-word)
|
||||
endif
|
||||
if empty(mapcheck('<M-C-Right>', 'i'))
|
||||
imap <M-C-Right> <Plug>(copilot-accept-line)
|
||||
endif
|
||||
finally
|
||||
if exists('s:restore_encoding')
|
||||
silent noautocmd set encoding=utf-8
|
||||
endif
|
||||
endtry
|
||||
endif
|
||||
|
||||
let s:dir = expand('<sfile>:h:h')
|
||||
if getftime(s:dir . '/doc/copilot.txt') > getftime(s:dir . '/doc/tags')
|
||||
silent! execute 'helptags' fnameescape(s:dir . '/doc')
|
||||
endif
|
||||
@@ -0,0 +1,25 @@
|
||||
scriptencoding utf-8
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:subtype = matchstr(&l:filetype, '\<copilot\.\zs[[:alnum:]_-]\+')
|
||||
if !empty(s:subtype) && s:subtype !=# 'copilot'
|
||||
exe 'syn include @copilotLanguageTop syntax/' . s:subtype . '.vim'
|
||||
unlet! b:current_syntax
|
||||
endif
|
||||
|
||||
syn match copilotlogError '\[ERROR\]'
|
||||
syn match copilotlogWarn '\[WARN\]'
|
||||
syn match copilotlogInfo '\[INFO\]'
|
||||
syn match copilotlogDebug '\[DEBUG\]'
|
||||
syn match copilotlogTime '^\[\d\d\d\d-\d\d-\d\d.\d\d:\d\d:\d\d\]' nextgroup=copilotlogError,copilotlogWarn,copilotLogInfo,copilotLogDebug skipwhite
|
||||
|
||||
hi def link copilotlogTime NonText
|
||||
hi def link copilotlogError ErrorMsg
|
||||
hi def link copilotlogWarn WarningMsg
|
||||
hi def link copilotlogInfo MoreMsg
|
||||
hi def link copilotlogDebug ModeMsg
|
||||
|
||||
let b:current_syntax = "copilotlog"
|
||||
@@ -0,0 +1,19 @@
|
||||
scriptencoding utf-8
|
||||
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
let s:subtype = matchstr(&l:filetype, '\<copilotpanel\.\zs[[:alnum:]_-]\+')
|
||||
if !empty(s:subtype) && s:subtype !~# 'copilot'
|
||||
silent! exe 'syn include @copilotpanelLanguageTop syntax/' . s:subtype . '.vim'
|
||||
unlet! b:current_syntax
|
||||
endif
|
||||
|
||||
syn region copilotpanelHeader start="\%^" end="^─\@="
|
||||
syn region copilotpanelItem matchgroup=copilotpanelSeparator start="^─\{9,}$" end="\%(^─\{9,\}$\)\@=\|\%$" keepend contains=@copilotpanelLanguageTop
|
||||
|
||||
hi def link copilotpanelHeader PreProc
|
||||
hi def link copilotpanelSeparator Comment
|
||||
|
||||
let b:current_syntax = "copilotpanel"
|
||||
1
vim/.config/vim/pack/plugins/start/fzf.vim/.gitattributes
vendored
Normal file
1
vim/.config/vim/pack/plugins/start/fzf.vim/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.sh text eol=lf
|
||||
1
vim/.config/vim/pack/plugins/start/fzf.vim/.github/FUNDING.yml
vendored
Normal file
1
vim/.config/vim/pack/plugins/start/fzf.vim/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github: junegunn
|
||||
49
vim/.config/vim/pack/plugins/start/fzf.vim/.github/ISSUE_TEMPLATE/issue.yml
vendored
Normal file
49
vim/.config/vim/pack/plugins/start/fzf.vim/.github/ISSUE_TEMPLATE/issue.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: Issue Template
|
||||
description: Report a problem or bug related to fzf.vim to help us improve
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Check the version of fzf used by running
|
||||
|
||||
```vim
|
||||
:echo system(fzf#exec() .. ' --version')
|
||||
```
|
||||
|
||||
If you don't have the latest version, run the following code to download it
|
||||
|
||||
```vim
|
||||
:call fzf#install()
|
||||
```
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Checklist
|
||||
options:
|
||||
- label: I have fzf 0.54.0 or later
|
||||
required: true
|
||||
- label: I have searched through the existing issues
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Output of `:echo system(fzf#exec() .. ' --version')`
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: OS
|
||||
options:
|
||||
- label: Linux
|
||||
- label: macOS
|
||||
- label: Windows
|
||||
- label: Etc.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Problem / Steps to reproduce
|
||||
validations:
|
||||
required: true
|
||||
1
vim/.config/vim/pack/plugins/start/fzf.vim/.gitignore
vendored
Normal file
1
vim/.config/vim/pack/plugins/start/fzf.vim/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
doc/tags
|
||||
21
vim/.config/vim/pack/plugins/start/fzf.vim/LICENSE
Normal file
21
vim/.config/vim/pack/plugins/start/fzf.vim/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Junegunn Choi
|
||||
|
||||
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.
|
||||
489
vim/.config/vim/pack/plugins/start/fzf.vim/README.md
Normal file
489
vim/.config/vim/pack/plugins/start/fzf.vim/README.md
Normal file
@@ -0,0 +1,489 @@
|
||||
<div align="center" markdown="1">
|
||||
<sup>Special thanks to:</sup>
|
||||
<br>
|
||||
<a href="https://tuple.app/fzf.vim">
|
||||
<img alt="Tuple's sponsorship image" src="https://raw.githubusercontent.com/junegunn/i/master/tuple.png" width="400">
|
||||
</a>
|
||||
|
||||
### [Tuple, the premier screen sharing app for developers](https://tuple.app/fzf.vim)
|
||||
[Available for MacOS & Windows](https://tuple.app/fzf.vim)<br>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
fzf :heart: vim
|
||||
===============
|
||||
|
||||
Things you can do with [fzf][fzf] and Vim.
|
||||
|
||||
Rationale
|
||||
---------
|
||||
|
||||
[fzf][fzf] itself is not a Vim plugin, and the official repository only
|
||||
provides the [basic wrapper function][run] for Vim. It's up to the users to
|
||||
write their own Vim commands with it. However, I've learned that many users of
|
||||
fzf are not familiar with Vimscript and are looking for the "default"
|
||||
implementation of the features they can find in the alternative Vim plugins.
|
||||
|
||||
Why you should use fzf on Vim
|
||||
-----------------------------
|
||||
|
||||
Because you can and you love fzf.
|
||||
|
||||
fzf runs asynchronously and can be orders of magnitude faster than similar Vim
|
||||
plugins. However, the benefit may not be noticeable if the size of the input
|
||||
is small, which is the case for many of the commands provided here.
|
||||
Nevertheless I wrote them anyway since it's really easy to implement custom
|
||||
selector with fzf.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
fzf.vim depends on the basic Vim plugin of [the main fzf
|
||||
repository][fzf-main], which means you need to **set up both "fzf" and
|
||||
"fzf.vim" on Vim**. To learn more about fzf/Vim integration, see
|
||||
[README-VIM][README-VIM].
|
||||
|
||||
[fzf-main]: https://github.com/junegunn/fzf
|
||||
[README-VIM]: https://github.com/junegunn/fzf/blob/master/README-VIM.md
|
||||
|
||||
### Using [vim-plug](https://github.com/junegunn/vim-plug)
|
||||
|
||||
```vim
|
||||
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
|
||||
Plug 'junegunn/fzf.vim'
|
||||
```
|
||||
|
||||
`fzf#install()` makes sure that you have the latest binary, but it's optional,
|
||||
so you can omit it if you use a plugin manager that doesn't support hooks.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [fzf][fzf-main] 0.54.0 or above
|
||||
- For syntax-highlighted preview, install [bat](https://github.com/sharkdp/bat)
|
||||
- If [delta](https://github.com/dandavison/delta) is available, `GF?`,
|
||||
`Commits` and `BCommits` will use it to format `git diff` output.
|
||||
- `Ag` requires [The Silver Searcher (ag)][ag]
|
||||
- `Rg` requires [ripgrep (rg)][rg]
|
||||
- `Tags` and `Helptags` require Perl
|
||||
- `Tags PREFIX` requires `readtags` command from [Universal Ctags](https://ctags.io/)
|
||||
|
||||
```sh
|
||||
# Installing dependencies using Homebrew
|
||||
brew install fzf bat ripgrep the_silver_searcher perl universal-ctags
|
||||
```
|
||||
|
||||
Commands
|
||||
--------
|
||||
|
||||
| Command | List |
|
||||
| --- | --- |
|
||||
| `:Files [PATH]` | Files (runs `$FZF_DEFAULT_COMMAND` if defined) |
|
||||
| `:GFiles [OPTS]` | Git files (`git ls-files`) |
|
||||
| `:GFiles?` | Git files (`git status`) |
|
||||
| `:Buffers` | Open buffers |
|
||||
| `:Colors` | Color schemes |
|
||||
| `:Ag [PATTERN]` | [ag][ag] search result (`ALT-A` to select all, `ALT-D` to deselect all) |
|
||||
| `:Rg [PATTERN]` | [rg][rg] search result (`ALT-A` to select all, `ALT-D` to deselect all) |
|
||||
| `:RG [PATTERN]` | [rg][rg] search result; relaunch ripgrep on every keystroke |
|
||||
| `:Lines [QUERY]` | Lines in loaded buffers |
|
||||
| `:BLines [QUERY]` | Lines in the current buffer |
|
||||
| `:Tags [PREFIX]` | Tags in the project (`ctags -R`) |
|
||||
| `:BTags [QUERY]` | Tags in the current buffer |
|
||||
| `:Changes` | Changelist across all open buffers |
|
||||
| `:Marks` | Marks |
|
||||
| `:BMarks` | Marks in the current buffer |
|
||||
| `:Jumps` | Jumps |
|
||||
| `:Windows` | Windows |
|
||||
| `:Locate PATTERN` | `locate` command output |
|
||||
| `:History` | `v:oldfiles` and open buffers |
|
||||
| `:History:` | Command history |
|
||||
| `:History/` | Search history |
|
||||
| `:Snippets` | Snippets ([UltiSnips][us]) |
|
||||
| `:Commits [LOG_OPTS]` | Git commits (requires [fugitive.vim][f]) |
|
||||
| `:BCommits [LOG_OPTS]` | Git commits for the current buffer; visual-select lines to track changes in the range |
|
||||
| `:Commands` | Commands |
|
||||
| `:Maps` | Normal mode mappings |
|
||||
| `:Helptags` | Help tags <sup id="a1">[1](#helptags)</sup> |
|
||||
| `:Filetypes` | File types
|
||||
|
||||
- Most commands support `CTRL-T` / `CTRL-X` / `CTRL-V` key
|
||||
bindings to open in a new tab, a new split, or in a new vertical split
|
||||
- Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen
|
||||
- You can set `g:fzf_vim.command_prefix` to give the same prefix to the commands
|
||||
- e.g. `let g:fzf_vim.command_prefix = 'Fzf'` and you have `FzfFiles`, etc.
|
||||
|
||||
(<a name="helptags">1</a>: `Helptags` will shadow the command of the same name
|
||||
from [pathogen][pat]. But its functionality is still available via `call
|
||||
pathogen#helptags()`. [↩](#a1))
|
||||
|
||||
[pat]: https://github.com/tpope/vim-pathogen
|
||||
[f]: https://github.com/tpope/vim-fugitive
|
||||
|
||||
Customization
|
||||
-------------
|
||||
|
||||
### Configuration options of the base plugin
|
||||
|
||||
Every command in fzf.vim internally calls `fzf#wrap` function of the main
|
||||
repository which supports a set of global option variables. So please read
|
||||
through [README-VIM][README-VIM] to learn more about them.
|
||||
|
||||
### Configuration options for fzf.vim
|
||||
|
||||
All configuration values for this plugin are stored in `g:fzf_vim` dictionary,
|
||||
so **make sure to initialize it before assigning any configuration values to
|
||||
it**.
|
||||
|
||||
```vim
|
||||
" Initialize configuration dictionary
|
||||
let g:fzf_vim = {}
|
||||
```
|
||||
|
||||
#### Preview window
|
||||
|
||||
Some commands will show the preview window on the right. You can customize the
|
||||
behavior with `g:fzf_vim.preview_window`. Here are some examples:
|
||||
|
||||
```vim
|
||||
" This is the default option:
|
||||
" - Preview window on the right with 50% width
|
||||
" - CTRL-/ will toggle preview window.
|
||||
" - Note that this array is passed as arguments to fzf#vim#with_preview function.
|
||||
" - To learn more about preview window options, see `--preview-window` section of `man fzf`.
|
||||
let g:fzf_vim.preview_window = ['right,50%', 'ctrl-/']
|
||||
|
||||
" Preview window is hidden by default. You can toggle it with ctrl-/.
|
||||
" It will show on the right with 50% width, but if the width is smaller
|
||||
" than 70 columns, it will show above the candidate list
|
||||
let g:fzf_vim.preview_window = ['hidden,right,50%,<70(up,40%)', 'ctrl-/']
|
||||
|
||||
" Empty value to disable preview window altogether
|
||||
let g:fzf_vim.preview_window = []
|
||||
|
||||
" fzf.vim needs bash to display the preview window.
|
||||
" On Windows, fzf.vim will first see if bash is in $PATH, then if
|
||||
" Git bash (C:\Program Files\Git\bin\bash.exe) is available.
|
||||
" If you want it to use a different bash, set this variable.
|
||||
" let g:fzf_vim = {}
|
||||
" let g:fzf_vim.preview_bash = 'C:\Git\bin\bash.exe'
|
||||
```
|
||||
|
||||
#### Command-level options
|
||||
|
||||
```vim
|
||||
" [Buffers] Jump to the existing window if possible (default: 0)
|
||||
let g:fzf_vim.buffers_jump = 1
|
||||
|
||||
" [Ag|Rg|RG] Display path on a separate line for narrow screens (default: 0)
|
||||
" * Requires Perl and fzf 0.56.0 or later
|
||||
let g:fzf_vim.grep_multi_line = 0
|
||||
" PATH:LINE:COL:LINE
|
||||
let g:fzf_vim.grep_multi_line = 1
|
||||
" PATH:LINE:COL:
|
||||
" LINE
|
||||
let g:fzf_vim.grep_multi_line = 2
|
||||
" PATH:LINE:COL:
|
||||
" LINE
|
||||
" (empty line between items using --gap option)
|
||||
|
||||
" [[B]Commits] Customize the options used by 'git log':
|
||||
let g:fzf_vim.commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'
|
||||
|
||||
" [Tags] Command to generate tags file
|
||||
let g:fzf_vim.tags_command = 'ctags -R'
|
||||
|
||||
" [Commands] --expect expression for directly executing the command
|
||||
let g:fzf_vim.commands_expect = 'alt-enter,ctrl-x'
|
||||
```
|
||||
|
||||
#### Command-level fzf options
|
||||
|
||||
You can set fzf options for each command by setting
|
||||
`g:fzf_vim.{command}_options`.
|
||||
|
||||
```vim
|
||||
" In string
|
||||
let g:fzf_vim.buffers_options = '--style full --border-label " Open Buffers "'
|
||||
|
||||
" In list (No need to quote or escape values)
|
||||
let g:fzf_vim.buffers_options = ['--style', 'full', '--border-label', ' Open Buffers ']
|
||||
```
|
||||
|
||||
#### List type to handle multiple selections
|
||||
|
||||
The following commands will fill the quickfix list when multiple entries are
|
||||
selected.
|
||||
|
||||
* `Ag`
|
||||
* `Rg` / `RG`
|
||||
* `Lines` / `BLines`
|
||||
* `Tags` / `BTags`
|
||||
|
||||
By setting `g:fzf_vim.listproc`, you can make them use location list instead.
|
||||
|
||||
```vim
|
||||
" Default: Use quickfix list
|
||||
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#quickfix(list) }
|
||||
|
||||
" Use location list instead of quickfix list
|
||||
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#location(list) }
|
||||
```
|
||||
|
||||
You can customize the list type per command by defining variables named
|
||||
`g:fzf_vim.listproc_{command_name_in_lowercase}`.
|
||||
|
||||
```vim
|
||||
" Command-wise customization
|
||||
let g:fzf_vim.listproc_ag = { list -> fzf#vim#listproc#quickfix(list) }
|
||||
let g:fzf_vim.listproc_rg = { list -> fzf#vim#listproc#location(list) }
|
||||
```
|
||||
|
||||
You can further customize the behavior by providing a custom function to
|
||||
process the list instead of using the predefined `fzf#vim#listproc#quickfix`
|
||||
or `fzf#vim#listproc#location`.
|
||||
|
||||
```vim
|
||||
" A customized version of fzf#vim#listproc#quickfix.
|
||||
" The last two lines are commented out not to move to the first entry.
|
||||
function! g:fzf_vim.listproc(list)
|
||||
call setqflist(a:list)
|
||||
copen
|
||||
wincmd p
|
||||
" cfirst
|
||||
" normal! zvzz
|
||||
endfunction
|
||||
```
|
||||
|
||||
### Advanced customization
|
||||
|
||||
#### Vim functions
|
||||
|
||||
Each command in fzf.vim is backed by a Vim function. You can override
|
||||
a command or define a variation of it by calling its corresponding function.
|
||||
|
||||
| Command | Vim function |
|
||||
| --- | --- |
|
||||
| `Files` | `fzf#vim#files(dir, [spec dict], [fullscreen bool])` |
|
||||
| `GFiles` | `fzf#vim#gitfiles(git_options, [spec dict], [fullscreen bool])` |
|
||||
| `GFiles?` | `fzf#vim#gitfiles('?', [spec dict], [fullscreen bool])` |
|
||||
| `Buffers` | `fzf#vim#buffers([query string], [bufnrs list], [spec dict], [fullscreen bool])` |
|
||||
| `Colors` | `fzf#vim#colors([spec dict], [fullscreen bool])` |
|
||||
| `Rg` | `fzf#vim#grep(command, [spec dict], [fullscreen bool])` |
|
||||
| `RG` | `fzf#vim#grep2(command_prefix, query, [spec dict], [fullscreen bool])` |
|
||||
| ... | ... |
|
||||
|
||||
(We can see that the last two optional arguments of each function are
|
||||
identical. They are directly passed to `fzf#wrap` function. If you haven't
|
||||
read [README-VIM][README-VIM] already, please read it before proceeding.)
|
||||
|
||||
#### Example: Customizing `Files` command
|
||||
|
||||
This is the default definition of `Files` command:
|
||||
|
||||
```vim
|
||||
command! -bang -nargs=? -complete=dir Files call fzf#vim#files(<q-args>, <bang>0)
|
||||
```
|
||||
|
||||
Let's say you want to a variation of it called `ProjectFiles` that only
|
||||
searches inside `~/projects` directory. Then you can do it like this:
|
||||
|
||||
```vim
|
||||
command! -bang ProjectFiles call fzf#vim#files('~/projects', <bang>0)
|
||||
```
|
||||
|
||||
Or, if you want to override the command with different fzf options, just pass
|
||||
a custom spec to the function.
|
||||
|
||||
```vim
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline']}, <bang>0)
|
||||
```
|
||||
|
||||
Want a preview window?
|
||||
|
||||
```vim
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', 'cat {}']}, <bang>0)
|
||||
```
|
||||
|
||||
It kind of works, but you probably want a nicer previewer program than `cat`.
|
||||
fzf.vim ships [a versatile preview script](bin/preview.sh) you can readily
|
||||
use. It internally executes [bat](https://github.com/sharkdp/bat) for syntax
|
||||
highlighting, so make sure to install it.
|
||||
|
||||
```vim
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', '~/.vim/plugged/fzf.vim/bin/preview.sh {}']}, <bang>0)
|
||||
```
|
||||
|
||||
However, it's not ideal to hard-code the path to the script which can be
|
||||
different in different circumstances. So in order to make it easier to set up
|
||||
the previewer, fzf.vim provides `fzf#vim#with_preview` helper function.
|
||||
Similarly to `fzf#wrap`, it takes a spec dictionary and returns a copy of it
|
||||
with additional preview options.
|
||||
|
||||
```vim
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview({'options': ['--layout=reverse', '--info=inline']}), <bang>0)
|
||||
```
|
||||
|
||||
You can just omit the spec argument if you only want the previewer.
|
||||
|
||||
```vim
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
|
||||
```
|
||||
|
||||
#### Example: `git grep` wrapper
|
||||
|
||||
The following example implements `GGrep` command that works similarly to
|
||||
predefined `Ag` or `Rg` using `fzf#vim#grep`.
|
||||
|
||||
- We set the base directory to git root by setting `dir` attribute in spec
|
||||
dictionary.
|
||||
- [The preview script](bin/preview.sh) supports `grep` format
|
||||
(`FILE_PATH:LINE_NO:...`), so we can just wrap the spec with
|
||||
`fzf#vim#with_preview` as before to enable previewer.
|
||||
|
||||
```vim
|
||||
command! -bang -nargs=* GGrep
|
||||
\ call fzf#vim#grep(
|
||||
\ 'git grep --line-number -- '.fzf#shellescape(<q-args>),
|
||||
\ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0)
|
||||
```
|
||||
|
||||
Mappings
|
||||
--------
|
||||
|
||||
| Mapping | Description |
|
||||
| --- | --- |
|
||||
| `<plug>(fzf-maps-n)` | Normal mode mappings |
|
||||
| `<plug>(fzf-maps-i)` | Insert mode mappings |
|
||||
| `<plug>(fzf-maps-x)` | Visual mode mappings |
|
||||
| `<plug>(fzf-maps-o)` | Operator-pending mappings |
|
||||
| `<plug>(fzf-complete-word)` | `cat /usr/share/dict/words` |
|
||||
| `<plug>(fzf-complete-path)` | Path completion using `find` (file + dir) |
|
||||
| `<plug>(fzf-complete-file)` | File completion using `find` |
|
||||
| `<plug>(fzf-complete-line)` | Line completion (all open buffers) |
|
||||
| `<plug>(fzf-complete-buffer-line)` | Line completion (current buffer only) |
|
||||
|
||||
```vim
|
||||
" Mapping selecting mappings
|
||||
nmap <leader><tab> <plug>(fzf-maps-n)
|
||||
xmap <leader><tab> <plug>(fzf-maps-x)
|
||||
omap <leader><tab> <plug>(fzf-maps-o)
|
||||
|
||||
" Insert mode completion
|
||||
imap <c-x><c-k> <plug>(fzf-complete-word)
|
||||
imap <c-x><c-f> <plug>(fzf-complete-path)
|
||||
imap <c-x><c-l> <plug>(fzf-complete-line)
|
||||
```
|
||||
|
||||
Completion functions
|
||||
--------------------
|
||||
|
||||
| Function | Description |
|
||||
| --- | --- |
|
||||
| `fzf#vim#complete#path(command, [spec])` | Path completion |
|
||||
| `fzf#vim#complete#word([spec])` | Word completion |
|
||||
| `fzf#vim#complete#line([spec])` | Line completion (all open buffers) |
|
||||
| `fzf#vim#complete#buffer_line([spec])` | Line completion (current buffer only) |
|
||||
|
||||
```vim
|
||||
" Path completion with custom source command
|
||||
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('fd')
|
||||
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('rg --files')
|
||||
|
||||
" Word completion with custom spec with popup layout option
|
||||
inoremap <expr> <c-x><c-k> fzf#vim#complete#word({'window': { 'width': 0.2, 'height': 0.9, 'xoffset': 1 }})
|
||||
```
|
||||
|
||||
Custom completion
|
||||
-----------------
|
||||
|
||||
`fzf#vim#complete` is a helper function for creating custom fuzzy completion
|
||||
using fzf. If the first parameter is a command string or a Vim list, it will
|
||||
be used as the source.
|
||||
|
||||
```vim
|
||||
" Replace the default dictionary completion with fzf-based fuzzy completion
|
||||
inoremap <expr> <c-x><c-k> fzf#vim#complete('cat /usr/share/dict/words')
|
||||
```
|
||||
|
||||
For advanced uses, you can pass an options dictionary to the function. The set
|
||||
of options is pretty much identical to that for `fzf#run` only with the
|
||||
following exceptions:
|
||||
|
||||
- `reducer` (funcref)
|
||||
- Reducer transforms the output lines of fzf into a single string value
|
||||
- `prefix` (string or funcref; default: `\k*$`)
|
||||
- Regular expression pattern to extract the completion prefix
|
||||
- Or a function to extract completion prefix
|
||||
- Both `source` and `options` can be given as funcrefs that take the
|
||||
completion prefix as the argument and return the final value
|
||||
- `sink` or `sink*` are ignored
|
||||
|
||||
```vim
|
||||
" Global line completion (not just open buffers. ripgrep required.)
|
||||
inoremap <expr> <c-x><c-l> fzf#vim#complete(fzf#wrap({
|
||||
\ 'prefix': '^.*$',
|
||||
\ 'source': 'rg -n ^ --color always',
|
||||
\ 'options': '--ansi --delimiter : --nth 3..',
|
||||
\ 'reducer': { lines -> join(split(lines[0], ':\zs')[2:], '') }}))
|
||||
```
|
||||
|
||||
### Reducer example
|
||||
|
||||
```vim
|
||||
function! s:make_sentence(lines)
|
||||
return substitute(join(a:lines), '^.', '\=toupper(submatch(0))', '').'.'
|
||||
endfunction
|
||||
|
||||
inoremap <expr> <c-x><c-s> fzf#vim#complete({
|
||||
\ 'source': 'cat /usr/share/dict/words',
|
||||
\ 'reducer': function('<sid>make_sentence'),
|
||||
\ 'options': '--multi --reverse --margin 15%,0',
|
||||
\ 'left': 20})
|
||||
```
|
||||
|
||||
Status line of terminal buffer
|
||||
------------------------------
|
||||
|
||||
When fzf starts in a terminal buffer (see [fzf/README-VIM.md][termbuf]), you
|
||||
may want to customize the statusline of the containing buffer.
|
||||
|
||||
[termbuf]: https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzf-inside-terminal-buffer
|
||||
|
||||
### Hide statusline
|
||||
|
||||
```vim
|
||||
autocmd! FileType fzf set laststatus=0 noshowmode noruler
|
||||
\| autocmd BufLeave <buffer> set laststatus=2 showmode ruler
|
||||
```
|
||||
|
||||
### Custom statusline
|
||||
|
||||
```vim
|
||||
function! s:fzf_statusline()
|
||||
" Override statusline as you like
|
||||
highlight fzf1 ctermfg=161 ctermbg=251
|
||||
highlight fzf2 ctermfg=23 ctermbg=251
|
||||
highlight fzf3 ctermfg=237 ctermbg=251
|
||||
setlocal statusline=%#fzf1#\ >\ %#fzf2#fz%#fzf3#f
|
||||
endfunction
|
||||
|
||||
autocmd! User FzfStatusLine call <SID>fzf_statusline()
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT
|
||||
|
||||
[fzf]: https://github.com/junegunn/fzf
|
||||
[run]: https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzfrun
|
||||
[ag]: https://github.com/ggreer/the_silver_searcher
|
||||
[rg]: https://github.com/BurntSushi/ripgrep
|
||||
[us]: https://github.com/SirVer/ultisnips
|
||||
1836
vim/.config/vim/pack/plugins/start/fzf.vim/autoload/fzf/vim.vim
Executable file
1836
vim/.config/vim/pack/plugins/start/fzf.vim/autoload/fzf/vim.vim
Executable file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,164 @@
|
||||
" Copyright (c) 2015 Junegunn Choi
|
||||
"
|
||||
" MIT License
|
||||
"
|
||||
" 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.
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
let s:is_win = has('win32') || has('win64')
|
||||
|
||||
function! s:extend(base, extra)
|
||||
let base = copy(a:base)
|
||||
if has_key(a:extra, 'options')
|
||||
let extra = copy(a:extra)
|
||||
let extra.extra_options = remove(extra, 'options')
|
||||
return extend(base, extra)
|
||||
endif
|
||||
return extend(base, a:extra)
|
||||
endfunction
|
||||
|
||||
if v:version >= 704
|
||||
function! s:function(name)
|
||||
return function(a:name)
|
||||
endfunction
|
||||
else
|
||||
function! s:function(name)
|
||||
" By Ingo Karkat
|
||||
return function(substitute(a:name, '^s:', matchstr(expand('<sfile>'), '<SNR>\d\+_\zefunction$'), ''))
|
||||
endfunction
|
||||
endif
|
||||
|
||||
function! fzf#vim#complete#word(...)
|
||||
let sources = empty(&dictionary) ? ['/usr/share/dict/words'] : split(&dictionary, ',')
|
||||
return fzf#vim#complete(s:extend({
|
||||
\ 'source': 'cat ' . join(map(sources, 'fzf#shellescape(v:val)'))},
|
||||
\ get(a:000, 0, fzf#wrap())))
|
||||
endfunction
|
||||
|
||||
" ----------------------------------------------------------------------------
|
||||
" <plug>(fzf-complete-path)
|
||||
" <plug>(fzf-complete-file)
|
||||
" <plug>(fzf-complete-file-ag)
|
||||
" ----------------------------------------------------------------------------
|
||||
function! s:file_split_prefix(prefix)
|
||||
let expanded = expand(a:prefix)
|
||||
let slash = (s:is_win && !&shellslash) ? '\\' : '/'
|
||||
return isdirectory(expanded) ?
|
||||
\ [expanded,
|
||||
\ substitute(a:prefix, '[/\\]*$', slash, ''),
|
||||
\ ''] :
|
||||
\ [fnamemodify(expanded, ':h'),
|
||||
\ substitute(fnamemodify(a:prefix, ':h'), '[/\\]*$', slash, ''),
|
||||
\ fnamemodify(expanded, ':t')]
|
||||
endfunction
|
||||
|
||||
function! s:file_source(prefix)
|
||||
let [dir, head, tail] = s:file_split_prefix(a:prefix)
|
||||
return printf(
|
||||
\ "cd %s && ".s:file_cmd." | sed %s",
|
||||
\ fzf#shellescape(dir), fzf#shellescape('s:^:'.(empty(a:prefix) || a:prefix == tail ? '' : head).':'))
|
||||
endfunction
|
||||
|
||||
function! s:file_options(prefix)
|
||||
let [_, head, tail] = s:file_split_prefix(a:prefix)
|
||||
return ['--prompt', head, '--query', tail]
|
||||
endfunction
|
||||
|
||||
function! s:fname_prefix(str)
|
||||
let isf = &isfname
|
||||
let white = []
|
||||
let black = []
|
||||
if isf =~ ',,,'
|
||||
call add(white, ',')
|
||||
let isf = substitute(isf, ',,,', ',', 'g')
|
||||
endif
|
||||
if isf =~ ',^,,'
|
||||
call add(black, ',')
|
||||
let isf = substitute(isf, ',^,,', ',', 'g')
|
||||
endif
|
||||
|
||||
for token in split(isf, ',')
|
||||
let target = white
|
||||
if token[0] == '^'
|
||||
let target = black
|
||||
let token = token[1:]
|
||||
endif
|
||||
|
||||
let ends = matchlist(token, '\(.\+\)-\(.\+\)')
|
||||
if empty(ends)
|
||||
call add(target, token)
|
||||
else
|
||||
let ends = map(ends[1:2], "len(v:val) == 1 ? char2nr(v:val) : str2nr(v:val)")
|
||||
for i in range(ends[0], ends[1])
|
||||
call add(target, nr2char(i))
|
||||
endfor
|
||||
endif
|
||||
endfor
|
||||
|
||||
let prefix = a:str
|
||||
for offset in range(1, len(a:str))
|
||||
let char = a:str[len(a:str) - offset]
|
||||
if (char =~ '\w' || index(white, char) >= 0) && index(black, char) < 0
|
||||
continue
|
||||
endif
|
||||
let prefix = strpart(a:str, len(a:str) - offset + 1)
|
||||
break
|
||||
endfor
|
||||
|
||||
return prefix
|
||||
endfunction
|
||||
|
||||
function! fzf#vim#complete#path(command, ...)
|
||||
let s:file_cmd = a:command
|
||||
return fzf#vim#complete(s:extend({
|
||||
\ 'prefix': s:function('s:fname_prefix'),
|
||||
\ 'source': s:function('s:file_source'),
|
||||
\ 'options': s:function('s:file_options')}, get(a:000, 0, fzf#wrap())))
|
||||
endfunction
|
||||
|
||||
" ----------------------------------------------------------------------------
|
||||
" <plug>(fzf-complete-line)
|
||||
" <plug>(fzf-complete-buffer-line)
|
||||
" ----------------------------------------------------------------------------
|
||||
function! s:reduce_line(lines)
|
||||
return join(split(a:lines[0], '\t\zs')[3:], '')
|
||||
endfunction
|
||||
|
||||
|
||||
function! fzf#vim#complete#line(...)
|
||||
let [display_bufnames, lines] = fzf#vim#_lines(0)
|
||||
let nth = display_bufnames ? 4 : 3
|
||||
return fzf#vim#complete(s:extend({
|
||||
\ 'prefix': '^.*$',
|
||||
\ 'source': lines,
|
||||
\ 'options': '--tiebreak=index --ansi --nth '.nth.'.. --tabstop=1',
|
||||
\ 'reducer': s:function('s:reduce_line')}, get(a:000, 0, fzf#wrap())))
|
||||
endfunction
|
||||
|
||||
function! fzf#vim#complete#buffer_line(...)
|
||||
return fzf#vim#complete(s:extend({
|
||||
\ 'prefix': '^.*$',
|
||||
\ 'source': fzf#vim#_uniq(getline(1, '$'))}, get(a:000, 0, fzf#wrap())))
|
||||
endfunction
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
" Copyright (c) 2024 Junegunn Choi
|
||||
"
|
||||
" MIT License
|
||||
"
|
||||
" 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.
|
||||
|
||||
function! s:warn(message)
|
||||
echohl WarningMsg
|
||||
echom a:message
|
||||
echohl None
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! fzf#vim#ipc#start(Callback)
|
||||
if !exists('*job_start') && !exists('*jobstart')
|
||||
call s:warn('job_start/jobstart function not supported')
|
||||
return ''
|
||||
endif
|
||||
|
||||
if !executable('mkfifo')
|
||||
call s:warn('mkfifo is not available')
|
||||
return ''
|
||||
endif
|
||||
|
||||
call fzf#vim#ipc#stop()
|
||||
|
||||
let g:fzf_ipc = { 'fifo': tempname(), 'callback': a:Callback }
|
||||
if !filereadable(g:fzf_ipc.fifo)
|
||||
call system('mkfifo '..shellescape(g:fzf_ipc.fifo))
|
||||
if v:shell_error
|
||||
call s:warn('Failed to create fifo')
|
||||
endif
|
||||
endif
|
||||
|
||||
call fzf#vim#ipc#restart()
|
||||
|
||||
return g:fzf_ipc.fifo
|
||||
endfunction
|
||||
|
||||
function! fzf#vim#ipc#restart()
|
||||
if !exists('g:fzf_ipc')
|
||||
throw 'fzf#vim#ipc not started'
|
||||
endif
|
||||
|
||||
let Callback = g:fzf_ipc.callback
|
||||
if exists('*job_start')
|
||||
let g:fzf_ipc.job = job_start(
|
||||
\ ['cat', g:fzf_ipc.fifo],
|
||||
\ {'out_cb': { _, msg -> call(Callback, [msg]) },
|
||||
\ 'exit_cb': { _, status -> status == 0 ? fzf#vim#ipc#restart() : '' }}
|
||||
\ )
|
||||
else
|
||||
let eof = ['']
|
||||
let g:fzf_ipc.job = jobstart(
|
||||
\ ['cat', g:fzf_ipc.fifo],
|
||||
\ {'stdout_buffered': 1,
|
||||
\ 'on_stdout': { j, msg, e -> msg != eof ? call(Callback, msg) : '' },
|
||||
\ 'on_exit': { j, status, e -> status == 0 ? fzf#vim#ipc#restart() : '' }}
|
||||
\ )
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fzf#vim#ipc#stop()
|
||||
if !exists('g:fzf_ipc')
|
||||
return
|
||||
endif
|
||||
|
||||
let job = g:fzf_ipc.job
|
||||
if exists('*job_stop')
|
||||
call job_stop(job)
|
||||
else
|
||||
call jobstop(job)
|
||||
call jobwait([job])
|
||||
endif
|
||||
|
||||
call delete(g:fzf_ipc.fifo)
|
||||
unlet g:fzf_ipc
|
||||
endfunction
|
||||
@@ -0,0 +1,38 @@
|
||||
" Copyright (c) 2023 Junegunn Choi
|
||||
"
|
||||
" MIT License
|
||||
"
|
||||
" 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.
|
||||
|
||||
function! fzf#vim#listproc#quickfix(list)
|
||||
call setqflist(a:list)
|
||||
copen
|
||||
wincmd p
|
||||
cfirst
|
||||
normal! zvzz
|
||||
endfunction
|
||||
|
||||
function! fzf#vim#listproc#location(list)
|
||||
call setloclist(0, a:list)
|
||||
lopen
|
||||
wincmd p
|
||||
lfirst
|
||||
normal! zvzz
|
||||
endfunction
|
||||
3
vim/.config/vim/pack/plugins/start/fzf.vim/bin/preview.rb
Executable file
3
vim/.config/vim/pack/plugins/start/fzf.vim/bin/preview.rb
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
puts 'preview.rb is deprecated. Use preview.sh instead.'
|
||||
93
vim/.config/vim/pack/plugins/start/fzf.vim/bin/preview.sh
Executable file
93
vim/.config/vim/pack/plugins/start/fzf.vim/bin/preview.sh
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
REVERSE="\x1b[7m"
|
||||
RESET="\x1b[m"
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "usage: $0 [--tag] FILENAME[:LINENO][:IGNORED]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $1 = --tag ]]; then
|
||||
shift
|
||||
"$(dirname "${BASH_SOURCE[0]}")/tagpreview.sh" "$@"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# Ignore if an empty path is given
|
||||
[[ -z $1 ]] && exit
|
||||
|
||||
IFS=':' read -r -a INPUT <<< "$1"
|
||||
FILE=${INPUT[0]}
|
||||
CENTER=${INPUT[1]}
|
||||
|
||||
if [[ "$1" =~ ^[A-Za-z]:\\ ]]; then
|
||||
FILE=$FILE:${INPUT[1]}
|
||||
CENTER=${INPUT[2]}
|
||||
fi
|
||||
|
||||
if [[ -n "$CENTER" && ! "$CENTER" =~ ^[0-9] ]]; then
|
||||
exit 1
|
||||
fi
|
||||
CENTER=${CENTER/[^0-9]*/}
|
||||
|
||||
# MS Win support
|
||||
if [[ "$FILE" =~ '\' ]]; then
|
||||
if [ -z "$MSWINHOME" ]; then
|
||||
MSWINHOME="$HOMEDRIVE$HOMEPATH"
|
||||
fi
|
||||
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null ; then
|
||||
MSWINHOME="${MSWINHOME//\\/\\\\}"
|
||||
FILE="${FILE/#\~\\/$MSWINHOME\\}"
|
||||
FILE=$(wslpath -u "$FILE")
|
||||
elif [ -n "$MSWINHOME" ]; then
|
||||
FILE="${FILE/#\~\\/$MSWINHOME\\}"
|
||||
fi
|
||||
fi
|
||||
|
||||
FILE="${FILE/#\~\//$HOME/}"
|
||||
if [ ! -r "$FILE" ]; then
|
||||
if [[ "${INPUT[0]}" != '[No Name]' ]]; then
|
||||
echo "File not found ${FILE}"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$CENTER" ]; then
|
||||
CENTER=0
|
||||
fi
|
||||
|
||||
# Sometimes bat is installed as batcat.
|
||||
if [[ -z "$BATCAT" ]]; then
|
||||
if command -v batcat > /dev/null; then
|
||||
BATCAT="batcat"
|
||||
elif command -v bat > /dev/null; then
|
||||
BATCAT="bat"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$FZF_PREVIEW_COMMAND" ] && [ "${BATCAT:+x}" ] && [[ ! -d "$FILE" ]] ; then
|
||||
${BATCAT} --style="${BAT_STYLE:-numbers}" --color=always --pager=never \
|
||||
--highlight-line=$CENTER -- "$FILE"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
FILE_LENGTH=${#FILE}
|
||||
MIME=$(file --dereference --mime -- "$FILE")
|
||||
if [[ "${MIME:FILE_LENGTH}" =~ binary ]] && [[ ! -d "$FILE" ]]; then
|
||||
echo "$MIME"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DEFAULT_COMMAND="highlight -O ansi -l {} || coderay {} || rougify {} || cat {}"
|
||||
if [[ -d "$FILE" ]]; then
|
||||
DEFAULT_COMMAND="tree -C -L2 {} || ls -l --color=always {}"
|
||||
fi
|
||||
CMD=${FZF_PREVIEW_COMMAND:-$DEFAULT_COMMAND}
|
||||
CMD=${CMD//{\}/"$(printf %q "$FILE")"}
|
||||
|
||||
eval "$CMD" 2> /dev/null | awk "{ \
|
||||
if (NR == $CENTER) \
|
||||
{ gsub(/\x1b[[0-9;]*m/, \"&$REVERSE\"); printf(\"$REVERSE%s\n$RESET\", \$0); } \
|
||||
else printf(\"$RESET%s\n\", \$0); \
|
||||
}"
|
||||
73
vim/.config/vim/pack/plugins/start/fzf.vim/bin/tagpreview.sh
Executable file
73
vim/.config/vim/pack/plugins/start/fzf.vim/bin/tagpreview.sh
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
REVERSE="\x1b[7m"
|
||||
RESET="\x1b[m"
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "usage: $0 FILENAME:TAGFILE:EXCMD"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IFS=':' read -r FILE TAGFILE EXCMD <<< "$*"
|
||||
|
||||
# Complete file paths which are relative to the given tag file
|
||||
if [ "${FILE:0:1}" != "/" ]; then
|
||||
FILE="$(dirname "${TAGFILE}")/${FILE}"
|
||||
fi
|
||||
|
||||
if [ ! -r "$FILE" ]; then
|
||||
echo "File not found ${FILE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If users aren't using vim, they are probably using neovim
|
||||
if command -v vim > /dev/null; then
|
||||
VIMNAME="vim"
|
||||
elif command -v nvim > /dev/null; then
|
||||
VIMNAME="nvim"
|
||||
else
|
||||
echo "Cannot preview tag: vim or nvim unavailable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CENTER="$("${VIMNAME}" -R -i NONE -u NONE -e -m -s "${FILE}" \
|
||||
-c "set nomagic" \
|
||||
-c "silent ${EXCMD}" \
|
||||
-c 'let l=line(".") | new | put =l | print | qa!')" || exit
|
||||
|
||||
START_LINE="$(( CENTER - FZF_PREVIEW_LINES / 2 ))"
|
||||
if (( START_LINE <= 0 )); then
|
||||
START_LINE=1
|
||||
fi
|
||||
END_LINE="$(( START_LINE + FZF_PREVIEW_LINES - 1 ))"
|
||||
|
||||
# Sometimes bat is installed as batcat.
|
||||
if command -v batcat > /dev/null; then
|
||||
BATNAME="batcat"
|
||||
elif command -v bat > /dev/null; then
|
||||
BATNAME="bat"
|
||||
fi
|
||||
|
||||
if [ -z "$FZF_PREVIEW_COMMAND" ] && [ "${BATNAME:+x}" ]; then
|
||||
${BATNAME} --style="${BAT_STYLE:-numbers}" \
|
||||
--color=always \
|
||||
--pager=never \
|
||||
--wrap=never \
|
||||
--terminal-width="${FZF_PREVIEW_COLUMNS}" \
|
||||
--line-range="${START_LINE}:${END_LINE}" \
|
||||
--highlight-line="${CENTER}" \
|
||||
"$FILE"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
DEFAULT_COMMAND="highlight -O ansi -l {} || coderay {} || rougify {} || cat {}"
|
||||
CMD=${FZF_PREVIEW_COMMAND:-$DEFAULT_COMMAND}
|
||||
CMD=${CMD//{\}/$(printf %q "$FILE")}
|
||||
|
||||
eval "$CMD" 2> /dev/null | awk "{ \
|
||||
if (NR >= $START_LINE && NR <= $END_LINE) { \
|
||||
if (NR == $CENTER) \
|
||||
{ gsub(/\x1b[[0-9;]*m/, \"&$REVERSE\"); printf(\"$REVERSE%s\n$RESET\", \$0); } \
|
||||
else printf(\"$RESET%s\n\", \$0); \
|
||||
} \
|
||||
}"
|
||||
23
vim/.config/vim/pack/plugins/start/fzf.vim/bin/tags.pl
Executable file
23
vim/.config/vim/pack/plugins/start/fzf.vim/bin/tags.pl
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
|
||||
my $prefix = shift @ARGV;
|
||||
|
||||
foreach my $file (@ARGV) {
|
||||
my $lines;
|
||||
if ($prefix eq "") {
|
||||
open $lines, $file;
|
||||
} else {
|
||||
# https://perldoc.perl.org/perlopentut#Expressing-the-command-as-a-list
|
||||
open $lines, '-|', 'readtags', '-t', $file, '-e', '-p', '-', $prefix;
|
||||
}
|
||||
while (<$lines>) {
|
||||
unless (/^\!/) {
|
||||
s/^[^\t]*/sprintf("%-24s", $&)/e;
|
||||
s/$/\t$file/;
|
||||
print;
|
||||
}
|
||||
}
|
||||
close $lines;
|
||||
}
|
||||
545
vim/.config/vim/pack/plugins/start/fzf.vim/doc/fzf-vim.txt
Normal file
545
vim/.config/vim/pack/plugins/start/fzf.vim/doc/fzf-vim.txt
Normal file
@@ -0,0 +1,545 @@
|
||||
fzf-vim.txt fzf-vim Last change: June 8 2025
|
||||
FZF-VIM - TABLE OF CONTENTS *fzf-vim* *fzf-vim-toc*
|
||||
==============================================================================
|
||||
|
||||
fzf :heart: vim |fzf-vim-fzfheart-vim|
|
||||
Rationale |fzf-vim-rationale|
|
||||
Why you should use fzf on Vim |fzf-vim-why-you-should-use-fzf-on-vim|
|
||||
Installation |fzf-vim-installation|
|
||||
Using vim-plug |fzf-vim-using-vim-plug|
|
||||
Dependencies |fzf-vim-dependencies|
|
||||
Commands |fzf-vim-commands|
|
||||
Customization |fzf-vim-customization|
|
||||
Configuration options of the base plugin |fzf-vim-configuration-options-of-the-base-plugin|
|
||||
Configuration options for fzf.vim |fzf-vim-configuration-options-for-fzf-vim|
|
||||
Preview window |fzf-vim-preview-window|
|
||||
Command-level options |fzf-vim-command-level-options|
|
||||
Command-level fzf options |fzf-vim-command-level-fzf-options|
|
||||
List type to handle multiple selections |fzf-vim-list-type-to-handle-multiple-selections|
|
||||
Advanced customization |fzf-vim-advanced-customization|
|
||||
Vim functions |fzf-vim-vim-functions|
|
||||
Example: Customizing Files command |fzf-vim-example-customizing-files-command|
|
||||
Example: git grep wrapper |fzf-vim-example-git-grep-wrapper|
|
||||
Mappings |fzf-vim-mappings|
|
||||
Completion functions |fzf-vim-completion-functions|
|
||||
Custom completion |fzf-vim-custom-completion|
|
||||
Reducer example |fzf-vim-reducer-example|
|
||||
Status line of terminal buffer |fzf-vim-status-line-of-terminal-buffer|
|
||||
Hide statusline |fzf-vim-hide-statusline|
|
||||
Custom statusline |fzf-vim-custom-statusline|
|
||||
License |fzf-vim-license|
|
||||
|
||||
FZF :HEART: VIM *fzf-vim-fzfheart-vim*
|
||||
==============================================================================
|
||||
|
||||
Things you can do with {fzf}{1} and Vim.
|
||||
|
||||
{1} https://github.com/junegunn/fzf
|
||||
|
||||
|
||||
RATIONALE *fzf-vim-rationale*
|
||||
==============================================================================
|
||||
|
||||
{fzf}{1} itself is not a Vim plugin, and the official repository only provides
|
||||
the {basic wrapper function}{2} for Vim. It's up to the users to write their
|
||||
own Vim commands with it. However, I've learned that many users of fzf are not
|
||||
familiar with Vimscript and are looking for the "default" implementation of
|
||||
the features they can find in the alternative Vim plugins.
|
||||
|
||||
{1} https://github.com/junegunn/fzf
|
||||
{2} https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzfrun
|
||||
|
||||
|
||||
WHY YOU SHOULD USE FZF ON VIM *fzf-vim-why-you-should-use-fzf-on-vim*
|
||||
==============================================================================
|
||||
|
||||
Because you can and you love fzf.
|
||||
|
||||
fzf runs asynchronously and can be orders of magnitude faster than similar Vim
|
||||
plugins. However, the benefit may not be noticeable if the size of the input
|
||||
is small, which is the case for many of the commands provided here.
|
||||
Nevertheless I wrote them anyway since it's really easy to implement custom
|
||||
selector with fzf.
|
||||
|
||||
|
||||
INSTALLATION *fzf-vim-installation*
|
||||
==============================================================================
|
||||
|
||||
fzf.vim depends on the basic Vim plugin of {the main fzf repository}{1}, which
|
||||
means you need to set up both "fzf" and "fzf.vim" on Vim. To learn more about
|
||||
fzf/Vim integration, see {README-VIM}{3}.
|
||||
|
||||
{1} https://github.com/junegunn/fzf
|
||||
{3} https://github.com/junegunn/fzf/blob/master/README-VIM.md
|
||||
|
||||
|
||||
< Using vim-plug >____________________________________________________________~
|
||||
*fzf-vim-using-vim-plug*
|
||||
>
|
||||
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
|
||||
Plug 'junegunn/fzf.vim'
|
||||
<
|
||||
`fzf#install()` makes sure that you have the latest binary, but it's optional,
|
||||
so you can omit it if you use a plugin manager that doesn't support hooks.
|
||||
|
||||
|
||||
< Dependencies >______________________________________________________________~
|
||||
*fzf-vim-dependencies*
|
||||
|
||||
- {fzf}{1} 0.54.0 or above
|
||||
- For syntax-highlighted preview, install {bat}{4}
|
||||
- If {delta}{5} is available, `GF?`, `Commits` and `BCommits` will use it to
|
||||
format `git diff` output.
|
||||
- `Ag` requires {The Silver Searcher (ag)}{6}
|
||||
- `Rg` requires {ripgrep (rg)}{7}
|
||||
- `Tags` and `Helptags` require Perl
|
||||
- `Tags PREFIX` requires `readtags` command from {Universal Ctags}{8}
|
||||
>
|
||||
# Installing dependencies using Homebrew
|
||||
brew install fzf bat ripgrep the_silver_searcher perl universal-ctags
|
||||
<
|
||||
{1} https://github.com/junegunn/fzf
|
||||
{4} https://github.com/sharkdp/bat
|
||||
{5} https://github.com/dandavison/delta
|
||||
{6} https://github.com/ggreer/the_silver_searcher
|
||||
{7} https://github.com/BurntSushi/ripgrep
|
||||
{8} https://ctags.io/
|
||||
|
||||
|
||||
COMMANDS *fzf-vim-commands*
|
||||
==============================================================================
|
||||
|
||||
*:Files* *:GFiles* *:Buffers* *:Colors* *:Ag* *:Rg* *:RG* *:Lines* *:BLines* *:Tags* *:BTags*
|
||||
*:Changes* *:Marks* *:BMarks* *:Jumps* *:Windows* *:Locate* *:History* *:Snippets* *:Commits*
|
||||
*:BCommits* *:Commands* *:Maps* *:Helptags* *:Filetypes*
|
||||
|
||||
-----------------------+--------------------------------------------------------------------------------------
|
||||
Command | List ~
|
||||
-----------------------+--------------------------------------------------------------------------------------
|
||||
`:Files [PATH]` | Files (runs `$FZF_DEFAULT_COMMAND` if defined)
|
||||
`:GFiles [OPTS]` | Git files ( `git ls-files` )
|
||||
`:GFiles?` | Git files ( `git status` )
|
||||
`:Buffers` | Open buffers
|
||||
`:Colors` | Color schemes
|
||||
`:Ag [PATTERN]` | {ag}{6} search result ( `ALT-A` to select all, `ALT-D` to deselect all)
|
||||
`:Rg [PATTERN]` | {rg}{7} search result ( `ALT-A` to select all, `ALT-D` to deselect all)
|
||||
`:RG [PATTERN]` | {rg}{7} search result; relaunch ripgrep on every keystroke
|
||||
`:Lines [QUERY]` | Lines in loaded buffers
|
||||
`:BLines [QUERY]` | Lines in the current buffer
|
||||
`:Tags [PREFIX]` | Tags in the project ( `ctags -R` )
|
||||
`:BTags [QUERY]` | Tags in the current buffer
|
||||
`:Changes` | Changelist across all open buffers
|
||||
`:Marks` | Marks
|
||||
`:BMarks` | Marks in the current buffer
|
||||
`:Jumps` | Jumps
|
||||
`:Windows` | Windows
|
||||
`:Locate PATTERN` | `locate` command output
|
||||
`:History` | `v:oldfiles` and open buffers
|
||||
`:History:` | Command history
|
||||
`:History/` | Search history
|
||||
`:Snippets` | Snippets ({UltiSnips}{9})
|
||||
`:Commits [LOG_OPTS]` | Git commits (requires {fugitive.vim}{10})
|
||||
`:BCommits [LOG_OPTS]` | Git commits for the current buffer; visual-select lines to track changes in the range
|
||||
`:Commands` | Commands
|
||||
`:Maps` | Normal mode mappings
|
||||
`:Helptags` | Help tags [1]
|
||||
`:Filetypes` | File types
|
||||
-----------------------+--------------------------------------------------------------------------------------
|
||||
|
||||
*g:fzf_vim.command_prefix*
|
||||
|
||||
- Most commands support CTRL-T / CTRL-X / CTRL-V key bindings to open in a new
|
||||
tab, a new split, or in a new vertical split
|
||||
- Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen
|
||||
- You can set `g:fzf_vim.command_prefix` to give the same prefix to the commands
|
||||
- e.g. `let g:fzf_vim.command_prefix = 'Fzf'` and you have `FzfFiles`, etc.
|
||||
|
||||
(1: `Helptags` will shadow the command of the same name from {pathogen}{11}.
|
||||
But its functionality is still available via `call pathogen#helptags()`. [↩])
|
||||
|
||||
{6} https://github.com/ggreer/the_silver_searcher
|
||||
{7} https://github.com/BurntSushi/ripgrep
|
||||
{7} https://github.com/BurntSushi/ripgrep
|
||||
{9} https://github.com/SirVer/ultisnips
|
||||
{10} https://github.com/tpope/vim-fugitive
|
||||
{11} https://github.com/tpope/vim-pathogen
|
||||
|
||||
|
||||
CUSTOMIZATION *fzf-vim-customization*
|
||||
==============================================================================
|
||||
|
||||
|
||||
< Configuration options of the base plugin >__________________________________~
|
||||
*fzf-vim-configuration-options-of-the-base-plugin*
|
||||
|
||||
Every command in fzf.vim internally calls `fzf#wrap` function of the main
|
||||
repository which supports a set of global option variables. So please read
|
||||
through {README-VIM}{3} to learn more about them.
|
||||
|
||||
{3} https://github.com/junegunn/fzf/blob/master/README-VIM.md
|
||||
|
||||
|
||||
< Configuration options for fzf.vim >_________________________________________~
|
||||
*fzf-vim-configuration-options-for-fzf-vim*
|
||||
|
||||
*g:fzf_vim*
|
||||
|
||||
All configuration values for this plugin are stored in `g:fzf_vim` dictionary,
|
||||
so make sure to initialize it before assigning any configuration values to it.
|
||||
>
|
||||
" Initialize configuration dictionary
|
||||
let g:fzf_vim = {}
|
||||
<
|
||||
|
||||
Preview window~
|
||||
*fzf-vim-preview-window*
|
||||
|
||||
*g:fzf_vim.preview_window*
|
||||
|
||||
Some commands will show the preview window on the right. You can customize the
|
||||
behavior with `g:fzf_vim.preview_window`. Here are some examples:
|
||||
|
||||
*g:fzf_vim.preview_bash*
|
||||
>
|
||||
" This is the default option:
|
||||
" - Preview window on the right with 50% width
|
||||
" - CTRL-/ will toggle preview window.
|
||||
" - Note that this array is passed as arguments to fzf#vim#with_preview function.
|
||||
" - To learn more about preview window options, see `--preview-window` section of `man fzf`.
|
||||
let g:fzf_vim.preview_window = ['right,50%', 'ctrl-/']
|
||||
|
||||
" Preview window is hidden by default. You can toggle it with ctrl-/.
|
||||
" It will show on the right with 50% width, but if the width is smaller
|
||||
" than 70 columns, it will show above the candidate list
|
||||
let g:fzf_vim.preview_window = ['hidden,right,50%,<70(up,40%)', 'ctrl-/']
|
||||
|
||||
" Empty value to disable preview window altogether
|
||||
let g:fzf_vim.preview_window = []
|
||||
|
||||
" fzf.vim needs bash to display the preview window.
|
||||
" On Windows, fzf.vim will first see if bash is in $PATH, then if
|
||||
" Git bash (C:\Program Files\Git\bin\bash.exe) is available.
|
||||
" If you want it to use a different bash, set this variable.
|
||||
" let g:fzf_vim = {}
|
||||
" let g:fzf_vim.preview_bash = 'C:\Git\bin\bash.exe'
|
||||
<
|
||||
|
||||
Command-level options~
|
||||
*fzf-vim-command-level-options*
|
||||
|
||||
*g:fzf_vim.commands_expect* *g:fzf_vim.tags_command* *g:fzf_vim.commits_log_options*
|
||||
*g:fzf_vim.buffers_jump*
|
||||
>
|
||||
" [Buffers] Jump to the existing window if possible (default: 0)
|
||||
let g:fzf_vim.buffers_jump = 1
|
||||
|
||||
" [Ag|Rg|RG] Display path on a separate line for narrow screens (default: 0)
|
||||
" * Requires Perl and fzf 0.56.0 or later
|
||||
let g:fzf_vim.grep_multi_line = 0
|
||||
" PATH:LINE:COL:LINE
|
||||
let g:fzf_vim.grep_multi_line = 1
|
||||
" PATH:LINE:COL:
|
||||
" LINE
|
||||
let g:fzf_vim.grep_multi_line = 2
|
||||
" PATH:LINE:COL:
|
||||
" LINE
|
||||
" (empty line between items using --gap option)
|
||||
|
||||
" [[B]Commits] Customize the options used by 'git log':
|
||||
let g:fzf_vim.commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'
|
||||
|
||||
" [Tags] Command to generate tags file
|
||||
let g:fzf_vim.tags_command = 'ctags -R'
|
||||
|
||||
" [Commands] --expect expression for directly executing the command
|
||||
let g:fzf_vim.commands_expect = 'alt-enter,ctrl-x'
|
||||
<
|
||||
|
||||
Command-level fzf options~
|
||||
*fzf-vim-command-level-fzf-options*
|
||||
|
||||
You can set fzf options for each command by setting
|
||||
`g:fzf_vim.{command}_options`.
|
||||
>
|
||||
" In string
|
||||
let g:fzf_vim.buffers_options = '--style full --border-label " Open Buffers "'
|
||||
|
||||
" In list (No need to quote or escape values)
|
||||
let g:fzf_vim.buffers_options = ['--style', 'full', '--border-label', ' Open Buffers ']
|
||||
<
|
||||
|
||||
List type to handle multiple selections~
|
||||
*fzf-vim-list-type-to-handle-multiple-selections*
|
||||
|
||||
The following commands will fill the quickfix list when multiple entries are
|
||||
selected.
|
||||
|
||||
- `Ag`
|
||||
- `Rg` / `RG`
|
||||
- `Lines` / `BLines`
|
||||
- `Tags` / `BTags`
|
||||
|
||||
*g:fzf_vim.listproc*
|
||||
|
||||
By setting `g:fzf_vim.listproc`, you can make them use location list instead.
|
||||
>
|
||||
" Default: Use quickfix list
|
||||
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#quickfix(list) }
|
||||
|
||||
" Use location list instead of quickfix list
|
||||
let g:fzf_vim.listproc = { list -> fzf#vim#listproc#location(list) }
|
||||
<
|
||||
You can customize the list type per command by defining variables named
|
||||
`g:fzf_vim.listproc_{command_name_in_lowercase}`.
|
||||
|
||||
*g:fzf_vim.listproc_rg* *g:fzf_vim.listproc_ag*
|
||||
>
|
||||
" Command-wise customization
|
||||
let g:fzf_vim.listproc_ag = { list -> fzf#vim#listproc#quickfix(list) }
|
||||
let g:fzf_vim.listproc_rg = { list -> fzf#vim#listproc#location(list) }
|
||||
<
|
||||
You can further customize the behavior by providing a custom function to
|
||||
process the list instead of using the predefined `fzf#vim#listproc#quickfix`
|
||||
or `fzf#vim#listproc#location`.
|
||||
>
|
||||
" A customized version of fzf#vim#listproc#quickfix.
|
||||
" The last two lines are commented out not to move to the first entry.
|
||||
function! g:fzf_vim.listproc(list)
|
||||
call setqflist(a:list)
|
||||
copen
|
||||
wincmd p
|
||||
" cfirst
|
||||
" normal! zvzz
|
||||
endfunction
|
||||
<
|
||||
|
||||
< Advanced customization >____________________________________________________~
|
||||
*fzf-vim-advanced-customization*
|
||||
|
||||
|
||||
Vim functions~
|
||||
*fzf-vim-vim-functions*
|
||||
|
||||
Each command in fzf.vim is backed by a Vim function. You can override a
|
||||
command or define a variation of it by calling its corresponding function.
|
||||
|
||||
----------+---------------------------------------------------------------------------------
|
||||
Command | Vim function ~
|
||||
----------+---------------------------------------------------------------------------------
|
||||
`Files` | `fzf#vim#files(dir, [spec dict], [fullscreen bool])`
|
||||
`GFiles` | `fzf#vim#gitfiles(git_options, [spec dict], [fullscreen bool])`
|
||||
`GFiles?` | `fzf#vim#gitfiles('?', [spec dict], [fullscreen bool])`
|
||||
`Buffers` | `fzf#vim#buffers([query string], [bufnrs list], [spec dict], [fullscreen bool])`
|
||||
`Colors` | `fzf#vim#colors([spec dict], [fullscreen bool])`
|
||||
`Rg` | `fzf#vim#grep(command, [spec dict], [fullscreen bool])`
|
||||
`RG` | `fzf#vim#grep2(command_prefix, query, [spec dict], [fullscreen bool])`
|
||||
... | ...
|
||||
----------+---------------------------------------------------------------------------------
|
||||
|
||||
(We can see that the last two optional arguments of each function are
|
||||
identical. They are directly passed to `fzf#wrap` function. If you haven't
|
||||
read {README-VIM}{3} already, please read it before proceeding.)
|
||||
|
||||
{3} https://github.com/junegunn/fzf/blob/master/README-VIM.md
|
||||
|
||||
|
||||
Example: Customizing Files command~
|
||||
*fzf-vim-example-customizing-files-command*
|
||||
|
||||
This is the default definition of `Files` command:
|
||||
>
|
||||
command! -bang -nargs=? -complete=dir Files call fzf#vim#files(<q-args>, <bang>0)
|
||||
<
|
||||
Let's say you want to a variation of it called `ProjectFiles` that only
|
||||
searches inside `~/projects` directory. Then you can do it like this:
|
||||
>
|
||||
command! -bang ProjectFiles call fzf#vim#files('~/projects', <bang>0)
|
||||
<
|
||||
Or, if you want to override the command with different fzf options, just pass
|
||||
a custom spec to the function.
|
||||
>
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline']}, <bang>0)
|
||||
<
|
||||
Want a preview window?
|
||||
>
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', 'cat {}']}, <bang>0)
|
||||
<
|
||||
It kind of works, but you probably want a nicer previewer program than `cat`.
|
||||
fzf.vim ships {a versatile preview script}{12} you can readily use. It
|
||||
internally executes {bat}{4} for syntax highlighting, so make sure to install
|
||||
it.
|
||||
>
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, {'options': ['--layout=reverse', '--info=inline', '--preview', '~/.vim/plugged/fzf.vim/bin/preview.sh {}']}, <bang>0)
|
||||
<
|
||||
However, it's not ideal to hard-code the path to the script which can be
|
||||
different in different circumstances. So in order to make it easier to set up
|
||||
the previewer, fzf.vim provides `fzf#vim#with_preview` helper function.
|
||||
Similarly to `fzf#wrap`, it takes a spec dictionary and returns a copy of it
|
||||
with additional preview options.
|
||||
>
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview({'options': ['--layout=reverse', '--info=inline']}), <bang>0)
|
||||
<
|
||||
You can just omit the spec argument if you only want the previewer.
|
||||
>
|
||||
command! -bang -nargs=? -complete=dir Files
|
||||
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)
|
||||
<
|
||||
{12} bin/preview.sh
|
||||
{4} https://github.com/sharkdp/bat
|
||||
|
||||
|
||||
Example: git grep wrapper~
|
||||
*fzf-vim-example-git-grep-wrapper*
|
||||
|
||||
The following example implements `GGrep` command that works similarly to
|
||||
predefined `Ag` or `Rg` using `fzf#vim#grep`.
|
||||
|
||||
- We set the base directory to git root by setting `dir` attribute in spec
|
||||
dictionary.
|
||||
- {The preview script}{12} supports `grep` format (`FILE_PATH:LINE_NO:...`), so
|
||||
we can just wrap the spec with `fzf#vim#with_preview` as before to enable
|
||||
previewer.
|
||||
>
|
||||
command! -bang -nargs=* GGrep
|
||||
\ call fzf#vim#grep(
|
||||
\ 'git grep --line-number -- '.fzf#shellescape(<q-args>),
|
||||
\ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0)
|
||||
<
|
||||
{12} bin/preview.sh
|
||||
|
||||
|
||||
MAPPINGS *fzf-vim-mappings*
|
||||
==============================================================================
|
||||
|
||||
---------------------------------+------------------------------------------
|
||||
Mapping | Description ~
|
||||
---------------------------------+------------------------------------------
|
||||
<plug>(fzf-maps-n) | Normal mode mappings
|
||||
<plug>(fzf-maps-i) | Insert mode mappings
|
||||
<plug>(fzf-maps-x) | Visual mode mappings
|
||||
<plug>(fzf-maps-o) | Operator-pending mappings
|
||||
<plug>(fzf-complete-word) | `cat /usr/share/dict/words`
|
||||
<plug>(fzf-complete-path) | Path completion using `find` (file + dir)
|
||||
<plug>(fzf-complete-file) | File completion using `find`
|
||||
<plug>(fzf-complete-line) | Line completion (all open buffers)
|
||||
<plug>(fzf-complete-buffer-line) | Line completion (current buffer only)
|
||||
---------------------------------+------------------------------------------
|
||||
>
|
||||
" Mapping selecting mappings
|
||||
nmap <leader><tab> <plug>(fzf-maps-n)
|
||||
xmap <leader><tab> <plug>(fzf-maps-x)
|
||||
omap <leader><tab> <plug>(fzf-maps-o)
|
||||
|
||||
" Insert mode completion
|
||||
imap <c-x><c-k> <plug>(fzf-complete-word)
|
||||
imap <c-x><c-f> <plug>(fzf-complete-path)
|
||||
imap <c-x><c-l> <plug>(fzf-complete-line)
|
||||
<
|
||||
|
||||
COMPLETION FUNCTIONS *fzf-vim-completion-functions*
|
||||
==============================================================================
|
||||
|
||||
-----------------------------------------+--------------------------------------
|
||||
Function | Description ~
|
||||
-----------------------------------------+--------------------------------------
|
||||
`fzf#vim#complete#path(command, [spec])` | Path completion
|
||||
`fzf#vim#complete#word([spec])` | Word completion
|
||||
`fzf#vim#complete#line([spec])` | Line completion (all open buffers)
|
||||
`fzf#vim#complete#buffer_line([spec])` | Line completion (current buffer only)
|
||||
-----------------------------------------+--------------------------------------
|
||||
>
|
||||
" Path completion with custom source command
|
||||
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('fd')
|
||||
inoremap <expr> <c-x><c-f> fzf#vim#complete#path('rg --files')
|
||||
|
||||
" Word completion with custom spec with popup layout option
|
||||
inoremap <expr> <c-x><c-k> fzf#vim#complete#word({'window': { 'width': 0.2, 'height': 0.9, 'xoffset': 1 }})
|
||||
<
|
||||
|
||||
CUSTOM COMPLETION *fzf-vim-custom-completion*
|
||||
==============================================================================
|
||||
|
||||
`fzf#vim#complete` is a helper function for creating custom fuzzy completion
|
||||
using fzf. If the first parameter is a command string or a Vim list, it will
|
||||
be used as the source.
|
||||
>
|
||||
" Replace the default dictionary completion with fzf-based fuzzy completion
|
||||
inoremap <expr> <c-x><c-k> fzf#vim#complete('cat /usr/share/dict/words')
|
||||
<
|
||||
For advanced uses, you can pass an options dictionary to the function. The set
|
||||
of options is pretty much identical to that for `fzf#run` only with the
|
||||
following exceptions:
|
||||
|
||||
- `reducer` (funcref)
|
||||
- Reducer transforms the output lines of fzf into a single string value
|
||||
- `prefix` (string or funcref; default: `\k*$`)
|
||||
- Regular expression pattern to extract the completion prefix
|
||||
- Or a function to extract completion prefix
|
||||
- Both `source` and `options` can be given as funcrefs that take the completion
|
||||
prefix as the argument and return the final value
|
||||
- `sink` or `sink*` are ignored
|
||||
>
|
||||
" Global line completion (not just open buffers. ripgrep required.)
|
||||
inoremap <expr> <c-x><c-l> fzf#vim#complete(fzf#wrap({
|
||||
\ 'prefix': '^.*$',
|
||||
\ 'source': 'rg -n ^ --color always',
|
||||
\ 'options': '--ansi --delimiter : --nth 3..',
|
||||
\ 'reducer': { lines -> join(split(lines[0], ':\zs')[2:], '') }}))
|
||||
<
|
||||
|
||||
< Reducer example >___________________________________________________________~
|
||||
*fzf-vim-reducer-example*
|
||||
>
|
||||
function! s:make_sentence(lines)
|
||||
return substitute(join(a:lines), '^.', '\=toupper(submatch(0))', '').'.'
|
||||
endfunction
|
||||
|
||||
inoremap <expr> <c-x><c-s> fzf#vim#complete({
|
||||
\ 'source': 'cat /usr/share/dict/words',
|
||||
\ 'reducer': function('<sid>make_sentence'),
|
||||
\ 'options': '--multi --reverse --margin 15%,0',
|
||||
\ 'left': 20})
|
||||
<
|
||||
|
||||
STATUS LINE OF TERMINAL BUFFER *fzf-vim-status-line-of-terminal-buffer*
|
||||
==============================================================================
|
||||
|
||||
When fzf starts in a terminal buffer (see {fzf/README-VIM.md}{13}), you may
|
||||
want to customize the statusline of the containing buffer.
|
||||
|
||||
{13} https://github.com/junegunn/fzf/blob/master/README-VIM.md#fzf-inside-terminal-buffer
|
||||
|
||||
|
||||
< Hide statusline >___________________________________________________________~
|
||||
*fzf-vim-hide-statusline*
|
||||
>
|
||||
autocmd! FileType fzf set laststatus=0 noshowmode noruler
|
||||
\| autocmd BufLeave <buffer> set laststatus=2 showmode ruler
|
||||
<
|
||||
|
||||
< Custom statusline >_________________________________________________________~
|
||||
*fzf-vim-custom-statusline*
|
||||
>
|
||||
function! s:fzf_statusline()
|
||||
" Override statusline as you like
|
||||
highlight fzf1 ctermfg=161 ctermbg=251
|
||||
highlight fzf2 ctermfg=23 ctermbg=251
|
||||
highlight fzf3 ctermfg=237 ctermbg=251
|
||||
setlocal statusline=%#fzf1#\ >\ %#fzf2#fz%#fzf3#f
|
||||
endfunction
|
||||
|
||||
autocmd! User FzfStatusLine call <SID>fzf_statusline()
|
||||
<
|
||||
|
||||
LICENSE *fzf-vim-license*
|
||||
==============================================================================
|
||||
|
||||
MIT
|
||||
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:sw=2:ts=2:ft=help:norl:nowrap:
|
||||
164
vim/.config/vim/pack/plugins/start/fzf.vim/plugin/fzf.vim
Normal file
164
vim/.config/vim/pack/plugins/start/fzf.vim/plugin/fzf.vim
Normal file
@@ -0,0 +1,164 @@
|
||||
" Copyright (c) 2015 Junegunn Choi
|
||||
"
|
||||
" MIT License
|
||||
"
|
||||
" 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.
|
||||
|
||||
if exists('g:loaded_fzf_vim')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_fzf_vim = 1
|
||||
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
let s:is_win = has('win32') || has('win64')
|
||||
|
||||
function! s:conf(name, default)
|
||||
let conf = get(g:, 'fzf_vim', {})
|
||||
let val = get(conf, a:name, get(g:, 'fzf_' . a:name, a:default))
|
||||
return val
|
||||
endfunction
|
||||
|
||||
function! s:defs(commands)
|
||||
let prefix = s:conf('command_prefix', '')
|
||||
if prefix =~# '^[^A-Z]'
|
||||
echoerr 'g:fzf_command_prefix must start with an uppercase letter'
|
||||
return
|
||||
endif
|
||||
for command in a:commands
|
||||
let name = ':'.prefix.matchstr(command, '\C[A-Z]\S\+')
|
||||
if 2 != exists(name)
|
||||
execute substitute(command, '\ze\C[A-Z]', prefix, '')
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
call s:defs([
|
||||
\'command! -bang -nargs=? -complete=dir Files call fzf#vim#files(<q-args>, fzf#vim#with_preview(), <bang>0)',
|
||||
\'command! -bang -nargs=? GitFiles call fzf#vim#gitfiles(<q-args>, fzf#vim#with_preview(<q-args> == "?" ? { "placeholder": "" } : {}), <bang>0)',
|
||||
\'command! -bang -nargs=? GFiles call fzf#vim#gitfiles(<q-args>, fzf#vim#with_preview(<q-args> == "?" ? { "placeholder": "" } : {}), <bang>0)',
|
||||
\'command! -bar -bang -nargs=? -complete=buffer Buffers call fzf#vim#buffers(<q-args>, fzf#vim#with_preview({ "placeholder": "{1}" }), <bang>0)',
|
||||
\'command! -bang -nargs=* Lines call fzf#vim#lines(<q-args>, <bang>0)',
|
||||
\'command! -bang -nargs=* BLines call fzf#vim#buffer_lines(<q-args>, <bang>0)',
|
||||
\'command! -bar -bang Colors call fzf#vim#colors(<bang>0)',
|
||||
\'command! -bang -nargs=+ -complete=dir Locate call fzf#vim#locate(<q-args>, fzf#vim#with_preview(), <bang>0)',
|
||||
\'command! -bang -nargs=* Ag call fzf#vim#ag(<q-args>, fzf#vim#with_preview(), <bang>0)',
|
||||
\'command! -bang -nargs=* Rg call fzf#vim#grep("rg --column --line-number --no-heading --color=always --smart-case -- ".fzf#shellescape(<q-args>), fzf#vim#with_preview(), <bang>0)',
|
||||
\'command! -bang -nargs=* RG call fzf#vim#grep2("rg --column --line-number --no-heading --color=always --smart-case -- ", <q-args>, fzf#vim#with_preview(), <bang>0)',
|
||||
\'command! -bang -nargs=* Tags call fzf#vim#tags(<q-args>, fzf#vim#with_preview({ "placeholder": "--tag {2}:{-1}:{3..}" }), <bang>0)',
|
||||
\'command! -bang -nargs=* BTags call fzf#vim#buffer_tags(<q-args>, fzf#vim#with_preview({ "placeholder": "{2}:{3..}" }), <bang>0)',
|
||||
\'command! -bar -bang Snippets call fzf#vim#snippets(<bang>0)',
|
||||
\'command! -bar -bang Commands call fzf#vim#commands(<bang>0)',
|
||||
\'command! -bar -bang Jumps call fzf#vim#jumps(fzf#vim#with_preview({ "placeholder": "{2..4}"}), <bang>0)',
|
||||
\'command! -bar -bang -nargs=* Marks call fzf#vim#marks(<q-args>, <bang>0)',
|
||||
\'command! -bar -bang -nargs=* BMarks call fzf#vim#marks("abcdefghijklmnopqrstuvwxyz", <bang>0)',
|
||||
\'command! -bar -bang Changes call fzf#vim#changes(<bang>0)',
|
||||
\'command! -bar -bang Helptags call fzf#vim#helptags(fzf#vim#with_preview({ "placeholder": "--tag {2}:{3}:{4}" }), <bang>0)',
|
||||
\'command! -bar -bang Windows call fzf#vim#windows(fzf#vim#with_preview({ "placeholder": "{2}" }), <bang>0)',
|
||||
\'command! -bar -bang -nargs=* -range=% -complete=file Commits let b:fzf_winview = winsaveview() | <line1>,<line2>call fzf#vim#commits(<q-args>, fzf#vim#with_preview({ "placeholder": "" }), <bang>0)',
|
||||
\'command! -bar -bang -nargs=* -range=% BCommits let b:fzf_winview = winsaveview() | <line1>,<line2>call fzf#vim#buffer_commits(<q-args>, fzf#vim#with_preview({ "placeholder": "" }), <bang>0)',
|
||||
\'command! -bar -bang Maps call fzf#vim#maps("n", <bang>0)',
|
||||
\'command! -bar -bang Filetypes call fzf#vim#filetypes(<bang>0)',
|
||||
\'command! -bang -nargs=* History call s:history(<q-args>, fzf#vim#with_preview(), <bang>0)'])
|
||||
|
||||
function! s:history(arg, extra, bang)
|
||||
let bang = a:bang || a:arg[len(a:arg)-1] == '!'
|
||||
if a:arg[0] == ':'
|
||||
call fzf#vim#command_history(bang)
|
||||
elseif a:arg[0] == '/'
|
||||
call fzf#vim#search_history(bang)
|
||||
else
|
||||
call fzf#vim#history(a:extra, bang)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! fzf#complete(...)
|
||||
return call('fzf#vim#complete', a:000)
|
||||
endfunction
|
||||
|
||||
if (has('nvim') || has('terminal') && has('patch-8.0.995')) && (s:conf('statusline', 1) || s:conf('nvim_statusline', 1))
|
||||
function! s:fzf_restore_colors()
|
||||
if exists('#User#FzfStatusLine')
|
||||
doautocmd User FzfStatusLine
|
||||
else
|
||||
if $TERM !~ "256color"
|
||||
highlight default fzf1 ctermfg=1 ctermbg=8 guifg=#E12672 guibg=#565656
|
||||
highlight default fzf2 ctermfg=2 ctermbg=8 guifg=#BCDDBD guibg=#565656
|
||||
highlight default fzf3 ctermfg=7 ctermbg=8 guifg=#D9D9D9 guibg=#565656
|
||||
else
|
||||
highlight default fzf1 ctermfg=161 ctermbg=238 guifg=#E12672 guibg=#565656
|
||||
highlight default fzf2 ctermfg=151 ctermbg=238 guifg=#BCDDBD guibg=#565656
|
||||
highlight default fzf3 ctermfg=252 ctermbg=238 guifg=#D9D9D9 guibg=#565656
|
||||
endif
|
||||
setlocal statusline=%#fzf1#\ >\ %#fzf2#fz%#fzf3#f
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:fzf_vim_term()
|
||||
if get(w:, 'airline_active', 0)
|
||||
let w:airline_disabled = 1
|
||||
autocmd BufWinLeave <buffer> let w:airline_disabled = 0
|
||||
endif
|
||||
autocmd WinEnter,ColorScheme <buffer> call s:fzf_restore_colors()
|
||||
|
||||
setlocal nospell
|
||||
call s:fzf_restore_colors()
|
||||
endfunction
|
||||
|
||||
augroup _fzf_statusline
|
||||
autocmd!
|
||||
autocmd FileType fzf call s:fzf_vim_term()
|
||||
augroup END
|
||||
endif
|
||||
|
||||
if !exists('g:fzf#vim#buffers')
|
||||
let g:fzf#vim#buffers = {}
|
||||
endif
|
||||
|
||||
augroup fzf_buffers
|
||||
autocmd!
|
||||
if exists('*reltimefloat')
|
||||
autocmd BufWinEnter,WinEnter * let g:fzf#vim#buffers[bufnr('')] = reltimefloat(reltime())
|
||||
else
|
||||
autocmd BufWinEnter,WinEnter * let g:fzf#vim#buffers[bufnr('')] = localtime()
|
||||
endif
|
||||
autocmd BufDelete * silent! call remove(g:fzf#vim#buffers, expand('<abuf>'))
|
||||
augroup END
|
||||
|
||||
inoremap <expr> <plug>(fzf-complete-word) fzf#vim#complete#word()
|
||||
if s:is_win
|
||||
inoremap <expr> <plug>(fzf-complete-path) fzf#vim#complete#path('dir /s/b')
|
||||
inoremap <expr> <plug>(fzf-complete-file) fzf#vim#complete#path('dir /s/b/a:-d')
|
||||
else
|
||||
inoremap <expr> <plug>(fzf-complete-path) fzf#vim#complete#path("find . -path '*/\.*' -prune -o -print \| sed '1d;s:^..::'")
|
||||
inoremap <expr> <plug>(fzf-complete-file) fzf#vim#complete#path("find . -path '*/\.*' -prune -o -type f -print -o -type l -print \| sed 's:^..::'")
|
||||
endif
|
||||
inoremap <expr> <plug>(fzf-complete-file-ag) fzf#vim#complete#path('ag -l -g ""')
|
||||
inoremap <expr> <plug>(fzf-complete-line) fzf#vim#complete#line()
|
||||
inoremap <expr> <plug>(fzf-complete-buffer-line) fzf#vim#complete#buffer_line()
|
||||
|
||||
nnoremap <silent> <plug>(fzf-maps-n) :<c-u>call fzf#vim#maps('n', 0)<cr>
|
||||
inoremap <silent> <plug>(fzf-maps-i) <c-o>:call fzf#vim#maps('i', 0)<cr>
|
||||
xnoremap <silent> <plug>(fzf-maps-x) :<c-u>call fzf#vim#maps('x', 0)<cr>
|
||||
onoremap <silent> <plug>(fzf-maps-o) <c-c>:<c-u>call fzf#vim#maps('o', 0)<cr>
|
||||
|
||||
let &cpo = s:cpo_save
|
||||
unlet s:cpo_save
|
||||
|
||||
1
vim/.config/vim/pack/plugins/start/lsp
Submodule
1
vim/.config/vim/pack/plugins/start/lsp
Submodule
Submodule vim/.config/vim/pack/plugins/start/lsp added at e99ec151da
@@ -28,7 +28,8 @@ filetype plugin on
|
||||
filetype indent on
|
||||
set ofu=syntaxcomplete#Complete#
|
||||
|
||||
au FileType python setlocal tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
" au FileType python setlocal tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
au FileType markdown setlocal tabstop=4 expandtab shiftwidth=4 softtabstop=4
|
||||
|
||||
" enable snippets
|
||||
" let g:UltiSnipsExpandTrigger="<tab>"
|
||||
@@ -52,14 +53,19 @@ nmap <leader>jn <cmd>% !jsonnetfmt -<cr>
|
||||
nmap <leader>js <cmd>% !jq . -<cr>
|
||||
|
||||
set lazyredraw " redraw only when req'd
|
||||
|
||||
set wildmenu " visual auto-complete
|
||||
set showmatch
|
||||
set cursorline
|
||||
set wildmode=longest:full,full
|
||||
set wildignore=*.pyc,*.swp,.git/**
|
||||
|
||||
set showmatch " highlights matching parens
|
||||
|
||||
set cursorline " highlights the current line
|
||||
|
||||
" Search down into subfolders
|
||||
" Provides tab-completion for all file-related tasks
|
||||
set path+=**
|
||||
|
||||
|
||||
" netrw config
|
||||
let g:netrw_banner=0 " disable annoying banner
|
||||
let g:netrw_browse_split=0 " open in prior window
|
||||
@@ -72,7 +78,7 @@ let g:netrw_liststyle=3 " tree view
|
||||
" - <CR>/v/t to open in an h-split/v-split/tab
|
||||
" - check |netrw-browse-maps| for more mappings
|
||||
|
||||
" fzf-lua
|
||||
" fzf-lua shortcuts
|
||||
nnoremap <c-p> <cmd>Files<CR>
|
||||
nnoremap <c-\> <cmd>Buffers<CR>
|
||||
nnoremap <c-g> <cmd>Rg<CR>
|
||||
@@ -80,7 +86,7 @@ nnoremap <c-g> <cmd>Rg<CR>
|
||||
"
|
||||
" Github Copilot
|
||||
"
|
||||
" disable Copilot for now
|
||||
" disable Copilot ny default
|
||||
let g:copilot_enabled = 0
|
||||
" map key to enable copilot
|
||||
nmap <leader>cp :let g:copilot_enabled = 1<CR>
|
||||
Reference in New Issue
Block a user