" AUTHOR: "A.J" <andrwj@gmail.com>
" LASTUPDATE: 2026-01-03
" VERSION: 3.3.10

" Utility Functions: {{{
   " Ternary: 삼항연사자 대용
   " ex) let g:my_colorscheme = Ternary(exists('g:colors_name'), g:colors_name, 'argonaut')
   function! Ternary(condition, if_true, if_false)
      if a:condition
         return a:if_true
      else
         return a:if_false
      endif
   endfunction

   " v:argv에서 +로 시작하는 인자 찾기
   function! CheckPlusCommand()
      for arg in v:argv
         if arg =~ '^+'
            " + 이후의 문자열을 추출 (예: +PlugInstall -> PlugInstall)
            let cmd = substitute(arg, '^+', '', '')
            return cmd
         endif
      endfor
      return ''
   endfunction

   let s:either_vim_path = has('nvim') ? expand('~/.config/nvim/autoload/either.vim') : expand('~/.vim/autoload/either.vim')
   if filereadable(s:either_vim_path)
      " either.vim을 autoload로 로드
      execute 'runtime ' . s:either_vim_path

      " either.vim 함수를 편리하게 호출하기 위한 명령어 정의 (선택 사항)
      command! -nargs=+ Right call either#Right(<f-args>)
      command! -nargs=+ Left call either#Left(<f-args>)
      command! -nargs=1 IsRight echo either#IsRight(<f-args>)
      command! -nargs=1 IsLeft echo either#IsLeft(<f-args>)
      command! -nargs=1 GetValue echo either#GetValue(<f-args>)
      command! -nargs=+ Map call either#Map(<f-args>)
      command! -nargs=+ Bind call either#Bind(<f-args>)
      command! -nargs=+ Fold call either#Fold(<f-args>)
   endif

   function! IsMacOS()
      return has('mac') || has('macunix')
   endfunction


   " Toggle Highlighting Group
   let g:__highlight_toggle_backup = {}

   function! DisableHighlight(group) abort
   if empty(a:group)
      echoerr '하이라이트 그룹 이름이 비어 있습니다.'
      return
   endif

   if a:group =~ '[^A-Za-z0-9_]'
      echoerr '유효하지 않은 하이라이트 그룹 이름: ' . a:group
      return
   endif

   if !hlexists(a:group)
      echoerr '하이라이트 그룹 "' . a:group . '"이 존재하지 않습니다.'
      return
   endif

   if has_key(g:__highlight_toggle_backup, a:group)
      let attrs = g:__highlight_toggle_backup[a:group]
      let cmd = 'highlight ' . a:group

      for [key, val] in items(attrs)
         " 빈 값 제외
         if empty(val)
         continue
         endif

         " cterm 계열은 RGB 코드가 아니어야 함
         if key =~# '^cterm' && val =~# '^#'
         continue
         endif

         let cmd .= ' ' . key . '=' . val
      endfor

      execute cmd
      call remove(g:__highlight_toggle_backup, a:group)
      echom '하이라이트 그룹 "' . a:group . '" 복원됨'
   else
      let id = synIDtrans(hlID(a:group))
      let g:__highlight_toggle_backup[a:group] = {
            \ 'guifg': synIDattr(id, 'fg#'),
            \ 'guibg': synIDattr(id, 'bg#'),
            \ 'gui': synIDattr(id, 'gui'),
            \ 'cterm': synIDattr(id, 'cterm'),
            \ 'ctermfg': synIDattr(id, 'fg'),
            \ 'ctermbg': synIDattr(id, 'bg'),
            \ }

      execute 'highlight clear' a:group
      execute 'highlight link' a:group 'Normal'
      echom '하이라이트 그룹 "' . a:group . '" 무력화됨 (→ Normal)'
   endif
   endfunction

" }}}

"Section: Initialization {{{
   set nocompatible     " → Vim을 Vi 호환 모드가 아닌 Vim 고유 기능을 사용하는 확장 모드로 전환

   " 아래 설정이 없으면, Vim은 기본적으로 어떤 파일이든 filetype을 비워둔다.
   " 즉 언어에 특화된 구문 강조(syntax), 들여쓰기(indent), 플러그인 등이 작동하지 않는다
   " 또한 위치에 따라 설정이 엎어 써질 수 있다:
   " .vimrc 앞쪽	filetype indent 스크립트가 사용자 설정을 덮어쓸 수 있음
   " .vimrc 뒤쪽	사용자 설정이 우선됨 (단, 일부 filetype에서는 여전히 setlocal로 덮힘)
   " autocmd FileType * 사용	사용자 설정을 확정적으로 유지하는 가장 안전한 방법
   filetype plugin indent on

   " 플러그인등에 포함된 indent 설정을 불러오고 난 뒤에 사용자 설정으로 덮을 예정.
   " curl -fLo ~/.vim/autoload/plug.vim --create-dirs \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
   " vim [ PlugInstall | PlugClean | PlugUpdate | PlugUpgrade | PlugStatus | PlugDiff ]
   if !exists('$NOVIMPLUGINS')

      let g:plugin_dir = '~/.vim/plugged'
      call plug#begin(g:plugin_dir)

         " 셋업방법:
         " ① Install in system PATH: brew install fzf
         " ② git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
         " ③ ~/.fzf/install 실행
         " ④ cd  ~/.vim/plugged/fzf && ./install  (system fzf를 symlink)
         " ⑤ sudo ln -s /bin/zsh /usr/local/bin/zsh  <-- 이 부분을 하지 않으면 Colors 등의 명령에서 오류가 발생한다
         Plug 'junegunn/fzf'


         " 아래 설정을 활성화하면 Docker 같은 환경에서 문제가 발생한다.
         " set rtp+=/opt/homebrew/opt/fzf
         " Homebrew를 통해 설치된 fzf의 Vim 플러그인 연동을 수동으로 활성화하기 위해 사용
         " 특히 Vim-Plug 등의 플러그인 매니저를 쓰지 않고, 시스템 설치된 fzf의 runtime 파일만 연결하고 싶을 때

         " 주의: 위의  러그인과 별개의 다른 플러그인이며, VIM 에서 많은 기능을 제공한다:
         " https://github.com/junegunn/fzf.vim
         Plug 'junegunn/fzf.vim'
         let g:using_fzf = 1

         " Themes
         Plug 'ayu-theme/ayu-vim'
         Plug 'dracula/vim'                     "Darducla theme
         Plug 'challenger-deep-theme/vim',     { 'as': 'challenger-deep' }
         Plug 'sainnhe/gruvbox-material'
         Plug 'catppuccin/nvim', { 'as': 'catppuccin' }
         Plug 'Rigellute/shades-of-purple.vim'
         Plug 'flazz/vim-colorschemes'          " (argonaut 색상테마 포함. 지우지 말 것)

         Plug 'junegunn/rainbow_parentheses.vim'
         let g:using_rainbow_parentheses = 1

         Plug 'Yggdroot/indentLine',    { 'on': ['IndentLinesToggle'] }

         " Multi Cursor
         Plug 'mg979/vim-visual-multi', {'branch': 'master'}

         " <F3> to maximize Tab/Window
         Plug 'szw/vim-maximizer'

         " visualizing marks
         Plug 'jeetsukumaran/vim-markology'
         let g:using_markology = 1

         " Buffer 목록을 Tree형태로 표시
         Plug 'el-iot/buffer-tree'

         " land to window you choose like tmux's 'display-pane' keymap: -
         Plug 't9md/vim-choosewin', { 'on': ['<Plug>(choosewin)', '<Plug>(choosewin-swap)'] }
         let g:using_choosewin = 1

         Plug 'airblade/vim-gitgutter'
         let g:using_gitgutter = 1

         " 새로운 탭에 파일 열기
         Plug 'francoiscabrol/ranger.vim'
         if has('nvim')
            Plug 'rbgrouleff/bclose.vim'
         endif
         let g:ranger_map_keys = 0  "<leader>f 로 맵핑하지 못하게 설정


         " NerdTree File Manager
         " https://github.com/PhilRunninger/nerdtree-visual-selection
         Plug 'preservim/nerdtree'
         Plug 'Xuyuanp/nerdtree-git-plugin'
         Plug 'PhilRunninger/nerdtree-visual-selection'
         let g:using_nerdtree = Ternary(CheckPlusCommand() != '', 0, 1)

         Plug 'scrooloose/nerdcommenter'        " WARN: lazy-loading 되지 않는다
         let g:using_nerdcommenter = 1

         " Markdown 테이블을 만들어줌
         Plug 'dhruvasagar/vim-table-mode',     { 'on': 'TableModeToggle' }
         let g:using_vim_table_mode = 1

         " Simple & Easy alignment
         Plug 'junegunn/vim-easy-align'
         let g:using_easy_align = 1

         "tabular vim-markdown은 같이 설정되야 함
         Plug 'plasticboy/vim-markdown'        "pandoc을 대신함
         Plug 'godlygeek/tabular',              { 'on': ['Tabularize'] }
         let g:using_tabularize = 1

         Plug 'easymotion/vim-easymotion'
         let g:using_easymotion = 1

         " 들여쓰기 가이드라인 표시
         Plug 'nathanaelkane/vim-indent-guides',{ 'on': 'IndentGuidesToggle' }
         let g:using_indent_guides = 1

         Plug 'terryma/vim-multiple-cursors'
         let g:using_multiple_cursors = 1

         Plug 'tpope/vim-fugitive',
         let g:using_fugitive = 1

         "Python
         " pip install pyvim pynvim
         " brew install pyvim
         " vim +CocInstall coc-pyright (nodejs 사용. 설치하지 않으면 LanguageServer 기능이 동작 X)
         Plug 'neoclide/coc.nvim', {'branch': 'release'}

         "Python 코드 입력 시 PEP8 기준으로 자동 들여쓰기(Indent) 동작 제공
         "완전히 독립적(CoC는 LSP/Lint/Format, 이 플러그인은 Vim의 indentexpr에 개입)
         "CoC의 LSP, Format 기능과 충돌 없음
         "단, CoC에서 LSP 기반 포매터(black 등)로 전체 코드 포맷 시, 기존 들여쓰기가 "black 스타일"로 덮어쓰기될 수 있음
         "실시간 입력 중엔 vim-python-pep8-indent가 작동
         "저장(Format on Save) 등에서 CoC 포매터(black 등)가 동작할 경우, 최종 들여쓰기 스타일은 포매터 결과에 따름
         Plug 'Vimjas/vim-python-pep8-indent'

         "Copy & Paste(복사/붙여넣기) 시, 기존 Vim 동작보다 더 정교하게 컨텍스트를 파악하여 자동으로 Indent/Unindent 수행
         "CoC에 대해 완전히 독립적(Vim 내부의 TextYankPost, Paste 등 이벤트 기반)
         "CoC의 자동 완성, 진단, 포매팅, LSP 기능과 충돌하지 않음
         "CoC가 직접적으로 개입하지 않는 영역이므로 상호 영향 거의 없음
         "다만, 붙여넣기 이후 CoC 포매터를 적용하면(예: black, yapf 등), 결과가 다시 포매팅될 수 있음
         Plug 'ubaldot/vim-replica'  "debugger

         "앞선 두개의 모듈은 저장 시 자동 포매터(black 등)가 최종 들여쓰기를 덮어쓸 수 있으므로,
         "입력/편집 중엔 두 플러그인이 역할을 담당하고, 파일 저장/포매팅 단계에선 CoC 포매터가 최종 스타일을 결정
         "vim-python-pep8-indent, vim-replica 모두 CoC와 병행 사용 가능.
         "어떤 환경에서도 정상 작동하며, CoC의 핵심 LSP/완성/포매팅 기능과 별도 계층에서 동작

         "pip install flake8 pylint black isort
         let g:using_coc = 1


         if filereadable('/.dockerenv')
            "PHP
            Plug 'stanangeloff/php.vim' "PHP 문법 강조를 개선하여 최신 PHP 버전(8.x 포함)을 지원합니다.
            Plug 'shawncplus/phpcomplete.vim' "PHP 자동 완성 기능을 제공합니다. 함수, 클래스, 변수 등을 빠르게 완성.
            Plug 'captbaritone/better-indent-support-for-php-with-html'  "PHP와 HTML이 섞인 코드에서 들여쓰기를 깔끔하게 유지.
            Plug 'jwalton512/vim-blade'  "Laravel의 Blade 템플릿 문법 강조 및 자동 완성.
            Plug 'noahfrederick/vim-composer' "Composer 명령어를 Vim 내에서 실행 및 관리.

            "pecl install xdebug && docker-php-ext-enable xdebug
            "Plug 'joonty/vdebug'
         endif


         " CtrlP
         Plug 'kien/ctrlp.vim'
         let g:using_ctrlp = 1

         " Hex value Colorizer
         Plug 'chrisbra/Colorizer'
         let g:using_colorizer = 1

         "현재 라인을 위/아래로 이동
         Plug 'matze/vim-move'
         let g:using_line_move = 1

         " tmux를 거쳐 macOS로 복사/붙여넣기
         Plug 'ojroques/vim-oscyank', {'branch': 'main'}

      call plug#end()
   endif

   "Section: buffer {{{
      augroup OnReadBuffer
         autocmd!
         autocmd BufNew,BufAdd,BufCreate,BufNewFile,BufRead * let g:buffer_height=10
      augroup END

      "<Space> b +
      function! IncreaseBufferHeight()
         let g:buffer_height += 1
         execute printf(":resize %s", g:buffer_height)
         execute printf("set terminal height to echo %s", g:buffer_height)
      endfunction

      "<Space> b -
      function! DecreaseBufferHeight()
         let g:buffer_height -= 1
         execute printf(":resize %s", g:buffer_height)
      endfunction

      function! DeleteEmptyBuffers()
         let [i, n; empty] = [1, bufnr('$')]
         while i <= n
            if bufexists(i) && bufname(i) == '' && getbufline(i,1,2) == ['']
               call add(empty, i)
            endif
            let i += 1
         endwhile
         if len(empty) > 0
            execute 'bdelete!' join(empty)
         endif
      endfunction

   "}}}

