dotfiles

<-- duh.
Log | Files | Refs | LICENSE

commit dcc090a89810aeb037390c84616ca71c48823402
parent e2447723db2fc3bc0fb7363a56969c7b88835c5c
Author: Hayden Hamilton <hayden@haydenvh.com>
Date:   Sat, 15 Feb 2020 09:00:04 +0000

Grub & vim stuff

Diffstat:
A.config/vim/.netrwhist | 12++++++++++++
A.config/vim/autoload/goyo.vim | 447+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/autoload/magit/git.vim | 348+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/autoload/magit/helper.vim | 29+++++++++++++++++++++++++++++
A.config/vim/autoload/magit/mapping.vim | 262+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/autoload/magit/sign.vim | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/autoload/magit/state.vim | 385+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/autoload/magit/sys.vim | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/autoload/magit/utils.vim | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/colors/.vimrc | 0
A.config/vim/common/magit_common.vim | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/plugin/deadkeys.vim | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/plugin/goyo.vim | 24++++++++++++++++++++++++
A.config/vim/plugin/ipa.vim | 186+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/plugin/magit.vim | 1357+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.config/vim/plugin/prose.vim | 38++++++++++++++++++++++++++++++++++++++
A.config/vim/syntax/magit.vim | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
17 files changed, 3869 insertions(+), 0 deletions(-)

