Update 2024-12-15 14:45 OpenBSD/amd64-t14

This commit is contained in:
c0dev0id
2024-12-15 14:45:59 +01:00
parent beac7b226a
commit 6d6f0e9a46
66 changed files with 12003 additions and 1 deletions

View File

@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
target: 0%
patch:
default:
target: 0%

View File

@@ -0,0 +1,240 @@
conflict-marker.vim
===================
[![CI](https://github.com/rhysd/conflict-marker.vim/actions/workflows/ci.yml/badge.svg)](https://github.com/rhysd/conflict-marker.vim/actions/workflows/ci.yml)
[![Coverage](https://codecov.io/gh/rhysd/conflict-marker.vim/branch/master/graph/badge.svg)](https://codecov.io/gh/rhysd/conflict-marker.vim)
Highlight, jump and resolve conflict markers quickly.
[conflict-marker.vim](https://github.com/rhysd/conflict-marker.vim) is Vim plugin for developers fighting against conflicts.
All features are available if and only if an opened buffer contains a conflict marker.
conflict-marker.vim does:
- highlight conflict markers.
- jump among conflict markers.
- jump within conflict block; beginning, separator and end of the block.
- resolve conflict with various strategies; theirs, ours, none and both strategies.
- support both `diff2` (Git default) and [`diff3`](https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging) conflict styles.
This plugin tries to define some mappings if a conflict marker is detected.
If you don't want to use default mappings, set `g:conflict_marker_enable_mappings` to `0`.
## Installation
Please follow the instruction in `:help add-package`.
If you use some plugin manager, please follow its instruction and documentation to install.
For example, you can install this plugin with [neobundle.vim](https://github.com/Shougo/neobundle.vim).
```vim
NeoBundle 'rhysd/conflict-marker.vim'
```
## Conflict Markers
Conflict markers can be customized using the following options:
```vim
" Default values
let g:conflict_marker_begin = '^<<<<<<< \@='
let g:conflict_marker_common_ancestors = '^||||||| .*$'
let g:conflict_marker_separator = '^=======$'
let g:conflict_marker_end = '^>>>>>>> \@='
```
## Highlight Conflict Markers
Conflict markers are highlighted by default. Use the following option to disable
highlighting:
```vim
let g:conflict_marker_enable_highlight = 0
```
Each conflict marker and conflict part is associated to a specific syntax group:
| marker / part | syntax group |
|------|--------------|
| begin conflict marker (`<<<<<<<`) | `ConflictMarkerBegin` |
| *ours* part of the conflict | `ConflictMarkerOurs` |
| common ancestors marker (`\|\|\|\|\|\|\|`) | `ConflictMarkerCommonAncestors` |
| common ancestors part of the conflict | `ConflictMarkerCommonAncestorsHunk` |
| separator conflict marker (`=======`) | `ConflictMarkerSeparator` |
| *theirs* part of the conflict | `ConflictMarkerTheirs` |
| end conflict marker (`>>>>>>>`) | `ConflictMarkerEnd` |
By default, `ConflictMarkerBegin`, `ConflictMarkerSeparator`,
`ConflictMarkerCommonAncestors` and `ConflictMarkerEnd` are
linked to the `Error` syntax group.
To link them to another syntax group, use the following option:
```vim
" Default value
let g:conflict_marker_highlight_group = 'Error'
```
`ConflictMarkerOurs`, `ConflictMarkerTheirs`, and
`ConflictMarkerCommonAncestors` are not linked to any syntax group by default,
and can be used to customize the highlight of the *ours* and *theirs*
parts of the conflict.
To use a specific highlight for each marker, disable the default highlight
group, and define your own highlights for each syntax group.
**Example:**
```vim
" disable the default highlight group
let g:conflict_marker_highlight_group = ''
" Include text after begin and end markers
let g:conflict_marker_begin = '^<<<<<<<\+ .*$'
let g:conflict_marker_common_ancestors = '^|||||||\+ .*$'
let g:conflict_marker_end = '^>>>>>>>\+ .*$'
highlight ConflictMarkerBegin guibg=#2f7366
highlight ConflictMarkerOurs guibg=#2e5049
highlight ConflictMarkerTheirs guibg=#344f69
highlight ConflictMarkerEnd guibg=#2f628e
highlight ConflictMarkerCommonAncestorsHunk guibg=#754a81
```
![Screenshot_20190911_212653](https://user-images.githubusercontent.com/454315/64728297-f8953d80-d4da-11e9-9033-df5bfdee2f7a.png)
## Jump among Conflict Markers
`[x` and `]x` mappings are defined as default. Use the following option to
disable them:
```vim
let g:conflict_marker_enable_mappings = 0
```
## Jump within a Conflict Marker
This feature uses matchit.vim, which is bundled in Vim (`macros/matchit.vim`).
`%` mapping is extended by matchit.vim. Use the following option to disable this
feature:
```vim
let g:conflict_marker_enable_matchit = 0
```
## Resolve a Conflict with Various Strategies
This plugin defines mappings as default: `ct` for theirs, `co` for ours, `cn` for
none and `cb` for both. Use the following option to disable mappings:
```vim
let g:conflict_marker_enable_mappings = 0
```
### Theirs
```
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
```
`ct` or `:ConflictMarkerThemselves`
```
theirs
```
### Ours
```
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
```
`co` or `:ConflictMarkerOurselves`
```
ours
```
### Apply Both
```
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
```
`cb` or `:ConflictMarkerBoth`
```
ours
theirs
```
### Apply Both in Reverse Order
```
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
```
`cB` or `:ConflictMarkerBoth!`
```
theirs
ours
```
### Apply None
```
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
```
`cn` or `:ConflictMarkerNone`
```
```
## Customize
TODO
## License
This plugin is distributed under MIT license.
```
Copyright (c) 2013 rhysd
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.
```

View File

@@ -0,0 +1,154 @@
" Note:
" In this plugin, position of marker is treated with [line, col], not line.
" This is because some markers may be not linewise but characterwise.
" I consider the extensibility of this plugin and markers are customizable,
" I don't throw the possibility of characterwise conflict hunks away.
function! s:current_conflict_begin() abort
let begin = searchpos(g:conflict_marker_begin, 'bcnW')
let before_end = searchpos(g:conflict_marker_end, 'bnW')
if begin == [0, 0] || (before_end != [0, 0] && before_end[0] > begin[0])
return [0, 0]
endif
return begin
endfunction
function! s:current_conflict_end() abort
let after_begin = searchpos(g:conflict_marker_begin, 'nW')
let end = searchpos(g:conflict_marker_end, 'cnW')
if end == [0, 0] || (after_begin != [0, 0] && end[0] > after_begin[0])
return [0, 0]
endif
return end
endfunction
function! s:current_conflict_common_ancestors(before_begin, after_sep) abort
" when separator is before cursor
let before_ancestor = searchpos(g:conflict_marker_common_ancestors, 'bcnW')
if before_ancestor != [0, 0] && a:before_begin != [0, 0] && a:before_begin[0] < before_ancestor[0]
return before_ancestor
endif
" when separator is after cursor
let after_ancestor = searchpos(g:conflict_marker_common_ancestors, 'cnW')
if after_ancestor != [0, 0] && a:after_sep != [0, 0] && after_ancestor[0] < a:after_sep[0]
return after_ancestor
endif
return [0, 0]
endfunction
function! s:current_conflict_separator(before_begin, after_end) abort
" when separator is before cursor
let before_sep = searchpos(g:conflict_marker_separator, 'bcnW')
if before_sep != [0, 0] && a:before_begin != [0, 0] && a:before_begin[0] < before_sep[0]
return before_sep
endif
" when separator is after cursor
let after_sep = searchpos(g:conflict_marker_separator, 'cnW')
if after_sep != [0, 0] && a:after_end != [0, 0] && after_sep[0] < a:after_end[0]
return after_sep
endif
return [0, 0]
endfunction
function! s:valid_hunk(hunk) abort
return filter(copy(a:hunk), 'v:val == [0, 0]') == []
endfunction
function! conflict_marker#markers() abort
let begin = s:current_conflict_begin()
let end = s:current_conflict_end()
return [begin, s:current_conflict_separator(begin, end), end]
endfunction
" Note: temporary implementation, linewise
function! conflict_marker#themselves() abort
let markers = conflict_marker#markers()
if ! s:valid_hunk(markers) | return | endif
execute markers[2][0] . 'delete' '_'
execute markers[0][0] . ',' . markers[1][0] . 'delete' '_'
silent! call repeat#set("\<Plug>(conflict-marker-themselves)", v:count)
endfunction
" Note: temporary implementation, linewise
function! conflict_marker#ourselves() abort
let markers = conflict_marker#markers()
if ! s:valid_hunk(markers) | return | endif
let common_ancestors_pos = s:current_conflict_common_ancestors(markers[0], markers[1])
if common_ancestors_pos != [0, 0]
execute common_ancestors_pos[0] . ',' . markers[2][0] . 'delete' '_'
else
execute markers[1][0] . ',' . markers[2][0] . 'delete' '_'
endif
execute markers[0][0] . 'delete' '_'
silent! call repeat#set("\<Plug>(conflict-marker-ourselves)", v:count)
endfunction
" Note: temporary implementation, linewise
function! conflict_marker#down_together() abort
let markers = conflict_marker#markers()
if ! s:valid_hunk(markers) | return | endif
execute markers[0][0] . ',' . markers[2][0] . 'delete' '_'
silent! call repeat#set("\<Plug>(conflict-marker-none)", v:count)
endfunction
" Note: temporary implementation, linewise
function! conflict_marker#compromise(reverse) abort
let markers = conflict_marker#markers()
if ! s:valid_hunk(markers) | return | endif
execute markers[2][0] . 'delete' '_'
let common_ancestors_pos = s:current_conflict_common_ancestors(markers[0], markers[1])
let has_common_ancestors = common_ancestors_pos != [0, 0]
if has_common_ancestors
execute common_ancestors_pos[0] . ',' . markers[1][0] . 'delete' '_'
else
execute markers[1][0] . 'delete' '_'
endif
execute markers[0][0] . 'delete' '_'
if a:reverse
let ancestors_lines = has_common_ancestors ? markers[1][0] - common_ancestors_pos[0] : 0
let theirs_start = markers[1][0] - 2 - ancestors_lines + 1
let theirs_end = markers[2][0] - 3 - ancestors_lines
let theirs = getline(theirs_start, theirs_end)
execute theirs_start . ',' . theirs_end . 'delete' '_'
let ours_start = markers[0][0]
call append(ours_start - 1, theirs)
endif
silent! call repeat#set("\<Plug>(conflict-marker-both)", v:count)
endfunction
function! s:jump_to_hunk_if_valid(original_pos, hunk) abort
if s:valid_hunk(a:hunk)
call cursor(a:hunk[0][0], a:hunk[0][1])
return 1
else
echohl ErrorMsg | echo 'conflict not found' | echohl None
call setpos('.', a:original_pos)
return 0
endif
endfunction
function! conflict_marker#next_conflict(accept_cursor) abort
let pos = getpos('.')
return s:jump_to_hunk_if_valid(pos, [
\ searchpos(g:conflict_marker_begin, (a:accept_cursor ? 'cW' : 'W')),
\ searchpos(g:conflict_marker_separator, 'cW'),
\ searchpos(g:conflict_marker_end, 'cW'),
\ ])
endfunction
function! conflict_marker#previous_conflict(accept_cursor) abort
let pos = getpos('.')
return s:jump_to_hunk_if_valid(pos, reverse([
\ searchpos(g:conflict_marker_end, (a:accept_cursor ? 'bcW' : 'bW')),
\ searchpos(g:conflict_marker_separator, 'bcW'),
\ searchpos(g:conflict_marker_begin, 'bcW'),
\ ]))
endfunction

View File

@@ -0,0 +1,24 @@
let s:save_cpo = &cpo
set cpo&vim
function! conflict_marker#detect#markers() abort
if !g:conflict_marker_enable_detect
return
endif
let view = winsaveview()
try
keepjumps call cursor(1, 1)
for marker in [g:conflict_marker_begin, g:conflict_marker_separator, g:conflict_marker_end]
if search(marker, 'cW') == 0
return 0
endif
endfor
return 1
finally
call winrestview(view)
endtry
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@@ -0,0 +1,60 @@
let s:save_cpo = &cpo
set cpo&vim
let s:source = {
\ 'name' : 'conflict',
\ 'description' : 'conflicts in current buffer',
\ 'default_kind' : 'jump_list',
\ 'hooks' : {},
\ }
function! unite#sources#conflict#define() abort
return s:source
endfunction
function! s:source.hooks.on_init(args, context) abort
if ! conflict_marker#detect#markers()
return
endif
let a:context.source__path = expand('%:p')
let a:context.source__bufnr = bufnr('%')
let pos_save = getpos('.')
let a:context.source__markers = []
normal! gg
if ! conflict_marker#next_conflict(1)
return
endif
let end_line = search(g:conflict_marker_end, 'cWn')
call add(a:context.source__markers, [getline('.'), line('.')])
call add(a:context.source__markers, [getline(end_line), end_line])
while 1
silent if ! conflict_marker#next_conflict(0)
break
endif
let end_line = search(g:conflict_marker_end, 'cWn')
call add(a:context.source__markers, [getline('.'), line('.')])
call add(a:context.source__markers, [getline(end_line), end_line])
endwhile
call setpos('.', pos_save)
endfunction
function! s:source.gather_candidates(args, context) abort
if ! has_key(a:context, 'source__markers')
return []
endif
return map(a:context.source__markers, "{
\ 'word' : v:val[0].' (line:'.v:val[1].')',
\ 'action__path' : a:context.source__path,
\ 'action__buffer_nr' : a:context.source__bufnr,
\ 'action__line' : v:val[1],
\ }")
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@@ -0,0 +1,176 @@
*conflict-marker.txt* a weapon to fight against conflicts
Author : rhysd <lin90162@yahoo.co.jp>
CONTENTS *conflict-marker.vim-contents*
Introduction |conflict-marker.vim-introduction|
Usage |conflict-marker.vim-usage|
Mappings |conflict-marker.vim-mappings|
Variables |conflict-marker.vim-variables|
Repository Page |conflict-marker.vim-repository-page|
License |conflict-marker.vim-license|
==============================================================================
INTRODUCTION *conflict-marker.vim-introduction*
*conflict-marker.vim* is a plugin for developers fighting against conflicts.
All features are available iff an opened buffer contains a conflict marker.
conflict-marker.vim does
1. highlight conflict markers.
2. jump among conflict markers.
3. jump within conflict block; begin, separator and end of the block.
4. resolve conflict with various strategies; "theirs", "ours", "none"
and "both".
==============================================================================
USAGE *conflict-marker.vim-usage*
Please see README.md in below repository page. TODO
https://github.com/rhysd/conflict-marker.vim/blob/master/README.md
==============================================================================
MAPPINGS *conflict-marker.vim-mappings*
[x
]x
Jump among Conflict Markers.
Use the following option to disable them: >
let g:conflict_marker_enable_mappings = 0
<
*<Plug>(conflict-marker-next-hunk)*
*<Plug>(conflict-marker-prev-hunk)*
Jump among Conflict Markers.
ct
co
cn
Resolve a Conflict with Various Strategies.
`ct` for theirs, `co` for ours, `cn` for none and `cb` for both.
See |conflict-marker.vim-example| for more details.
Use the following option to disable them: >
let g:conflict_marker_enable_mappings = 0
<
*<Plug>(conflict-marker-themselves)*
*<Plug>(conflict-marker-ourselves)*
*<Plug>(conflict-marker-both)*
*<Plug>(conflict-marker-both-rev)*
*<Plug>(conflict-marker-none)*
Resolve a Conflict with Various Strategies.
See |conflict-marker.vim-example| for more details.
==============================================================================
EXAMPLE *conflict-marker.vim-example*
How this plugin resolves conflicts is shown below.
Theirs: >
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
<
↓`ct` or `:ConflictMarkerThemselves` >
theirs
<
Ours: >
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
<
↓`co` or `:ConflictMarkerOurselves` >
ours
<
Apply Both: >
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
<
↓`cb` or `:ConflictMarkerBoth` >
ours
theirs
<
Apply Both in Reverse Order: >
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
<
↓`cB` or `:ConflictMarkerBoth!` >
theirs
ours
<
Apply None: >
<<<<<<< HEAD
ours
=======
theirs
>>>>>>> deadbeef0123
<
↓`cn` or `:ConflictMarkerNone` >
(empty)
<
==============================================================================
VARIABLES *conflict-marker.vim-variables*
Please see README.md in below repository page. TODO
https://github.com/rhysd/conflict-marker.vim/blob/master/README.md
==============================================================================
REPOSITORY PAGE *conflict-marker.vim-repository-page*
The latest version of |conflict-marker.vim| is available at
https://github.com/rhysd/conflict-marker.vim
Contributions (pull requests) are welcome. None of them are too short.
Especially, English check is very helpful because I'm poor at English :(
==============================================================================
LICENSE *conflict-marker.vim-license*
|conflict-marker.vim| is distributed under MIT license.
Copyright (c) 2013 rhysd
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.
==============================================================================
vim:tw=78:colorcolumn=78:ts=8:ft=help:norl:noet:fen:fdl=0:

View File

@@ -0,0 +1,136 @@
if exists('g:loaded_conflict_marker')
finish
endif
let s:save_cpo = &cpo
set cpo&vim
function! s:var(name, default)
let g:conflict_marker_{a:name} = get(g:, 'conflict_marker_'.a:name, a:default)
endfunction
call s:var('highlight_group', 'Error')
call s:var('begin', '^<<<<<<<\+')
call s:var('common_ancestors', '^|||||||\+')
call s:var('separator', '^=======\+$')
call s:var('end', '^>>>>>>>\+')
call s:var('enable_mappings', 1)
call s:var('enable_hooks', 1)
call s:var('enable_highlight', 1)
call s:var('enable_matchit', 1)
call s:var('enable_detect', 1)
command! -nargs=0 ConflictMarkerThemselves call conflict_marker#themselves()
command! -nargs=0 ConflictMarkerOurselves call conflict_marker#ourselves()
command! -nargs=0 -bang ConflictMarkerBoth call conflict_marker#compromise(<bang>0)
command! -nargs=0 ConflictMarkerNone call conflict_marker#down_together()
command! -nargs=0 -bang ConflictMarkerNextHunk call conflict_marker#next_conflict(<bang>0)
command! -nargs=0 -bang ConflictMarkerPrevHunk call conflict_marker#previous_conflict(<bang>0)
nnoremap <silent><Plug>(conflict-marker-themselves) :<C-u>ConflictMarkerThemselves<CR>
nnoremap <silent><Plug>(conflict-marker-ourselves) :<C-u>ConflictMarkerOurselves<CR>
nnoremap <silent><Plug>(conflict-marker-both) :<C-u>ConflictMarkerBoth<CR>
nnoremap <silent><Plug>(conflict-marker-both-rev) :<C-u>ConflictMarkerBoth!<CR>
nnoremap <silent><Plug>(conflict-marker-none) :<C-u>ConflictMarkerNone<CR>
nnoremap <silent><Plug>(conflict-marker-next-hunk) :<C-u>ConflictMarkerNextHunk<CR>
nnoremap <silent><Plug>(conflict-marker-prev-hunk) :<C-u>ConflictMarkerPrevHunk<CR>
function! s:execute_hooks()
if g:conflict_marker_enable_mappings
nmap <buffer>]x <Plug>(conflict-marker-next-hunk)
nmap <buffer>[x <Plug>(conflict-marker-prev-hunk)
nmap <buffer>ct <Plug>(conflict-marker-themselves)
nmap <buffer>co <Plug>(conflict-marker-ourselves)
nmap <buffer>cn <Plug>(conflict-marker-none)
nmap <buffer>cb <Plug>(conflict-marker-both)
nmap <buffer>cB <Plug>(conflict-marker-both-rev)
endif
if exists('g:conflict_marker_hooks') && has_key(g:conflict_marker_hooks, 'on_detected')
if type(g:conflict_marker_hooks.on_detected) == type('')
call call(function(g:conflict_marker_hooks.on_detected), [])
else
call call(g:conflict_marker_hooks.on_detected, [], {})
endif
endif
endfunction
function! s:set_conflict_marker_to_match_words()
if ! exists('g:loaded_matchit')
runtime macros/matchit.vim
if ! exists('g:loaded_matchit')
" matchit.vim doesn't exists. remove autocmd
let g:conflict_marker_enable_matchit = 0
endif
endif
if exists('b:conflict_marker_match_words_loaded')
return
endif
let group = printf('%s:%s:%s:%s',
\ g:conflict_marker_begin,
\ g:conflict_marker_common_ancestors,
\ g:conflict_marker_separator,
\ g:conflict_marker_end)
let b:match_words = exists('b:match_words') ? b:match_words . ',' . group : group
let b:conflict_marker_match_words_loaded = 1
endfunction
function! s:create_highlight_links()
if exists('g:conflict_marker_highlight_group') && strlen(g:conflict_marker_highlight_group)
execute 'highlight default link ConflictMarkerBegin '.g:conflict_marker_highlight_group
execute 'highlight default link ConflictMarkerCommonAncestors '.g:conflict_marker_highlight_group
execute 'highlight default link ConflictMarkerSeparator '.g:conflict_marker_highlight_group
execute 'highlight default link ConflictMarkerEnd '.g:conflict_marker_highlight_group
endif
endfunction
function! s:on_detected()
if g:conflict_marker_enable_hooks
call s:execute_hooks()
endif
if g:conflict_marker_enable_highlight
execute printf('syntax match ConflictMarkerBegin containedin=ALL /%s/',
\ g:conflict_marker_begin)
execute printf('syntax region ConflictMarkerOurs containedin=ALL start=/%s/hs=e+1 end=/%s\&/',
\ g:conflict_marker_begin,
\ g:conflict_marker_separator)
execute printf('syntax match ConflictMarkerCommonAncestors containedin=ALL /%s/',
\ g:conflict_marker_common_ancestors)
execute printf('syntax region ConflictMarkerCommonAncestorsHunk containedin=ALL start=/%s/hs=e+1 end=/%s\&/',
\ g:conflict_marker_common_ancestors,
\ g:conflict_marker_separator)
execute printf('syntax match ConflictMarkerSeparator containedin=ALL /%s/',
\ g:conflict_marker_separator)
execute printf('syntax region ConflictMarkerTheirs containedin=ALL start=/%s/hs=e+1 end=/%s\&/',
\ g:conflict_marker_separator,
\ g:conflict_marker_end)
execute printf('syntax match ConflictMarkerEnd containedin=ALL /%s/',
\ g:conflict_marker_end)
call s:create_highlight_links()
endif
if g:conflict_marker_enable_matchit
call s:set_conflict_marker_to_match_words()
endif
endfunction
augroup ConflictMarkerDetect
autocmd!
autocmd BufReadPost,FileChangedShellPost,ShellFilterPost,StdinReadPost * if conflict_marker#detect#markers()
\ | call s:on_detected()
\ | endif
augroup END
if g:conflict_marker_enable_highlight
call s:create_highlight_links()
endif
let &cpo = s:save_cpo
unlet s:save_cpo
let g:loaded_conflict_marker = 1

View File

@@ -0,0 +1,3 @@
[run]
plugins = covimerage
data_file = .coverage_covimerage

View File

@@ -0,0 +1,2 @@
/profile.txt
/.coverage_covimerage

View File

@@ -0,0 +1,18 @@
let g:repo_root = fnamemodify(expand('<sfile>'), ':h:h')
call themis#option('exclude', g:repo_root . '/test/profile.txt')
call themis#option('exclude', g:repo_root . '/test/README.md')
call themis#option('exclude', g:repo_root . '/test/.coveragerc')
call themis#option('exclude', g:repo_root . '/test/.gitignore')
call themis#helper('command').with(themis#helper('assert'))
if $PROFILE_LOG !=# ''
execute 'profile' 'start' $PROFILE_LOG
execute 'profile!' 'file' g:repo_root . '/autoload/conflict_marker.vim'
execute 'profile!' 'file' g:repo_root . '/autoload/conflict_marker/detect.vim'
execute 'profile!' 'file' g:repo_root . '/plugin/conflict_marker.vim'
endif
call themis#option('runtimepath', expand(g:repo_root))
syntax on

View File

@@ -0,0 +1,59 @@
# Prerequisites
[Python](https://www.python.org/) is requried to take code coverage.
# How to run unit tests
This repository uses [vim-themis](https://github.com/thinca/vim-themis) to run unit tests.
Clone vim-themis in your local
```sh
git clone https://github.com/thinca/vim-themis.git
```
Run `vim-flavor` command via `bundle exec`:
Execute `themis` command to run all unit tests
```sh
cd /path/to/conflict-marker.vim/test
/path/to/vim-themis/bin/themis *.vimspec
```
It runs all unit tests and outputs the results in terminal.
# How to take code coverage
This repository uses [covimerage](https://github.com/Vimjas/covimerage) to take code coverage.
Install covimerage in `./venv` directory.
```sh
python -m venv venv
source ./venv/bin/activate
pip install covimerage
covimerage --version
```
Run unit tests enabling profiling by setting `PROFILE_LOG` environment variable.
```sh
cd /path/to/conflict-marker.vim/test
PROFILE_LOG=profile.txt /path/to/vim-themis/bin/themis *.vimspec
```
It saves profiling results to `profile.txt`. Extract code coverage data from it using `covimerage`.
```sh
covimerage write_coverage profile.txt
```
Output code coverage results with `coverage` command which is part of standard Python toolchain.
```sh
# Show code coverage results in terminal
coverage report
# Output coverage data to XML file
coverage xml
```

View File

@@ -0,0 +1,76 @@
Describe Default settings
It provides variables to customize
Assert Exists('g:loaded_conflict_marker')
Assert Equals(g:conflict_marker_highlight_group, 'Error')
Assert Equals(g:conflict_marker_begin, '^<<<<<<<\+')
Assert Equals(g:conflict_marker_common_ancestors, '^|||||||\+')
Assert Equals(g:conflict_marker_separator, '^=======\+$')
Assert Equals(g:conflict_marker_end, '^>>>>>>>\+')
Assert Equals(g:conflict_marker_enable_mappings, 1)
Assert Equals(g:conflict_marker_enable_hooks, 1)
Assert Equals(g:conflict_marker_enable_highlight, 1)
Assert Equals(g:conflict_marker_enable_matchit, 1)
End
It provides commands
Assert Exists(':ConflictMarkerThemselves')
Assert Exists(':ConflictMarkerOurselves')
Assert Exists(':ConflictMarkerBoth')
Assert Exists(':ConflictMarkerNone')
Assert Exists(':ConflictMarkerNextHunk')
Assert Exists(':ConflictMarkerPrevHunk')
End
It provides <Plug> mappings
Assert NotEmpty(mapcheck('<Plug>(conflict-marker-themselves)', 'n'))
Assert NotEmpty(mapcheck('<Plug>(conflict-marker-ourselves)', 'n'))
Assert NotEmpty(mapcheck('<Plug>(conflict-marker-both)', 'n'))
Assert NotEmpty(mapcheck('<Plug>(conflict-marker-both-rev)', 'n'))
Assert NotEmpty(mapcheck('<Plug>(conflict-marker-none)', 'n'))
Assert NotEmpty(mapcheck('<Plug>(conflict-marker-next-hunk)', 'n'))
Assert NotEmpty(mapcheck('<Plug>(conflict-marker-prev-hunk)', 'n'))
End
Context with text buffer
Before
new
End
After
close!
End
It provides user mappings unless g:conflict_marker_enable_mappings is 0
let lines = [
\ "<<<<<<< HEAD",
\ "ourselves1",
\ "=======",
\ "themselves1",
\ ">>>>>>> 8374eabc232",
\ ]
for l in range(1, len(lines))
call setline(l, lines[l-1])
endfor
doautocmd BufReadPost
Assert NotEmpty(mapcheck(']x', 'n'))
Assert NotEmpty(mapcheck('[x', 'n'))
Assert NotEmpty(mapcheck('ct', 'n'))
Assert NotEmpty(mapcheck('co', 'n'))
Assert NotEmpty(mapcheck('cn', 'n'))
Assert NotEmpty(mapcheck('cb', 'n'))
Assert NotEmpty(mapcheck('cB', 'n'))
End
It does not provide user mappings until hunk is found
Assert Falsy(mapcheck(']x', 'n'))
Assert Falsy(mapcheck('[x', 'n'))
Assert Falsy(mapcheck('ct', 'n'))
Assert Falsy(mapcheck('co', 'n'))
Assert Falsy(mapcheck('cn', 'n'))
Assert Falsy(mapcheck('cb', 'n'))
Assert Falsy(mapcheck('cB', 'n'))
End
End
End

View File

@@ -0,0 +1,53 @@
let s:lines = [
\ '<<<<<<< HEAD',
\ 'ourselves1',
\ '=======',
\ 'themselves1',
\ '>>>>>>> 8374eabc232',
\ ]
lockvar s:lines
Describe g:conflict_marker_hooks
Before
new
for l in range(1, len(s:lines))
call setline(l, s:lines[l-1])
endfor
End
After
unlet! g:conflict_marker_hooks
close!
End
It does nothing if does not have on_detected hook
let g:conflict_marker_hooks = {}
" Check exception is not thrown
doautocmd BufReadPost
End
It executes on_detected hook specified by string
let g:test_hooked = 0
function! TestHook()
let g:test_hooked = 1
endfunction
let g:conflict_marker_hooks = {'on_detected' : 'TestHook'}
doautocmd BufReadPost
Assert g:test_hooked
unlet g:test_hooked
End
It executes on_detected hook specified by funcref
let g:test_hooked = 0
let g:conflict_marker_hooks = {}
function! g:conflict_marker_hooks.on_detected()
let g:test_hooked = 1
endfunction
doautocmd BufReadPost
Assert g:test_hooked
unlet g:test_hooked
End
End

View File

@@ -0,0 +1,279 @@
let s:lines = [
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves1',
\ '=======',
\ 'themselves1',
\ '>>>>>>> 8374eabc232',
\ '',
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves2',
\ '=======',
\ 'themselves2',
\ '>>>>>>> 8374eabc232',
\ '',
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves3',
\ '=======',
\ 'themselves3',
\ '>>>>>>> 8374eabc232',
\ '',
\ ]
lockvar s:lines
let s:lines_diff3 = [
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves1',
\ '|||||||',
\ 'base1',
\ '=======',
\ 'themselves1',
\ '>>>>>>> 8374eabc232',
\ '',
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves2',
\ '|||||||',
\ 'base2',
\ '=======',
\ 'themselves2',
\ '>>>>>>> 8374eabc232',
\ '',
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves3',
\ '|||||||',
\ 'base3',
\ '=======',
\ 'themselves3',
\ '>>>>>>> 8374eabc232',
\ '',
\ ]
lockvar s:lines_diff3
let s:lines_long_markers = [
\ '',
\ '<<<<<<<<<<<<<< HEAD',
\ 'ourselves1',
\ '==============',
\ 'themselves1',
\ '>>>>>>>>>>>>>> 8374eabc232',
\ '',
\ '',
\ '<<<<<<<< HEAD',
\ 'ourselves2',
\ '========',
\ 'themselves2',
\ '>>>>>>>> 8374eabc232',
\ '',
\ ]
lockvar s:lines_long_markers
function! s:setup(lines) abort
new
for l in range(1, len(a:lines))
call setline(l, a:lines[l-1])
endfor
endfunction
Describe :ConflictMarkerNextHunk
Context applying to diff2
Before
call s:setup(s:lines)
End
After
close!
End
It moves cursor to next hunk
normal! gg
for l in [2, 9, 16]
ConflictMarkerNextHunk
Assert Equals(line('.'), l)
endfor
End
It doesn't move cursor at the end of buffer
normal! G
ConflictMarkerNextHunk
Assert Equals(line('.'), line('$'))
End
It doesn't accept at cursor
normal! ggj
ConflictMarkerNextHunk
Assert Equals(line('.'), 9)
End
It accepts position at cursor with bang
normal! ggj
ConflictMarkerNextHunk!
Assert Equals(line('.'), 2)
End
End
Context applying to diff3
Before
call s:setup(s:lines_diff3)
End
After
close!
End
It moves cursor to next hunk
normal! gg
for l in [2, 11, 20]
ConflictMarkerNextHunk
Assert Equals(line('.'), l)
endfor
End
It doesn't move cursor at the end of buffer
normal! G
ConflictMarkerNextHunk
Assert Equals(line('.'), line('$'))
End
It doesn't accept at cursor
normal! ggj
ConflictMarkerNextHunk
Assert Equals(line('.'), 11)
End
It accepts position at cursor with bang
normal! ggj
ConflictMarkerNextHunk!
Assert Equals(line('.'), 2)
End
End
Context markers with more than 7 characters
Before
call s:setup(s:lines_long_markers)
End
After
close!
End
It moves cursor to next hunk
normal! gg
for l in [2, 9]
ConflictMarkerNextHunk
Assert Equals(line('.'), l)
endfor
End
It accepts position at cursor with bang
normal! ggj
ConflictMarkerNextHunk!
Assert Equals(line('.'), 2)
End
End
End
Describe :ConflictMarkerPrevHunk
Context applying to diff2
Before
call s:setup(s:lines)
End
After
close!
End
It moves cursor to previous hunk
normal! G
for l in [16, 9, 2]
ConflictMarkerPrevHunk
Assert Equals(line('.'), l)
endfor
End
It doesn't move cursor at the top of buffer
normal! gg
ConflictMarkerPrevHunk
Assert Equals(line('.'), 1)
End
It doesn't accept at cursor
normal! Gk
ConflictMarkerPrevHunk
Assert Equals(line('.'), 9)
End
It accepts position at cursor with bang
normal! Gk
ConflictMarkerPrevHunk!
Assert Equals(line('.'), 16)
End
End
Context applying to diff3
Before
call s:setup(s:lines_diff3)
End
After
close!
End
It moves cursor to previous hunk
normal! G
for l in [20, 11, 2]
ConflictMarkerPrevHunk
Assert Equals(line('.'), l)
endfor
End
It doesn't move cursor at the top of buffer
normal! gg
ConflictMarkerPrevHunk
Assert Equals(line('.'), 1)
End
It doesn't accept at cursor
normal! Gk
ConflictMarkerPrevHunk
Assert Equals(line('.'), 11)
End
It accepts position at cursor with bang
normal! Gk
ConflictMarkerPrevHunk!
Assert Equals(line('.'), 20)
End
End
Context markers with more than 7 characters
Before
call s:setup(s:lines_long_markers)
End
After
close!
End
It moves cursor to previous hunk
normal! G
for l in [9, 2]
ConflictMarkerPrevHunk
Assert Equals(line('.'), l)
endfor
End
It accepts position at cursor with bang
normal! Gk
ConflictMarkerPrevHunk!
Assert Equals(line('.'), 9)
End
End
End

View File

@@ -0,0 +1,78 @@
let s:lines = [
\ '<<<<<<< HEAD',
\ 'ourselves1',
\ '=======',
\ 'themselves1',
\ '>>>>>>> 8374eabc232',
\ ]
lockvar s:lines
let s:lines_diff3 = [
\ '<<<<<<< HEAD',
\ 'ourselves1',
\ '||||||| merged common ancestors',
\ 'common ancestors1',
\ '=======',
\ 'themselves1',
\ '>>>>>>> 8374eabc232',
\ ]
lockvar s:lines_diff3
Describe matchit
Before
new
for l in range(1, len(s:lines))
call setline(l, s:lines[l-1])
endfor
doautocmd BufReadPost
End
After
close!
End
It defines b:match_words
Assert Exists('b:match_words')
Assert Equals(b:match_words, '^<<<<<<<\+:^|||||||\+:^=======\+$:^>>>>>>>\+')
End
It jumps jumps between delimiters in a conflict marker
normal! gg
normal %
Assert Equals(line('.'), 3)
normal %
Assert Equals(line('.'), 5)
normal %
Assert Equals(line('.'), 1)
normal %
Assert Equals(line('.'), 3)
End
End
Describe matchit with diff3
Before
new
for l in range(1, len(s:lines_diff3))
call setline(l, s:lines_diff3[l-1])
endfor
doautocmd BufReadPost
End
After
close!
End
It jumps between delimiters in a conflict marker
normal! gg
normal %
Assert Equals(line('.'), 3)
normal %
Assert Equals(line('.'), 5)
normal %
Assert Equals(line('.'), 7)
normal %
Assert Equals(line('.'), 1)
End
End

View File

@@ -0,0 +1,203 @@
let g:lines_diff2 = [
\ '<<<<<<< HEAD',
\ 'ourselves',
\ '=======',
\ 'themselves',
\ '>>>>>>> 8374eabc232',
\ '',
\ ]
lockvar g:lines_diff2
let g:lines_diff3 = [
\ '<<<<<<< HEAD',
\ 'ourselves',
\ '||||||| base',
\ 'ancestors',
\ '=======',
\ 'themselves',
\ '>>>>>>> 8374eabc232',
\ '',
\ ]
lockvar g:lines_diff3
function! s:load(lines)
new
for l in range(1, len(a:lines))
call setline(l, a:lines[l-1])
endfor
doautocmd BufReadPost
endfunction
Describe :ConflictMarkerThemselves
Context applying to diff2
Before
call s:load(g:lines_diff2)
End
After
close!
End
It resolves a conflict with themselves strategy
ConflictMarkerThemselves
Assert Equals(getline(1, '$'), ['themselves', ''])
End
It makes no change out of marker
normal! G
ConflictMarkerThemselves
Assert Equals(getline(1, '$'), g:lines_diff2)
End
End
Context applying to diff3
Before
call s:load(g:lines_diff3)
End
After
close!
End
It resolves a conflict with themselves strategy
ConflictMarkerThemselves
Assert Equals(getline(1, '$'), ['themselves', ''])
End
End
End
Describe :ConflictMarkerOurselves
Context applying to diff2
Before
call s:load(g:lines_diff2)
End
After
close!
End
It resolves a conflict with ourselves strategy
ConflictMarkerOurselves
Assert Equals(getline(1, '$'), ['ourselves', ''])
End
It makes no change out of marker
normal! G
ConflictMarkerOurselves
Assert Equals(getline(1, '$'), g:lines_diff2)
End
End
Context applying to diff3
Before
call s:load(g:lines_diff3)
End
After
close!
End
It resolves a conflict with ourselves strategy
ConflictMarkerOurselves
Assert Equals(getline(1, '$'), ['ourselves', ''])
End
End
End
Describe :ConflictMarkerNone
Context applying to diff2
Before
call s:load(g:lines_diff2)
End
After
close!
End
It resolves a conflict by removing both modifications
ConflictMarkerNone
Assert Equals(getline(1, '$'), [''])
End
It makes no change out of marker
normal! G
ConflictMarkerNone
Assert Equals(getline(1, '$'), g:lines_diff2)
End
End
Context applying to diff3
Before
call s:load(g:lines_diff3)
End
After
close!
End
It resolves a conflict by removing both modifications
ConflictMarkerNone
Assert Equals(getline(1, '$'), [''])
End
End
End
Describe :ConflictMarkerBoth
Context applying to diff2
Before
call s:load(g:lines_diff2)
End
After
close!
End
It resolves a conflict by keeping theirs and ours
ConflictMarkerBoth
Assert Equals(getline(1, '$'), ['ourselves', 'themselves', ''])
End
It makes no change out of marker
normal! G
ConflictMarkerBoth
Assert Equals(getline(1, '$'), g:lines_diff2)
End
Context with bang
It resolves a conflict by keeping theirs and ours in reverse order
ConflictMarkerBoth!
Assert Equals(getline(1, '$'), ['themselves', 'ourselves', ''])
End
It makes no change out of marker
normal! G
ConflictMarkerBoth!
Assert Equals(getline(1, '$'), g:lines_diff2)
End
End
End
Context applying to diff3
Before
call s:load(g:lines_diff3)
End
After
close!
End
It resolves a conflict by keeping theirs and ours
ConflictMarkerBoth
Assert Equals(getline(1, '$'), ['ourselves', 'themselves', ''])
End
Context with bang
It resolves a conflict by keeping theirs and ours in reverse order with bang
ConflictMarkerBoth!
Assert Equals(getline(1, '$'), ['themselves', 'ourselves', ''])
End
End
End
End

View File

@@ -0,0 +1,82 @@
let s:lines = [
\ '<<<<<<< HEAD',
\ 'ourselves1',
\ '=======',
\ 'themselves1',
\ '>>>>>>> 8374eabc232',
\ '',
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves2',
\ '=======',
\ 'themselves2',
\ '>>>>>>> 8374eabc232',
\ '',
\ '',
\ '<<<<<<< HEAD',
\ 'ourselves3',
\ '=======',
\ 'themselves3',
\ '>>>>>>> 8374eabc232',
\ ]
lockvar s:lines
function! GetHighlight(line, col)
return synIDattr(synID(a:line,a:col,1),'name')
endfunction
Describe Conflict marker
Before
new
for l in range(1, len(s:lines))
call setline(l, s:lines[l-1])
endfor
End
After
close!
End
It is highlighted
doautocmd BufReadPost
for l in [1, 8, 15]
Assert Equals(GetHighlight(l, 1), 'ConflictMarkerBegin')
Assert Equals(GetHighlight(l+1, 2), 'ConflictMarkerOurs')
Assert Equals(GetHighlight(l+2, 3), 'ConflictMarkerSeparator')
Assert Equals(GetHighlight(l+3, 4), 'ConflictMarkerTheirs')
Assert Equals(GetHighlight(l+4, 5), 'ConflictMarkerEnd')
endfor
End
It is not highlighted if no marker is detected at BufReadPost
for l in [1, 8, 15]
Assert NotEquals(GetHighlight(l, 1), 'ConflictMarkerBegin')
Assert NotEquals(GetHighlight(l+1, 2), 'ConflictMarkerOurs')
Assert NotEquals(GetHighlight(l+2, 3), 'ConflictMarkerSeparator')
Assert NotEquals(GetHighlight(l+3, 4), 'ConflictMarkerTheirs')
Assert NotEquals(GetHighlight(l+4, 5), 'ConflictMarkerEnd')
endfor
End
Describe g:conflict_marker_enable_detect
Before
let saved = g:conflict_marker_enable_detect
End
After
let g:conflict_marker_enable_detect = saved
End
It disables detection when 0 is set (#18)
let g:conflict_marker_enable_detect = 0
doautocmd BufReadPost
for l in [1, 8, 15]
Assert NotEquals(GetHighlight(l, 1), 'ConflictMarkerBegin')
Assert NotEquals(GetHighlight(l+1, 2), 'ConflictMarkerOurs')
Assert NotEquals(GetHighlight(l+2, 3), 'ConflictMarkerSeparator')
Assert NotEquals(GetHighlight(l+3, 4), 'ConflictMarkerTheirs')
Assert NotEquals(GetHighlight(l+4, 5), 'ConflictMarkerEnd')
endfor
End
End
End