" }}}

"Plugin: (Color Scheme) {{{

   " 색상테마 정보를 저장할 파일
   let g:colorscheme_config_file = expand('~/.colorscheme.vim')
   let g:my_colorscheme = exists('g:colors_name') ? g:colors_name : 'argonaut'

   " 현재 색상 정보 저장
   function! SaveColorscheme()
      let g:my_colorscheme = exists('g:colors_name') ? g:colors_name : 'argonaut'
      call writefile([g:my_colorscheme], g:colorscheme_config_file)
      echom 'colorscheme ' . g:my_colorscheme . ' saved'
   endfunction

   " 색상 정보 불러와서 적용
   function! LoadColorscheme()
      if filereadable(g:colorscheme_config_file)
         " 파일의 첫 번째 줄을 읽어 colorscheme 이름으로 사용
         let l:colorscheme = readfile(g:colorscheme_config_file, '', 1)
         let l:colorscheme = l:colorscheme[0] "첫번째 라인값을 추출
         let l:colorscheme = substitute(l:colorscheme, '^\s\+', '', '') " 앞 공백 제거
         let l:colorscheme = substitute(l:colorscheme, '\s\+$', '', '') " 끝 공백 제거
         let l:colorscheme = get(l:, colorscheme, 'argonaut')
         execute 'colorscheme ' . l:colorscheme
      else
         colorscheme argonaut
      endif
   endfunction

   " Vim 초기화가 완료되고 첫 화면을 표시할 때 실행하지만, 화면이 한번 번쩍이게 되서 거슬린다.
   ">> augroup LoadUserColorscheme
   ">>    autocmd!
   ">>    autocmd VimEnter * call LoadColorscheme()
   ">> augroup END

   " Therefore, 그냥 바로 설정한다
   call LoadColorscheme()

"}}}

"Section: Cursor Color {{{
   autocmd BufNewFile,InsertLeave * highlight Cursor guibg=red
   autocmd BufEnter,InsertEnter * highlight Cursor guibg=green
"}}}

"Section: Save Cursorline Highlight & Restore {{{
   " CursorLine 저장/복구 -- FZF 유틸리티를 실행하고 나면 CursorLine이 망가지는 것을 해결하기 위함.
   let g:cursorline_saved = {}
   function! SaveCursorLine()
      let l:hi = execute('highlight CursorLine')
      if l:hi =~# 'cleared' || l:hi =~# 'links to Normal'
         let g:cursorline_saved = {'cleared': v:true}
      else
         let g:cursorline_saved = {
               \ 'gui': synIDattr(synIDtrans(hlID('CursorLine')), 'gui'),
               \ 'guibg': synIDattr(synIDtrans(hlID('CursorLine')), 'bg', 'gui'),
               \ 'cterm': synIDattr(synIDtrans(hlID('CursorLine')), 'cterm'),
               \ 'ctermbg': synIDattr(synIDtrans(hlID('CursorLine')), 'bg', 'cterm'),
               \ 'cleared': v:false
               \ }
      endif
      let g:cursorline_saved.cursorline = &cursorline

      echomsg 'CursorLine saved'
   endfunction

   function! RestoreCursorLine()
      if get(g:cursorline_saved, 'cleared', v:true)
         highlight clear CursorLine
         highlight link CursorLine Normal
      else
         " 속성값이 없을 경우 'NONE'을 할당해야 함을 잊지 말것
         let l:cmd = 'highlight CursorLine'

         let l:value = get(g:cursorline_saved, 'guibg', '')
         let l:cmd .= ' guibg=' . Ternary(!empty(l:value), l:value, 'NONE')

         let l:value = get(g:cursorline_saved, 'gui', '')
         let l:cmd .= ' gui=' . Ternary(!empty(l:value), l:value, 'NONE')

         let l:value = get(g:cursorline_saved, 'ctermbg', '')
         let l:cmd .= ' ctermbg=' . Ternary(!empty(l:value), l:value, 'NONE')

         let l:value = get(g:cursorline_saved, 'cterm', '')
         let l:cmd .= ' cterm=' . Ternary(!empty(l:value), l:value, 'NONE')

         execute l:cmd
      endif
      if get(g:cursorline_saved, 'cursorline', v:false)
         set cursorline
      else
         set nocursorline
      endif
      echomsg 'CursorLine restored'
   endfunction

   " 단축키
   nnoremap <Leader>sc :call SaveCursorLine()<CR>
   nnoremap <Leader>rc :call RestoreCursorLine()<CR>

   " 주의: ColorScheme을 읽어들이고 활성화 시킨 후에, CursorLine을 저장해두는 것을 일지 말라.
   " call SaveCursorLine()

"}}}

" Section: Trailing whitespace 제거 {{{
   function! TrimTrailingWhitespace()
   " 현재 커서 위치 저장
   let l:save = winsaveview()
   " 모든 줄의 끝 공백 제거
   keeppatterns %s/\s\+$//e
   " 커서 위치 복원
   call winrestview(l:save)
   endfunction

   " 파일 저장 시 TrimTrailingWhitespace 실행
   augroup TrimWhitespace
   autocmd!
   autocmd BufWritePre * call TrimTrailingWhitespace()
   augroup END
" }}}

