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

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015-2022 itchyny
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,12 @@
# vim-cursorword
## Underlines the word under the cursor
![vim-cursorword](https://raw.githubusercontent.com/wiki/itchyny/vim-cursorword/image/image.gif)
## Installation
Install with your favorite plugin manager.
## Author
itchyny (https://github.com/itchyny)
## License
This software is released under the MIT License, see LICENSE.

View File

@ -0,0 +1,58 @@
" =============================================================================
" Filename: autoload/cursorword.vim
" Author: itchyny
" License: MIT License
" Last Change: 2022/11/17 08:57:47.
" =============================================================================
let s:save_cpo = &cpo
set cpo&vim
function! cursorword#highlight() abort
if !get(g:, 'cursorword_highlight', 1) | return | endif
highlight default CursorWord term=underline cterm=underline gui=underline
endfunction
let s:alphabets = '^[\x00-\x7f\xb5\xc0-\xd6\xd8-\xf6\xf8-\u01bf\u01c4-\u02af\u0370-\u0373\u0376\u0377\u0386-\u0481\u048a-\u052f]\+$'
function! cursorword#matchadd(...) abort
let enable = get(b:, 'cursorword', get(g:, 'cursorword', 1)) && !has('vim_starting')
if !enable && !get(w:, 'cursorword_match') | return | endif
let i = (a:0 ? a:1 : mode() ==# 'i' || mode() ==# 'R') && col('.') > 1
let line = getline('.')
let word = matchstr(line[:(col('.')-i-1)], '\k*$') . matchstr(line[(col('.')-i-1):], '^\k*')[1:]
if get(w:, 'cursorword_state', []) ==# [ word, enable ] | return | endif
let w:cursorword_state = [ word, enable ]
if get(w:, 'cursorword_match')
silent! call matchdelete(w:cursorword_id)
endif
let w:cursorword_match = 0
if !enable || word ==# '' || len(word) !=# strchars(word) && word !~# s:alphabets || len(word) > 1000 | return | endif
let pattern = '\<' . escape(word, '~"\.^$[]*') . '\>'
let w:cursorword_id = matchadd('CursorWord', pattern, -100)
let w:cursorword_match = 1
endfunction
let s:delay = get(g:, 'cursorword_delay', 50)
if has('timers') && s:delay > 0
let s:timer = 0
function! cursorword#cursormoved() abort
if get(w:, 'cursorword_match')
silent! call matchdelete(w:cursorword_id)
let w:cursorword_match = 0
let w:cursorword_state = []
endif
call timer_stop(s:timer)
let s:timer = timer_start(s:delay, 'cursorword#timer_callback')
endfunction
function! cursorword#timer_callback(...) abort
call cursorword#matchadd()
endfunction
else
function! cursorword#cursormoved() abort
call cursorword#matchadd()
endfunction
endif
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,72 @@
*cursorword.txt* Underlines the word under the cursor
Author: itchyny (https://github.com/itchyny)
License: MIT License
Repository: https://github.com/itchyny/vim-cursorword
Last Change: 2022/11/17 18:55:06.
CONTENTS *cursorword-contents*
Introduction |cursorword-introduction|
Options |cursorword-options|
Changelog |cursorword-changelog|
==============================================================================
INTRODUCTION *cursorword-introduction*
This *cursorword* plugin underlines the word under the cursor. That's it.
While we are coding, we always pay attention to the variable under the cursor.
Where did we define the variable? In which statement do we use the variable?
Searching the variable using |star| or |#| is a simple solution to highlight all
the places the variable is used. However, it costs too much time to highlight
a word, move around to check the places and clear the highlight. This plugin
|cursorword| provides you the modest underlines for the variables under the
cursor to let you know all the places the variable is used at a glance without
stopping coding.
The brightest plugin (https://github.com/osyo-manga/vim-brightest) is a nice
plugin to fulfill highlights of the word under the cursor. However, it uses
too long codes and is too slow. I had been using the plugin for a while but I
could not bear the slowness caused by brightest on the cursor motions. This is
why I created |cursorword|. I think that a plugin which is running all the time
should be coded with the performance efficiency in mind. When we publish a
plugin which stays running in all buffers, we should be aware that it will use
much resource of all the users.
The code of |cursorword| is very tiny. It's very tiny that |cursorword| runs ten
times faster than brightest. Instead of its efficiency, |cursorword| is totally
unconfigurable. But you will find this plugin just comfortable; the modest
underlines are enough for us. A good configurable plugin would have many
options that users can configure almost all the features. But be relaxed and
imagine, do we need such a lot of options for a plugin to highlight the word
under the cursor? Most people would never need such a lot of options. We
should not implement features for a few power users at the sacrifice of the
performance of the software. Keep your software small for the happiness of
most users. Too much configurability makes your software dirty and causes
unwanted slowness on many users. We have to rethink what good configurability
is and for what kind of software such configurability is required.
==============================================================================
OPTIONS *cursorword-options*
g:cursorword *g:cursorword*
Set this variable to 0 to disable this plugin globally.
b:cursorword *b:cursorword*
If you set this variable to 0, the plugin stops highlighting
the word under the cursor in the buffer. This variable has
priority over |g:cursorword|.
g:cursorword_highlight *g:cursorword_highlight*
Set this variable to 0 to disable the default highlighting
style. If you set this variable to 0, you need to define your
own style for the CursorWord |highlight-groups|.
g:cursorword_delay *g:cursorword_delay*
The delay duration in milliseconds for setting the word
highlight after cursor motions. When the value is set to 0, the
plugin highlights the word synchronously, but there is a
performance sacrifice. The default value is 50.
==============================================================================
vim:tw=78:sw=4:ts=8:ft=help:norl:noet:

View File

@ -0,0 +1,32 @@
" =============================================================================
" Filename: plugin/cursorword.vim
" Author: itchyny
" License: MIT License
" Last Change: 2020/05/01 19:05:29.
" =============================================================================
if exists('g:loaded_cursorword') || v:version < 703
finish
endif
let g:loaded_cursorword = 1
let s:save_cpo = &cpo
set cpo&vim
augroup cursorword
autocmd!
if has('vim_starting')
autocmd VimEnter * call cursorword#highlight() |
\ autocmd cursorword WinEnter,BufEnter * call cursorword#matchadd()
else
call cursorword#highlight()
autocmd WinEnter,BufEnter * call cursorword#matchadd()
endif
autocmd ColorScheme * call cursorword#highlight()
autocmd CursorMoved,CursorMovedI * call cursorword#cursormoved()
autocmd InsertEnter * call cursorword#matchadd(1)
autocmd InsertLeave * call cursorword#matchadd(0)
augroup END
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2024 Rick Howe (Takumi Ohtani)
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,147 @@
# diffchar.vim
*Highlight the exact differences, based on characters and words*
```
____ _ ____ ____ _____ _ _ _____ ____
| | | || || || || | | || _ || _ |
| _ || || __|| __|| || | | || | | || | ||
| | | || || |__ | |__ | __|| |_| || |_| || |_||_
| |_| || || __|| __|| | | || || __ |
| || || | | | | |__ | _ || _ || | | |
|____| |_||_| |_| |_____||_| |_||_| |_||_| |_|
```
This plugin has been developed in order to make diff mode more useful. Vim
highlights all the text in between the first and last different characters on
a changed line. But this plugin will find the exact differences between them,
character by character - so called *DiffChar*.
For example, in diff mode:
![example1](example1.png)
This plugin will exactly show the changed and added units:
![example2](example2.png)
#### Sync with diff mode
This plugin will synchronously show/reset the highlights of the exact
differences as soon as the diff mode begins/ends. And the exact differences
will be kept updated while editing.
#### Diff unit
This plugin shows the diffs based on a `g:DiffUnit`. Its default is 'Word1'
and it handles a `\w\+` word and a `\W` character as a diff unit. There are other
types of word provided and you can also set 'Char' to compare character by
character. In addition, you can specify one or more diff unit delimiters, such
as comma (','), colon (':'), tab ("\t"), and HTML tag symbols ('<' and '>'),
and also specify a custom pattern in the `g:DiffUnit`.
#### Diff matching colors
In diff mode, the corresponding `hl-DiffChange` lines are compared between two
windows. As a default, all the changed units are highlighted with
`hl-DiffText`. You can set `g:DiffColors` to use more than one matching color
to make it easy to find the corresponding units between two windows. The
number of colors depends on the color scheme. In addition, `hl-DiffAdd` is
always used for the added units and both the previous and next character of
the deleted units are shown in bold/underline.
#### Diff pair visible
While showing the exact differences, when the cursor is moved on a diff unit,
you can see its corresponding unit highlighted with `hl-Cursor`,
`hl-TermCursor`, or similar one in another window, based on a
`g:DiffPairVisible`. If you change its default, the corresponding unit is
echoed in the command line or displayed in a popup/floating window just below
the cursor position or at the mouse position. Those options take effect on
`:diffupdate` command as well.
#### Jump to next/prev diff unit
You can use `]b` or `]e` to jump cursor to start or end position of the next
diff unit, and `[b` or `[e` to the start or end position of the previous unit.
#### Get/put a diff unit
Like line-based `:diffget`/`:diffput` and `do`/`dp` vim commands, you can use
`<Leader>g` and `<Leader>p` commands in normal mode to get and put each diff
unit, where the cursor is on, between 2 buffers and undo its difference. Those
keymaps are configurable in your vimrc and so on.
#### Check diff lines locally
When the diff mode begins, this plugin locally checks the `hl-DiffChange`
lines in the limited range of the current visible and its upper/lower lines of
a window. And each time a cursor is moved on to another range upon scrolling
or searching, those diff lines will be checked in that range. Which means,
independently of the file size, the number of lines to be checked and then the
time consumed are always constant.
#### Tab page individual
This plugin works on each tab page individually. You can use a tab page
variable (t:), instead of a global one (g:), to specify different options on
each tab page. Note that this plugin can not handle more than two diff mode
windows in a tab page. If it would happen, to prevent any trouble, all the
highlighted units are to be reset in the tab page.
#### Follow 'diffopt' option
This plugin supports `icase`, `iwhite`, `iwhiteall`, and `iwhiteeol` in the
`diffopt` option. In addition, when `indent-heuristic` is specified,
positioning of the added/deleted diff units is adjusted to reduce the number
of diff hunks and make them easier to read.
#### Comparison algorithm
To find the exact differences, this plugin uses "An O(NP) Sequence Comparison
Algorithm" developed by S.Wu, et al., which always finds an optimum sequence.
But it takes time to check a long and dissimilar line. To improve the
performance, the algorithm is also implemented in Vim9 script. In addition,
if available, this plugin uses a builtin diff function (`diff()` in vim
patch-9.1.0071 and Lua `vim.diff()` in nvim 0.6.0) and makes it much faster.
#### See also
For a range and area selectable partial comparison, see
[spotdiff.vim](https://github.com/rickhowe/spotdiff.vim) plugin.
### Options
* `g:DiffUnit`, `t:DiffUnit`: A type of difference unit
| Value | Description |
| --- | --- |
| 'Char' | any single character |
| 'Word1' | `\w\+` word and any `\W` single character (default) |
| 'Word2' | non-space and space words |
| 'Word3' | `\<` or `\>` character class boundaries (set by `iskeyword` option) |
| 'word' | see `word` |
| 'WORD' | see `WORD` |
| '[{del}]' | one or more diff unit delimiters (e.g. "[,:\t<>]") |
| '/{pat}/' | a pattern to split into diff units (e.g. '/.\{4}\zs/') |
* `g:DiffColors`, `t:DiffColors`: Matching colors for changed units
| Value | Description |
| --- | --- |
| 0 | `hl-DiffText` (default) |
| 1 | `hl-DiffText` + a few (3, 4, ...) highlight groups |
| 2 | `hl-DiffText` + several (7, 8, ...) highlight groups |
| 3 | `hl-DiffText` + many (11, 12, ...) highlight groups |
| 100 | all available highlight groups in random order |
| [{hlg}] | a list of your favorite highlight groups |
* `g:DiffPairVisible`, `t:DiffPairVisible`: Visibility of corresponding diff units
| Value | Description |
| --- | --- |
| 0 | disable |
| 1 | highlight with `hl-Cursor` (default) |
| 2 | highlight with `hl-Cursor` + echo in the command line |
| 3 | highlight with `hl-Cursor` + popup/floating window at cursor position |
| 4 | highlight with `hl-Cursor` + popup/floating window at mouse position |
### Keymaps
| Mapping | Default Key | Description |
| --- | --- | --- |
| `<Plug>JumpDiffCharPrevStart` | `[b` | Jump cursor to the start position of the previous diff unit |
| `<Plug>JumpDiffCharNextStart` | `]b` | Jump cursor to the start position of the next diff unit |
| `<Plug>JumpDiffCharPrevEnd` | `[e` | Jump cursor to the end position of the previous diff unit |
| `<Plug>JumpDiffCharNextEnd` | `]e` | Jump cursor to the end position of the next diff unit |
| `<Plug>GetDiffCharPair` | `<Leader>g` | Get a corresponding diff unit from another buffer to undo difference |
| `<Plug>PutDiffCharPair` | `<Leader>p` | Put a corresponding diff unit to another buffer to undo difference |
### Demo
![demo](demo.gif)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

View File

@ -0,0 +1,309 @@
*diffchar.txt* Highlight the exact differences, based on characters and words
>
____ _ ____ ____ _____ _ _ _____ ____
| | | || || || || | | || _ || _ |
| _ || || __|| __|| || | | || | | || | ||
| | | || || |__ | |__ | __|| |_| || |_| || |_||_
| |_| || || __|| __|| | | || || __ |
| || || | | | | |__ | _ || _ || | | |
|____| |_||_| |_| |_____||_| |_||_| |_||_| |_|
<
Last Change: 2024/02/14
Version: 9.7 (on or after patch-8.1.1418 and nvim-0.5.0)
Author: Rick Howe (Takumi Ohtani) <rdcxy754@ybb.ne.jp>
Copyright: (c) 2014-2024 Rick Howe
License: MIT
-----------------------------------------------------------------------------
INTRODUCTION *diffchar*
This plugin has been developed in order to make diff mode more useful. Vim
highlights all the text in between the first and last different characters on
a changed line. But this plugin will find the exact differences between them,
character by character - so called DiffChar.
For example, in diff mode: (`-`:`hl-DiffText` / |+|:|hl-DiffAdd|)
+-------------------------------------------------+
|The `quick brown fox jumps over the lazy` dog. |
| `-----------------------------------` |
|~ |
+-------------------------------------------------+
|The `lazy fox jumps over the quick brown` dog. |
| `-----------------------------------` |
|~ |
+-------------------------------------------------+
This plugin will exactly show the changed and added units:
+-------------------------------------------------+
|The `quick` |brown| fox jumps over the `lazy` dog. |
| `-----` |++++++| `----` |
|~ |
+-------------------------------------------------+
|The `lazy` fox jumps over the `quick` |brown| dog. |
| `----` `-----` |++++++| |
|~ |
+-------------------------------------------------+
Sync with diff mode ~
This plugin will synchronously show/reset the highlights of the exact
differences as soon as the diff mode begins/ends. And the exact differences
will be kept updated while editing.
Diff unit ~
This plugin shows the diffs based on a |g:DiffUnit|. Its default is 'Word1'
and it handles a \w\+ word and a \W character as a diff unit. There are other
types of word provided and you can also set 'Char' to compare character by
character. In addition, you can specify one or more diff unit delimiters, such
as comma (','), colon (':'), tab ("\t"), and HTML tag symbols ('<' and '>'),
and also specify a custom pattern in the |g:DiffUnit|.
Diff matching colors ~
In diff mode, the corresponding |hl-DiffChange| lines are compared between two
windows. As a default, all the changed units are highlighted with
|hl-DiffText|. You can set |g:DiffColors| to use more than one matching color
to make it easy to find the corresponding units between two windows. The
number of colors depends on the color scheme. In addition, |hl-DiffAdd| is
always used for the added units and both the previous and next character of
the deleted units are shown in bold/underline.
Diff pair visible ~
While showing the exact differences, when the cursor is moved on a diff unit,
you can see its corresponding unit highlighted with |hl-Cursor|,
|hl-TermCursor|, or similar one in another window, based on a
|g:DiffPairVisible|. If you change its default, the corresponding unit is
echoed in the command line or displayed in a popup/floating window just below
the cursor position or at the mouse position. Those options take effect on
`:diffupdate` command as well.
Jump to next/prev diff unit ~
You can use `]b` or `]e` to jump cursor to start or end position of the next
diff unit, and `[b` or `[e` to the start or end position of the previous unit.
Get/put a diff unit ~
Like line-based `:diffget`/`:diffput` and `do`/`dp` vim commands, you can use
`<Leader>g` and `<Leader>p` commands in normal mode to get and put each diff
unit, where the cursor is on, between 2 buffers and undo its difference. Those
keymaps are configurable in your vimrc and so on.
Check diff lines locally ~
When the diff mode begins, this plugin locally checks the |hl-DiffChange|
lines in the limited range of the current visible and its upper/lower lines of
a window. And each time a cursor is moved on to another range upon scrolling
or searching, those diff lines will be checked in that range. Which means,
independently of the file size, the number of lines to be checked and then the
time consumed are always constant.
Tab page individual ~
This plugin works on each tab page individually. You can use a tab page
variable (t:), instead of a global one (g:), to specify different options on
each tab page. Note that this plugin can not handle more than two diff mode
windows in a tab page. If it would happen, to prevent any trouble, all the
highlighted units are to be reset in the tab page.
Follow 'diffopt' option ~
This plugin supports "icase", "iwhite", "iwhiteall", and "iwhiteeol" in the
'diffopt' option. In addition, when "indent-heuristic" is specified,
positioning of the added/deleted diff units is adjusted to reduce the number
of diff hunks and make them easier to read.
Comparison algorithm ~
To find the exact differences, this plugin uses "An O(NP) Sequence Comparison
Algorithm" developed by S.Wu, et al., which always finds an optimum sequence.
But it takes time to check a long and dissimilar line. To improve the
performance, the algorithm is also implemented in Vim9 script. In addition,
if available, this plugin uses a builtin diff function (|diff()| in vim
patch-9.1.0071 and Lua |vim.diff()| in nvim 0.6.0) and makes it much faster.
See also ~
For a range and area selectable partial comparison, see |spotdiff.vim|
(https://github.com/rickhowe/spotdiff.vim) plugin.
-----------------------------------------------------------------------------
OPTIONS *diffchar-options*
|g:DiffUnit|, |t:DiffUnit|
A type of diff unit
'Char' : any single character
'Word1' : \w\+ word and any \W single character (default)
'Word2' : non-space and space words
'Word3' : \< or \> character class boundaries (set by 'iskeyword' option)
'word' : see `word`
'WORD' : see `WORD`
'[{del}]' : one or more diff unit delimiters (e.g. "[,:\t<>]")
'/{pat}/' : a pattern to split into diff units (e.g. '/.\{4}\zs/')
|g:DiffColors|, |t:DiffColors|
Matching colors for changed units
0 : |hl-DiffText| (default)
1 : |hl-DiffText| + a few (3, 4, ...) highlight groups
2 : |hl-DiffText| + several (7, 8, ...) highlight groups
3 : |hl-DiffText| + many (11, 12, ...) highlight groups
100 : all available highlight groups in random order
[{hlg}] : a list of your favorite highlight groups
|g:DiffPairVisible|, |t:DiffPairVisible|
Visibility of corresponding diff units
0 : disable
1 : highlight with |hl-Cursor| (default)
2 : highlight with |hl-Cursor| + echo in the command line
3 : highlight with |hl-Cursor| + popup/floating window at cursor position
4 : highlight with |hl-Cursor| + popup/floating window at mouse position
-----------------------------------------------------------------------------
KEYMAPS *diffchar-keymaps*
<Plug>JumpDiffCharPrevStart (default: `[b`)
Jump cursor to the start position of the previous diff unit
<Plug>JumpDiffCharNextStart (default: `]b`)
Jump cursor to the start position of the next diff unit
<Plug>JumpDiffCharPrevEnd (default: `[e`)
Jump cursor to the end position of the previous diff unit
<Plug>JumpDiffCharNextEnd (default: `]e`)
Jump cursor to the end position of the next diff unit
<Plug>GetDiffCharPair (default: `<Leader>g`)
Get a corresponding diff unit from another buffer to undo difference
<Plug>PutDiffCharPair (default: `<Leader>p`)
Put a corresponding diff unit to another buffer to undo difference
-----------------------------------------------------------------------------
CHANGE HISTORY *diffchar-history*
Update : 9.7
* Implemented to use a new builtin |diff()| function (available on
patch-9.1.0071) to compare diff units and make it faster in vim.
Update : 9.6, 9.61
* Changed to locally but not incrementally check the limited number of the
|hl-DiffChange| lines upon scrolling or searching.
* Fixed not to use |hl-DiffText| as the first highlight group if [{hlg}] is
specified in the |g:DiffColors| option.
Update : 9.5
* Improved not to update diff unit highlighting on unchanged diff lines on the
DiffUpdated event.
* Fixed the E421 error when 'termguicolors' is off on nvim.
Update : 9.4
* Implemented to use a builtin Lua |vim.diff()| function to compare diff units
and make it faster in nvim.
Update : 9.3
* Improved to follow the 'wincolor' option and show the colors accordingly.
* Fixed to work on some color scheme in which the "g:colors_name" variable is
different from its file name.
Update : 9.2
* Fixed the plugin error when 3 or more windows turn to be diff mode.
* Fixed the issue which the new diff lines can not be incrementally found upon
scrolling on patch-9.0.0913 or later.
* Made it faster to find diff lines in a file with many lines folded.
Update : 9.1
* Added vim original 'word' and 'WORD' units, one or more unit delimiters, and
a custom pattern to split into diff units in |g:DiffUnit| option.
* Improved to redraw diff units whenever the ColorScheme event happens when
multiple matching colors are being used (0 < |g:DiffColors|).
* Changed the category of |g:DiffColors| option as a few, several, and many
numbers of matching colors, depending on the loaded color scheme.
* Added a list of your favorite highlight groups in |g:DiffColors| option.
Update : 9.01
* Fixed to work on a |hl-Diff| highlighting group even if it is linked.
Update : 9.0
* Enhanced to make diff units easier to read when "indent-heuristic" is
specified in the 'diffopt' option.
* Improved to update diff units using `:diffupdate` command when |g:DiffUnit|,
|g:DiffColors|, and |g:DiffPairVisible| options are modified.
* Updated to check a new WinScrolled event (patch-8.2.4713) to incrementally
find scrolled diff lines.
* Implemented the comparison algorithm and diff unit highlighting in Vim9
script and made them 10 times faster on patch-8.2.3965 or later.
* Made this plugin available on or after patch-8.1.1418 and nvim-0.5.0.
Update : 8.91
* Updated to check a new WinClosed event (patch-8.2.3591) to appropriately
reset or repair the highlighted DiffChar units when a window is closed.
Update : 8.9
* Fixed not to overrule syntax highlighting.
* Fixed to successfully sync with diff mode even without patch-8.1.414.
* Changed the highlighting groups used in |g:DiffColors| option.
Update : 8.8
* Changed the highlighting groups used in |g:DiffColors| option, to completely
highlight a changed diff unit and to make each unit more visible.
* Changed to use |hl-Cursor|, |hl-TermCursor|, or similar one, as appropriate,
to highlight a corresponding diff unit, for |g:DiffPairVisible| option.
* Fixed to use proper |hl-Diff| highlighting groups even if they are linked.
* Optimized how to draw each unit and then improved performance.
Update : 8.7
* Enhanced |g:DiffPairVisible| option to show a corresponding diff unit as
well in a floating window on nvim, if its value is 3, and show a popup (not
a balloon) window at the mouse position, if its value is 4.
* Improved performance, use the external diff command together if available,
if there are so many diff units included in a line or it has taken much time
in a diff session.
* Removed |g:DiffMaxLines| option, and locally checks the limited number of
the |hl-DiffChange| lines and incrementally checks them upon scrolling or
searching.
* Removed |g:DiffModeSync| option, and always synchronize with the diff mode.
* `:SDChar`, `:RDChar`, `:TDChar`, and `:EDChar` commands are still available
but deprecated.
Update : 8.6
* Enhanced |g:DiffPairVisible| option to show a corresponding diff unit as a
popup-window just below the cursor position (available on patch-8.1.1391).
And changed its default as 1 (diff unit highlighting only).
* Fixed not to stop monitoring the changes of text and 'diffopt' option,
even if there is no |hl-DiffChange| line, when |g:DiffModeSync| option is
enabled.
Update : 8.5
* Enhanced to show a balloon on GUI and display a corresponding diff unit,
where the mouse is pointing, if |g:DiffPairVisible| option is enabled
(patch-8.1.647 is required to correctly display multibyte characters).
* Fixed to correctly handle |hl-DiffChange| lines while editing.
Update : 8.4
* Extended |g:DiffMaxLines| option to allow a negative value as multiples of
the window height and changed its default as -3.
* Fixed to reset all highlighted DiffChar units when more than two windows
become diff mode in a tab page.
* Deleted |g:DiffSplitTime| option.
Update : 8.3
* Fixed not to detect more |hl-DiffChange| lines than |g:DiffMaxLines| option.
Update : 8.2
* Fixed to correctly update the highlighted DiffChar units while editing when
a new internal diff is not specified in 'diffopt' option (patch-8.1.360).
Update : 8.1
* Fixed to properly detect |hl-DiffChange| lines even when all visible lines
of current window are in a closed fold if a |g:DiffMaxLines| option is
enabled.
Update : 8.0
* Introduced a |g:DiffMaxLines| option to dynamically detect a limited number
of |hl-DiffChange| lines, when the diff mode begins and whenever a cursor is
moved onto an undetected line. It enables to always take a minimum constant
time, independently of the file size.
* Enhanced to check a new DiffUpdated event (patch-8.1.397) to follow diff
updates and some changes of 'diffopt' option.
* Enhanced to support new iwhiteall and iwhiteeol of 'diffopt' option
(patch-8.1.360).
* Removed |g:DiffUpdate| option and merged it into |g:DiffModeSync|.
* Removed keymap for <F7> and <F8>, which toggle to show/reset the highlights.
* Changed to work in diff mode, not in non-diff mode.
* Removed a support for vim version 7.x.
* Changed not to set 'diffexpr' option when a new internal diff is specified
in 'diffopt' (patch-8.1.360).
vim:tw=78:ts=8:ft=help:norl:

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -0,0 +1,97 @@
" diffchar.vim: Highlight the exact differences, based on characters and words
"
" ____ _ ____ ____ _____ _ _ _____ ____
" | | | || || || || | | || _ || _ |
" | _ || || __|| __|| || | | || | | || | ||
" | | | || || |__ | |__ | __|| |_| || |_| || |_||_
" | |_| || || __|| __|| | | || || __ |
" | || || | | | | |__ | _ || _ || | | |
" |____| |_||_| |_| |_____||_| |_||_| |_||_| |_|
"
" Last Change: 2024/02/14
" Version: 9.7 (on or after patch-8.1.1418 and nvim-0.5.0)
" Author: Rick Howe (Takumi Ohtani) <rdcxy754@ybb.ne.jp>
" Copyright: (c) 2014-2024 Rick Howe
" License: MIT
" This 9.x version requires:
" * the OptionSet autocommand event triggered with the diff option
" patch-8.0.0736 (nvim-0.3.0), patch-8.1.0414 (nvim-0.3.2)
" * window ID argument in matchaddpos()/matchdelete()/getmatches()
" patch-8.1.0218 (nvim-0.3.5), patch-8.1.1084 (nvim-0.4.4)
" * the DiffUpdated autocommand event
" patch-8.1.0397 (nvim-0.3.2)
" * the win_execute() function
" patch-8.1.1418 (nvim-0.5.0)
if exists('g:loaded_diffchar') || !has('diff') || v:version < 800 ||
\!exists('*win_execute')
finish
endif
let g:loaded_diffchar = 9.7
let s:save_cpo = &cpoptions
set cpo&vim
" Options
if !exists('g:DiffUnit') " a type of diff unit
" let g:DiffUnit = 'Char' " any single character
" let g:DiffUnit = 'Word1' " \w\+ word and any \W single character
" let g:DiffUnit = 'Word2' " non-space and space words
" let g:DiffUnit = 'Word3' " \< or \> character class boundaries
" let g:DiffUnit = 'word' " see word
" let g:DiffUnit = 'WORD' " see WORD
" let g:DiffUnit = '[{del}]' " a list of unit delimiters (e.g. "[,:\t<>]")
" let g:DiffUnit = '/{pat}/' " a pattern to split (e.g. '/.\{4}\zs/')
endif
if !exists('g:DiffColors') " matching colors for changed units
" let g:DiffColors = 0 " hl-DiffText only
" let g:DiffColors = 1 " hl-DiffText + a few (3, 4, ...)
" let g:DiffColors = 2 " hl-DiffText + several (7, 8, ...)
" let g:DiffColors = 3 " hl-DiffText + many (11, 12, ...)
" let g:DiffColors = 100 " all available highlight groups in random order
" let g:DiffColors = [{hlg}] " a list of your favorite highlight groups
endif
if !exists('g:DiffPairVisible') " a visibility of corresponding diff units
" let g:DiffPairVisible = 0 " disable
" let g:DiffPairVisible = 1 " highlight
" let g:DiffPairVisible = 2 " highlight + echo
" let g:DiffPairVisible = 3 " highlight + popup/floating at cursor pos
" let g:DiffPairVisible = 4 " highlight + popup/floating at mouse pos
endif
" Keymaps
for [key, plg, cmd] in [
\['[b', '<Plug>JumpDiffCharPrevStart',
\':<C-U>call diffchar#JumpDiffChar(0, 0)'],
\[']b', '<Plug>JumpDiffCharNextStart',
\':<C-U>call diffchar#JumpDiffChar(1, 0)'],
\['[e', '<Plug>JumpDiffCharPrevEnd',
\':<C-U>call diffchar#JumpDiffChar(0, 1)'],
\[']e', '<Plug>JumpDiffCharNextEnd',
\':<C-U>call diffchar#JumpDiffChar(1, 1)'],
\['<Leader>g', '<Plug>GetDiffCharPair',
\':<C-U>call diffchar#CopyDiffCharPair(0)'],
\['<Leader>p', '<Plug>PutDiffCharPair',
\':<C-U>call diffchar#CopyDiffCharPair(1)']]
if !hasmapto(plg, 'n') && empty(maparg(key, 'n'))
if get(g:, 'DiffCharDoMapping', 1)
call execute('nmap <silent> ' . key . ' ' . plg)
endif
endif
call execute('nnoremap <silent> ' . plg . ' ' . cmd . '<CR>')
endfor
" Event groups
let g:DiffCharInitEvent = ['augroup diffchar', 'autocmd!',
\'autocmd OptionSet diff call diffchar#ToggleDiffModeSync()',
\'augroup END']
call execute(g:DiffCharInitEvent)
call execute('autocmd diffchar VimEnter * ++once
\ if &diff | call diffchar#ToggleDiffModeSync(1) | endif')
let &cpoptions = s:save_cpo
unlet s:save_cpo
" vim: ts=2 sw=0 sts=-1 et

View File

@ -0,0 +1,23 @@
vim-improve-diff License
==============================================================================
The MIT License (MIT)
Copyright (c) 2015 Alisue, hashnote.net
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,72 @@
vim-improve-diff
==============================================================================
vim-improve-diff is a plugin to improve diff feature in Vim.
It provide the following features:
**Auto diffupdate**
When user leave an insert mode, it call `diffupdate` when the current buffer
is in diff mode.
**Auto diffoff**
When user close a diff buffer, it count the number of diff buffer in a current
tab page and call `diffoff!` when there is only a single diff buffer remains.
**Improved :DiffOrig**
If no :DiffOrig command is defined, it automatically define an improved versin
of :DiffOrig command.
You would probably interested in [lambdalisue/vim-unified-diff](https://github.com/lambdalisue/vim-unified-diff) which use a 'histogram' algorithm to improve the quality of diff.
Install
-------------------------------------------------------------------------------
The repository follow a standard directory structure thus you can use [gmarik/Vundle.vim], [Shougo/neobundle.vim], or other vim plugin manager to install vim-gita like:
```vim
" Vundle.vim
Plugin 'lambdalisue/vim-improve-diff'
" neobundle.vim
NeoBundle 'lambdalisue/vim-improve-diff'
```
If you are not using any vim plugin manager, you can copy the repository to your $VIM directory to enable the plugin.
[Shougo/neobundle.vim]: https://github.com/Shougo/neobundle.vim
[gmarik/Vundle.vim]: https://github.com/gmarik/Vundle.vim
Usage
-------------------------------------------------------------------------------
After you install, it automatically enable all features.
See [vim-improve-diff.txt](./doc/vim-improve-diff.txt) or execute `:help vim-improve-diff` to control the features.
License
-------------------------------------------------------------------------------
The MIT License (MIT)
Copyright (c) 2015 Alisue, hashnote.net
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,81 @@
let s:save_cpo = &cpo
set cpo&vim
function! improve_diff#diffoff(...) abort " {{{
let expr = get(a:000, 0, '%')
if getwinvar(bufwinnr(expr), '&diff')
call setwinvar(bufwinnr(expr), '&diff', 0)
endif
endfunction " }}}
function! improve_diff#diffupdate(...) abort " {{{
let expr = get(a:000, 0, '%')
if getwinvar(bufwinnr(expr), '&diff')
diffupdate
endif
endfunction " }}}
function! improve_diff#difforig(...) abort " {{{
let horizontal = get(a:000, 0, 0)
let bufnum = bufnr('%')
let filetype = &filetype
let filename = expand('%')
let sep = has('unix') ? ':' : '-'
if horizontal
noautocmd execute printf('new ORIG%s%s', sep, filename)
else
noautocmd execute printf('vnew ORIG%s%s', sep, filename)
endif
r # | normal! 1Gdd
silent execute printf('setlocal filetype=%s', filetype)
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile
setlocal readonly nomodifiable
diffthis
silent execute printf('%swincmd w', bufwinnr(bufnum))
diffthis
diffupdate
endfunction " }}}
function! improve_diff#enable_auto_diffupdate() abort " {{{
augroup vim-improve-diff-auto-diffupdate
autocmd! *
autocmd InsertLeave * call improve_diff#diffupdate()
augroup END
endfunction " }}}
function! improve_diff#enable_auto_diffoff() abort " {{{
augroup vim-improve-diff-auto-diffoff
autocmd! *
autocmd BufWinLeave * call improve_diff#diffoff(expand('<afile>'))
augroup END
endfunction " }}}
function! improve_diff#enable() abort " {{{
call improve_diff#enable_auto_diffupdate()
call improve_diff#enable_auto_diffoff()
endfunction " }}}
function! improve_diff#disable_auto_diffupdate() abort " {{{
augroup vim-improve-diff-auto-diffupdate
autocmd! *
augroup END
endfunction " }}}
function! improve_diff#disable_auto_diffoff() abort " {{{
augroup vim-improve-diff-auto-diffoff
autocmd! *
augroup END
endfunction " }}}
function! improve_diff#disable() abort " {{{
call improve_diff#disable_auto_diffupdate()
call improve_diff#disable_auto_diffoff()
endfunction " }}}
nnoremap <silent> <Plug>(improve-diff-diffupdate)
\ :<C-u>call improve_diff#diffupdate()<CR>
nnoremap <silent> <Plug>(improve-diff-diffoff)
\ :<C-u>call improve_diff#diffoff()<CR>
nnoremap <silent> <Plug>(improve-diff-difforig-h)
\ :<C-u>call improve_diff#difforig(1)<CR>
nnoremap <silent> <Plug>(improve-diff-difforig-v)
\ :<C-u>call improve_diff#difforig(0)<CR>
let &cpo = s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker:

View File

@ -0,0 +1,191 @@
*vim-improve-diff.txt* A small plugin to improve diff feature in Vim
Version: 0.1.0
Author: Alisue <lambdalisue@hashnote.net> *vim-improve-diff-author*
Support: Vim 7.3 and above
License: MIT license {{{
Copyright (c) 2015 Alisue, hashnote.net
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.
}}}
=============================================================================
CONTENTS *vim-improve-diff-contents*
Introduction |vim-improve-diff-introduction|
Install |vim-improve-diff-install|
Usage |vim-improve-diff-usage|
Interface |vim-improve-diff-interface|
Options |vim-improve-diff-interface-options|
Mappings |vim-improve-diff-interface-mappings|
Functions |vim-improve-diff-interface-functions|
Commands |vim-improve-diff-interface-commands|
==============================================================================
INTRODUCTION *vim-improve-diff-introduction*
*vim-improve-diff* is a plugin to improve diff feature in Vim.
It provide the following features:
Auto diffupdate (|improve_diff#auto_diffupdate()|)
When user leave an insert mode, it call |diffupdate| when the current buffer
is in diff mode.
Auto diffoff (|improve_diff#auto_diffoff()|)
When user close a diff buffer, automatically call |diffoff|.
Improved |:DiffOrig| command
If no |:DiffOrig| command is defined, it automatically define an improved
version of |:DiffOrig| command.
You would probably interested in lambdalisue/vim-unified-diff which use
a 'histogram' algorithm to improve the quality of diff.
- lambdalisue/vim-unified-diff: https://github.com/lambdalisue/vim-unified-diff
==============================================================================
INSTALL *vim-improve-diff-install*
The repository (https://github.com/lambdalisue/vim-improve-diff) follow a
standard vim plugin's directory structure thus you can use Vundle.vim or
neobundle.vim to install |vim-improve-diff| like:
>
" Vundle.vim
Plugin 'lambdalisue/vim-improve-diff'
" neobundle.vim
NeoBundle 'lambdalisue/vim-improve-diff'
<
==============================================================================
INTERFACE *vim-improve-diff-interface*
------------------------------------------------------------------------------
Options *vim-improve-diff-interface-options*
*g:improve_diff#enable*
g:improve_diff#enable
Enable all features of vim-improve-diff.
The default value is 1.
*g:improve_diff#enable_auto_diffupdate*
g:improve_diff#enable_auto_diffupdate
Enable auto diffupdate feature (|improve_diff#auto_diffupdate()|).
This option takes effect only when |g:improve_diff#enable| is 0.
The default value is 0.
*g:improve_diff#enable_auto_diffoff*
g:improve_diff#enable_auto_diffoff
Enable auto diffoff feature (|improve_diff#auto_diffoff()|).
This option takes effect only when |g:improve_diff#enable| is 0.
The default value is 0.
*g:improve_diff#define_DiffOrig*
g:improve_diff#define_DiffOrig
Define an improved version of :DiffOrig.
The default value is 1 if :DiffOrig has not been defined, otherwise
the default value is 0.
------------------------------------------------------------------------------
Mappings *vim-improve-diff-interface-mappings*
*<Plug>(improve-diff-diffupdate)*
<Plug>(improve-diff-diffupdate)
Call |diff_improve#diffupdate()|
*<Plug>(improve-diff-diffoff)*
<Plug>(improve-diff-diffoff)
Call |diff_improve#diffoff()|
*<Plug>(improve-diff-difforig-h)*
<Plug>(improve-diff-difforig-h)
Call |diff_improve#difforig()| to horizontally open a original version.
*<Plug>(improve-diff-difforig-v)*
<Plug>(improve-diff-difforig-v)
Call |diff_improve#difforig()| to vertically open a original version.
-------------------------------------------------------------------------------
Functions *vim-improve-diff-interface-functions*
*diff_improve#enable()*
diff_improve#enable()
Enable all feature of vim-improve-diff.
*diff_improve#enable_auto_diffupdate()*
diff_improve#enable_auto_diffupdate()
Enable auto diffupdate feature. It define an autocmd to call
|diff_improve#diffupdate()| when user leave an insert mode.
*diff_improve#enable_auto_diffoff()*
diff_improve#enable_auto_diffoff()
Enable auto diffoff feature. It define an autocmd to call
|diff_improve#diffoff()| when user close a buffer.
*diff_improve#diffupdate()*
diff_improve#diffupdate([{expr}])
It takes effect only when the current buffer is in diff mode.
It call |diffupdate| on the current buffer.
*diff_improve#diffoff()*
diff_improve#diffoff([{expr}])
It takes effect only when the current buffer is in diff mode.
It call ||diffoff| on the {expr} or current buffer window.
*diff_improve#difforig()*
diff_improve#difforig([{horizontal}])
It open a current saved version of the current buffer in diff mode.
It is an improved version of :DiffOrig command of
$VIMRUNTIME/vimrc_example.vim.
If {horizontal} is 1, it open the saved version horizontally.
-------------------------------------------------------------------------------
Commands *vim-improve-diff-interface-commands*
*:DiffOrig-improved*
:DiffOrig [{horizontal}]
It call |diff_improve#difforig()|.
vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl:noet

View File

@ -0,0 +1,17 @@
let s:save_cpo = &cpo
set cpo&vim
if get(g:, 'improve_diff#enable', 1)
call improve_diff#enable()
elseif get(g:, 'improve_diff#enable_auto_diffupdate')
call improve_diff#enable_auto_diffupdate()
elseif get(g:, 'improve_diff#enable_auto_diffoff')
call improve_diff#enable_auto_diffoff()
endif
if get(g:, 'improve_diff#define_DiffOrig', !exists(':DiffOrig'))
command! -nargs=? DiffOrig call improve_diff#difforig(<f-args>)
endif
let &cpo = s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker:

View File

@ -0,0 +1,29 @@
# poppy.vim
vim port of [highlightparentheses.el](https://github.com/tsdh/highlight-parentheses.el) which gives rainbow parens propagating from the cursor
Enabled with autocmds ( :h autocommand )
example:
`au! cursormoved * call PoppyInit()`
or:
`au! cursormoved *.lisp call PoppyInit()`
or even make a mapping:
```
augroup Poppy
au!
augroup END
nnoremap <silent> <leader>hp :call clearmatches() \| let g:poppy = -get(g:,'poppy',-1) \|
\ exe 'au! Poppy CursorMoved *' . (g:poppy > 0 ? ' call PoppyInit()' : '') <cr>
```
modify coloring by changing `g:poppyhigh`, which is a list of highlight group names.
If you want only 1 paren level highlighted, let `g:poppyhigh` to a list with 1 group name.
If you want the highlighting to include matches which are under the cursor, like the matchparen plugin
included with vim, `let g:poppy_point_enable = 1` .

View File

@ -0,0 +1,49 @@
if !has('reltime') || exists('*PoppyInit')
finish
endif
let g:poppyhigh = get(g:,'poppyhigh',['identifier','constant','preproc','special','type'])
function s:highpat()
let s:synid_cache = {}
let stoplinebottom = line('w$')
let stoplinetop = line('w0')
let s:poppyhigh = deepcopy(g:poppyhigh)
let inc = get(g:,'poppy_point_enable') && getline('.')[col('.')-1] =~ '[[({]' ? 'c' : ''
call searchpair('\m[[({]','','noop',inc.(len(g:poppyhigh) > 1 ? 'r' : '').'nbW',"getline('.')[col('.')-1] == 'n' ||"
\ ."s:SynAt(line('.'),col('.')) =~? 'regex\\|comment\\|string' ||"
\ ."s:endpart(".stoplinebottom.")",stoplinetop,30)
endfunction
function s:SynAt(l,c)
let pos = a:l.','.a:c
if !has_key(s:synid_cache,pos)
let s:synid_cache[pos] = synIDattr(synID(a:l,a:c,0),'name')
endif
return s:synid_cache[pos]
endfunction
if exists('*matchaddpos')
function s:matchadd(hi,pos)
return matchaddpos(a:hi,a:pos)
endfunction
else
function s:matchadd(hi,pos)
return matchadd(a:hi,'\%' . a:pos[0][0] . 'l\%' . a:pos[0][1] . 'c\|\%' . a:pos[1][0] . 'l\%' . a:pos[1][1] . 'c')
endfunction
endif
function s:endpart(b)
let i = stridx('[({',getline('.')[col('.')-1])
let p = searchpairpos('\V'.'[({'[i],'','\V'.'])}'[i],'nW',"s:SynAt(line('.'),col('.')) =~? 'regex\\|comment\\|string'"
\ ,a:b,300)
if p[0] && (line2byte(p[0])+p[1] > line2byte(s:pos[0]) + s:pos[1] || get(g:,'poppy_point_enable') && p == s:pos)
let w:poppies += [s:matchadd(remove(add(s:poppyhigh,s:poppyhigh[0]),0), [getpos('.')[1:2],p])]
else
return 1
endif
endfunction
function PoppyInit()
let s:pos = getpos('.')[1:2] | let w:poppies = get(w:,'poppies',[])
\ | silent! call filter(w:poppies,'matchdelete(v:val)>0') | call s:highpat()
endfunction

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2023 Rick Howe (Takumi Ohtani)
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,173 @@
# spotdiff.vim
### A range and area selectable `:diffthis` to compare partially
Vim provides a diff mode which is useful to see differences between windows.
However, it always shows the differences for entire line. And it can not
compare a sequence of words within a line, and sentences and paragraphs which
are separated into several lines.
To compare partially everywhere in any window, this plugin provides two groups
of commands, which are alternative to vim original `:diffthis`, `:diffoff`,
and `:diffupdate`. One is for which allows to select a range of lines in diff
mode. Another is for which allows to select the Visual, motion, and text
object area in non-diff normal mode. Both work independently in a tab page.
## Selecting a range of lines
There are `:Diffthis`, `:Diffoff`, and `:Diffupdate` commands available.
You can use `:Diffthis` to specify a range of lines to be compared. And can
use `:Diffoff` to reset and `:Diffupdate` to update the differences.
Do not use vim original diff commands together with this plugin's ones. Try
`:Diffoff!` to reset all in a trouble.
If you have installed [diffchar.vim](https://github.com/rickhowe/diffchar.vim)
plugin, you can see the exact differences and use their options and keymaps.
#### Commands
* `:[range]Diffthis`
* Select a range of lines with `[range]` (default: current line) and make the
current window diff mode. The selected lines are highlighted in
`hl-CursorColumn`. Shortly after the two separate windows become diff
mode, `:Diffthis` shows the differences for selected lines in each window.
It is also possible to select two ranges of lines in the same window. In
that case, `:Diffthis` opens a temporary new window at above or below (or
left or right if "vertical" is included in the 'diffopt' option) of the
current one, copies selected lines to it, and shows the difference with
source window.
* `:Diffoff[!]`
* Clear the selected range of lines and reset diff mode for the current
window. If `!` flag is specified, clear and reset for all windows in the
current tab page. The temporary window created by `:Diffthis` will be
closed.
* `:Diffupdate`
* Update the differences for the selected range of lines in the current tab
page.
#### Demo
![demoRS](demoRS.gif)
## Selecting the Visual, motion, and text object area
There are `:VDiffthis`, `:VDiffoff`, and `:VDiffupdate` commands available.
You can use `:VDiffthis` to specify the Visual area to be compared. And can
use `:VDiffoff` to reset and `:VDiffupdate` to update the differences. Note
that those commands work in non-diff normal mode.
While showing the exact differences, when the cursor is moved on a difference
unit, you can see its corresponding unit highlighted in `hl-Cursor`, according
to the `g:DiffPairVisible` option.
You can use `]b` or `]e` to jump cursor to start or end position of the next
difference unit, and `[b` or `[e` to the start or end position of the previous
unit.
This plugin provides the corresponding mappings to those commands, such as
`<Plug>(VDiffthis)` and `<Plug>(VDiffoff)`. As a default, `<Leader>t` and `<Leader>o`
keys are mapped to them and, for example, `v$<Leader>t` selects the text from
the current cursor position to the end of line and `3vis<Leader>t` selects the
next 3 sentences as the Visual area. And `<Leader>o` clears the selected area.
In addition to selecting the Visual area, you can use `<Leader>t` as a custom
operator followed by a motion or a text object command, which will set those
selected area as the Visual one and then call `:VDiffthis`. For example,
`<Leader>t$` and `<Leader>t3is` work same as above examples.
#### Commands
* `:[range]VDiffthis[!]`
* Select the characterwise, linewise, or blockwise Visual area most recently
used in the current window. If `[range]` (default: current line) is not
specified as `'<,'>` and different from the last Visual area, those
specified lines are selected as linewise area instead. The selected area
is highlighted in `hl-DiffChange` with "italic", and then will be compared
as a single combined line. Shortly after the two area are selected,
`:VDiffthis` compares them based on the `g:DiffUnit` option and "icase",
"iwhite", "iwhiteall" and "iwhiteeol" flags in the 'diffopt' option. In
addition, when "indent-heuristic" is specified, positioning of the
added/deleted diff units is adjusted to make them easier to read. Then
their differences are shown using the `g:DiffColors` option. It is also
possible to select two area in the same window. If `!` flag is specified,
each line is separately compared, which would be useful particular for
columns in a table on blockwise area. Redundant lines in the line-by-line
comparison are shown with "strikethrough".
* `:VDiffoff[!]`
* Clear the selected area in the current window and reset the differences.
When there are two area selected in the same window, both area will be
cleared. But either one is cleared if the current cursor is located within
it. If `!` flag is specified, clear and reset all area in the current tab
page.
* `:VDiffupdate`
* Compare the selected area again and show their differences in the current
tab page, when you make changes to the selected area or you want to change
the `g:DiffUnit` or `g:DiffColors` option or some flags in the 'diffopt'
option.
#### Options
These options are same as those used in the [diffchar.vim](https://github.com/rickhowe/diffchar.vim) plugin.
* `g:DiffUnit`, `t:DiffUnit`: A type of difference unit
| Value | Description |
| --- | --- |
| 'Char' | any single character |
| 'Word1' | `\w\+` word and any `\W` single character (default) |
| 'Word2' | non-space and space words |
| 'Word3' | `\<` or `\>` character class boundaries (set by `iskeyword` option) |
| 'word' | see `word` |
| 'WORD' | see `WORD` |
| '[{del}]' | one or more diff unit delimiters (e.g. "[,:\t<>]") |
| '/{pat}/' | a pattern to split into diff units (e.g. '/.\{4}\zs/') |
* `g:DiffColors`, `t:DiffColors`: Matching colors for changed units (`hl-DiffAdd` for added units)
| Value | Description |
| --- | --- |
| 0 | `hl-DiffText` (default) |
| 1 | `hl-DiffText` + a few (3, 4, ...) highlight groups |
| 2 | `hl-DiffText` + several (7, 8, ...) highlight groups |
| 3 | `hl-DiffText` + many (11, 12, ...) highlight groups |
| 100 | all available highlight groups in random order |
| [{hlg}] | a list of your favorite highlight groups |
* `g:DiffPairVisible`, `t:DiffPairVisible`: Visibility of corresponding diff units
| Value | Description |
| --- | --- |
| 0 | disable |
| 1 | highlight with `hl-Cursor` (default) |
#### Keymaps
These keymaps are same as those used in the [diffchar.vim](https://github.com/rickhowe/diffchar.vim) plugin.
| Mapping | Default Key | Description |
| --- | --- | --- |
| `<Plug>JumpDiffCharPrevStart` | `[b` | Jump cursor to the start position of the previous diff unit |
| `<Plug>JumpDiffCharNextStart` | `]b` | Jump cursor to the start position of the next diff unit |
| `<Plug>JumpDiffCharPrevEnd` | `[e` | Jump cursor to the end position of the previous diff unit |
| `<Plug>JumpDiffCharNextEnd` | `]e` | Jump cursor to the end position of the next diff unit |
These keymaps are used only in this plugin.
| Mapping | Default Key | Description |
| --- | --- | --- |
| `<Plug>(VDiffthis)` | `<Leader>t` | * Call `:VDiffthis` for the visually selected area<br>* Set the selected motion and text object area as the Visual one and then call `:VDiffthis` |
| `<Plug>(VDiffthis!)` | `<Leader>T` | * Call `:VDiffthis!` for the visually selected area<br>* Set the selected motion and text object area as the Visual one and then call `:VDiffthis!` |
| `<Plug>(VDiffoff)` | `<Leader>o` | Call `:VDiffoff` in the current window |
| `<Plug>(VDiffoff!)` | `<Leader>O` | Call `:VDiffoff!` in the current tab page |
| `<Plug>(VDiffupdate)` | `<Leader>u` | Call `:VDiffupdate` in the current tab page |
#### Demo
![demoVS](demoVS.gif)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

@ -0,0 +1,283 @@
*spotdiff.txt* A range and area selectable `:diffthis` to compare partially
Last Change: 2024/06/23
Version: 5.2
Author: Rick Howe (Takumi Ohtani) <rdcxy754@ybb.ne.jp>
Copyright: (c) 2014-2024 by Rick Howe
License: MIT
INTRODUCTION *spotdiff*
Vim provides a diff mode which is useful to see differences between windows.
However, it always shows the differences for entire line. And it can not
compare a sequence of words within a line, and sentences and paragraphs which
are separated into several lines.
To compare partially everywhere in any window, this plugin provides two groups
of commands, which are alternative to vim original `:diffthis`, `:diffoff`,
and `:diffupdate`. One is for which allows to select a range of lines in diff
mode. Another is for which allows to select the Visual, motion, and text
object area in non-diff normal mode. Both work independently in a tab page.
==============================================================================
Selecting a range of lines *spotdiff-range*
There are `:Diffthis`, `:Diffoff`, and `:Diffupdate` commands available.
You can use `:Diffthis` to specify a range of lines to be compared. And can
use `:Diffoff` to reset and `:Diffupdate` to update the differences.
Do not use vim original diff commands together with this plugin's ones. Try
`:Diffoff!` to reset all in a trouble.
If you have installed |diffchar.vim| plugin
(https://github.com/rickhowe/diffchar.vim), you can see the exact differences
and use their options and keymaps.
Commands ~
:[range]Diffthis
Select a range of lines with [range] (default: current line) and make the
current window diff mode. The selected lines are highlighted in
|hl-CursorColumn|. Shortly after the two separate windows become diff
mode, `:Diffthis` shows the differences for selected lines in each window.
It is also possible to select two ranges of lines in the same window. In
that case, `:Diffthis` opens a temporary new window at above or below (or
left or right if "vertical" is included in the 'diffopt' option) of the
current one, copies selected lines to it, and shows the difference with
source window.
:Diffoff[!]
Clear the selected range of lines and reset diff mode for the current
window. If `!` flag is specified, clear and reset for all windows in the
current tab page. The temporary window created by `:Diffthis` will be
closed.
:Diffupdate
Update the differences for the selected range of lines in the current tab
page.
==============================================================================
Selecting the Visual, motion, and text object area *spotdiff-area*
There are `:VDiffthis`, `:VDiffoff`, and `:VDiffupdate` commands available.
You can use `:VDiffthis` to specify the Visual area to be compared. And can
use `:VDiffoff` to reset and `:VDiffupdate` to update the differences. Note
that those commands work in non-diff normal mode.
While showing the exact differences, when the cursor is moved on a difference
unit, you can see its corresponding unit highlighted in |hl-Cursor|, according
to the |g:DiffPairVisible| option.
You can use `]b` or `]e` to jump cursor to start or end position of the next
difference unit, and `[b` or `[e` to the start or end position of the previous
unit.
This plugin provides the corresponding mappings to those commands, such as
<Plug>(VDiffthis) and <Plug>(VDiffoff). As a default, <Leader>t and <Leader>o
keys are mapped to them and, for example, "v$<Leader>t" selects the text from
the current cursor position to the end of line and "3vis<Leader>t" selects the
next 3 sentences as the Visual area. And "<Leader>o" clears the selected area.
In addition to selecting the Visual area, you can use <Leader>t as a custom
operator followed by a motion or a text object command, which will set those
selected area as the Visual one and then call `:VDiffthis`. For example,
"<Leader>t$" and "<Leader>t3is" work same as above examples.
Commands ~
:[range]VDiffthis[!]
Select the characterwise, linewise, or blockwise Visual area most recently
used in the current window. If [range] (default: current line) is not
specified as "'<,'>" and different from the last Visual area, those
specified lines are selected as linewise area instead. The selected area
is highlighted in |hl-DiffChange| with "italic", and then will be compared
as a single combined line. Shortly after the two area are selected,
`:VDiffthis` compares them based on the |g:DiffUnit| option and "icase",
"iwhite", "iwhiteall" and "iwhiteeol" flags in the 'diffopt' option. In
addition, when "indent-heuristic" is specified, positioning of the
added/deleted diff units is adjusted to make them easier to read. Then
their differences are shown using the |g:DiffColors| option. It is also
possible to select two area in the same window. If `!` flag is specified,
each line is separately compared, which would be useful particular for
columns in a table on blockwise area. Redundant lines in the line-by-line
comparison are shown with "strikethrough".
:VDiffoff[!]
Clear the selected area in the current window and reset the differences.
When there are two area selected in the same window, both area will be
cleared. But either one is cleared if the current cursor is located within
it. If `!` flag is specified, clear and reset all area in the current tab
page.
:VDiffupdate
Compare the selected area again and show their differences in the current
tab page, when you make changes to the selected area or you want to change
the |g:DiffUnit| or |g:DiffColors| option or some flags in the 'diffopt'
option.
Options ~
* These options are same as those used in the |diffchar.vim| plugin.
|g:DiffUnit|, |t:DiffUnit|
A type of diff unit
'Char' : any single character
'Word1' : \w\+ word and any \W single character (default)
'Word2' : non-space and space words
'Word3' : \< or \> character class boundaries (set by 'iskeyword' option)
'word' : see `word`
'WORD' : see `WORD`
'[{del}]' : one or more diff unit delimiters (e.g. "[,:\t<>]")
'/{pat}/' : a pattern to split into diff units (e.g. '/.\{4}\zs/')
|g:DiffColors|, |t:DiffColors|
Matching colors for changed units (|hl-DiffAdd| for added units)
0 : |hl-DiffText| (default)
1 : |hl-DiffText| + a few (3, 4, ...) highlight groups
2 : |hl-DiffText| + several (7, 8, ...) highlight groups
3 : |hl-DiffText| + many (11, 12, ...) highlight groups
100 : all available highlight groups in random order
[{hlg}] : a list of your favorite highlight groups
|g:DiffPairVisible|, |t:DiffPairVisible|
Visibility of corresponding diff units
0 : disable
1 : highlight with |hl-Cursor| (default)
Keymaps ~
* These keymaps are same as those used in the |diffchar.vim| plugin.
<Plug>JumpDiffCharPrevStart (default: `[b`)
Jump cursor to the start position of the previous difference unit
<Plug>JumpDiffCharNextStart (default: `]b`)
Jump cursor to the start position of the next difference unit
<Plug>JumpDiffCharPrevEnd (default: `[e`)
Jump cursor to the end position of the previous difference unit
<Plug>JumpDiffCharNextEnd (default: `]e`)
Jump cursor to the end position of the next difference unit
* These keymaps are used only in this plugin.
<Plug>(VDiffthis) (default: `<Leader>t`)
Call `:VDiffthis` for the visually selected area
Set the selected motion and text object area as the Visual one and then
call `:VDiffthis`
<Plug>(VDiffthis!) (default: `<Leader>T`)
Call `:VDiffthis!` for the visually selected area
Set the selected motion and text object area as the Visual one and then
call `:VDiffthis!`
<Plug>(VDiffoff) (default: `<Leader>o`)
Call `:VDiffoff` in the current window
<Plug>(VDiffoff!) (default: `<Leader>O`)
Call `:VDiffoff!` in the current tab page
<Plug>(VDiffupdate) (default: `<Leader>u`)
Call `:VDiffupdate` in the current tab page
==============================================================================
CHANGE HISTORY *spotdiff-history*
Update : 5.2
* Implemented to update the differences shortly after the text is changed.
Update : 5.1
* Added to open a temporary new window at left or right in |:Diffthis| command
if "vertical" is included in the 'diffopt' option.
Update : 5.0
* Changed to support vim 8.2 and nvim 0.4.4 or later.
* Added some minor changes such as an error check in `:Diffthis` command.
Update : 4.5
* Implemented to redefine visual area highlight groups whenever the color
scheme is loaded.
* Updated |g:DiffUnit| and |g:DiffColors| options to reflect those updated in
the |diffchar.vim| 9.1.
- Added vim original 'word' and 'WORD' units, one or more unit delimiters,
and a custom pattern to split into diff units in |g:DiffUnit| option.
- Changed the category of |g:DiffColors| option as a few, several, and many
numbers of matching colors, depending on the loaded color scheme.
- Added a list of your favorite highlight groups in |g:DiffColors| option.
Update : 4.4
* Enhanced to make diff units easier to read when "indent-heuristic" is
specified in the 'diffopt' option.
* Fixed some defects.
Update : 4.3
* Updated to check a new WinClosed event (patch-8.2.3591) to appropriately
clear the selected range or area and reset its differences when a window is
closed.
Update : 4.2
* Changed `:VDiffoff` command to check the current cursor position and find
which of two selected area is to be cleared in the same window.
Update : 4.1
* Added the keymaps which correspond to the `:VDiffthis`, `:VDiffoff`, and
`:VDiffupdate` commands.
* Added a custom operator which can select the motion and text object area by
using the 'operatorfunc' option.
* Added [range] to `:VDiffoff` to clear either one of selected area in the
same window.
* Added the diffchar's |g:DiffPairVisible| option which highlights a
corresponding diff unit.
* Added the diffchar's keymaps which jump cursor to the start/end position of
the next/previous diff unit.
Update : 4.0
* Added `:VDiffthis`, `:VDiffoff`, and `:VDiffupdate` commands to select the
Visual area to be compared as a single combined line or multiple separate
lines.
* Removed to use Conceal and Sign features in `:Diffthis` command.
Update : 3.2
* Changed to use |hl-CursorLine|, instead of underline and '-' in the fold
column, to indicate the selected lines.
Update : 3.1
* Set a plugin specific expression to 'diffexpr' option while spot diff'ed to
disable a new internal diff (patch-8.1.360).
Update : 3.0
* Disable a new internal diff in 'diffopt' option (patch-8.1.360) to prevent
unselected lines to be incorrectly diff'ed. And make this plugin work well
even if an external diff command is not available.
* Open a temporary window, when `:Diffthis` is used twice in a single window,
highly enough to display all selected lines. And close it when `:Diffoff` is
used not only in it but also in the original window.
* Support new iwhiteall and iwhiteeol of 'diffopt' option.
* Removed a support for vim version 7.x.
Update : 2.2
* Added `:Diffupdate` command.
Update : 2.1
* The selected lines are all underlined using sign feature, in addition to a
'-' in the fold column, to make them more visible.
* Fixed some defects.
Update : 2.0
* `:Diffthis` indicates the selected lines with a '-' in the fold column.
* `:Diffthis` always highlighted other lines than selected with |hl-Conceal|,
but `!` is required as optionally.
Update : 1.1
* `:Diffthis` highlights other lines than selected with |hl-Conceal|, instead
of showing selected lines with sign feature.
* `:Diffthis` and `:Diffoff` try to repair any diff mode mismatch, instead of
stopping with error messages.
* The 'diffopt' foldcolumn:{n} option was ignored, but follows it as vim does.
* A temporary new window, which opens when `:Diffthis` is used twice in a
single window, was sometimes too large, but shows as few as those lines.
vim:tw=78:ts=8:ft=help:norl:

View File

@ -0,0 +1,60 @@
" spotdiff.vim : A range and area selectable diffthis to compare partially
"
" Last Change: 2024/06/23
" Version: 5.2
" Author: Rick Howe (Takumi Ohtani) <rdcxy754@ybb.ne.jp>
" Copyright: (c) 2014-2024 by Rick Howe
" License: MIT
if exists('g:loaded_spotdiff') || !has('diff') || !exists('##WinClosed')
finish
endif
let g:loaded_spotdiff = 5.2
let s:save_cpo = &cpoptions
set cpo&vim
command! -range -bar Diffthis call spotdiff#Diffthis(<line1>, <line2>)
command! -bang -bar Diffoff call spotdiff#Diffoff(<bang>0)
command! -bar Diffupdate call spotdiff#Diffupdate()
command! -range -bang -bar
\ VDiffthis call spotdiff#VDiffthis(<line1>, <line2>, <bang>0)
command! -bang -bar VDiffoff call spotdiff#VDiffoff(<bang>0)
command! -bar VDiffupdate call spotdiff#VDiffupdate()
for [mod, key, plg, cmd] in [
\['v', '<Leader>t', '<Plug>(VDiffthis)',
\':<C-U>call spotdiff#VDiffthis(line("''<"), line("''>"), 0)<CR>'],
\['v', '<Leader>T', '<Plug>(VDiffthis!)',
\':<C-U>call spotdiff#VDiffthis(line("''<"), line("''>"), 1)<CR>'],
\['n', '<Leader>o', '<Plug>(VDiffoff)',
\':<C-U>call spotdiff#VDiffoff(0)<CR>'],
\['n', '<Leader>O', '<Plug>(VDiffoff!)',
\':<C-U>call spotdiff#VDiffoff(1)<CR>'],
\['n', '<Leader>u', '<Plug>(VDiffupdate)',
\':<C-U>call spotdiff#VDiffupdate()<CR>'],
\['n', '<Leader>t', '<Plug>(VDiffthis)',
\':let &operatorfunc = ''<SID>VDiffOpFunc0''<CR>g@'],
\['n', '<Leader>T', '<Plug>(VDiffthis!)',
\':let &operatorfunc = ''<SID>VDiffOpFunc1''<CR>g@']]
if !hasmapto(plg, mod) && empty(maparg(key, mod))
if get(g:, 'VDiffDoMapping', 1)
call execute(mod . 'map <silent> ' . key . ' ' . plg)
endif
endif
call execute(mod . 'noremap <silent> ' . plg . ' ' . cmd)
endfor
function! s:VDiffOpFunc0(vm) abort
call spotdiff#VDiffOpFunc(a:vm, 0)
endfunction
function! s:VDiffOpFunc1(vm) abort
call spotdiff#VDiffOpFunc(a:vm, 1)
endfunction
let &cpoptions = s:save_cpo
unlet s:save_cpo
" vim: ts=2 sw=0 sts=-1 et

View File

@ -0,0 +1,24 @@
Copyright (c) 2016, Matthew J. Wozniski
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The names of the contributors may not be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,38 @@
Tabular
==============
Sometimes, it's useful to line up text. Naturally, it's nicer to have the
computer do this for you, since aligning things by hand quickly becomes
unpleasant. While there are other plugins for aligning text, the ones I've
tried are either impossibly difficult to understand and use, or too simplistic
to handle complicated tasks. This plugin aims to make the easy things easy
and the hard things possible, without providing an unnecessarily obtuse
interface. It's still a work in progress, and criticisms are welcome.
See [Aligning Text with Tabular.vim](http://vimcasts.org/episodes/aligning-text-with-tabular-vim/)
for a screencast that shows how Tabular.vim works.
See [doc/Tabular.txt](http://raw.github.com/godlygeek/tabular/master/doc/Tabular.txt)
for detailed documentation.
Installation
==============
## Vim 8.1+
No third-party package manager is required! Clone into:
`.vim/pack/plugins/start`
Make sure you include `packloadall` in your `.vimrc`.
## Pathogen
mkdir -p ~/.vim/bundle
cd ~/.vim/bundle
git clone https://github.com/godlygeek/tabular.git
Once help tags have been generated (either using Pathogen's `:Helptags`
command, or by pointing vim's `:helptags` command at the directory where you
installed Tabular), you can view the manual with `:help tabular`.
See [pathogen.vim](https://github.com/tpope/vim-pathogen) for help or for package manager installation.

View File

@ -0,0 +1,74 @@
" Copyright (c) 2016, Matthew J. Wozniski
" All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
" * Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" * Redistributions in binary form must reproduce the above copyright
" notice, this list of conditions and the following disclaimer in the
" documentation and/or other materials provided with the distribution.
" * The names of the contributors may not be used to endorse or promote
" products derived from this software without specific prior written
" permission.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
" NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if !exists(':Tabularize') || get(g:, 'no_default_tabular_maps', 0)
finish " Tabular.vim wasn't loaded or the default maps are unwanted
endif
let s:save_cpo = &cpo
set cpo&vim
AddTabularPattern! assignment /[|&+*/%<>=!~-]\@<!\([<>!=]=\|=\~\)\@![|&+*/%<>=!~-]*=/l1r1
AddTabularPattern! two_spaces / /l0
AddTabularPipeline! multiple_spaces / / map(a:lines, "substitute(v:val, ' *', ' ', 'g')") | tabular#TabularizeStrings(a:lines, ' ', 'l0')
AddTabularPipeline! spaces / / map(a:lines, "substitute(v:val, ' *' , ' ' , 'g')") | tabular#TabularizeStrings(a:lines, ' ' , 'l0')
AddTabularPipeline! argument_list /(.*)/ map(a:lines, 'substitute(v:val, ''\s*\([(,)]\)\s*'', ''\1'', ''g'')')
\ | tabular#TabularizeStrings(a:lines, '[(,)]', 'l0')
\ | map(a:lines, 'substitute(v:val, ''\(\s*\),'', '',\1 '', "g")')
\ | map(a:lines, 'substitute(v:val, ''\s*)'', ")", "g")')
function! SplitCDeclarations(lines)
let rv = []
for line in a:lines
" split the line into declaractions
let split = split(line, '\s*[,;]\s*')
" separate the type from the first declaration
let type = substitute(split[0], '\%(\%([&*]\s*\)*\)\=\k\+$', '', '')
" add the ; back on every declaration
call map(split, 'v:val . ";"')
" add the first element to the return as-is, and remove it from the list
let rv += [ remove(split, 0) ]
" transform the other elements by adding the type on at the beginning
call map(split, 'type . v:val')
" and add them all to the return
let rv += split
endfor
return rv
endfunction
AddTabularPipeline! split_declarations /,.*;/ SplitCDeclarations(a:lines)
AddTabularPattern! ternary_operator /^.\{-}\zs?\|:/l1
AddTabularPattern! cpp_io /<<\|>>/l1
AddTabularPattern! pascal_assign /:=/l1
AddTabularPattern! trailing_c_comments /\/\*\|\*\/\|\/\//l1
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,437 @@
" Tabular: Align columnar data using regex-designated column boundaries
" Maintainer: Matthew Wozniski (godlygeek@gmail.com)
" Date: Thu, 03 May 2012 20:49:32 -0400
" Version: 1.0
"
" Long Description:
" Sometimes, it's useful to line up text. Naturally, it's nicer to have the
" computer do this for you, since aligning things by hand quickly becomes
" unpleasant. While there are other plugins for aligning text, the ones I've
" tried are either impossibly difficult to understand and use, or too simplistic
" to handle complicated tasks. This plugin aims to make the easy things easy
" and the hard things possible, without providing an unnecessarily obtuse
" interface. It's still a work in progress, and criticisms are welcome.
"
" License:
" Copyright (c) 2012, Matthew J. Wozniski
" All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
" * Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" * Redistributions in binary form must reproduce the above copyright
" notice, this list of conditions and the following disclaimer in the
" documentation and/or other materials provided with the distribution.
" * The names of the contributors may not be used to endorse or promote
" products derived from this software without specific prior written
" permission.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
" NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
" Stupid vimscript crap {{{1
let s:savecpo = &cpo
set cpo&vim
" Private Functions {{{1
" Return the number of bytes in a string after expanding tabs to spaces. {{{2
" This expansion is done based on the current value of 'tabstop'
if exists('*strdisplaywidth')
" Needs vim 7.3
let s:Strlen = function("strdisplaywidth")
else
function! s:Strlen(string)
" Implement the tab handling part of strdisplaywidth for vim 7.2 and
" earlier - not much that can be done about handling doublewidth
" characters.
let rv = 0
let i = 0
for char in split(a:string, '\zs')
if char == "\t"
let rv += &ts - i
let i = 0
else
let rv += 1
let i = (i + 1) % &ts
endif
endfor
return rv
endfunction
endif
" Align a string within a field {{{2
" These functions do not trim leading and trailing spaces.
" Right align 'string' in a field of size 'fieldwidth'
function! s:Right(string, fieldwidth)
let spaces = a:fieldwidth - s:Strlen(a:string)
return matchstr(a:string, '^\s*') . repeat(" ", spaces) . substitute(a:string, '^\s*', '', '')
endfunction
" Left align 'string' in a field of size 'fieldwidth'
function! s:Left(string, fieldwidth)
let spaces = a:fieldwidth - s:Strlen(a:string)
return a:string . repeat(" ", spaces)
endfunction
" Center align 'string' in a field of size 'fieldwidth'
function! s:Center(string, fieldwidth)
let spaces = a:fieldwidth - s:Strlen(a:string)
let right = spaces / 2
let left = right + (right * 2 != spaces)
return repeat(" ", left) . a:string . repeat(" ", right)
endfunction
" Remove spaces around a string {{{2
" Remove all trailing spaces from a string.
function! s:StripTrailingSpaces(string)
return matchstr(a:string, '^.\{-}\ze\s*$')
endfunction
" Remove all leading spaces from a string.
function! s:StripLeadingSpaces(string)
return matchstr(a:string, '^\s*\zs.*$')
endfunction
" Find the longest common indent for a list of strings {{{2
" If a string is shorter than the others but contains no non-whitespace
" characters, it does not end the match. This provides consistency with
" vim's behavior that blank lines don't have trailing spaces.
function! s:LongestCommonIndent(strings)
if empty(a:strings)
return ''
endif
let n = 0
while 1
let ns = join(map(copy(a:strings), 'v:val[n]'), '')
if ns !~ '^ \+$\|^\t\+$'
break
endif
let n += 1
endwhile
return strpart(a:strings[0], 0, n)
endfunction
" Split a string into fields and delimiters {{{2
" Like split(), but include the delimiters as elements
" All odd numbered elements are delimiters
" All even numbered elements are non-delimiters (including zero)
function! s:SplitDelim(string, delim)
let rv = []
let beg = 0
let len = len(a:string)
let searchoff = 0
while 1
let mid = match(a:string, a:delim, beg + searchoff, 1)
if mid == -1 || mid == len
break
endif
let matchstr = matchstr(a:string, a:delim, beg + searchoff, 1)
let length = strlen(matchstr)
if length == 0 && beg == mid
" Zero-length match for a zero-length delimiter - advance past it
let searchoff += 1
continue
endif
if beg == mid
let rv += [ "" ]
else
let rv += [ a:string[beg : mid-1] ]
endif
let rv += [ matchstr ]
let beg = mid + length
let searchoff = 0
endwhile
let rv += [ strpart(a:string, beg) ]
return rv
endfunction
" Replace lines from `start' to `start + len - 1' with the given strings. {{{2
" If more lines are needed to show all strings, they will be added.
" If there are too few strings to fill all lines, lines will be removed.
function! s:SetLines(start, len, strings)
if a:start > line('$') + 1 || a:start < 1
throw "Invalid start line!"
endif
if len(a:strings) > a:len
let fensave = &fen
let view = winsaveview()
call append(a:start + a:len - 1, repeat([''], len(a:strings) - a:len))
call winrestview(view)
let &fen = fensave
elseif len(a:strings) < a:len
let fensave = &fen
let view = winsaveview()
sil exe (a:start + len(a:strings)) . ',' . (a:start + a:len - 1) . 'd_'
call winrestview(view)
let &fen = fensave
endif
call setline(a:start, a:strings)
endfunction
" Runs the given commandstring argument as an expression. {{{2
" The commandstring expression is expected to reference the a:lines argument.
" If the commandstring expression returns a list the items of that list will
" replace the items in a:lines, otherwise the expression is assumed to have
" modified a:lines itself.
function! s:FilterString(lines, commandstring)
exe 'let rv = ' . a:commandstring
if type(rv) == type(a:lines) && rv isnot a:lines
call filter(a:lines, 0)
call extend(a:lines, rv)
endif
endfunction
" Public API {{{1
if !exists("g:tabular_default_format")
let g:tabular_default_format = "l1"
endif
let s:formatelempat = '\%([lrc]\d\+\)'
function! tabular#ElementFormatPattern()
return s:formatelempat
endfunction
" Given a list of strings and a delimiter, split each string on every
" occurrence of the delimiter pattern, format each element according to either
" the provided format (optional) or the default format, and join them back
" together with enough space padding to guarantee that the nth delimiter of
" each string is aligned.
function! tabular#TabularizeStrings(strings, delim, ...)
if a:0 > 1
echoerr "TabularizeStrings accepts only 2 or 3 arguments (got ".(a:0+2).")"
return 1
endif
let formatstr = (a:0 ? a:1 : g:tabular_default_format)
if formatstr !~? s:formatelempat . '\+'
echoerr "Tabular: Invalid format \"" . formatstr . "\" specified!"
return 1
endif
let format = split(formatstr, s:formatelempat . '\zs')
let lines = a:strings
call map(lines, 's:SplitDelim(v:val, a:delim)')
let first_fields = []
" Strip spaces from non-delimiters; spaces in delimiters must have been
" matched intentionally
for line in lines
if len(line) == 1 && s:do_gtabularize
continue " Leave non-matching lines unchanged for GTabularize
endif
call add(first_fields, line[0])
if len(line) >= 1
for i in range(0, len(line)-1, 2)
let line[i] = s:StripLeadingSpaces(s:StripTrailingSpaces(line[i]))
endfor
endif
endfor
let common_indent = s:LongestCommonIndent(first_fields)
" Find the max length of each field
let maxes = []
for line in lines
if len(line) == 1 && s:do_gtabularize
continue " non-matching lines don't affect field widths for GTabularize
endif
for i in range(len(line))
if i == len(maxes)
let maxes += [ s:Strlen(line[i]) ]
else
let maxes[i] = max( [ maxes[i], s:Strlen(line[i]) ] )
endif
endfor
endfor
" Concatenate the fields, according to the format pattern.
for idx in range(len(lines))
let line = lines[idx]
if len(line) == 1 && s:do_gtabularize
let lines[idx] = line[0] " GTabularize doesn't change non-matching lines
continue
endif
for i in range(len(line))
let how = format[i % len(format)][0]
let pad = format[i % len(format)][1:-1]
if how =~? 'l'
let field = s:Left(line[i], maxes[i])
elseif how =~? 'r'
let field = s:Right(line[i], maxes[i])
elseif how =~? 'c'
let field = s:Center(line[i], maxes[i])
endif
let line[i] = field . repeat(" ", pad)
endfor
let prefix = common_indent
if len(line) == 1 && s:do_gtabularize
" We didn't strip the indent in this case; nothing to put back.
let prefix = ''
endif
let lines[idx] = s:StripTrailingSpaces(prefix . join(line, ''))
endfor
endfunction
" Apply 0 or more filters, in sequence, to selected text in the buffer {{{2
" The lines to be filtered are determined as follows:
" If the function is called with a range containing multiple lines, then
" those lines will be used as the range.
" If the function is called with no range or with a range of 1 line, then
" if GTabularize mode is being used,
" the range will not be adjusted
" if "includepat" is not specified,
" that 1 line will be filtered,
" if "includepat" is specified and that line does not match it,
" no lines will be filtered
" if "includepat" is specified and that line does match it,
" all contiguous lines above and below the specified line matching the
" pattern will be filtered.
"
" The remaining arguments must each be a filter to apply to the text.
" Each filter must either be a String evaluating to a function to be called.
function! tabular#PipeRange(includepat, ...) range
exe a:firstline . ',' . a:lastline
\ . 'call tabular#PipeRangeWithOptions(a:includepat, a:000, {})'
endfunction
" Extended version of tabular#PipeRange, which
" 1) Takes the list of filters as an explicit list rather than as varargs
" 2) Supports passing a dictionary of options to control the routine.
" Currently, the only supported option is 'mode', which determines whether
" to behave as :Tabularize or as :GTabularize
" This allows me to add new features here without breaking API compatibility
" in the future.
function! tabular#PipeRangeWithOptions(includepat, filterlist, options) range
let top = a:firstline
let bot = a:lastline
let s:do_gtabularize = (get(a:options, 'mode', '') ==# 'GTabularize')
if !s:do_gtabularize
" In the default mode, apply range extension logic
if a:includepat != '' && top == bot
if top < 0 || top > line('$') || getline(top) !~ a:includepat
return
endif
while top > 1 && getline(top-1) =~ a:includepat
let top -= 1
endwhile
while bot < line('$') && getline(bot+1) =~ a:includepat
let bot += 1
endwhile
endif
endif
let lines = map(range(top, bot), 'getline(v:val)')
for filter in a:filterlist
if type(filter) != type("")
echoerr "PipeRange: Bad filter: " . string(filter)
endif
call s:FilterString(lines, filter)
unlet filter
endfor
call s:SetLines(top, bot - top + 1, lines)
endfunction
" Part of the public interface so interested pipelines can query this and
" adjust their behavior appropriately.
function! tabular#DoGTabularize()
return s:do_gtabularize
endfunction
function! s:SplitDelimTest(string, delim, expected)
let result = s:SplitDelim(a:string, a:delim)
if result !=# a:expected
echomsg 'Test failed!'
echomsg ' string=' . string(a:string) . ' delim=' . string(a:delim)
echomsg ' Returned=' . string(result)
echomsg ' Expected=' . string(a:expected)
endif
endfunction
function! tabular#SplitDelimUnitTest()
let assignment = '[|&+*/%<>=!~-]\@<!\([<>!=]=\|=\~\)\@![|&+*/%<>=!~-]*='
let two_spaces = ' '
let ternary_operator = '^.\{-}\zs?\|:'
let cpp_io = '<<\|>>'
let pascal_assign = ':='
let trailing_c_comments = '\/\*\|\*\/\|\/\/'
call s:SplitDelimTest('a+=b', assignment, ['a', '+=', 'b'])
call s:SplitDelimTest('a-=b', assignment, ['a', '-=', 'b'])
call s:SplitDelimTest('a!=b', assignment, ['a!=b'])
call s:SplitDelimTest('a==b', assignment, ['a==b'])
call s:SplitDelimTest('a&=b', assignment, ['a', '&=', 'b'])
call s:SplitDelimTest('a|=b', assignment, ['a', '|=', 'b'])
call s:SplitDelimTest('a=b=c', assignment, ['a', '=', 'b', '=', 'c'])
call s:SplitDelimTest('a b c', two_spaces, ['a', ' ', 'b', ' ', 'c'])
call s:SplitDelimTest('a b c', two_spaces, ['a b', ' ', ' c'])
call s:SplitDelimTest('ab c', two_spaces, ['ab', ' ', '', ' ', 'c'])
call s:SplitDelimTest('a?b:c', ternary_operator, ['a', '?', 'b', ':', 'c'])
call s:SplitDelimTest('a<<b<<c', cpp_io, ['a', '<<', 'b', '<<', 'c'])
call s:SplitDelimTest('a:=b=c', pascal_assign, ['a', ':=', 'b=c'])
call s:SplitDelimTest('x//foo', trailing_c_comments, ['x', '//', 'foo'])
call s:SplitDelimTest('x/*foo*/',trailing_c_comments, ['x', '/*', 'foo', '*/', ''])
call s:SplitDelimTest('#ab#cd#ef', '[^#]*', ['#', 'ab', '#', 'cd', '#', 'ef', ''])
call s:SplitDelimTest('#ab#cd#ef', '#\zs', ['#', '', 'ab#', '', 'cd#', '', 'ef'])
endfunction
" Stupid vimscript crap, part 2 {{{1
let &cpo = s:savecpo
unlet s:savecpo
" vim:set sw=2 sts=2 fdm=marker:

View File

@ -0,0 +1,260 @@
*Tabular.txt* Configurable, flexible, intuitive text aligning
*tabular* *tabular.vim*
#|#|#|#|#| #| #| ~
#| #|#|#| #|#|#| #| #| #| #|#|#| #| #|#| ~
#| #| #| #| #| #| #| #| #| #| #|#| ~
#| #| #| #| #| #| #| #| #| #| #| ~
#| #|#|#| #|#|#| #|#|#| #| #|#|#| #| ~
For Vim version 7.0 or newer
By Matt Wozniski
mjw@drexel.edu
Reference Manual ~
*tabular-toc*
1. Description |tabular-intro|
2. Walkthrough |tabular-walkthrough|
3. Scripting |tabular-scripting|
The functionality mentioned here is a plugin, see |add-plugin|.
You can avoid loading this plugin by setting the "Tabular_loaded" global
variable in your |vimrc| file: >
:let g:tabular_loaded = 1
==============================================================================
1. Description *tabular-intro*
Sometimes, it's useful to line up text. Naturally, it's nicer to have the
computer do this for you, since aligning things by hand quickly becomes
unpleasant. While there are other plugins for aligning text, the ones I've
tried are either impossibly difficult to understand and use, or too simplistic
to handle complicated tasks. This plugin aims to make the easy things easy
and the hard things possible, without providing an unnecessarily obtuse
interface. It's still a work in progress, and criticisms are welcome.
==============================================================================
2. Walkthrough *tabular-walkthrough* *:Tabularize*
Tabular's commands are based largely on regular expressions. The basic
technique used by Tabular is taking some regex to match field delimiters,
splitting the input lines at those delimiters, trimming unnecessary spaces
from the non-delimiter parts, padding the non-delimiter parts of the lines
with spaces to make them the same length, and joining things back together
again.
For instance, consider starting with the following lines:
>
Some short phrase,some other phrase
A much longer phrase here,and another long phrase
<
Let's say we want to line these lines up at the commas. We can tell
Tabularize to do this by passing a pattern matching , to the Tabularize
command:
>
:Tabularize /,
Some short phrase , some other phrase
A much longer phrase here , and another long phrase
<
I encourage you to try copying those lines to another buffer and trying to
call :Tabularize. You'll want to take notice of two things quickly: First,
instead of requiring a range, Tabularize tries to figure out what you want to
happen. Since it knows that you want to act on lines matching a comma, it
will look upwards and downwards for lines around the current line that match a
comma, and consider all contiguous lines matching the pattern to be the range
to be acted upon. You can always override this by specifying a range, though.
The second thing you should notice is that you'll almost certainly be able to
abbreviate :Tabularize to :Tab - using this form in mappings and scripts is
discouraged as it will make conflicts with other scripts more likely, but for
interactive use it's a nice timesaver. Another convenience feature is that
running :Tabularize without providing a new pattern will cause it to reuse the
last pattern it was called with.
So, anyway, now the commas line up. Splitting the lines on commas, Tabular
realized that 'Some short phrase' would need to be padded with spaces to match
the length of 'A much longer phrase here', and it did that before joining the
lines back together. You'll also notice that, in addition to the spaces
inserting for padding, extra spaces were inserted between fields. That's
because by default, Tabular prints things left-aligned with one space between
fields. If you wanted to print things right-aligned with no spaces between
fields, you would provide a different format to the Tabularize command:
>
:Tabularize /,/r0
Some short phrase, some other phrase
A much longer phrase here,and another long phrase
<
A format specifier is either l, r, or c, followed by one or more digits. If
the letter is l, the field will be left aligned, similarly for r and right
aligning and c and center aligning. The number following the letter is the
number of spaces padding to insert before the start of the next field.
Multiple format specifiers can be added to the same command - each field will
be printed with the next format specifier in the list; when they all have been
used the first will be used again, and so on. So, the last command right
aligned every field, then inserted 0 spaces of padding before the next field.
What if we wanted to right align the text before the comma, and left align the
text after the comma? The command would look like this:
>
:Tabularize /,/r1c1l0
Some short phrase , some other phrase
A much longer phrase here , and another long phrase
<
That command would be read as "Align the matching text, splitting fields on
commas. Print everything before the first comma right aligned, then 1 space,
then the comma center aligned, then 1 space, then everything after the comma
left aligned." Notice that the alignment of the field the comma is in is
irrelevant - since it's only 1 cell wide, it looks the same whether it's right,
left, or center aligned. Also notice that the 0 padding spaces specified for
the 3rd field are unused - but they would be used if there were enough fields
to require looping through the fields again. For instance:
>
abc,def,ghi
a,b
a,b,c
:Tabularize /,/r1c1l0
abc , def, ghi
a , b
a , b , c
<
Notice that now, the format pattern has been reused; field 4 (the second comma)
is right aligned, field 5 is center aligned. No spaces were inserted between
the 3rd field (containing "def") and the 4th field (the second comma) because
the format specified 'l0'.
But, what if you only wanted to act on the first comma on the line, rather than
all of the commas on the line? Let's say we want everything before the first
comma right aligned, then the comma, then everything after the comma left
aligned:
>
abc,def,ghi
a,b
a,b,c
:Tabularize /^[^,]*\zs,/r0c0l0
abc,def,ghi
a,b
a,b,c
<
Here, we used a Vim regex that would only match the first comma on the line.
It matches the beginning of the line, followed by all the non-comma characters
up to the first comma, and then forgets about what it matched so far and
pretends that the match starts exactly at the comma.
But, now that this command does exactly what we want it to, it's become pretty
unwieldy. It would be unpleasant to need to type that more than once or
twice. The solution is to assign a name to it.
>
:AddTabularPattern first_comma /^[^,]*\zs,/r0c0l0
<
Now, typing ":Tabularize first_comma" will do the same thing as typing the
whole pattern out each time. Of course this is more useful if you store the
name in a file to be used later.
NOTE: In order to make these new commands available every time vim starts,
you'll need to put those new commands into a .vim file in a plugin directory
somewhere in your 'runtimepath'. In order to make sure that Tabular.vim has
already been loaded before your file tries to use :AddTabularPattern or
:AddTabularPipeline, the new file should be installed in an after/plugin
directory in 'runtimepath'. In general, it will be safe to find out where the
TabularMaps.vim plugin was installed, and place other files extending
Tabular.vim in the same directory as TabularMaps.vim. For more information,
and some suggested best practices, check out the |tabular-scripting| section.
Lastly, we'll approach the case where tabular cannot achieve your desired goal
just by splitting lines apart, trimming whitespace, padding with whitespace,
and rejoining the lines. As an example, consider the multiple_spaces command
from TabularMaps.vim. The goal is to split using two or more spaces as a
field delimiter, and join fields back together, properly lined up, with only
two spaces between the end of each field and the beginning of the next.
Unfortunately, Tabular can't do this with only the commands we know so far:
>
:Tabularize / /
<
The above function won't work, because it will consider "a b" as 5 fields
delimited by two pairs of 2 spaces ( 'a', ' ', '', ' ', 'b' ) instead of as
3 fields delimited by one set of 2 or more spaces ( 'a', ' ', 'b' ).
>
:Tabularize / \+/
<
The above function won't work either, because it will leave the delimiter as 4
spaces when used against "a b", meaning that we would fail at our goal of
collapsing everything down to two spaces between fields. So, we need a new
command to get around this:
>
:AddTabularPipeline multiple_spaces / \{2,}/
\ map(a:lines, "substitute(v:val, ' \{2,}', ' ', 'g')")
\ | tabular#TabularizeStrings(a:lines, ' ', 'l0')
<
Yeah. I know it looks complicated. Bear with me. I probably will try to add
in some shortcuts for this syntax, but this verbose will be guaranteed to
always work.
You should already recognize the name being assigned. The next thing to
happen is / \{2,}/ which is a pattern specifying which lines should
automatically be included in the range when no range is given. Without this,
there would be no pattern to use for extending the range. Everything after
that is a | separated list of expressions to be evaluated. In the context in
which they will be evaluated, a:lines will be set to a List of Strings
containing the text of the lines being filtered as they procede through the
pipeline you've set up. The \ at the start of the lines are just vim's line
continuation marker; you needn't worry much about them. So, the first
expression in the pipeline transforms each line by replacing every instance of
2 or more spaces with exactly two spaces. The second command in the pipeline
performs the equivalent of ":Tabularize / /l0"; the only difference is that
it is operating on a List of Strings rather than text in the buffer. At the
end of the pipeline, the Strings in the modified a:lines (or the return value
of the last expression in the pipeline, if it returns a List) will replace the
chosen range.
==============================================================================
3. Extending *tabular-scripting*
As mentioned above, the most important consideration when extending Tabular
with new maps or commands is that your plugin must be loaded after Tabular.vim
has finished loading, and only if Tabular.vim has loaded successfully. The
easiest approach to making sure it loads after Tabular.vim is simply putting
the new file (we'll call it "tabular_extra.vim" as an example) into an
"after/plugin/" directory in 'runtimepath', for instance:
>
~/.vim/after/plugin/tabular_extra.vim
<
The default set of mappings, found in "TabularMaps.vim", is installed in
the after/plugin/ subdirectory of whatever directory Tabular was installed to.
The other important consideration is making sure that your commands are only
called if Tabular.vim was actually loaded. The easiest way to do this is by
checking for the existence of the :Tabularize command at the start of your
plugin. A short example plugin would look like this:
>
" after/plugin/my_tabular_commands.vim
" Provides extra :Tabularize commands
if !exists(':Tabularize')
finish " Give up here; the Tabular plugin musn't have been loaded
endif
" Make line wrapping possible by resetting the 'cpo' option, first saving it
let s:save_cpo = &cpo
set cpo&vim
AddTabularPattern! asterisk /*/l1
AddTabularPipeline! remove_leading_spaces /^ /
\ map(a:lines, "substitute(v:val, '^ *', '', '')")
" Restore the saved value of 'cpo'
let &cpo = s:save_cpo
unlet s:save_cpo
<
==============================================================================
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:

View File

@ -0,0 +1,350 @@
" Tabular: Align columnar data using regex-designated column boundaries
" Maintainer: Matthew Wozniski (godlygeek@gmail.com)
" Date: Thu, 03 May 2012 20:49:32 -0400
" Version: 1.0
"
" Long Description:
" Sometimes, it's useful to line up text. Naturally, it's nicer to have the
" computer do this for you, since aligning things by hand quickly becomes
" unpleasant. While there are other plugins for aligning text, the ones I've
" tried are either impossibly difficult to understand and use, or too simplistic
" to handle complicated tasks. This plugin aims to make the easy things easy
" and the hard things possible, without providing an unnecessarily obtuse
" interface. It's still a work in progress, and criticisms are welcome.
"
" License:
" Copyright (c) 2012, Matthew J. Wozniski
" All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
" * Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
" * Redistributions in binary form must reproduce the above copyright
" notice, this list of conditions and the following disclaimer in the
" documentation and/or other materials provided with the distribution.
" * The names of the contributors may not be used to endorse or promote
" products derived from this software without specific prior written
" permission.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS
" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
" NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
" Abort if running in vi-compatible mode or the user doesn't want us.
if &cp || exists('g:tabular_loaded')
if &cp && &verbose
echo "Not loading Tabular in compatible mode."
endif
finish
endif
let g:tabular_loaded = 1
" Stupid vimscript crap {{{1
let s:savecpo = &cpo
set cpo&vim
" Private Things {{{1
" Dictionary of command name to command
let s:TabularCommands = {}
" Generate tab completion list for :Tabularize {{{2
" Return a list of commands that match the command line typed so far.
" NOTE: Tries to handle commands with spaces in the name, but Vim doesn't seem
" to handle that terribly well... maybe I should give up on that.
function! s:CompleteTabularizeCommand(argstart, cmdline, cursorpos)
let names = keys(s:TabularCommands)
if exists("b:TabularCommands")
let names += keys(b:TabularCommands)
endif
let cmdstart = substitute(a:cmdline, '^\s*\S\+\s*', '', '')
return filter(names, 'v:val =~# ''^\V'' . escape(cmdstart, ''\'')')
endfunction
" Choose the proper command map from the given command line {{{2
" Returns [ command map, command line with leading <buffer> removed ]
function! s:ChooseCommandMap(commandline)
let map = s:TabularCommands
let cmd = a:commandline
if cmd =~# '^<buffer>\s\+'
if !exists('b:TabularCommands')
let b:TabularCommands = {}
endif
let map = b:TabularCommands
let cmd = substitute(cmd, '^<buffer>\s\+', '', '')
endif
return [ map, cmd ]
endfunction
" Parse '/pattern/format' into separate pattern and format parts. {{{2
" If parsing fails, return [ '', '' ]
function! s:ParsePattern(string)
if a:string[0] != '/'
return ['','']
endif
let pat = '\\\@<!\%(\\\\\)\{-}\zs/' . tabular#ElementFormatPattern() . '*$'
let format = matchstr(a:string[1:-1], pat)
if !empty(format)
let format = format[1 : -1]
let pattern = a:string[1 : -len(format) - 2]
else
let pattern = a:string[1 : -1]
endif
return [pattern, format]
endfunction
" Split apart a list of | separated expressions. {{{2
function! s:SplitCommands(string)
if a:string =~ '^\s*$'
return []
endif
let end = match(a:string, "[\"'|]")
" Loop until we find a delimiting | or end-of-string
while end != -1 && (a:string[end] != '|' || a:string[end+1] == '|')
if a:string[end] == "'"
let end = match(a:string, "'", end+1) + 1
if end == 0
throw "No matching end single quote"
endif
elseif a:string[end] == '"'
" Find a " preceded by an even number of \ (or 0)
let pattern = '\%(\\\@<!\%(\\\\\)*\)\@<="'
let end = matchend(a:string, pattern, end+1) + 1
if end == 0
throw "No matching end double quote"
endif
else " Found ||
let end += 2
endif
let end = match(a:string, "[\"'|]", end)
endwhile
if end == 0 || a:string[0 : end - (end > 0)] =~ '^\s*$'
throw "Empty element"
endif
if end == -1
let rv = [ a:string ]
else
let rv = [ a:string[0 : end-1] ] + s:SplitCommands(a:string[end+1 : -1])
endif
return rv
endfunction
" Public Things {{{1
" Command associating a command name with a simple pattern command {{{2
" AddTabularPattern[!] [<buffer>] name /pattern[/format]
"
" If <buffer> is provided, the command will only be available in the current
" buffer, and will be used instead of any global command with the same name.
"
" If a command with the same name and scope already exists, it is an error,
" unless the ! is provided, in which case the existing command will be
" replaced.
"
" pattern is a regex describing the delimiter to be used.
"
" format describes the format pattern to be used. The default will be used if
" none is provided.
com! -nargs=+ -bang AddTabularPattern
\ call AddTabularPattern(<q-args>, <bang>0)
function! AddTabularPattern(command, force)
try
let [ commandmap, rest ] = s:ChooseCommandMap(a:command)
let name = matchstr(rest, '.\{-}\ze\s*/')
let pattern = substitute(rest, '.\{-}\s*\ze/', '', '')
let [ pattern, format ] = s:ParsePattern(pattern)
if empty(name) || empty(pattern)
throw "Invalid arguments!"
endif
if !a:force && has_key(commandmap, name)
throw string(name) . " is already defined, use ! to overwrite."
endif
let command = "tabular#TabularizeStrings(a:lines, " . string(pattern)
if !empty(format)
let command .= ", " . string(format)
endif
let command .= ")"
let commandmap[name] = { 'pattern' : pattern, 'commands' : [ command ] }
catch
echohl ErrorMsg
echomsg "AddTabularPattern: " . v:exception
echohl None
endtry
endfunction
" Command associating a command name with a pipeline of functions {{{2
" AddTabularPipeline[!] [<buffer>] name /pattern/ func [ | func2 [ | func3 ] ]
"
" If <buffer> is provided, the command will only be available in the current
" buffer, and will be used instead of any global command with the same name.
"
" If a command with the same name and scope already exists, it is an error,
" unless the ! is provided, in which case the existing command will be
" replaced.
"
" pattern is a regex that will be used to determine which lines will be
" filtered. If the cursor line doesn't match the pattern, using the command
" will be a no-op, otherwise the cursor and all contiguous lines matching the
" pattern will be filtered.
"
" Each 'func' argument represents a function to be called. This function
" will have access to a:lines, a List containing one String per line being
" filtered.
com! -nargs=+ -bang AddTabularPipeline
\ call AddTabularPipeline(<q-args>, <bang>0)
function! AddTabularPipeline(command, force)
try
let [ commandmap, rest ] = s:ChooseCommandMap(a:command)
let name = matchstr(rest, '.\{-}\ze\s*/')
let pattern = substitute(rest, '.\{-}\s*\ze/', '', '')
let commands = matchstr(pattern, '^/.\{-}\\\@<!\%(\\\\\)\{-}/\zs.*')
let pattern = matchstr(pattern, '/\zs.\{-}\\\@<!\%(\\\\\)\{-}\ze/')
if empty(name) || empty(pattern)
throw "Invalid arguments!"
endif
if !a:force && has_key(commandmap, name)
throw string(name) . " is already defined, use ! to overwrite."
endif
let commandlist = s:SplitCommands(commands)
if empty(commandlist)
throw "Must provide a list of functions!"
endif
let commandmap[name] = { 'pattern' : pattern, 'commands' : commandlist }
catch
echohl ErrorMsg
echomsg "AddTabularPipeline: " . v:exception
echohl None
endtry
endfunction
" Tabularize /pattern[/format] {{{2
" Tabularize name
"
" Align text, either using the given pattern, or the command associated with
" the given name.
com! -nargs=* -range -complete=customlist,<SID>CompleteTabularizeCommand
\ Tabularize <line1>,<line2>call Tabularize(<q-args>)
function! Tabularize(command, ...) range
let piperange_opt = {}
if a:0
let piperange_opt = a:1
endif
if empty(a:command)
if !exists("s:last_tabularize_command")
echohl ErrorMsg
echomsg "Tabularize hasn't been called yet; no pattern/command to reuse!"
echohl None
return
endif
else
let s:last_tabularize_command = a:command
endif
let command = s:last_tabularize_command
let range = a:firstline . ',' . a:lastline
try
let [ pattern, format ] = s:ParsePattern(command)
if !empty(pattern)
let cmd = "tabular#TabularizeStrings(a:lines, " . string(pattern)
if !empty(format)
let cmd .= "," . string(format)
endif
let cmd .= ")"
exe range . 'call tabular#PipeRangeWithOptions(pattern, [ cmd ], '
\ . 'piperange_opt)'
else
if exists('b:TabularCommands') && has_key(b:TabularCommands, command)
let usercmd = b:TabularCommands[command]
elseif has_key(s:TabularCommands, command)
let usercmd = s:TabularCommands[command]
else
throw "Unrecognized command " . string(command)
endif
exe range . 'call tabular#PipeRangeWithOptions(usercmd["pattern"], '
\ . 'usercmd["commands"], piperange_opt)'
endif
catch
echohl ErrorMsg
echomsg "Tabularize: " . v:exception
echohl None
return
endtry
endfunction
function! TabularizeHasPattern()
return exists("s:last_tabularize_command")
endfunction
" GTabularize /pattern[/format] {{{2
" GTabularize name
"
" Align text on only matching lines, either using the given pattern, or the
" command associated with the given name. Mnemonically, this is similar to
" the :global command, which takes some action on all rows matching a pattern
" in a range. This command is different from normal :Tabularize in 3 ways:
" 1) If a line in the range does not match the pattern, it will be left
" unchanged, and not in any way affect the outcome of other lines in the
" range (at least, normally - but Pipelines can and will still look at
" non-matching rows unless they are specifically written to be aware of
" tabular#DoGTabularize() and handle it appropriately).
" 2) No automatic range determination - :Tabularize automatically expands
" a single-line range (or a call with no range) to include all adjacent
" matching lines. That behavior does not make sense for this command.
" 3) If called without a range, it will act on all lines in the buffer (like
" :global) rather than only a single line
com! -nargs=* -range=% -complete=customlist,<SID>CompleteTabularizeCommand
\ GTabularize <line1>,<line2>
\ call Tabularize(<q-args>, { 'mode': 'GTabularize' } )
" Stupid vimscript crap, part 2 {{{1
let &cpo = s:savecpo
unlet s:savecpo
" vim:set sw=2 sts=2 fdm=marker:

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Marko Nimac
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,44 @@
# traces.vim
## Overview
This plugin highlights patterns and ranges for Ex commands in Command-line mode.
It also provides live preview for `:substitute`.
## Requirements
### Vim 8.1
or
### Neovim 0.2.3
## Feature comparison
**Note**: some of the features provided by this plugin are already present in Vim/Neovim.
| | traces.vim | Vim | Neovim |
|--------------------------------------------------------------| :----------: | :---------------: | :---------------: |
| `:substitute` preview | ✓ | | ✓ |
| pattern preview for `:substitute` | ✓ | ✓<sup>[1]</sup> | ✓ |
| pattern preview for `:global`, `:vglobal`, `:sort` | ✓ | ✓<sup>[1]</sup> | ✓<sup>[2]</sup> |
| pattern preview for `:vimgrep` | | ✓<sup>[1]</sup> | ✓<sup>[2]</sup> |
| off-screen results window for `:substitute` | ✓ | | ✓ |
| off-screen results window for `:global`, `:vglobal`, `:sort` | ✓ | | |
| range preview | ✓ | | |
[1] added by patch [v8.1.0271](https://github.com/vim/vim/commit/b0acacd767a2b0618a7f3c08087708f4329580d0)
[2] available in Neovim [0.5.0](https://github.com/neovim/neovim/pull/12721)
## Example
![example](img/traces_example.gif?raw=true)
## Installation
Use plugin/runtimepath manager of choice or install manually with the following command:
### Linux
`git clone --depth 1 https://github.com/markonm/traces.vim ~/.vim/pack/plugins/start/traces.vim`
### Windows
`git clone --depth 1 https://github.com/markonm/traces.vim %HOMEPATH%/vimfiles/pack/plugins/start/traces.vim`
## Inspiration
- [vim-over](https://github.com/osyo-manga/vim-over)
- [incsearch.vim](https://github.com/haya14busa/incsearch.vim)
- [inccommand](https://neovim.io/doc/user/options.html#'inccommand')
- [nvim-incnormal](https://github.com/bfredl/nvim-incnormal)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,216 @@
*traces.txt* Range, pattern and substitute preview for Vim
Version 1.1.0
CONTENTS *traces-contents*
1. Introduction |traces-introduction|
2. Requirements |traces-requirements|
3. Options |traces-options|
|g:traces_enabled|
|g:traces_preserve_view_state|
|g:traces_substitute_preview|
|g:traces_skip_modifiers|
|g:traces_num_range_preview|
|g:traces_timeout|
|g:traces_search_timeout|
|g:traces_preview_window|
|g:traces_abolish_integration|
|g:traces_normal_preview|
4. Highlights |traces-highlights|
|hl-TracesSearch|
|hl-TracesReplace|
5. Bugs |traces-bugs|
6. Changelog |traces-changelog|
==============================================================================
INTRODUCTION *traces-introduction*
This plugin highlights |pattern|s and |:range|s for Ex commands in
Command-line mode.
Ranges composed of at least one pattern or mark specifier will be highlighted
immediately. Ranges that do not include any pattern or mark specifier will
not be highlighted because they cannot be uniquely identified as ranges
related to buffer lines (see |:command-addr|).
To force immediate preview for ranges composed entirely of absolute specifiers
({number}, ., $, %), first enter and delete '/' or some other pattern or mark
specifier. Also see |g:traces_num_range_preview|.
Patterns for the following Ex commands will be highlighted immediately as
typed:
|:substitute|
|:smagic|
|:snomagic|
|:global|
|:vglobal|
|:sort|
Live preview is implemented for the following Ex commands:
|:substitute|
|:smagic|
|:snomagic|
|:normal|
==============================================================================
REQUIREMENTS *traces-requirements*
Vim 8.1
or
Neovim 0.2.3
==============================================================================
OPTIONS *traces-options*
*g:traces_enabled*
g:traces_enabled boolean (default 1)
If value is 0, this plugin will be disabled and no
highlighting will be done.
*g:traces_preserve_view_state*
g:traces_preserve_view_state boolean (default 0)
If value is 1, view position will not be changed when
highlighting ranges or patterns outside initial view position.
*g:traces_substitute_preview*
g:traces_substitute_preview boolean (default 1)
If value is 1, |:substitute|, |:smagic| and |:snomagic| will
be previewed.
*g:traces_skip_modifiers*
g:traces_skip_modifiers boolean (default 1)
If value is 1, |cdo|, |cfdo|, |ldo|, |lfdo|, |bufdo|, |tabdo|,
|argdo| and |windo| will be ignored when processing command
line.
*g:traces_num_range_preview*
g:traces_num_range_preview boolean (default 0)
If value is 1, numerical ranges :N, and :N; will be
highlighted immediately.
Highlighted: >
:10,
:10;15
<
Not highlighted: >
:10
<
*g:traces_timeout*
g:traces_timeout number (default 1000)
If preview is slower than the timeout (in milliseconds), it
gets disabled until Command-line mode is entered again. Time
spent saving undo history is ignored. Cannot be lower than
200.
*g:traces_search_timeout*
g:traces_search_timeout number (default 500)
If searching is slower than the timeout (in milliseconds), it
gets disabled until new character is passed to Command-line.
Cannot be higher than |g:traces_timeout|.
*g:traces_preview_window*
g:traces_preview_window string (default empty)
Window used to show off-screen matches.
Set the option to Ex command which will be used to open a new
window. Use a combination of Ex commands |:new| or |:vnew| and
command modifiers |vertical|, |leftabove|, |aboveleft|,
|rightbelow|, |belowright|, |topleft| and |botright|. Prepend
"new" or "vnew" with a number to specify height or width of the
window. Preview window is opened only when selected range
exceeds visible viewport.
Example: >
let g:traces_preview_window = "botright 10new"
let g:traces_preview_window = "vertical botright new"
let g:traces_preview_window = "topleft 15new"
<
As a fallback the string is evaluated with |eval()| which
permits the following:
Example: >
" If window width is greater than 160 columns, open vertical
" window or else open horizontal window
let g:traces_preview_window =
\ "winwidth('%') > 160 ? 'bot vnew' : 'bot 10new'"
<
*g:traces_abolish_integration*
g:traces_abolish_integration boolean (default 0)
If value is 1, |:Subvert| from abolish.vim will be previewed.
*g:traces_normal_preview*
g:traces_normal_preview boolean (default 0)
WARNING: experimental, unstable
The following actions performed during the preview might break
the preview or lose the undo history.
- opening, closing or switching buffers or windows
If value is 1, |:normal| will be previewed.
Requires patch 8.2.2961 on Vim.
==============================================================================
HIGHLIGHTS *traces-highlights*
*hl-TracesSearch*
TracesSearch Search pattern highlighting. Links to |hl-Search| by default.
*hl-TracesReplace*
TracesReplace Substitute string highlighting. Links to |hl-TracesSearch| by
default.
Example: >
highlight link TracesSearch Cursor
highlight link TracesReplace DiffAdd
<
==============================================================================
BUGS *traces-bugs*
- highlighting is disabled for |:terminal| windows because of redrawing
issues
- If you have any problems or suggestions, please let me know at:
https://github.com/markonm/traces.vim
==============================================================================
CHANGELOG *traces-changelog*
1.1.0 January 21, 2019 *traces-changelog-1.1.0*
- New options
- |g:traces_num_range_preview|
- |g:traces_enabled|
- Pattern preview for |:sort|
- Various bugs fixed
1.0.0 April 30, 2018 *traces-changelog-1.0.0*
- Substitute preview
- Use |CmdlineChanged| event
- New options
- |g:traces_substitute_preview|
- |g:traces_skip_modifiers|
- Deprecated options
- |g:traces_whole_file_range|
- New highlight group |hl-TracesSearch|
- Various bugs fixed
0.1.0 December 21, 2017 *traces-changelog-0.1.0*
- Increased Vim/Neovim requirements
- Use |CmdlineEnter| and |CmdlineLeave| events
- Disable |hlsearch| when highlighting patterns
- Highlight all windows that contain current buffer
- New options
- |g:traces_whole_file_range|
- |g:traces_preserve_view_state|
- Various bugs fixed
0.0.0 September 18, 2017 *traces-changelog-0.0.0*
- Initial version.
==============================================================================
vim:tw=78:ts=8:ft=help:norl:fen:fdl=0:fdm=marker:

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

View File

@ -0,0 +1,114 @@
if !exists('##CmdlineEnter') || exists('g:loaded_traces_plugin') || !has('timers') || &cp
finish
endif
let g:loaded_traces_plugin = 1
let s:cpo_save = &cpo
set cpo&vim
let g:traces_enabled = get(g:, 'traces_enabled', 1)
let g:traces_preserve_view_state = get(g:, 'traces_preserve_view_state')
let g:traces_substitute_preview = get(g:, 'traces_substitute_preview', 1)
let g:traces_normal_preview = get(g:, 'traces_normal_preview', 0)
let g:traces_num_range_preview = get(g:, 'traces_num_range_preview', 0)
let g:traces_skip_modifiers = get(g:, 'traces_skip_modifiers', 1)
let g:traces_preview_window = get(g:, 'traces_preview_window', '')
let g:traces_abolish_integration = get(g:, 'traces_abolish_integration', 0)
let s:view = {}
function! s:track_cmdl(...) abort
let current_cmdl = getcmdline()
if get(s:, 'previous_cmdl', '') !=# current_cmdl
let s:previous_cmdl = current_cmdl
call traces#init(current_cmdl, s:view)
endif
endfunction
function! s:cmdline_changed() abort
if exists('s:start_init_timer')
call timer_stop(s:start_init_timer)
endif
let s:start_init_timer = timer_start(1, {_-> traces#init(getcmdline(), s:view)})
endfunction
function! s:create_cmdl_changed_au(...) abort
augroup traces_augroup_cmdline_changed
autocmd!
autocmd CmdlineChanged : call s:cmdline_changed()
augroup END
" necessary when entering command line that has already been populated with
" text from mappings
call s:cmdline_changed()
endfunction
function! s:t_start() abort
if !g:traces_enabled || mode(1) =~# '^c.' || &buftype ==# 'terminal'
return
endif
if exists('##CmdlineChanged')
let s:track_cmdl_timer = timer_start(30,function('s:create_cmdl_changed_au'))
else
let s:track_cmdl_timer = timer_start(30,function('s:track_cmdl'),{'repeat':-1})
endif
endfunction
function! s:t_stop() abort
if exists('s:previous_cmdl')
unlet s:previous_cmdl
endif
if exists('s:track_cmdl_timer')
call timer_stop(s:track_cmdl_timer)
unlet s:track_cmdl_timer
endif
if exists('s:start_init_timer')
call timer_stop(s:start_init_timer)
unlet s:start_init_timer
endif
augroup traces_augroup_cmdline_changed
autocmd!
augroup END
endfunction
silent! cnoremap <unique> <expr> <c-r><c-w> traces#check_b() ? traces#get_cword() : "\<c-r>\<c-w>"
silent! cnoremap <unique> <expr> <c-r><c-a> traces#check_b() ? traces#get_cWORD() : "\<c-r>\<c-a>"
silent! cnoremap <unique> <expr> <c-r><c-f> traces#check_b() ? traces#get_cfile() : "\<c-r>\<c-f>"
silent! cnoremap <unique> <expr> <c-r><c-p> traces#check_b() ? traces#get_pfile() : "\<c-r>\<c-p>"
silent! cnoremap <unique> <expr> <c-r><c-r><c-w> traces#check_b() ? "\<c-r>\<c-r>=traces#get_cword()\<cr>" : "\<c-r>\<c-r>\<c-w>"
silent! cnoremap <unique> <expr> <c-r><c-r><c-a> traces#check_b() ? "\<c-r>\<c-r>=traces#get_cWORD()\<cr>" : "\<c-r>\<c-r>\<c-a>"
silent! cnoremap <unique> <expr> <c-r><c-r><c-f> traces#check_b() ? "\<c-r>\<c-r>=traces#get_cfile()\<cr>" : "\<c-r>\<c-r>\<c-f>"
silent! cnoremap <unique> <expr> <c-r><c-r><c-p> traces#check_b() ? "\<c-r>\<c-r>=traces#get_pfile()\<cr>" : "\<c-r>\<c-r>\<c-p>"
silent! cnoremap <unique> <expr> <c-r><c-o><c-w> traces#check_b() ? "\<c-r>\<c-r>=traces#get_cword()\<cr>" : "\<c-r>\<c-o>\<c-w>"
silent! cnoremap <unique> <expr> <c-r><c-o><c-a> traces#check_b() ? "\<c-r>\<c-r>=traces#get_cWORD()\<cr>" : "\<c-r>\<c-o>\<c-a>"
silent! cnoremap <unique> <expr> <c-r><c-o><c-f> traces#check_b() ? "\<c-r>\<c-r>=traces#get_cfile()\<cr>" : "\<c-r>\<c-o>\<c-f>"
silent! cnoremap <unique> <expr> <c-r><c-o><c-p> traces#check_b() ? "\<c-r>\<c-r>=traces#get_pfile()\<cr>" : "\<c-r>\<c-o>\<c-p>"
augroup traces_augroup
autocmd!
autocmd CmdlineEnter,CmdwinLeave : call s:t_start()
autocmd CmdlineLeave,CmdwinEnter : call s:t_stop()
autocmd CmdlineLeave : if mode(1) is 'c' | call traces#cmdl_leave() | endif
" s:view is used to restore correct view when entering command line from
" visual mode
autocmd CursorMoved * let s:view = extend(winsaveview(), {'mode': mode()})
" 'incsearch' is not compatible with traces.vim, turn it off for : command-line
" https://github.com/vim/vim/commit/b0acacd767a2b0618a7f3c08087708f4329580d0
" https://github.com/neovim/neovim/pull/12721/commits/e8a8b9ed08405c830a049c4e43910c5ce9cdb669
autocmd CmdlineEnter,CmdwinLeave : let s:incsearch = &incsearch
\| noautocmd let &incsearch = 0
autocmd CmdlineLeave,CmdwinEnter : if exists('s:incsearch') | noautocmd let &incsearch = s:incsearch | endif
if exists('+inccommand')
" 'inccommand' is not compatible with traces.vim, turn it off
" https://github.com/neovim/neovim/commit/7215d356949bf07960cc3a3d8b83772635d729d0
autocmd CmdlineEnter : noautocmd let &inccommand = ''
endif
augroup END
highlight default link TracesSearch Search
highlight default link TracesReplace TracesSearch
highlight default link TracesCursor TracesSearch
let &cpo = s:cpo_save
unlet s:cpo_save

View File

@ -0,0 +1,764 @@
Execute (Setup):
Save g:traces_preserve_view_state, g:traces_substitute_preview,
\ &listchars, &hlsearch, &cursorline, &cursorline, &encoding,
\ &winminwidth, &winminheight
let g:traces_preserve_view_state = 0
let g:traces_substitute_preview = 1
let g:traces_normal_preview = 1
let g:traces_skip_modifiers = 1
let g:traces_num_range_preview = 0
let g:traces_preview_window = ''
let g:traces_abolish_integration = 0
function! Group(group) abort
let matches = filter(getmatches(), {idx, val -> val.group == a:group})
if !empty(matches)
return matches[0].pattern
endif
endfunction
let &listchars = 'eol:.'
set encoding=utf-8
After:
call traces#cmdl_leave()
Before:
let g:traces_preserve_view_state = 0
let g:traces_substitute_preview = 1
let g:traces_skip_modifiers = 1
let g:traces_num_range_preview = 0
call clearmatches()
#######################
# Test positioning #
#######################
Given (Ten lines):
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine
10 ten
11 foo/bar
12 foo?bar
13 \
14 four
Execute (Range):
14
call traces#init('/four', {})
Assert line('.') is 4
Execute (Range):
14
call traces#init('/four/', {})
Assert line('.') is 4
Execute (Range):
14
let @/= 'four'
call traces#init('\/', {})
Assert line('.') is 4
Execute (Range):
set nowrapscan
14
call traces#init('/four/-', {})
Assert line('.') is 14
set wrapscan
Execute (Range):
set nowrapscan
14
let @/= 'four'
call traces#init('\/-', {})
Assert line('.') is 14
set wrapscan
Execute (Range):
1
call traces#init('5;10', winsaveview())
Assert line('.') == 1
Execute (Range):
let g:traces_num_range_preview = 1
1
call traces#init('5;10', winsaveview())
Assert line('.') == 10
Execute (Range):
let g:traces_num_range_preview = 1
1
call traces#init('5;', winsaveview())
Assert line('.') == 5
Execute (Range):
let g:traces_num_range_preview = 1
1
call traces#init('5,', winsaveview())
Assert line('.') == 1
Execute (Range):
1
call traces#init('5,', winsaveview())
Assert line('.') == 1
Execute (Range):
1
call traces#init('5;', winsaveview())
Assert line('.') == 1
Execute (Range):
1
call traces#init('5', winsaveview())
Assert line('.') == 1
Execute (Range):
1
call traces#init('10;5g/', winsaveview())
Assert line('.') == 5
Execute (Range):
1
call traces#init('5;10g/', winsaveview())
Assert line('.') == 10
Execute (Range):
call traces#init('5;10s/.', {})
Assert line('.') == 5
Execute (Range):
call traces#init('5;10s?.', {})
Assert line('.') == 10
Execute (Range):
call traces#init('10;5s/.', {})
Assert line('.') == 5
Execute (Range):
call traces#init('10;5s?.', {})
Assert line('.') == 10
Execute (Range):
call traces#init('/three', {})
Assert line('.') == 3
Execute (Range):
/ten/
call traces#init('?two', {})
Assert line('.') == 2
Execute (Range):
call traces#init('/three/;/eight/', {})
Assert line('.') == 8
Execute (Range):
7
ma m
1
call traces#init('/three/;''m', {})
Assert line('.') == 7
Execute (Range):
call traces#init('/foo\/bar', {})
Assert line('.') == 11
Execute (Range):
call traces#init('/foo\/bar/foobar', {})
Assert line('.') == 11
Execute (Range):
call traces#init('/two/3', {})
Assert line('.') == 5
Execute (Range):
call traces#init('/foo?bar', {})
Assert line('.') == 12
Execute (Range):
call traces#init('?foo\?bar?', {})
Assert line('.') == 12
Execute (Range):
call traces#init('?foo\?bar', {})
Assert line('.') == 12
Execute (Range):
call traces#init('/ten/++', {})
Assert line('.') == 12
call traces#init('', {})
Assert line('.') == 1
Execute (Range):
call traces#init('/one/;11s/five', {})
Assert line('.') == 5
call traces#init('', {})
Assert line('.') == 1
Execute (Range):
call traces#init('/one/;11g/five', {})
Assert line('.') == 5
call traces#init('', {})
Assert line('.') == 1
# test g:traces_preserve_view_state = 1
Execute (Range):
let g:traces_preserve_view_state = 1
call traces#init('/ten/++', {})
Assert line('.') == 1
Execute (Range):
let g:traces_preserve_view_state = 1
call traces#init('/one/;11s/five', {})
Assert line('.') == 1
Execute (Range):
let g:traces_preserve_view_state = 1
call traces#init('/one/;11g/five', {})
Assert line('.') == 1
Execute (Range):
let g:traces_preserve_view_state = 1
call traces#init('g/five', {})
Assert line('.') == 1
Execute (Global, test invalid pattern):
6
call traces#init('g/bazbar', {})
Assert line('.') == 6
Execute (Substitute, test invalid pattern):
6
call traces#init('s/bazbar', {})
Assert line('.') == 6
Execute (Substitute, test invalid pattern):
6
call traces#init('%s/bazbar', {})
Assert line('.') == 6
Execute (Range, test invalid pattern):
6
call traces#init('/bazbar', {})
Assert line('.') == 6
Execute (Range, test invalid pattern):
6
call traces#init('?bazbar', {})
Assert line('.') == 6
Execute (Range, test invalid pattern):
6
call traces#init('?bazbar', {})
Assert line('.') == 6
Execute (Substitute, no range):
11
call traces#init('s/bar', {})
Assert line('.') == 11
Assert col('.') == 9
Given (Ten lines):
1 one
2 two
3 three
4 baz
5 five
6 six
7 seven
8 eight
9 nine
10 baz
11 foo/bar
12 foo?bar
13 \
14 four
Execute (Substitute with range):
6
call traces#init('3;11s/baz', {})
Assert line('.') == 4
Execute (Substitute with range):
6
call traces#init('3;11s?baz', {})
Assert line('.') == 10
Execute (Substitute with range):
6
call traces#init('%s/baz', {})
Assert line('.') == 10
Execute (Substitute with range):
6
call traces#init('%s?baz', {})
Assert line('.') == 4
Execute (Invalid substitute):
6
call traces#init('s/baz', {})
Assert line('.') == 6
#######################
# Test highlighting #
#######################
Given (Ten lines):
1 one
2 two
3 three
4 four
5 five
6 six
7 seven
8 eight
9 nine
10 ten
11 foo/bar
12 foo?bar
13 \
14 four
Execute (Sort):
call traces#init('%sort /\w\+/', {})
AssertEqual '\m\%>0l\%<15l\%(\m\w\+\m\)', Group('TracesSearch')
Execute (Global):
call traces#init('7,/four/g/foobar', {})
AssertEqual '\m\%>3l\%<8l\%(\mfoobar\m\)', Group('TracesSearch')
call traces#init('7,/four/g', {})
AssertEqual 0, Group('TracesSearch')
Execute (Range):
6
call traces#init('/./', {})
AssertEqual '\%>6l\%<8l\_.', Group('Visual')
call traces#init('/.//', {})
AssertEqual '\%>6l\%<8l\_.', Group('Visual')
Execute (Range):
6
call traces#init('?.?', {})
AssertEqual '\%>4l\%<6l\_.', Group('Visual')
call traces#init('?.??', {})
AssertEqual '\%>4l\%<6l\_.', Group('Visual')
Execute (Range):
6
call traces#init('/.', {})
AssertEqual '\%>6l\%<8l\_.', Group('Visual')
call traces#init('/', {})
Assert empty(getmatches())
Execute (Range):
6
call traces#init('?.', {})
AssertEqual '\%>4l\%<6l\_.', Group('Visual')
call traces#init('?', {})
Assert empty(getmatches())
Execute (Range):
6
call traces#init('/ten/;?four', {})
AssertEqual '\m\%>3l\%<5l\%(\mfour\m\)', Group('TracesSearch')
Execute (Range):
6
call traces#init('?.?;?.?;?', {})
AssertEqual '\%>3l\%<5l\_.', Group('Visual')
call traces#init('', {})
Assert empty(getmatches())
Execute (Range):
6
call traces#init('/./;/./;/', {})
AssertEqual '\%>7l\%<9l\_.', Group('Visual')
call traces#init('', {})
Assert empty(getmatches())
Execute (Range):
call traces#init('22;g', {})
AssertEqual 0, Group('Visual')
call traces#init('', {})
Assert empty(getmatches())
Execute (Range):
call traces#init(';+++s/', {})
AssertEqual '\%>0l\%<5l\_.', Group('Visual')
call traces#init('', {})
Assert empty(getmatches())
Execute (Range):
call traces#init('/one/;/eight/', {})
AssertEqual '\%>0l\%<9l\_.', Group('Visual')
call traces#init('', {})
Assert empty(getmatches())
Execute (Range):
call traces#init('1;/eight/', {})
AssertEqual '\%>0l\%<9l\_.', Group('Visual')
Execute (Range):
call traces#init(';/eight/', {})
AssertEqual '\%>0l\%<9l\_.', Group('Visual')
Execute (Range):
call traces#init(',/eight/', {})
AssertEqual '\%>0l\%<9l\_.', Group('Visual')
Execute (Range):
call traces#init(';/eight/;', {})
AssertEqual '\%>7l\%<9l\_.', Group('Visual')
Execute (Range):
call traces#init('3;/seven/', {})
AssertEqual '\%>2l\%<8l\_.', Group('Visual')
Execute (Range):
call traces#init('7;/four/', {})
AssertEqual '\%>6l\%<15l\_.', Group('Visual')
Execute (Range):
call traces#init('7,/four/', {})
AssertEqual '\%>3l\%<8l\_.', Group('Visual')
Execute (Range):
call traces#init('7,/four/s/foobar', {})
AssertEqual '\%>3l\%<8l\_.', Group('Visual')
AssertEqual '\m\%>3l\%<8l\%(\mfoobar\m\)', Group('TracesSearch')
Execute (Global):
call traces#init('7,/four/g/foobar', {})
AssertEqual '\%>3l\%<8l\_.', Group('Visual')
AssertEqual '\m\%>3l\%<8l\%(\mfoobar\m\)', Group('TracesSearch')
Execute (Global):
call traces#init('g/foobar', {})
AssertEqual '\mfoobar', Group('TracesSearch')
Execute (Range):
call traces#init('7;/four/', {})
AssertEqual '\%>6l\%<15l\_.', Group('Visual')
Execute (Substitute):
call traces#init('3;5s/\w\+/foobar', {})
AssertEqual '\%>2l\%<6l\_.', Group('Visual')
Execute (Substitute):
call traces#init('3;5s/\w\+/\r', {})
AssertEqual '\%>2l\%<9l\_.', Group('Visual')
Execute (Substitute):
call traces#init('silent! 3;5s/\w\+/\r', {})
AssertEqual '\%>2l\%<9l\_.', Group('Visual')
Execute (Substitute):
call traces#init('cdo 3;5s/\w\+/\r', {})
AssertEqual '\%>2l\%<9l\_.', Group('Visual')
Execute (Substitute):
call traces#init(':3;5s/\w\+/\r', {})
AssertEqual '\%>2l\%<9l\_.', Group('Visual')
Execute (Substitute):
call traces#init(':::: 3;5s/\w\+/\r', {})
AssertEqual '\%>2l\%<9l\_.', Group('Visual')
Execute (Substitute):
call traces#init('silent! 0;$windo silent! 3;5s/\w\+/\r', {})
AssertEqual '\%>2l\%<9l\_.', Group('Visual')
Execute (Substitute):
let g:traces_skip_modifiers = 0
call traces#init('silent! 0;$windo silent! 3;5s/\w\+/\r', {})
AssertEqual 0, Group('Visual')
Execute (Substitute):
call traces#init('3;5s/\w\+/foobar', {})
AssertEqual '\%>2l\%<6l\_.', Group('Visual')
call traces#init('3;5s', {})
AssertEqual 0, Group('Visual')
Execute (Substitute):
call traces#init('3;5s/\w\+/foobar', {})
AssertEqual '\%>2l\%<6l\_.', Group('Visual')
call traces#init('3;5sgibberish', {})
AssertEqual 0, Group('Visual')
Given (Three paragraphs):
paragraph1
paragraph1
paragraph1
paragraph2
paragraph2
paragraph2
paragraph3
paragraph3
paragraph3
Execute (Substitute):
call traces#init(',''}s', {})
call traces#init(',''}s/', {})
AssertEqual '\%>0l\%<5l\_.', Group('Visual')
#######################
# Test normal #
#######################
Given (Three lines):
one
two
three
Execute (Normal):
call traces#init('%normal! Iline ', {})
Expect:
line one
line two
line three
Execute (Normal):
call cursor(2, 3)
call traces#init('normal! a foobar', {})
Expect:
one
two foobar
three
Execute (Normal):
execute "normal ggVG\<esc>"
call traces#init('''<,''>normal! ve', {})
call traces#cmdl_leave()
call traces#init('''<,''>normal! veA word', {})
Expect:
one word
two word
three word
Execute (Normal with an error):
3d
call traces#init('%normal! isomething:asdf ', {})
call traces#cmdl_leave()
u
Expect:
one
two
three
Execute (Normal with an error):
call traces#init('%normal! vfX', {})
call traces#cmdl_leave()
AssertEqual 'n', mode()
#######################
# Test substitute #
#######################
Given (Zhongwen):
Execute (Substitute, expression with decimal number):
call traces#init('?二?+;/九/-s/\v四|六|一|十/数字/g', {})
Expect:
数字
数字
Given (Three lines):
1
2
3
Execute (Substitute, expression with decimal number):
call traces#init('%s/\d/\=submatch(0) * 0.55', {})
Expect:
0.55
1.1
1.65
Given (Three lines):
foo
foo
foo
Execute (Substitute with a backlash at the end of string):
call traces#init('%s/foo/\', {})
Expect:
\
\
\
Execute (Substitute on first line):
call traces#init('s/foo/bar', {})
Expect:
bar
foo
foo
Execute (Substitute on first and second line):
call traces#init('1;2s/foo/bar', {})
Expect:
bar
bar
foo
Execute (Substitute on every line):
call traces#init('%s/foo/bar', {})
Expect:
bar
bar
bar
Execute (Substitute on every line and revert):
call traces#init('%s/foo/bar', {})
call traces#cmdl_leave()
Expect:
foo
foo
foo
Execute (Turn off substitute preview and try to substitute):
let g:traces_substitute_preview = 0
call traces#init('%s/foo/bar', {})
Expect:
foo
foo
foo
Execute (Substitute and empty command line):
call traces#init('%s/foo/bar', {})
call traces#init('', {})
Expect:
foo
foo
foo
Given (Three lines):
foo.*
Execute (Snomagic):
call traces#init('%snoma/.*/bar', {})
Expect:
foobar
Execute (Smagic):
call traces#init('%sma/.*/bar', {})
Expect:
bar
#######################
# Test settings #
#######################
Given (Three lines):
one
two
three
Execute (Test winminwidth):
let &winminwidth = 0
let &winminheight = 0
call traces#init('%s/.', {})
Execute (Test eol):
let &listchars = ''
call traces#init('1;/three/', {})
AssertEqual '\%>0l\%<4l\(.\|^\)', Group('Visual')
let &listchars = 'eol:.'
Execute (Test hlsearch):
let &hlsearch = 1
call traces#init('1;/three/s/one', {})
AssertEqual &hlsearch, 0
call traces#cmdl_leave()
AssertEqual &hlsearch, 1
Execute (Test cursorcolumn):
let &cursorcolumn = 1
call traces#init('1;/three/s/one', {})
AssertEqual &cursorcolumn, 0
call traces#cmdl_leave()
AssertEqual &cursorcolumn, 1
Execute (Test cursorline):
let &cursorline = 1
call traces#init('1;/three/s/one', {})
AssertEqual &cursorline, 0
call traces#cmdl_leave()
AssertEqual &cursorline, 1
Execute (Test conceallevel):
let &conceallevel = 1
call traces#init('1;/three/s/one/four', {})
AssertEqual &conceallevel, 2
call traces#cmdl_leave()
AssertEqual &conceallevel, 1
Execute (Test concealcursor):
let &concealcursor = 'niv'
call traces#init('1;/three/s/one/four', {})
AssertEqual &concealcursor, 'c'
call traces#cmdl_leave()
AssertEqual &concealcursor, 'niv'
#######################
# Test undo history #
#######################
Execute:
new
AssertEqual undotree().seq_last, 0
call traces#init('s/^/foobar', {})
AssertEqual getline('.'), 'foobar'
call traces#cmdl_leave()
AssertEqual undotree().seq_last, 1
AssertEqual getline('.'), ''
call traces#init('s/^/foobar', {})
AssertEqual getline('.'), 'foobar'
call traces#cmdl_leave()
AssertEqual undotree().seq_last, 1
AssertEqual getline('.'), ''
bd
#######################
# Cleanup #
#######################
Execute (Cleanup):
Restore

View File

@ -0,0 +1,9 @@
let g:netrw_dirhistmax =10
let g:netrw_dirhistcnt =7
let g:netrw_dirhist_7='/home/sdk/blog/themes/plague/layouts/_default'
let g:netrw_dirhist_6='/home/sdk/blog/content/about'
let g:netrw_dirhist_5='/home/sdk/blog/content/distfiles'
let g:netrw_dirhist_4='/home/sdk/blog/content/about'
let g:netrw_dirhist_3='/usr/ports/pobj/urlscan-1.0.6/urlscan-1.0.6/urlscan'
let g:netrw_dirhist_2='/usr/ports/openbsd-wip/security/phrasendrescher'
let g:netrw_dirhist_1='/usr/ports/mystuff/security/enchive'

View File

@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2024, the VIM undotree plug-in authors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,129 @@
### [Project on Vim.org](http://www.vim.org/scripts/script.php?script_id=4177)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/mbbill/undotree?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
### Screenshot
![](doc/_static/undotree.png)
### Table of Contents
<!-- TOC -->
- [Description](#description)
- [Download and Install](#download-and-install)
- [Usage](#usage)
- [Configuration](#configuration)
- [Debug](#debug)
- [License](#license)
- [Author](#author)
<!-- /TOC -->
### Description
Undotree visualizes the undo history and makes it easy to browse and switch between different undo branches. You may be wondering, _what are undo "branches" anyway?_ They're a feature of Vim that allow you to go back to a prior state even after it has been overwritten by later edits. For example: In most editors, if you make some change A, followed by change B, then go back to A and make another change C, normally you wouldn't be able to go back to change B because the undo history is linear. That's not the case with Vim, however. Vim internally stores the entire edit history for each file as a single, monolithic tree structure; this plug-in exposes that tree to you so that you can not only switch back and forth between older and more recent edits linearly but can also switch between diverging branches.
> Note: use `:help 'undolevels'` in Vim for information on configuring the size of the undo history
### How it works
Some users may have questions about whether file contents change when switching between undo history states. With undotree, you don't need to worry about data loss or disk writes. The plugin will **never** save your data or write to disk. Instead, it modifies the current buffer temporarily, just like auto-completion plugins do. This means that any changes made by undotree are reversible with a single click, allowing you to easily revert to any prior state.
Vim's undo/redo feature is a great way to protect your work from accidental changes or data loss. Unlike other editors, where undoing and then accidentally typing something can cause you to lose your edits, Vim allows you to revert to previous states without losing any data, as long as you keep the Vim session alive. If you want to keep your undo history permanently, Vim offers a persistent undo feature. This feature saves your undo history to a file on disk, allowing you to preserve your undo history across editing sessions. To enable persistent undo, refer to the instructions below. This can be a useful option for those who want to maintain a long-term undo history for a file or project.
### Persisting the undo history
Undo/redo functionality is a useful feature for most editors, including Vim. However, by default, Vim's undo history is only available during the current editing session, as it is stored in memory and lost once the process exits. While tools such as undotree can aid in accessing historical states, it does not offer a permanent solution. For some users, it may be safer or more convenient to persist the undo history across editing sessions, and that's where Vim's persistent undo feature comes in.
Persistent undo saves the undo history in a file on disk, rather than in RAM. Whenever a change is made, Vim saves the edited file with its current state, while also saving the entire undo history to a separate file on disk that includes all states. This means that even after exiting Vim, the undo history is still available when you reopen the file, allowing you to continue to undo/redo changes. The undo history file is incremental and saves every change permanently, similar to Git.
If you're worried about the potential storage space used by persistent undo files, undotree provides an option to clean them up. Additionally, undotree is written in pure Vim script, making it lightweight, simple, and fast, and only runs when needed. To enable persistent undo, simply type `:h persistent-undo` in Vim, or follow the instructions provided in the *Usage* section below.
### Download and Install
Using Vim's built-in package manager:
```sh
mkdir -p ~/.vim/pack/mbbill/start
cd ~/.vim/pack/mbbill/start
git clone https://github.com/mbbill/undotree.git
vim -u NONE -c "helptags undotree/doc" -c q
```
Use whatever plug-in manager to pull the master branch. I've included 2 examples of the most used:
- *Vundle:* `Plugin 'mbbill/undotree'`
- *Vim-Plug:* `Plug 'mbbill/undotree'`
- *Packer:* `use 'mbbill/undotree'`
And install them with the following:
- *Vundle:* `:PluginInstall`
- *Vim-Plug:* `:PlugInstall`
- *Packer:* `:PackerSync`
### Usage
1. Use `:UndotreeToggle` to toggle the undo-tree panel.
You may want to map this command to whatever hotkey by adding the following line to your vimrc, take `F5` for example.
```vim
nnoremap <F5> :UndotreeToggle<CR>
```
Or the equivalent mapping if using Neovim and Lua script.
```lua
vim.keymap.set('n', '<leader><F5>', vim.cmd.UndotreeToggle)
```
2. Markers
* Every change has a sequence number and it is displayed before timestamps.
* The current state is marked as `> number <`.
* The next state which will be restored by `:redo` or `<ctrl-r>` is marked as `{ number }`.
* The `[ number ]` marks the most recent change.
* The undo history is sorted by timestamps.
* Saved changes are marked as `s` and the big `S` indicates the most recent saved change.
3. Press `?` in undotree window for quick help.
4. Persistent undo
* Usually, I would like to store the undo files in a separate place like below.
```vim
if has("persistent_undo")
let target_path = expand('~/.undodir')
" create the directory and any parent directories
" if the location does not exist.
if !isdirectory(target_path)
call mkdir(target_path, "p", 0700)
endif
let &undodir=target_path
set undofile
endif
```
* Alternatively, if you wish to persist the undo history for a currently
open file only, you can use the `:UndotreePersistUndo` command.
#### Configuration
[Here](https://github.com/mbbill/undotree/blob/master/plugin/undotree.vim#L27) is a list of options.
#### Debug
1. Create a file under $HOME with the name `undotree_debug.log`
* `$touch ~/undotree_debug.log`
2. Run vim, and the log will automatically be appended to the file, and you may watch it using `tail`:
* `$tail -F ~/undotree_debug.log`
3. If you want to disable debug, just delete that file.
### License
**BSD**
### Author
Ming Bai &lt;mbbill AT gmail DOT COM&gt;

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

View File

@ -0,0 +1,519 @@
*undotree.txt* The undo history visualizer for VIM
Author: Ming Bai <mbbill AT gmail DOT COM>
Licence: BSD
Homepage: https://github.com/mbbill/undotree/
==============================================================================
CONTENTS *undotree-contents*
1. Intro ................................ |undotree-intro|
2. Usage ................................ |undotree-usage|
3. Configuration ........................ |undotree-config|
3.1 undotree_WindowLayout .......... |undotree_WindowLayout|
3.2 undotree_CustomUndotreeCmd...... |undotree_CustomUndotreeCmd|
undotree_CustomDiffpanelCmd..... |undotree_CustomDiffpanelCmd|
3.3 undotree_SplitWidth ............ |undotree_SplitWidth|
3.4 undotree_DiffpanelHeight ....... |undotree_DiffpanelHeight|
3.5 undotree_DiffAutoOpen .......... |undotree_DiffAutoOpen|
3.6 undotree_SetFocusWhenToggle .... |undotree_SetFocusWhenToggle|
3.7 undotree_TreeNodeShape ......... |undotree_TreeNodeShape|
undotree_TreeVertShape ......... |undotree_TreeVertShape|
undotree_TreeSplitShape ........ |undotree_TreeSplitShape|
undotree_TreeReturnShape ....... |undotree_TreeReturnShape|
3.8 undotree_DiffCommand ........... |undotree_DiffCommand|
3.9 undotree_RelativeTimestamp ..... |undotree_RelativeTimestamp|
3.10 undotree_ShortIndicators ....... |undotree_ShortIndicators|
3.11 undotree_HighlightChangedText .. |undotree_HighlightChangedText|
3.12 undotree_HighlightSyntaxAdd .... |undotree_HighlightSyntaxAdd|
undotree_HighlightSyntaxChange . |undotree_HighlightSyntaxChange|
3.13 Undotree_CustomMap ............. |Undotree_CustomMap|
3.14 undotree_HelpLine .............. |undotree_HelpLine|
3.15 undotree_CursorLine ............ |undotree_CursorLine|
3.16 undotree_UndoDir................ |undotree_UndoDir|
4. Bugs ................................. |undotree-bugs|
5. Changelog ............................ |undotree-changelog|
6. License .............................. |undotree-license|
==============================================================================
1. Intro *undotree-intro*
The plug-in visualizes undo history and makes it easier to browse and switch
between different undo branches. You might wonder what are undo "branches"?
It's vim feature that allows you to go back to a state when it is overwritten
by a latest edit. For most editors, if you make a change A, then B, then go
back to A and make change C, normally you won't be able to go back to B
because undo history is linear. That's not the case for Vim because it
internally keeps all the edit history like a tree structure, and this plug-in
exposes the tree to you so that you not only can switch back and forth but
also can switch between branches.
Some people have questions about file contents being changed when switching
between undo history states. Don't worry, undotree will NEVER save your data
or write to disk. All it does is to change the current buffer little bit, just
like those auto-completion plug-ins do. It just adds or removes something in
the buffer temporarily, and if you don't like you can always go back to the
last state easily. Let's say, you made some change but didn't save, then you
use undotree and go back to an arbitrary version, your unsaved change doesn't
get lost - it stores in the latest undo history node. Clicking that node on
undotree will bring you back instantly. Play with undo/redo on other editors
is always dangerous because when you step back and accidentally typed
something, boom! You lose your edits. But don't worry, that won't happen in
Vim. Then you might ask what if I make some changes without saving and switch
back to an old version and then exit? Well, imagine what would happen if you
don't have undotree? You lose your latest edits and the file on disk is your
last saved version. This behaviour remains the same with undotree. So, if you
saved, you won't lose anything.
We all know that usually undo/redo is only for the current edit session. It's
stored in memory and once the process exits, the undo history is lost.
Although undotree makes switching between history states easier, it doesn't do
more than that. Sometimes it would be much safer or more convenient to keep
the undo history across edit sessions. In this case you might need to enable a
Vim feature called persistent undo. Let me explain how persistent undo works:
instead of keeping undo history in RAM, persistent undo keeps undo history in
file. Let's say you make a change A, then B, then go back to A and make change
C, then you save the file. Now Vim save the file with content state C, and in
the mean time it saves the entire undo history to a file including state A, B
and C. Next time when you open the file, Vim will also restore undo history.
So you can still go back to B. The history file is incremental, and every
change will be recorded permanently, kind of like Git. You might think that's
too much, well, undotree does provide a way to clean them up. If you need to
enable persistent undo, type :h persistent-undo or follow the instructions
below.
Undotree is written in pure Vim script and doesn't rely on any third party
tools. It's lightweight, simple and fast. It only does what it supposed to do,
and it only runs when you need it.
==============================================================================
2. Usage *undotree-usage*
Use :UndotreeToggle to toggle the undo-tree panel. You may want to map this
command to whatever hotkey by adding the following line to your vimrc, take F5
for example.
>
nnoremap <F5> :UndotreeToggle<cr>
<
Markers
* Every change has a sequence number and it is displayed before timestamps.
* The current state is marked as > number <.
* The next state which will be restored by :redo or <ctrl-r> is marked as
{ number }.
* The [ number ] marks the most recent change.
* The undo history is sorted by timestamps.
* Saved changes are marked as s and the big S indicates the most recent
saved change.
* Press ? in undotree window for quick help.
Persistent undo
Usually I would like to store the undo files in a separate place like below.
>
if has("persistent_undo")
let target_path = expand('~/.undodir')
" create the directory and any parent directories
" if the location does not exist.
if !isdirectory(target_path)
call mkdir(target_path, "p", 0700)
endif
let &undodir=target_path
set undofile
endif
<
Alternatively, the persistent undofile can be activated by using the
:UndotreePersistUndo command. This will enable the undofile for the current
buffer only, as undotree utilizes the setlocal undofile function. Once this
command is executed and the persistence undofile is created, the "setlocal
undofile" function will automatically be executed the next time the file is
reopened.
See |undotree_UndoDir|
You may want to map the command to whatever hotkey by adding this following
line to your vimrc, for instance:
`nnoremap <F6> :UndotreePersistUndo<cr>`
==============================================================================
3. Configuration *undotree-config*
------------------------------------------------------------------------------
3.1 g:undotree_WindowLayout *undotree_WindowLayout*
Set the undotree window layout.
Style 1
>
+----------+------------------------+
| | |
| | |
| undotree | |
| | |
| | |
+----------+ |
| | |
| diff | |
| | |
+----------+------------------------+
<
Style 2
>
+----------+------------------------+
| | |
| | |
| undotree | |
| | |
| | |
+----------+------------------------+
| |
| diff |
| |
+-----------------------------------+
<
Style 3
>
+------------------------+----------+
| | |
| | |
| | undotree |
| | |
| | |
| +----------+
| | |
| | diff |
| | |
+------------------------+----------+
<
Style 4
>
+------------------------+----------+
| | |
| | |
| | undotree |
| | |
| | |
+------------------------+----------+
| |
| diff |
| |
+-----------------------------------+
<
Default: 1
------------------------------------------------------------------------------
3.2 g:undotree_CustomUndotreeCmd *undotree_CustomUndotreeCmd*
g:undotree_CustomDiffpanelCmd *undotree_CustomDiffpanelCmd*
Set up custom window layout.
Setting |undotree_CustomUndotreeCmd| will ignore |undotree_SplitWidth|, and
setting |undotree_CustomDiffpanelCmd| will ignore |undotree_DiffpanelHeight|.
An |undotree_CustomUndotreeCmd| will always open the undotree window relative
to the tracked window and |undotree_CustomDiffpanelCmd| will always open the
diffpanel relative to the undotree window.
Useful when
* absolute positioning commands (|topleft|, |botright|) don't play well
with other plugins
* you have a preferred split window layout and would like to use
UndoTree relative to one specific window only
Examples:
* To recreate Style 1:
>
let g:undotree_CustomUndotreeCmd = 'topleft vertical 30 new'
let g:undotree_CustomDiffpanelCmd = 'belowright 10 new'
<
* To recreate Style 2:
>
let g:undotree_CustomUndotreeCmd = 'topleft vertical 30 new'
let g:undotree_CustomDiffpanelCmd = 'botright 10 new'
<
* A custom layout example:
>
+------------------------+----------+
| | |
| | w |
| | i |
| | n |
| window_1 | d |
| | o |
| | w |
| | | |
| | 2 |
| | |
+------------------------+----------+
| |
| window_3 |
| |
+-----------------------------------+
<
Using the following setup wouldn't mess up the current layout as it
does not use absolute positioning:
>
let g:undotree_CustomUndotreeCmd = 'vertical 32 new'
let g:undotree_CustomDiffpanelCmd= 'belowright 12 new'
<
Issuing :UndotreeToggle now in window_1 would result in:
>
+--------+---------------+----------+
| | | |
| u | | w |
| n | | i |
| d | | n |
| o | window_1 | d |
| | | o |
+--------+ | w |
| | | | |
| diff | | 2 |
| | | |
+--------+---------------+----------+
| |
| window_3 |
| |
+-----------------------------------+
<
Executing :UndotreeToggle again would turn off UndoTree (independently
of which window was active at the time). Moving between window1, window_2
and window_3 would result in showing the respective window's changelog
in the undotree panel.
CAVEAT: To avoid the Vim's default behaviour of equalizing window sizes
when closing a window, set the 'noequalalways' option.
------------------------------------------------------------------------------
3.3 g:undotree_SplitWidth *undotree_SplitWidth*
Set the undotree window width.
Default: 30
------------------------------------------------------------------------------
3.4 g:undotree_DiffpanelHeight *undotree_DiffpanelHeight*
Set the diff window height.
Default: 10
------------------------------------------------------------------------------
3.5 g:undotree_DiffAutoOpen *undotree_DiffAutoOpen*
Set this to 1 to auto open the diff window.
Default: 1
------------------------------------------------------------------------------
3.6 g:undotree_SetFocusWhenToggle *undotree_SetFocusWhenToggle*
If set to 1, the undotree window will get focus after being opened, otherwise
focus will stay in current window.
Default: 0
------------------------------------------------------------------------------
3.7 g:undotree_TreeNodeShape *undotree_TreeNodeShape*
g:undotree_TreeVertShape *undotree_TreeVertShape*
g:undotree_TreeSplitShape *undotree_TreeSplitShape*
g:undotree_TreeReturnShape *undotree_TreeReturnShape*
Set the characters used to draw the tree. Although you can put any character
you want in these shape variables, the only Unicode box drawing characters
that work well are these three. Make sure your font will render them; you can
easily see if that's the case in the last column of this table.
Variable | Default | Unicode Box Character
---------------------------+---------------+-----------------------
g:undotree_TreeNodeShape | * |
g:undotree_TreeReturnShape | \ (backslash) | ╲ (U+2572)
g:undotree_TreeVertShape | | (pipe) | │ (U+2502)
g:undotree_TreeSplitShape | / (slash) | (U+2571)
------------------------------------------------------------------------------
3.8 g:undotree_DiffCommand *undotree_DiffCommand*
Set the command used to get the diff output.
Default: "diff"
------------------------------------------------------------------------------
3.9 g:undotree_RelativeTimestamp *undotree_RelativeTimestamp*
Set to 1 to use relative timestamp.
Default: 1
------------------------------------------------------------------------------
3.10 g:undotree_ShortIndicators *undotree_ShortIndicators*
Set to 1 to get short timestamps when |undotree_RelativeTimestamp| is also
enabled:
>
Before | After
===========================
(5 seconds ago) | (5 s)
----------------|----------
(1 minute ago) | (1 m)
----------------|----------
(2 minutes ago) | (2 m)
----------------|----------
(1 hour ago) | (1 h)
----------------|----------
(Original) | (Orig)
<
Default: 0
------------------------------------------------------------------------------
3.11 g:undotree_HighlightChangedText *undotree_HighlightChangedText*
Set to 1 to highlight the changed text.
Default: 1
------------------------------------------------------------------------------
3.12 g:undotree_HighlightSyntaxAdd *undotree_HighlightSyntaxAdd*
g:undotree_HighlightSyntaxDel *undotree_HighlightSyntaxDel*
g:undotree_HighlightSyntaxChange *undotree_HighlightSyntaxChange*
Set the highlight linked syntax type.
You may chose your favorite through ":hi" command.
Default: "DiffAdd", "DiffDelete" and "DiffChange"
------------------------------------------------------------------------------
3.13 g:Undotree_CustomMap *Undotree_CustomMap*
There are two ways of changing the default key mappings:
The first way is to define global mappings as the following example:
>
nmap <buffer> J <plug>UndotreeNextState
nmap <buffer> K <plug>UndotreePreviousState
<
A better approach is to define the callback function g:Undotree_CustomMap().
The function will be called after the undotree windows is initialized, so the
key mappings only works on the undotree windows.
>
function g:Undotree_CustomMap()
nmap <buffer> J <plug>UndotreeNextState
nmap <buffer> K <plug>UndotreePreviousState
endfunc
<
List of the commands available for redefinition.
>
<plug>UndotreeHelp
<plug>UndotreeClose
<plug>UndotreeFocusTarget
<plug>UndotreeClearHistory
<plug>UndotreeTimestampToggle
<plug>UndotreeDiffToggle
<plug>UndotreeNextState
<plug>UndotreePreviousState
<plug>UndotreeNextSavedState
<plug>UndotreePreviousSavedState
<plug>UndotreeRedo
<plug>UndotreeUndo
<plug>UndotreeEnter
<
------------------------------------------------------------------------------
3.14 g:undotree_HelpLine *undotree_HelpLine*
Set to 0 to hide "Press ? for help".
Default: 1
------------------------------------------------------------------------------
3.15 g:undotree_CursorLine
Set to 0 to disable cursorline.
Default: 1
------------------------------------------------------------------------------
3.16 g:undotree_UndoDir *undotree_UndoDir*
Set the path for the persistence undo directory. Due to the differing formats
of the persistence undo files between nvim and vim, the default undodir for
both has been intentionally given different paths. This ensures that users who
use both nvim and vim do not accidentally lose their persistence undo files
due to the different ways in which vim and nvim handle these files.
If the g:undotree_UndoDir is not set and undodir has been set to "." (vim's
default undodir value), then the g:undotree_UndoDir value will be set to:
- vim: $HOME/.local/state/undo/vim/
- nvim: $HOME/.local/state/undo/nvim/
==============================================================================
4. Bugs *undotree-bugs*
Post any issue and feature request here:
https://github.com/mbbill/undotree/issues
==============================================================================
5. Changelog *undotree-changelog*
Further changes will not be recorded. Please go to github page for more
information.
4.4 (2017-10-15)
- Autoload plugin functions
4.3 (2013-02-18)
- Several fixes and enhancements.
4.2 (2012-11-24)
- Fixed some small issue.
4.1 (2012-09-05)
- Enhanced tree style.
- Multi-window switching support.
4.0 (2012-08-30)
- Live updated highlight for changed text.
- Customizable key mappings.
- Fixed some minor bugs.
3.1 (2012-08-25)
- Add saved status.
- Add relative timestamp.
- Add ability of clear undo history.
3.0 (2012-08-24)
- Add diff panel.
- Performance improvement.
2.2 (2012-08-21)
- Stable version.
2.1 (2012-08-20)
- Fixed some annoying issues.
2.0 (2012-08-19)
- Hotkey support.
- Handle undo levels.
- Auto refresh.
- And so on.
1.0 (2012-08-18)
- Initial upload
==============================================================================
6. License *undotree-license*
BSD
vim:tw=78:ts=8:ft=help:norl:

View File

@ -0,0 +1,203 @@
"=================================================
" File: plugin/undotree.vim
" Description: Manage your undo history in a graph.
" Author: Ming Bai <mbbill@gmail.com>
" License: BSD
" Avoid installing twice.
if exists('g:loaded_undotree')
finish
endif
let g:loaded_undotree = 0
" At least version 7.3 with 005 patch is needed for undo branches.
" Refer to https://github.com/mbbill/undotree/issues/4 for details.
" Thanks kien
if v:version < 703
command! -nargs=0 -bar UndotreeToggle :echoerr "undotree.vim needs Vim version >= 7.3"
finish
endif
if (v:version == 703 && !has("patch005"))
command! -nargs=0 -bar UndotreeToggle :echoerr "undotree.vim needs vim7.3 with patch005 applied."
finish
endif
let g:loaded_undotree = 1 " Signal plugin availability with a value of 1.
"=================================================
"Options:
" Window layout
" style 1
" +----------+------------------------+
" | | |
" | | |
" | undotree | |
" | | |
" | | |
" +----------+ |
" | | |
" | diff | |
" | | |
" +----------+------------------------+
" Style 2
" +----------+------------------------+
" | | |
" | | |
" | undotree | |
" | | |
" | | |
" +----------+------------------------+
" | |
" | diff |
" | |
" +-----------------------------------+
" Style 3
" +------------------------+----------+
" | | |
" | | |
" | | undotree |
" | | |
" | | |
" | +----------+
" | | |
" | | diff |
" | | |
" +------------------------+----------+
" Style 4
" +-----------------------++----------+
" | | |
" | | |
" | | undotree |
" | | |
" | | |
" +------------------------+----------+
" | |
" | diff |
" | |
" +-----------------------------------+
if !exists('g:undotree_WindowLayout')
let g:undotree_WindowLayout = 1
endif
" e.g. using 'd' instead of 'days' to save some space.
if !exists('g:undotree_ShortIndicators')
let g:undotree_ShortIndicators = 0
endif
" undotree window width
if !exists('g:undotree_SplitWidth')
if g:undotree_ShortIndicators == 1
let g:undotree_SplitWidth = 24
else
let g:undotree_SplitWidth = 30
endif
endif
" diff window height
if !exists('g:undotree_DiffpanelHeight')
let g:undotree_DiffpanelHeight = 10
endif
" auto open diff window
if !exists('g:undotree_DiffAutoOpen')
let g:undotree_DiffAutoOpen = 1
endif
" if set, let undotree window get focus after being opened, otherwise
" focus will stay in current window.
if !exists('g:undotree_SetFocusWhenToggle')
let g:undotree_SetFocusWhenToggle = 0
endif
" tree node shape.
if !exists('g:undotree_TreeNodeShape')
let g:undotree_TreeNodeShape = '*'
endif
" tree vertical shape.
if !exists('g:undotree_TreeVertShape')
let g:undotree_TreeVertShape = '|'
endif
" tree split shape.
if !exists('g:undotree_TreeSplitShape')
let g:undotree_TreeSplitShape = '/'
endif
" tree return shape.
if !exists('g:undotree_TreeReturnShape')
let g:undotree_TreeReturnShape = '\'
endif
if !exists('g:undotree_DiffCommand')
let g:undotree_DiffCommand = "diff"
endif
" relative timestamp
if !exists('g:undotree_RelativeTimestamp')
let g:undotree_RelativeTimestamp = 1
endif
" Highlight changed text
if !exists('g:undotree_HighlightChangedText')
let g:undotree_HighlightChangedText = 1
endif
" Highlight changed text using signs in the gutter
if !exists('g:undotree_HighlightChangedWithSign')
let g:undotree_HighlightChangedWithSign = 1
endif
" Highlight linked syntax type.
" You may chose your favorite through ":hi" command
if !exists('g:undotree_HighlightSyntaxAdd')
let g:undotree_HighlightSyntaxAdd = "DiffAdd"
endif
if !exists('g:undotree_HighlightSyntaxChange')
let g:undotree_HighlightSyntaxChange = "DiffChange"
endif
if !exists('g:undotree_HighlightSyntaxDel')
let g:undotree_HighlightSyntaxDel = "DiffDelete"
endif
" Deprecates the old style configuration.
if exists('g:undotree_SplitLocation')
echo "g:undotree_SplitLocation is deprecated,
\ please use g:undotree_WindowLayout instead."
endif
" Show help line
if !exists('g:undotree_HelpLine')
let g:undotree_HelpLine = 1
endif
" Show cursorline
if !exists('g:undotree_CursorLine')
let g:undotree_CursorLine = 1
endif
" Define the default persistence undo directory if not defined in vim/nvim
" startup script.
if !exists('g:undotree_UndoDir')
let s:undoDir = &undodir
let s:subdir = has('nvim') ? 'nvim' : 'vim'
if s:undoDir == "."
let s:undoDir = $HOME . '/.local/state/' . s:subdir . '/undo/'
endif
let g:undotree_UndoDir = s:undoDir
endif
augroup undotreeDetectPersistenceUndo
au!
au BufReadPost * call undotree#UndotreePersistUndo(0)
augroup END
"=================================================
" User commands.
command! -nargs=0 -bar UndotreeToggle :call undotree#UndotreeToggle()
command! -nargs=0 -bar UndotreeHide :call undotree#UndotreeHide()
command! -nargs=0 -bar UndotreeShow :call undotree#UndotreeShow()
command! -nargs=0 -bar UndotreeFocus :call undotree#UndotreeFocus()
command! -nargs=0 -bar UndotreePersistUndo :call undotree#UndotreePersistUndo(1)
" vim: set et fdm=marker sts=4 sw=4:

View File

@ -0,0 +1,37 @@
"=================================================
" File: undotree.vim
" Description: undotree syntax
" Author: Ming Bai <mbbill@gmail.com>
" License: BSD
execute "syn match UndotreeNode ' \\zs".escape(g:undotree_TreeNodeShape,'*')."\\ze '"
execute "syn match UndotreeNodeCurrent '\\zs".escape(g:undotree_TreeNodeShape,'*')."\\ze.*>\d\+<'"
syn match UndotreeTimeStamp '(.*)$'
syn match UndotreeFirstNode 'Original'
execute "syn match UndotreeBranch '[".escape(g:undotree_TreeVertShape.g:undotree_TreeSplitShape.g:undotree_TreeReturnShape,'\')."]'"
syn match UndotreeSeq ' \zs\d\+\ze '
syn match UndotreeCurrent '>\d\+<'
syn match UndotreeNext '{\d\+}'
syn match UndotreeHead '\[\d\+]'
syn match UndotreeHelp '^".*$' contains=UndotreeHelpKey,UndotreeHelpTitle
syn match UndotreeHelpKey '^" \zs.\{-}\ze:' contained
syn match UndotreeHelpTitle '===.*===' contained
syn match UndotreeSavedSmall ' \zss\ze '
syn match UndotreeSavedBig ' \zsS\ze '
hi def link UndotreeNode Question
hi def link UndotreeNodeCurrent Statement
hi def link UndotreeTimeStamp Function
hi def link UndotreeFirstNode Function
hi def link UndotreeBranch Constant
hi def link UndotreeSeq Comment
hi def link UndotreeCurrent Statement
hi def link UndotreeNext Type
hi def link UndotreeHead Identifier
hi def link UndotreeHelp Comment
hi def link UndotreeHelpKey Function
hi def link UndotreeHelpTitle Type
hi def link UndotreeSavedSmall WarningMsg
hi def link UndotreeSavedBig MatchParen
" vim: set et fdm=marker sts=4 sw=4:

View File

@ -29,6 +29,12 @@ if &diff
syntax off
set colorcolumn=
endif
set diffopt=internal
set diffopt+=filler,context:100000
set diffopt+=iwhite,iblank
set diffopt+=algorithm:patience
set diffexpr=
filetype plugin indent on " load plugins based on filetype
set re=1 " use old regexp engine (faster)
let mapleader = ","
@ -66,6 +72,7 @@ set fillchars+=foldopen:\🗁
set wildmode=full
""map :q map <leader>q :bp<bar>sp<bar>bn<bar>bd<CR>
nmap Q :qall!
let g:currentmode={
\ 'n' : 'NORMAL',
@ -153,7 +160,6 @@ highlight DiffDelete ctermfg=234 ctermbg=0
highlight DiffChange ctermfg=255 ctermbg=234
highlight DiffText ctermfg=166 ctermbg=234
" GITGUTTER
set signcolumn=number
highlight GitGutterAddLine ctermfg=1 ctermbg=0