diff --git a/.config/vim/.netrwhist b/.config/vim/.netrwhist @@ -0,0 +1,12 @@ +let g:netrw_dirhistmax =10 +let g:netrw_dirhistcnt =2 +let g:netrw_dirhist_2='/etc/bash' +let g:netrw_dirhist_1='/etc/bash/bashrc.d' +let g:netrw_dirhist_0='/home/hayden/.config/i3' +let g:netrw_dirhist_9='/home/hayden' +let g:netrw_dirhist_8='/' +let g:netrw_dirhist_7='/home' +let g:netrw_dirhist_6='/home/hayden' +let g:netrw_dirhist_5='/home/hayden/work/website2/html/downloads/sent' +let g:netrw_dirhist_4='/home/hayden/work/website2/bin/templates' +let g:netrw_dirhist_3='/home/hayden/music/synth/eg/voyager' diff --git a/.config/vim/autoload/goyo.vim b/.config/vim/autoload/goyo.vim @@ -0,0 +1,447 @@ +" Copyright (c) 2015 Junegunn Choi +" +" MIT License +" +" Permission is hereby granted, free of charge, to any person obtaining +" a copy of this software and associated documentation files (the +" "Software"), to deal in the Software without restriction, including +" without limitation the rights to use, copy, modify, merge, publish, +" distribute, sublicense, and/or sell copies of the Software, and to +" permit persons to whom the Software is furnished to do so, subject to +" the following conditions: +" +" The above copyright notice and this permission notice shall be +" included in all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +let s:cpo_save = &cpo +set cpo&vim + +function! s:const(val, min, max) + return min([max([a:val, a:min]), a:max]) +endfunction + +function! s:get_color(group, attr) + return synIDattr(synIDtrans(hlID(a:group)), a:attr) +endfunction + +function! s:set_color(group, attr, color) + let gui = has('gui_running') || has('termguicolors') && &termguicolors + execute printf('hi %s %s%s=%s', a:group, gui ? 'gui' : 'cterm', a:attr, a:color) +endfunction + +function! s:blank(repel) + if bufwinnr(t:goyo_pads.r) <= bufwinnr(t:goyo_pads.l) + 1 + \ || bufwinnr(t:goyo_pads.b) <= bufwinnr(t:goyo_pads.t) + 3 + call s:goyo_off() + endif + execute 'wincmd' a:repel +endfunction + +function! s:init_pad(command) + execute a:command + + setlocal buftype=nofile bufhidden=wipe nomodifiable nobuflisted noswapfile + \ nonu nocursorline nocursorcolumn winfixwidth winfixheight statusline=\ + if exists('&rnu') + setlocal nornu + endif + if exists('&colorcolumn') + setlocal colorcolumn= + endif + let bufnr = winbufnr(0) + + execute winnr('#') . 'wincmd w' + return bufnr +endfunction + +function! s:setup_pad(bufnr, vert, size, repel) + let win = bufwinnr(a:bufnr) + execute win . 'wincmd w' + execute (a:vert ? 'vertical ' : '') . 'resize ' . max([0, a:size]) + augroup goyop + execute 'autocmd WinEnter,CursorMoved <buffer> nested call s:blank("'.a:repel.'")' + autocmd WinLeave <buffer> call s:hide_statusline() + augroup END + + " To hide scrollbars of pad windows in GVim + let diff = winheight(0) - line('$') - (has('gui_running') ? 2 : 0) + if diff > 0 + setlocal modifiable + call append(0, map(range(1, diff), '""')) + normal! gg + setlocal nomodifiable + endif + execute winnr('#') . 'wincmd w' +endfunction + +function! s:resize_pads() + augroup goyop + autocmd! + augroup END + + let t:goyo_dim.width = s:const(t:goyo_dim.width, 2, &columns) + let t:goyo_dim.height = s:const(t:goyo_dim.height, 2, &lines) + + let vmargin = max([0, (&lines - t:goyo_dim.height) / 2 - 1]) + let yoff = s:const(t:goyo_dim.yoff, - vmargin, vmargin) + let top = vmargin + yoff + let bot = vmargin - yoff - 1 + call s:setup_pad(t:goyo_pads.t, 0, top, 'j') + call s:setup_pad(t:goyo_pads.b, 0, bot, 'k') + + let nwidth = max([len(string(line('$'))) + 1, &numberwidth]) + let width = t:goyo_dim.width + (&number ? nwidth : 0) + let hmargin = max([0, (&columns - width) / 2 - 1]) + let xoff = s:const(t:goyo_dim.xoff, - hmargin, hmargin) + call s:setup_pad(t:goyo_pads.l, 1, hmargin + xoff, 'l') + call s:setup_pad(t:goyo_pads.r, 1, hmargin - xoff, 'h') +endfunction + +function! s:tranquilize() + let bg = s:get_color('Normal', 'bg#') + for grp in ['NonText', 'FoldColumn', 'ColorColumn', 'VertSplit', + \ 'StatusLine', 'StatusLineNC', 'SignColumn'] + " -1 on Vim / '' on GVim + if bg == -1 || empty(bg) + call s:set_color(grp, 'fg', get(g:, 'goyo_bg', 'black')) + call s:set_color(grp, 'bg', 'NONE') + else + call s:set_color(grp, 'fg', bg) + call s:set_color(grp, 'bg', bg) + endif + call s:set_color(grp, '', 'NONE') + endfor +endfunction + +function! s:hide_statusline() + setlocal statusline=\ +endfunction + +function! s:hide_linenr() + if !get(g:, 'goyo_linenr', 0) + setlocal nonu + if exists('&rnu') + setlocal nornu + endif + endif + if exists('&colorcolumn') + setlocal colorcolumn= + endif +endfunction + +function! s:maps_nop() + let mapped = filter(['R', 'H', 'J', 'K', 'L', '|', '_'], + \ "empty(maparg(\"\<c-w>\".v:val, 'n'))") + for c in mapped + execute 'nnoremap <c-w>'.escape(c, '|').' <nop>' + endfor + return mapped +endfunction + +function! s:maps_resize() + let commands = { + \ '=': ':<c-u>let t:goyo_dim = <sid>parse_arg(t:goyo_dim_expr) <bar> call <sid>resize_pads()<cr>', + \ '>': ':<c-u>let t:goyo_dim.width = winwidth(0) + 2 * v:count1 <bar> call <sid>resize_pads()<cr>', + \ '<': ':<c-u>let t:goyo_dim.width = winwidth(0) - 2 * v:count1 <bar> call <sid>resize_pads()<cr>', + \ '+': ':<c-u>let t:goyo_dim.height += 2 * v:count1 <bar> call <sid>resize_pads()<cr>', + \ '-': ':<c-u>let t:goyo_dim.height -= 2 * v:count1 <bar> call <sid>resize_pads()<cr>' + \ } + let mapped = filter(keys(commands), "empty(maparg(\"\<c-w>\".v:val, 'n'))") + for c in mapped + execute 'nnoremap <silent> <c-w>'.c.' '.commands[c] + endfor + return mapped +endfunction + +nnoremap <silent> <plug>(goyo-resize) :<c-u>call <sid>resize_pads()<cr> + +function! s:goyo_on(dim) + let dim = s:parse_arg(a:dim) + if empty(dim) + return + endif + + let s:orig_tab = tabpagenr() + let settings = + \ { 'laststatus': &laststatus, + \ 'showtabline': &showtabline, + \ 'fillchars': &fillchars, + \ 'winminwidth': &winminwidth, + \ 'winwidth': &winwidth, + \ 'winminheight': &winminheight, + \ 'winheight': &winheight, + \ 'ruler': &ruler, + \ 'sidescroll': &sidescroll, + \ 'sidescrolloff': &sidescrolloff + \ } + + " New tab + tab split + + let t:goyo_master = winbufnr(0) + let t:goyo_dim = dim + let t:goyo_dim_expr = a:dim + let t:goyo_pads = {} + let t:goyo_revert = settings + let t:goyo_maps = extend(s:maps_nop(), s:maps_resize()) + if has('gui_running') + let t:goyo_revert.guioptions = &guioptions + endif + + " vim-gitgutter + let t:goyo_disabled_gitgutter = get(g:, 'gitgutter_enabled', 0) + if t:goyo_disabled_gitgutter + silent! GitGutterDisable + endif + + " vim-signify + let t:goyo_disabled_signify = exists('b:sy') && b:sy.active + if t:goyo_disabled_signify + SignifyToggle + endif + + " vim-airline + let t:goyo_disabled_airline = exists('#airline') + if t:goyo_disabled_airline + AirlineToggle + endif + + " vim-powerline + let t:goyo_disabled_powerline = exists('#PowerlineMain') + if t:goyo_disabled_powerline + augroup PowerlineMain + autocmd! + augroup END + augroup! PowerlineMain + endif + + " lightline.vim + let t:goyo_disabled_lightline = exists('#lightline') + if t:goyo_disabled_lightline + silent! call lightline#disable() + endif + + call s:hide_linenr() + " Global options + let &winheight = max([&winminheight, 1]) + set winminheight=1 + set winheight=1 + set winminwidth=1 winwidth=1 + set laststatus=0 + set showtabline=0 + set noruler + set fillchars+=vert:\ + set fillchars+=stl:\ + set fillchars+=stlnc:\ + set sidescroll=1 + set sidescrolloff=0 + + " Hide left-hand scrollbars + if has('gui_running') + set guioptions-=l + set guioptions-=L + endif + + let t:goyo_pads.l = s:init_pad('vertical topleft new') + let t:goyo_pads.r = s:init_pad('vertical botright new') + let t:goyo_pads.t = s:init_pad('topleft new') + let t:goyo_pads.b = s:init_pad('botright new') + + call s:resize_pads() + call s:tranquilize() + + augroup goyo + autocmd! + autocmd TabLeave * nested call s:goyo_off() + autocmd VimResized * call s:resize_pads() + autocmd ColorScheme * call s:tranquilize() + autocmd BufWinEnter * call s:hide_linenr() | call s:hide_statusline() + autocmd WinEnter,WinLeave * call s:hide_statusline() + if has('nvim') + autocmd TermClose * call feedkeys("\<plug>(goyo-resize)") + endif + augroup END + + call s:hide_statusline() + if exists('g:goyo_callbacks[0]') + call g:goyo_callbacks[0]() + endif + if exists('#User#GoyoEnter') + doautocmd User GoyoEnter + endif +endfunction + +function! s:goyo_off() + if !exists('#goyo') + return + endif + + " Oops, not this tab + if !exists('t:goyo_revert') + return + endif + + " Clear auto commands + augroup goyo + autocmd! + augroup END + augroup! goyo + augroup goyop + autocmd! + augroup END + augroup! goyop + + for c in t:goyo_maps + execute 'nunmap <c-w>'.escape(c, '|') + endfor + + let goyo_revert = t:goyo_revert + let goyo_disabled_gitgutter = t:goyo_disabled_gitgutter + let goyo_disabled_signify = t:goyo_disabled_signify + let goyo_disabled_airline = t:goyo_disabled_airline + let goyo_disabled_powerline = t:goyo_disabled_powerline + let goyo_disabled_lightline = t:goyo_disabled_lightline + let goyo_orig_buffer = t:goyo_master + let [line, col] = [line('.'), col('.')] + + if tabpagenr() == 1 + tabnew + normal! gt + bd + endif + tabclose + execute 'normal! '.s:orig_tab.'gt' + if winbufnr(0) == goyo_orig_buffer + " Doesn't work if window closed with `q` + execute printf('normal! %dG%d|', line, col) + endif + + let wmw = remove(goyo_revert, 'winminwidth') + let ww = remove(goyo_revert, 'winwidth') + let &winwidth = ww + let &winminwidth = wmw + let wmh = remove(goyo_revert, 'winminheight') + let wh = remove(goyo_revert, 'winheight') + let &winheight = max([wmh, 1]) + let &winminheight = wmh + let &winheight = wh + + for [k, v] in items(goyo_revert) + execute printf('let &%s = %s', k, string(v)) + endfor + execute 'colo '. get(g:, 'colors_name', 'default') + + if goyo_disabled_gitgutter + silent! GitGutterEnable + endif + + if goyo_disabled_signify + silent! if !b:sy.active + SignifyToggle + endif + endif + + if goyo_disabled_airline && !exists('#airline') + AirlineToggle + " For some reason, Airline requires two refreshes to avoid display + " artifacts + silent! AirlineRefresh + silent! AirlineRefresh + endif + + if goyo_disabled_powerline && !exists('#PowerlineMain') + doautocmd PowerlineStartup VimEnter + silent! PowerlineReloadColorscheme + endif + + if goyo_disabled_lightline + silent! call lightline#enable() + endif + + if exists('#Powerline') + doautocmd Powerline ColorScheme + endif + + if exists('g:goyo_callbacks[1]') + call g:goyo_callbacks[1]() + endif + if exists('#User#GoyoLeave') + doautocmd User GoyoLeave + endif +endfunction + +function! s:relsz(expr, limit) + if a:expr !~ '%$' + return str2nr(a:expr) + endif + return a:limit * str2nr(a:expr[:-2]) / 100 +endfunction + +function! s:parse_arg(arg) + if exists('g:goyo_height') || !exists('g:goyo_margin_top') && !exists('g:goyo_margin_bottom') + let height = s:relsz(get(g:, 'goyo_height', '85%'), &lines) + let yoff = 0 + else + let top = max([0, s:relsz(get(g:, 'goyo_margin_top', 4), &lines)]) + let bot = max([0, s:relsz(get(g:, 'goyo_margin_bottom', 4), &lines)]) + let height = &lines - top - bot + let yoff = top - bot + endif + + let dim = { 'width': s:relsz(get(g:, 'goyo_width', 80), &columns), + \ 'height': height, + \ 'xoff': 0, + \ 'yoff': yoff } + if empty(a:arg) + return dim + endif + let parts = matchlist(a:arg, '^\s*\([0-9]\+%\?\)\?\([+-][0-9]\+%\?\)\?\%(x\([0-9]\+%\?\)\?\([+-][0-9]\+%\?\)\?\)\?\s*$') + if empty(parts) + echohl WarningMsg + echo 'Invalid dimension expression: '.a:arg + echohl None + return {} + endif + if !empty(parts[1]) | let dim.width = s:relsz(parts[1], &columns) | endif + if !empty(parts[2]) | let dim.xoff = s:relsz(parts[2], &columns) | endif + if !empty(parts[3]) | let dim.height = s:relsz(parts[3], &lines) | endif + if !empty(parts[4]) | let dim.yoff = s:relsz(parts[4], &lines) | endif + return dim +endfunction + +function! goyo#execute(bang, dim) + if a:bang + if exists('#goyo') + call s:goyo_off() + endif + else + if exists('#goyo') == 0 + call s:goyo_on(a:dim) + elseif !empty(a:dim) + if winnr('$') < 5 + call s:goyo_off() + return goyo#execute(a:bang, a:dim) + endif + let dim = s:parse_arg(a:dim) + if !empty(dim) + let t:goyo_dim = dim + let t:goyo_dim_expr = a:dim + call s:resize_pads() + endif + else + call s:goyo_off() + end + end +endfunction + +let &cpo = s:cpo_save +unlet s:cpo_save + diff --git a/.config/vim/autoload/magit/git.vim b/.config/vim/autoload/magit/git.vim @@ -0,0 +1,348 @@ +function! magit#git#get_version() + if ( !exists("s:git_version") ) + let s:git_version = matchlist(system(g:magit_git_cmd . " --version"), + \ 'git version \(\d\+\)\.\(\d\+\)\.\(\d\+\)\.\(\d\+\)\.\(g\x\+\)')[1:5] + endif + return s:git_version +endfunction + +function! magit#git#is_version_sup_equal(major, minor, rev) + let git_ver = magit#git#get_version() + return ( ( a:major > git_ver[0] ) || + \ (a:major >= git_ver[0] && a:minor > git_ver[1] ) || + \ (a:major >= git_ver[0] && a:minor >= git_ver[1] && a:rev >= git_ver[2] ) + \ ) +endfunction + +" magit#git#get_status: this function returns the git status output formated +" into a List of Dict as +" [ {staged', 'unstaged', 'filename'}, ... ] +function! magit#git#get_status() + let file_list = [] + + " systemlist v7.4.248 problem again + " we can't use git status -z here, because system doesn't make the + " difference between NUL and NL. -status z terminate entries with NUL, + " instead of NF + let status_list=magit#sys#systemlist(g:magit_git_cmd . " status --porcelain") + for file_status_line in status_list + let line_match = matchlist(file_status_line, '\(.\)\(.\) \%(.\{-\} -> \)\?"\?\(.\{-\}\)"\?$') + let filename = line_match[3] + call add(file_list, { 'staged': line_match[1], 'unstaged': line_match[2], 'filename': filename }) + endfor + return file_list +endfunction + +function! magit#git#get_config(conf_name, default) + try + silent! let git_result=magit#utils#strip( + \ magit#sys#system(g:magit_git_cmd . " config --get " . a:conf_name)) + catch 'shell_error' + return a:default + endtry + return git_result +endfunction + +" magit#git#is_work_tree: this function check that path passed as parameter is +" inside a git work tree +" param[in] path: path to check +" return: top work tree path if in a work tree, empty string otherwise +function! magit#git#is_work_tree(path) + let dir = getcwd() + try + call magit#utils#chdir(a:path) + let top_dir=system(g:magit_git_cmd . " rev-parse --show-toplevel") + if ( executable("cygpath") ) + let top_dir = magit#utils#strip(system("cygpath " . top_dir)) + endif + if ( v:shell_error != 0 ) + return '' + endif + return magit#utils#strip(top_dir) . "/" + finally + call magit#utils#chdir(dir) + endtry +endfunction + +" magit#git#set_top_dir: this function set b:magit_top_dir and b:magit_git_dir +" according to a path +" param[in] path: path to set. This path must be in a git repository work tree +function! magit#git#set_top_dir(path) + let dir = getcwd() + try + call magit#utils#chdir(a:path) + try + let top_dir=magit#utils#strip( + \ system(g:magit_git_cmd . " rev-parse --show-toplevel")) . "/" + let git_dir=magit#utils#strip(system(g:magit_git_cmd . " rev-parse --git-dir")) . "/" + if ( executable("cygpath") ) + let top_dir = magit#utils#strip(system("cygpath " . top_dir)) + let git_dir = magit#utils#strip(system("cygpath " . git_dir)) + endif + catch 'shell_error' + call magit#sys#print_shell_error() + throw 'set_top_dir_error' + endtry + let b:magit_top_dir=top_dir + let b:magit_git_dir=git_dir + finally + call magit#utils#chdir(dir) + endtry +endfunction + +" magit#git#top_dir: return the absolute path of current git worktree for the +" current magit buffer +" return top directory +function! magit#git#top_dir() + if ( !exists("b:magit_top_dir") ) + throw 'top_dir_not_set' + endif + return b:magit_top_dir +endfunction + +" magit#git#git_dir: return the absolute path of current git worktree +" return git directory +function! magit#git#git_dir() + if ( !exists("b:magit_git_dir") ) + throw 'git_dir_not_set' + endif + return b:magit_git_dir +endfunction + +" magit#git#git_diff: helper function to get diff of a file +" nota: when git fail (due to misformated patch for example), an error +" message is raised. +" WARNING: diff is generated without prefix. To apply this diff, git apply +" must use the option -p0. +" param[in] filemane: it must be quoted if it contains spaces +" param[in] status: status of the file (see g:magit_git_status_code) +" param[in] mode: can be staged or unstaged +" return: two values +" [0]: boolean, if true current file is binary +" [1]: string array containing diff output +function! magit#git#git_diff(filename, status, mode) + let dev_null = ( a:status == '?' ) ? "/dev/null " : "" + let staged_flag = ( a:mode == 'staged' ) ? "--staged" : "" + let git_cmd=g:magit_git_cmd . " diff --no-ext-diff " . staged_flag . + \ " --no-prefix --no-color -p -U" . b:magit_diff_context . + \ " -- " . dev_null . " " . a:filename + + if ( a:status != '?' ) + try + silent let diff_list=magit#sys#systemlist(git_cmd) + catch 'shell_error' + call magit#sys#print_shell_error() + throw 'diff error' + endtry + else + silent let diff_list=magit#sys#systemlist_noraise(git_cmd) + endif + + if ( empty(diff_list) ) + echohl WarningMsg + echom "diff command \"" . git_cmd . "\" returned nothing" + echohl None + throw 'diff error' + endif + return [ + \ ( diff_list[-1] =~ "^Binary files .* differ$" && len(diff_list) <= 4 ) + \, diff_list ] +endfunction + +" magit#git#sub_check: this function checks if given submodule has modified or +" untracked content +" param[in] submodule: submodule path +" param[in] check_level: can be modified or untracked +function! magit#git#sub_check(submodule, check_level) + let ignore_flag = ( a:check_level == 'modified' ) ? + \ '--ignore-submodules=untracked' : '' + let git_cmd=g:magit_git_cmd . " status --porcelain " . ignore_flag . " " . a:submodule + return ( !empty(magit#sys#systemlist(git_cmd)) ) +endfunction + +" magit#git#git_sub_summary: helper function to get diff of a submodule +" nota: when git fail (due to misformated patch for example), an error +" message is raised. +" param[in] filemane: it must be quoted if it contains spaces +" param[in] mode: can be staged or unstaged +function! magit#git#git_sub_summary(filename, mode) + let staged_flag = ( a:mode == 'staged' ) ? " --cached " : " --files " + let git_cmd=g:magit_git_cmd . " submodule summary " . staged_flag . " HEAD " + \ .a:filename + silent let diff_list=magit#sys#systemlist(git_cmd) + if ( empty(diff_list) ) + if ( a:mode == 'unstaged' ) + if ( magit#git#sub_check(a:filename, 'modified') ) + return "modified content" + endif + if ( magit#git#sub_check(a:filename, 'untracked') ) + return "untracked content" + endif + endif + echohl WarningMsg + echom "diff command \"" . git_cmd . "\" returned nothing" + echohl None + throw 'diff error' + endif + return diff_list +endfunction + +" magit#git#git_add: helper function to add a whole file +" nota: when git fail (due to misformated patch for example), an error +" message is raised. +" param[in] filemane: it must be quoted if it contains spaces +function! magit#git#git_add(filename) + let git_cmd=g:magit_git_cmd . " add --no-ignore-removal -- " . a:filename + try + silent let git_result=magit#sys#system(git_cmd) + catch 'shell_error' + call magit#sys#print_shell_error() + throw 'add error' + endtry +endfunction + +" magit#git#git_checkout: helper function to add a whole file +" nota: when git fail (due to misformated patch for example), an error +" message is raised. +" param[in] filemane: it must be quoted if it contains spaces +function! magit#git#git_checkout(filename) + let git_cmd=g:magit_git_cmd . " checkout -- " . a:filename + try + silent let git_result=magit#sys#system(git_cmd) + catch 'shell_error' + call magit#sys#print_shell_error() + throw 'checkout error' + endtry +endfunction + +" magit#git#git_reset: helper function to add a whole file +" nota: when git fail (due to misformated patch for example), an error +" message is raised. +" param[in] filemane: it must be quoted if it contains spaces +function! magit#git#git_reset(filename) + let git_cmd=g:magit_git_cmd . " reset HEAD -- " . a:filename + try + silent let git_result=magit#sys#system(git_cmd) + catch 'shell_error' + call magit#sys#print_shell_error() + throw 'reset error' + endtry +endfunction + +" magit#git#git_apply: helper function to stage a selection +" nota: when git fail (due to misformated patch for example), an error +" message is raised. +" param[in] selection: the text to stage. It must be a patch, i.e. a diff +" header plus one or more hunks +" return: no +function! magit#git#git_apply(header, selection) + let selection = magit#utils#flatten(a:header + a:selection) + if ( selection[-1] !~ '^$' ) + let selection += [ '' ] + endif + let git_cmd=g:magit_git_cmd . " apply --recount --no-index --cached -p0 -" + try + silent let git_result=magit#sys#system(git_cmd, selection) + catch 'shell_error' + call magit#sys#print_shell_error() + echom "Tried to aply this" + echom string(selection) + throw 'apply error' + endtry +endfunction + +" magit#git#git_unapply: helper function to unstage a selection +" nota: when git fail (due to misformated patch for example), an error +" message is raised. +" param[in] selection: the text to stage. It must be a patch, i.e. a diff +" header plus one or more hunks +" return: no +function! magit#git#git_unapply(header, selection, mode) + let cached_flag='' + if ( a:mode == 'staged' ) + let cached_flag=' --cached ' + endif + let selection = magit#utils#flatten(a:header + a:selection) + if ( selection[-1] !~ '^$' ) + let selection += [ '' ] + endif + try + silent let git_result=magit#sys#system( + \ g:magit_git_cmd . " apply --recount --no-index -p0 --reverse " . + \ cached_flag . " - ", selection) + catch 'shell_error' + call magit#sys#print_shell_error() + echom "Tried to unaply this" + echom string(selection) + throw 'unapply error' + endtry +endfunction + +" magit#git#submodule_status: helper function to return the submodule status +" return submodule status +function! magit#git#submodule_status() + return magit#sys#system(g:magit_git_cmd . " submodule status") +endfunction + +" magit#git#get_branch_name: get the branch name given a reference +" WARNING does not seem to work with SHA1 +" param[in] ref can be HEAD or a branch name +" return branch name +function! magit#git#get_branch_name(ref) + return magit#utils#strip(magit#sys#system(g:magit_git_cmd . " rev-parse --abbrev-ref " . a:ref)) +endfunction + +" magit#git#count_object: this function returns the output of git +" count-objects, in a dict object +" It contains the following information: count, size, in-pack, packs, +" size-pack, prune-packable, garbage, size-garbage +function! magit#git#count_object() + let count_object=magit#sys#systemlist(g:magit_git_cmd . " count-objects -v") + let refs={} + for line in count_object + let ref=split(line, ":") + let refs[ref[0]] = ref[1] + endfor + return refs +endfunction + +" magit#git#check_repo: check the health of the repo +" return 0 if everything is fine, 1 otherwise +function! magit#git#check_repo() + try + let head_br=magit#git#get_branch_name("HEAD") + catch 'shell_error' + let count = magit#git#count_object()['count'] + if ( count != 0 ) + return 1 + endif + endtry + return 0 +endfunction + +" magit#git#get_commit_subject: get the subject of a commit (first line) +" param[in] ref: reference, can be SHA1, brnach name or HEAD +" return commit subject +function! magit#git#get_commit_subject(ref) + try + return magit#utils#strip(magit#sys#system(g:magit_git_cmd . " show " . + \" --no-prefix --no-patch --format=\"%s\" " . a:ref)) + catch 'shell_error' + return "" + endtry +endfunction + +" magit#git#get_remote_branch: get the branch name of the default remote, for +" upstream and push +" WARNING does not work with SHA1 +" param[in] ref: reference, can be HEAD or branch name +" param[in] type: type of default remote: upstream or push +" return the remote branch name, 'none' if it has not +function! magit#git#get_remote_branch(ref, type) + try + return magit#utils#strip(magit#sys#system( + \ g:magit_git_cmd . " rev-parse --abbrev-ref=loose " . a:ref . "@{" . a:type . "}")) + catch 'shell_error' + return "none" + endtry +endfunction diff --git a/.config/vim/autoload/magit/helper.vim b/.config/vim/autoload/magit/helper.vim @@ -0,0 +1,29 @@ + +" magit#helper#get_filename: helper function to get the current filename, according to +" cursor position +" return: filename +function! magit#helper#get_filename() + return substitute(getline(search(g:magit_file_re, "cbnW")), g:magit_file_re, '\2', '') +endfunction + +" magit#helper#get_hunkheader_line_nb: helper function to get the current hunk +" header line number, according to cursor position +" return: hunk header line number +function! magit#helper#get_hunkheader_line_nb() + return search(g:magit_hunk_re, "cbnW") +endfunction + +" magit#utils#get_section: helper function to get the current section, according to +" cursor position +" return: section id, empty string if no section found +function! magit#helper#get_section() + let section_line=getline(search(g:magit_section_re, "bnW")) + for [section_name, section_str] in items(g:magit_sections) + if ( section_line == section_str ) + return section_name + endif + endfor + return '' +endfunction + + diff --git a/.config/vim/autoload/magit/mapping.vim b/.config/vim/autoload/magit/mapping.vim @@ -0,0 +1,262 @@ + +let g:magit_stage_file_mapping = get(g:, 'magit_stage_file_mapping', 'F' ) +let g:magit_stage_hunk_mapping = get(g:, 'magit_stage_hunk_mapping', 'S' ) +let g:magit_stage_line_mapping = get(g:, 'magit_stage_line_mapping', 'L' ) +let g:magit_mark_line_mapping = get(g:, 'magit_mark_line_mapping', 'M' ) +let g:magit_commit_mapping = get(g:, 'magit_commit_mapping', 'CC' ) +let g:magit_commit_amend_mapping = get(g:, 'magit_commit_amend_mapping', 'CA' ) +let g:magit_commit_fixup_mapping = get(g:, 'magit_commit_fixup_mapping', 'CF' ) +let g:magit_close_commit_mapping = get(g:, 'magit_close_commit_mapping', 'CU' ) +let g:magit_reload_mapping = get(g:, 'magit_reload_mapping', 'R' ) +let g:magit_edit_mapping = get(g:, 'magit_edit_mapping', 'E' ) + +let g:magit_jump_next_hunk = get(g:, 'magit_jump_next_hunk', '<C-N>') +let g:magit_jump_prev_hunk = get(g:, 'magit_jump_prev_hunk', '<C-P>') + +let g:magit_ignore_mapping = get(g:, 'magit_ignore_mapping', 'I' ) +let g:magit_discard_hunk_mapping = get(g:, 'magit_discard_hunk_mapping', 'DDD' ) + +let g:magit_close_mapping = get(g:, 'magit_close_mapping', 'q' ) +let g:magit_toggle_help_mapping = get(g:, 'magit_toggle_help_mapping', '?' ) + +let g:magit_diff_shrink = get(g:, 'magit_diff_shrink', '-' ) +let g:magit_diff_enlarge = get(g:, 'magit_diff_enlarge', '+' ) +let g:magit_diff_reset = get(g:, 'magit_diff_reset', '0' ) + +let g:magit_folding_toggle_mapping = get(g:, 'magit_folding_toggle_mapping', [ '<CR>' ]) +let g:magit_folding_open_mapping = get(g:, 'magit_folding_open_mapping', [ 'zo', 'zO' ]) +let g:magit_folding_close_mapping = get(g:, 'magit_folding_close_mapping', [ 'zc', 'zC' ]) + +" magit#open_close_folding_wrapper: wrapper function to +" magit#open_close_folding. If line under cursor is not a cursor, execute +" normal behavior +" param[in] mapping: which has been set +" param[in] visible : boolean, force visible value. If not set, toggle +" visibility +function! s:mg_open_close_folding_wrapper(mapping, ...) + if ( getline(".") =~ g:magit_file_re ) + return call('magit#open_close_folding', a:000) + elseif ( foldlevel(line(".")) == 2 ) + if ( foldclosed(line('.')) == -1 ) + foldclose + else + foldopen + endif + else + silent! execute "silent! normal! " . a:mapping + endif +endfunction + +" s:nmapping_wrapper: wrapper for normal mapping commands +" it needs a wrapper because some mappings must only be enabled in some +" sections. For example, wa want that 'S' mapping to be enabled in staged and +" unstaged sections, but not in commit section. +" param[in] mapping the key for the mapping (lhs) +" param[in] function the function to call (rhs) +" param[in] ... : optional, section, the regex of the sections where to enable the +" mapping. If there is no section parameter or if the section parameter regex +" match the current section, the rhs is called. Otherwise, the mapping is +" applied to its original meaning. +function! s:nmapping_wrapper(mapping, function, ...) + if ( a:0 == 0 || magit#helper#get_section() =~ a:1 ) + execute "call " . a:function + else + " feedkeys(..., 'n') is prefered over execute normal! + " normal! does not enter in insert mode + call feedkeys(a:mapping, 'n') + endif +endfunction + +" s:xmapping_wrapper: wrapper for visual mapping commands +" it needs a wrapper because some mappings must only be enabled in some +" sections. For example, wa want that 'S' mapping to be enabled in staged and +" unstaged sections, but not in commit section. +" param[in] mapping the key for the mapping (lhs) +" param[in] function the function to call (rhs) +" param[in] ... : optional, section, the regex of the sections where to enable the +" mapping. If there is no section parameter or if the section parameter regex +" match the current section, the rhs is called. Otherwise, the mapping is +" applied to its original meaning. +function! s:xmapping_wrapper(mapping, function, ...) range + if ( a:0 == 0 || magit#helper#get_section() =~ a:1 ) + execute a:firstline . "," . a:lastline . "call " . a:function + else + " feedkeys(..., 'n') is prefered over execute normal! + " normal! does not enter in insert mode + call feedkeys(a:mapping, 'n') + endif +endfunction +" s:mg_set_mapping: helper function to setup the mapping +" param[in] mode the mapping mode, one letter. Can be 'n', 'x', 'i', ... +" param[in] mapping the key for the mapping (lhs) +" param[in] function the function to call (rhs) +" param[in] ... : optional, section, the regex of the section(s) +function! s:mg_set_mapping(mode, mapping, function, ...) + if ( a:0 == 1 ) + execute a:mode . "noremap <buffer><silent><nowait> " + \ . a:mapping . + \ " :call <SID>" . a:mode . "mapping_wrapper(\"" . + \ a:mapping . "\", \"" . + \ a:function . "\"" . + \ ", \'" . a:1 . "\'" . + \ ")<cr>" + else + execute a:mode . "noremap <buffer><silent><nowait> " + \ . a:mapping . + \ " :call " . + \ a:function . "<cr>" + endif +endfunction + +function! magit#mapping#set_default() + + call s:mg_set_mapping('n', g:magit_stage_hunk_mapping, + \"magit#stage_hunk(0)", '\<\%(un\)\?staged\>') + call s:mg_set_mapping('n', g:magit_stage_file_mapping, + \ "magit#stage_file()", '\<\%(un\)\?staged\>') + call s:mg_set_mapping('n', g:magit_discard_hunk_mapping, + \ "magit#stage_hunk(1)", '\<\%(un\)\?staged\>') + call s:mg_set_mapping('n', g:magit_stage_line_mapping, + \ "magit#stage_vselect()", '\<\%(un\)\?staged\>') + call s:mg_set_mapping('x', g:magit_stage_hunk_mapping, + \ "magit#stage_vselect()", '\<\%(un\)\?staged\>') + call s:mg_set_mapping('n', g:magit_mark_line_mapping, + \ "magit#mark_vselect()", '\<\%(un\)\?staged\>') + call s:mg_set_mapping('x', g:magit_mark_line_mapping, + \ "magit#mark_vselect()", '\<\%(un\)\?staged\>') + + call s:mg_set_mapping('n', g:magit_ignore_mapping, + \ "magit#ignore_file()", '\<\%(un\)\?staged\>') + call s:mg_set_mapping('n', g:magit_edit_mapping, + \ "magit#jump_to()", '\<\%(un\)\?staged\>') + + call s:mg_set_mapping('n', g:magit_reload_mapping, + \ "magit#update_buffer()") + call s:mg_set_mapping('n', g:magit_close_mapping, + \ "magit#close_magit()") + call s:mg_set_mapping('n', g:magit_diff_shrink, + \ "magit#update_diff('-')") + call s:mg_set_mapping('n', g:magit_diff_enlarge, + \ "magit#update_diff('+')") + call s:mg_set_mapping('n', g:magit_diff_reset, + \ "magit#update_diff('0')") + call s:mg_set_mapping('n', g:magit_toggle_help_mapping, + \ "magit#toggle_help()") + + call s:mg_set_mapping('n', g:magit_commit_mapping, + \ "magit#commit_command('CC')") + call s:mg_set_mapping('n', g:magit_commit_amend_mapping, + \ "magit#commit_command('CA')") + call s:mg_set_mapping('n', g:magit_commit_fixup_mapping, + \ "magit#commit_command('CF')") + call s:mg_set_mapping('n', g:magit_close_commit_mapping, + \ "magit#close_commit()") + + call s:mg_set_mapping('n', g:magit_jump_next_hunk, + \ "magit#jump_hunk('N')") + call s:mg_set_mapping('n', g:magit_jump_prev_hunk, + \ "magit#jump_hunk('P')") + + for mapping in g:magit_folding_toggle_mapping + " trick to pass '<cr>' in a mapping command without being interpreted + let func_arg = ( mapping ==? "<cr>" ) ? '+' : mapping + execute "nnoremap <buffer><silent><nowait> " . mapping . " :call <SID>mg_open_close_folding_wrapper('" . func_arg . "')<return>" + endfor + for mapping in g:magit_folding_open_mapping + execute "nnoremap <buffer><silent><nowait> " . mapping . " :call <SID>mg_open_close_folding_wrapper('" . mapping . "', 1)<return>" + endfor + for mapping in g:magit_folding_close_mapping + execute "nnoremap <buffer><silent><nowait> " . mapping . " :call <SID>mg_open_close_folding_wrapper('" . mapping . "', 0)<return>" + endfor + + " s:magit_inline_help: Dict containing inline help for each section + let s:magit_inline_help = { + \ 'staged': [ +\g:magit_stage_hunk_mapping +\.' if cursor on filename header, unstage file', +\' if cursor in hunk, unstage hunk', +\' if visual selection in hunk (with v), unstage selection', +\' if lines marked in hunk (with ' . g:magit_mark_line_mapping . '), unstage marked lines', +\g:magit_stage_line_mapping +\.' unstage the line under the cursor', +\g:magit_mark_line_mapping +\.' if cursor in hunk, mark line under cursor "to be unstaged"', +\' if visual selection in hunk (with v), mark selected lines "to be unstaged"', +\g:magit_stage_file_mapping +\.' if cursor on filename header or hunk, unstage whole file', +\g:magit_edit_mapping +\.' edit, jump cursor to file containing this hunk', +\g:magit_jump_next_hunk.','.g:magit_jump_prev_hunk +\. ' move to Next/Previous hunk in magit buffer', +\], + \ 'unstaged': [ +\g:magit_stage_hunk_mapping +\.' if cursor on filename header, stage file', +\' if cursor in hunk, stage hunk', +\' if visual selection in hunk (with v), stage selection', +\' if lines marked in hunk (with ' . g:magit_mark_line_mapping . '), stage marked lines', +\g:magit_stage_line_mapping +\.' stage the line under the cursor', +\g:magit_mark_line_mapping +\.' if cursor in hunk, mark line under cursor "to be staged"', +\' if visual selection in hunk (with v), mark selected lines "to be staged"', +\g:magit_stage_file_mapping +\.' if cursor on filename header or hunk, stage whole file', +\g:magit_edit_mapping +\.' edit, jump cursor to file containing this hunk', +\g:magit_jump_next_hunk.','.g:magit_jump_prev_hunk +\. ' move to Next/Previous hunk in magit buffer', +\g:magit_discard_hunk_mapping +\. ' discard file changes (warning, changes will be lost)', +\g:magit_ignore_mapping +\.' add file in .gitgnore', +\], + \ 'global': [ +\g:magit_sections['help'], +\g:magit_folding_toggle_mapping[0] +\. ' if cursor on filename header line, unhide diffs for this file', +\g:magit_commit_mapping +\. ' From stage mode: set commit mode in normal flavor', +\' From commit mode: commit all staged changes with commit flavor', +\' (normal or amend) with message in "Commit message" section', +\g:magit_commit_amend_mapping +\. ' From stage or commit mode: set commit mode in amend flavor, and', +\' display "Commit message" section with previous commit message.', +\g:magit_commit_fixup_mapping +\. ' From stage mode: amend staged changes to previous commit without', +\' modifying the previous commit message', +\g:magit_close_commit_mapping +\. ' commit undo, cancel and close current commit message', +\g:magit_reload_mapping +\.' refresh magit buffer', +\g:magit_diff_shrink.','.g:magit_diff_enlarge.','.g:magit_diff_reset +\. ' shrink,enlarge,reset diff context', +\g:magit_close_mapping +\.' close magit buffer', +\g:magit_toggle_help_mapping +\.' toggle help showing in magit buffer', +\'=======' +\], +\} +endfunction + +" s:mg_get_inline_help_line_nb: this function returns the number of lines of +" a given section, or 0 if help is disabled. +" param[in] section: section identifier +" return number of lines +function! magit#mapping#get_section_help_line_nb(section) + return ( g:magit_show_help == 1 ) ? + \ len(s:magit_inline_help[a:section]) : 0 +endfunction + +" s:mg_section_help: this function writes in current buffer the inline help +" for a given section, it does nothing if inline help is disabled. +" WARNING: this function writes in file, it should only be called through +" protected functions like magit#update_buffer +" param[in] section: section identifier +function! magit#mapping#get_section_help(section) + if ( g:magit_show_help == 1 ) + silent put =s:magit_inline_help[a:section] + endif +endfunction + diff --git a/.config/vim/autoload/magit/sign.vim b/.config/vim/autoload/magit/sign.vim @@ -0,0 +1,116 @@ +" Got lot of stuf from vim-gitgutter +" https://github.com/airblade/vim-gitgutter + +" Vim doesn't namespace sign ids so every plugin shares the same +" namespace. Sign ids are simply integers so to avoid clashes with other +" signs we guess at a clear run. +" +" Note also we currently never reset s:next_sign_id. +let s:first_sign_id = 42000 +let s:next_sign_id = s:first_sign_id +let s:dummy_sign_id = s:first_sign_id - 1 +" Remove-all-signs optimisation requires Vim 7.3.596+. +let s:supports_star = v:version > 703 || (v:version == 703 && has("patch596")) + +function! magit#sign#remove_all(...) + if ( a:0 == 1 ) + let pattern = a:1 + else + let pattern = '^Magit.*' + endif + let signs = magit#sign#find_signs(pattern, 1, line('$')) + call magit#sign#remove_signs(signs) +endfunction + +" magit#sign#remove_signs: unplace a list of signs +" param[in] sign_ids: list of signs dict +function! magit#sign#remove_signs(sign_ids) + let bufnr = magit#utils#bufnr() + for sign in values(a:sign_ids) + execute "sign unplace" sign.id + endfor +endfunction + +function! magit#sign#add_sign(line, type, bufnr) + let id = <SID>get_next_sign_id() + execute ":sign place " . id . + \ " line=" . a:line . " name=" . s:magit_mark_signs[a:type] . + \ " buffer=" . a:bufnr + return id +endfunction + +function! magit#sign#remove_sign(id) + execute ":sign unplace " . a:id +endfunction + +" s:get_next_sign_id: helper function to increment sign ids +function! s:get_next_sign_id() + let next_id = s:next_sign_id + let s:next_sign_id += 1 + return next_id +endfunction + +" magit#sign#find_signs: this function returns signs matching a pattern in a +" range of lines +" param[in] pattern: regex pattern to match +" param[in] startline,endline: range of lines +" FIXME: find since which version "sign place" is sorted +function! magit#sign#find_signs(pattern, startline, endline) + let bufnr = magit#utils#bufnr() + " <line_number (string)>: {'id': <id (number)>, 'name': <name (string)>} + let found_signs = {} + + redir => signs + silent execute "sign place buffer=" . bufnr + redir END + + for sign_line in filter(split(signs, '\n'), 'v:val =~# "="') + " Typical sign line: line=88 id=1234 name=GitGutterLineAdded + " We assume splitting is faster than a regexp. + let components = split(sign_line) + let name = split(components[2], '=')[1] + let line_number = str2nr(split(components[0], '=')[1]) + if ( name =~# a:pattern && + \ line_number >= a:startline && + \ line_number <= a:endline ) + let id = str2nr(split(components[1], '=')[1]) + let found_signs[line_number] = {'id': id, 'name': name} + endif + endfor + return found_signs +endfunction + +" magit#sign#find_stage_signs: helper function to get marked lines for stage +" param[in] startline,endline: range of lines +" return Dict of marked lines +function! magit#sign#find_stage_signs(startline, endline) + return magit#sign#find_signs(s:magit_mark_signs.M, a:startline, a:endline) +endfunction + +" s:magit_mark_sign: string of the sign for lines to be staged +let s:magit_mark_signs = {'M': 'MagitTBS', 'S': 'MagitBS', 'E': 'MagitBE'} + +" magit#sign#init: initializer function for signs +function! magit#sign#init() + execute "sign define " . s:magit_mark_signs.M . " text=S> linehl=Visual" + execute "sign define " . s:magit_mark_signs.S + execute "sign define " . s:magit_mark_signs.E +endfunction + +" magit#sign#toggle_signs: toggle marks for range of lines +" marked lines are unmarked, non marked are marked +" param[in] type; type of sign to toggle (see s:magit_mark_signs) +" param[in] startline,endline: range of lines +function! magit#sign#toggle_signs(type, startline, endline) + let bufnr = magit#utils#bufnr() + let current_signs = magit#sign#find_signs(s:magit_mark_signs[a:type], a:startline, a:endline) + let line = a:startline + while ( line <= a:endline ) + if ( has_key(current_signs, line) == 0 ) + call magit#sign#add_sign(line, a:type, bufnr) + else + call magit#sign#remove_sign(current_signs[line].id) + endif + let line += 1 + endwhile +endfunction diff --git a/.config/vim/autoload/magit/state.vim b/.config/vim/autoload/magit/state.vim @@ -0,0 +1,385 @@ +" magit#state#is_file_visible: file getter function +" return if file is visible +function! magit#state#is_file_visible() dict + return self.visible +endfunction + +" magit#state#set_file_visible: file setter function +" param[in] val: visible state to set to file +function! magit#state#set_file_visible(val) dict + let self.visible = a:val +endfunction + +" magit#state#toggle_file_visible: file setter function, toggle file visible +" state +function! magit#state#toggle_file_visible() dict + let self.visible = ( self.visible == 0 ) ? 1 : 0 +endfunction + +" magit#state#init_file_visible: init file visible status, among several conditions +function! magit#state#init_file_visible() dict + if ( !self.new ) + return self.is_visible() + else + if ( self.status == 'M' || b:magit_default_show_all_files > 1 ) + call self.set_visible(b:magit_default_show_all_files) + endif + return self.is_visible() + endif +endfunction + +" magit#state#is_file_dir: file getter function +" return 1 if current file is a directory, 0 otherwise +function! magit#state#is_file_dir() dict + return self.dir != 0 +endfunction + +" magit#state#must_be_added: file helper function +" there are some conditions where files must be widely added (git add), not +" 'diff applied' (git apply) +" return 1 if file must +function! magit#state#must_be_added() dict + return ( self.empty == 1 || + \ self.symlink != '' || + \ self.dir != 0 || + \ self.binary == 1 || + \ self.submodule == 1 ) +endfunction + +" magit#state#file_get_hunks: function accessor for hunks objects +" return: List of List of hunks lines +function! magit#state#file_get_hunks() dict + return self.diff.hunks +endfunction + +" magit#state#file_get_flat_hunks: function accessor for hunks lines +" return: all hunks lines of a file, including hunk headers +function! magit#state#file_get_flat_hunks() dict + let hunks = self.diff.hunks + let lines = [] + for hunk in hunks + call add(lines, hunk.header) + call add(lines, hunk.lines) + endfor + return lines +endfunction + +" s:hunk_template: template for hunk object (nested in s:diff_template) +" WARNING: this variable must be deepcopy()'ied +let s:hunk_template = { +\ 'header': '', +\ 'line_pos': 0, +\ 'lines': [], +\ 'marks': [], +\} + +" s:diff_template: template for diff object (nested in s:file_template) +" WARNING: this variable must be deepcopy()'ied +let s:diff_template = { +\ 'len': 0, +\ 'header': [], +\ 'hunks': [s:hunk_template], +\} + +" s:file_template: template for file object +" WARNING: this variable must be deepcopy()'ied +let s:file_template = { +\ 'new': 1, +\ 'exists': 0, +\ 'visible': 0, +\ 'filename': '', +\ 'status': '', +\ 'empty': 0, +\ 'dir': 0, +\ 'binary': 0, +\ 'submodule': 0, +\ 'symlink': '', +\ 'diff': s:diff_template, +\ 'line_pos': 0, +\ 'is_dir': function("magit#state#is_file_dir"), +\ 'is_visible': function("magit#state#is_file_visible"), +\ 'set_visible': function("magit#state#set_file_visible"), +\ 'init_visible': function("magit#state#init_file_visible"), +\ 'toggle_visible': function("magit#state#toggle_file_visible"), +\ 'must_be_added': function("magit#state#must_be_added"), +\ 'get_header': function("magit#state#file_get_header"), +\ 'get_hunks' : function("magit#state#file_get_hunks"), +\ 'get_flat_hunks' : function("magit#state#file_get_flat_hunks"), +\ 'get_filename_header' : function("magit#state#file_get_filename_header"), +\} + +" magit#state#get_file: function accessor for file +" param[in] mode: can be staged or unstaged +" param[in] filename: filename to access +" param[in] create: boolean. If 1, non existing file in Dict will be created. +" if 0, 'file_doesnt_exists' exception will be thrown +" return: Dict of file +function! magit#state#get_file(mode, filename, ...) dict + let file_exists = has_key(self.dict[a:mode], a:filename) + let create = ( a:0 == 1 ) ? a:1 : 0 + if ( file_exists == 0 && create == 1 ) + let self.dict[a:mode][a:filename] = deepcopy(s:file_template) + let self.dict[a:mode][a:filename].filename = a:filename + elseif ( file_exists == 0 && create == 0 ) + throw 'file_doesnt_exists' + endif + return self.dict[a:mode][a:filename] +endfunction + +" magit#state#file_get_header: function accessor for diff header +" param[in] mode: can be staged or unstaged +" param[in] filename: header of filename to access +" return: List of diff header lines +function! magit#state#file_get_header() dict + return self.diff.header +endfunction + +function! magit#state#file_get_filename_header() dict + if ( self.status == 'L' ) + return g:magit_git_status_code.L . ': ' . self.filename . ' -> ' . self.symlink + else + return g:magit_git_status_code[self.status] . ': ' . self.filename + endif +endfunction + +function! magit#state#check_max_lines(file) dict + let total_lines = self.nb_diff_lines + a:file.diff.len + if ( total_lines > g:magit_warning_max_lines && b:magit_warning_max_lines_answered == 0 ) + echohl WarningMsg + let ret = input("There are " . total_lines . " diff lines to display. Do you want to display all diffs? y(es) / N(o) : ", "") + echohl None + let b:magit_warning_max_lines_answered = 1 + if ( ret !~? '^y\%(e\%(s\)\?\)\?$' ) + call a:file.set_visible(0) + let a:file.diff.len = 0 + let b:magit_default_show_all_files = 0 + return 1 + endif + endif + return 0 +endfunction + +" magit#state#add_file: method to add a file with all its +" properties (filename, exists, status, header and hunks) +" param[in] mode: can be staged or unstaged +" param[in] status: one character status code of the file (AMDRCU?) +" param[in] filename: filename +function! magit#state#add_file(mode, status, filename, depth) dict + let file = self.get_file(a:mode, a:filename, 1) + let file.exists = 1 + + let file.status = a:status + let file.depth = a:depth + + " discard previous diff + let file.diff = deepcopy(s:diff_template) + + if ( a:status == '?' && getftype(a:filename) == 'link' ) + let file.status = 'L' + let file.symlink = resolve(a:filename) + let file.diff.hunks[0].header = 'New symbolic link file' + elseif ( magit#utils#is_submodule(a:filename)) + let file.status = 'S' + let file.submodule = 1 + if ( !file.is_visible() ) + return + endif + let diff_list=magit#git#git_sub_summary(magit#utils#add_quotes(a:filename), + \ a:mode) + let file.diff.len = len(diff_list) + + if ( self.check_max_lines(file) != 0 ) + return + endif + + let file.diff.hunks[0].header = '' + let file.diff.hunks[0].lines = diff_list + let self.nb_diff_lines += file.diff.len + elseif ( a:status == '?' && isdirectory(a:filename) == 1 ) + let file.status = 'N' + let file.dir = 1 + if ( !file.is_visible() ) + return + endif + for subfile in magit#utils#ls_all(a:filename) + call self.add_file(a:mode, a:status, subfile, a:depth + 1) + endfor + elseif ( a:status == '?' && getfsize(a:filename) == 0 ) + let file.status = 'E' + let file.empty = 1 + let file.diff.hunks[0].header = 'New empty file' + else + if ( !file.init_visible() ) + return + endif + let line = 0 + " match( + let [ is_bin, diff_list ] = + \ magit#git#git_diff(magit#utils#add_quotes(a:filename), + \ a:status, a:mode) + + if ( is_bin ) + let file.binary = 1 + let file.diff.hunks[0].header = 'Binary file' + if ( file.new ) + call file.set_visible(0) + endif + return + endif + + let file.diff.len = len(diff_list) + + if ( self.check_max_lines(file) != 0 ) + return + endif + + while ( line < file.diff.len && diff_list[line] !~ "^@.*" ) + call add(file.diff.header, diff_list[line]) + let line += 1 + endwhile + + if ( line < file.diff.len ) + let hunk = file.diff.hunks[0] + let hunk.header = diff_list[line] + + for diff_line in diff_list[line+1 : -1] + if ( diff_line =~ "^@.*" ) + let hunk = deepcopy(s:hunk_template) + call add(file.diff.hunks, hunk) + let hunk.header = diff_line + continue + endif + call add(hunk.lines, diff_line) + endfor + endif + let self.nb_diff_lines += file.diff.len + endif + +endfunction + +" magit#state#update: update self.dict +" if a file does not exists anymore (because all its changes have been +" committed, deleted, discarded), it is removed from g:mg_diff_dict +" else, its diff is discarded and regenrated +" what is resilient is its 'visible' parameter +function! magit#state#update() dict + let self.nb_diff_lines = 0 + for diff_dict_mode in values(self.dict) + for file in values(diff_dict_mode) + let file.exists = 0 + let file.new = 0 + " always discard previous diff + let file.diff = deepcopy(s:diff_template) + endfor + endfor + + let dir = getcwd() + try + call magit#utils#chdir(magit#git#top_dir()) + call magit#utils#refresh_submodule_list() + let status_list = magit#git#get_status() + for [mode, diff_dict_mode] in items(self.dict) + for file_status in status_list + let status=file_status[mode] + + " untracked code apperas in staged column, we skip it + if ( status == ' ' || ( ( mode == 'staged' ) && status == '?' ) ) + continue + endif + call self.add_file(mode, status, file_status.filename, 0) + endfor + endfor + finally + call magit#utils#chdir(dir) + endtry + + " remove files that have changed their mode or been committed/deleted/discarded... + for diff_dict_mode in values(self.dict) + for [key, file] in items(diff_dict_mode) + if ( file.exists == 0 ) + unlet diff_dict_mode[key] + endif + endfor + endfor +endfunction + +" magit#state#set_files_visible: global dict setter function +" update all files visible state +" param[in] is_visible: boolean value to set to files +function! magit#state#set_files_visible(is_visible) dict + for diff_dict_mode in values(self.dict) + for file in values(diff_dict_mode) + call file.set_visible(a:is_visible) + endfor + endfor +endfunction + +" magit#state#get_files: global dict file objects getter function +" param[in] mode: mode to select, can be 'staged' or 'unstaged' +" return list of file objects belonging to mode +function! magit#state#get_files(mode) dict + return self.dict[a:mode] +endfunction + +" magit#state#get_files_nb: returns the number of files in a given section +" param[in] mode: mode to select, can be 'staged' or 'unstaged' +" return number of files of this section +function! magit#state#get_files_nb(mode) dict + return len(self.dict[a:mode]) +endfunction + +" magit#state#get_files: global dict file objects (copy) getter function +" param[in] mode: mode to select, can be 'staged' or 'unstaged' +" return ordered list of file objects belonging to mode +function! magit#state#get_files_ordered(mode) dict + let modified = [] + let others = [] + for filename in sort(keys(self.dict[a:mode])) + let file = self.get_file(a:mode, filename) + if ( file.status == 'M' ) + call add(modified, file) + else + call add(others, file) + endif + endfor + return modified + others +endfunction + +" magit#state#get_filenames: global dict filenames getter function +" param[in] mode: mode to select, can be 'staged' or 'unstaged' +" return ordered list of filename strings belonging to mode, modified files +" first +function! magit#state#get_filenames(mode) dict + let files = self.get_files_ordered(a:mode) + return map(copy(files), 'v:val.filename') +endfunction + + +" dict: structure containing all diffs +" It is formatted as follow +" { +" 'staged': { +" 'filename': s:file_template, +" 'filename': s:file_template, +" ... +" }, +" 'unstaged': { +" 'filename': s:file_template, +" 'filename': s:file_template, +" ... +" }, +" } +let magit#state#state = { + \ 'nb_diff_lines': 0, + \ 'get_file': function("magit#state#get_file"), + \ 'get_files': function("magit#state#get_files"), + \ 'get_files_nb': function("magit#state#get_files_nb"), + \ 'get_files_ordered': function("magit#state#get_files_ordered"), + \ 'get_filenames': function("magit#state#get_filenames"), + \ 'add_file': function("magit#state#add_file"), + \ 'set_files_visible': function("magit#state#set_files_visible"), + \ 'check_max_lines': function("magit#state#check_max_lines"), + \ 'update': function("magit#state#update"), + \ 'dict': { 'staged': {}, 'unstaged': {}}, + \ } + diff --git a/.config/vim/autoload/magit/sys.vim b/.config/vim/autoload/magit/sys.vim @@ -0,0 +1,119 @@ +" ======= system wrappers ======= +" Recent vim/neovim versions introduced a new handy function, systemlist: +" > Same as |system()|, but returns a |List| with lines (parts of +" > output separated by NL) with NULs transformed into NLs. +" In the same time, they introduced the capabilty of system to take a list as +" parameter +" These two new behavior are emulated if not present. +" Moreover, v:shell_error are detected and an exception is thrown if any. +" Matching functions, without exception raising, are available. The problem is +" that if an error is awaited, the exception thrown discards the return value. + +" s:system: magit#sys#system internal, with explicit catch shell error +" parameter +" param[in] ...: command + optional args +" return: command output as a string +function! s:magit_system(...) + let dir = getcwd() + try + call magit#utils#chdir(magit#git#top_dir()) + " List as system() input is since v7.4.247, it is safe to check + " systemlist, which is sine v7.4.248 + if exists('*systemlist') + return call('system', a:000) + else + if ( a:0 == 2 ) + if ( type(a:2) == type([]) ) + " ouch, this one is tough: input is very very sensitive, join + " MUST BE done with "\n", not '\n' !! + let arg=join(a:2, "\n") + else + let arg=a:2 + endif + return system(a:1, arg) + else + return system(a:1) + endif + endif + finally + call magit#utils#chdir(dir) + endtry +endfunction + +" s:systemlist: magit#sys#systemlist internal, with explicit catch shell +" error parameter +" param[in] catch: boolean, do we throw an exception in case of shell error +" param[in] ...: command + optional args to execute, args can be List or String +" return: command output as a list +function! s:magit_systemlist(...) + let dir = getcwd() + try + call magit#utils#chdir(magit#git#top_dir()) + " systemlist since v7.4.248 + if exists('*systemlist') + return call('systemlist', a:000) + else + return split(call('s:magit_system', a:000), '\n') + endif + finally + call magit#utils#chdir(dir) + endtry +endfunction + +" magit#sys#system: wrapper for system, which only takes String as input in vim, +" although it can take String or List input in neovim. +" INFO: temporarly change pwd to git top directory, then restore to previous +" pwd at the end of function +" param[in] ...: command + optional args +" return: command output as a string +" throw 'shell_error' in case of shell error +function! magit#sys#system(...) + let ret = call('s:magit_system', a:000) + if ( v:shell_error != 0 ) + let b:magit_shell_error = string(ret) + let b:magit_shell_cmd = string(a:000) + throw 'shell_error' + endif + return ret +endfunction + +" magit#sys#systemlist: wrapper for systemlist, which only exists in neovim for +" the moment. +" INFO: temporarly change pwd to git top directory, then restore to previous +" pwd at the end of function +" param[in] ...: command + optional args to execute, args can be List or String +" return: command output as a list +" throw 'shell_error' in case of shell error +function! magit#sys#systemlist(...) + let ret = call('s:magit_systemlist', a:000) + if ( v:shell_error != 0 ) + let b:magit_shell_error = string(ret) + let b:magit_shell_cmd = string(a:000) + throw 'shell_error' + endif + return ret +endfunction + +" magit#sys#system_noraise: magit#sys#system alias, without error +" exception +" param[in] ...: command + optional args +" return: command output as a string +function! magit#sys#system_noraise(...) + return call('s:magit_system', a:000) +endfunction + +" magit#sys#systemlist_noraise: magit#sys#systemlist alias, without error +" exception +" param[in] ...: command + optional args to execute, args can be List or String +" return: command output as a list +function! magit#sys#systemlist_noraise(...) + return call('s:magit_systemlist', a:000) +endfunction + +function! magit#sys#print_shell_error() + echohl WarningMsg + echom "Shell command error" + echom "Cmd: " . b:magit_shell_cmd + echom "Error msg: " . b:magit_shell_error + echohl None +endfunction diff --git a/.config/vim/autoload/magit/utils.vim b/.config/vim/autoload/magit/utils.vim @@ -0,0 +1,180 @@ + +" magit#utils#ls_all: list all files (including hidden ones) in a given path +" return : list of filenames +function! magit#utils#ls_all(path) + return split(globpath(a:path, '.[^.]*', 1) . "\n" . + \ globpath(a:path, '*', 1), '\n') +endfunction + +let s:submodule_list = [] +" magit#utils#refresh_submodule_list: this function refresh the List s:submodule_list +" magit#utils#is_submodule() is using s:submodule_list +function! magit#utils#refresh_submodule_list() + let s:submodule_list = map(split(magit#git#submodule_status(), "\n"), 'split(v:val)[1]') +endfunction + +" magit#utils#is_submodule search if dirname is in s:submodule_list +" param[in] dirname: must end with / +" INFO: must be called from top work tree +function! magit#utils#is_submodule(dirname) + return ( index(s:submodule_list, a:dirname) != -1 ) +endfunction + +" magit#utils#chdir will change the directory respecting +" local/tab-local/global directory settings. +function! magit#utils#chdir(dir) + " This is a dirty hack to fix tcd breakages on neovim. + " Future work should be based on nvim API. + if exists(':tcd') + let chdir = haslocaldir() ? 'lcd' : haslocaldir(-1, 0) ? 'tcd' : 'cd' + else + let chdir = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd' + endif + execute chdir fnameescape(a:dir) +endfunction + +" magit#utils#clear_undo: this function clear local undo history. +" vimagit wants to clear undo history after each changes in vimagit buffer by +" vimagit backend. +" Use this function with caution: to be effective, the undo must be ack'ed +" with a change. The hack is the line +" exe "normal a \<BS>\<Esc>" +" We move on first line to make this trick where it should be no folding +function! magit#utils#clear_undo() + let old_undolevels = &l:undolevels + let cur_pos = line('.') + setlocal undolevels=-1 + call cursor(1, 0) + exe "normal a \<BS>\<Esc>" + call cursor(cur_pos, 0) + let &l:undolevels = old_undolevels + unlet old_undolevels +endfunction + +" magit#utils#underline: helper function to underline a string +" param[in] title: string to underline +" return a string composed of strlen(title) '=' +function! magit#utils#underline(title) + return substitute(a:title, ".", "=", "g") +endfunction + +" magit#utils#strip: helper function to strip a string +" WARNING: it only works with monoline string +" param[in] string: string to strip +" return: stripped string +function! magit#utils#strip(string) + return substitute(a:string, '^\s*\(.\{-}\)\s*\n\=$', '\1', '') +endfunction + +" magit#utils#strip_array: helper function to strip an array (remove empty rows +" on both sides) +" param[in] array: array to strop +" return: stripped array +function! magit#utils#strip_array(array) + let array_len = len(a:array) + let start = 0 + while ( start < array_len && a:array[start] == '' ) + let start += 1 + endwhile + let end = array_len - 1 + while ( end >= 0 && a:array[end] == '' ) + let end -= 1 + endwhile + return a:array[ start : end ] +endfunction + +" magit#utils#join_list: helper function to concatente a list of strings with newlines +" param[in] list: List to concat +" return: concatenated list +function! magit#utils#join_list(list) + return join(a:list, "\n") . "\n" +endfunction + +" magit#utils#add_quotes: helper function to protect filename with quotes +" return quoted filename +function! magit#utils#add_quotes(filename) + return '"' . a:filename . '"' +endfunction + +" magit#utils#remove_quotes: helper function to remove quotes aroudn filename +" return unquoted filename +function! magit#utils#remove_quotes(filename) + let ret=matchlist(a:filename, '"\([^"]*\)"') + if ( empty(ret) ) + throw 'no quotes found: ' . a:filename + endif + return ret[1] +endfunction + +" magit#utils#fatten: flat a nested list. it return a one dimensional list with +" primary elements +" https://gist.github.com/dahu/3322468 +" param[in] list: a List, can be nested or not +" return: one dimensional list +function! magit#utils#flatten(list) + let val = [] + for elem in a:list + if type(elem) == type([]) + call extend(val, magit#utils#flatten(elem)) + else + call extend(val, [elem]) + endif + unlet elem + endfor + return val +endfunction + +" magit#utils#append_file: helper function to append to a file +" Version working with file *possibly* containing trailing newline +" param[in] file: filename to append +" param[in] lines: List of lines to append +function! magit#utils#append_file(file, lines) + let fcontents=[] + if ( filereadable(a:file) ) + let fcontents=readfile(a:file, 'b') + endif + if !empty(fcontents) && empty(fcontents[-1]) + call remove(fcontents, -1) + endif + call writefile(fcontents+a:lines, a:file, 'b') +endfunction + +" s:bufnr: local variable to store current magit buffer id +let s:bufnr = 0 +" magit#utils#setbufnr: function to set current magit buffer id +" param[in] bufnr: current magit buffer id +function! magit#utils#setbufnr(bufnr) + let s:bufnr = a:bufnr +endfunction + +" magit#utils#bufnr: function to get current magit buffer id +" return: current magit buffer id +function! magit#utils#bufnr() + return s:bufnr +endfunction + +" magit#utils#search_buffer_in_windows: search if a buffer is displayed in one +" of opened windows +" NOTE: windo command modify winnr('#'), if you want to use it, save it before +" calling this function +" param[in] filename: filename to search +" return: window id, 0 if not found +function! magit#utils#search_buffer_in_windows(filename) + let cur_win = winnr() + let last_win = winnr('#') + let files={} + windo if ( !empty(@%) ) | let files[@%] = winnr() | endif + execute last_win."wincmd w" + execute cur_win."wincmd w" + return ( has_key(files, buffer_name(a:filename)) ) ? + \files[buffer_name(a:filename)] : 0 +endfunction + +function! magit#utils#start_profile(...) + let prof_file = ( a:0 == 1 ) ? a:1 : "/tmp/vimagit.log" + profdel * + execute "profile start " . prof_file . " | profile pause" + profile file * + profile func * + profile continue +endfunction diff --git a/.config/vim/colors/.vimrc b/.config/vim/colors/.vimrc diff --git a/.config/vim/common/magit_common.vim b/.config/vim/common/magit_common.vim @@ -0,0 +1,62 @@ +" Section names +" These are used to beautify the magit buffer and to help for some block +" selection +let g:magit_sections = { + \ 'info': 'Info', + \ 'help': 'Help', + \ 'staged': 'Staged changes', + \ 'unstaged': 'Unstaged changes', + \ 'commit': 'Commit message', + \ 'stash': 'Stash list' + \ } + +let g:magit_section_info = { + \ 'cur_repo': 'Repository:', + \ 'cur_head': 'Head:', + \ 'cur_upstream': 'Upstream:', + \ 'cur_push': 'Push:', + \ 'commit_mode': 'Commit mode:', + \ } + +let g:magit_git_status_code = { + \ 'M': 'modified', + \ 'A': 'added', + \ 'D': 'deleted', + \ 'R': 'renamed', + \ 'T': 'typechanged', + \ 'C': 'copied', + \ 'U': 'updated but unmerged', + \ '?': 'untracked', + \ '!': 'ignored', + \ 'E': 'empty', + \ 'L': 'symlink', + \ 'N': 'new dir', + \ 'S': 'submodule', + \ } + +let g:magit_commit_mode = { + \ 'CC': 'normal', + \ 'CA': 'amend', + \ } + +" Regular expressions used to select blocks +let g:magit_file_re = '^\(' +for status_code in values(g:magit_git_status_code) + let g:magit_file_re .= status_code . '\|' +endfor +let g:magit_file_re .= 'unknown status\): \(.\{-\}\)\%( -> .*\)\?$' + +let g:magit_section_re = '^\(' +for section_name in values(g:magit_sections) + let g:magit_section_re .= section_name . '\|' +endfor +let g:magit_section_re .= 'unknown section\)$' + +let g:magit_diff_re = '^diff --git' +let g:magit_end_diff_re = '^$' +let g:magit_stash_re = '^stash@{\d\+}:' +let g:magit_hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@' +let g:magit_bin_re = '^Binary files ' +let g:magit_eof_re = '\%$' + + diff --git a/.config/vim/plugin/deadkeys.vim b/.config/vim/plugin/deadkeys.vim @@ -0,0 +1,253 @@ +let g:DeadKeysOn=0 + +function! ToggleDeadKeys() + if !g:DeadKeysOn + call DeadKeys() + else + call DeadKeysOff() + endif +endfunction + +function! DeadKeys() + echo "Dead Keys: On" + let g:DeadKeysOn=1 + " grave accents + imap `a à + imap `e è + imap `i ì + imap `o ò + imap `u ù + imap `A À + imap `E È + imap `I Ì + imap `O Ò + imap `U Ù + imap `<space> ` + + " umlaut + imap "a ä + imap "e ë + imap "i ï + imap "o ö + imap "u ü + imap "A Ä + imap "E Ë + imap "I Ï + imap "O Ö + imap "U Ü + imap "<space> " + + " macrons + imap :a ā + imap :e ē + imap :i ī + imap :o ō + imap :u ū + imap :A Ā + imap :E Ē + imap :I Ī + imap :O Ō + imap :U Ū + + " acute accents + imap 'a á + imap 'A Á + imap 'C Ć + imap 'c ć + imap 'e é + imap 'E É + imap 'i í + imap 'I Í + imap 'N Ń + imap 'n ń + imap 'o ó + imap 'R Ŕ + imap 'r ŕ + imap 'S Ś + imap 's ś + imap 'O Ó + imap 'u ú + imap 'U Ú + imap '<space> ' + + " under dot + imap .D Ḍ + imap .d ḍ + imap .H Ḥ + imap .h ḥ + imap .L Ḹ + imap .l ḹ + imap .M Ṃ + imap .m ṃ + imap .N Ṇ + imap .n ṇ + imap .R Ṛ + imap .r ṛ + imap .G Ṝ + imap .g ṝ + imap .S Ṣ + imap .s ṣ + imap .T Ṭ + imap .t ṭ + + " tilde + imap ~a ã + imap ~A à + imap ~e ẽ + imap ~E Ẽ + imap ~i ĩ + imap ~I Ĩ + imap ~o õ + imap ~O Õ + imap ~u ũ + imap ~U Ũ + imap ~n ñ + imap ~N Ñ + + " caron + imap >A Ǎ + imap >a ǎ + imap >C Č + imap >c č + imap >E Ě + imap >e ě + imap >G Ǧ + imap >g ǧ + imap >I Ǐ + imap >i ǐ + imap >O Ǒ + imap >o ǒ + imap >R Ř + imap >r ř + imap >S Ṧ + imap >s ṧ + imap >U Ǔ + imap >u ǔ + imap >V Ǚ + imap >v ǚ + imap >Z Ž + imap >z ž + +endfunction "deadkeys() + + +function! DeadKeysOff() + echo "Dead Keys: Off" + let g:DeadKeysOn=0 + + " unmapping graves + iunmap `a + iunmap `e + iunmap `i + iunmap `o + iunmap `u + iunmap `A + iunmap `E + iunmap `I + iunmap `O + iunmap `U + iunmap `<space> + + " unmapping umlauts + iunmap "a + iunmap "e + iunmap "i + iunmap "o + iunmap "u + iunmap "A + iunmap "E + iunmap "I + iunmap "O + iunmap "U + iunmap "<space> + + " unmapping macrons + iunmap :a + iunmap :e + iunmap :i + iunmap :o + iunmap :u + iunmap :A + iunmap :E + iunmap :I + iunmap :O + iunmap :U + + " unmapping acutes + iunmap 'a + iunmap 'A + iunmap 'C + iunmap 'c + iunmap 'e + iunmap 'E + iunmap 'i + iunmap 'I + iunmap 'N + iunmap 'n + iunmap 'o + iunmap 'R + iunmap 'r + iunmap 'S + iunmap 's + iunmap 'O + iunmap 'u + iunmap 'U + iunmap '<space> + " under dot + iunmap .D + iunmap .d + iunmap .H + iunmap .h + iunmap .L + iunmap .l + iunmap .M + iunmap .m + iunmap .N + iunmap .n + iunmap .R + iunmap .r + iunmap .G + iunmap .g + iunmap .S + iunmap .s + iunmap .T + iunmap .t + + "tilde + iunmap ~a + iunmap ~A + iunmap ~e + iunmap ~E + iunmap ~i + iunmap ~I + iunmap ~o + iunmap ~O + iunmap ~u + iunmap ~U + iunmap ~n + + " caron + iunmap >A + iunmap >a + iunmap >C + iunmap >c + iunmap >E + iunmap >e + iunmap >G + iunmap >g + iunmap >I + iunmap >i + iunmap >O + iunmap >o + iunmap >R + iunmap >r + iunmap >S + iunmap >s + iunmap >U + iunmap >u + iunmap >V + iunmap >v + iunmap >Z + iunmap >z + +endfunction diff --git a/.config/vim/plugin/goyo.vim b/.config/vim/plugin/goyo.vim @@ -0,0 +1,24 @@ +" Copyright (c) 2015 Junegunn Choi +" +" MIT License +" +" Permission is hereby granted, free of charge, to any person obtaining +" a copy of this software and associated documentation files (the +" "Software"), to deal in the Software without restriction, including +" without limitation the rights to use, copy, modify, merge, publish, +" distribute, sublicense, and/or sell copies of the Software, and to +" permit persons to whom the Software is furnished to do so, subject to +" the following conditions: +" +" The above copyright notice and this permission notice shall be +" included in all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +command! -nargs=? -bar -bang Goyo call goyo#execute(<bang>0, <q-args>) diff --git a/.config/vim/plugin/ipa.vim b/.config/vim/plugin/ipa.vim @@ -0,0 +1,186 @@ +let g:IPAOn=0 + +function! ToggleIPA() + if !g:IPAOn + call IPA() + else + call IPAOff() + endif +endfunction + +function! IPA() + echo "IPA macros activated" + let g:IPAOn=1 + imap ,nn ɲ̊ + imap ,gn ɲ + imap ,ng ŋ + imap ,' ʔ + imap ,sh ʃ + imap ,zh ʒ + imap ,xi ɕ + imap ,zi ʑ + imap ,ph ɸ + imap ,bh β + imap ,th θ + imap ,dh ð + imap ,cc ç + imap ,jj ʝ + imap ,gh ɣ + imap ,xx χ + imap ,fr ʁ + imap ,HH ħ + imap ,hh ɦ + imap ,vv ʋ + imap ,er ɹ + imap ,fl ɾ + imap ,bb ʙ + imap ,ih ɨ + imap ,ii ɪ + imap ,eu ɯ̽ + imap ,uu ʊ + imap ,uh ə + imap ,eh ɛ + imap ,oe œ + imap ,au ɔ + imap ,ae æ + imap ,aa ɐ + imap ,OE ɶ + imap ,ah ɑ + imap ,ba ɒ +endfunction + +function! IPAOff() + echo "IPA macros off." + let g:IPAOn=0 + iunmap ,nn + iunmap ,gn + iunmap ,ng + iunmap ,' + iunmap ,sh + iunmap ,zh + iunmap ,xi + iunmap ,zi + iunmap ,ph + iunmap ,bh + iunmap ,th + iunmap ,dh + iunmap ,cc + iunmap ,jj + iunmap ,gh + iunmap ,xx + iunmap ,fr + iunmap ,HH + iunmap ,hh + iunmap ,vv + iunmap ,er + iunmap ,fl + iunmap ,bb + iunmap ,ih + iunmap ,ii + iunmap ,eu + iunmap ,uu + iunmap ,uh + iunmap ,eh + iunmap ,oe + iunmap ,au + iunmap ,ae + iunmap ,aa + iunmap ,OE + iunmap ,ah + iunmap ,ba +endfunction + +" As of yet unimplemented: +"b̪ +"t̼ +"d̼ +"ʈ +"ɖ +"ɟ +"ɡ +"ɢ +"ʡ +"ʂ +"ʐ +"θ̼ +"ð̼ +"θ̠ +"ð̠ +"ɹ̠̊ +"ɹ̠ +"ɻ +"ʕ +"ʢ +"ʋ̥ +"ɹ̥ +"ɻ̊ +"ɻ +"j̊ +"ɰ̊ +"ɰ +"ʔ̞ +"ⱱ̟ +"ⱱ +"ɾ̼ +"ɾ̥ +"ɽ̊ +"ɽ +"ɢ̆ +"ʡ̮ +"ʙ̥ +"r̼ +"r̥ +"ɽ̊ +"ɽ +"ʀ̥ +"ʀ +"ʜ +"ʢ +"ɬ +"ɮ +"ɭ̊ +"ʎ̥ +"ʎ̝ +"ʟ̝̊ +"ʟ̝ +"l̥ +"ɭ̊ +"ɭ +"ʎ̥ +"ʎ +"ʟ̥ +"ʟ +"ʟ̠ +"ɺ +"ɺ̢ +"ʎ̮ +"ʟ̆ +"ʉ +"ɯ +"ʏ +"ɪ̈ +"ʊ̈ +"ø +"ɘ +"ɵ +"ɤ +"e̞ +"ø̞ +"ɵ̞ +"ɤ̞ +"o̞ +"ɜ +"ɞ +"ʌ +"ɞ̞ +"ä +"ɒ̈ +"m̥ +"ɱ +"n̼ +"n̥ +"ɳ̊ +"ɳ +"ŋ̊ +"ɴ +"p̪ diff --git a/.config/vim/plugin/magit.vim b/.config/vim/plugin/magit.vim @@ -0,0 +1,1357 @@ +scriptencoding utf-8 + +if exists('g:loaded_magit') || !executable('git') || &cp + finish +endif +let g:loaded_magit = 1 + +let g:vimagit_version = [1, 7, 3] + +" Initialisation {{{ + +" FIXME: find if there is a minimum vim version required +" if v:version < 703 +" endif + +" source common file. variables in common file are shared with plugin and +" syntax files +let g:vimagit_path = fnameescape(resolve(expand('<sfile>:p:h'))) +execute 'source ' . g:vimagit_path . '/../common/magit_common.vim' + +" these mappings are broadly applied, for all vim buffers +let g:magit_show_magit_mapping = get(g:, 'magit_show_magit_mapping', '<leader>M' ) + +" user options +let g:magit_enabled = get(g:, 'magit_enabled', 1) +let g:magit_show_help = get(g:, 'magit_show_help', 0) +let g:magit_default_show_all_files = get(g:, 'magit_default_show_all_files', 1) +let g:magit_default_fold_level = get(g:, 'magit_default_fold_level', 1) +let g:magit_auto_close = get(g:, 'magit_auto_close', 0) +let g:magit_auto_foldopen = get(g:, 'magit_auto_foldopen', 1) +let g:magit_default_sections = get(g:, 'magit_default_sections', ['info', 'global_help', 'commit', 'staged', 'unstaged']) +let g:magit_discard_untracked_do_delete = get(g:, 'magit_discard_untracked_do_delete', 0) + +let g:magit_refresh_gutter = get(g:, 'magit_refresh_gutter' , 1) +" Should deprecate the following +let g:magit_refresh_gitgutter = get(g:, 'magit_refresh_gitgutter', 0) + +let g:magit_commit_title_limit = get(g:, 'magit_commit_title_limit', 50) + +let g:magit_scrolloff = get(g:, 'magit_scrolloff', 3) + +let g:magit_warning_max_lines = get(g:, 'magit_warning_max_lines', 10000) + +let g:magit_git_cmd = get(g:, 'magit_git_cmd' , "git") + +execute "nnoremap <silent> " . g:magit_show_magit_mapping . " :call magit#show_magit('v')<cr>" + +if (g:magit_refresh_gutter == 1 || g:magit_refresh_gitgutter == 1) + autocmd User VimagitUpdateFile + \ if ( exists("*gitgutter#process_buffer") ) | + \ call gitgutter#process_buffer(bufnr(g:magit_last_updated_buffer), 0) | + \ elseif ( exists("*sy#util#refresh_windows") ) | + \ call sy#util#refresh_windows() | + \ endif +endif +" }}} + +" s:mg_cut_str cut a string given a limit size +" param[in] str string to cut +" param[in] limit maximum number of column +" return string cut on limit +function! s:mg_cut_str(str, limit) + if ( len(a:str) < a:limit ) + return a:str + elseif ( ( a:limit - 3 ) < 0 ) + return "" + else + return printf("%.*s...", a:limit - 3, a:str) + endif +endfunction + +" s:mg_get_info: this function writes in current buffer current git state +" WARNING: this function writes in file, it should only be called through +" protected functions like magit#update_buffer +function! s:mg_get_info() + let align_w=12 + + let repo_line=printf("%-*s %s", + \ align_w, + \ g:magit_section_info.cur_repo, + \ magit#git#top_dir()) + + try + let head_br=magit#git#get_branch_name("HEAD") + catch 'shell_error' + let head_br="Empty repository" + endtry + let upstream_br=magit#git#get_remote_branch("HEAD", "upstream") + let push_br=magit#git#get_remote_branch("HEAD", "push") + let max_br_w = max([len(head_br), len(upstream_br), len(push_br)]) + + let limit=winwidth(0)-align_w-max_br_w-3 + let head_msg=s:mg_cut_str(magit#git#get_commit_subject("HEAD"), limit) + let upstream_msg=s:mg_cut_str(magit#git#get_commit_subject(upstream_br), limit) + let push_msg=s:mg_cut_str(magit#git#get_commit_subject(push_br), limit) + + let head_line=magit#utils#strip(printf("%-*s %-*s %s", + \ align_w, g:magit_section_info.cur_head, + \ max_br_w, head_br, head_msg)) + let upstream_line=magit#utils#strip(printf("%-*s %-*s %s", + \ align_w, g:magit_section_info.cur_upstream, + \ max_br_w, upstream_br, upstream_msg)) + let push_line=magit#utils#strip(printf("%-*s %-*s %s", + \ align_w, g:magit_section_info.cur_push, + \ max_br_w, push_br, push_msg)) + + + silent put =g:magit_sections.info + silent put =magit#utils#underline(g:magit_sections.info) + silent put ='' + silent put =repo_line + silent put =head_line + silent put =upstream_line + silent put =push_line + + if ( b:magit_current_commit_mode != '' ) + let commit_mode_line=printf("%-*s %s", + \ align_w, g:magit_section_info.commit_mode, + \ g:magit_commit_mode[b:magit_current_commit_mode]) + silent put =commit_mode_line + endif + silent put ='' + silent put ='Press ? to display help' + silent put ='' + silent put ='' +endfunction + +" s:mg_display_files: display in current buffer files, filtered by some +" parameters +" param[in] mode: files mode, can be 'staged' or 'unstaged' +" param[in] curdir: directory containing files (only needed for untracked +" directory) +" param[in] depth: current directory depth (only needed for untracked +" directory) +function! s:mg_display_files(mode, curdir, depth) + + " FIXME: ouch, must store subdirs in more efficient way + for filename in b:state.get_filenames(a:mode) + let file = b:state.get_file(a:mode, filename, 0) + if ( file.depth != a:depth || filename !~ a:curdir . '.*' ) + continue + endif + silent put =file.get_filename_header() + let file.line_pos = line('.') + + if ( file.dir != 0 ) + if ( file.visible == 1 ) + call s:mg_display_files(a:mode, filename, a:depth + 1) + continue + endif + endif + + if ( file.visible == 0 ) + silent put ='' + continue + endif + if ( file.exists == 0 ) + echoerr "Error, " . filename . " should not exists" + endif + let hunks = file.get_hunks() + for hunk in hunks + if ( hunk.header != '' ) + silent put =hunk.header + let hunk.line_pos = line('.') + endif + if ( !empty(hunk.lines) ) + silent put =hunk.lines + endif + endfor + silent put ='' + endfor +endfunction + +" s:mg_get_staged_section: this function writes in current buffer all staged +" or unstaged files, using b:state.dict information +" WARNING: this function writes in file, it should only be called through +" protected functions like magit#update_buffer +" param[in] mode: 'staged' or 'unstaged' +function! s:mg_get_staged_section(mode) + silent put =g:magit_sections[a:mode] + call magit#mapping#get_section_help(a:mode) + silent put =magit#utils#underline(g:magit_sections[a:mode]) + silent put ='' + call s:mg_display_files(a:mode, '', 0) + silent put ='' +endfunction + +" s:mg_get_stashes: this function write in current buffer all stashes +" WARNING: this function writes in file, it should only be called through +" protected functions like magit#update_buffer +function! s:mg_get_stashes() + try + silent! let stash_list=magit#sys#systemlist(g:magit_git_cmd . " stash list") + catch 'shell_error' + call magit#sys#print_shell_error() + return + endtry + + if (!empty(stash_list)) + silent put =g:magit_sections.stash + silent put =magit#utils#underline(g:magit_sections.stash) + silent put ='' + + for stash in stash_list + let stash_id=substitute(stash, '^\(stash@{\d\+}\):.*$', '\1', '') + silent put =stash + silent! execute "read !git stash show -p " . stash_id + endfor + silent put ='' + silent put ='' + endif +endfunction + +" b:magit_current_commit_msg: this variable store the current commit message, +" saving it among refreshes (remember? the whole buffer is wiped at each +" refresh). +let b:magit_current_commit_msg = [] + +" s:mg_get_commit_section: this function writes in current buffer the commit +" section. It is a commit message, depending on b:magit_current_commit_mode +" WARNING: this function writes in file, it should only be called through +" protected functions like magit#update_buffer +" param[in] b:magit_current_commit_mode: this function uses global commit mode +" 'CC': prepare a brand new commit message +" 'CA': get the last commit message +function! s:mg_get_commit_section() + if ( b:magit_current_commit_mode != '' ) + silent put =g:magit_sections.commit + silent put =magit#utils#underline(g:magit_sections.commit) + + let git_dir=magit#git#git_dir() + " refresh the COMMIT_EDITMSG file + if ( b:magit_current_commit_mode == 'CC' ) + silent! call magit#sys#system_noraise("GIT_EDITOR=/bin/false " . + \ g:magit_git_cmd . " -c commit.verbose=no commit -e 2> /dev/null") + elseif ( b:magit_current_commit_mode == 'CA' ) + silent! call magit#sys#system_noraise("GIT_EDITOR=/bin/false " . + \ g:magit_git_cmd . " -c commit.verbose=no commit --amend -e 2> /dev/null") + endif + if ( !empty(b:magit_current_commit_msg) ) + silent put =b:magit_current_commit_msg + elseif ( filereadable(git_dir . 'COMMIT_EDITMSG') ) + let comment_char=magit#git#get_config("core.commentChar", '#') + let commit_msg=magit#utils#join_list(filter(readfile(git_dir . 'COMMIT_EDITMSG'), 'v:val !~ "^' . comment_char . '"')) + silent put =commit_msg + endif + silent put ='' + silent put ='' + endif +endfunction + +" s:mg_search_block: helper function, to get start and end line of a block, +" giving a start and multiple end pattern +" a "pattern parameter" is a List: +" @[0]: end pattern regex +" @[1]: number of line to exclude above (negative), below (positive) or none (0) +" param[in] start_pattern: start "pattern parameter", which will be search +" backward (cursor position is set to end of line before searching, to find the +" pattern if on the current line) +" param[in] end_pattern: list of end "pattern parameter". Each pattern is +" searched in order. It'll choose the match with the minimum line number +" (smallest region search) +" param[in] upperlimit_pattern: regex of upper limit. If start_pattern line is +" inferior to upper_limit line, block is discarded +" param[in]: end_pattern_on_cursor: boolean, if true end pattern is also +" search on cursor position +" return: [startline, endline] +function! s:mg_search_block(start_pattern, end_pattern, upper_limit_pattern, + \ end_pattern_on_cursor) + + let upper_limit=0 + if ( a:upper_limit_pattern != "" ) + let upper_limit=search(a:upper_limit_pattern, "cbnW") + endif + + let start=search(a:start_pattern[0], "cbnW") + if ( start == 0 || start < upper_limit ) + throw "out_of_block" + endif + let start+=a:start_pattern[1] + + let end=0 + let min=line('$') + for end_p in a:end_pattern + let curr_end=search(end_p[0], a:end_pattern_on_cursor ? "c" : "" . "nW") + if ( curr_end != 0 && curr_end <= min ) + let end=curr_end + end_p[1] + let min=curr_end + endif + endfor + if ( end == 0 ) + throw "out_of_block" + endif + + return [start,end] +endfunction + +" s:mg_get_commit_msg: get the commit meesgae currently in commit section +" return a string containg the commit message +" \param[in] out_of_block (optional): if set, will first move the cursor to +" the commit block before getting content +function! s:mg_get_commit_msg(...) + let commit_section_pat_start='^'.g:magit_sections.commit.'$' + " Get next section pattern with g:magit_default_sections order + let commit_position = match(g:magit_default_sections, 'commit') + if ( commit_position + 1 == len(g:magit_default_sections) ) + let commit_section_pat_end='\%$' + else + let commit_section_pat_end='^'.g:magit_sections[g:magit_default_sections[commit_position+1]].'$' + endif + + let commit_jump_line = 2 + let out_of_block = a:0 == 1 ? a:1 : 0 + if ( out_of_block ) + let old_pos=line('.') + let commit_pos=search(commit_section_pat_start, "cw") + if ( commit_pos != 0 ) + call cursor(commit_pos+1, 0) + endif + endif + try + let [start, end] = <SID>mg_search_block( + \ [commit_section_pat_start, commit_jump_line], + \ [ [commit_section_pat_end, -1] ], "", 1) + finally + if ( out_of_block && commit_pos != 0 ) + call cursor(old_pos, 0) + endif + endtry + return magit#utils#strip_array(getline(start, end)) +endfunction + +" s:mg_git_commit: commit staged stuff with message prepared in commit section +" param[in] mode: mode to commit +" 'CF': don't use commit section, just amend previous commit with staged +" stuff, without modifying message +" 'CC': commit staged stuff with message in commit section to a brand new +" commit +" 'CA': commit staged stuff with message in commit section amending last +" commit +" return no +function! s:mg_git_commit(mode) abort + if ( a:mode == 'CF' ) + try + silent let git_result=magit#sys#system(g:magit_git_cmd . + \ " commit --amend -C HEAD") + catch 'shell_error' + call magit#sys#print_shell_error() + echoerr "Commit fix failed" + endtry + else + let commit_flag="" + if ( a:mode != 'CA' && empty( magit#get_staged_files() ) ) + let choice = confirm( + \ "Do you really want to commit without any staged files?", + \ "&Yes\n&No", 2) + if ( choice != 1 ) + return + else + let commit_flag.=" --allow-empty " + endif + endif + + let commit_msg=s:mg_get_commit_msg() + if ( empty( commit_msg ) ) + let choice = confirm( + \ "Do you really want to commit with an empty message?", + \ "&Yes\n&No", 2) + if ( choice != 1 ) + return + else + let commit_flag.=" --allow-empty-message " + endif + endif + + if ( a:mode == 'CA' ) + let commit_flag.=" --amend " + endif + let commit_cmd=g:magit_git_cmd . " commit " . commit_flag . + \ " --file - " + try + silent! let git_result=magit#sys#system(commit_cmd, commit_msg) + catch 'shell_error' + call magit#sys#print_shell_error() + echoerr "Commit failed" + endtry + let b:magit_current_commit_mode='' + let b:magit_current_commit_msg=[] + endif + let b:magit_just_commited = 1 +endfunction + +" s:mg_select_file_block: select the whole diff file, relative to the current +" cursor position +" nota: if the cursor is not in a diff file when the function is called, this +" function will fail +" return: a List +" @[0]: return value +" @[1]: List of lines containing the patch for the whole file +function! s:mg_select_file_block() + return <SID>mg_search_block( + \ [g:magit_file_re, 1], + \ [ [g:magit_end_diff_re, 0], + \ [g:magit_file_re, -1], + \ [g:magit_stash_re, -1], + \ [g:magit_section_re, -2], + \ [g:magit_bin_re, 0], + \ [g:magit_eof_re, 0 ] + \ ], + \ "", + \ 0) +endfunction + +" s:mg_select_hunk_block: select a hunk, from the current cursor position +" nota: if the cursor is not in a hunk when the function is called, this +" function will fail +" return: a List +" @[0]: return value +" @[1]: List of lines containing the hunk +function! s:mg_select_hunk_block() + return <SID>mg_search_block( + \ [g:magit_hunk_re, 0], + \ [ [g:magit_hunk_re, -1], + \ [g:magit_end_diff_re, 0], + \ [g:magit_file_re, -1], + \ [g:magit_stash_re, -1], + \ [g:magit_section_re, -2], + \ [g:magit_eof_re, 0 ] + \ ], + \ g:magit_file_re, + \ 0) +endfunction + +" s:mg_create_diff_from_select: craft the diff to apply from a selection +" in a chunk +" remarks: it works with full lines, and can not span over multiple chunks +" param[in] select_lines: List containing all selected line numbers +" return: List containing the diff to apply, including the chunk header (must +" be applied with git apply --recount) +function! s:mg_create_diff_from_select(select_lines) + let start_select_line = a:select_lines[0] + let end_select_line = a:select_lines[-1] + let [starthunk,endhunk] = <SID>mg_select_hunk_block() + if ( start_select_line < starthunk || end_select_line > endhunk ) + throw 'out of hunk selection' + endif + let section=magit#helper#get_section() + let filename=magit#helper#get_filename() + let hunks = b:state.get_file(section, filename).get_hunks() + for hunk in hunks + if ( hunk.header == getline(starthunk) ) + let current_hunk = hunk + break + endif + endfor + let selection = [] + call add(selection, current_hunk.header) + + let current_line = starthunk + 1 + " when staging by visual selection, lines out of selection must be + " ignored. To do so, + lines are simply ignored, - lines are considered as + " untouched. + " For unstaging, - lines must be ignored and + lines considered untouched. + if ( section == 'unstaged' ) + let remove_line_char = '+' + let replace_line_char = '-' + else + let remove_line_char = '-' + let replace_line_char = '+' + endif + for hunk_line in current_hunk.lines + if ( index(a:select_lines, current_line) != -1 ) + call add(selection, getline(current_line)) + elseif ( hunk_line =~ '^'.remove_line_char.'.*' ) + " just ignore these lines + elseif ( hunk_line =~ '^'.replace_line_char.'.*' ) + call add(selection, substitute(hunk_line, + \ '^'.replace_line_char.'\(.*\)$', ' \1', '')) + elseif ( hunk_line =~ '^ .*' ) + call add(selection, hunk_line) + else + throw 'visual selection error: ' . hunk_line + endif + let current_line += 1 + endfor + return selection +endfunction + +" s:mg_mark_lines_in_hunk: this function toggle marks for selected lines in a +" hunk. +" if a hunk contains marked lines, only these lines will be (un)staged on next +" (un)stage command +" param[in] start_select_line,end_select_line: limits of the selection +function! s:mg_mark_lines_in_hunk(start_select_line, end_select_line) + let [starthunk,endhunk] = <SID>mg_select_hunk_block() + if ( a:start_select_line < starthunk || a:end_select_line > endhunk ) + throw 'out of hunk selection' + endif + return magit#sign#toggle_signs('M', a:start_select_line, a:end_select_line) +endfunction + +" }}} + +" {{{ User functions and commands + +" magit#open_close_folding() +" param[in] visible : boolean, force visible value. If not set, toggle +" visibility +function! magit#open_close_folding(...) + let list = matchlist(getline("."), g:magit_file_re) + if ( empty(list) ) + throw 'non file header line: ' . getline(".") + endif + let filename = list[2] + let section=magit#helper#get_section() + " if first param is set, force visible to this value + " else, toggle value + let file = b:state.get_file(section, filename, 0) + if ( a:0 == 1 ) + call file.set_visible(a:1) + else + call file.toggle_visible() + endif + call magit#update_buffer() +endfunction + +let g:magit_last_updated_buffer = '' + +" s:mg_display_functions: Dict wrapping all display related functions +" This Dict should be accessed through g:magit_default_sections +let s:mg_display_functions = { + \ 'info': { 'fn': function("s:mg_get_info"), 'arg': []}, + \ 'global_help': { 'fn': function("magit#mapping#get_section_help"), 'arg': ['global']}, + \ 'commit': { 'fn': function("s:mg_get_commit_section"), 'arg': []}, + \ 'staged': { 'fn': function("s:mg_get_staged_section"), 'arg': ['staged']}, + \ 'unstaged': { 'fn': function("s:mg_get_staged_section"), 'arg': ['unstaged']}, + \ 'stash': { 'fn': function("s:mg_get_stashes"), 'arg': []}, +\ } + +" magit#update_buffer: this function: +" 1. checks that current buffer is the wanted one +" 2. save window state (cursor position...) +" 3. delete buffer +" 4. fills with unstage stuff +" 5. restore window state +" param[in] updated file (optional): this filename is updated to absolute +" path, set in g:magit_last_updated_buffer and the User autocmd +" param[in] current section (optional) +" param[in] current hunk id +" when params 1 & 2 & 3 are set, it means +" that a stage/unstage action occured. We try to smartly set the cursor +" position after the refresh +" - on current file on closest hunk if still contains hunks in current section +" - else on next file if any +" - else on previous file if any +" - or cursor stay where it is +" VimagitUpdateFile event is raised +function! magit#update_buffer(...) + let buffer_name=bufname("%") + " (//|\\\\) is to handle old vim 7.4-0 fnameescape behavior on Windows + if ( buffer_name !~ "\\v^magit:(//|\\\\).*" ) + echoerr "Not in magit buffer but in " . buffer_name + return + endif + + if ( a:0 >= 1 ) + let cur_filename = a:1 + endif + if ( a:0 >= 2 ) + let cur_section = a:2 + endif + if ( a:0 >= 3 ) + let cur_hunk_id = a:3 + endif + + if ( b:magit_current_commit_mode != '' ) + try + let b:magit_current_commit_msg = s:mg_get_commit_msg(1) + catch /^out_of_block$/ + let b:magit_current_commit_msg = [] + endtry + call s:set_mode_write() + else + call s:set_mode_read() + endif + " FIXME: find a way to save folding state. According to help, this won't + " help: + " > This does not save fold information. + " Playing with foldenable around does not help. + " mkview does not help either. + let l:winview = winsaveview() + + " remove all signs (needed as long as we wipe buffer) + call magit#sign#remove_all() + + " remove folding while we are updating the buffer. writing to the buffer + " while the folding is enabled can be veryyyyy slow. + " One last strange thing is that, the first time the buffer is written, it + " is not slow at all. It is slow the second time, at first refresh (can be + " order of seconds). Then at third time (2nd refresh), it is fast again. + " refs: + " https://github.com/jreybert/vimagit/issues/170 + " https://github.com/jreybert/vimagit/issues/36 (maybe) + setlocal foldmethod=manual + " delete buffer + silent! execute "silent :%delete _" + + " be smart for the cursor position after refresh, if stage/unstaged + " occured + if ( a:0 >= 2 ) + let filenames = b:state.get_filenames(cur_section) + let pos = match(filenames, cur_filename) + let next_filename = (pos < len(filenames) - 1) ? filenames[pos+1] : '' + let prev_filename = (pos > 0) ? filenames[pos-1] : '' + endif + + call b:state.update() + + if ( g:magit_auto_close == 1 && + \ b:magit_just_commited == 1 && + \ empty(b:state.get_filenames('staged')) && + \ empty(b:state.get_filenames('unstaged')) ) + let b:magit_just_commited = 0 + call magit#close_magit() + return + endif + + for section in g:magit_default_sections + try + let func = s:mg_display_functions[section] + catch + echohl WarningMsg + echom 'unknown section to display: ' . section + echom 'please check your redefinition of g:magit_default_sections' + echohl None + endtry + call call(func.fn, func.arg) + endfor + + call winrestview(l:winview) + + call magit#utils#clear_undo() + + setlocal filetype=magit + setlocal foldmethod=syntax + + if ( b:magit_current_commit_mode != '' && b:magit_commit_newly_open == 1 ) + let commit_section_pat_start='^'.g:magit_sections.commit.'$' + silent! let section_line=search(commit_section_pat_start, "w") + silent! call cursor(section_line+2+magit#mapping#get_section_help_line_nb('commit'), 0) + if exists('#User#VimagitEnterCommit') + doautocmd User VimagitEnterCommit + endif + let b:magit_commit_newly_open = 0 + endif + + let g:magit_last_updated_buffer = '' + if ( a:0 >= 1 ) + let abs_filename = magit#git#top_dir() . cur_filename + if ( bufexists(abs_filename) ) + let g:magit_last_updated_buffer = abs_filename + if exists('#User#VimagitUpdateFile') + doautocmd User VimagitUpdateFile + endif + endif + endif + + if exists('#User#VimagitRefresh') + doautocmd User VimagitRefresh + endif + + if ( a:0 >= 3 ) + if (b:state.get_files_nb(cur_section) > 0) + " if, in this order, current file, next file, previous file exists in + " current section, move cursor to it + let cur_file = 1 + for fname in [cur_filename, next_filename, prev_filename] + try + let file = b:state.get_file(cur_section, fname) + if ( cur_file ) + let hunk_id = max([0, min([len(file.get_hunks())-1, cur_hunk_id])]) + let cur_file = 0 + else + let hunk_id = 0 + endif + + if ( file.is_visible() ) + call cursor(file.get_hunks()[hunk_id].line_pos, 0) + if ( g:magit_auto_foldopen ) + foldopen + endif + else + call cursor(file.line_pos, 0) + endif + break + catch 'file_doesnt_exists' + endtry + endfor + else + " if current section is empty, move cursor to top to other section + if (cur_section == 'staged') + let cur_section = 'unstaged' + elseif (cur_section == 'unstaged') + let cur_section = 'staged' + endif + let section_line=search(g:magit_sections[cur_section], "bnw") + call cursor(section_line, 0) + endif + silent execute "normal! zt" + endif + + if exists(':AirlineRefresh') + execute "AirlineRefresh" + endif + +endfunction + +" magit#toggle_help: toggle inline help showing in magit buffer +function! magit#toggle_help() + let g:magit_show_help = ( g:magit_show_help == 0 ) ? 1 : 0 + call magit#update_buffer() +endfunction + +" magit#show_magit: prepare and show magit buffer +" it also set local mappings to magit buffer +" param[in] display: +" 'v': vertical split +" 'h': horizontal split +" 'c': current buffer (should be used when opening vim in vimagit mode +function! magit#show_magit(display, ...) + if ( &filetype == 'netrw' ) + let cur_file = "" + let cur_file_path = b:netrw_curdir + else + let cur_file = expand("%:p") + let cur_file_path = isdirectory(cur_file) ? cur_file : fnamemodify(cur_file, ":h") + endif + + let git_dir='' + let try_paths = [ cur_file_path, getcwd() ] + for path in try_paths + let git_dir=magit#git#is_work_tree(path) + if ( git_dir != '' ) + break + endif + endfor + + if ( git_dir == '' ) + echohl ErrorMsg + echom "magit can not find any git repository" + echohl None + echom "make sure that current opened file or vim current directory points to a git repository" + echom "search paths:" + for path in try_paths + echom path + endfor + return + endif + + let buffer_name=fnameescape('magit://' . git_dir) + + let magit_win = magit#utils#search_buffer_in_windows(buffer_name) + + if ( magit_win != 0 ) + silent execute magit_win."wincmd w" + elseif ( a:display == 'v' ) + silent execute "vnew " . buffer_name + " next is a workaround for vader, revert as soon as vader bug is fixed + " https://github.com/junegunn/vader.vim/issues/135 + silent execute "buffer " . buffer_name + let b:magit_only = 0 + elseif ( a:display == 'h' ) + silent execute "new " . buffer_name + let b:magit_only = 0 + elseif ( a:display == 'c' ) + if ( !bufexists(buffer_name) ) + if ( bufname("%") == "" ) + silent keepalt enew + else + silent enew + endif + silent execute "file " . buffer_name + else + silent execute "buffer " . buffer_name + endif + let b:magit_only = 1 + else + throw 'parameter_error' + endif + + call magit#git#set_top_dir(git_dir) + + let b:magit_default_show_all_files = g:magit_default_show_all_files + let b:magit_default_fold_level = g:magit_default_fold_level + let b:magit_warning_max_lines_answered = 0 + + if ( a:0 > 0 ) + let b:magit_default_show_all_files = a:1 + endif + if ( a:0 > 1 ) + let b:magit_default_fold_level = a:2 + endif + + setlocal buftype=nofile + setlocal bufhidden=hide + setlocal noswapfile + setlocal foldmethod=syntax + setlocal foldnestmax=20 + setlocal nobuflisted + setlocal nomodeline + let &l:foldlevel = b:magit_default_fold_level + setlocal filetype=magit + if ( g:magit_scrolloff != -1 ) + if ( has("patch-8.1.0864") ) + let &l:scrolloff = g:magit_scrolloff + else + let s:default_scrolloff=&scrolloff + " ugly hack, scrolloff is a global only option before patch 8.1.0864 + execute "autocmd BufLeave " . buffer_name . " :set scrolloff=" . s:default_scrolloff + execute "autocmd BufEnter " . buffer_name . " :set scrolloff=" . g:magit_scrolloff + let &scrolloff = g:magit_scrolloff + endif + endif + + augroup vimagit_buffer + autocmd! + " catch write command + execute "autocmd BufWriteCmd " . buffer_name . " :call magit#commit_command('CC')" + + " let magit buffer in read mode when cursor is not in file, to avoid + " unfortunate commit with a :wall command out of magit buffer if a commit + " message is ongoing + execute "autocmd BufEnter " . buffer_name . " + \ :if ( exists('b:magit_current_commit_mode') && + \ b:magit_current_commit_mode != '' ) | + \ call s:set_mode_write() | + \ endif" + execute "autocmd BufLeave " . buffer_name . " + \ :if ( exists('b:magit_current_commit_mode') && + \ b:magit_current_commit_mode != '' ) | + \ call s:set_mode_read() | + \ endif" + augroup END + + " s:magit_commit_mode: global variable which states in which commit mode we are + " values are: + " '': not in commit mode + " 'CC': normal commit mode, next commit command will create a new commit + " 'CA': amend commit mode, next commit command will ament current commit + " 'CF': fixup commit mode, it should not be a global state mode + let b:magit_current_commit_mode='' + let b:magit_commit_newly_open=0 + + let b:magit_diff_context=3 + + let b:magit_just_commited = 0 + + if ( magit#git#check_repo() != 0 ) + echohl ErrorMsg + echom "git repository seems to be corrupted" + echohl None + echom "To be safe, vimagit ends now" + echom "Check your repository health with git fsck" + echom "If the result shows no problem, open an issue" + return + endif + + let b:state = deepcopy(g:magit#state#state) + call magit#utils#setbufnr(bufnr(buffer_name)) + call magit#sign#init() + + call magit#mapping#set_default() + + if exists('#User#VimagitBufferInit') + doautocmd User VimagitBufferInit + endif + + call magit#update_buffer() + + function! s:jump_first_file() + let unstaged_files = b:state.get_files_ordered('unstaged') + if ( !empty(unstaged_files) ) + call cursor(unstaged_files[0].line_pos, 0) + else + let staged_files = b:state.get_files_ordered('staged') + if ( !empty(staged_files) ) + call cursor(staged_files[0].line_pos, 0) + endif + endif + endfunction + " move cursor to (in priority order if not found): + " - current file unstaged + " - current file staged + " - first unstaged file + " - first stage file + let cur_filename = matchlist(cur_file, git_dir . '\(.*\)') + if ( !empty(cur_filename) ) + let cur_file = cur_filename[1] + try + let file = b:state.get_file('unstaged', cur_file, 0) + call cursor(file.line_pos, 0) + catch 'file_doesnt_exists' + try + let file = b:state.get_file('staged', cur_file, 0) + call cursor(file.line_pos, 0) + catch 'file_doesnt_exists' + call s:jump_first_file() + endtry + endtry + else + call s:jump_first_file() + endif + +endfunction + +function! magit#close_magit() + if ( b:magit_only == 0 ) + close + else + try + edit # + catch /^Vim\%((\a\+)\)\=:E\%(194\|499\)/ + try + close + catch /^Vim\%((\a\+)\)\=:E444/ + quit + endtry + endtry + endif +endfunction + +function! s:mg_stage_closed_file(discard) + if ( getline(".") =~ g:magit_file_re ) + let list = matchlist(getline("."), g:magit_file_re) + let filename = list[2] + let section=magit#helper#get_section() + + let file = b:state.get_file(section, filename) + if ( file.is_visible() == 0 || + \ file.is_dir() == 1 ) + if ( a:discard == 0 ) + if ( section == 'unstaged' ) + call magit#git#git_add(magit#utils#add_quotes(filename)) + elseif ( section == 'staged' ) + call magit#git#git_reset(magit#utils#add_quotes(filename)) + else + echoerr "Must be in \"" . + \ g:magit_sections.staged . "\" or \"" . + \ g:magit_sections.unstaged . "\" section" + endif + else + if ( section == 'unstaged' ) + if ( file.status == '?' || file.must_be_added() ) + if ( g:magit_discard_untracked_do_delete == 1 ) + if ( delete(filename, "rf") != 0 ) + echoerr "Can not delete \"" . filename . "\"" + return + endif + else + echohl WarningMsg + echomsg "By default, vimagit won't discard " + \ "untracked file (which means delete this file)" + echomsg "You can force this behaviour, " + \ "setting g:magit_discard_untracked_do_delete=1" + echohl None + return + endif + else + call magit#git#git_checkout(magit#utils#add_quotes(filename)) + endif + else + echohl WarningMsg + echomsg "Can not discard file in \"" . + \ g:magit_sections.staged . "\" section, " + \ "unstage file first." + echohl None + return + endif + endif + + call magit#update_buffer(filename, section, 0) + + return + endif + endif + throw "out_of_block" +endfunction + +" magit#stage_block: this function (un)stage a block, according to parameter +" INFO: in unstaged section, it stages the hunk, and in staged section, it +" unstages the hunk +" param[in] block_type: can be 'file' or 'hunk' +" param[in] discard: boolean, if true, discard instead of (un)stage +" return: no +function! magit#stage_block(selection, discard) abort + let section=magit#helper#get_section() + let filename=magit#helper#get_filename() + + let file = b:state.get_file(section, filename, 0) + let header = file.get_header() + + " find current hunk position in file matching against current selection + " header + try + let hunk_id = match(map(deepcopy(file.get_hunks()), 'v:val.header'), "\\V" . a:selection[0]) + catch /^Vim\%((\a\+)\)\=:E874/ + echoerr "Escape issue with '" . a:selection[0] ."'" + return + endtry + + + if ( a:discard == 0 ) + if ( section == 'unstaged' ) + if ( file.must_be_added() ) + call magit#git#git_add(magit#utils#add_quotes(filename)) + else + call magit#git#git_apply(header, a:selection) + endif + elseif ( section == 'staged' ) + if ( file.must_be_added() ) + call magit#git#git_reset(magit#utils#add_quotes(filename)) + else + call magit#git#git_unapply(header, a:selection, 'staged') + endif + else + echoerr "Must be in \"" . + \ g:magit_sections.staged . "\" or \"" . + \ g:magit_sections.unstaged . "\" section" + endif + else + if ( section == 'unstaged' ) + if ( file.status == '?' || file.must_be_added() ) + if ( g:magit_discard_untracked_do_delete == 1 ) + if ( delete(filename, "rf") != 0 ) + echoerr "Can not delete \"" . filename . "\"" + return + endif + else + echohl WarningMsg + echomsg "By default, vimagit won't discard " + \ "untracked file (which means delete this file)" + echomsg "You can force this behaviour, " + \ "setting g:magit_discard_untracked_do_delete=1" + echohl None + return + endif + else + call magit#git#git_unapply(header, a:selection, 'unstaged') + endif + else + echoerr "Must be in \"" . + \ g:magit_sections.unstaged . "\" section" + endif + endif + + call magit#update_buffer(filename, section, hunk_id) + +endfunction + +" magit#stage_file: this function (un)stage a whole file, from the current +" cursor position +" INFO: in unstaged section, it stages the file, and in staged section, it +" unstages the file +" return: no +function! magit#stage_file() + try + call <SID>mg_stage_closed_file(0) + return + catch 'out_of_block' + try + let [start, end] = <SID>mg_select_file_block() + catch /^out_of_block$/ + echohl ErrorMsg + echomsg "Error while staging." + echohl None + echomsg "Your cursor must be:" + echomsg " - on a file header line" + echomsg " - or on a hunk header line" + echomsg " - or within a hunk" + echomsg "If you repect one of previous points, please open a new issue:" + echomsg "https://github.com/jreybert/vimagit/issues/new" + return + endtry + let selection = getline(start, end) + endtry + return magit#stage_block(selection, 0) +endfunction +" +" magit#stage_hunk: this function (un)stage/discard a hunk, from the current +" cursor position +" INFO: in unstaged section, it stages the hunk, and in staged section, it +" unstages the hunk +" param[in] discard: +" - when set to 0, (un)stage +" - when set to 1, discard +" return: no +function! magit#stage_hunk(discard) + try + call <SID>mg_stage_closed_file(a:discard) + return + catch 'out_of_block' + try + let [start,end] = <SID>mg_select_hunk_block() + catch 'out_of_block' + try + let [start,end] = <SID>mg_select_file_block() + catch /^out_of_block$/ + echohl ErrorMsg + echomsg "Error while staging." + echohl None + echomsg "Your cursor must be:" + echomsg " - on a file header line" + echomsg " - or on a hunk header line" + echomsg " - or within a hunk" + echomsg "If you repect one of previous points, please open a new issue:" + echomsg "https://github.com/jreybert/vimagit/issues/new" + return + endtry + endtry + let marked_lines = magit#sign#find_stage_signs(start, end) + if ( empty(marked_lines) ) + let selection = getline(start, end) + else + let selection = <SID>mg_create_diff_from_select( + \ map(keys(marked_lines), 'str2nr(v:val)')) + call magit#sign#remove_signs(marked_lines) + endif + endtry + return magit#stage_block(selection, a:discard) +endfunction + +" magit#stage_vselect: this function (un)stage text being sectected in Visual +" mode +" remarks: it works with full lines, and can not span over multiple chunks +" INFO: in unstaged section, it stages the file, and in staged section, it +" unstages the file +" return: no +function! magit#stage_vselect() range + " func-range a:firstline a:lastline seems to work at least from vim 7.2 + let lines = [] + let curline = a:firstline + while ( curline <= a:lastline ) + call add(lines, curline) + let curline += 1 + endwhile + try + let selection = <SID>mg_create_diff_from_select(lines) + catch /^out_of_block$/ + echohl ErrorMsg + echomsg "Error while staging a visual selection." + echohl None + echomsg "Visual selection staging has currently some limitations:" + echomsg " - selection must be limited within a single hunk" + echomsg " - only work for staging, not for unstaging" + echomsg "If you repect current limitations, please open a new issue:" + echomsg "https://github.com/jreybert/vimagit/issues/new" + return + endtry + return magit#stage_block(selection, 0) +endfunction + +" magit#mark_vselect: wrapper function to mark selected lines (see +" mg_mark_lines_in_hunk) +function! magit#mark_vselect() range + return <SID>mg_mark_lines_in_hunk(a:firstline, a:lastline) +endfunction + +" magit#ignore_file: this function add the file under cursor to .gitignore +" FIXME: git diff adds some strange characters to end of line +function! magit#ignore_file() abort + let ignore_file=magit#helper#get_filename() + call magit#utils#append_file(magit#git#top_dir() . ".gitignore", + \ [ ignore_file ] ) + call magit#update_buffer() +endfunction + +" set magit buffer in write mode +function! s:set_mode_write() + setlocal buftype=acwrite +endfunction + +" set magit buffer in read only mode +function! s:set_mode_read() + setlocal buftype=nofile +endfunction + +" magit#commit_command: entry function for commit mode +" INFO: it has a different effect if current section is commit section or not +" param[in] mode: commit mode +" 'CF': do not set global b:magit_current_commit_mode, directly call magit#git_commit +" 'CA'/'CF': if in commit section mode, call magit#git_commit, else just set +" global state variable b:magit_current_commit_mode, +function! magit#commit_command(mode) + if ( a:mode == 'CF' ) + call <SID>mg_git_commit(a:mode) + else + let section=magit#helper#get_section() + if ( section == 'commit' && +\ !(b:magit_current_commit_mode == 'CC' && a:mode == 'CA' ) ) + if ( b:magit_current_commit_mode == '' ) + echoerr "Error, commit section should not be enabled" + return + endif + " when we do commit, it is prefered ot commit the way we prepared it + " (.i.e normal or amend), whatever we commit with CC or CA. + call <SID>mg_git_commit(b:magit_current_commit_mode) + if exists('#User#VimagitLeaveCommit') + doautocmd User VimagitLeaveCommit + endif + else + let b:magit_current_commit_mode=a:mode + let b:magit_commit_newly_open=1 + call s:set_mode_write() + setlocal nomodified + endif + endif + call magit#update_buffer() +endfunction + +" magit#close_commit: cancel for commit mode +" close commit section if opened +function! magit#close_commit() + if ( b:magit_current_commit_mode == '' ) + return + endif + + let git_dir=magit#git#git_dir() + let commit_editmsg=git_dir . 'COMMIT_EDITMSG' + if ( filereadable(commit_editmsg) ) + let commit_msg=s:mg_get_commit_msg() + call writefile(commit_msg, commit_editmsg) + endif + + let b:magit_current_commit_mode='' + let b:magit_current_commit_msg=[] + if exists('#User#VimagitLeaveCommit') + doautocmd User VimagitLeaveCommit + endif + call magit#update_buffer() +endfunction + +" magit#jump_hunk: function to jump among hunks +" it closes the current fold (if any), jump to next hunk and unfold it +" param[in] dir: can be 'N' (for next) or 'P' (for previous) +function! magit#jump_hunk(dir) + let back = ( a:dir == 'P' ) ? 'b' : '' + let line = search('\%(^@@ \|' . g:magit_file_re . '\)', back . 'wn') + if ( line != 0 ) + if ( foldlevel(line('.')) == 2 ) + try + foldclose + catch /^Vim\%((\a\+)\)\=:E490/ + endtry + endif + call cursor(line, 0) + + if ( foldlevel(line('.')) == 0 ) + return + endif + " if current line if an header file of an open file, go next + if ( foldlevel(line('.')) == 1 ) + let line = search('\%(^@@ \|' . g:magit_file_re . '\)', back . 'wn') + call cursor(line, 0) + endif + while ( foldclosed(line) != -1 ) + try + foldopen + catch /^Vim\%((\a\+)\)\=:E490/ + break + endtry + endwhile + silent execute "normal! zt" + endif +endfunction + +" magit#get_staged_files: function returning an array with staged files names +" return: an array with staged files names +function! magit#get_staged_files() + return keys(b:state.dict.staged) +endfunction + +" magit#get_staged_files: function returning an array with unstaged files +" names +" return: an array with unstaged files names +function! magit#get_unstaged_files() + return keys(b:state.dict.unstaged) +endfunction + +" magit#jump_to: function to move cursor to the file location of the current +" hunk +" if this file is already displayed in a window, jump to the window, if not, +" jump to last window and open buffer, at the beginning of the hunk +function! magit#jump_to() + let section=magit#helper#get_section() + let filename=fnameescape(magit#git#top_dir() . magit#helper#get_filename()) + let header_line_nb=magit#helper#get_hunkheader_line_nb() + + let line_in_file=substitute(getline(header_line_nb), + \ '^@@ -\d\+,\d\+ +\(\d\+\),\d\+ @@.*$', '\1', "") + + " header_line_nb+2: +2 because we skip the header and the fist line + let hunk_extract=getline(header_line_nb+2, line('.')) + let line_in_hunk = len(filter(hunk_extract, 'v:val =~ "^[ +]"')) + let line_in_file += line_in_hunk + + " winnr('#') is overwritten by magit#get_win() + let last_win = winnr('#') + let buf_win = magit#utils#search_buffer_in_windows(filename) + let buf_win = ( buf_win == 0 ) ? last_win : buf_win + if ( buf_win == 0 || winnr('$') == 1 ) + rightbelow vnew + else + execute buf_win."wincmd w" + endif + + try + execute "edit " . "+" . line_in_file . " " filename + catch + if ( v:exception == 'Vim:Interrupt' && buf_win == 0) + close + elseif ( v:exception != 'Vim(edit):E325: ATTENTION' ) + throw v:exception + endif + endtry +endfunction + +function! magit#update_diff(way) + if ( a:way == "+" ) + let b:magit_diff_context+=1 + elseif ( a:way == "0" ) + let b:magit_diff_context=3 + elseif ( b:magit_diff_context > 1 ) + let b:magit_diff_context-=1 + endif + call magit#update_buffer() +endfunction + +function! magit#show_version() + return g:vimagit_version[0] . "." . + \ g:vimagit_version[1] . "." . + \ g:vimagit_version[2] +endfunction + +function! magit#get_current_mode() + if ( b:magit_current_commit_mode == '' ) + return "STAGING" + elseif ( b:magit_current_commit_mode == 'CC' ) + return "COMMIT" + elseif ( b:magit_current_commit_mode == 'CA' ) + return "AMEND" + endif +endfunction + +command! Magit call magit#show_magit('v') +command! MagitOnly call magit#show_magit('c') + +" }}} diff --git a/.config/vim/plugin/prose.vim b/.config/vim/plugin/prose.vim @@ -0,0 +1,38 @@ +let g:ProseOn=0 + +function! ToggleProse() + if !g:ProseOn + call Prose() + else + call ProseOff() + endif +endfunction + +function! Prose() + echo "Prose: On" + let g:ProseOn=1 + + noremap j gj + noremap k gk + noremap 0 g0 + noremap $ g$ + noremap A g$a + noremap I g0i + setlocal linebreak nonumber norelativenumber t_Co=0 foldcolumn=2 + hi! link FoldColumn Normal + +endfunction + +function! ProseOff() + echo "Prose: Off" + let g:ProseOn=0 + + noremap j j + noremap k k + noremap 0 0 + noremap $ $ + noremap A A + noremap I I + setlocal nolinebreak number relativenumber t_Co=256 foldcolumn=0 + +endfunction diff --git a/.config/vim/syntax/magit.vim b/.config/vim/syntax/magit.vim @@ -0,0 +1,51 @@ +if exists("b:current_syntax") + finish +endif + +let s:vimagit_path = fnameescape(resolve(expand('<sfile>:p:h'))) +execute 'source ' . s:vimagit_path . '/../common/magit_common.vim' + +syn case match +syn sync minlines=50 + +syn include @diff syntax/diff.vim + +execute 'syn match titleEntry "' . g:magit_section_re . '\n\%(.*\n\)\{-}=\+"' +hi def link titleEntry Comment + +execute 'syn region commitMsg start=/' . g:magit_sections.commit . '/ end=/\%(' . g:magit_section_re . '\)\@=/ contains=titleEntry' +execute 'syn match commitMsgExceed "\%(=\+\n\+\_^.\{' . g:magit_commit_title_limit . '}\)\@<=.*$" contained containedin=commitMsg' +hi def link commitMsgExceed Comment + +execute 'syn match stashEntry "' . g:magit_stash_re . '"' +hi def link stashEntry String + +execute 'syn match fileEntry "' . g:magit_file_re . '"' +hi def link fileEntry String + +execute 'syn region gitStash start=/' . g:magit_stash_re . '/ end=/\%(' . + \ g:magit_stash_re . '\)\@=/ contains=stashEntry fold' + +execute 'syn region gitFile start=/' . g:magit_file_re . '/ end=/\%(' . + \ g:magit_end_diff_re . '\)\@=/ contains=gitHunk,fileEntry fold' + +execute 'syn region gitHunk start=/' . + \ g:magit_hunk_re . '/ end=/\%(' . g:magit_end_diff_re . '\|' . g:magit_hunk_re + \ '\)\@=/ contains=@diff fold' + +execute 'syn match gitInfoRepo "\%(' . g:magit_section_info.cur_repo . '\)\@<=.*$" oneline' +execute 'syn match gitInfoHead "\%(' . g:magit_section_info.cur_head . '\s*\)\@<=\S\+" oneline' +execute 'syn match gitInfoUpstream "\%(' . g:magit_section_info.cur_upstream . '\s*\)\@<=\S\+" oneline' +execute 'syn match gitInfoPush "\%(' . g:magit_section_info.cur_push . '\s*\)\@<=\S\+" oneline' +execute 'syn match gitCommitMode "\%(' . g:magit_section_info.commit_mode . '\)\@<=.*$" oneline' +"execute 'syn match gitInfoCommit "\%(' . g:magit_section_info.cur_commit . '\)\@<=.*$" contains=infoSha1 oneline' +"syntax match infoSha1 containedin=gitInfoCommit "\x\{7,}" + +highlight default link gitInfoRepo Directory +highlight default link gitInfoHead Identifier +highlight default link gitInfoUpstream Identifier +highlight default link gitInfoPush Identifier +highlight default link gitCommitMode Special +highlight default link infoSha1 Identifier + +let b:current_syntax = "magit"