"Section: Terminal {{{
   " open buffered terminal
   function! OpenTerminal()
      execute ":set termwinsize=" . g:buffer_height . "x0"
      execute ":botright terminal zsh"
   endfunction
   " open terminal in horizentally split buffer
   nnoremap <silent><space>t-  :call OpenTerminal()<cr>

   "open terminal in vertically split buffer
   nnoremap <silent><space>t\| :vnew<cr>:below terminal<cr><C-W>k:bdelete<cr>

   " open terminal in tabbed buffer (full size)
   nnoremap <silent><space>tt :tabnew<cr>:below terminal<cr><C-W>k:bdelete<cr>

   " To back to normal mode,  C-\ C-N
   " To back to termial mode, i
   tnoremap <silent><Esc>   <C-\><C-N>
   tnoremap <M-[> <Esc>
   tnoremap <C-v><Esc> <Esc>

   "suspend vim and exit to shell
   " nnoremap <space>ts   :w!<cr>:stop<cr>

   " 윈도우 최대화 토글
   function! ToggleMaximizeBuffer()
      if exists('b:is_maximized_buffer')
         execute "normal! \<C-W>="
         unlet b:is_maximized_buffer
      else
         execute "normal! \<C-W>_\<C-W>|"
         let b:is_maximized_buffer = 1
      endif
   endfunction

   "maximize current buffer
   noremap <silent><space><enter> :call ToggleMaximizeBuffer()<CR>

   " 수직으로 화면 나눔
   noremap <silent><space>s\| :vnew<cr>
   " 수편으로 화면 나눔
   noremap <silent><space>s-  :botright new<cr>

   noremap <silent><space>bn  :bnext!<cr>

   noremap <silent><space>bh  <C-W>h
   noremap <silent><space>bj  <C-W>j
   noremap <silent><space>bk  <C-W>k
   noremap <silent><space>bl  <C-W>l
"}}}


"Section: 파일 & 버퍼(buffer) {{{
   if get(g:, 'using_fzf', 0) == 1
      " map <silent><space>bb :ls<cr>
      " using FZF's feature (버퍼목록에서 화살표 및 키보드로 선택가능하다. :ls 명령은 그저 목록 표시만 할 뿐이다)

      nnoremap <space>ff :Files<cr>
      nnoremap <space>fs :Rg<cr>

      nnoremap <space>bb :Buffers<cr>
      nnoremap <space>bd :bdelete!<cr>
      nnoremap <space>bp :bprevious!<cr>
      nnoremap <space>[  :bprevious!<cr>
      nnoremap [[  :bprevious!<cr>
      nnoremap <space>bn :bnext!<cr>
      nnoremap <space>]  :bnext!<cr>
      nnoremap ]]  :bnext!<cr>
      nnoremap <space>bv :vnew<cr>
      nnoremap <space>bN :new<cr>
      "map <leader>af :VimFilerExplorer<cr>

      nnoremap <silent><space>++ :MaximizerToggle<cr>
      "vnoremap <silent><C-x>++ :MaximizerToggle<cr>
      "inoremap <silent><C-x>++:MaximizerToggle<cr>
   endif
"}}}


"Section: 탭(tab) {{{
      map <space>tN :tabnew<cr>
      map <silent><space>tn :tabnext<cr>
      map <silent><space>}  :tabnext<cr>
      map <silent><space>tp :tabprevious<cr>
      map <silent><space>{  :tabprevious<cr>
      map <silent><space>td :tabclose<cr>
      map <silent><space>tD :tabonly<cr>
      map <space>to :tabfind
"}}}

"Section: 'francoiscabrol/vim-ranger' (새로운 탭에 파일 열기) {{{
      "새로운 탭에 파일 열기. open new tab
      "This only works in version of console vim, not with  MacVIM
      nnoremap <silent> <space>arr :RangerWorkingDirectoryExistingOrNewTab<cr>
   "}}}

"Section: 그외 ... {{{
   "괄호안을 지움 dp | cp
   "onoremap p i(
   "괄호안을 지움cin
   "onoremap in( :<c-u>normal! f(vi(<cr>
   "return 문을 만날때까지 삭제 db
   "onoremap b /return<cr>
   "현재줄을 다음줄 뒤로 붙이기
   "nnoremap <leader>sw viw^<c-v>$d<esc>pJ$<cr>

   "선택된 블럭양끝에 따옴표 넣기
   "vnoremap <leader>" viw<esc>a"<esc>hbi"<esc>lel

   " r: Enter 입력 시 주석 기호 자동 삽입 방지
   " o: o 또는 O 입력 시 주석 기호 자동 삽입 방지
   autocmd FileType * setlocal formatoptions-=r formatoptions-=oÉ
"}}}



"Plugin: CoC (python, vimscript, bash) {{{
   " https://github.com/neoclide/coc.nvim/wiki/Language-servers
   " | 도구      | 대표 역할         | 실제 프로젝트 사용률(%) | 주 사용 목적            | 비고                   |
   " | -------- | --------------- | :---------------- | -------------------- | --------------------- |
   " | flake8   | Style/Lint      |     60\~70        | 코드 스타일, PEP8 점검   | 가장 표준적 lint 도구     |
   " | pylint   | Static Analysis |     35\~45        | 스타일 + 구조/복잡도 진단  | 대규모 코드에서 선호       |
   " | black    | Formatter       |     55\~65        | 자동 코드 포매팅         | 점유율 급상승            |
   " | isort    | Import Sorter   |     40\~50        | import 정렬           | black과 함께 많이 사용    |
   " | mypy     | Type Checker    |     25\~35        | 타입 힌트/정적 타입 체크   | 점진적 도입, FastAPI 등  |
   " | yapf     | Formatter       |      5\~10        | 대체 포매터             | black에 밀려 사용 감소    |
   " | autopep8 | Formatter       |     10\~15        | 자동 PEP8 스타일 적용    | black에 밀려 감소        |

   " ● = 완전 지원 | ○ = 일부 지원 또는 제한적 지원 | × = 미지원

   " | 도구      | 코드 스타일 검사 | 문법/에러 진단 | 정적 분석/구조 진단 | 점수화/리포트 | 코드 포매팅 | import 정렬 | 타입 검사 | 주요 독자적 기능              |
   " | -------- | :----------: | :------: | :--------------: | :-----:    | :----:   | :-------:  | :---:  | --------------------       |
   " | flake8   |     ●        |     ●    |      ○           |    ×       |    ×     |     ×      |   ×    | 플러그인 확장, 빠른 PEP8 검사    |
   " | pylint   |     ●        |     ●    |      ●           |    ●       |    ×     |     ×      |   ×    | 설계 진단, 복잡도, 점수, 리팩터링  |
   " | black    |     ○        |     ×    |      ×           |    ×       |    ●     |     ×      |   ×    | 포매팅 자동화, 스타일 논쟁 제거    |
   " | isort    |     ×        |     ×    |      ×           |    ×       |    ×     |     ●      |   ×    | import 그룹/순서 자동 정렬      |
   " | mypy     |     ×        |   ●(타입) |      ○           |    ×       |    ×     |     ×      |   ●    |  타입 힌트 기반 정적 타입 체크     |
   " | autopep8 |     ●        |     ×    |      ×           |    ×       |    ●     |     ×      |   ×    | PEP8 위반 자동 수정            |
   " | yapf     |     ○        |     ×    |      ×           |    ×       |    ●     |     ×      |   ×    | 스타일 가이드라인 기반 포매팅      |



   if get(g:, 'using_coc', 0) == 1
      let g:coc_global_config="$HOME/.vim/coc-settings.json"

      " 120 컬럼위치 넘어가면 색상 변경 (이럴필요가 있을까? 2014-9-5)
      "autocmd FileType python highlight Excess ctermbg=DarkGrey guibg=Black
      "autocmd FileType python match Excess /\%120v.*/
      "autocmd FileType python set nowrap

      " coc.nvim 설정
      " TAB으로 자동완성 항목 선택
      inoremap <silent><expr> <Tab>
            \ pumvisible() ? "\<C-n>" :
            \ <SID>check_back_space() ? "\<Tab>" :
            \ coc#refresh()
      inoremap <silent><expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<C-h>"

      function! s:check_back_space() abort
         let col = col('.') - 1
         return !col || getline('.')[col - 1] =~# '\s'
      endfunction

      nnoremap <silent>gd <Plug>(coc-definition)
      nnoremap <silent>K <Plug>(coc-hover)


      " CoC 하이라이팅 끄기
      nnoremap <silent><space>th :call DisableHighlight('CocInlayHint')<cr>

      " updatetime -- 커서 멈춤 후 비동기 작업 시작 전 대기 시간(밀리초).
      " 늘리기 (기본 4000ms -> 10000ms; 10초 동안 입력 없으면 업데이트) -- CoC Diagnoses Message가 너무 자주 출력될 때, 조절.
      " CoC 진단메세지가 표시될 경우 확인: ':CocCommand workspace.showOutput'
      set updatetime=10000

      " coc-vimlsp 작업 공간 설정
      " 문제가 될 경우 vimlsp 정지 ==> ':CocDisable extension coc-vimlsp'
      let g:coc_vimlsp_root_markers = ['~/.vim']
      let g:coc_vimlsp_timeout = 60000


      " 'ubaldot/vim-replica'  "debugger
      nnoremap <leader>db :ReplicaToggleBreakpoint<CR>

      "PEP8 경고 무시 (CoC 사용할 때는 듣지 않는다)
      let g:pep8_ignore = 'E501,W601,E265,W503'
      "- E501(line too long),
      "- W601(old-style comparison),
      "- E265(block comment),
      "- W503(line break before binary operator)

      augroup python_files
         autocmd!
         autocmd BufNewFile,BufRead *.py,*.pyw setlocal smartindent cinwords=if,elif,else,for,while,try,except,finally,def,class
            \ foldmethod=indent
            \ tabstop=3
            \ shiftwidth=3
            \ textwidth=0
            \ expandtab
            \ autoindent
            \ fileformat=unix
            \ encoding=utf-8
            \ commentstring=#%s
            \ define=^\s*\\(def\\\\|class\\)
      autocmd FileType python setlocal indentexpr=GetPythonPEP8Indent(v:lnum)
      "coc-vimlsp 인덱싱 오류출력을 제한 하기 위해, 파일을 열었을 때 파일과 같은 폴더로 CWD를 이동.
      autocmd BufEnter * if expand('%:p') != '' | execute 'cd ' . expand('%:p:h') | endif
      augroup END

      " 경고/오류에 대한 자세한 내용을 보이는 웹 사이트로 브라우저로 바로 연결하는 Vimscript
      function! PycodeExplain()
         let diags = CocAction('diagnosticList')
         let lnum = line('.')
         let col = col('.')
         for diag in diags
            if diag['lnum'] + 1 == lnum
               " pycodestyle/flake8 코드를 메시지에서 정규식으로 추출
               let msg = diag['message']
               let code = matchstr(msg, '\v(E|W|F)\d{3}')
               if code != ''
               let url = 'https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes'
               execute '!open ' . url
               return
               endif
            endif
         endfor
         echo "No flake8/pycodestyle code found for current line."
      endfunction

      function! PyrightExplain()
         let diags = CocAction('diagnosticList')
         let lnum = line('.')
         let found = 0
         for diag in diags
            " 해당 라인, Pyright 진단만 선택
            if diag['lnum'] + 1 == lnum && get(diag, 'source', '') =~? 'pyright'
               let code = get(diag, 'code', '')
               if code != ''
               let url = 'https://github.com/microsoft/pyright/blob/main/docs/configuration.md#type-check-diagnostics-settings'
               echom 'Pyright code: ' . code
               execute '!open ' . url
               let found = 1
               break
               endif
            endif
         endfor
         if !found
            echo "No Pyright diagnostic found for current line."
         endif
      endfunction

      function! PycodeErrors()
         let l:line = getline('.')
         let l:code = matchstr(l:line, '\v([EWF]\d{3})')
         if l:code != ''
            if l:code =~? '^E\d\{3}$'
               let l:site = 'https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes'
               echo "Open: " . l:site . " (code: " . l:code . ")"
               if has('mac')
               call system('open ' . shellescape(l:site) . ' &')
               elseif has('unix')
               call system('xdg-open ' . shellescape(l:site) . ' &')
               elseif has('win32')
               call system('start ' . shellescape(l:site))
               else
               echo "Cannot detect OS to open browser."
               endif
            else
               echo "No site mapping for code: " . l:code
            endif
         else
            echo "No E/W/F error code found on this line."
         endif
      endfunction

      nnoremap <space>pe :call PycodeErrors()<CR>

      "오류/경고가 보이는 라인에서 아래 키를 입력해서 브라우저를 오픈 (2025-06-25; 동작하지 않는다)
      " nnoremap <space>pe :call PycodeExplain()<CR>

      " 오류/경고를 모두 나열 & JUMP 기능제공: Quickfix/Location List 활용하기
      nnoremap <space>pl :CocList diagnostics<CR>

   endif
"}}}

"Filetype: vimscript {{{
   " npm install -g vim-language-server
   " Install coc.nvim
   " :CocInstall coc-vimlsp
"}}}

"Filetype: json {{{
   " JSON prettifier
   autocmd FileType json,js nnoremap <buffer> <leader>fmt :%!python3 -m json.tool<cr>
"}}}

"Filetype: shell {{{
   "autocmd FileType sh nnoremap <buffer> <localleader>c I#<esc>
"}}}

"Filetype: vim {{{
   autocmd FileType vim setlocal foldmethod=marker
"}}}

"Plugin: NERDtree {{{
   if get(g:, 'using_nerdtree', 0) != 0
      function! CheckGivenArguments()
         if 0 == argc()
            NERDTree
         endif
      endfunction

      augroup NERDTree
         let g:NERDTreeDirArrowExpandable = '▸'
         let g:NERDTreeDirArrowCollapsible = '▾'

         autocmd!
         nnoremap <silent> <space>ft :NERDTreeToggle<cr>
         "파일지정없이 vim을 열었을 경우, 자동으로 NERDTree를 동작시킴
         autocmd VimEnter * call CheckGivenArguments()

         " Exit Vim if NERDTree is the only window remaining in the only tab.
         autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif
      augroup END

      "https://github.com/Xuyuanp/nerdtree-git-plugi
      let g:NERDTreeGitStatusIndicatorMapCustom = {
         \ 'Modified'  :'✹',
         \ 'Staged'    :'✚',
         \ 'Untracked' :'✭',
         \ 'Renamed'   :'➜',
         \ 'Unmerged'  :'═',
         \ 'Deleted'   :'✖',
         \ 'Dirty'     :'✗',
         \ 'Ignored'   :'☒',
         \ 'Clean'     :'✔︎',
         \ 'Unknown'   :'?',
         \ }
   endif
"}}}

"Plugin: vim-table-mode {{{

   "block을 잡은후 <leader>tt --> Tableize
   "다른 구분자 적용 --> :Tableize/;   ';'이 구분자
   "g:table_mode_corner_corner='+' 로 설정해야 테두리가 제대로 나온다.

   if get(g:, 'using_vim_table_mode', 0) == 1
      let g:table_mode_separator='|'
      let g:table_mode_align_char=':'
      let g:table_mode_corner_corner='+'
      nnoremap <buffer> <silent> <leader><tab> :TableModeToggle<cr>

   endif
" }}}

"Plugin: vim-markdown (markdown 타입은 vim-pandoc으로 처리중) {{{
   let g:vim_markdown_folding_disabled=1
   let g:vim_markdown_emphasis_multiline=0
   let g:vim_markdown_conceal = 0  "이미지 태그 라인이 보이지 않는 것을 해결
"}}}

"Plugin: Tabularize {{{
   if get(g:, 'using_tabularize', 0) == 1
      "http://vimcasts.org/episodes/aligning-text-with-tabular-vim/
      ":Tabularize /패턴 ==> 패턴을 기준으로해서 컬럼폭을 맞춤
      augroup tabularize
         autocmd!
         nnoremap <space>a= :Tabularize /=
         nnoremap <space>a: :Tabularize /:
         nnoremap <space>a:: :Tabularize /:\zs
         nnoremap <space>a, :Tabularize /,
         nnoremap <space>a<Bar> :Tabularize /
      augroup END
   endif
"}}}

"Plugin: easymotion {{{
   " https://github.com/easymotion/vim-easymotion

   if get(g:, 'using_easymotion', 0) == 1
      augroup easymotion
         autocmd!
         map  / <Plug>(easymotion-sn)
         omap / <Plug>(easymotion-tn)
         map  n <Plug>(easymotion-next)
         map  N <Plug>(easymotion-prev)
      augroup END
   endif
"}}}

"Plugin: pebble-vim-syntax {{{
   "특정 위치에서의 C 소스는 페블어플리케이션으로 인식하게함
   " augroup pebble
   "    "autocmd!
   "    "autocmd FileType C set syntax=pebble
   "    "autocmd Filetype C set makeprg=bash\ --init-file\ ~/.shell_prompt.sh\ -c\ 'cd\ ..\ &&\ pebble\ build'
   "    "autocmd Filetype C set errorformat=../src/%f:%l:%c:\ %m
   "    "autocmd Filetype C nmap <leader>b :make!<cr><cr>:cw<cr>
   "    "autocmd Filetype C nmap <F4> :cw<cr>

   "    "autocmd BufNewFile,BufRead ~/Develops/pebble.applications/*.{c,h} set syntax=pebble
   "    "autocmd BufNewFile,BufRead ~/Develops/pebble.applications/*.{c,h} set makeprg=bash\ --init-file\ ~/.shell_prompt.sh\ -c\ 'cd\ ..\ &&\ pebble\ build'
   "    "autocmd BufNewFile,BufRead ~/Develops/pebble.applications/*.{c,h} set errorformat=../src/c/%f:%l:%c:\ %m
   "    "autocmd BufNewFile,BufRead ~/Develops/pebble.applications/*.{c,h} nmap <leader>b :make!<cr><cr>:cw<cr>
   "    "autocmd BufNewFile,BufRead ~/Develops/pebble.applications/*.{c,h} nmap <F4> :cw<cr>
   "    " autocmd BufWritePost ~/Develops/pebble.applications/*.{c,h} *.c,*.h silent! !ctags --fields=+l --C-kinds=+p -e -R % 2> /dev/null &
   " augroup END
"}}}

"Plugin: rainbow_parenthesis {{{
   if get(g:, 'using_rainbow_parentheses', 0) == 1
      augroup rainbow_lisp
      autocmd!
      autocmd BufNewFile,BufRead *.js,*.mjs,*.jsx,*.ts,*.tsx,*.css,*.html,*.json RainbowParentheses
      augroup END
      let g:rainbow#max_level = 16
      let g:rainbow#pairs = [['(', ')'], ['[', ']'],['{', '}'],['<', '>']]

      " List of colors that you do not want. ANSI code or #RRGGBB
      let g:rainbow#blacklist = [229, 10, 81, 112, 161, 233, 234, '#ffffff', '#000000', 0, 254]

      " See the enabled colors
      " :RainbowParenthesesColors

      " Activate
      " :RainbowParentheses

      " Deactivate
      " :RainbowParentheses!

      " Toggle
      " :RainbowParentheses!!
      nnoremap <silent><space>tR :RainbowParentheses!!<cr>

   endif
"}}}

"Plugin: UndoTree {{{
   " https://github.com/mbbill/undotree
   if has('persistent_undo')
      set undodir="$HOME/.vim/undodir"
      set undofile

      augroup UndoTree
         autocmd!
         nnoremap <leader>u :UndotreeToggle<cr>
      augroup END
   endif
"}}}

"Plugin: (윈도우 선택) vim-choosewin {{{
   if get(g:, 'using_choosewin', 0) == 1
      "keymap '='
      let g:choosewin_overlay_enable = 1
      let g:choosewin_overlay_clear_multibyte = 1
      let g:choosewin_blink_on_land      = 0 " dont' blink at land
      let g:choosewin_statusline_replace = 0 " don't replace statusline
      let g:choosewin_tabline_replace    = 0 " don't replace tabline
      nmap <leader><backspace> <Plug>(choosewin)
      nmap <leader>] <Plug>(choosewin-swap)
      " tmux like overlay color
      let g:choosewin_color_overlay = {
            \ 'gui': ['DodgerBlue3', 'DodgerBlue3' ],
            \ 'cterm': [ 125, 125 ]
            \ }
      let g:choosewin_color_overlay_current = {
            \ 'gui': ['firebrick1', 'firebrick1' ],
            \ 'cterm': [ 124, 124 ]
            \ }
   endif
"}}}

"Plugin: markology (마킹|마크) {{{
   if get(g:, 'using_markology', 0) == 1
      "Section: characters for marking {{{
         " https://github.com/jeetsukumaran/vim-markology/blob/master/doc/markology.txt
         "m+: 추가, m-:삭제, m<space>:토글, m,:토글,
         "m[ / m]: 이전/이후로 점프
         "m{ / m}: jump lexicographically
         "m?: 모든 표식 보이기
         "m~: quickfix window
         "m_: MarkologyClearAll
         "m1: MarkologyEnable
         "m0: MarkologyDisable
         "m!: MarkologyToggle
         "m*: MarkologyLineHighlightToggle

         "h: Help, m: Non-modifiable, p: Preview, q: Quickfix, r: Readonly
         let g:markology_ignore_type='hq'
         let g:markology_include='23456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
         " 소문자 표식인 경우, 전체 라인을 강조표시
         let g:markology_hlline_lower=0
         " 대문자 표식인 경우, 전체 라인을 강조표시
         let g:markology_hlline_upper=1
         " 그외의 경우, 전체라인 강조
         let g:markology_hlline_other=0

         " 사용사 설정 (예제)
         " nmap <silent> ;0 <Plug>MarkologyEnable
         " nmap <silent> ;1 <Plug>MarkologyDisable
         " nmap <silent> ;! <Plug>MarkologyToggle
         " nmap <silent> ;, <Plug>MarkologyPlaceMarkToggle
         " nmap <silent> ;+ <Plug>MarkologyPlaceMark
         " nmap <silent> ;- <Plug>MarkologyClearMark
         " nmap <silent> ;_ <Plug>MarkologyClearAll
         " nmap <silent> ;] <Plug>MarkologyNextLocalMarkPos
         " nmap <silent> ;[ <Plug>MarkologyPrevLocalMarkPos
         " nmap <silent> ;} <Plug>MarkologyNextLocalMarkByAlpha
         " nmap <silent> ;{ <Plug>MarkologyPrevLocalMarkByAlpha
         " nmap <silent> ;? <Plug>MarkologyLocationList
         " nmap <silent> ;~ <Plug>MarkologyQuickFix
      "}}}

      "Section: Color Sheme {{{
         " 주의: LoadColorScheme() 함수에서 컬러스킴을 정한 뒤에 설정해야 한다.
         " Gutter 배경 색상 변경 (예: 연한 회색)
         augroup GutterColor
            autocmd!
            autocmd VimEnter * highlight SignColumn guibg=#2e2e2e
         augroup END

         "MarkologyHLl  : This group is used to highlight all the lowercase marks.
         "MarkologyHLu  : This group is used to highlight all the uppercase marks.
         "MarkologyHLo  : This group is used to highlight all other marks.
         "MarkologyHLm  : This group is used when multiple marks are on the same line.
         "MarkologyHLLine : This group is used to highlight lines if line-highlighting is selected.

         " highlight MarkologyHLl guifg=red guibg=green
         " highlight MarkologyHLu guifg=red guibg=green
         " highlight MarkologyHLo guifg=red guibg=green
         " highlight MarkologyHLm guifg=red guibg=green
         " highlight MarkologyHLLine guifg=red guibg=green

         " hi MarkologyHLl ctermfg=green ctermbg=black cterm=bold guifg=green guibg=black
         " hi MarkologyHLLine cterm=underline gui=undercurl guisp=#007777
         " hi MarkologyHLu ctermfg=green ctermbg=black cterm=bold guifg=green guibg=black
         " hi MarkologyHLo ctermfg=green ctermbg=black cterm=bold guifg=green guibg=black
         " hi MarkologyHLm ctermfg=green ctermbg=black cterm=bold guifg=green guibg=black
      "}}}
   endif
   " 모든 Mark를 삭제
   nmap <silent><space>dT :delmarks 0-9a-zA-Z[]<CR>
"}}}

"Plugin: GitGutter {{{
   "https://github.com/airblade/vim-gitgutter

   if get(g:, 'using_gitgutter', 0) == 1
      let g:gitgutter_eager = 0
      let g:gitgutter_realtime = 0
      let g:gitgutter_async = 1

      " 표시 기호 갯수 제한없음
      let g:gitgutter_max_signs = -1

      nmap ]h <Plug>(GitGutterNextHunk)
      nmap [h <Plug>(GitGutterPrevHunk)

      function! GitStatus()
         let [a,m,r] = GitGutterGetHunkSummary()
         return printf('+%d ~%d -%d', a, m, r)
      endfunction
      set statusline+=%{GitStatus()}

      highlight GitGutterAdd    guifg=#009900 ctermfg=2
      highlight GitGutterChange guifg=#bbbb00 ctermfg=3
      highlight GitGutterDelete guifg=#ff2222 ctermfg=1

      " 파일이 저장될 때, 표식 업데이트
      autocmd BufWritePost * GitGutter

      " let g:gitgutter_sign_added = 'xx'
      " let g:gitgutter_sign_modified = 'yy'
      " let g:gitgutter_sign_removed = 'zz'
      " let g:gitgutter_sign_removed_first_line = '^^'
      " let g:gitgutter_sign_modified_removed = 'ww'

      " turn off with :GitGutterDisable
      " turn on with :GitGutterEnable
      " toggle with :GitGutterToggle
   endif
"}}}

"Plugin: fugitive (Git) {{{
   " https://github.com/tpope/vim-fugitive/blob/master/doc/fugitive.txt

   if get(g:, 'using_fugitive', 0) == 1
      augroup fugitive
         autocmd!
         nnoremap <space>gs :Gstatus<cr>
         nnoremap <space>gd :call TurnOffHighlight()<cr>:Gdiff<cr>
         nnoremap <space>gc :Gcommit<cr>
         nnoremap <space>gb :Gblame<cr>
         nnoremap <space>gl :Glog<cr>
         nnoremap <space>gp :Git push<cr>
         nnoremap <space>gw :Gwrite<cr>
      augroup END

      let g:fugitive_no_maps = 0
      set statusline+=%{FugitiveStatusline()}
   endif
"}}}


"Plugin: Markdown View {{{
   if IsMacOS()
      augroup zettlr
         autocmd!
         autocmd FileType markdown nnoremap <leader>v :!open -a Zettlr.app %<cr><cr>
         "autocmd FileType markdown set dictionary+=$HOME/.vim/dicts/corpus.dict
      augroup END
   endif
"}}}

"Section: 커서 위치의 단어를 모두 강조하가
   set updatetime=500
   function! HighlightWordUnderCursor()
      if getline(".")[col(".")-1] !~# '[[:punct:][:blank:]]'
         exec 'match' 'Search' '/\V\<'.expand('<cword>').'\>/'
      else
         match none
      endif
   endfunction

   autocmd! CursorHold,CursorHoldI * call HighlightWordUnderCursor()
"}}}

"Plugin: '(들여쓰기 가이드<블록>) nathanaelkane/vim-indent-guides' {{{

   if get(g:, 'using_indent_guides', 0) == 1
      nnoremap <silent><space>tg :IndentGuidesToggle<cr>

      " set background=dark
      " let g:indent_guides_enable_on_vim_startup = 0
      " let g:indent_guides_auto_colors = 1
      " let g:indent_guides_start_level = 2
      " let g:indent_guides_guide_size = 1

      let g:indentLine_enabled = 1
      let g:indentLine_color_term = 1       "vim
      let g:indentLine_bgcolor_term = 1
      let g:indentLine_color_gui = '#A4E57E' "Gvim

      " background color
      let g:indentLine_color_tty_light = 3 " (default: 4)
      let g:indentLine_color_dark = 5 " (default: 2)
      let g:indentLine_char = '┆ '
      let g:indentLine_char_list = ['|', '¦', '┆', '┊']

      autocmd VimEnter,Colorscheme * :highlight IndentGuidesOdd  guibg=black     ctermbg=3
      autocmd VimEnter,Colorscheme * :highlight IndentGuidesEven guibg=darkgrey  ctermbg=4

      " INFO: 파일 전체 탭 다시 들여쓰기: gg=G
      " NOTE: 기존 들여쓰기를 완전히 다시 쓰기 때문에 문제가 될 수 있다
      " INFO: 현재 라인이후 탭 다시 들여쓰기: =G
   endif
"}}}

"Plugin: 'terryma/vim-multiple-cursors' {{{

   if get(g:, 'using_multiple_cursors', 0) == 1
      " disabled for some critical error
      " https://github.com/terryma/vim-multiple-cursors

      " 전역으로 키를 미리 맵핑하는 여부
      " let g:multi_cursor_use_default_mapping=0
      " let g:multi_cursor_exit_from_visual_mode=1
      " let g:multi_cursor_exit_from_insert_mode=1
      "
      " let g:multi_cursor_start_word_key      = '<c-n>'
      " let g:multi_cursor_select_all_word_key = '<a-a>'
      " let g:multi_cursor_start_key           = 'g<c-n>'
      " let g:multi_cursor_select_all_key      = 'g<a-a>'
      " let g:multi_cursor_next_key            = '<c-n>'
      " let g:multi_cursor_prev_key            = '<c-p>'
      " let g:multi_cursor_skip_key            = '<c-x>'
      " let g:multi_cursor_quit_key            = '<c-c>'

      " default highlighting (see help :highlight and help :highlight-link)
      " cterm에는 6자리 헥스코드값을 쓰면 오류! 터미널이기 때문. gui쪽에는 가능. (#f5f454)

      highlight multiple_cursors_cursor term=reverse cterm=reverse gui=reverse
      highlight multiple_cursors_cursor ctermbg=Yellow
      highlight link multiple_cursors_visual visual

      augroup MultipleCursorsSelectionFix
         autocmd User MultipleCursorsPre  if &selection ==# 'exclusive' | let g:multi_cursor_save_selection = &selection | set selection=inclusive | endif
         autocmd User MultipleCursorsPost if exists('g:multi_cursor_save_selection') | let &selection = g:multi_cursor_save_selection | unlet g:multi_cursor_save_selection | endif
      augroup END
   endif
"}}}

"Plugin: LISTP {{{
   autocmd BufNewFile,BufRead .spacemacs set syntax=lisp
   autocmd BufNewFile,BufRead .clj set syntax=clojure
   " vim-clojure-static의 구문 강조 기능이 한번에 처리할 최대 행 수
   " 높은 값일수록 긴 함수를 만났을 때 처리시간이 오래 걸린다.
   " 0으로 설정하면 제한없이 끝까지 처리.
   let g:clojure_maxlines=200

"}}}

"Plugin: preservim/nerdcommenter (타입별 코멘트 문자 지정) {{{

   if get(g:, 'using_nerdcommenter', 0) == 1
      " https://github.com/preservim/nerdcommenter

      " 기본 키맵핑을 설정하지 않을 때
      " let g:NERDCreateDefaultMappings = 0

      " 코멘트 토글
      nnoremap <C-c><C-c> :call NERDComment('n', 'toggle')<cr>
      vnoremap <C-c><C-c> :call NERDComment('x', 'toggle')<cr>gv

      autocmd FileType apache setlocal commentstring=#\ %s
      autocmd FileType javascript setlocal commentstring=//\ %s
      autocmd FileType vim setlocal commentstring="\ %s
      autocmd FileType sh setlocal commentstring=#\ %s

      " Add spaces after comment delimiters by default
      let g:NERDSpaceDelims = 1

      " Use compact syntax for prettified multi-line comments
      let g:NERDCompactSexyComs = 1

      " Align line-wise comment delimiters flush left instead of following code indentation
      let g:NERDDefaultAlign = 'left'

      " Set a language to use its alternate delimiters by default
      let g:NERDAltDelims_java = 1

      " Add your own custom formats or override the defaults
      let g:NERDCustomDelimiters = {
         \ 'c': { 'left': '/**','right': '*/' },
         \ 'javascript': { 'left': '//','right': '' },
         \ 'vim': { 'left': '"','right': '' },
         \ 'sh': { 'left': '#','right': '' }
         \ }

      " Allow commenting and inverting empty lines (useful when commenting a region)
      let g:NERDCommentEmptyLines = 1

      " 코멘트를 벗길 때, 줄끝 공백삭제
      let g:NERDTrimTrailingWhitespace = 1

      " Enable NERDCommenterToggle to check all selected lines is commented or not
      let g:NERDToggleCheckAllLines = 1
   endif
