"# Vimproved
set nocompatible

"# Buffer
set hidden

set encoding=utf-8

set autoread
autocmd FocusGained,BufEnter * :silent!<space>!

"# Aparência e som
try
  colorscheme calmo
catch
  colorscheme blue
endtry

set background=dark
set t_Co=256
set termguicolors
set noerrorbells novisualbell t_vb=
set belloff=all
set conceallevel=2

"# Comportamento
syntax on

filetype plugin indent on
set showmatch
set showmode
set showcmd
set autoindent
set mouse=
set linebreak
set nocursorcolumn nocursorline
set number norelativenumber
set nrformats-=octal
set lazyredraw
set nobackup
set noswapfile
set scrolloff=3
set clipboard^=unnamedplus,unnamed
set colorcolumn=
set backspace=indent,eol,start
set formatoptions+=jcr
set hlsearch
set incsearch
set ignorecase
set nosmartcase
set noemoji
if !has('nvim')
  set renderoptions=
else
  set modelineexpr
endif
set modeline
set modelines=5
set tabstop=4
set softtabstop=4
set shiftwidth=4
set smarttab
set expandtab
set fillchars=vert:,fold:
set foldlevelstart=99

let g:html_dynamic_folds=1
let g:html_prevent_copy = "fntd"

let g:netrw_liststyle=3
let g:netrw_bufsettings = 'noma nomod nu nobl nowrap ro'
set shellslash

"## Autocomplete
set wildmenu
set shortmess+=c
set wildcharm=<tab>
set completeopt=menuone,noinsert,noselect

