Compare commits

...

6 Commits

Author SHA1 Message Date
0f1b35eda3 Don't call coc#status() if it doesn't exist 2021-04-19 20:10:29 +01:00
9aa45a4df5 Use coc-jedi and coc-pyright instead of coc-pyls 2021-04-19 20:10:29 +01:00
78e821e386 Add a call to coc#status() in statusline
Don't miss out on the status of coc.nvim by insuring updates are
rendered in the statusline.
2021-04-19 20:10:29 +01:00
2b02d0ae81 Ignore compiled python files 2021-04-19 20:10:29 +01:00
f00eb38200 Fix coc.nvim mappings in C/C++ files 2021-04-19 20:10:29 +01:00
46d27c17fd Move formatexpr config in-tree, out of plugin
Introduces the `format` Python module which provides `clang_format()`
and `yapf()` functions which efficiently (compared to vimscript) invoke
`clang-format` or `yapf` respectively then apply the minimal number of
changes using `difflib.SequenceMatcher`.

Additionally, in order to invoke these Python functions add |autoload|
functions `format#clang_format()` and `format#yapf()` which can be
directly used by the 'formatexpr' setting.

Finally, add |ftplugin| files which set 'formatexpr' when the |autoload|
functions are available.
2021-04-19 20:10:29 +01:00
16 changed files with 186 additions and 15 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ local.vim
.netrwhist .netrwhist
pack/* pack/*
spell/* spell/*
*.pyc

View File

@ -9,8 +9,6 @@ setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,:///,://
setlocal commentstring=//%s setlocal commentstring=//%s
" Stop automatic new lines which typing long single liners. " Stop automatic new lines which typing long single liners.
setlocal textwidth=0 setlocal textwidth=0
" Map K to get YouCompleteMe documentation.
nnoremap K :YcmCompleter GetDoc<CR>
" "ys{motion}t" turns "word" -> "TODO(word):" " "ys{motion}t" turns "word" -> "TODO(word):"
let b:surround_{char2nr("t")} = "TODO(\r):" let b:surround_{char2nr("t")} = "TODO(\r):"
" "ys{motion}/" turns "text" into "/*text*/" " "ys{motion}/" turns "text" into "/*text*/"

14
autoload/format.vim Normal file
View File

@ -0,0 +1,14 @@
if !has('pythonx')
finish
endif
" set debug=msg,throw
pythonx import format
function! format#clang_format() abort
pythonx format.clang_format()
endfunction
function! format#yapf() abort
pythonx format.yapf()
endfunction

3
ftplugin/c.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#clang_format()
endif

3
ftplugin/cpp.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#clang_format()
endif

3
ftplugin/java.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#clang_format()
endif

3
ftplugin/javascript.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#clang_format()
endif

3
ftplugin/objc.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#clang_format()
endif

3
ftplugin/objcpp.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#clang_format()
endif

3
ftplugin/proto.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#clang_format()
endif

3
ftplugin/python.vim Normal file
View File

@ -0,0 +1,3 @@
if has('pythonx')
set formatexpr=format#yapf()
endif

8
plugin/format.vim Normal file
View File

@ -0,0 +1,8 @@
if !has('pythonx')
finish
endif
let g:clang_format_path = get(g:, 'clang_format_path', 'clang-format')
let g:clang_format_style = get(g:, 'clang_format_style', 'google')
let g:yapf_path = get(g:, 'yapf_path', 'yapf')
let g:yapf_style = get(g:, 'yapf_style', 'pep8')

View File

@ -1,10 +1,10 @@
" coc.nvim " coc.nvim
nnoremap <silent> <leader>fi <Plug>(coc-fix-current) nmap <silent> <leader>fi <Plug>(coc-fix-current)
nnoremap <silent> <leader>gd <Plug>(coc-definition) nmap <silent> <leader>gd <Plug>(coc-definition)
nnoremap <silent> <leader>gt <Plug>(coc-type-definition) nmap <silent> <leader>gt <Plug>(coc-type-definition)
nnoremap <silent> <leader>sd <Plug>(coc-diagnostic-info) nmap <silent> <leader>sd <Plug>(coc-diagnostic-info)
nnoremap <silent> <leader>gr <Plug>(coc-references) nmap <silent> <leader>gr <Plug>(coc-references)
nnoremap <silent> K :call do#show_documentation()<CR> nmap <silent> K :call do#show_documentation()<CR>
if has('nvim') if has('nvim')
" Make nvim :terminal more like vim :terminal " Make nvim :terminal more like vim :terminal

View File