"}}}

"Section: Syntax for Todo Conceal {{{
   if !exists("b:current_syntax")
      " Custom conceal
      syntax match todoCheckbox "\[\ \]" conceal cchar=☐
      syntax match todoCheckbox "\[x\]" conceal cchar=☑︎

      let b:current_syntax = "todo"

      hi def link todoCheckbox Todo
      hi Conceal guibg=NONE ctermbg=NONE

      setlocal cole=1
   endif
"}}}

"Section: Tip {{{
   " 모든 버퍼를 탭으로 다시 열기
   " :bufdo tab split
   " :tab sball
"}}}

"Plugin:: split-term  {{{
   " https://github.com/vimlab/split-term.vim
   " Term --  :new      + :term (수평분할후 터미널 열기)
   " VTerm -- :vnew     + :term (수직분할후 터미널 열기)
   " TTerm -- :tabnew   + :term (새탭에 터미널 열기)
   " 10Term  -- 10줄 높이 터미널 열기
   " 100VTerm -- 100줄 수직분할후 터미널 열기
   " :Term git status   -- 명령실행

   " default shell
   let g:split_term_default_shell = "zsh"
   " 항상 수평분할로 열기
   let g:split_term_vertical = 0

   " <Esc> - Switch to normal mode (instead of <C-\><C-n>)
   " Bind Alt+hjkl, Ctrl+arrows to navigate through windows (eg. switching to buffer/windows left, right etc.)
   " Alt+h - does a <C-w>h
   " Alt+j - does a <C-w>j
   " Alt+k - does a <C-w>k
   " Alt+l - does a <C-w>l
   " Ctrl+Left - does a <C-w>h
   " Ctrl+Down - does a <C-w>j
   " Ctrl+Up - does a <C-w>k
   " Ctrl+Right - does a <C-w>l
   " Ctrl+v - copy-pasting, does a <C-\><C-N>pi

   " 위의 키 맵핑을 disable
   let g:disable_key_mappings = 0
