diff --git a/plugin/hightlight.vim b/plugin/hightlight.vim index 337494d..fd2aa85 100644 --- a/plugin/hightlight.vim +++ b/plugin/hightlight.vim @@ -10,122 +10,182 @@ endif let g:loaded_highlight = 1 +" GLOBAL VARIABLES: +" ====================================================================== + +let g:highlight_register_default_color = 'Yellow' + + " SCRIPT VARIABLES: " ====================================================================== -" s:highlight_register_color :: { String : String } {{{2 +" s:registry_colors :: { String : String } {{{2 " ---------------------------------------------------------------------- " Mapping between registry name and color that should be used for " highlighting. -let s:highlight_register_color = {} +let s:registry_colors = {} -" s:matches :: { String : Match } {{{2 +" s:registry :: { String : { String : Match } } {{{2 " ---------------------------------------------------------------------- -" List of matches corresponding to the registry. - -let s:matches = {} - - -" s:registry :: { String : [String] } {{{2 -" ---------------------------------------------------------------------- -" Name of register corresponding to a list of the keys used in the -" s:matches corresponding to the match of the word in said register. -" Used to find the matches that can be deleted later on. +" Name of register corresponding to a dict of some unique identifier of the +" word being matched, paired with the actual match object. let s:registry = {} -" FUNCTION: MatchName(reg, word) {{{1 -" ====================================================================== - -function! s:MatchName(reg, word) - return a:reg . '_' . word -endfunction - - " FUNCTION: GroupName(reg) {{{1 " ====================================================================== +" Note group names are not allowed to have special characters; they +" must be alphanumeric or underscores. function! s:GroupName(reg) - return 'PlugHighlightRegister_' . a:reg + return 'HighlightRegistry_' . char2nr(a:reg) endfunction -" FUNCTION: ClearHighlightRegister(reg) {{{1 +" FUNCTION: InitRegister(reg) {{{1 +" ====================================================================== +" Setups the group and highlighting. Matches are added afterward. + +function! s:InitRegister(reg, color) + call s:ClearRegister(a:reg) + let s:registry_colors[a:reg] = a:color + exe 'hi ' . s:GroupName(a:reg) . ' cterm=bold,underline ctermfg=' . a:color +endfunction + + +" FUNCTION: ClearRegister(reg) {{{1 " ====================================================================== " Used to clear out the 'registers' that are used to hold which values are " highlighted under a certain match group. -function! s:ClearHighlightRegister(reg) +function! s:ClearRegister(reg) exe 'hi clear ' . s:GroupName(a:reg) - unlet s:highlight_register_color[a:reg] + if has_key(s:registry_colors, a:reg) + unlet s:registry_colors[a:reg] + endif if has_key(s:registry, a:reg) - for m in s:registry[a:reg] - matchdelete(s:matches[s:registry[a:reg]]) - unlet s:matches[s:registry[a:reg]] + for key in keys(s:registry[a:reg]) + call matchdelete(s:registry[a:reg][key]) + unlet s:registry[a:reg][key] endfor unlet s:registry[a:reg] endif + call s:ActivateRegister(a:reg) endfunction -" FUNCTION: InitHighlightRegister(reg) {{{1 +" FUNCTION: ActivateRegister(reg) {{{1 " ====================================================================== -" Setups the group and highlighting. Matches are added afterward +" We must actively set the search register to perform searches as expected. -function! s:InitHighlightRegister(reg, color) - call c:ClearHighlightRegister(a:reg) - let s:highlight_register_color[a:reg] = a:color - exe 'hi ' . s:GroupName(a:reg) . ' cterm=bold, underline ctermbg=' . a:color +function! s:ActivateRegister(reg) + if has_key(s:registry, a:reg) && has_key(s:registry_colors, a:reg) + let search = '' + for key in keys(s:registry[a:reg]) + let search = search . key . '\|' + endfor + let @/ = search[:-3] + exe 'hi Search cterm=bold,underline ctermbg=none ctermfg=' . s:registry_colors[a:reg] + set hlsearch + else + let @/ = '' + endif endfunction -" FUNCTION: AppendToSearch(reg, word) {{{1 +" FUNCTION: AppendToSearch(reg, pattern) {{{1 " ====================================================================== -function! s:AppendToSearch(reg, word) - let m = matchadd(s:GroupName(a:reg), '\<' . a:word . '\>') - let s:matches[s:MatchName(a:reg, a:word)] = l:m +function! s:AppendToSearch(reg, pattern) + let s:last_seen = a:pattern + if !has_key(s:registry_colors, a:reg) + call s:InitRegister(a:reg, g:highlight_register_default_color) + endif if !has_key(s:registry, a:reg) - let s:registry[a:reg] = [] + let s:registry[a:reg] = {} endif - append(s:registry[a:reg], s:MatchName(a:reg, a:word)) + " Don't want to add multiple match objects into registry + if !has_key(s:registry[a:reg], a:pattern) + let s:registry[a:reg][a:pattern] = + \ matchadd(s:GroupName(a:reg), a:pattern) + endif + call s:ActivateRegister(a:reg) endfunction -" FUNCTION: RemoveFromSearch(reg, word) {{{1 +" FUNCTION: AppendToSearchForward(reg, pattern) {{{1 " ====================================================================== -function! s:RemoveFromSearch(reg, word) - matchdelete(s:matches[s:MatchName(a:reg, a:word)]) - unlet s:matches[s:MatchName(a:reg, a:word)] - let i = 0 - while i < len(s:registry[a:reg]) - if s:registry[a:reg] == s:MatchName(a:reg, a:word) - unlet s:registry[a:reg][i] - break +function! s:AppendToSearchForward(reg, pattern) + call s:AppendToSearch(a:reg, a:pattern) + normal! * +endfunction + + +" FUNCTION: AppendToSearchBackward(reg, pattern) {{{1 +" ====================================================================== + +function! s:AppendToSearchBackward(reg, pattern) + call s:AppendToSearch(a:reg, a:pattern) + normal! # +endfunction + + +" FUNCTION: RemoveFromSearch(reg, pattern) {{{1 +" ====================================================================== + +function! s:RemoveFromSearch(reg, pattern) + if has_key(s:registry, a:reg) && has_key(s:registry[a:reg], a:pattern) + call matchdelete(s:registry[a:reg][a:pattern]) + unlet s:registry[a:reg][a:pattern] + if len(s:registry[a:reg]) == 0 + unlet s:registry[a:reg] endif - i = i + 1 - endwhile - if len(s:registry[a:reg]) == 0 - unlet s:registry[a:reg] endif + call s:ActivateRegister(a:reg) endfunction - -" FUNCTION: Initialize {{{1 + +" PROCEDURE: Initialize {{{1 " ====================================================================== -call s:InitHighlightRegister('0', 'Yellow') -call s:InitHighlightRegister('1', 'DarkYellow') -call s:InitHighlightRegister('2', 'Red') -call s:InitHighlightRegister('3', 'DarkRed') -call s:InitHighlightRegister('4', 'Green') -call s:InitHighlightRegister('5', 'DarkGreen') -call s:InitHighlightRegister('6', 'Blue') -call s:InitHighlightRegister('7', 'DarkBlue') -call s:InitHighlightRegister('8', 'Magenta') -call s:InitHighlightRegister('9', 'DarkMagenta') +exe 'hi Search cterm=bold,underline ctermbg=none ctermfg=' . g:highlight_register_default_color + +call s:InitRegister('0', 'Yellow') +call s:InitRegister('1', 'DarkYellow') +call s:InitRegister('2', 'Red') +call s:InitRegister('3', 'Magenta') +call s:InitRegister('4', 'Green') +call s:InitRegister('5', 'Cyan') +call s:InitRegister('6', 'Blue') +call s:InitRegister('7', 'White') +call s:InitRegister('8', 'Gray') +call s:InitRegister('9', 'Black') + +noremap HighlightRegistry_AppendToSearch + \ :call AppendToSearch(v:register, '\<'.expand('').'\>') +noremap HighlightRegistry_Forward_AppendToSearch + \ :call AppendToSearchForward(v:register, '\<'.expand('').'\>') +noremap HighlightRegistry_Backward_AppendToSearch + \ :call AppendToSearchBackward(v:register, '\<'.expand('').'\>') +noremap HighlightRegistry_RemoveFromSearch + \ :call RemoveFromSearch(v:register, '\<'.expand('').'\>') +noremap HighlightRegistry_ClearRegister + \ :call ClearRegister(v:register) + +" Basic Mappings +nmap & HighlightRegistry_AppendToSearch +nmap * HighlightRegistry_Forward_AppendToSearch +nmap # HighlightRegistry_Backward_AppendToSearch + +" Additional Register Modifiers +nmap d& HighlightRegistry_RemoveFromSearch +nmap c& HighlightRegistry_ClearRegister + +" Other Mappings +nmap n :norm! nzzzv +nmap N :norm! Nzzzv