درود!!
من مجبور شدم آرچ رو حذف کنم و دیبان نصب کنم در همین حین ادیتور مورد علاقه من یعنی زد روی دیبان پشتیبانی نمیشه:(
از طرفی codium هم سرور های LSP ش نصب نمیشد.
بخاطر همین به سوی او بازگشتم! بازگشت همه به سوی اوست! یعنی ویم!!!!
تنظیمات خیلی اصولی و دقیقی رو برای زبان های سی پلاس پلاس و پایتون نوشتم!!! اما بیشتر برای سی پلاس پلاس هست. توی این تنظیمات به یک نقطه خیلی توجه کردم؛ سرعت عمل و ابتکار. توی این فایل من پلاگین های زیادی رو نسبت به سری قبل نصب نکردم و زیاد به UI توجه آنچنانی نکردم ( برخلاف تنظیمات پیشین من ) هرچند که یک تم ساده و عالی برای کسانی که میخوان از چشم هاشون محافظت کنند انتخاب کردم و تمام.
قبل از هرچیز باید این بسته ها رو نصب کنید:
sudo apt install clangd
sudo apt install clang-format
sudo apt install nodejs
البته به بسته های دیگه ایی هم نیاز دارید برای پایتون اما خب فعلا برای من سی پلاس پلاس و سی واجب تر هست!
پلاگین های لازم برای ویم ( به vim-plug هم نیاز دارید ):
Plug 'arecarn/vim-fold-cycle'
Plug 'kshenoy/vim-signature'
Plug 'tpope/vim-sensible'
Plug 'vim-airline/vim-airline'
Plug 'dense-analysis/ale'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'dracula/vim'
Plug 'morhetz/gruvbox'
Plug 'preservim/nerdtree'
Plug 'raimondi/delimitmate'
Plug 'ap/vim-buftabline'
ما قراره ویم رو جوری تنظیم کنیم که سرعت عملمون از ۱۰ ه ۱۰۰۰۰۰۰ برسه باور کنید همچین چیزی شدنیه و من باور دارم که قراره بخاطر این تنظمات و شخصی سازی جایزه نوبل ویم رو تقدیم کنند! کم کم باید امسال یک تورینگ ببرم

خب ما قرار چیکار کنیم و به چه چیز هایی نیاز داریم؟ :
فولد و آن فولد کردن؛ مارک کردن ؛ باز کردن تب (به طور کلی همینه )
اول بزارید یکم هیجان زدتون کنم. فرض کنید توی یک فایل هستید که کم کم ۳۰۰ خط کد سی پلاس پلاس توشه و لازمه که هر دقیقه بین خط ۹۰ و ۲۰۰ جابجا بشید. میتونید دو کار بکنید ۱: شماره خط رو هر دقیقه تو ویم به این صورت بنویسید:200 یا میتونید یک کار عقلانی تر بکنید. از مارک کردن استفاده بکنید!!!!!!!
یا فرض کنید یک تابع نوشتید که ۶۰ خط و حجم زیادی رو اشغال میکنه شما اون رو به صورت خودکار نمیخواید فولد کنید پس دستی فولدش میکنید. میدونی چقدر سخته و زمان بر هست؟
برای تب هم که واضحه میخواید هم زمان روی چندتا فایل کار کنید و حرکت کنید.البته این یک خلاصه کوچیک بود.
پس بریم شروع کنیم:
let mapleader = " "
syntax on
set foldenable
set foldmethod=syntax
set foldlevelstart=99
set foldnestmax=3
set foldcolumn=1
set fillchars=fold:\
set number
set relativenumber
set mouse=a
set cursorline
set ttyfast
set lazyredraw
set updatetime=300
set clipboard=unnamedplus
set background=dark
set hidden
set ignorecase
set smartcase
set completeopt=menuone,noinsert,noselect
set timeoutlen=3000
filetype plugin indent on
set viewoptions=folds,cursor,slash,unix
set tabstop=8
set shiftwidth=8
set softtabstop=8
set noexpandtab
اول از همه باید باید باید مپ لیدر ما ( دکمه ایی که قراره خیلی زیاد ازش استفاده بشه ) برابر اسپیس باشه که یک سرعب و انعطاف نجومی به ما میده. بعدش باید ویم رو برای شناسایی سینتکس آماده کنیم و چندتا دستور دیگه برای فولد کردن اضافه میکنیم تا بهره وری رو به ۱۰۰ برسونیم ( اگر سوال داشتید که اینها چی هستند و چی کار میکنند بپرسید چون جا نمیشه همش رو توی یک فرسته بنویسم ) بعدش ویم رو برای نشون دادن شماره خط و پشتیبانی از موس آماده میکنیم ( برای تاچ پد هم میشه چون من از موس متنفرم ) بعدش کاری میکنیم که روی اون خطی که هستیم برجسته بشه و بک گراند رو تیره میکنیم برای تمی که قراره استفاده کنیم.
بعدش باید ویم رو برای افزایش سرعت بهینه کنیم بخاطر همین میگیم ttyfast هست و از ماکرو های غیر ضروری هم خود داری میکنیم. و زمان انتظار برای آپدیت تایم هم ۳۰۰ میلی ثانیه میزاریم و زمان برای انتظار هم ۳ ثانیه ( ۳۰۰۰ میلی ثانیه چون برای نرمال مود نیاز داریم).
بعدش کاری میکنیم که ویم بتونه از کلیپ بورد هم استفاده بکنه مثلا کنرل +سی و بعدش کاری میکنیم که فایل ها بدون ذخیره شدن تو بافر بمونه.
بعد کاری میکنیم موقعیت فولد ها و نشانگر و ... اینجور چیز های ذخیره بشوند.
بعدش یک سری تنظیمات برای حساسیت ویم برای نوشتن رو تنظیم میکنیم. که هم به حروف بزرگ و کوچیک حساس نباشه و هم اگر از حروف بزرگ استفاده کردیم حساس بشه ( خوراک نینجا های regex ) بعدش چندتا چیز دیگه برای نمایش پیشنهادات فعال میکنیم ( تقریبا ! )
این قسمتش خیلی مهمه. من به طور پیش فرض هر تب رو برابر ۸ تا فاصله قرار دارم اینکار باعث میشه که کدم خوانا تر باشه ( از نظر خودم ) و اینکه از تب واقعی استفاده میکنم!
خب حالا بریم بخش بعدی:
function! CloseTabByName()
let name = input("Enter tab path (partial, relative or full): ")
for i in range(tabpagenr('$'))
let bufnrs = tabpagebuflist(i + 1)
for b in bufnrs
let fullpath = fnamemodify(bufname(b), ':p:.')
if fullpath =~? name
execute (i + 1) . "tabclose"
echo "Closed tab containing: " . fullpath
return
endif
endfor
endfor
echo "No tab found matching: " . name
endfunction
nnoremap <silent> <leader>T :call CloseTabByName()<CR>
بی نظیره بی نظیره واقعا این تابع بی نظیره این تابع باعث میشه که اسم تبی که میخواید رو بنویسید و بعد ببندید خیلی راحت هم با space + T کار میکنه. هر چند که باید آدرس کامل و مطلق رو براش بنویسید.
nnoremap <silent> <leader>T :call CloseTabByName()<CR>
function! CloseCurrentTab()
if tabpagenr('$') > 1
tabclose
echo "Closed current tab"
else
echo "Cannot close the last tab page"
endif
endfunction
nnoremap <silent> <C-j> :call CloseCurrentTab()<CR>
خب حالا اگر نخواید یک ساعت آدرس به اون تابع ندید و میخواید مثل یک نینجا تب رو ببندید کافیه برید روی تب مورد نظر و crtl + j رو فشار بدید.
nnoremap <leader>m :marks<CR>
با این دستور لیست مارک هایی که دارید بالا میاد یعنی space + m چون بعضی وقت ها یادتون میره چندتا مارک دارید و هرکدوم کجا هستند.
let g:buftabline_numbers = 2
nnoremap <silent> <leader>l :tabnext<CR>
nnoremap <silent> <leader>h :tabprevious<CR>
دستور اول میزاره که میتونید تبتون رو چک کنید که از ۰ تا ۲ میتونید مقدار دهی کنید ( خودتون بزنید ببینید چی میشه )
ولی دستور دوم و سوم خیلی مهم با space + l به تب بعدی میرید و با space + h به تب قبلی ( خودم اشتباهی space + p میزنم شاید تغیرش دادم

)
autocmd BufWinLeave *.* mkview
autocmd BufWinEnter *.* silent! loadview
let g:fold_cycle_default_mapping = 0 "disable default mappings
خب اینجا هم یک سری تنظیمات عادیه ولی آخریش برای تنظیم فولد کردن که از تنظمات دیفالت عادی جلوگیری میکنه.
nnoremap <leader>u za
colorscheme gruvbox
این دو خط هم عالین خط اول میگه که با space + u یک تابع رو به صورت خودکار فولد و آن فولد کنی ( باید بری روی ابتدای کروشه اون تابع ) زیباست نه؟ خط بعدی هم تم مورد علاقه من هست که فوق العادست ( نمیدونم چرا وقتی اسمش رو میبینم یا میشنوم یا rust میفتم

)
augroup CppFormat
autocmd!
autocmd BufWritePre *.cpp,*.h,*.c call CppFormatPreserveCursor()
augroup END
این تابع هم برای فرمت کردن کد سی پلاس پلاس و سی هست
function! CppFormatPreserveCursor()
let l:save_cursor = getpos(".")
silent! %!clang-format
call setpos('.', l:save_cursor)
endfunction
این هم برای اینه که وقتی فرمت میکنی نشانگر به ابتدای فایل نپره (جا بجا نوشتم جای دو تابع )
autocmd VimEnter * if argc() == 0 | NERDTree | endif
nnoremap <leader>n :NERDTreeToggle<CR>
خط اول باعث میشه که وقتی دستور vim خالی رو اجرا کردید nerdtree باز بشه و لیست فایل ها نمایش داده بشوند ( آیکون اضافه نکردم چون بیخوده و فقط حجم اضافه میکنه ) با دستور space+ n باز و بستش میکنید
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <silent><expr> <CR> pumvisible() ? coc#_select_confirm() : "\<CR>"
این خطوط باعث میشن که وقتی کاکا ویم ( coc-nvim ) برای lsp پیشنهاد میده بتونید از تب و arrow key ها استفاده کنید.
let g:ale_linters = {
\ 'cpp': ['clangd'],
\ 'python': ['flake8'],
\}
let g:ale_fixers = {
\ 'cpp': ['clang-format'],
\ 'python': ['black'],
\}
این خطوط هم حتما فعال کنید برای دریافت هشدار ها و اصلاحات
function! s:SafeBlack()
let l:cmd = 'black --quiet ' . shellescape(expand('%:p'))
call system(l:cmd)
if v:shell_error == 0
silent! edit!
endif
endfunction
augroup PythonFormat
autocmd!
autocmd BufWritePre *.py call s:SafeBlack()
augroup END
فرمت پایتون
let g:airline_powerline_fonts = 1
"
let g:SignatureMarkTextHLDynamic = 1
let g:SignatureMarkText = '⚑'
let g:SignatureMarkerText = '✗'
let g:SignatureIncludeMarks = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
let g:SignaturePrioritizeMarks = 1
تنظیمات مارک کردن
let g:next_mark_idx = 0
let g:mark_list = []
function! s:NextDynamicMark()
let idx = g:next_mark_idx % 26
let letter = nr2char(char2nr('a') + idx)
execute "normal! m" . letter
if index(g:mark_list, letter) < 0
call add(g:mark_list, letter)
endif
let g:next_mark_idx += 1
echo ">> mark '" . letter . "' set"
endfunction
nnoremap <silent> ma :call <SID>NextDynamicMark()<CR>
بی نظیره! این تابع باعث میشه که شما بتونید به ترتیب حروف الفبا مارک کنید مثلا اگر روی یک خط هستید و space + ma زدید اولین مارکتون میشه a و به همین ترتیب تا آخر ادامه داره برای بقیه خط هااما اگر نمیخواید مشکلی نیست فقط space +m رو فشار بدید و یکم مکث کنید و حرف دلخواهتون رو بنویسید.
et g:mark_cycle_idx = 0
function! s:JumpNextMark()
if empty(g:mark_list)
echo ">> no marks set"
return
endif
let idx = g:mark_cycle_idx % len(g:mark_list)
let letter = g:mark_list[idx]
execute "normal! '" . letter
let g:mark_cycle_idx += 1
endfunction
nnoremap <silent> <leader>j :call <SID>JumpNextMark()<CR>
این تابع باعث میشه که به ترتیب حرف الفبا روی مارک ها حرکت کنید و سراغ مارک بعدی برید یعنی space + j
function! s:JumpToTypedMark()
let c = nr2char(getchar())
if c =~# '[a-z]'
execute "normal! '" . c
else
echohl ErrorMsg | echo ">> invalid mark: ".c | echohl None
endif
endfunction
nnoremap <silent> <leader>v :call <SID>JumpToTypedMark()<CR>
دوست نداری به ترتیب حروف الفبا روی مارک های حرکت کنی و دوست داری بری مستقیم سراغ مارکی که میخوای؟ ایرادی نداره space + v بعدش اسم مارکت رو بزن ؛) و بعد اینتر
function! DeleteMarkOnThisLine()
let marks = split(execute('marks'), "\n")[1:]
let currline = line('.')
for line in marks
let fields = split(line)
if len(fields) >= 2
let mark = fields[0]
let lnum = str2nr(fields[1])
if lnum == currline && mark =~# '^[a-zA-Z]$'
execute 'delmarks ' . mark
call remove(g:mark_list, index(g:mark_list, mark))
echo ">> Mark '" . mark . "' deleted from line " . lnum
return
endif
endif
endfor
echo ">> No mark found on this line"
endfunction
nnoremap <leader>d :call DeleteMarkOnThisLine()<CR>
این تابع باعث میشه وقتی روی یک مارک هستید با زدن space + d اون مارک به صورت خودکار حذف بشه!
عالی بود نه؟
فایل کامل:
let mapleader = " "
syntax on
set foldenable
set foldmethod=syntax
set foldlevelstart=99
set foldnestmax=3
set foldcolumn=1
set fillchars=fold:\
set number
set relativenumber
set mouse=a
set cursorline
set ttyfast
set lazyredraw
set updatetime=300
set clipboard=unnamedplus
set background=dark
set hidden
set ignorecase
set smartcase
set completeopt=menuone,noinsert,noselect
set timeoutlen=3000
filetype plugin indent on
set viewoptions=folds,cursor,slash,unix
set tabstop=8
set shiftwidth=8
set softtabstop=8
set noexpandtab
call plug#begin('~/.vim/plugged')
Plug 'arecarn/vim-fold-cycle'
Plug 'kshenoy/vim-signature'
Plug 'tpope/vim-sensible'
Plug 'vim-airline/vim-airline'
Plug 'dense-analysis/ale'
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'dracula/vim'
Plug 'morhetz/gruvbox'
Plug 'preservim/nerdtree'
Plug 'raimondi/delimitmate'
Plug 'ap/vim-buftabline'
call plug#end()
function! CloseTabByName()
let name = input("Enter tab path (partial, relative or full): ")
for i in range(tabpagenr('$'))
let bufnrs = tabpagebuflist(i + 1)
for b in bufnrs
let fullpath = fnamemodify(bufname(b), ':p:.')
if fullpath =~? name
execute (i + 1) . "tabclose"
echo "Closed tab containing: " . fullpath
return
endif
endfor
endfor
echo "No tab found matching: " . name
endfunction
nnoremap <silent> <leader>T :call CloseTabByName()<CR>
function! CloseCurrentTab()
if tabpagenr('$') > 1
tabclose
echo "Closed current tab"
else
echo "Cannot close the last tab page"
endif
endfunction
nnoremap <silent> <C-j> :call CloseCurrentTab()<CR>
nnoremap <leader>m :marks<CR>
let g:buftabline_numbers = 2
nnoremap <silent> <leader>l :tabnext<CR>
nnoremap <silent> <leader>h :tabprevious<CR>
autocmd BufWinLeave *.* mkview
autocmd BufWinEnter *.* silent! loadview
let g:fold_cycle_default_mapping = 0 "disable default mappings
nnoremap <leader>u za
colorscheme gruvbox
function! CppFormatPreserveCursor()
let l:save_cursor = getpos(".")
silent! %!clang-format
call setpos('.', l:save_cursor)
endfunction
augroup CppFormat
autocmd!
autocmd BufWritePre *.cpp,*.h,*.c call CppFormatPreserveCursor()
augroup END
autocmd VimEnter * if argc() == 0 | NERDTree | endif
nnoremap <leader>n :NERDTreeToggle<CR>
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
inoremap <silent><expr> <CR> pumvisible() ? coc#_select_confirm() : "\<CR>"
let g:ale_linters = {
\ 'cpp': ['clangd'],
\ 'python': ['flake8'],
\}
let g:ale_fixers = {
\ 'cpp': ['clang-format'],
\ 'python': ['black'],
\}
function! s:SafeBlack()
let l:cmd = 'black --quiet ' . shellescape(expand('%:p'))
call system(l:cmd)
if v:shell_error == 0
silent! edit!
endif
endfunction
augroup PythonFormat
autocmd!
autocmd BufWritePre *.py call s:SafeBlack()
augroup END
let g:airline_powerline_fonts = 1
"
let g:SignatureMarkTextHLDynamic = 1
let g:SignatureMarkText = '⚑'
let g:SignatureMarkerText = '✗'
let g:SignatureIncludeMarks = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
let g:SignaturePrioritizeMarks = 1
"
"
let g:next_mark_idx = 0
let g:mark_list = []
function! s:NextDynamicMark()
let idx = g:next_mark_idx % 26
let letter = nr2char(char2nr('a') + idx)
execute "normal! m" . letter
if index(g:mark_list, letter) < 0
call add(g:mark_list, letter)
endif
let g:next_mark_idx += 1
echo ">> mark '" . letter . "' set"
endfunction
nnoremap <silent> ma :call <SID>NextDynamicMark()<CR>
let g:mark_cycle_idx = 0
function! s:JumpNextMark()
if empty(g:mark_list)
echo ">> no marks set"
return
endif
let idx = g:mark_cycle_idx % len(g:mark_list)
let letter = g:mark_list[idx]
execute "normal! '" . letter
let g:mark_cycle_idx += 1
endfunction
nnoremap <silent> <leader>j :call <SID>JumpNextMark()<CR>
function! s:JumpToTypedMark()
let c = nr2char(getchar())
if c =~# '[a-z]'
execute "normal! '" . c
else
echohl ErrorMsg | echo ">> invalid mark: ".c | echohl None
endif
endfunction
nnoremap <silent> <leader>v :call <SID>JumpToTypedMark()<CR>
function! DeleteMarkOnThisLine()
let marks = split(execute('marks'), "\n")[1:]
let currline = line('.')
for line in marks
let fields = split(line)
if len(fields) >= 2
let mark = fields[0]
let lnum = str2nr(fields[1])
if lnum == currline && mark =~# '^[a-zA-Z]$'
execute 'delmarks ' . mark
call remove(g:mark_list, index(g:mark_list, mark))
echo ">> Mark '" . mark . "' deleted from line " . lnum
return
endif
endif
endfor
echo ">> No mark found on this line"
endfunction
nnoremap <leader>d :call DeleteMarkOnThisLine()<CR>
تنظیمات کاکا ویم رو در فرسته بعدی میفرستم اما قبلش باید black رو برای پایتون نصب کنید.
هر سوالی داشتید در خدمتم!