vim9script set encoding=utf-8 scriptencoding utf-8 # ---------------------------------------------------------- # 基本設定 {{{ set fileencodings=ucs-bom,utf-8,iso-2022-jp,cp932,euc-jp set noexpandtab set tabstop=3 # 意外とありな気がしてきた… set shiftwidth=0 set softtabstop=0 set autoindent set smartindent set breakindent set backspace=indent,start,eol set nf=alpha,hex set virtualedit=block set list set listchars=tab:\|\ ,trail:-,extends:>,precedes:<,nbsp:% set fillchars= set cmdheight=0 set laststatus=2 set noruler set noshowcmd set noshowmode set display=lastline set ambiwidth=double set belloff=all set ttimeoutlen=50 set wildmenu set autochdir set backupskip=/var/tmp/* set undodir=~/.vim/undo set undofile set updatetime=2000 set incsearch set hlsearch nohlsearch augroup vimrc # 新しい自由 au! augroup End #}}} ------------------------------------------------------- # ---------------------------------------------------------- # ユーティリティ {{{ const rtproot = has('win32') ? '~/vimfiles' : '~/.vim' const has_deno = executable('deno') # こんな感じ # MultiCmd nmap,vmap xxx yyyNNNVVV<>zzz # ↓ # nmap xxx yyyNNNzzz | vmap xxx yyyVVVzzz def MultiCmd(qargs: string) const [cmds, args] = qargs->split('^\S*\zs') for cmd in cmds->split(',') const a = args ->substitute('', '<>', 'g') ->substitute('\|$\)', '', 'g') ->substitute('<>', '', 'g') execute cmd a endfor enddef command! -nargs=* MultiCmd MultiCmd() # その他 command! -nargs=1 -complete=var Enable = 1 command! -nargs=1 -complete=var Disable = 0 def RemoveEmptyLine(line: number) silent! execute ':' line 's/\s\+$//' silent! execute ':' line 's/^\s*\n//' enddef def BufIsSmth(): bool return &modified || ! empty(bufname()) enddef def IndentStr(expr: any): string return matchstr(getline(expr), '^\s*') enddef # 指定幅以上なら'>'で省略する def TruncToDisplayWidth(str: string, width: number): string return strdisplaywidth(str) <= width ? str : str->matchstr(printf('.*\%%<%dv', width + 1)) .. '>' enddef #}}} ------------------------------------------------------- # ---------------------------------------------------------- # プラグイン {{{ # jetpack {{{ const jetpackfile = expand(rtproot .. '/pack/jetpack/opt/vim-jetpack/plugin/jetpack.vim') const has_jetpack = filereadable(jetpackfile) if ! has_jetpack const jetpackurl = 'https://raw.githubusercontent.com/tani/vim-jetpack/master/plugin/jetpack.vim' system(printf('curl -fsSLo %s --create-dirs %s', jetpackfile, jetpackurl)) endif packadd vim-jetpack jetpack#begin() Jetpack 'tani/vim-jetpack', { 'opt': 1 } Jetpack 'airblade/vim-gitgutter' Jetpack 'alvan/vim-closetag' Jetpack 'ctrlpvim/ctrlp.vim' Jetpack 'cohama/lexima.vim' # 括弧補完 Jetpack 'delphinus/vim-auto-cursorline' Jetpack 'dense-analysis/ale' Jetpack 'easymotion/vim-easymotion' Jetpack 'hrsh7th/vim-vsnip' Jetpack 'hrsh7th/vim-vsnip-integ' Jetpack 'itchyny/lightline.vim' Jetpack 'kana/vim-textobj-user' Jetpack 'LeafCage/vimhelpgenerator' Jetpack 'luochen1990/rainbow' # 虹色括弧 Jetpack 'machakann/vim-sandwich' Jetpack 'mattn/ctrlp-matchfuzzy' Jetpack 'mattn/vim-notification' Jetpack 'matze/vim-move' # 行移動 Jetpack 'mechatroner/rainbow_csv' Jetpack 'michaeljsmith/vim-indent-object' Jetpack 'osyo-manga/vim-textobj-multiblock' Jetpack 'othree/html5.vim' Jetpack 'othree/yajs.vim' Jetpack 'prabirshrestha/asyncomplete-buffer.vim' Jetpack 'prabirshrestha/asyncomplete.vim' Jetpack 'rafamadriz/friendly-snippets' Jetpack 'thinca/vim-portal' Jetpack 'tpope/vim-fugitive' # Gdiffとか Jetpack 'tyru/caw.vim' # コメント化 Jetpack 'yami-beta/asyncomplete-omni.vim' Jetpack 'yegappan/mru' Jetpack 'vim-jp/vital.vim' Jetpack 'utubo/jumpcuorsor.vim' # vimに対応させたやつ(様子見)vim-jetpackだとインストール出来ないかも? Jetpack 'utubo/vim-auto-hide-cmdline' Jetpack 'utubo/vim-colorscheme-girly' Jetpack 'utubo/vim-minviml' Jetpack 'utubo/vim-portal-aim' Jetpack 'utubo/vim-registers-lite' Jetpack 'utubo/vim-reformatdate' Jetpack 'utubo/vim-tabtoslash' # あまり使ってないけど作ったので… Jetpack 'utubo/vim-shrink' Jetpack 'utubo/vim-tablist' Jetpack 'utubo/vim-tabpopupmenu' Jetpack 'utubo/vim-textobj-twochars' if has_deno Jetpack 'vim-denops/denops.vim' Jetpack 'vim-skk/skkeleton' endif jetpack#end() if ! has_jetpack jetpack#sync() endif #}}} # easymotion {{{ Enable g:EasyMotion_smartcase Enable g:EasyMotion_use_migemo Enable g:EasyMotion_enter_jump_first Disable g:EasyMotion_do_mapping g:EasyMotion_keys = 'asdghklqwertyuiopzxcvbnmfjASDGHKLQWERTYUIOPZXCVBNMFJ;' map s (ahc)(easymotion-s) #}}} # sandwich {{{ g:sandwich#recipes = deepcopy(g:sandwich#default_recipes) g:sandwich#recipes += [ { buns: ["\r", '' ], input: ["\r"], command: ["normal! a\r"] }, { buns: ['', '' ], input: ['q'] }, { buns: ['「', '」'], input: ['k'] }, { buns: ['{ ', ' }'], input: ['{'] }, { buns: ['${', '}' ], input: ['${'] }, { buns: ['%{', '}' ], input: ['%{'] }, { buns: ['CommentString(0)', 'CommentString(1)'], expr: 1, input: ['c'] }, ] def! g:CommentString(index: number): string return &commentstring->split('%s')->get(index, '') enddef Enable g:sandwich_no_default_key_mappings Enable g:operator_sandwich_no_default_key_mappings MultiCmd nmap,vmap Sd (operator-sandwich-delete)ab MultiCmd nmap,vmap Sr (operator-sandwich-replace)ab MultiCmd nmap,vmap Sa (operator-sandwich-add)iw MultiCmd nmap,vmap S (operator-sandwich-add)iw nmap S^ v^S nmap S$ vg_S nmap SS (matchstr(getline('.'), '[''"]', col('.')) ==# '"') ? 'Sr''' : 'Sr"' # 改行で挟んだあとタブでインデントされると具合が悪くなるので… def FixSandwichPos() var c = g:operator#sandwich#object.cursor if g:fix_sandwich_pos[1] !=# c.inner_head[1] c.inner_head[2] = getline(c.inner_head[1])->match('\S') + 1 c.inner_tail[2] = getline(c.inner_tail[1])->match('$') + 1 endif enddef au vimrc User OperatorSandwichAddPre g:fix_sandwich_pos = getpos('.') au vimrc User OperatorSandwichAddPost FixSandwichPos() # 内側に連続で挟むやつ var big_mac_crown = [] def BigMac(first: bool = true) const c = g:operator#sandwich#object.cursor.inner_head[1 : 2] if first || big_mac_crown !=# c big_mac_crown = c au vimrc User OperatorSandwichAddPost ++once BigMac(false) if first feedkeys('Sa') else setpos("'<", g:operator#sandwich#object.cursor.inner_head) setpos("'>", g:operator#sandwich#object.cursor.inner_tail) feedkeys('gvSa') endif endif enddef nmap Sm viwSm vmap Sm call BigMac() # 囲みを削除したら行末空白と空行も削除 def RemoveAirBuns() const c = g:operator#sandwich#object.cursor RemoveEmptyLine(c.tail[1]) RemoveEmptyLine(c.head[1]) enddef au vimrc User OperatorSandwichDeletePost RemoveAirBuns() #}}} # MRU {{{ # デフォルト設定(括弧内にフルパス)だとパスに括弧が含まれているファイルが開けないので、パスに使用されない">"を区切りにする g:MRU_Filename_Format = { formatter: 'fnamemodify(v:val, ":t") . " > " . v:val', parser: '> \zs.*', syntax: '^.\{-}\ze >' } # 数字キーで開く def MRUwithNumKey(use_tab: bool) b:use_tab = use_tab setlocal number redraw if &cmdheight !=# 0 echoh Question echo printf('[1]..[9] => open with a %s.', use_tab ? 'tab' : 'window') echoh None endif const key = use_tab ? 't' : '' for i in range(1, 9) execute printf('nmap %d :%d%s', i, i, key) endfor enddef def MyMRU() Enable b:auto_cursorline_disabled setlocal cursorline nnoremap w call MRUwithNumKey(!b:use_tab) nnoremap R MruRefreshnormal! u nnoremap q! MRUwithNumKey(BufIsSmth()) enddef au vimrc FileType mru MyMRU() au vimrc ColorScheme * hi link MruFileName Directory nnoremap MRUToggle g:MRU_Exclude_Files = has('win32') ? $TEMP .. '\\.*' : '^/tmp/.*\|^/var/tmp/.*' #}}} # 補完 {{{ def RegisterAsyncompSource(name: string, white: list, black: list) execute printf("asyncomplete#register_source(asyncomplete#sources#%s#get_source_options({ name: '%s', whitelist: %s, blacklist: %s, completor: asyncomplete#sources#%s#completor }))", name, name, white, black, name) enddef RegisterAsyncompSource('omni', ['*'], ['c', 'cpp', 'html']) RegisterAsyncompSource('buffer', ['*'], ['go']) MultiCmd imap,smap JJ vsnip#expandable() ? '(vsnip-expand)' : 'JJ' MultiCmd imap,smap vsnip#available(1) ? '(vsnip-expand-or-jump)' : '' MultiCmd imap,smap vsnip#jumpable(1) ? '(vsnip-jump-next)' : pumvisible() ? '' : '' MultiCmd imap,smap vsnip#jumpable(-1) ? '(vsnip-jump-prev)' : pumvisible() ? '' : '' #imap pumvisible() ? '' : '' Enable g:lexima_accept_pum_with_enter #}}} # ALE {{{ Enable g:ale_set_quickfix Enable g:ale_fix_on_save Disable g:ale_lint_on_insert_leave Disable g:ale_set_loclist g:ale_sign_error = '🐞' g:ale_sign_warning = '🐝' g:ale_fixers = { typescript: ['deno'] } g:ale_lint_delay = &updatetime nmap [a (ale_previous_wrap) nmap ]a (ale_next_wrap) # cmdheight=0だとALEのホバーメッセージがちらつくのでg:ll_aleに代入してlightlineで表示する Disable g:ale_echo_cursor g:ll_are = '' def ALEEchoCursorCmdHeight0() var loc = ale#util#FindItemAtCursor(bufnr())[1] if !empty(loc) g:ll_ale = loc.type ==# 'E' ? '🐞' : '🐝' g:ll_ale ..= ' ' g:ll_ale ..= get(loc, 'detail', loc.text)->split('\n')[0] ->substitute('^\[[^]]*\] ', '', '') else g:ll_ale = '' endif enddef au vimrc CursorMoved * ALEEchoCursorCmdHeight0() #}}} # lightline {{{ # ヤンクしたやつを表示するやつ g:ll_reg = '' def LLYankPost() var reg = v:event.regcontents ->join('\n') ->substitute('\t', '›', 'g') ->TruncToDisplayWidth(20) g:ll_reg = '📋:' .. reg enddef au vimrc TextYankPost * LLYankPost() # 毎時45分から15分間休憩しようね g:ll_tea_break = '0:00' g:ll_tea_break_opentime = localtime() def! g:VimrcTimer60s(timer: any) const tick = (localtime() - g:ll_tea_break_opentime) / 60 const mm = tick % 60 const tea = mm >= 45 ? '☕🍴🍰' : '' g:ll_tea_break = tea .. printf('%d:%02d', tick / 60, mm) lightline#update() if (mm ==# 45) notification#show(" ☕🍴🍰\nHave a break time !") endif enddef timer_stop(get(g:, 'vimrc_timer_60s', 0)) g:vimrc_timer_60s = timer_start(60000, 'VimrcTimer60s', { repeat: -1 }) # &ff if has('win32') def! g:LLFF(): string return &ff !=# 'dos' ? &ff : '' enddef else def! g:LLFF(): string return &ff ==# 'dos' ? &ff : '' enddef endif # &fenc def! g:LLNotUtf8(): string return &fenc ==# 'utf-8' ? '' : &fenc enddef # lightline設定 g:lightline = { colorscheme: 'wombat', active: { left: [['mode', 'paste'], ['fugitive', 'filename'], ['ale']], right: [['teabreak'], ['ff', 'notutf8', 'li'], ['reg']] }, component: { teabreak: '%{g:ll_tea_break}', reg: '%{g:ll_reg}', ale: '%=%{g:ll_ale}', li: '%2c,%l/%L' }, component_function: { ff: 'LLFF', notutf8: 'LLNotUtf8' }, } # tablineはデフォルト au vimrc VimEnter * set tabline= #}}} # skk {{{ if has_deno if ! empty($SKK_JISYO_DIR) skkeleton#config({ globalJisyo: expand($SKK_JISYO_DIR .. 'SKK-JISYO.L'), userJisyo: expand($SKK_JISYO_DIR .. '.skkeleton'), }) endif skkeleton#config({ eggLikeNewline: true, keepState: true, showCandidatesCount: 1, }) map! (skkeleton-toggle) endif #}}} # textobj-multiblock {{{ MultiCmd omap,xmap ab (textobj-multiblock-a) MultiCmd omap,xmap ib (textobj-multiblock-i) g:textobj_multiblock_blocks = [ \ [ "(", ")" ], \ [ "[", "]" ], \ [ "{", "}" ], \ [ '<', '>' ], \ [ '"', '"', 1 ], \ [ "'", "'", 1 ], \ [ ">", "<", 1 ], \ [ "「", "」", 1 ], ] #}}} # Portal {{{ nnoremap a PortalAim nnoremap b PortalAim blue nnoremap o PortalAim orange nnoremap r PortalReset #}}} # ヘルプ作成 {{{ g:vimhelpgenerator_version = '' g:vimhelpgenerator_author = 'Author : utubo' g:vimhelpgenerator_defaultlanguage = 'en' #}}} # cmdline statusline 切り替え {{{ Enable g:auto_hide_cmdline_switch_statusline # statusline非表示→cmdline表示の順にしないとちらつくので応急処置… # 本筋はCmdlineEnterPreを作るかupdate_screen(VALID)をCmdlineEnter発行の後にするしかない? # ソース # https://github.com/vim/vim/blob/master/src/ex_getln.c # static char_u * getcmdline_int() # 前者 # `trigger_cmd_autocmd(firstc == -1 || firstc == NUL ? '-' : firstc, EVENT_CMDLINEENTERPRE)` # を`if (cmdheight0)`の手前で実行する? # `firstc == -1`のくだりは後の行から移動してきてもいいかもしれない # ドキュメント修正も必要 # でもautocmdの中で`cmdheight`を変更されたらどうするの? # 後者 # 理由があって今のタイミングでupdate_screenしているのだから移動できるわけがない… MultiCmd nnoremap,vnoremap : (ahc-switch): MultiCmd nnoremap,vnoremap / (ahc-switch)noh/ MultiCmd nnoremap,vnoremap ? (ahc-switch)noh? MultiCmd nmap,vmap ; : nnoremap ; ; nnoremap : : # 自作プラグイン(vim-registerslite)と被ってしまった… # inoremap = (ahc-switch)= #}}} # その他 {{{ Enable g:rainbow_active g:auto_cursorline_wait_ms = &updatetime g:ctrlp_match_func = {'match': 'ctrlp_matchfuzzy#matcher'} g:ctrlp_cmd = 'CtrlPMixed' nmap [c (ahc)(GitGutterPrevHunk) nmap ]c (ahc)(GitGutterNextHunk) nmap ga :Git add % nmap gc :Git commit -m '' nmap gp :Git push nnoremap gv Gvdiffsplit nnoremap gd Gdiffsplit nnoremap gl Git pull nnoremap t call tabpopupmenu#popup() nnoremap T call tablist#Show() MultiCmd nmap,vmap c (caw:hatpos:toggle) MultiCmd nmap,tmap (shrink-height)w MultiCmd nmap,tmap (shrink-width)w # EasyMotionとどっちを使うか様子見中 noremap s (jumpcursor-jump) #}}} # 開発用 {{{ const localplugins = expand(rtproot .. '/pack/local/opt/*') if localplugins !=# '' &runtimepath = substitute(localplugins, '\n', ',', 'g') .. ',' .. &runtimepath endif #}}} filetype plugin indent on #}}} ------------------------------------------------------- # ---------------------------------------------------------- # コピペ寄せ集め色々 {{{ au vimrc InsertLeave * set nopaste au vimrc BufReadPost *.log* normal! G vnoremap * "vy/\Vsubstitute(escape(@v,'\/'),"\n",'\\n','g') inoremap kj `^ inoremap kk `^ inoremap u # https://github.com/astrorobot110/myvimrc/blob/master/vimrc set matchpairs+=(:),「:」,『:』,【:】,[:],<:> # https://github.com/Omochice/dotfiles nnoremap i len(getline('.')) !=# 0 ? 'i' : '"_cc' nnoremap a len(getline('.')) !=# 0 ? 'a' : '"_cc' nnoremap A len(getline('.')) !=# 0 ? 'A' : '"_cc' #}}} ------------------------------------------------------- # ---------------------------------------------------------- # タブ幅やタブ展開を自動設定 {{{ def SetupTabstop() const limit = 100 const org = getpos('.') cursor(1, 1) if !!search('^\t', 'nc', limit) setlocal noexpandtab setlocal tabstop=3 # 意外とありな気がしてきた… elseif !!search('^ \S', 'nc', limit) setlocal expandtab setlocal tabstop=2 elseif !!search('^ \S', 'nc', limit) setlocal expandtab setlocal tabstop=4 endif setpos('.', org) enddef au vimrc BufReadPost * SetupTabstop() #}}} ------------------------------------------------------- # ---------------------------------------------------------- # vimgrep {{{ def VimGrep(keyword: string, ...targets: list) var path = join(targets, ' ') # パスを省略した場合は、同じ拡張子のファイルから探す if empty(path) path = expand('%:e') ==# '' ? '*' : ('*.' .. expand('%:e')) endif # 適宜タブで開く(ただし明示的に「%」を指定したらカレントで開く) const use_tab = BufIsSmth() && path !=# '%' if use_tab tabnew endif # lvimgrepしてなんやかんやして終わり execute printf('silent! lvimgrep %s %s', keyword, path) if ! empty(getloclist(0)) lwindow else echoh ErrorMsg echomsg 'Not found.: ' .. keyword echoh None if use_tab tabnext - tabclose + endif endif enddef command! -nargs=+ VimGrep VimGrep() nmap / :VimGrep def SetupQF() nnoremap ; :silent! normal! zvw nnoremap w :silent! normal! zvw nnoremap t :silent! normal! zvT nnoremap q lexpr '':q nnoremap f nnoremap b # 様子見中(使わなそうなら削除する) execute printf('nnoremap T T%dgt', tabpagenr()) enddef au vimrc FileType qf SetupQF() au vimrc WinEnter * if winnr('$') ==# 1 && &buftype ==# 'quickfix' | q | endif #}}} ------------------------------------------------------- # ---------------------------------------------------------- # diff {{{ set splitright set fillchars+=diff:\ # 削除行は空白文字で埋める # diffモードを自動でoff https://hail2u.net/blog/software/vim-turn-off-diff-mode-automatically.html au vimrc WinEnter * if (winnr('$') ==# 1) && !!getbufvar(winbufnr(0), '&diff') | diffoff | endif #}}} ------------------------------------------------------- # ---------------------------------------------------------- # 日付関係 {{{ g:reformatdate_extend_names = [{ a: ['日', '月', '火', '水', '木', '金', '土'], A: ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'], }] inoremap strftime('%Y/%m/%d') cnoremap strftime('%Y%m%d') nnoremap call reformatdate#reformat(localtime()) nnoremap call reformatdate#inc(v:count) nnoremap call reformatdate#dec(v:count) nnoremap /\d\{4\}\/\d\d\/\d\d #}}} ------------------------------------------------------- # ---------------------------------------------------------- # スマホ用 {{{ # - キーが小さいので押しにくいものはSpaceへマッピング # - スマホでのコーディングは基本的にバグ取り nnoremap zz q! # スタックトレースからyankしてソースの該当箇所を探すのを補助 nnoremap e G?\cErr\\|Exception nnoremap y yiw nnoremap f (getreg('"') =~ '^\d\+$' ? ':' : '/') .. getreg('"') .. '' # スマホだと:と/とファンクションキーが遠いので… nmap . : nmap , / for i in range(1, 10) execute printf('nmap %d ', i % 10, i) endfor nmap 1 nmap 2 #}}} ------------------------------------------------------- # ---------------------------------------------------------- # カーソルを行頭に沿わせて移動 {{{ def PutHat(): string const x = getline('.')->match('\S') + 1 if x !=# 0 || !exists('w:my_hat') w:my_hat = col('.') ==# x ? '^' : '' endif return w:my_hat enddef nnoremap j 'j' .. PutHat() nnoremap k 'k' .. PutHat() #}}} ------------------------------------------------------- # ---------------------------------------------------------- # 折り畳み {{{ # こんなかんじでインデントに合わせて表示📁 {{{ def! g:MyFoldText(): string const src = getline(v:foldstart) const indent = repeat(' ', indent(v:foldstart)) const text = &foldmethod ==# 'indent' ? '' : src->substitute(matchstr(&foldmarker, '^[^,]*'), '', '')->trim() return indent .. text .. '📁' enddef set foldtext=g:MyFoldText() set fillchars+=fold:\ # 折り畳み時の「-」は半角空白 au vimrc ColorScheme * hi! link Folded Delimiter #}}} # ホールドマーカーの前にスペース、後ろに改行を入れる {{{ def Zf() const firstline = min([line('.'), line('v')]) const lastline = max([line('.'), line('v')]) execute ':' firstline 's/\v(\S)?$/\1 /' append(lastline, IndentStr(firstline)) cursor([firstline, 1]) cursor([lastline + 1, 1]) normal! zf enddef vnoremap zf call Zf() #}}} # ホールドマーカーを削除したら行末をトリムする {{{ def Zd() if foldclosed(line('.')) ==# -1 normal! zc endif const head = foldclosed(line('.')) const tail = foldclosedend(line('.')) if head ==# -1 return endif const org = getpos('.') normal! zd RemoveEmptyLine(tail) RemoveEmptyLine(head) setpos('.', org) enddef nnoremap zd call Zd() #}}} # その他折りたたみ関係 {{{ set foldmethod=marker au vimrc FileType markdown,yaml setlocal foldlevelstart=99 | setlocal foldmethod=indent au vimrc BufReadPost * :silent! normal! zO nnoremap h (col('.') ==# 1 && 0 < foldlevel('.') ? 'zc' : 'h') nnoremap Z set foldmethod=indent nnoremap Z{ set foldmethod=marker nnoremap Zy set foldmethod=syntax #}}} #}}} ------------------------------------------------------- # ---------------------------------------------------------- # ビジュアルモードあれこれ {{{ def KeepingCurPos(expr: string) const cur = getcurpos() execute expr setpos('.', cur) enddef vnoremap u call KeepingCurPos('undo') vnoremap call KeepingCurPos('redo') vnoremap normal! >gv vnoremap normal! #}}} # ---------------------------------------------------------- # コマンドモードあれこれ {{{ cnoremap cnoremap cnoremap trim(@") cnoremap escape(@", '~^$.*?/\[]') cnoreabbrev cs colorscheme # 「jj」で、「kk」はキャンセル # ただし保存は片手で「;jj」でもOK(「;wjj」じゃなくていい) cnoremap kk cnoremap jj (empty(getcmdline()) && getcmdtype() ==# ':' ? 'update' : '') inoremap ;jj `^update #}}} ------------------------------------------------------- # ---------------------------------------------------------- # terminalとか {{{ if has('win32') command! Powershell :bo terminal ++close pwsh nnoremap SH Powershell nnoremap silent !start explorer %:p:h else nnoremap SH bo terminal endif tnoremap ; : tnoremap w tnoremap exit #}}} ------------------------------------------------------- # ---------------------------------------------------------- # markdownのチェックボックス {{{ def ToggleCheckBox() const a = getline('.') var b = substitute(a, '^\(\s*\)- \[ \]', '\1- [x]', '') # check on if a ==# b b = substitute(a, '^\(\s*\)- \[x\]', '\1- [ ]', '') # check off endif if a ==# b b = substitute(a, '^\(\s*\)\(- \)*', '\1- [ ] ', '') # a new check box endif setline('.', b) var c = getpos('.') c[2] += len(b) - len(a) setpos('.', c) enddef noremap x call ToggleCheckBox() #}}} ------------------------------------------------------- # ---------------------------------------------------------- # バッファの情報を色付きで表示 {{{ def ShowBufInfo(event: string = '') if &ft ==# 'qf' return endif var isReadPost = event ==# 'BufReadPost' if isReadPost && ! filereadable(expand('%')) # プラグインとかが一時的なbufnameを付与して開いた場合は無視する return endif var msg = [] add(msg, ['Title', '"' .. bufname() .. '"']) add(msg, ['Normal', ' ']) if &modified add(msg, ['Delimiter', '[+]']) add(msg, ['Normal', ' ']) endif if !isReadPost add(msg, ['Tag', '[New]']) add(msg, ['Normal', ' ']) endif if &readonly add(msg, ['WarningMsg', '[RO]']) add(msg, ['Normal', ' ']) endif const w = wordcount() if isReadPost || w.bytes !=# 0 add(msg, ['Constant', printf('%dL, %dB', w.bytes ==# 0 ? 0 : line('$'), w.bytes)]) add(msg, ['Normal', ' ']) endif add(msg, ['MoreMsg', printf('%s %s %s', &ff, (empty(&fenc) ? &encoding : &fenc), &ft)]) var msglen = 0 const maxlen = &columns - 2 for i in reverse(range(0, len(msg) - 1)) var s = msg[i][1] var d = strdisplaywidth(s) msglen += d if maxlen < msglen const l = maxlen - msglen + d while !empty(s) && l < strdisplaywidth(s) s = s[1 :] endwhile msg[i][1] = s msg = msg[i : ] insert(msg, ['NonText', '<'], 0) break endif endfor redraw echo '' for m in msg execute 'echohl' m[0] echon m[1] endfor echohl Normal enddef noremap (ahc)call ShowBufInfo() # cmdheight=0にしたら無用になった # au vimrc BufNewFile * ShowBufInfo('BufNewFile') # au vimrc BufReadPost * ShowBufInfo('BufReadPost') #}}} ------------------------------------------------------- # ---------------------------------------------------------- # 閉じる {{{ def Quit(expr: string = '') if ! empty(expr) if winnr() ==# winnr(expr) return endif execute 'wincmd' expr endif if mode() ==# 't' quit! else confirm quit endif enddef nnoremap q nnoremap Q q nnoremap qh call Quit('h') nnoremap qj call Quit('j') nnoremap qk call Quit('k') nnoremap ql call Quit('l') nnoremap qq call Quit() nnoremap q: q: nnoremap q/ q/ nnoremap q? q? #}}} ------------------------------------------------------- # ---------------------------------------------------------- # ファイルを移動して保存 {{{ def MoveFile(newname: string) const oldpath = expand('%') const newpath = expand(newname) if ! empty(oldpath) && filereadable(oldpath) if filereadable(newpath) echoh Error echo 'file "' .. newname .. '" already exists.' echoh None return endif rename(oldpath, newpath) endif execute 'saveas!' newpath # 開き直してMRUに登録 edit enddef command! -nargs=1 -complete=file MoveFile call MoveFile() cnoreabbrev mv MoveFile #}}} # ---------------------------------------------------------- # vimrc作成用 {{{ # カーソル行を実行するやつ cnoremap (exec_line) getline('.')->substitute('^[ \t"#:]\+', '', '') .. '' nmap g: (ahc):(exec_line) nmap g9 (ahc):vim9cmd (exec_line) vmap g: "vy(ahc):=@v vmap g9 "vy(ahc):vim9cmd =@v # カーソル位置のハイライトを確認するやつ nnoremap gh 'hi ' .. synID(line('.'), col('.'), 1)->synIDattr('name')->substitute('^$', 'Normal', '') .. '' #}}} # ---------------------------------------------------------- # その他細々したの {{{ if has('clipboard') au vimrc FocusGained * @" = @+ au vimrc FocusLost * @+ = @" endif nnoremap set number! nnoremap set wrap! cnoremap (rpl) 's///g \| noh' .. repeat('', 9) nmap gs :%(rpl) nmap gS :%(rpl)call feedkeys(expand('')->escape('^$.*?/\[]'), 'ni') vmap gs :(rpl) nnoremap Y y$ nnoremap p $p nnoremap P ^P nnoremap p oP nnoremap P Op # 分割キーボードで右手親指がになったので nmap # `T`多少潰しても大丈夫だろう… nmap TE :tabe nnoremap TN tabnew nnoremap TD tabe ./ nnoremap TT silent! tabnext # onoremap } 'm`0' .. v:count1 .. v:operator .. '}' onoremap { 'm`V' .. v:count1 .. '{' .. v:operator vnoremap h mode() ==# 'V' ? 'h' : 'h' vnoremap l mode() ==# 'V' ? 'l' : 'l' vnoremap J j vnoremap K k inoremap kj `^ inoremap 「 「」 inoremap 「」 「」 inoremap ( () inoremap () () au vimrc FileType vim if getline(1) ==# 'vim9script' | &commentstring = '#%s' | endif #}}} ------------------------------------------------------- # ---------------------------------------------------------- # 様子見中 {{{ # 使わなそうなら削除する vnoremap p '"_s' .. v:register .. '' vnoremap P p nnoremap h ^ nnoremap l $ nnoremap d "_d nnoremap n nohlsearch au vimrc CursorHold * feedkeys(' n') # nohはauで動かない(:help noh) # どっちもw。左手オンリーと右手オンリーのマッピング nnoremap w w nnoremap o w # CSVとかのヘッダを固定表示する。ファンクションキーじゃなくてコマンド定義すればいいかな… nnoremap 1s:1w vnoremap 1sw # US→「"」押しにくい、JIS→「'」押しにくい # デフォルトのMはあまり使わないかなぁ… nnoremap ' " nnoremap m ' nnoremap M m # うーん… inoremap jj inoremap jjh ^ inoremap jjl $ inoremap jje ea inoremap jj; $; inoremap jj, $, inoremap jj{ $ { inoremap jj} $ } inoremap jj $ inoremap jjk 「」 inoremap jjx call ToggleCheckBox() # これはちょっと押しにくい(自分のキーボードだと) inoremap call ToggleCheckBox() # 英単語は`q`のあとは必ず`u`だから`q`をプレフィックスにする手もありか? # そもそも`q`が押しにくいか… cnoremap qq # syntax固有の追加強調 def ClearMySyntax() for id in get(w:, 'my_syntax', []) matchdelete(id) endfor w:my_syntax = [] enddef def AddMySyntax(group: string, pattern: string) w:my_syntax->add(matchadd(group, pattern)) enddef au vimrc Syntax * ClearMySyntax() # 「==#」とかの存在を忘れないように au vimrc Syntax javascript,vim AddMySyntax('SpellRare', '\s[=!]=\s') # 基本的にnormalは再マッピングさせないように「!」を付ける au vimrc Syntax vim AddMySyntax('SpellRare', '\ smile #}}} ------------------------------------------------------- # ---------------------------------------------------------- # † あともう1回「これ使ってないな…」と思ったときに消す {{{ nnoremap a A # 最後の選択範囲を現在行の下に移動する nnoremap m '' .. getpos("'<")[1] .. ',' .. getpos("'>")[1] .. 'move ' .. getpos('.')[1] .. '' #}}} ------------------------------------------------------- # ---------------------------------------------------------- # デフォルトマッピングデー {{{ if strftime('%d') ==# '01' def DMD() notification#show("✨ Today, Let's enjoy the default key mapping ! ✨") imapclear mapclear enddef au vimrc VimEnter * DMD() endif #}}} ------------------------------------------------------- # ---------------------------------------------------------- # 色 {{{ def DefaultColors() g:rainbow_conf = { guifgs: ['#9999ee', '#99ccee', '#99ee99', '#eeee99', '#ee99cc', '#cc99ee'], ctermfgs: ['105', '117', '120', '228', '212', '177'] } g:rcsv_colorpairs = [ ['105', '#9999ee'], ['117', '#99ccee'], ['120', '#99ee99'], ['228', '#eeee99'], ['212', '#ee99cc'], ['177', '#cc99ee'] ] enddef au vimrc ColorSchemePre * DefaultColors() def MyMatches() if exists('w:my_matches') && !empty(getmatches()) return endif w:my_matches = 1 matchadd('String', '「[^」]*」') matchadd('Label', '^\s*■.*$') matchadd('Delimiter', 'WARN\|注意\|注:\|[★※][^\s()()]*') matchadd('Todo', 'TODO') matchadd('Error', 'ERROR') matchadd('Delimiter', '- \[ \]') # 全角空白、半角幅の円記号、文末空白 matchadd('SpellBad', ' \|¥\|\s\+$') # 稀によくtypoする単語(気づいたら追加する) matchadd('SpellBad', 'stlye') enddef au vimrc VimEnter,WinEnter * MyMatches() set t_Co=256 syntax on set background=dark silent! colorscheme girly #}}} ------------------------------------------------------- # ---------------------------------------------------------- # メモ {{{ # でフォルダを開く(win32) # MRU # # # 日付関係 # # # # # ヘッダ行を表示(あんまり使わない) # 行番号表示切替 # 折り返し表示切替 #}}} ------------------------------------------------------- if filereadable(expand('~/.vimrc_local')) source ~/.vimrc_local endif