@ -1,4 +1,5 @@
" Show the statusline above the commandline. " Show the statusline above the commandline.
scriptencoding utf-8
set laststatus=2 set laststatus=2
" Define color variables. " Define color variables.
@ -6,10 +7,11 @@ let g:statusline#light_green = {'fg': ['235', '#080808'], 'bg': [ '35', '#0087f
let g:statusline#light_blue = {'fg': ['235', '#080808'], 'bg': [ '33', '#0087ff']} let g:statusline#light_blue = {'fg': ['235', '#080808'], 'bg': [ '33', '#0087ff']}
let g:statusline#light_orange = {'fg': ['235', '#080808'], 'bg': ['209', '#eb754d']} let g:statusline#light_orange = {'fg': ['235', '#080808'], 'bg': ['209', '#eb754d']}
let g:statusline#light_red = {'fg': ['235', '#080808'], 'bg': ['124', '#af0000']} let g:statusline#light_red = {'fg': ['235', '#080808'], 'bg': ['124', '#af0000']}
let g:statusline#light_grey = {'fg': ['250', "#bcbcbc"], 'bg': ['236', "#303030"]} let g:statusline#light_grey = {'fg': ['250', '#bcbcbc'], 'bg': ['236', '#303030']}
let g:statusline#light_violet = {'fg': ['235', '#080808'], 'bg': [ '99', '#986fec']} let g:statusline#light_violet = {'fg': ['235', '#080808'], 'bg': [ '99', '#986fec']}
let g:statusline#dark_white = {'fg': [ '15', '#ffffff'], 'bg': ['233', '#121212']} let g:statusline#dark_white = {'fg': [ '15', '#ffffff'], 'bg': ['233', '#121212']}
let g:statusline#dark_yellow = {'fg': ['179', '#dfaf5f'], 'bg': ['233', '#121212']} let g:statusline#dark_yellow = {'fg': ['179', '#dfaf5f'], 'bg': ['233', '#121212']}
let g:statusline#dark_grey = {'fg': ['244', '#808080'], 'bg': ['233', '#121212']}
" Create highlight groups. " Create highlight groups.
function! s:hi(group, color) abort function! s:hi(group, color) abort
@ -27,9 +29,12 @@ call s:hi('StatusLineDusk', g:statusline#light_grey)
" StatusLineDark shows the filename and filetype and takes up most of the " StatusLineDark shows the filename and filetype and takes up most of the
" statusline, give it a dark background. " statusline, give it a dark background.
call s:hi('StatusLineDark', g:statusline#dark_white) call s:hi('StatusLineDark', g:statusline#dark_white)
" StatusLineChange show changes in the file by changing the colour of the " StatusLineChange shows changes in the file by changing the colour of the
" filename, give if a dark background. " filename, give if a dark background.
call s:hi('StatusLineChange', g:statusline#dark_yellow) call s:hi('StatusLineChange', g:statusline#dark_yellow)
" StatusLineFade shows the status of completion engines but using colors which
" fade into the background to avoid grabbing attention.
call s:hi('StatusLineDuskFade', g:statusline#dark_grey)
" Construct a statusline for special buffer types. " Construct a statusline for special buffer types.
function! statusline#special(group, name, title) function! statusline#special(group, name, title)
@ -59,6 +64,12 @@ function! statusline#generic(group, mode)
let l:state = '%#StatusLineDark#' let l:state = '%#StatusLineDark#'
\.'%{&readonly ? " 🔒" : ""}' \.'%{&readonly ? " 🔒" : ""}'
\.'%{&modifiable ? "" : " ⛔"}' \.'%{&modifiable ? "" : " ⛔"}'
if exists('*coc#status')
" Display coc.nvim status.
let l:coc = '%#StatusLineDuskFade#%( %{coc#status()}%)'
else
let l:coc = ''
endif
" Display filetype if set. " Display filetype if set.
let l:type = '%#StatusLineDark# %{&filetype} ' let l:type = '%#StatusLineDark# %{&filetype} '
" Display fileencoding if not utf-8 and fileformat if not unix with dusk " Display fileencoding if not utf-8 and fileformat if not unix with dusk
@ -70,7 +81,7 @@ function! statusline#generic(group, mode)
" Display current/total lines and column with dynamic highlights. " Display current/total lines and column with dynamic highlights.
let l:line = '%#'.a:group.'# ☰ %l/%L ㏑%2c ' let l:line = '%#'.a:group.'# ☰ %l/%L ㏑%2c '
" Combine the elements into a single string to be evaluated. " Combine the elements into a single string to be evaluated.
return l:mode.l:edit.l:file.l:state.'%='.l:type.l:format.l:line return l:mode.l:edit.l:file.l:state.l:coc.'%='.l:type.l:format.l:line
endfunction endfunction
" Define active statusline, this statusline is dynamic with StatusLineLight " Define active statusline, this statusline is dynamic with StatusLineLight

117
pythonx/format.py Normal file
View File

@ -0,0 +1,117 @@
"""Python formatexpr for clang-format & yapf"""
import json
import sys
import subprocess
import difflib
import vim
class FormatError(Exception):
"""A formatting error."""
def clang_format():
"""Call clang-format on the current text object."""
clang_format = vim.vars['clang_format_path']
# TODO: The cursor position before gq is invoked is not preserved in the
# jump list, this expression will return the cursor position at the
# beginning of the motion or text object.
# Is there a way to get the cursor position immediately before gq is
# invoked? So that we can pass the position to clang-format in order for
# it to return the updated position to continue editing.
# Query the current absolute cursor positon.
cursor = int(vim.eval('line2byte(".") + col(".")')) - 2
if cursor < 0:
return
# Determine the lines to format.
startline = int(vim.eval('v:lnum'))
endline = startline + int(vim.eval('v:count')) - 1
lines = f'{startline}:{endline}'
fallback_style = vim.vars['clang_format_style']
# Construct the clang-format command to call.
command = [
clang_format, '-style', 'file', '-cursor',
str(cursor), '-lines', lines, '-fallback-style', fallback_style
]
if vim.current.buffer.name:
command += ['-assume-filename', vim.current.buffer.name]
# Call the clang-format command.
output = call(command)
if not output:
return
# Read the clang-format json header.
header = json.loads(output[0])
if header.get('IncompleteFormat'):
raise FormatError('clang-format: incomplete (syntax errors).')
# Replace the formatted regions.
replace_regions(output[1:])
# Set the updated cursor position.
vim.command('goto %d' % (header['Cursor'] + 1))
def yapf():
"""Call yapf on the current text object."""
yapf = vim.vars['yapf_path']
# Determine the lines to format.
start = int(vim.eval('v:lnum'))
end = start + int(vim.eval('v:count'))
lines = '{0}-{1}'.format(start, end)
style = vim.vars['yapf_style']
# Construct the clang-format command to call.
command = [yapf, '--style', style, '--lines', lines]
# TODO: Since yapf is a Python package, we could import the module and
# call it directly instead. It would then be possible to output better
# error messages and act on the buffer directly.
# Call the yapf command.
output = call(command)
if not output:
return
# Replace the formatted regions.
replace_regions(output[:-1])
def call(command):
"""Call the command to format the text.
Arguments:
command (list): Formatting command to call.
text (str): Text to be passed to stdin of command.
Returns:
list: The output of the formatter split on new lines.
None: If the subprocess failed.
"""
# Don't open a cmd prompt window on Windows.
startupinfo = None
if sys.platform.startswith('win32'):
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
# Call the formatting command.
process = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
startupinfo=startupinfo)
stdout, stderr = process.communicate(
input='\n'.join(vim.current.buffer).encode('utf-8'))
if stderr:
raise FormatError(stderr)
if not stdout:
raise FormatError('No output from {0}.'.format(command[0]))
# Split the lines into a list of elements.
return stdout.decode('utf-8').split('\n')
def replace_regions(lines):
"""Replace formatted regions in the current buffer.
Arguments:
lines (list): The formatted buffer lines.
"""
matcher = difflib.SequenceMatcher(None, vim.current.buffer, lines)
for tag, i1, i2, j1, j2 in reversed(matcher.get_opcodes()):
if tag != 'equal':
vim.current.buffer[i1:i2] = lines[j1:j2]

6
vimrc
View File

@ -33,9 +33,10 @@ let g:coc_global_extensions = [
\ 'coc-cmake', \ 'coc-cmake',
\ 'coc-css', \ 'coc-css',
\ 'coc-html', \ 'coc-html',
\ 'coc-jedi',
\ 'coc-json', \ 'coc-json',
\ 'coc-marketplace', \ 'coc-marketplace',
\ 'coc-pyls', \ 'coc-pyright',
\ 'coc-ultisnips', \ 'coc-ultisnips',
\ 'coc-vimlsp', \ 'coc-vimlsp',
\ 'coc-yaml', \ 'coc-yaml',
@ -59,9 +60,6 @@ let g:ale_cmake_cmakelint_options =
" Version control differences in the sign column " Version control differences in the sign column
Pack 'mhinz/vim-signify' Pack 'mhinz/vim-signify'
" format.vim - format with text objects
Pack 'git@bitbucket.org:infektor/format.vim.git'
" vim-textobj-user - library for creating text objects " vim-textobj-user - library for creating text objects
Pack 'kana/vim-textobj-user' Pack 'kana/vim-textobj-user'
" vim-textobj-entire - Entire file text object " vim-textobj-entire - Entire file text object