"}}}

"Section:Improvement {{{
   " https://vi.stackexchange.com/questions/10249/what-is-the-difference-between-mapped-key-sequences-and-key-codes-timeoutl#answer-10284
   " put the following into ~/.screenrc
   " maptimeout 0
   set timeoutlen=1000
   set ttimeoutlen=0
"}}}

"Section: Visual Search {{{
   nmap <silent><space><tab><tab> :<C-u>cal OSearch("nl")<CR>
   nmap <silent><leader><tab><tab> :<C-u>cal OSearch("nj")<CR>
   vmap <silent><space><tab><tab> :<C-u>cal OSearch("vl")<CR>
   vmap <silent><leader><tab><tab> :<C-u>cal OSearch("vj")<CR>

   function! OSearch(action)
   let c = v:count1
   if a:action[0] == "n"
      let s = "/\\<".expand("<cword>")."\\>/"
   elseif a:action[0] == "v"
      execute "normal! gvy"
      let s = "/\\V".substitute(escape(@@, "/\\"), "\n", "\\\\n", "g")."/"
      let diff = (line2byte("'>") + col("'>")) - (line2byte("'<") + col("'<"))
   endif
   if a:action[1] == "l"
      try
         execute "ilist! ".s
      catch
         if a:action[0] == "v"
         normal! gv
         endif
         return ""
      endtry
      let c = input("Go to: ")
      if c !~ "^[1-9]\\d*$"
         if a:action[0] == "v"
         normal! gv
         endif
         return ""
      endif
   endif
   let v:errmsg = ""
   silent! execute "ijump! ".c." ".s
   if v:errmsg == ""
      if a:action[0] == "v"
         " Initial version
         " execute "normal! ".visualmode().diff."\<Space>"
         " Bug fixfor single character visual [<Tab>:
         if diff
         execute "normal! ".visualmode().diff."\<Space>"
         else
         execute "normal! ".visualmode()
         endif
      endif
   elseif a:action[0] == "v"
      normal! gv
   endif
   endfunction

"}}}

"Section: neovide {{{
   if has('nvim')
      let g:neovide_cursor_trail_length=0
      let g:neovide_cursor_animation_length=0.05
      let neovide_cursor_antialiasing=v:true
   endif
"}}}

"Plugin:anyjump  {{{
   if get(g:, 'using_anyjump', 0) == 1
      "https://github.com/pechorin/any-jump.vim
      " o/<CR>     open
      " s          open in split
      " v          open in vsplit
      " t          open in new tab
      " p/<tab>    preview
      " q/x        exit
      " r          references
      " b          back to first result
      " T          group by file
      " a          load next N results
      " A          load all results
      " L          toggle results lists ui style

      " Normal mode: Jump to definition under cursore
      nnoremap <space>j :AnyJump<CR>

      " Visual mode: jump to selected text in visual mode
      xnoremap <space>j :AnyJumpVisual<CR>

      " Normal mode: open previous opened file (after jump)
      nnoremap <leader>ab :AnyJumpBack<CR>

      " Normal mode: open last closed search window again
      nnoremap <leader>al :AnyJumpLastResults<CR>

      let g:any_jump_disable_default_keybindings = 0

      " Show line numbers in search rusults
      let g:any_jump_list_numbers = 0

      " Auto search references
      let g:any_jump_references_enabled = 1

      " Auto group results by filename
      let g:any_jump_grouping_enabled = 0

      " Amount of preview lines for each search result
      let g:any_jump_preview_lines_count = 5

      " Max search results, other results can be opened via [a]
      let g:any_jump_max_search_results = 10

      " Prefered search engine: rg or ag
      let g:any_jump_search_prefered_engine = 'rg'


      " Search results list styles:
      " - 'filename_first'
      " - 'filename_last'
      let g:any_jump_results_ui_style = 'filename_first'

      " Any-jump window size & position options
      let g:any_jump_window_width_ratio  = 0.6
      let g:any_jump_window_height_ratio = 0.6
      let g:any_jump_window_top_offset   = 4

      " Customize any-jump colors with extending default color scheme:
      let g:any_jump_colors = { "help": "Comment" }

      " Or override all default colors
      let g:any_jump_colors = {
            \"plain_text":         "Comment",
            \"preview":            "Comment",
            \"preview_keyword":    "Operator",
            \"heading_text":       "Function",
            \"heading_keyword":    "Identifier",
            \"group_text":         "Comment",
            \"group_name":         "Function",
            \"more_button":        "Operator",
            \"more_explain":       "Comment",
            \"result_line_number": "Comment",
            \"result_text":        "Statement",
            \"result_path":        "String",
            \"help":               "Comment"
            \}

      " Disable default any-jump keybindings (default: 0)
      let g:any_jump_disable_default_keybindings = 1

      " Remove comments line from search results (default: 1)
      let g:any_jump_remove_comments_from_results = 1

      " Custom ignore files
      " default is: ['*.tmp', '*.temp']
      let g:any_jump_ignored_files = ['*.tmp', '*.temp']

      " Search references only for current file type
      " (default: false, so will find keyword in all filetypes)
      let g:any_jump_references_only_for_current_filetype = 0

      " Disable search engine ignore vcs untracked files
      " (default: false, search engine will ignore vcs untracked files)
      let g:any_jump_disable_vcs_ignore = 0
   endif