set wildignore=.git,.git/**
set wildignore+=.svn,.svn/**
set wildignore+=.idea,.idea/**
set wildignore+=node_modules,node_modules/**
set wildignore+=.venv,*/*_cache/*
set wildignore+=dist,dist/**
set wildignore+=target,target/**
set wildignore+=build,build/**
set wildignore+=vendor,vendor/**
set wildignore+=assets,assets/**
set wildignore+=ios,ios/**
set wildignore+=android,android/**
set wildignore+=_site,_site/**
set wildignore+=public,public/**
set wildignore+=*/coverage,*/coverage/**
set wildignore+=*/_reports,*/_reports/**
set wildignore+=*/_gen
set wildignore+=DS_Store,DS_Store/**
set wildignore+=tags
set wildignore+=.next
set wildignore+=index.wiki

set wildignorecase

set complete=.,k,w,t

set tags=tags

set omnifunc=syntaxcomplete#Complete

"# Statusline
set laststatus=2

set statusline=
set statusline+=\ %{expand('%:~:.')}\ %r\%m
set statusline+=\%=
set statusline+=\ %p%%\ %l:\%c
set statusline+=\ %y

"# Funções
function! NN_ctags()
  let s:ctags_command="ctags" .
        \ " -R --totals" .
        \ " --exclude=.git --exclude=.svn" .
        \ " --exclude=vendor --exclude=_*" .
        \ " --exclude=*_cache" .
        \ " --exclude=node_modules --exclude=dist --exclude=build --exclude=ios --exclude=android" .
        \ " --exclude=_site" .
        \ " --php-kinds=cfvit" .
        \ " --python-kinds=-i" .
        \ " --languages=php,javascript,python"

  if filereadable(expand(".ctags"))
    let s:ctags_command.=" --options=.ctags"
  endif

  let s:ctags_command.=" ."

  execute "!".s:ctags_command
endfun

function! NN_EmojiToggle()
  if !has('nvim')
    if &renderoptions == ""
      set renderoptions=type:directx,gamma:1.0,contrast:0.1,level:1.0,geom:1,renmode:5,taamode:1
    else
      set renderoptions=
    endif
  endif
endfun

function! NN_SetGitDir()
  cd %:p:h
  let gitdir=system("git rev-parse --show-toplevel")
  let isnotgitdir=matchstr(gitdir, '^fatal:.*')
  if empty(isnotgitdir)
    cd `=gitdir`
  endif
endfunction

function! NN_Lexplorer()
  call NN_SetGitDir()
  Lexplore
endfunction

function! NN_Tasks()
  call NN_SetGitDir()
  vimgrep /\C\<TODO\>\|\C\<FIXME\>/j **
  copen
endfunction

function! NN_GitAula()
  let log = system("git log --pretty=format:\%s")
  vnew
  put=log
  normal! gg
  if search('^:tv: add aula')>0
    normal! 3W
    let s:numero_aula = expand('<cword>')+1
    echom system("git add -A && git commit -m \":tv: add aula ".s:numero_aula."\"")
  else
    echom system("git add -A && git commit -m \":tv: add aula 1\"")
  endif
  bdelete!
endfunction

function! s:ToggleComment()
  if getline('.') =~ "^\\s*$"
    return
  endif

  let commentstrings = split(&commentstring, ',')

  " handle multiple uncomments formats
  for commentstring in commentstrings
    let [comment_leader1, comment_leader2] = split(commentstring, '%s', 1)
    let comment_leader1 = substitute(comment_leader1, ' ', '', 'g')
    let comment_leader2 = substitute(comment_leader2, ' ', '', 'g')
    if getline('.') =~ "^\\s*" . comment_leader1
      call setline('.', substitute(getline('.'), "^\\(\\s*\\)" . comment_leader1 . "\\(\\s*\\)", "\\1", 'g'))
      call setline('.', substitute(getline('.'), "\\(\\s*\\)" . comment_leader2 . "\\(\\s*\\)$", "", 'g'))
      return
    end
  endfor

  " Comment
  let first_commentstring = commentstrings[0]
  let [comment_leader1, comment_leader2] = split(first_commentstring, '%s', 1)
  call setline('.', substitute(getline('.'), "^\\(\\s*\\)", "\\1" . comment_leader1, 'g'))
  call setline('.', substitute(getline('.'), "$", "\\1" . comment_leader2, 'g'))
endfunction

function! s:FechaOuDeletaBuffer()
  if tabpagenr('$') > 1 || winnr('$') > 1
    close
  else
    bd!
  endif
endfunction

function! s:AutoCompleteCarinhas()
  call complete(col('.'), [
        \ 'ಥ_ಥ',
        \ 'ლ(ಠ益ಠლ)',
        \ 'ಠ╭╮ಠ',
        \ '(╯°□°)╯︵ ʞooqǝɔɐɟ',
        \ '(╯°□°)╯︵ ┻━┻',
        \ '(╮°-°)╮┳━┳',
        \ '( ͡° ͜ʖ ͡°)',
        \ '¯\_(ツ)_/¯',
        \ '(~˘▾˘)~',
        \ 'ᕦ(ò_óˇ)ᕤ',
        \ '༼ つ ◕_◕ ༽つ',
        \])
  return ''
endfunction

"## Fold
function! s:FoldTextLikeMarkdown(comment, qtdcharamaisquehash)
  let lines_count = v:foldend - v:foldstart + 1
  let lines_count_text = '┤' . printf("%4s", lines_count) . '├'
  let foldchar = matchstr(&fillchars, 'fold:\zs.')
  let titulo = substitute(getline(v:foldstart),a:comment,"",'g')
  let titulo = substitute(titulo,"\#","",'g')
  let foldtextstart = repeat(foldchar, v:foldlevel + a:qtdcharamaisquehash) . titulo
  let foldtextend = lines_count_text . repeat(foldchar, 8)
  let foldtextlength = strlen(substitute(foldtextstart . foldtextend, '.', 'x', 'g')) + &foldcolumn
  return foldtextstart  . ' ' . repeat(foldchar, winwidth(0)-foldtextlength) . foldtextend
endfunction

function! s:FoldExprLikeMarkdown(firstcomment)
  let line = getline(v:lnum)
  if line =~ a:firstcomment.' .*$'
    return ">1"
  endif
  if line =~ a:firstcomment.'# .*$'
    return ">2"
  endif
  if line =~ a:firstcomment.'## .*$'
    return ">3"
  endif
  if line =~ a:firstcomment.'### .*$'
    return ">4"
  endif
  if line =~ a:firstcomment.'#### .*$'
    return ">5"
  endif
  return "="
endfunction

function! FoldTextMarkdown()
  return s:FoldTextLikeMarkdown("", 1)
endfunction

function! FoldExprMarkdown()
  return s:FoldExprLikeMarkdown("^##")
endfunction

function! FoldTextVim()
  return s:FoldTextLikeMarkdown("^\"", 1)
endfunction

function! FoldExprVim()
  return s:FoldExprLikeMarkdown('^"#')
endfunction

function! FoldTextLua()
  return s:FoldTextLikeMarkdown("^\-\-", 2)
endfunction

function! FoldExprLua()
  return s:FoldExprLikeMarkdown('^\-\-#')
endfunction

"# Comandos
command! -nargs=* Cake make! <args> | cw
command! -nargs=* Lake make! <args> | cw

command! BufOnly execute 'kb|%bdelete|e #|b#|bd%|normal `b'

command YankFullPathWorkDir let @+ = getcwd()
command YankFullPathFile let @+ = expand("%:p")
command YankRelativePathFile let @+ = expand('%:~:.')

"# Mapeamentos
let mapleader="\<space>"

nnoremap    <leader><leader>    :w<CR>
nnoremap    <leader><CR>        :call NN_Lexplorer()<CR>
nnoremap    <leader>/           :noh<CR>
nnoremap    <leader>.           :pwd<CR>
nnoremap    <leader>df          :call <SID>FechaOuDeletaBuffer()<CR>
nnoremap    <leader>ds          :on<CR>|" fecha todas splits exceto atual
nnoremap    <leader>j           <c-w>w|" estilo DWM
nnoremap    <leader>k           <c-w>W|" estilo DWM
nnoremap    <leader>n           :call NN_<c-d>|" funções pessoais
vnoremap    <leader>n           :call NN_<c-d>|" funções pessoais
vnoremap    <leader>p           "_dP
nnoremap    <expr><leader>q     empty(filter(getwininfo(), 'v:val.quickfix')) ? ":cope<CR>" : ":ccl<CR>"|" toggle quickfix
nnoremap    <expr><leader>l     empty(filter(getwininfo(), 'v:val.loclist')) ? ":lope<CR>" : ":lcl<CR>"|" toggle location-list
nnoremap    <leader>s           :split<CR>
nnoremap    <leader>t           :tab split<CR>
nnoremap    <leader>v           :vsplit<CR>
nnoremap    <leader>y           my^vg_"+y:echo "Copiado!!"<CR>
vnoremap    <leader>y           "+y:echo "Copiado!!"<CR>
nnoremap    <leader>z           za

nnoremap    <expr><leader>0    &diff ? ":diffoff<CR>" : ":diffthis<CR>"
nnoremap    <expr><leader>1    &diff ? ":diffget _LOCAL_<CR>" : ":diffthis<CR>:diffget _LOCAL_<CR>:diffoff<CR>"
nnoremap    <expr><leader>2    &diff ? ":diffget _BASE_<CR>" : ":diffthis<CR>:diffget _BASE_<CR>:diffoff<CR>"
nnoremap    <expr><leader>3    &diff ? ":diffget _REMOTE_<CR>" : ":diffthis<CR>:diffget _REMOTE_<CR>:diffoff<CR>"

nnoremap    !!          :!!<CR>|" repete ultimo :!comando
nnoremap    #           :b #<CR>|" FIXME volta para unlisted buffer tbm
vnoremap    <           <gv|" mantêm select após indentação
vnoremap    >           >gv|" mantêm select após indentação
nnoremap    gc          :call <SID>ToggleComment()<CR>
vnoremap    gc          :call <SID>ToggleComment()<CR>
vnoremap    J           :m '>+1<CR>gv=gv|" move linha selecionada pra baixo
vnoremap    K           :m '<-2<CR>gv=gv|" move linha selecionada pra cima
inoremap    kj          <esc>|" esc mais fácil
vnoremap    a'          "ac'<c-r>a'|" surround match
vnoremap    a"          "ac"<c-r>a"|" surround match
vnoremap    a(          "ac(<c-r>a)|" surround match
vnoremap    a{          "ac{<c-r>a}|" surround match
vnoremap    a[          "ac[<c-r>a]|" surround match
nnoremap    n           nzzzv|" centraliza match do search
nnoremap    N           Nzzzv|" centraliza match do search
nnoremap    Q           @q
nnoremap    q:          <nop>
nnoremap    Y           Vy
tnoremap    <esc>       <C-\><C-n>
noremap     \           za|" toggle fold
nnoremap    <expr><f2>  &foldlevel ? 'zM' :'zR'|" toggle fold todo arquivo
noremap     <up>        <nop>|" força hjkl
noremap     <down>      <nop>|" força hjkl
noremap     <left>      <nop>|" força hjkl
noremap     <right>     <nop>|" força hjkl
inoremap    <up>        <nop>|" força hjkl
inoremap    <down>      <nop>|" força hjkl
inoremap    <left>      <nop>|" força hjkl
inoremap    <right>     <nop>|" força hjkl
nnoremap    <c-\>       <c-]>|" teclado brasileiro <c-]> não funciona para tag jump
inoremap    <c-a>       <C-O>yiW<End>=<C-R>=<C-R>0<CR>|" calculadora - tip 73 https://vim.fandom.com/wiki/Vim_Tips_Wiki:Imported_tips
inoremap    <c-h>       <left>|" força hjkl
cnoremap    <c-h>       <left>|" força hjkl
cnoremap    <c-l>       <right>|" força hjkl
inoremap    <c-l>       <right>|" força hjkl
tnoremap    <c-l>       cls<CR>|" limpa terminal Windows
nnoremap    <c-n>       yiwV|" substitue multi cursors
xnoremap    <c-n>       :s/<c-r><c-*>//g<left><left>|" substitue multi cursors
nnoremap    <c-s>       mi<esc>gg=G`i|" indenta todo o arquivo
nnoremap    <c-q>       q:
nnoremap    <c-t>       :tj <c-r><c-w><CR>|" goto definition (tag jump do ctags)
nnoremap    <c-z>       <nop>
inoremap    <c-z>       <c-r>=<SID>AutoCompleteCarinhas()<CR>
tnoremap    <s-insert>  <c-w>"*
tnoremap    <c-s-v>     <c-w>"*

"# Abreviações
cnoreabbrev W! w!
cnoreabbrev Q! q!
cnoreabbrev Qa! qa!
cnoreabbrev QA! qa!
cnoreabbrev Wq wq
cnoreabbrev Wa wa
cnoreabbrev wQ wq
cnoreabbrev WQ wq
cnoreabbrev W w
cnoreabbrev Q q
cnoreabbrev Qa qa
cnoreabbrev QA qa
cnoreabbrev Wqa wqa
cnoreabbrev WQa wqa
cnoreabbrev WQA wqa
cnoreabbrev wQA wqa
cnoreabbrev wqA wqa
cnoreabbrev wQa wqa

"# AutoCmds
" FIXME Como colocar definição de filetype em ftdetect?
augroup filetype_detect
  au!
  au BufRead,BufNewFile *.phtml setfiletype html
  au BufRead,BufNewFile *.gv setfiletype dot
  au BufRead,BufNewFile *.todone setfiletype todone
  au BufRead,BufNewFile neni.* set buftype=nofile
augrou END

augroup commentstring
  au!
  au FileType php setlocal commentstring=#\ %s,//\ %s,/\\*\ %s\ \\*/
  au FileType html setlocal commentstring=<!--\ %s\ -->
augrou END