cleaning up
This commit is contained in:
parent
8f38a1df7b
commit
5bad8ef7a8
24 changed files with 287 additions and 187 deletions
18
.gitignore
vendored
18
.gitignore
vendored
|
@ -1,23 +1,19 @@
|
|||
# Created by https://www.gitignore.io/api/vim
|
||||
# Edit at https://www.gitignore.io/?templates=vim
|
||||
|
||||
### Vim ###
|
||||
# Swap
|
||||
# vim swap
|
||||
[._]*.s[a-v][a-z]
|
||||
[._]*.sw[a-p]
|
||||
[._]s[a-rt-v][a-z]
|
||||
[._]ss[a-gi-z]
|
||||
[._]sw[a-p]
|
||||
|
||||
# Session
|
||||
# session
|
||||
Session.vim
|
||||
|
||||
# Temporary
|
||||
# temporary
|
||||
.netrwhist
|
||||
*~
|
||||
# Auto-generated tag files
|
||||
tags
|
||||
# Persistent undo
|
||||
# persistent undo
|
||||
[._]*.un~
|
||||
|
||||
# End of https://www.gitignore.io/api/vim
|
||||
# handled by plugin manager (plugged)
|
||||
autoload/
|
||||
plugged/
|
||||
|
|
410
.vimrc
410
.vimrc
|
@ -3,53 +3,37 @@ filetype off " required
|
|||
|
||||
call plug#begin('~/.vim/plugged')
|
||||
|
||||
" reload config files automatically
|
||||
Plug 'xolox/vim-reload'
|
||||
|
||||
" Ctrlp for fuzzy file search
|
||||
Plug 'ctrlpvim/ctrlp.vim'
|
||||
|
||||
" File browser
|
||||
Plug 'scrooloose/nerdtree'
|
||||
|
||||
" tab support for nerdtree
|
||||
Plug 'jistr/vim-nerdtree-tabs'
|
||||
|
||||
" Snippet handler
|
||||
" Plug 'SirVer/ultisnips'
|
||||
|
||||
" snippets for ultisnips
|
||||
" Plug 'honza/vim-snippets'
|
||||
|
||||
" supertab for completion
|
||||
" Plug 'ervandew/supertab'
|
||||
|
||||
" YouCompleteMe auto-completion
|
||||
" Plug 'Valloric/YouCompleteMe'
|
||||
|
||||
" More clever matching for % key
|
||||
Plug 'tmhedberg/matchit'
|
||||
|
||||
" JavaScript syntax highlighting
|
||||
" Plug 'pangloss/vim-javascript'
|
||||
|
||||
" jsx syntax highlighting
|
||||
" Plug 'mxw/vim-jsx'
|
||||
|
||||
" Language server protocol linter
|
||||
" Plug 'w0rp/ale'
|
||||
|
||||
" fugitive.vim git integration
|
||||
Plug 'tpope/vim-fugitive'
|
||||
|
||||
" Clojure highlight
|
||||
" Plug 'guns/vim-clojure-static'
|
||||
|
||||
" Surround
|
||||
Plug 'tpope/vim-surround'
|
||||
|
||||
" Repeat of plugin commands
|
||||
Plug 'tpope/vim-repeat'
|
||||
|
||||
" Ack.vim -- can use ag with this
|
||||
Plug 'mileszs/ack.vim'
|
||||
" LSP support
|
||||
Plug 'yegappan/lsp'
|
||||
|
||||
" more commplete
|
||||
Plug 'girishji/vimcomplete'
|
||||
|
||||
" snippet support
|
||||
Plug 'hrsh7th/vim-vsnip'
|
||||
Plug 'hrsh7th/vim-vsnip-integ'
|
||||
Plug 'rafamadriz/friendly-snippets'
|
||||
|
||||
" Haskell syntax
|
||||
Plug 'neovimhaskell/haskell-vim'
|
||||
|
@ -60,6 +44,8 @@ Plug 'leafgarland/typescript-vim'
|
|||
call plug#end()
|
||||
" All of your Plugins must be added before the following line
|
||||
|
||||
language en_US.UTF-8
|
||||
|
||||
filetype plugin indent on " required
|
||||
syntax on
|
||||
|
||||
|
@ -83,91 +69,21 @@ set mouse=a
|
|||
set history=1000
|
||||
set undolevels=1000
|
||||
|
||||
|
||||
" highlight search results
|
||||
set hlsearch
|
||||
|
||||
" show tabs and spaces
|
||||
set list
|
||||
set listchars=tab:>··,trail:·
|
||||
set listchars=space:·,tab:..>,trail:·
|
||||
|
||||
hi SpecialKey ctermfg=darkgrey
|
||||
|
||||
" make delimitMate insert another line when
|
||||
" closing curlys for example
|
||||
let delimitMate_expand_cr = 1
|
||||
|
||||
" make YCM load with python 3
|
||||
let g:ycm_server_python_interpreter = '/usr/bin/python2'
|
||||
|
||||
" YCM non-arch package install path to ycm extra conf
|
||||
"let g:ycm_global_ycm_extra_conf = "~/.vim/bundle/YouCompleteMe/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py"
|
||||
|
||||
" YCM extra configuration for arch specific YCM package
|
||||
"let g:ycm_global_ycm_extra_conf = '/usr/share/vim/vimfiles/third_party/ycmd/cpp/ycm/.ycm_extra_conf.py'
|
||||
"let g:ycm_path_to_python_interpreter = '/usr/bin/python2'
|
||||
|
||||
" Eclim completion method should be set to omnifunc in order to work with YCM
|
||||
let g:EclimCompletionMethod = 'omnifunc'
|
||||
|
||||
" let syntastic handle the syntax checking
|
||||
let g:ycm_show_diagnostics_ui = 0
|
||||
|
||||
" make YCM compatible with UltiSnips (using supertab)
|
||||
let g:ycm_key_list_select_completion = ['<C-n>', '<Down>']
|
||||
let g:ycm_key_list_previous_completion = ['<C-p>', '<Up>']
|
||||
let g:SuperTabDefaultCompletionType = '<C-n>'
|
||||
|
||||
" better key bindings for UltiSnipsExpandTrigger
|
||||
let g:UltiSnipsExpandTrigger = "<tab>"
|
||||
let g:UltiSnipsJumpForwardTrigger = "<tab>"
|
||||
let g:UltiSnipsJumpBackwardTrigger = "<s-tab>"
|
||||
|
||||
" Leader maps
|
||||
let mapleader=","
|
||||
let maplocalleader="\\"
|
||||
map <leader>n <plug>NERDTreeTabsToggle<CR>
|
||||
|
||||
|
||||
autocmd VimEnter * wincmd p
|
||||
|
||||
|
||||
"for ino completion
|
||||
"autocmd BufNewFile,BufRead *.ino setlocal ft=arduino
|
||||
|
||||
" IMPORTANT: grep will sometimes skip displaying the file name if you
|
||||
" search in a singe file. This will confuse Latex-Suite. Set your grep
|
||||
" program to always generate a file-name.
|
||||
" set grepprg=grep\ -nH\ $*
|
||||
|
||||
" OPTIONAL: Starting with Vim 7, the filetype of empty .tex files defaults to
|
||||
" 'plaintex' instead of 'tex', which results in vim-latex not being loaded.
|
||||
" The following changes the default filetype back to 'tex':
|
||||
" let g:tex_flavor='latex'
|
||||
|
||||
" Short commands -----------------------
|
||||
|
||||
" Searching for visually selected text
|
||||
vnoremap // y/<C-R>"<CR>"
|
||||
|
||||
" For latex compiling
|
||||
augroup latex_macros " {
|
||||
autocmd!
|
||||
autocmd FileType tex :nnoremap <leader>c :w<CR> :!latexmk -pdf % <CR>
|
||||
autocmd FileType tex :nnoremap <leader>v :!evince %:r.pdf &<CR><CR>
|
||||
augroup END " }
|
||||
|
||||
" JavaScript macros
|
||||
augroup html_macros " {
|
||||
autocmd!
|
||||
autocmd FileType html :nnoremap <leader>c :w<CR> :silent !firefox %:p &<CR>
|
||||
augroup END " }
|
||||
|
||||
augroup javascript_macros " {
|
||||
autocmd!
|
||||
autocmd FileType javascript.jsx :nnoremap <localleader>df :YcmCompleter GoTo<CR>
|
||||
augroup END " }
|
||||
|
||||
" JSON macros
|
||||
" TODO move to ftplugin
|
||||
augroup json_macros " {
|
||||
autocmd!
|
||||
autocmd FileType json :nnoremap <localleader>fm :%!python -m json.tool<CR>
|
||||
|
@ -185,82 +101,11 @@ augroup c_stuff " {
|
|||
autocmd BufNewFile,BufRead *.h set ft=c
|
||||
augroup END " }
|
||||
|
||||
augroup verona_stuff " {
|
||||
autocmd!
|
||||
autocmd BufNewFile,BufRead *.verona set ft=typescript
|
||||
augroup end " }
|
||||
|
||||
" Function for toggling the relative line numbers
|
||||
function ToggleRelative()
|
||||
if &relativenumber==1
|
||||
set norelativenumber
|
||||
else
|
||||
set relativenumber
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Macros for toggling relative number lines
|
||||
noremap <F3> :call ToggleRelative()<CR>
|
||||
inoremap <F3> <C-O>:call ToggleRelative()<CR>
|
||||
|
||||
function GrepAskForDir(specifier)
|
||||
let cw = expand("<cword>")
|
||||
let cwd = getcwd()
|
||||
call inputsave()
|
||||
let dir = input('Grep for word ' . cw . 'in dir: ')
|
||||
call inputrestore()
|
||||
execute 'Ack '. a:specifier . ' ' . dir
|
||||
endfunction
|
||||
|
||||
noremap <leader>g :call GrepAskForDir(expand("<cword>"))<CR>
|
||||
|
||||
function SetIdentWidth()
|
||||
call inputsave()
|
||||
let l:width = input('Set ident: ')
|
||||
call inputrestore()
|
||||
if l:width==''
|
||||
set tabstop=8 shiftwidth=8 noexpandtab
|
||||
else
|
||||
let l:numw = str2nr(l:width, 10)
|
||||
execute 'set softtabstop=' . l:numw . ' shiftwidth=' . l:numw . ' expandtab'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
noremap <leader>i :call SetIdentWidth()<CR>
|
||||
noremap <leader>r :call ToggleRelative()<CR>
|
||||
|
||||
" Automatically user relative lines when not in insert mode
|
||||
" au InsertLeave * :set relativenumber
|
||||
" au InsertEnter * :set norelativenumber
|
||||
|
||||
|
||||
" Syntastic settings
|
||||
"let g:syntastic_mode_map = {
|
||||
" \ "mode": "active",
|
||||
" \ "passive_filetypes": ["java", "scala"] }
|
||||
|
||||
" Ale linter settings
|
||||
let g:ale_linters = {
|
||||
\ 'javascript': ['standard'],
|
||||
\}
|
||||
let g:ale_fixers = {'javascript': ['standard']}
|
||||
|
||||
"let g:ale_lint_on_text_changed = 'never'
|
||||
|
||||
" Ctrl-p settings
|
||||
"let g:ctrlp_max_files = 30000
|
||||
let g:ctrlp_user_command = ['.git', 'cd %s && git ls-files -co --exclude-standard']
|
||||
|
||||
let g:ale_linters_explicit = 1
|
||||
|
||||
" hlsearch
|
||||
noremap <leader>h :nohlsearch<CR>
|
||||
|
||||
" Ack
|
||||
if executable('ag')
|
||||
let g:ackprg = 'ag --vimgrep'
|
||||
endif
|
||||
|
||||
digraphs \- 8866
|
||||
digraphs -\ 8867
|
||||
digraphs !( 8840
|
||||
|
@ -274,4 +119,221 @@ digraphs /) 8716
|
|||
" Markdown
|
||||
let g:markdown_fenced_languages = ['python', 'typescript', 'javascript', 'haskell']
|
||||
|
||||
colorscheme habamax
|
||||
|
||||
" ############## AUTOCOMPLETE STUFF ##############
|
||||
|
||||
" ############## autocomplete
|
||||
|
||||
let autocomplete_opts = #{
|
||||
\ vsnip : #{ enable: v:true }
|
||||
\ }
|
||||
|
||||
" Expand
|
||||
imap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<C-j>'
|
||||
smap <expr> <C-j> vsnip#expandable() ? '<Plug>(vsnip-expand)' : '<C-j>'
|
||||
|
||||
" Expand or jump
|
||||
imap <expr> <C-l> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'
|
||||
smap <expr> <C-l> vsnip#available(1) ? '<Plug>(vsnip-expand-or-jump)' : '<C-l>'
|
||||
|
||||
" Jump forward or backward
|
||||
imap <expr> <Tab> vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
smap <expr> <Tab> vsnip#jumpable(1) ? '<Plug>(vsnip-jump-next)' : '<Tab>'
|
||||
imap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
smap <expr> <S-Tab> vsnip#jumpable(-1) ? '<Plug>(vsnip-jump-prev)' : '<S-Tab>'
|
||||
|
||||
" Select or cut text to use as $TM_SELECTED_TEXT in the next snippet.
|
||||
" See https://github.com/hrsh7th/vim-vsnip/pull/50
|
||||
" nmap s <Plug>(vsnip-select-text)
|
||||
" xmap s <Plug>(vsnip-select-text)
|
||||
" nmap S <Plug>(vsnip-cut-text)
|
||||
" xmap S <Plug>(vsnip-cut-text)
|
||||
|
||||
" If you want to use snippet for multiple filetypes, you can `g:vsnip_filetypes` for it.
|
||||
"let g:vsnip_filetypes = {}
|
||||
|
||||
|
||||
" lsp support stuff
|
||||
let g:lspOpts = #{
|
||||
\ aleSupport: v:false,
|
||||
\ autoComplete: v:true,
|
||||
\ autoHighlight: v:false,
|
||||
\ autoHighlightDiags: v:true,
|
||||
\ autoPopulateDiags: v:false,
|
||||
\ completionMatcher: 'case',
|
||||
\ completionMatcherValue: 1,
|
||||
\ diagSignErrorText: 'E>',
|
||||
\ diagSignHintText: 'H>',
|
||||
\ diagSignInfoText: 'I>',
|
||||
\ diagSignWarningText: 'W>',
|
||||
\ echoSignature: v:false,
|
||||
\ hideDisabledCodeActions: v:false,
|
||||
\ highlightDiagInline: v:false,
|
||||
\ hoverInPreview: v:false,
|
||||
\ ignoreMissingServer: v:false,
|
||||
\ keepFocusInDiags: v:true,
|
||||
\ keepFocusInReferences: v:true,
|
||||
\ completionTextEdit: v:true,
|
||||
\ diagVirtualTextAlign: 'above',
|
||||
\ diagVirtualTextWrap: 'default',
|
||||
\ noNewlineInCompletion: v:false,
|
||||
\ omniComplete: v:null,
|
||||
\ outlineOnRight: v:false,
|
||||
\ outlineWinSize: 20,
|
||||
\ semanticHighlight: v:false,
|
||||
\ showDiagInBalloon: v:true,
|
||||
\ showDiagInPopup: v:true,
|
||||
\ showDiagOnStatusLine: v:false,
|
||||
\ showDiagWithSign: v:true,
|
||||
\ showDiagWithVirtualText: v:false,
|
||||
\ showInlayHints: v:false,
|
||||
\ showSignature: v:true,
|
||||
\ snippetSupport: v:false,
|
||||
\ ultisnipsSupport: v:false,
|
||||
\ useBufferCompletion: v:false,
|
||||
\ usePopupInCodeAction: v:false,
|
||||
\ useQuickfixForLocations: v:false,
|
||||
\ vsnipSupport: v:false,
|
||||
\ bufferCompletionTimeout: 100,
|
||||
\ customCompletionKinds: v:false,
|
||||
\ completionKinds: {},
|
||||
\ filterCompletionDuplicates: v:false,
|
||||
\ }
|
||||
|
||||
autocmd User LspSetup call LspOptionsSet(lspOpts)
|
||||
|
||||
|
||||
let lspServers = [#{
|
||||
\ name: 'clang',
|
||||
\ filetype: ['c', 'cpp'],
|
||||
\ path: '/usr/bin/clangd',
|
||||
\ args: ['--background-index', '--header-insertion=never']
|
||||
\ }]
|
||||
autocmd User LspSetup call LspAddServer(lspServers)
|
||||
|
||||
|
||||
" ============ LogE_* =================
|
||||
|
||||
" Toggle relative line numbers
|
||||
function LogE_ToggleRelative()
|
||||
if &relativenumber==1
|
||||
set norelativenumber
|
||||
else
|
||||
set relativenumber
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" grep for arg in current or specified dir
|
||||
function LogE_GrepAskForDir(what)
|
||||
call inputsave()
|
||||
let dir = input('grep -r "' . a:what . '" in directory (default is ./): ')
|
||||
call inputrestore()
|
||||
|
||||
if !dir
|
||||
dir = './'
|
||||
endif
|
||||
|
||||
execute 'grep -r ' . a:what . ' ' . dir
|
||||
endfunction
|
||||
|
||||
" ask for input of number, and set indentation width accordingly
|
||||
" if input is '', setting defaults to
|
||||
" set tabstop=8 shiftwidth=8 noexpandtab
|
||||
" if input is 'n', settings are set as
|
||||
" set softtabstop=n shiftwidth=n expandtab
|
||||
function LogE_SetIndentWidth()
|
||||
call inputsave()
|
||||
let l:width = input('Set ident: ')
|
||||
call inputrestore()
|
||||
if l:width==''
|
||||
set tabstop=8 shiftwidth=8 noexpandtab
|
||||
else
|
||||
let l:numw = str2nr(l:width, 10)
|
||||
execute 'set softtabstop=' . l:numw . ' shiftwidth=' . l:numw . ' expandtab'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" terminal theme color adjustments
|
||||
function LogE_ColorAdjust_TomorrowDark()
|
||||
hi SpecialKey ctermfg=darkgrey
|
||||
hi ColorColumn ctermbg=darkgrey
|
||||
endfunction
|
||||
|
||||
function LogE_ColorAdjust_TomorrowLight()
|
||||
hi SpecialKey ctermfg=225
|
||||
hi ColorColumn ctermbg=225 " light pinkish
|
||||
endfunction
|
||||
|
||||
call LogE_ColorAdjust_TomorrowDark()
|
||||
|
||||
let g:ColorAdjustments = [
|
||||
\ ['tomorrowDark', function("LogE_ColorAdjust_TomorrowDark")],
|
||||
\ ['tomorrowLight', function("LogE_ColorAdjust_TomorrowLight")],
|
||||
\ ]
|
||||
|
||||
let g:CurrColorAdjust=g:ColorAdjustments[0][0]
|
||||
|
||||
function LogE_ColorAdjust_Rotate()
|
||||
let found=v:false
|
||||
for kv in g:ColorAdjustments
|
||||
if found
|
||||
let g:CurrColorAdjust=kv[0]
|
||||
call kv[1]()
|
||||
return
|
||||
endif
|
||||
|
||||
if kv[0] == g:CurrColorAdjust
|
||||
let found=v:true
|
||||
endif
|
||||
endfor
|
||||
|
||||
" NOTE: will only end up here if we need to wrap around the list of
|
||||
" color adjustments
|
||||
let wrap=g:ColorAdjustments[0]
|
||||
let g:CurrColorAdjust=wrap[0]
|
||||
call wrap[1]()
|
||||
return
|
||||
endfunction
|
||||
|
||||
" this is called from ftplugin scripts
|
||||
function LogE_LspDiagShowSignToggle()
|
||||
if g:lspOpts.showDiagWithSign
|
||||
let g:lspOpts.showDiagWithSign = v:false
|
||||
else
|
||||
let g:lspOpts.showDiagWithSign = v:true
|
||||
endif
|
||||
|
||||
call LspOptionsSet(g:lspOpts)
|
||||
endfunction
|
||||
|
||||
" ================= key mappings ================
|
||||
|
||||
" <leader> is , (comma)
|
||||
" <localleader> is \ (backslash)
|
||||
let mapleader=","
|
||||
let maplocalleader="\\"
|
||||
|
||||
" ----------- NORMAL MODE ------------------
|
||||
" NERDTree*
|
||||
noremap <leader>tn :NERDTreeToggle<CR>
|
||||
noremap <leader>fn :NERDTreeFocus<CR>
|
||||
noremap <leader>n :NERDTreeFocus<CR>
|
||||
|
||||
" rotate through color adjustments
|
||||
noremap <leader>ta :call LogE_ColorAdjust_Rotate()<CR>
|
||||
|
||||
" line numbers toggle
|
||||
noremap <F3> :call LogE_ToggleRelative()<CR>
|
||||
|
||||
" grep current word
|
||||
noremap <leader>gcw :call LogE_GrepAskForDir(expand("<cword>"))<CR>
|
||||
|
||||
" set indentation width
|
||||
noremap <leader>si :call LogE_SetIndentWidth()<CR>
|
||||
|
||||
" ------------- VISUAL MODE ---------------
|
||||
" Searching for visually selected text
|
||||
vnoremap // y/<C-R>"<CR>"
|
||||
|
||||
" ------------- INSERT MODE ---------------
|
||||
inoremap <F3> <F3>:call LogE_ToggleRelative()<CR>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
set softtabstop=8 shiftwidth=8 noexpandtab
|
|
@ -1 +0,0 @@
|
|||
set cinoptions=(4
|
14
ftplugin/c.vim
Normal file
14
ftplugin/c.vim
Normal file
|
@ -0,0 +1,14 @@
|
|||
map <leader>dd :LspDiagCurrent<CR>
|
||||
map <leader>dn :LspDiagNext<CR>
|
||||
map <leader>dp :LspDiagPrev<CR>
|
||||
|
||||
map <leader>er :LspRename<CR>
|
||||
|
||||
" toggle show diagnostic indicator next to line numbers
|
||||
map <leader>td :call LogE_LspDiagShowSignToggle()<CR>
|
||||
|
||||
" ctags file names
|
||||
set tags=tags;
|
||||
|
||||
|
||||
set colorcolumn=+0
|
10
ftplugin/cpp.vim
Normal file
10
ftplugin/cpp.vim
Normal file
|
@ -0,0 +1,10 @@
|
|||
set softtabstop=8 shiftwidth=8 noexpandtab
|
||||
|
||||
map <leader>dd :LspDiagCurrent<CR>
|
||||
map <leader>dn :LspDiagNext<CR>
|
||||
map <leader>dp :LspDiagPrev<CR>
|
||||
|
||||
map <leader>er :LspRename<CR>
|
||||
|
||||
" toggle show diagnostic indicator next to line numbers
|
||||
map <leader>td :call LogE_LspDiagShowSignToggle()<CR>
|
2
ftplugin/markdown.vim
Normal file
2
ftplugin/markdown.vim
Normal file
|
@ -0,0 +1,2 @@
|
|||
set colorcolumn=+1
|
||||
|
1
ftplugin/typescript.vim
Normal file
1
ftplugin/typescript.vim
Normal file
|
@ -0,0 +1 @@
|
|||
set softtabstop=2 shiftwidth=2 expandtab
|
8
indent/c.vim
Normal file
8
indent/c.vim
Normal file
|
@ -0,0 +1,8 @@
|
|||
set softtabstop=8 shiftwidth=8 noexpandtab
|
||||
|
||||
set cinoptions=(4,+4,m1,:0
|
||||
|
||||
" For cpp: E-s,
|
||||
|
||||
set fo=croqlj/
|
||||
set tw=80
|
6
indent/cpp.vim
Normal file
6
indent/cpp.vim
Normal file
|
@ -0,0 +1,6 @@
|
|||
set cinoptions=(4,:0
|
||||
|
||||
set fo=croqlj/
|
||||
set tw=80
|
||||
|
||||
set colorcolumn=+0
|
3
indent/markdown.vim
Normal file
3
indent/markdown.vim
Normal file
|
@ -0,0 +1,3 @@
|
|||
set tw=79
|
||||
|
||||
set tabstop=8 softtabstop=8 shiftwidth=8 noexpandtab
|
Loading…
Add table
Add a link
Reference in a new issue