"}}}

"Section: Copy & Paste in VIM way {{{
   " 가장 최근에 yank 내용을 붙여넣기 한다
   map <space>pp   /<C-r>0

   " Copy (Cmd-C)
   " Normal 모드: 현재 줄 yank → TextYankPost autocmd가 OSC 52로 system clipboard에 전달
   " Visual 모드: 선택 영역 yank → TextYankPost autocmd가 OSC 52로 system clipboard에 전달
   nmap <D-c> yy
   vmap <D-c> y
   imap <D-c> <Esc>yyi

   " Paste
   map <D-v> <C-r>0
   imap <D-v> <C-r>0

   " Save
   map <D-s> :w!<cr>
   imap <D-s> :w!<cr>

   " paste latest yaned content
   nnoremap <space>pp  /<C-r>0
   " select all region
   nnoremap <leader>a  ggVG
"}}}
"}}}


"Plugin: 'ddrscott/vim-side-search'  {{{
   if get(g:, 'using_side_search', 0) == 1
      " --heading and --stats are required!
      let g:side_search_prg = 'ag --word-regexp' " --ignore='*.js.map'" " --heading --stats -B 1 -A 4"

      " Can use `vnew` or `new`
      let g:side_search_splitter = 'vnew'
      let g:side_search_split_pct = 0.3

      nnoremap <space>fd viwy:SideSearch <C-r>0

      " SideSearch current word and return to original window
      " nnoremap <Leader>ss :SideSearch <C-r><C-w><CR> | wincmd p
      " Create an shorter `SS` command
      " command! -complete=file -nargs=+ SS execute 'SideSearch <args>'

      " or command abbreviation
      " cabbrev SS SideSearch
   endif
"}}}

"Section: folding {{{
   set nofoldenable
"}}}


"Plugin: 'junegunn/vim-easy-align' {{{
   "https://github.com/junegunn/vim-easy-align
   "github flavored markdown table (keys ex: <Bslash>,<Bar>,<Enter>

   if get(g:, 'using_easy_align', 0) == 1
      vmap <Leader>==<Bar> :EasyAlign*<Bar><Enter>

      "Start interactive EasyAlign in visual mode (e.g. vipga)
      xmap <leader>== <Plug>(EasyAlign)

      " Start interactive EasyAlign for a motion/text object (e.g. gaip)
      nmap <leader>== <Plug>(EasyAlign)
   endif

"}}}

"Plugin: Colorizer {{{
   if get(g:, 'using_colorizer', 0) == 1

      " augroup ColorizerGroup
      "    autocmd!
      "    "버퍼를 읽어들일 때 색상표시
      "    autocmd BufRead,BufNewFile,BufNew * ColorHighlight
      " augroup END

      nnoremap <silent> <space>tc :ColorToggle<cr>
   endif
"}}}

"Plugin: Line Move {{{
   " A+k -- up
   " A+j -- down
   if get(g:, 'using_line_move', 0) == 1
      " Modifier for Normal Mode
      let g:move_key_modifier = 'A'

      " Modifier for Visual Mode
      let g:move_key_modifier_visualmode = 'A'
   endif
"}}}

"Section: Global Preferences {{{

   let mapleader='\'    " → Backspace를 <leader>로 선언

   "vim 스크립트에서 한글 주석이나 다국어 문자열을 사용할 때 필수
   " 선언 이후부터 나오는 문자열들에 적용됨 (스크립트 해석 시점 기준)
   scriptencoding utf-8

   set encoding=utf-8
   set fileencodings=utf-8

   " GIXER: 범용 인덱스/헤더 정렬 도구 (General Identifier Aligner)
   let s:tpx_root_dir = expand('<sfile>:p:h')
   let s:gixer_vim = s:tpx_root_dir . '/general-index-aligner.vim'
   if filereadable(s:gixer_vim)
      execute 'source' fnameescape(s:gixer_vim)

      function! s:GixerToggle(is_visual) abort
         if !exists(':GIXER') || !exists(':GIXERClear')
            echohl ErrorMsg
            echomsg 'GIXER: 커맨드를 찾을 수 없습니다. general-index-aligner.vim 로딩 여부를 확인해 주세요.'
            echohl None
            return
         endif

         if !exists('g:gixer_toggle_next_by_buf') || type(g:gixer_toggle_next_by_buf) != v:t_dict
            let g:gixer_toggle_next_by_buf = {}
         endif
         let l:buf = bufnr('%')
         let l:next = get(g:gixer_toggle_next_by_buf, l:buf, 'apply')

         if a:is_visual
            let l:l1 = line("'<")
            let l:l2 = line("'>")
            if l:next ==# 'apply'
               execute l:l1 . ',' . l:l2 . 'GIXER'
               let g:gixer_toggle_next_by_buf[l:buf] = 'clean'
            else
               execute l:l1 . ',' . l:l2 . 'GIXERClear'
               let g:gixer_toggle_next_by_buf[l:buf] = 'apply'
            endif
            return
         endif

         if l:next ==# 'apply'
            execute 'GIXER'
            let g:gixer_toggle_next_by_buf[l:buf] = 'clean'
         else
            execute 'GIXERClear'
            let g:gixer_toggle_next_by_buf[l:buf] = 'apply'
         endif
      endfunction

      augroup tpx_gixer
         autocmd!
         autocmd FileType markdown nnoremap <buffer> <leader>fg :GIXER<CR>
         autocmd FileType markdown vnoremap <buffer> <leader>fg :<C-u>'<,'>GIXER<CR>
         autocmd FileType markdown nnoremap <buffer> <leader>fc :GIXERClear<CR>
         autocmd FileType markdown vnoremap <buffer> <leader>fc :<C-u>'<,'>GIXERClear<CR>
         autocmd FileType markdown nnoremap <buffer> <leader><leader> :call <SID>GixerToggle(0)<CR>
         autocmd FileType markdown vnoremap <buffer> <leader><leader> :<C-u>call <SID>GixerToggle(1)<CR>
      augroup END
   endif

   set nobackup
   set termguicolors
   set backspace=indent,eol,start
   set number
   set showmatch
   set cmdheight=1
   set tabstop=3 " 3칸을 공백으로 띄움
   set softtabstop=3
   set shiftwidth=3
   set expandtab
   set autoindent
   set shiftround
   set history=1000
   set splitright
   set showcmd
   set showmode
   set matchtime=2
   set ambiwidth=single
   set clipboard+=unnamed
   set nospell
   set mouse=a
   " Set SGR mouse support if available, otherwise fall back to xterm2
   if has("mouse_sgr")
      set ttymouse=sgr
   else
      set ttymouse=xterm2
   endif

   set nolinebreak
   set breakindent
   set breakindentopt=shift:0,min:0,sbr
   " set showbreak=>>
   set wrap
   set textwidth=0
   set wrapmargin=0
   set ruler
   set smartindent

   set nowritebackup
   set swapfile
   set backupdir=/tmp
   set cursorline "<--> set nocursorline

   " 팝업 메뉴를 VSCode 처럼 보이기
   " [menu]
   " - 완성 메뉴(팝업)를 항상 표시한다.
	" - 완성 후보가 있어도 메뉴 없이 바로 삽입되지 않음.
	" - <C-n>, <C-p>, <C-x><C-o> 등에서 필수.
   " [menuone]
   " - 후보가 1개만 있어도 메뉴 표시
   " - 기본값에서는 1개면 자동 삽입되는데, 이걸 막고 메뉴로 보여줌
   " - Tab/Enter로 확인 후 선택 가능하게 만듦
   " [noselect]
	" - 메뉴 첫 번째 항목을 자동 선택(preselect)하지 않음
	" - 커서가 아무 항목도 선택하지 않은 상태로 시작
	" - 화살표키로 수동 선택 → Enter로 확정
	set completeopt=menu,menuone,noselect
	set shortmess+=c
   " 완성 메뉴 있을 때 Enter = 완성 선택/삽입
   " 없을 때 Enter = 새 줄
   inoremap <expr> <CR> pumvisible() ? "\<C-y>" : "\<CR>"

   " 줄 끝으로 커서 이동가능하게 (이렇게 설정하면, 줄 끝이 다 삭제되고 x 를 눌렀을 때 왼쪽으로 이동하지 않는다)
   " set virtualedit=onemore
   set virtualedit=

   " 파일 내용이 클 경우, 검색할 때 시간끄는 요인이 된다
   set hlsearch
   set incsearch
   set ignorecase
   set smartcase
   set wildmenu
   set wildmode=list:longest,full
   set directory=/tmp

   " Python Error List 에서 커서가 이동만해도 해당 코드 주변을 보여줌! (set cursorline 필요)
   "- :ptag {tag}: 태그(함수/변수 정의) 미리보기
   " -:pedit {file}: 파일 미리보기
   "- :psearch {pattern}: 패턴 검색 미리보기
   set previewwindow

   " 편집하는 파일이 있는 폴더위치로 작업폴더 위치를 자동으로 변경
   set autochdir

   " 수정된 버퍼를 저장하지 않아도 다른 버퍼로 전환하거나 새 파일을 열 수 있습니다. 수정된 내용은 메모리에 유지되며, 버퍼 목록에 남아 있습니다.
   set hidden

   " 탭제목에 경로제외하고 파일명만 표시
   let &titlestring = @%

   " 명령입력창 높이
   set cmdheight=1

   " 주의: literal path를 지정하지 않으면 오류가 난다 FZF 명령등에서 External Shell을 요구하므로 주의.
   set shell=bash

   "Section: expandtab {{{
      augroup ExpandTab
         autocmd!
            nnoremap <space>tp :set paste<cr>
            nnoremap <space>re :set expandtab<cr>:retab<cr>:set autoindent<cr>:set list lcs=trail:·,tab:»»,eol:¬,nbsp:·<cr>
      augroup END
   "}}}

   " 전역 변수(global variables)를 .viminfo 파일에 저장하도록 지정
   if has('nvim')
      set shada+=!
   else
      set viminfo+=!
   endif

   syntax on

   match ErrorMsg /\t/
   match ErrorMsg /\s\+$/
   syntax enable

   " 파워라인 심볼 (Powerline symbols): ⮂ ⮃ ⮀ ⮁ ⭤·»¬
   " 0: never, 1: if has more than 2 items, 2: always
   set laststatus=0

   " ctags 파일 참조위치를 편지중인 파일이 위치한 폴더에서 먼처 찾고 상위폴더로 옮겨가면서 찾는다 (need +autochdir)
   " 공백없이 comman(,)로 항목구분
   set tags=./tags;

   " timeout for for key combination (microseconds)
   set tm=1000

   " 커서위치의 단어 선택
   nnoremap <space>v viw

   " load ~/.vimrc
   nnoremap <space>fed :e $MYVIMRC<cr>

   " apply ~/.vimrc
   nnoremap <space>feR :mapclear<cr>:vmapclear<cr>:imapclear<cr>:source $MYVIMRC<cr>

   " force save
   nnoremap <space>ss :w!<cr>

   "quit current buffer
   nnoremap <silent><leader>q :q!<cr>
   nnoremap <silent><space>qq :q!<cr>

   "quit all buffer
   nnoremap <silent><leader>Q :qa!<cr>
   nnoremap <silent><space>qa :qa!<cr>
   nnoremap <space>r :r!


   if has('gui_running')
      set guifont=D2Coding:h15
   endif


   "공백문자 보임
   set ambiwidth=single

   "문법강조의 cchar까지 보이지 않게 함
   " set conceallevel=2
   " set list lcs=trail:·,tab:»»,eol:¬,nbsp:·
   " map <silent> <space>tw :set list lcs=trail:·,tab:»»,eol:¬,nbsp:·<cr>
   " map <silent> <space>tW :set nolist<cr>

   map <silent> <space>tw :call ToggleListChars()<cr>
   function! ToggleListChars()
      if exists('b:list_chars')
         echo "hide white characters"
         execute ':set nolist'
         unlet b:list_chars
      else
         echo "show white characters"
         execute ':set list lcs=trail:·,tab:»»,eol:¬,nbsp:·'
         let b:list_chars = 1
      endif
   endfunction


   " 탭문자를 오류로 나타냄
   " https://vi.stackexchange.com/a/9353/3168
   match Error /\t/

   " 문장 끝 공백을 오류로 표시
   match Error /\s\+$/

   " JSON에서 일부 문자를 conceal(숨김 또는 강조) 처리를 끔.
   " double-quote, colon, comma, and curly braces등을 강조하지 못하게 함.
   let g:vim_json_syntax_conceal = 0
   let g:vim_json_conceal = 0
   set conceallevel=0


   " workaround for 'Nothing in register *'
   " VIM 안에서 선택한 내용을 시스템 클립보드로 복사 (vim --info --> +clipborad 있어야 함)
   if $TMUX == ''
      set clipboard+=unnamed
   endif

   "Section: Clickable {{{
      " Send more characters for redraws
      set ttyfast
      " Enable mouse use in all modes
      set mouse=a

      "타이핑하는 동안 마우스 숨김
      set mousehide

      " Enable mouse click & drag support in iTerm2 Vim
      " iTerm2 settings -> Profiles -> Terminal -> Mouse Reporting (enable)
      " iTerm2 settings -> Profiles -> Terminal -> Mouse Reporting -> Report Mouse Wheel Events (off)
      " iTerm2 settings -> Profiles -> Terminal -> Mouse Reporting -> Report Mouse clicks & drags (on)
      " iTerm2 settings -> Profiles -> Terminal -> Mouse Reporting -> Terminal may enable alternate mouse scroll (on)
      if has("mouse_sgr")
         set ttymouse=sgr
      endif
   "}}}

   "Seciont: 탭제목에 전체 경로표시할 떄 {{{
      "let &titlestring = expand('%:p')
      set title
      set titleold=''
   "}}}

   "Section: 이탤릭 코멘트 {{{
      ".vim/terminfo/xterm-256color-italic.terminfo
      if &term=~ 'xterm-256color-italic'
            set t_ZH=[3m
            set t_ZR=[23m
            "highlight Comment font=Anonymous_Pro:h13
            highlight Comment cterm=italic
            highlight Comment ctermfg=240 guifg=#aaaaaa
            highlight Comment gui=italic
      endif
   "}}}

   " auto-indent 때문에 복사할 때 계단현상이 발생하는 것을 방지
   "Section: bracketed paste mode {{{
      if &term =~ "screen" || &term =~ "tmux" || &term =~ "xterm"
         let &t_BE = "\e[?2004h"
         let &t_BD = "\e[?2004l"
         let &t_PS = "\e[200~"
         let &t_PE = "\e[201~"
      endif
   "}}}

   "Section: 스펠 검사 (disable builtin feature) {{{
      set spelllang=en
      set nospell
      set novisualbell
      set noerrorbells
      set magic
   "}}}

   "Section: CursorLine 현재줄 강조색상 지정 (current line) {{{
      " set ctermbg & ctermbg to NONE ==> transparent
      " ctermfg ==> 문자열의 색상을 변경
      highlight CursorLine     cterm=NONE ctermbg=17 ctermfg=NONE
      highlight CursorColumn   cterm=NONE ctermbg=52 ctermfg=NONE
      " toggle column bar
      nnoremap <leader>\| :set cursorcolumn!<cr>

   "}}}

   "Section: block shift {{{
      "https://vim.fandom.com/wiki/Shifting_blocks_visually
      "블록을 움직이고 난 뒤에도 여전히 선택영역이 유지됨
      vnoremap > >gv
      vnoremap < <gv
      " ↓ 명령상태에서 탭 적용
      nnoremap <Tab> >>_
      nnoremap <S-Tab> <<_
      inoremap <S-Tab> <C-D>
      vnoremap <Tab> >gv
      vnoremap <S-Tab> <gv
   "}}}

   "Section:특정 문자열 강조 {{{
      augroup highlight_keyword
         ":highlight<cr> 명령의 결과로 나오는 목록에서 선택
         autocmd!
         autocmd WinEnter,VimEnter * :silent! call matchadd('Todo', 'TODO', -1)
         autocmd WinEnter,VimEnter * :silent! call matchadd('DiffText', 'NOTE\|INFO', -1)
         autocmd WinEnter,VimEnter * :silent! call matchadd('DiffAdd', 'Plugin:\|Section:', -1)
         autocmd WinEnter,VimEnter * :silent! call matchadd('WildMenu', 'WARN', -1)
         autocmd WinEnter,VimEnter * :silent! call matchadd('ErrorMsg', 'FIXME', -1)
      augroup END
   "}}}

   "Section:선택영역 색상 {{{
      highlight Visual term=bold,reverse cterm=bold ctermfg=0 ctermbg=121 gui=bold guifg=bg guibg=LightGreen
   "}}}

   "Section: Comments (not finished) {{{
      augroup commentgroup
         autocmd FileType c,cpp,java,scala let b:comment_char = '//'
         autocmd FileType sh,ruby,python   let b:comment_char = '#'
         autocmd FileType conf,fstab       let b:comment_char = '#'
         autocmd FileType tex              let b:comment_char = '%'
         autocmd FileType mail             let b:comment_char = '>'
         autocmd FileType vim              let b:comment_char = '"'
      augroup END

      "Ctrl-/ to comment
      function! SetComments()
         if !exists('b:comment_char')
            let b:comment_char = '#'
         endif
         let comment_cmd = 'map <silent><C-_>   I' . b:comment_char . ' <esc><esc>'
         execute comment_cmd
      endfunction
      call SetComments()
   "}}}


   " 검색 단어 제거 & 클립보드에 복사된 내용 찾기
   "Section: searching {{{
      "clear searching mark
      nnoremap <silent><leader>/ :let @/=''<cr>

      "searching with yanked text
      nnoremap <silent><space>/  /<C-R>0<cr>
   "}}}

   "Section:  Plug 'andrwj/vim-oscyank',{{{
      let g:oscyank_max_length = 0  " maximum length of a selection, 0 for unlimited length
      let g:oscyank_silent     = 0  " disable message on successful copy
      let g:oscyank_trim       = 0  " trim surrounding whitespaces before copy
      let g:oscyank_osc52      = "\x1b]52;c;%s\x07"  " the OSC52 format string to use
      nmap <space>y <Plug>OSCYankOperator
      nmap <space>yy <leader>c_
      vmap <space>y <Plug>OSCYankVisual

      " [T144] Vim yank → TMUX → system clipboard 자동 연동
      " y(yank) 실행 시 OSC 52 escape sequence를 통해 자동으로 system clipboard에 복사합니다.
      " TMUX의 set-clipboard on 설정과 연동하여 동작합니다.
      augroup OscYankOnYank
         autocmd!
         autocmd TextYankPost * if v:event.operator is 'y' | call OSCYankRegister('"') | endif
      augroup END
   "}}}

"}}}

"Section: Document (디버깅 방법) {{{
   " '#'은 숫자:
   " vim file -V#vim-error.log
"}}}

"Section: Vimscript Cheatsheet {{{
   " https://github.com/johngrib/vimscript-cheatsheet
   " g: - Global.
   " l: - Local to a function.
   " s: - Local to a script file.
   " a: - Function argument (only inside a function).
   " v: - Global, predefined by Vim.
   " b: - Local to the current buffer.
   " w: - Local to the current window.
   " t: - Local to the current tab page.
"}}}

" -------------------------------------------------------------------------------

"Loading Plugins: {{{
   "Plug 'kovisoft/paredit',               { 'for': ['clojure', 'scheme', 'lisp'] }
   "Plug 'gorkunov/smartpairs.vim'         " press v .. v.. v .. and it extends selection
   "Plug 'sheerun/vim-polyglot'

   "Plug 'pacha/vem-tabline'
   "Plug 'edkolev/promptline.vim'
   "Plug 'mattn/emmet-vim'                "https://github.com/mattn/emmet-vim
   "Plug 'mklabs/grunt.vim'               "https://github.com/mklabs/grunt.vim
   "Plug 'tpope/vim-scriptease'           "https://github.com/tpope/vim-scriptease
   "Plug 'xolox/vim-misc'                 "required by vim-notes.git
   "Plug 'xolox/vim-notes.git'
   "Plug 'othree/eregex.vim'
   "Plug 'terryma/vim-expand-region'      "그닥 효과적인지 모르겠다..
   "Plug 'mattn/flappyvird-vim'
   "Plug 'idanarye/vim-merginal'          "manage Git branches
   "Plug  'zoeesilcock/vim-caniuse'
   "Plug 'gilligan/vim-lldb'
   "Plug 'junegunn/seoul256.vim'
   "Plug 'sk1418/HowMuch'                 "수식계산
   "Plug 'drmikehenry/vim-fixkey/'        "매크로와 같이 쓸때 주의
   "Plug 'Raimondi/delimitMate'
   "Plug 'SirVer/ultisnips'
   "Plug 'benmills/vimux.git'             "Interactive with tmux
   "Plug 'fatih/vim-go'
   "Plug 'fatih/molokai'
   "Plug 'gregsexton/gitv'
   "Plug 'groenewege/vim-less'
   "Plug 'honza/vim-snippets'
   "Plug 'tyrannicaltoucan/vim-quantum'    "A color scheme based on Google's Material Design palette.
   "Plug 'HerringtonDarkholme/yats.vim',   { 'for': ['typescript', 'javascript'] }     "Most Advanced TypeScript Syntax highlighting plugin

   "Plug 'jreybert/vimagit',               { 'on': ['Magit', 'MagitOnly'] }
   "Plug 'tpope/vim-haml'                 "Vim runtime files for Haml, Sass, and SCSS
   "Plug 'tpope/vim-repeat'
   "Plug 'tpope/vim-surround.git'         "문장/구절을 둘러싼 인용부호를 바꿈: cs
   "Plug 'guns/xterm-color-table.vim'
   "Plug 'duff/vim-scratch'               "Scratch buffer
   "Plug 'mhinz/vim-startify'
   "Plug 'Rykka/clickable.vim'            "riv plugin
   "Plug 'ekalinin/Dockerfile.vim'

   " b로 시작하는 커스톰 단축키가 많아서(markology 패키지)  bookmark 패키지의 기본 바인딩을 금지해야한다
   "let g:bookmark_no_default_key_mappings = 1
   "Plug 'MattesGroeger/vim-bookmarks'     " do not make lazy loading!  This plugin is needed at the begining

   "Plug 'editorconfig/editorconfig-vim'

   "Plug 'ddrscott/vim-side-search',       { 'on': ['SideSearch'] }

   "Plug 'danilamihailov/vim-tips-wiki'

   "Plug 'wellle/tmux-complete.vim'

   " ctags 버전에 따라 CPU를 태운다...
   " if executable('ctags')
   "    Plug 'prabirshrestha/asyncomplete-tags.vim'
   "    Plug 'ludovicchabant/vim-gutentags'
   " endif
   "

   " 스펠체킹 및 수정 & 제안
   " Plug 'kamykn/spelunker.vim'

   " 별로 사용하질 않는다
   " if has('python3') && has('timers')
   "    Plug 'AlphaMycelium/pathfinder.vim'
   " endif

   " 화면분할+터미널 열기
   "Plug 'vimlab/split-term.vim'
   "Plug 'skywind3000/vim-quickui'

   " GeoVIM: Tab 상태 저장/복구
   " Plug 'tpope/vim-obsession'

   "Plug 'pechorin/any-jump.vim'


   "call plug#end()
" }}}

"Plugin: ctrlp {{{
   "<c-f>, <c-b> -- cycle between modes
   "<c-d> -- switch to filename on search instead of full path
   "<c-r> -- regex mode
   "<c-j>, <c-k> -- arrow keys to move
   "<c-t>, <c-v>, <c-x> -- open selected file
   "<c-n>, <c-p> -- to select the next/previous string in the prompt's history
   "<c-y>  -- to create a new file and its parent directories.
   "<c-z> o mark/unmark multiple files and <c-o> to open them
   ".. to go up
   ":25 to jum to line 25

   " let g:ctrlp_switch_buffer = 'et'
   "   "t - in a new tab.
   "   "h - in a new horizontal split.
   "   "v - in a new vertical split.
   "   "r - in the current window.
"    let g:ctrlp_working_path_mode='t'
"    " ↓ MacOSX/Linux
"    set wildignore+=*/tmp/*,*.so,*.swp,*.zip
"    let g:ctrlp_show_hidden = 1
"    let g:ctrlp_regexp = 1
"    let g:ctrlp_use_caching = 1
"    let g:ctrlp_clear_cache_on_exit = 0
"    let g:ctrlp_root_markers = ['.git', '.projectile', '.project']
"    let g:ctrlp_follow_symlinks = 1
"    let g:ctrlp_open_new_file = 't'
"    let g:ctrlp_follow_symlinks = 1
"    let g:ctrlp_max_files = 4096
"    let g:ctrlp_max_height = 50
"    let g:ctrlp_max_history = 10
"    let g:ctrlp_show_hidden = 1
"    let g:ctrlp_map = '<c-p>'
"    let g:ctrlp_cmd = 'CtrlPag'
"    let g:ctrlp_extensions = ['ag', 'line', 'funky', 'tag', 'dir' ]
"    let g:ctrlp_user_command = 'ag -l --nocolor -U --ignore-dir .git --ignore-dir .log --ignore-dir node_modules --ignore-dir build --ignore "**.min.js" --ignore "**.min.*"  %s'
"    let g:ctrlp_user_command = 'rg --vimgrep -S -g "*.min.js" -g "!.log" -g "!node_modules" -g "!build" -g "!*.min.*" %s'
"    let g:ctrlp_custom_ignore = '\v[\/]\.(git|hg|svn|node_modules|idea|log|swap|DS_Store)$,*.min.,js'
"    "let g:ctrlp_user_command = 'fd --type f --color never "" %s'

" "
"    if executable('ag')
"       let g:ctrlp_ag_timeout = 5
"       " ↓ 기본값은 PWD
"       " let g:ctrlp_ag_search_base = 'current-file-dir'
"      let g:ctrlp_ag_ignores = '--ignore .git
"          \ --ignore "deps/*"
"          \ --ignore "build/*"
"          \ --ignore ".idea/*"
"          \ --ignore ".log/*"
"          \ --ignore "jquery*.min.js"
"          \ --ignore "*.min.js"
"          \ --ignore "node_modules/*"'

"      "파일 및 컨텐트 찾기
"      nnoremap <space><Bslash><Bslash> :CtrlPag<cr>

"      "VisualBlock을 잡았을 때, 선택영역을 포함한 파일을 찾음
"      vnoremap <space><Bslash>v  :CtrlPagVisual<cr>

"      "이전 검색결과에서 찾기
"      let g:fzf_mru_relative = 0
"      let g:fzf_mru_no_sort = 0
"      nnoremap <space>fh  :FZFMru<cr>
"      nnoremap <space>fH  :FZFMru
"      nnoremap <space>fs  :Rg
"    endif

"      " let g:ctrlp_user_command = {
"      "    \ 'types': {
"      "        \ 1: ['.git', 'cd %s && git ls-files . -co --exclude-standard', 'find %s -type f'],
"      "        \ },
"      "    \ 'fallback': 'find %s -type f'
"      "    \ }

"    "let g:ctrlp_funky_matchtype = 'path'
"    let g:ctrlp_funky_syntax_highlight = 1
" "
" "     " CtrlP auto cache clearing.
" "     " ----------------------------------------------------------------------------
"    function! SetupCtrlP()
"    if exists('g:loaded_ctrlp') && g:loaded_ctrlp
"       augroup CtrlPExtension
"          autocmd!
"          autocmd FocusGained  * CtrlPClearCache
"          autocmd BufWritePost * CtrlPClearCache
"       augroup END
"    endif
"    endfunction
"    if has('autocmd')
"       autocmd VimEnter * :call SetupCtrlP()
"    endif
" " }}}

"Plugin: Spelling  (kamykn/spelunker.vim) {{{
"    set nospell

"    let g:enable_spelunker_vim = 1

"    " Enable spelunker.vim on readonly files or buffer. (default: 0)
"    let g:enable_spelunker_vim_on_readonly = 0

"    " Check spelling for words longer than set characters. (default: 4)
"    let g:spelunker_target_min_char_len = 4

"    " Max amount of word suggestions. (default: 15)
"    let g:spelunker_max_suggest_words = 7

"    " Max amount of highlighted words in buffer. (default: 100)
"    let g:spelunker_max_hi_words_each_buf = 100

"    " Spellcheck type: (default: 1)
"    " 1: 파일 열때나 저장할 때 검사 (큰 파일은 시간 소요)
"    " 2: Spellcheck displayed words in buffer. Fast and dynamic. The waiting time
"    " depends on the setting of CursorHold `set updatetime=1000`.
"    let g:spelunker_check_type = 2

"    " Highlight type: (default: 1)
"    " 1: Highlight all types (SpellBad, SpellCap, SpellRare, SpellLocal).
"    " 2: Highlight only SpellBad.
"    " FYI: https://vim-jp.org/vimdoc-en/spell.html#spell-quickstart
"    let g:spelunker_highlight_type = 1

"    " Option to disable word checking.
"    " Disable URI checking. (default: 0)
"    let g:spelunker_disable_uri_checking = 1

"    " Disable checking words in backtick/backquote. (default: 0)
"    let g:spelunker_disable_backquoted_checking = 0

"    " Disable default autogroup. (default: 0)
"    let g:spelunker_disable_auto_group = 1

" " Create own custom autogroup to enable spelunker.vim for specific filetypes.
"    augroup spelunker
"       autocmd!
"       " Setting for g:spelunker_check_type = 1:
"       " autocmd BufWinEnter,BufWritePost *.vim,*.js,*.jsx,*.json,*.md call spelunker#check()
"       " Setting for g:spelunker_check_type = 2:
"       " autocmd CursorHold *.vim,*.js,*.jsx,*.json,*.md call spelunker#check_displayed_words()
"    augroup END

"    " Override highlight group name of incorrectly spelled words. (default:
"    " 'SpelunkerSpellBad')
"    let g:spelunker_spell_bad_group = 'SpelunkerSpellBad'

"    " Override highlight group name of complex or compound words. (default:
"    " 'SpelunkerComplexOrCompoundWord')
"    let g:spelunker_complex_or_compound_word_group = 'SpelunkerComplexOrCompoundWord'

"    " Override highlight setting.
"    highlight SpelunkerSpellBad cterm=underline ctermfg=247 gui=underline guifg=#9e9e9e
"    highlight SpelunkerComplexOrCompoundWord cterm=underline ctermfg=NONE gui=underline guifg=NONE
" "}}}

" "Plugin:  gives suggestions to improve my movements ( AlphaMycelium/pathfinder.vim ) {{{
"    "If you set g:pf_autorun_delay to a negative value, you get two commands instead:
"    ":PathfinderBegin: Set the start position. This still happens automatically when switching windows/tabs, or loading a new file.
"    ":PathfinderRun: Set the target position and get a suggestion.
"    let g:pf_autorun_delay = -1

"}}}

"Section Profiling {{{
   ":profile start profile.log
   ":profile func *
   ":profile file *
   " At this point do slow actions
   ":profile pause
   ":noautocmd qall!
"}}}

"Section: Guide  {{{
   "  https://simianwesthighlandterrier.htmlpasta.com/
"{{{

"Section: 현재 문자의 ASCII 코드값을 상태바에 표시하가 {{{
   " set statusline+=%b\ 0x%B
"}}}

"Section: convert Tab to Space {{{
   "https://vim.fandom.com/wiki/Super_retab
   "첫컬럼의 문자가 탭인경우에만 적용됨
   " :command! -range=% -nargs=0 Tab2Space execute '<line1>,<line2>s#^\t\+#\=repeat(" ", len(submatch(0))*' . &ts . ')'
"}}}

"Section: enable Vi-mode in console {{{
   "To enable Vi-mode, edit (or create) the file ~/.inputrc or /etc/inputrc and add the following lines:
   "set editing-mode vi
   "set keymap vi-command
"}}}

"Plugin: vim-tmux-clipboard {{{
   "add set -g focus-events on to your tmux.conf.
"}}}

"Plugin: brglng/vim-im-select {{{
   " install: curl -Ls https://raw.githubusercontent.com/daipeihust/im-select/master/install_mac.sh | sh
   " let g:im_select_command = "/usr/local/bin/im-select"

"}}}

"Plugin: 'majutsushi/tagbar' {{{
   " brew install --HEAD universal-ctags/universal-ctags/universal-ctags
   " brew install ctags-exuberant
   " let g:tagbar_ctags_bin="/usr/local/bin/ctags"
   " nmap <space>tt :TagbarToggle<cr>
   " source ~/Develops/Vim/tagbar.vim
"}}}

"Section: NeoVIM Host {{{
   " npm install -g neovim
   " pyenv install 3.7.7
   " pyenv virtualenv 3.4.4 py3nvim
   " pyenv activate py3nvim
   " pip3 install pynvim
   " brew install cpanminus
   " cpanm Neovim::Ext

   " let g:python2_host_prog="`pyenv root`/shims/python2"
   " let g:python3_host_prog="`pyenv root`/shims/python3"

   " disable
   " let g:loaded_python_provider=0
   " enable
   " let g:loaded_python3_provider=0
"}}}

"Plugin: 'HerringtonDarkholme/yats.vim'  {{{
   "turn off old regex engine
   " set re=0
"}}}

"Section: Jump to Definition {{{
   "gd: to local declaration
   "gD: to global declaration
   "g*: search for the word under the cursor
   "g#: same as g* but in backward direction
   "gg: goes to the first line in the buffer
   "G : goest to the last line
   "gf: go to the file under the cursor
   "g]: jump to a tag definition
"}}}
