├── .gitignore ├── .gitmodules ├── Makefile ├── README.md ├── autoload ├── hexokinase.vim └── hexokinase │ ├── checker.vim │ ├── highlighters │ ├── background.vim │ ├── backgroundfull.vim │ ├── foreground.vim │ ├── foregroundfull.vim │ ├── sign_column.vim │ └── virtual.vim │ ├── patterns │ ├── colour_names.vim │ ├── full_hex.vim │ ├── rgb.vim │ ├── rgba.vim │ └── triple_hex.vim │ ├── utils.vim │ ├── v1.vim │ ├── v2.vim │ └── v2 │ └── scraper.vim ├── doc └── hexokinase.txt ├── lua └── hexokinase.lua ├── plugin └── hexokinase.vim ├── screenshot_colours.txt └── test_colours.txt /.gitignore: -------------------------------------------------------------------------------- 1 | sample_colours* 2 | gif_colours.txt 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "hexokinase"] 2 | path = hexokinase 3 | url = https://github.com/RRethy/hexokinase.git 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: hexokinase 2 | hexokinase: 3 | git submodule init && git submodule update && cd hexokinase/ && go build 4 | 5 | .PHONY: clean 6 | clean: 7 | rm -rf hexokinase/ 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-hexokinase 2 | 3 | The fastest (Neo)Vim plugin for asynchronously displaying the colours in the file (#rrggbb, #rgb, rgb(a)? functions, hsl(a)? functions, web colours, custom patterns) 4 | 5 | > let g:Hexokinase_highlighters = ['virtual'] 6 | 7 | ![gif](https://media.giphy.com/media/PikQiakj2NYxFDmcdl/giphy.gif) 8 | 9 | > let g:Hexokinase_highlighters = ['sign_column'] 10 | 11 | ![gif](https://media.giphy.com/media/5kFmgYX1mF7l25BnYe/giphy.gif) 12 | 13 | > set signcolumn=yes:9 " Neovim only 14 | 15 | 16 | 17 | > let g:Hexokinase_highlighters = ['foreground'] 18 | 19 | 20 | 21 | > let g:Hexokinase_highlighters = ['foregroundfull'] 22 | 23 | 24 | 25 | > let g:Hexokinase_highlighters = ['background'] 26 | 27 | 28 | 29 | > let g:Hexokinase_highlighters = ['backgroundfull'] 30 | 31 | 32 | 33 | ## Rationale 34 | 35 | **Problem:** [Colorizer](https://github.com/chrisbra/Colorizer) and [Colorizer](https://github.com/lilydjwg/colorizer) are plugins which also display the colour of text. However, they do so by changing the background of the text which is not pleasing to look at. On top of that, they all scrape the file synchronously. 36 | 37 | **Solution:** Have 6 different options for displaying colour, including as virtual text or in the sign column. As well, do all scraping asynchronously. 38 | 39 | ## About 40 | 41 | This plugin can display the colour of 6 digit hex codes, 3 digit hex codes, rgb functions, rgba functions, hsl functions, hsla functions, and custom patterns. 42 | 43 | Colour can be displayed in each of the 6 six ways shown above, or can be customized to display colour any way the user chooses. 44 | 45 | **Note:** By default all filetypes are scraped and highlighted on `['TextChanged', 'InsertLeave', 'BufRead']`, see `:h g:Hexokinase_refreshEvents` for more info. 46 | 47 | ## Requirements 48 | 49 | - `:h 'termguicolors'` must be turned on and your terminal must support it 50 | - **Golang must be installed, for more information visit https://golang.org/doc/install.** 51 | - For *virtual text*: Neovim 0.3.2 52 | - For *sign_column*: Vim compiled with `+signs` or any Neovim version 53 | - Currently, untested on Windows, help is welcomed. 54 | 55 | ## Installation 56 | 57 | 1. Install Golang https://golang.org/doc/install 58 | 2. Install the plugin with the plugin manager of choice and ensure `make hexokinase` is executed in the project root: 59 | 60 | ```vim 61 | " vim-plug 62 | Plug 'rrethy/vim-hexokinase', { 'do': 'make hexokinase' } 63 | 64 | " minpac 65 | call minpac#add('rrethy/vim-hexokinase', { 'do': 'make hexokinase' }) 66 | 67 | " dein 68 | call dein#add('rrethy/vim-hexokinase', { 'build': 'make hexokinase' }) 69 | 70 | " etc. 71 | ``` 72 | 73 | 3. `:set termguicolors` 74 | 75 | ## Quick Start 76 | 77 | Choose your method of highlighting: 78 | 79 | ```vim 80 | " Neovim default 81 | let g:Hexokinase_highlighters = [ 'virtual' ] 82 | 83 | " Vim default 84 | let g:Hexokinase_highlighters = [ 'sign_column' ] 85 | 86 | " All possible highlighters 87 | let g:Hexokinase_highlighters = [ 88 | \ 'virtual', 89 | \ 'sign_column', 90 | \ 'background', 91 | \ 'backgroundfull', 92 | \ 'foreground', 93 | \ 'foregroundfull' 94 | \ ] 95 | ``` 96 | 97 | Choose which patterns are matched: 98 | 99 | ```vim 100 | " Patterns to match for all filetypes 101 | " Can be a comma separated string or a list of strings 102 | " Default value: 103 | let g:Hexokinase_optInPatterns = 'full_hex,rgb,rgba,hsl,hsla,colour_names' 104 | 105 | " All possible values 106 | let g:Hexokinase_optInPatterns = [ 107 | \ 'full_hex', 108 | \ 'triple_hex', 109 | \ 'rgb', 110 | \ 'rgba', 111 | \ 'hsl', 112 | \ 'hsla', 113 | \ 'colour_names' 114 | \ ] 115 | 116 | " Filetype specific patterns to match 117 | " entry value must be comma seperated list 118 | let g:Hexokinase_ftOptInPatterns = { 119 | \ 'css': 'full_hex,rgb,rgba,hsl,hsla,colour_names', 120 | \ 'html': 'full_hex,rgb,rgba,hsl,hsla,colour_names' 121 | \ } 122 | ``` 123 | 124 | Choose which filetypes to scrape automatically (by default ALL filetypes are scraped): 125 | 126 | ```vim 127 | " Sample value, to keep default behaviour don't define this variable 128 | let g:Hexokinase_ftEnabled = ['css', 'html', 'javascript'] 129 | ``` 130 | 131 | ## Commands 132 | 133 | | Command | Description | 134 | |---|---| 135 | | **HexokinaseToggle** | Toggle the colouring | 136 | | **HexokinaseTurnOn** | Turn on colouring (refresh if already turned on) | 137 | | **HexokinaseTurnOff** | Turn off colouring | 138 | 139 | ## Full Configuration 140 | 141 | See `:help hexokinase.txt` 142 | 143 | ## Custom Patterns 144 | 145 | See `:help g:Hexokinase_palettes`. 146 | 147 | This can be used to colour specific variables. 148 | 149 | ## FAQ 150 | 151 | > I'm seeing grey colours when I toggle vim-hexokinase 152 | 153 | You need `termguicolors` to be turned on. Verify `:set termguicolors?` outputs `termguicolors`. For more info, see https://github.com/RRethy/vim-hexokinase/issues/10. 154 | -------------------------------------------------------------------------------- /autoload/hexokinase.vim: -------------------------------------------------------------------------------- 1 | " This file is for v1, v2 is all in the subdirectories 2 | 3 | fun! hexokinase#toggle_scraping() abort 4 | let b:hexokinase_scraper_on = !get(b:, 'hexokinase_scraper_on', 0) 5 | let g:Hexokinase_silent = get(g:, 'Hexokinase_silent', 0) 6 | if b:hexokinase_scraper_on 7 | call hexokinase#scrape_colours() 8 | if !g:Hexokinase_silent 9 | echo 'Turned on highlighting' 10 | endif 11 | else 12 | call hexokinase#tear_down() 13 | if !g:Hexokinase_silent 14 | echo 'Turned off highlighting' 15 | endif 16 | endif 17 | endf 18 | 19 | fun! hexokinase#on_autoload_ft_set() abort 20 | let b:hexokinase_scraper_on = !get(b:, 'hexokinase_scraper_on', 0) 21 | if b:hexokinase_scraper_on 22 | call hexokinase#scrape_colours() 23 | endif 24 | endf 25 | 26 | fun! hexokinase#scrape_colours() abort 27 | let lnum = 1 28 | " Builds a map of patterns to processors 29 | let pattern_processor_map = hexokinase#utils#get_pat_proc_map() 30 | " Builds a regex that handles all colour patterns 31 | let pattern = hexokinase#utils#get_colour_pattern(keys(pattern_processor_map)) 32 | 33 | for lnum in range(1, line('$')) 34 | 35 | let line_text = getline(lnum) 36 | let n = 1 37 | let colorsInfo = [] 38 | 39 | let [colourMatch,start,end] = matchstrpos(line_text, pattern, 0, n) 40 | " Try to process the colour to a six digit hex code 41 | while colourMatch !=# '' 42 | let processed = 0 43 | for pattern_regex in keys(pattern_processor_map) 44 | if colourMatch =~# '^' . pattern_regex . '$' 45 | " Call the appropriate pocessor to get a six digit hex or empty str 46 | let colourMatch = pattern_processor_map[pattern_regex](colourMatch) 47 | if !empty(colourMatch) 48 | let processed = 1 49 | break 50 | endif 51 | endif 52 | endfor 53 | 54 | if processed 55 | call add(colorsInfo, [colourMatch, start, end]) 56 | endif 57 | let n += 1 58 | let [colourMatch,start,end] = matchstrpos(line_text, pattern, 0, n) 59 | endwhile 60 | 61 | " Reverse such that the last highlighting is the first color and thus 62 | " can overwrite other highlighting (sign_column, virtual) 63 | " https://github.com/RRethy/vim-hexokinase/issues/12 64 | call reverse(colorsInfo) 65 | 66 | for [colourMatch,start,end] in colorsInfo 67 | " Create the highlight group 68 | let hl_name = 'hexokinaseHighlight'.strpart(colourMatch, 1) 69 | exe 'hi '.hl_name.' guifg='.colourMatch 70 | for F in g:Hexokinase_highlightCallbacks 71 | call F(lnum, colourMatch, hl_name, start + 1, end) 72 | endfor 73 | endfor 74 | endfor 75 | endf 76 | 77 | fun! hexokinase#tear_down() abort 78 | for F in g:Hexokinase_tearDownCallbacks 79 | call F() 80 | endfor 81 | endf 82 | -------------------------------------------------------------------------------- /autoload/hexokinase/checker.vim: -------------------------------------------------------------------------------- 1 | " Experimental and unused currently 2 | finish 3 | 4 | fun! hexokinase#checker#check() abort 5 | call s:cancel_cur_job() 6 | 7 | let tmpname = hexokinase#utils#tmpname() 8 | let fail = writefile(getbufline(bufnr('%'), 1, '$'), tmpname) 9 | if !fail 10 | let opts = { 11 | \ 'tmpname': tmpname, 12 | \ 'on_exit': function('s:on_exit'), 13 | \ 'bufnr': bufnr('%'), 14 | \ } 15 | let cmd = printf('%s -check=%s ', g:Hexokinase_executable_path, tmpname) 16 | let cmd .= hexokinase#utils#getPatModifications() 17 | if !empty(g:Hexokinase_palettes) 18 | let cmd .= ' -palettes='.join(g:Hexokinase_palettes, ',') 19 | endif 20 | let b:hexokinase_job_id = jobstart(cmd, opts) 21 | endif 22 | endf 23 | 24 | fun! s:on_exit(id, status, event) abort dict 25 | call delete(self.tmpname) 26 | if !a:status 27 | if bufnr('%') == self.bufnr 28 | call hexokinase#v2#scraper#on() 29 | endif 30 | endif 31 | endf 32 | 33 | fun! s:cancel_cur_job() abort 34 | let b:hexokinase_checker_job_id = get(b:, 'hexokinase_checker_job_id', -1) 35 | try 36 | call chanclose(b:hexokinase_checker_job_id) 37 | catch /E900/ 38 | endtry 39 | endf 40 | -------------------------------------------------------------------------------- /autoload/hexokinase/highlighters/background.vim: -------------------------------------------------------------------------------- 1 | let s:isNvim040 = exists('*nvim_buf_add_highlight') 2 | if s:isNvim040 3 | let s:namespace = nvim_create_namespace('') 4 | endif 5 | 6 | if !s:isNvim040 7 | augroup hexokinase_background_autocmds 8 | autocmd! 9 | " TODO figure out how many of these can be cut down on 10 | autocmd BufEnter,BufWinEnter,WinNew,TabNew,BufNew,BufAdd * call s:showhl() 11 | augroup END 12 | 13 | fun! s:showhl() abort 14 | call s:hidehl() 15 | for it in get(b:, 'hexokinase_colours', []) 16 | if has_key(it, 'bg_check') 17 | let id = matchaddpos(it.hlname, it.positions) 18 | call add(w:hexokinase_bg_match_ids, id) 19 | endif 20 | endfor 21 | endf 22 | 23 | fun! s:hidehl() abort 24 | for it in get(w:, 'hexokinase_bg_match_ids', []) 25 | try 26 | call matchdelete(it) 27 | catch /\v(E803|E802)/ 28 | endtry 29 | endfor 30 | let w:hexokinase_bg_match_ids = [] 31 | endf 32 | end 33 | 34 | fun! hexokinase#highlighters#background#highlightv2(bufnr) abort 35 | for it in getbufvar(a:bufnr, 'hexokinase_colours', []) 36 | let it['hlname'] = hexokinase#utils#create_bg_hl(it.hex) 37 | let buflines = getbufline(a:bufnr, it.lnum) 38 | if len(buflines) == 0 39 | continue 40 | endif 41 | let line = buflines[0] 42 | 43 | if s:isNvim040 44 | let positions = [] 45 | 46 | if line[it.end - 1] ==# ')' 47 | let [_, _, first_char] = matchstrpos(line, '(', it.start) 48 | let positions = [ 49 | \ { 50 | \ 'col_start': str2nr(first_char)-1, 51 | \ 'col_end': str2nr(first_char) 52 | \ }, 53 | \ { 54 | \ 'col_start': str2nr(it.end)-1, 55 | \ 'col_end': str2nr(it.end) 56 | \ } 57 | \ ] 58 | elseif line[it.start - 1] ==# '#' 59 | let positions = [ 60 | \ { 61 | \ 'col_start': str2nr(it.start)-1, 62 | \ 'col_end': str2nr(it.start) 63 | \ } 64 | \ ] 65 | else 66 | let positions = [ 67 | \ { 68 | \ 'col_start': str2nr(it.start)-1, 69 | \ 'col_end': str2nr(it.end) 70 | \ } 71 | \ ] 72 | endif 73 | 74 | for pos in positions 75 | call nvim_buf_add_highlight( 76 | \ a:bufnr, 77 | \ s:namespace, 78 | \ it.hlname, 79 | \ str2nr(it.lnum)-1, 80 | \ pos.col_start, 81 | \ pos.col_end, 82 | \ ) 83 | endfor 84 | else 85 | if line[it.end - 1] ==# ')' 86 | let [_, _, first_char] = matchstrpos(line, '(', it.start) 87 | let it['positions'] = [[it.lnum, first_char, 1], [it.lnum, it.end, 1]] 88 | elseif line[it.start - 1] ==# '#' 89 | let it['positions'] = [[it.lnum, it.start, 1]] 90 | else 91 | let it['positions'] = [[it.lnum, it.start, it.end - it.start + 1]] 92 | endif 93 | 94 | let it['bg_check'] = 1 95 | endif 96 | endfor 97 | 98 | if a:bufnr == bufnr('%') && !s:isNvim040 99 | call s:showhl() 100 | endif 101 | endf 102 | 103 | fun! hexokinase#highlighters#background#tearDownv2(bufnr) abort 104 | if s:isNvim040 105 | if !bufexists(a:bufnr) 106 | return 107 | endif 108 | 109 | if exists('*nvim_buf_clear_namespace') 110 | call nvim_buf_clear_namespace(a:bufnr, s:namespace, 0, -1) 111 | endif 112 | else 113 | let b:hexokinase_colours = [] 114 | if a:bufnr == bufnr('%') 115 | call s:hidehl() 116 | endif 117 | endif 118 | endf 119 | 120 | fun! hexokinase#highlighters#background#highlight(lnum, hex, hl_name, start, end) abort 121 | let b:bg_match_ids = get(b:, 'bg_match_ids', []) 122 | if getline(a:lnum)[a:end - 1] ==# ')' 123 | let [_, _, first_char] = matchstrpos(getline(a:lnum), '(', a:start) 124 | call add(b:bg_match_ids, matchaddpos(a:hl_name, [[a:lnum, first_char, 1], [a:lnum, a:end, 1]])) 125 | else 126 | call add(b:bg_match_ids, matchaddpos(a:hl_name, [[a:lnum, a:start, 1]])) 127 | endif 128 | endf 129 | 130 | fun! hexokinase#highlighters#background#tearDown() abort 131 | let b:bg_match_ids = get(b:, 'bg_match_ids', []) 132 | for id in b:bg_match_ids 133 | try 134 | call matchdelete(id) 135 | catch /\v(E803|E802)/ 136 | endtry 137 | endfor 138 | let b:bbgmatch_ids = [] 139 | endf 140 | -------------------------------------------------------------------------------- /autoload/hexokinase/highlighters/backgroundfull.vim: -------------------------------------------------------------------------------- 1 | let s:isNvim040 = exists('*nvim_buf_add_highlight') 2 | if s:isNvim040 3 | let s:namespace = nvim_create_namespace('') 4 | endif 5 | 6 | if !s:isNvim040 7 | augroup hexokinase_backgroundfull_autocmds 8 | autocmd! 9 | " TODO figure out how many of these can be cut down on 10 | autocmd BufEnter,BufWinEnter,WinNew,TabNew,BufNew,BufAdd * call s:showhl() 11 | augroup END 12 | 13 | fun! s:showhl() abort 14 | call s:hidehl() 15 | for it in get(b:, 'hexokinase_colours', []) 16 | if has_key(it, 'bgfull_check') 17 | let id = matchaddpos(it.hlname, it.positions) 18 | call add(w:hexokinase_bgfull_match_ids, id) 19 | endif 20 | endfor 21 | endf 22 | 23 | fun! s:hidehl() abort 24 | for it in get(w:, 'hexokinase_bgfull_match_ids', []) 25 | try 26 | call matchdelete(it) 27 | catch /\v(E803|E802)/ 28 | endtry 29 | endfor 30 | let w:hexokinase_bgfull_match_ids = [] 31 | endf 32 | end 33 | 34 | fun! hexokinase#highlighters#backgroundfull#highlightv2(bufnr) abort 35 | for it in getbufvar(a:bufnr, 'hexokinase_colours', []) 36 | let it['hlname'] = hexokinase#utils#create_bg_hl(it.hex) 37 | if s:isNvim040 38 | call nvim_buf_add_highlight( 39 | \ a:bufnr, 40 | \ s:namespace, 41 | \ it.hlname, 42 | \ str2nr(it.lnum)-1, 43 | \ str2nr(it.start)-1, 44 | \ str2nr(it.end) 45 | \ ) 46 | else 47 | let it['positions'] = [[it.lnum, it.start, it.end - it.start + 1]] 48 | let it['bgfull_check'] = 1 49 | endif 50 | endfor 51 | 52 | if a:bufnr == bufnr('%') && !s:isNvim040 53 | call s:showhl() 54 | endif 55 | endf 56 | 57 | fun! hexokinase#highlighters#backgroundfull#tearDownv2(bufnr) abort 58 | if s:isNvim040 59 | if !bufexists(a:bufnr) 60 | return 61 | endif 62 | 63 | if exists('*nvim_buf_clear_namespace') 64 | call nvim_buf_clear_namespace(a:bufnr, s:namespace, 0, -1) 65 | endif 66 | else 67 | let b:hexokinase_colours = [] 68 | if a:bufnr == bufnr('%') 69 | call s:hidehl() 70 | endif 71 | endif 72 | endf 73 | 74 | fun! hexokinase#highlighters#backgroundfull#highlight(lnum, hex, hl_name, start, end) abort 75 | let b:bgfull_match_ids = get(b:, 'bgfull_match_ids', []) 76 | call add(b:bgfull_match_ids, matchaddpos(a:hl_name, [[a:lnum, a:start, a:end - a:start + 1]])) 77 | endf 78 | 79 | fun! hexokinase#highlighters#backgroundfull#tearDown() abort 80 | let b:bgfull_match_ids = get(b:, 'bgfull_match_ids', []) 81 | for id in b:bgfull_match_ids 82 | try 83 | call matchdelete(id) 84 | catch /\v(E803|E802)/ 85 | endtry 86 | endfor 87 | let b:bgfull_match_ids = [] 88 | endf 89 | -------------------------------------------------------------------------------- /autoload/hexokinase/highlighters/foreground.vim: -------------------------------------------------------------------------------- 1 | let s:isNvim040 = exists('*nvim_buf_add_highlight') 2 | if s:isNvim040 3 | let s:namespace = nvim_create_namespace('') 4 | endif 5 | 6 | if !s:isNvim040 7 | augroup hexokinase_foreground_autocmds 8 | autocmd! 9 | " TODO figure out how many of these can be cut down on 10 | autocmd BufEnter,BufWinEnter,WinNew,TabNew,BufNew,BufAdd * call s:showhl() 11 | augroup END 12 | 13 | fun! s:showhl() abort 14 | call s:hidehl() 15 | for it in get(b:, 'hexokinase_colours', []) 16 | if has_key(it, 'fg_check') 17 | let id = matchaddpos(it.hlname, it.positions) 18 | call add(w:hexokinase_fg_match_ids, id) 19 | endif 20 | endfor 21 | endf 22 | 23 | fun! s:hidehl() abort 24 | for it in get(w:, 'hexokinase_fg_match_ids', []) 25 | try 26 | call matchdelete(it) 27 | catch /\v(E803|E802)/ 28 | endtry 29 | endfor 30 | let w:hexokinase_fg_match_ids = [] 31 | endf 32 | end 33 | 34 | fun! hexokinase#highlighters#foreground#highlightv2(bufnr) abort 35 | for it in getbufvar(a:bufnr, 'hexokinase_colours', []) 36 | let it['hlname'] = hexokinase#utils#create_fg_hl(it.hex) 37 | let buflines = getbufline(a:bufnr, it.lnum) 38 | if len(buflines) == 0 39 | continue 40 | endif 41 | let line = buflines[0] 42 | 43 | if s:isNvim040 44 | let positions = [] 45 | 46 | if line[it.end - 1] ==# ')' 47 | let [_, _, first_char] = matchstrpos(line, '(', it.start) 48 | let positions = [ 49 | \ { 50 | \ 'col_start': str2nr(first_char)-1, 51 | \ 'col_end': str2nr(first_char) 52 | \ }, 53 | \ { 54 | \ 'col_start': str2nr(it.end)-1, 55 | \ 'col_end': str2nr(it.end) 56 | \ } 57 | \ ] 58 | elseif line[it.start - 1] ==# '#' 59 | let positions = [ 60 | \ { 61 | \ 'col_start': str2nr(it.start)-1, 62 | \ 'col_end': str2nr(it.start) 63 | \ } 64 | \ ] 65 | else 66 | let positions = [ 67 | \ { 68 | \ 'col_start': str2nr(it.start)-1, 69 | \ 'col_end': str2nr(it.end) 70 | \ } 71 | \ ] 72 | endif 73 | 74 | for pos in positions 75 | call nvim_buf_add_highlight( 76 | \ a:bufnr, 77 | \ s:namespace, 78 | \ it.hlname, 79 | \ str2nr(it.lnum)-1, 80 | \ pos.col_start, 81 | \ pos.col_end, 82 | \ ) 83 | endfor 84 | else 85 | if line[it.end - 1] ==# ')' 86 | let [_, _, first_char] = matchstrpos(line, '(', it.start) 87 | let it['positions'] = [[it.lnum, first_char, 1], [it.lnum, it.end, 1]] 88 | elseif line[it.start - 1] ==# '#' 89 | let it['positions'] = [[it.lnum, it.start, 1]] 90 | else 91 | let it['positions'] = [[it.lnum, it.start, it.end - it.start + 1]] 92 | endif 93 | 94 | let it['fg_check'] = 1 95 | endif 96 | endfor 97 | 98 | if a:bufnr == bufnr('%') && !s:isNvim040 99 | call s:showhl() 100 | endif 101 | endf 102 | 103 | fun! hexokinase#highlighters#foreground#tearDownv2(bufnr) abort 104 | if s:isNvim040 105 | if !bufexists(a:bufnr) 106 | return 107 | endif 108 | 109 | if exists('*nvim_buf_clear_namespace') 110 | call nvim_buf_clear_namespace(a:bufnr, s:namespace, 0, -1) 111 | endif 112 | else 113 | let b:hexokinase_colours = [] 114 | if a:bufnr == bufnr('%') 115 | call s:hidehl() 116 | endif 117 | endif 118 | endf 119 | 120 | fun! hexokinase#highlighters#foreground#highlight(lnum, hex, hl_name, start, end) abort 121 | let b:fg_match_ids = get(b:, 'fg_match_ids', []) 122 | if getline(a:lnum)[a:end - 1] ==# ')' 123 | let [_, _, first_char] = matchstrpos(getline(a:lnum), '(', a:start) 124 | call add(b:fg_match_ids, matchaddpos(a:hl_name, [[a:lnum, first_char, 1], [a:lnum, a:end, 1]])) 125 | else 126 | call add(b:fg_match_ids, matchaddpos(a:hl_name, [[a:lnum, a:start, 1]])) 127 | endif 128 | endf 129 | 130 | fun! hexokinase#highlighters#foreground#tearDown() abort 131 | let b:fg_match_ids = get(b:, 'fg_match_ids', []) 132 | for id in b:fg_match_ids 133 | try 134 | call matchdelete(id) 135 | catch /\v(E803|E802)/ 136 | endtry 137 | endfor 138 | let b:fg_match_ids = [] 139 | endf 140 | -------------------------------------------------------------------------------- /autoload/hexokinase/highlighters/foregroundfull.vim: -------------------------------------------------------------------------------- 1 | let s:isNvim040 = exists('*nvim_buf_add_highlight') 2 | if s:isNvim040 3 | let s:namespace = nvim_create_namespace('') 4 | endif 5 | 6 | if !s:isNvim040 7 | augroup hexokinase_foregroundfull_autocmds 8 | autocmd! 9 | " TODO figure out how many of these can be cut down on 10 | autocmd BufEnter,BufWinEnter,WinNew,TabNew,BufNew,BufAdd * call s:showhl() 11 | augroup END 12 | 13 | fun! s:showhl() abort 14 | call s:hidehl() 15 | for it in get(b:, 'hexokinase_colours', []) 16 | if has_key(it, 'fgfull_check') 17 | let id = matchaddpos(it.hlname, it.positions) 18 | call add(w:hexokinase_fgfull_match_ids, id) 19 | endif 20 | endfor 21 | endf 22 | 23 | fun! s:hidehl() abort 24 | for it in get(w:, 'hexokinase_fgfull_match_ids', []) 25 | try 26 | call matchdelete(it) 27 | catch /\v(E803|E802)/ 28 | endtry 29 | endfor 30 | let w:hexokinase_fgfull_match_ids = [] 31 | endf 32 | end 33 | 34 | fun! hexokinase#highlighters#foregroundfull#highlightv2(bufnr) abort 35 | for it in getbufvar(a:bufnr, 'hexokinase_colours', []) 36 | let it['hlname'] = hexokinase#utils#create_fg_hl(it.hex) 37 | if s:isNvim040 38 | call nvim_buf_add_highlight( 39 | \ a:bufnr, 40 | \ s:namespace, 41 | \ it.hlname, 42 | \ str2nr(it.lnum)-1, 43 | \ str2nr(it.start)-1, 44 | \ str2nr(it.end) 45 | \ ) 46 | else 47 | let it['positions'] = [[it.lnum, it.start, it.end - it.start + 1]] 48 | let it['fgfull_check'] = 1 49 | endif 50 | endfor 51 | 52 | if a:bufnr == bufnr('%') && !s:isNvim040 53 | call s:showhl() 54 | endif 55 | endf 56 | 57 | fun! hexokinase#highlighters#foregroundfull#tearDownv2(bufnr) abort 58 | if s:isNvim040 59 | if !bufexists(a:bufnr) 60 | return 61 | endif 62 | 63 | if exists('*nvim_buf_clear_namespace') 64 | call nvim_buf_clear_namespace(a:bufnr, s:namespace, 0, -1) 65 | endif 66 | else 67 | let b:hexokinase_colours = [] 68 | if a:bufnr == bufnr('%') 69 | call s:hidehl() 70 | endif 71 | endif 72 | endf 73 | 74 | fun! hexokinase#highlighters#foregroundfull#highlight(lnum, hex, hl_name, start, end) abort 75 | let b:fgfull_match_ids = get(b:, 'fgfull_match_ids', []) 76 | call add(b:fgfull_match_ids, matchaddpos(a:hl_name, [[a:lnum, a:start, a:end - a:start + 1]])) 77 | endf 78 | 79 | fun! hexokinase#highlighters#foregroundfull#tearDown() abort 80 | let b:fgfull_match_ids = get(b:, 'fgfull_match_ids', []) 81 | for id in b:fgfull_match_ids 82 | try 83 | call matchdelete(id) 84 | catch /\v(E803|E802)/ 85 | endtry 86 | endfor 87 | let b:fgfull_match_ids = [] 88 | endf 89 | -------------------------------------------------------------------------------- /autoload/hexokinase/highlighters/sign_column.vim: -------------------------------------------------------------------------------- 1 | let s:group_prefix = 'hexokinase-sign_column' 2 | 3 | fun! s:signs_api_hl(bufnr) abort 4 | let n = 0 5 | for it in getbufvar(a:bufnr, 'hexokinase_colours', []) 6 | let it['hlname'] = hexokinase#utils#create_fg_hl(it.hex) 7 | 8 | let sign_name = it.hlname . 'sign' 9 | let sign_id = 4000 + n 10 | let n += 1 11 | call sign_define(sign_name, 12 | \ { 13 | \ 'text': g:Hexokinase_signIcon, 14 | \ 'texthl': it.hlname, 15 | \ } 16 | \ ) 17 | call sign_place( 18 | \ sign_id, 19 | \ s:group_prefix.string(a:bufnr), 20 | \ sign_name, 21 | \ a:bufnr, 22 | \ { 'lnum': it.lnum } 23 | \ ) 24 | endfor 25 | endf 26 | 27 | fun! s:signs_api_tear_down(bufnr) abort 28 | if !bufexists(a:bufnr) 29 | return 30 | endif 31 | 32 | call sign_unplace(s:group_prefix.string(a:bufnr)) 33 | endf 34 | 35 | fun! s:signs_command_hl(bufnr) abort 36 | let sign_ids = [] 37 | for it in getbufvar(a:bufnr, 'hexokinase_colours', []) 38 | let it['hlname'] = hexokinase#utils#create_fg_hl(it.hex) 39 | 40 | let sign_name = it.hlname . 'sign' 41 | let sign_id = 4000 + it.lnum 42 | exe 'sign define ' . sign_name . ' text=' . g:Hexokinase_signIcon . ' texthl=' . it.hlname 43 | exe 'sign place ' . sign_id . ' line=' . it.lnum . ' name=' . sign_name . ' buffer=' . a:bufnr 44 | 45 | call add(sign_ids, sign_id) 46 | endfor 47 | call setbufvar(a:bufnr, 'sign_ids', sign_ids) 48 | endf 49 | 50 | fun! s:signs_command_tear_down(bufnr) abort 51 | if !bufexists(a:bufnr) 52 | return 53 | endif 54 | 55 | let sign_ids = getbufvar(a:bufnr, 'sign_ids', []) 56 | for sign_id in sign_ids 57 | exe 'sign unplace ' . sign_id . ' buffer=' . a:bufnr 58 | endfor 59 | 60 | call setbufvar(a:bufnr, 'sign_ids', []) 61 | endf 62 | 63 | fun! hexokinase#highlighters#sign_column#highlightv2(bufnr) abort 64 | if exists('*sign_place') 65 | call s:signs_api_hl(a:bufnr) 66 | else 67 | call s:signs_command_hl(a:bufnr) 68 | endif 69 | endf 70 | 71 | fun! hexokinase#highlighters#sign_column#tearDownv2(bufnr) abort 72 | if exists('*sign_place') 73 | call s:signs_api_tear_down(a:bufnr) 74 | else 75 | call s:signs_command_tear_down(a:bufnr) 76 | endif 77 | endf 78 | 79 | fun! hexokinase#highlighters#sign_column#highlight(lnum, hex, hl_name, start, end) abort 80 | let b:sign_ids = get(b:, 'sign_ids', []) 81 | 82 | let sign_name = a:hl_name . 'sign' 83 | let sign_id = 4000 + a:lnum 84 | exe 'sign define ' . sign_name . ' text=' . g:Hexokinase_signIcon . ' texthl=' . a:hl_name 85 | exe 'sign place ' . sign_id . ' line=' . a:lnum . ' name=' . sign_name . ' buffer=' . bufnr('%') 86 | 87 | call add(b:sign_ids, sign_id) 88 | endf 89 | 90 | fun! hexokinase#highlighters#sign_column#tearDown() abort 91 | call hexokinase#highlighters#sign_column#tearDownv2(bufnr('%')) 92 | endf 93 | -------------------------------------------------------------------------------- /autoload/hexokinase/highlighters/virtual.vim: -------------------------------------------------------------------------------- 1 | if exists('*nvim_create_namespace') 2 | let s:namespace = nvim_create_namespace('') 3 | else 4 | echoerr 'virtual highlighting only works with Neovim v0.3.2 - please upgrade' 5 | finish 6 | endif 7 | 8 | fun! hexokinase#highlighters#virtual#highlightv2(bufnr) abort 9 | for it in getbufvar(a:bufnr, 'hexokinase_colours', []) 10 | let it['hlname'] = hexokinase#utils#create_fg_hl(it.hex) 11 | 12 | let chunks = [[g:Hexokinase_virtualText, it.hlname]] 13 | if exists('*nvim_buf_get_virtual_text') 14 | let chunks += nvim_buf_get_virtual_text(a:bufnr, it.lnum - 1) 15 | elseif exists('*nvim_buf_get_extmarks') 16 | let set_chunks = nvim_buf_get_extmarks( 17 | \ a:bufnr, 18 | \ s:namespace, 19 | \ [it.lnum - 1, 0], 20 | \ [it.lnum - 1, 0], 21 | \ {'details': v:true} 22 | \ ) 23 | if !empty(set_chunks) 24 | let chunks += set_chunks[0][3].virt_text 25 | endif 26 | endif 27 | call nvim_buf_set_virtual_text( 28 | \ a:bufnr, 29 | \ s:namespace, 30 | \ it.lnum - 1, 31 | \ chunks, 32 | \ {} 33 | \ ) 34 | endfor 35 | endf 36 | 37 | fun! hexokinase#highlighters#virtual#tearDownv2(bufnr) abort 38 | if !bufexists(a:bufnr) 39 | return 40 | endif 41 | 42 | if exists('*nvim_buf_clear_namespace') 43 | call nvim_buf_clear_namespace(a:bufnr, s:namespace, 0, -1) 44 | endif 45 | endf 46 | 47 | fun! hexokinase#highlighters#virtual#highlight(lnum, hex, hl_name, start, end) abort 48 | if exists('*nvim_buf_set_virtual_text') 49 | let chunks = [[g:Hexokinase_virtualText, a:hl_name]] 50 | if exists('*nvim_buf_get_virtual_text') 51 | let chunks += nvim_buf_get_virtual_text(bufnr('%'), a:lnum - 1) 52 | endif 53 | call nvim_buf_set_virtual_text( 54 | \ bufnr('%'), 55 | \ s:namespace, 56 | \ a:lnum - 1, 57 | \ chunks, 58 | \ {} 59 | \ ) 60 | endif 61 | endf 62 | 63 | fun! hexokinase#highlighters#virtual#tearDown() abort 64 | call hexokinase#highlighters#virtual#tearDownv2(bufnr('%')) 65 | endf 66 | -------------------------------------------------------------------------------- /autoload/hexokinase/patterns/colour_names.vim: -------------------------------------------------------------------------------- 1 | " see: https://www.w3schools.com/colors/colors_names.asp // 2019-04-11 2 | let s:colours = { 3 | \ 'aliceblue': '#f0f8ff', 4 | \ 'antiquewhite': '#faebd7', 5 | \ 'aqua': '#00ffff', 6 | \ 'aquamarine': '#7fffd4', 7 | \ 'azure': '#f0ffff', 8 | \ 'beige': '#f5f5dc', 9 | \ 'bisque': '#ffe4c4', 10 | \ 'black': '#000000', 11 | \ 'blanchedalmond': '#ffebcd', 12 | \ 'blue': '#0000ff', 13 | \ 'blueviolet': '#8a2be2', 14 | \ 'brown': '#a52a2a', 15 | \ 'burlywood': '#deb887', 16 | \ 'cadetblue': '#5f9ea0', 17 | \ 'chartreuse': '#7fff00', 18 | \ 'chocolate': '#d2691e', 19 | \ 'coral': '#ff7f50', 20 | \ 'cornflowerblue': '#6495ed', 21 | \ 'cornsilk': '#fff8dc', 22 | \ 'crimson': '#dc143c', 23 | \ 'cyan': '#00ffff', 24 | \ 'darkblue': '#00008b', 25 | \ 'darkcyan': '#008b8b', 26 | \ 'darkgoldenrod': '#b8860b', 27 | \ 'darkgray': '#a9a9a9', 28 | \ 'darkgrey': '#a9a9a9', 29 | \ 'darkgreen': '#006400', 30 | \ 'darkkhaki': '#bdb76b', 31 | \ 'darkmagenta': '#8b008b', 32 | \ 'darkolivegreen': '#556b2f', 33 | \ 'darkorange': '#ff8c00', 34 | \ 'darkorchid': '#9932cc', 35 | \ 'darkred': '#8b0000', 36 | \ 'darksalmon': '#e9967a', 37 | \ 'darkseagreen': '#8fbc8f', 38 | \ 'darkslateblue': '#483d8b', 39 | \ 'darkslategray': '#2f4f4f', 40 | \ 'darkslategrey': '#2f4f4f', 41 | \ 'darkturquoise': '#00ced1', 42 | \ 'darkviolet': '#9400d3', 43 | \ 'deeppink': '#ff1493', 44 | \ 'deepskyblue': '#00bfff', 45 | \ 'dimgray': '#696969', 46 | \ 'dimgrey': '#696969', 47 | \ 'dodgerblue': '#1e90ff', 48 | \ 'firebrick': '#b22222', 49 | \ 'floralwhite': '#fffaf0', 50 | \ 'forestgreen': '#228b22', 51 | \ 'fuchsia': '#ff00ff', 52 | \ 'gainsboro': '#dcdcdc', 53 | \ 'ghostwhite': '#f8f8ff', 54 | \ 'gold': '#ffd700', 55 | \ 'goldenrod': '#daa520', 56 | \ 'gray': '#808080', 57 | \ 'grey': '#808080', 58 | \ 'green': '#008000', 59 | \ 'greenyellow': '#adff2f', 60 | \ 'honeydew': '#f0fff0', 61 | \ 'hotpink': '#ff69b4', 62 | \ 'indianred': '#cd5c5c', 63 | \ 'indigo': '#4b0082', 64 | \ 'ivory': '#fffff0', 65 | \ 'khaki': '#f0e68c', 66 | \ 'lavender': '#e6e6fa', 67 | \ 'lavenderblush': '#fff0f5', 68 | \ 'lawngreen': '#7cfc00', 69 | \ 'lemonchiffon': '#fffacd', 70 | \ 'lightblue': '#add8e6', 71 | \ 'lightcoral': '#f08080', 72 | \ 'lightcyan': '#e0ffff', 73 | \ 'lightgoldenrodyellow': '#fafad2', 74 | \ 'lightgray': '#d3d3d3', 75 | \ 'lightgrey': '#d3d3d3', 76 | \ 'lightgreen': '#90ee90', 77 | \ 'lightpink': '#ffb6c1', 78 | \ 'lightsalmon': '#ffa07a', 79 | \ 'lightseagreen': '#20b2aa', 80 | \ 'lightskyblue': '#87cefa', 81 | \ 'lightslategray': '#778899', 82 | \ 'lightslategrey': '#778899', 83 | \ 'lightsteelblue': '#b0c4de', 84 | \ 'lightyellow': '#ffffe0', 85 | \ 'lime': '#00ff00', 86 | \ 'limegreen': '#32cd32', 87 | \ 'linen': '#faf0e6', 88 | \ 'magenta': '#ff00ff', 89 | \ 'maroon': '#800000', 90 | \ 'mediumaquamarine': '#66cdaa', 91 | \ 'mediumblue': '#0000cd', 92 | \ 'mediumorchid': '#ba55d3', 93 | \ 'mediumpurple': '#9370db', 94 | \ 'mediumseagreen': '#3cb371', 95 | \ 'mediumslateblue': '#7b68ee', 96 | \ 'mediumspringgreen': '#00fa9a', 97 | \ 'mediumturquoise': '#48d1cc', 98 | \ 'mediumvioletred': '#c71585', 99 | \ 'midnightblue': '#191970', 100 | \ 'mintcream': '#f5fffa', 101 | \ 'mistyrose': '#ffe4e1', 102 | \ 'moccasin': '#ffe4b5', 103 | \ 'navajowhite': '#ffdead', 104 | \ 'navy': '#000080', 105 | \ 'oldlace': '#fdf5e6', 106 | \ 'olive': '#808000', 107 | \ 'olivedrab': '#6b8e23', 108 | \ 'orange': '#ffa500', 109 | \ 'orangered': '#ff4500', 110 | \ 'orchid': '#da70d6', 111 | \ 'palegoldenrod': '#eee8aa', 112 | \ 'palegreen': '#98fb98', 113 | \ 'paleturquoise': '#afeeee', 114 | \ 'palevioletred': '#db7093', 115 | \ 'papayawhip': '#ffefd5', 116 | \ 'peachpuff': '#ffdab9', 117 | \ 'peru': '#cd853f', 118 | \ 'pink': '#ffc0cb', 119 | \ 'plum': '#dda0dd', 120 | \ 'powderblue': '#b0e0e6', 121 | \ 'purple': '#800080', 122 | \ 'rebeccapurple': '#663399', 123 | \ 'red': '#ff0000', 124 | \ 'rosybrown': '#bc8f8f', 125 | \ 'royalblue': '#4169e1', 126 | \ 'saddlebrown': '#8b4513', 127 | \ 'salmon': '#fa8072', 128 | \ 'sandybrown': '#f4a460', 129 | \ 'seagreen': '#2e8b57', 130 | \ 'seashell': '#fff5ee', 131 | \ 'sienna': '#a0522d', 132 | \ 'silver': '#c0c0c0', 133 | \ 'skyblue': '#87ceeb', 134 | \ 'slateblue': '#6a5acd', 135 | \ 'slategray': '#708090', 136 | \ 'slategrey': '#708090', 137 | \ 'snow': '#fffafa', 138 | \ 'springgreen': '#00ff7f', 139 | \ 'steelblue': '#4682b4', 140 | \ 'tan': '#d2b48c', 141 | \ 'teal': '#008080', 142 | \ 'thistle': '#d8bfd8', 143 | \ 'tomato': '#ff6347', 144 | \ 'turquoise': '#40e0d0', 145 | \ 'violet': '#ee82ee', 146 | \ 'wheat': '#f5deb3', 147 | \ 'white': '#ffffff', 148 | \ 'whitesmoke': '#f5f5f5', 149 | \ 'yellow': '#ffff00', 150 | \ 'yellowgreen': '#9acd32' 151 | \ } 152 | 153 | function! hexokinase#patterns#colour_names#get_pattern() abort 154 | return '\c\<\(' . join(keys(s:colours), '\|') . '\)\>' 155 | endfunction 156 | 157 | function! hexokinase#patterns#colour_names#process(str) abort 158 | let str_lcase = tolower(a:str) 159 | if has_key(s:colours, str_lcase) 160 | return s:colours[str_lcase] 161 | else 162 | return '' 163 | endif 164 | endfunction 165 | -------------------------------------------------------------------------------- /autoload/hexokinase/patterns/full_hex.vim: -------------------------------------------------------------------------------- 1 | fun! hexokinase#patterns#full_hex#get_pattern() abort 2 | return '#\x\{6}' 3 | endf 4 | 5 | fun! hexokinase#patterns#full_hex#process(str) abort 6 | return a:str 7 | endf 8 | -------------------------------------------------------------------------------- /autoload/hexokinase/patterns/rgb.vim: -------------------------------------------------------------------------------- 1 | let s:REGEX_NUM = '\d\{1,3}' 2 | let s:REGEX_PERCENTAGE = s:REGEX_NUM.'%' 3 | 4 | fun! hexokinase#patterns#rgb#get_pattern() abort 5 | let val = '\('.s:REGEX_NUM.'\|'.s:REGEX_PERCENTAGE.'\)' 6 | let _ = '\s*' 7 | return 'rgb('._.val._.','._.val._.','._.val._.')' 8 | endf 9 | 10 | fun! hexokinase#patterns#rgb#process(str) abort 11 | let [r, g, b] = hexokinase#patterns#rgb#rgb_str_to_nums(a:str) 12 | if !hexokinase#utils#valid_rgb([r, g, b]) 13 | return '' 14 | endif 15 | return hexokinase#utils#rgb_to_hex([r, g, b]) 16 | endf 17 | 18 | fun! hexokinase#patterns#rgb#rgb_str_to_nums(rgb_str) abort 19 | let r = s:get_formatted_value('(', ',', a:rgb_str) 20 | let g = s:get_formatted_value(',', ',', a:rgb_str) 21 | let b = s:get_formatted_value(',', ')', a:rgb_str) 22 | return [r, g, b] 23 | endf 24 | 25 | fun! s:get_formatted_value(prefix, postfix, str) abort 26 | let _ = '\s*' 27 | if match(a:str, a:prefix._.s:REGEX_NUM._.a:postfix) != -1 28 | return str2nr(matchstr(a:str, a:prefix._.'\zs'.s:REGEX_NUM.'\ze'._.a:postfix)) 29 | else 30 | return str2nr(matchstr(a:str, a:prefix._.'\zs'.s:REGEX_NUM.'\ze'.'%'._.a:postfix)) * 255 / 100 31 | endif 32 | endf 33 | -------------------------------------------------------------------------------- /autoload/hexokinase/patterns/rgba.vim: -------------------------------------------------------------------------------- 1 | let s:REGEX_NUM = '\d\{1,3}' 2 | let s:REGEX_PERCENTAGE = s:REGEX_NUM.'%' 3 | 4 | fun! hexokinase#patterns#rgba#get_pattern() abort 5 | let val = '\('.s:REGEX_NUM.'\|'.s:REGEX_PERCENTAGE.'\)' 6 | let regex_alpha = '\([01]\|[01]\.\d\)' 7 | let _ = '\s*' 8 | return 'rgba('._.val._.','._.val._.','._.val._.','._.regex_alpha._.')' 9 | endf 10 | 11 | fun! hexokinase#patterns#rgba#process(str) abort 12 | let val = '\('.s:REGEX_NUM.'\|'.s:REGEX_PERCENTAGE.'\)' 13 | let _ = '\s*' 14 | let [old_r, old_g, old_b] = hexokinase#patterns#rgb#rgb_str_to_nums( 15 | \ matchstr(a:str, '('._.val._.','._.val._.','._.val._) . ')' 16 | \ ) 17 | let alpha = str2float(matchstr(a:str, ',\s*\zs\([01]\|[01]\.\d\)\ze\s*)')) 18 | let alpha = alpha > 1.0 ? 1.0 : alpha 19 | if !hexokinase#utils#valid_rgb([old_r, old_g, old_b]) || alpha == 0.0 20 | return '' 21 | endif 22 | 23 | return hexokinase#utils#rgb_to_hex( 24 | \ hexokinase#utils#apply_alpha_to_rgb( 25 | \ [old_r, old_g, old_b], alpha 26 | \ ) 27 | \) 28 | endf 29 | -------------------------------------------------------------------------------- /autoload/hexokinase/patterns/triple_hex.vim: -------------------------------------------------------------------------------- 1 | fun! hexokinase#patterns#triple_hex#get_pattern() abort 2 | return '\<#\x\{3}\>' 3 | endf 4 | 5 | fun! hexokinase#patterns#triple_hex#process(str) abort 6 | return '#' . a:str[1] . a:str[1] . a:str[2] . a:str[2] . a:str[3] . a:str[3] 7 | endf 8 | -------------------------------------------------------------------------------- /autoload/hexokinase/utils.vim: -------------------------------------------------------------------------------- 1 | let s:hexadecimals = ['0', '1', '2', '3', 2 | \ '4', '5', '6', '7', 3 | \ '8', '9', 'A', 'B', 4 | \ 'C', 'D', 'E', 'F'] 5 | 6 | fun! hexokinase#utils#get_colour_pattern(patterns_list) abort 7 | return '\%\(' . join(a:patterns_list, '\|') . '\)' 8 | endf 9 | 10 | " Combine the filetype specific pattern/processor map with the global one 11 | fun! hexokinase#utils#get_pat_proc_map() abort 12 | let pattern_processor_map = {} 13 | if has_key(g:Hexokinase_ft_patterns, &filetype) 14 | call extend(pattern_processor_map, g:Hexokinase_ft_patterns[&filetype]) 15 | endif 16 | call extend(pattern_processor_map, g:Hexokinase_patterns) 17 | return pattern_processor_map 18 | endf 19 | 20 | " rgbList should be a list of numbers 21 | fun! hexokinase#utils#rgb_to_hex(rgbList) abort 22 | let r = a:rgbList[0] 23 | let g = a:rgbList[1] 24 | let b = a:rgbList[2] 25 | let hex = '#' 26 | let hex .= s:hexadecimals[r / 16] 27 | let hex .= s:hexadecimals[r % 16] 28 | let hex .= s:hexadecimals[g / 16] 29 | let hex .= s:hexadecimals[g % 16] 30 | let hex .= s:hexadecimals[b / 16] 31 | let hex .= s:hexadecimals[b % 16] 32 | return hex 33 | endf 34 | 35 | " returns a list of numbers 36 | fun! hexokinase#utils#hex_to_rgb(hex) abort 37 | let raw_hex = [0, 0, 0, 0, 0, 0] 38 | for i in range(1, 6) 39 | let raw_hex[i - 1] = index(s:hexadecimals, toupper(a:hex[i])) 40 | endfor 41 | let r = (raw_hex[0] * 16) + raw_hex[1] 42 | let g = (raw_hex[2] * 16) + raw_hex[3] 43 | let b = (raw_hex[4] * 16) + raw_hex[5] 44 | return [r, g, b] 45 | endf 46 | 47 | fun! hexokinase#utils#get_background_rgb() abort 48 | return hexokinase#utils#hex_to_rgb(hexokinase#utils#get_background_hex()) 49 | endf 50 | 51 | fun! hexokinase#utils#get_background_hex() abort 52 | if !empty(get(g:, 'Hexokinase_alpha_bg', '')) 53 | return g:Hexokinase_alpha_bg 54 | elseif len(g:Hexokinase_highlighters) == 1 && g:Hexokinase_highlighters[0] ==# 'sign_column' 55 | return synIDattr(hlID('SignColumn'), 'bg') 56 | else 57 | return synIDattr(hlID('Normal'), 'bg') 58 | endif 59 | endf 60 | 61 | fun! hexokinase#utils#valid_rgb(rgbList) abort 62 | let [r, g, b] = a:rgbList 63 | if r > 255 || r < 0 || g > 255 || g < 0 || b > 255 || b < 0 64 | return 0 65 | else 66 | return 1 67 | endif 68 | endf 69 | 70 | fun! hexokinase#utils#apply_alpha_to_rgb(primary_rgb, alpha) abort 71 | let [bg_r, bg_g, bg_b] = hexokinase#utils#get_background_rgb() 72 | let [old_r, old_g, old_b] = a:primary_rgb 73 | 74 | let new_r = float2nr(bg_r + ((old_r - bg_r) * a:alpha)) 75 | let new_g = float2nr(bg_g + ((old_g - bg_g) * a:alpha)) 76 | let new_b = float2nr(bg_b + ((old_b - bg_b) * a:alpha)) 77 | return [new_r, new_g, new_b] 78 | endf 79 | 80 | fun! hexokinase#utils#tmpname() abort 81 | let l:clear_tempdir = 0 82 | 83 | if exists('$TMPDIR') && empty($TMPDIR) 84 | let l:clear_tempdir = 1 85 | let $TMPDIR = '/tmp' 86 | endif 87 | 88 | try 89 | let l:name = tempname() 90 | finally 91 | if l:clear_tempdir 92 | let $TMPDIR = '' 93 | endif 94 | endtry 95 | 96 | return l:name 97 | endf 98 | 99 | fun! hexokinase#utils#getPatModifications() abort 100 | if has_key(g:Hexokinase_ftOptOutPatterns, &filetype) 101 | let dp = g:Hexokinase_ftOptOutPatterns[&filetype] 102 | if type(dp) == 1 103 | return ['-dp', substitute(dp, '\s', '', 'g')] 104 | elseif type(dp) == 3 105 | return ['-dp', join(dp, ',')] 106 | else 107 | echohl Error | echom printf('ERROR: g:Hexokinase_ftOptOutPatterns[%s] must be a string or a list', &filetype) | echohl None 108 | endif 109 | elseif has_key(g:Hexokinase_ftOptInPatterns, &filetype) 110 | let ep = g:Hexokinase_ftOptInPatterns[&filetype] 111 | if type(ep) == 1 112 | return ['-ep', substitute(ep, '\s', '', 'g')] 113 | elseif type(ep) == 3 114 | return ['-ep', join(ep, ',')] 115 | else 116 | echohl Error | echom printf('ERROR: g:Hexokinase_ftOptInPatterns[%s] must be a string or a list', &filetype) | echohl None 117 | endif 118 | elseif !empty(g:Hexokinase_optOutPatterns) 119 | if type(g:Hexokinase_optOutPatterns) == 1 120 | return ['-dp', substitute(g:Hexokinase_optOutPatterns, '\s', '', 'g')] 121 | elseif type(g:Hexokinase_optOutPatterns) == 3 122 | return ['-dp', join(g:Hexokinase_optOutPatterns, ',')] 123 | else 124 | echohl Error | echom 'ERROR: g:Hexokinase_optOutPatterns must be a string or a list' | echohl None 125 | endif 126 | elseif !empty(g:Hexokinase_optInPatterns) 127 | if type(g:Hexokinase_optInPatterns) == 1 128 | return ['-ep', substitute(g:Hexokinase_optInPatterns, '\s', '', 'g')] 129 | elseif type(g:Hexokinase_optInPatterns) == 3 130 | return ['-ep', join(g:Hexokinase_optInPatterns, ',')] 131 | else 132 | echohl Error | echom 'ERROR: g:Hexokinase_optInPatterns must be a string or a list' | echohl None 133 | endif 134 | endif 135 | return [] 136 | endf 137 | 138 | fun! hexokinase#utils#create_fg_hl(hex) abort 139 | let hlname = 'v2hexokinaseHighlight'.strpart(a:hex, 1) 140 | exe 'hi '.hlname.' guifg='.a:hex 141 | return hlname 142 | endf 143 | 144 | fun! hexokinase#utils#create_bg_hl(hex) abort 145 | let hlname = 'v2hexokinaseHighlight_withfg'.strpart(a:hex, 1) 146 | let [r, g, b] = hexokinase#utils#hex_to_rgb(a:hex) 147 | " This calculation is from the following: 148 | " https://www.w3.org/TR/WCAG20/#relativeluminancedef 149 | if 0.2126 * r + 0.7152 * g + 0.0722 * b > 179 150 | let fg = '#000000' 151 | else 152 | let fg = '#ffffff' 153 | endif 154 | exe 'hi '.hlname.' guibg='.a:hex.' guifg='.fg 155 | return hlname 156 | endf 157 | -------------------------------------------------------------------------------- /autoload/hexokinase/v1.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | 3 | fun! hexokinase#v1#setup() abort 4 | if has('nvim') 5 | let g:Hexokinase_highlighters = get(g:, 'Hexokinase_highlighters', ['virtual']) 6 | else 7 | let g:Hexokinase_highlighters = get(g:, 'Hexokinase_highlighters', ['sign_column']) 8 | endif 9 | 10 | let g:Hexokinase_virtualText = get(g:, 'Hexokinase_virtualText', '■') 11 | let g:Hexokinase_signIcon = get(g:, 'Hexokinase_signIcon', '■') 12 | 13 | " initialize various patterns that are supported by default 14 | let g:Hexokinase_optInPatterns = get(g:, 'Hexokinase_optInPatterns', ['full_hex', 'triple_hex', 'rgb', 'rgba']) 15 | let g:Hexokinase_patterns = get(g:, 'Hexokinase_patterns', {}) 16 | for pat in g:Hexokinase_optInPatterns 17 | if pat ==# 'full_hex' 18 | let g:Hexokinase_patterns[hexokinase#patterns#full_hex#get_pattern()] = function('hexokinase#patterns#full_hex#process') 19 | elseif pat ==# 'triple_hex' 20 | let g:Hexokinase_patterns[hexokinase#patterns#triple_hex#get_pattern()] = function('hexokinase#patterns#triple_hex#process') 21 | elseif pat ==# 'rgb' 22 | let g:Hexokinase_patterns[hexokinase#patterns#rgb#get_pattern()] = function('hexokinase#patterns#rgb#process') 23 | elseif pat ==# 'rgba' 24 | let g:Hexokinase_patterns[hexokinase#patterns#rgba#get_pattern()] = function('hexokinase#patterns#rgba#process') 25 | elseif pat =~# 'colou\?r_names' 26 | let g:Hexokinase_patterns[hexokinase#patterns#colour_names#get_pattern()] = function('hexokinase#patterns#colour_names#process') 27 | endif 28 | endfor 29 | 30 | let g:Hexokinase_ft_patterns = get(g:, 'Hexokinase_ft_patterns', {}) 31 | 32 | let g:Hexokinase_builtinHighlighters = get(g:, 'Hexokinase_builtinHighlighters', ['virtual', 'sign_column', 'background', 'foreground', 'foregroundfull']) 33 | 34 | " initialize various highlighters 35 | let g:Hexokinase_highlightCallbacks = get(g:, 'Hexokinase_highlightCallbacks', []) 36 | let g:Hexokinase_tearDownCallbacks = get(g:, 'Hexokinase_tearDownCallbacks', []) 37 | for mode in g:Hexokinase_highlighters 38 | if index(g:Hexokinase_builtinHighlighters, mode) >= 0 39 | call add(g:Hexokinase_highlightCallbacks, function('hexokinase#highlighters#' . mode . '#highlight')) 40 | call add(g:Hexokinase_tearDownCallbacks, function('hexokinase#highlighters#' . mode . '#tearDown')) 41 | endif 42 | endfor 43 | 44 | command! HexokinaseToggle call hexokinase#toggle_scraping() 45 | command! HexokinaseRefresh call hexokinase#tear_down() | call hexokinase#scrape_colours() 46 | 47 | let g:Hexokinase_refreshEvents = get(g:, 'Hexokinase_refreshEvents', ['BufWritePost']) 48 | let g:Hexokinase_ftAutoload = get(g:, 'Hexokinase_ftAutoload', []) 49 | 50 | if has('autocmd') 51 | augroup hexokinase_autocmds 52 | autocmd! 53 | for event in g:Hexokinase_refreshEvents 54 | exe 'autocmd '.event.' * call s:on_refresh_event()' 55 | endfor 56 | if !empty(g:Hexokinase_ftAutoload) 57 | exe 'autocmd FileType '.join(g:Hexokinase_ftAutoload, ',').' call hexokinase#on_autoload_ft_set()' 58 | endif 59 | augroup END 60 | endif 61 | 62 | fun! s:on_refresh_event() abort 63 | if exists('b:hexokinase_scraper_on') && b:hexokinase_scraper_on 64 | HexokinaseRefresh 65 | endif 66 | endf 67 | 68 | fun! s:toggle() abort 69 | HexokinaseToggle 70 | endf 71 | endf 72 | -------------------------------------------------------------------------------- /autoload/hexokinase/v2.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | 3 | fun! hexokinase#v2#setup() abort 4 | if has('nvim') 5 | let g:Hexokinase_highlighters = get(g:, 'Hexokinase_highlighters', ['virtual']) 6 | else 7 | let g:Hexokinase_highlighters = get(g:, 'Hexokinase_highlighters', ['sign_column']) 8 | endif 9 | if len(g:Hexokinase_highlighters) == 1 && g:Hexokinase_highlighters[0] == 'sign_column' && &signcolumn == 'no' 10 | echom "[vim-hexokinase] You seem to be using sign_column for highlighting but 'signcolumn' is set to 'no', try enabling it to see colours." 11 | endif 12 | 13 | let g:Hexokinase_virtualText = get(g:, 'Hexokinase_virtualText', '■') 14 | let g:Hexokinase_signIcon = get(g:, 'Hexokinase_signIcon', '■') 15 | 16 | let g:Hexokinase_optOutPatterns = get(g:, 'Hexokinase_optOutPatterns', '') 17 | let g:Hexokinase_optInPatterns = get(g:, 'Hexokinase_optInPatterns', 'full_hex,rgb,rgba,hsl,hsla,colour_names') 18 | let g:Hexokinase_ftOptOutPatterns = get(g:, 'Hexokinase_ftOptOutPatterns', {}) 19 | let g:Hexokinase_ftOptInPatterns = get(g:, 'Hexokinase_ftOptInPatterns', {}) 20 | let g:Hexokinase_palettes = get(g:, 'Hexokinase_palettes', []) 21 | 22 | let g:Hexokinase_builtinHighlighters = get(g:, 'Hexokinase_builtinHighlighters', [ 23 | \ 'virtual', 24 | \ 'sign_column', 25 | \ 'background', 26 | \ 'backgroundfull', 27 | \ 'foreground', 28 | \ 'foregroundfull' 29 | \ ]) 30 | let g:Hexokinase_highlightCallbacks = get(g:, 'Hexokinase_highlightCallbacks', []) 31 | let g:Hexokinase_tearDownCallbacks = get(g:, 'Hexokinase_tearDownCallbacks', []) 32 | for highlighter in g:Hexokinase_highlighters 33 | if index(g:Hexokinase_builtinHighlighters, highlighter) >= 0 34 | call add(g:Hexokinase_highlightCallbacks, function('hexokinase#highlighters#' . highlighter . '#highlightv2')) 35 | call add(g:Hexokinase_tearDownCallbacks, function('hexokinase#highlighters#' . highlighter . '#tearDownv2')) 36 | endif 37 | endfor 38 | 39 | command! HexokinaseToggle call hexokinase#v2#scraper#toggle() 40 | command! HexokinaseTurnOn call hexokinase#v2#scraper#on() 41 | command! HexokinaseTurnOff call hexokinase#v2#scraper#off() 42 | 43 | let g:Hexokinase_refreshEvents = get(g:, 'Hexokinase_refreshEvents', ['TextChanged', 'InsertLeave', 'BufRead']) 44 | let g:Hexokinase_ftDisabled = get(g:, 'Hexokinase_ftDisabled', []) 45 | let g:Hexokinase_termDisabled = get(g:, 'Hexokinase_termDisabled', 0) 46 | 47 | augroup hexokinase_autocmds 48 | autocmd! 49 | exe 'autocmd '.join(g:Hexokinase_refreshEvents, ',').' * call s:on_refresh_event()' 50 | autocmd ColorScheme * call s:on_refresh_event() 51 | augroup END 52 | endf 53 | 54 | fun! s:on_refresh_event() abort 55 | let b:hexokinase_is_on = get(b:, 'hexokinase_is_on', 0) 56 | let b:hexokinase_is_disabled = get(b:, 'hexokinase_is_disabled', 0) 57 | if b:hexokinase_is_on 58 | call hexokinase#v2#scraper#on() 59 | return 60 | endif 61 | 62 | if b:hexokinase_is_disabled 63 | return 64 | endif 65 | 66 | if g:Hexokinase_termDisabled && &buftype ==# 'terminal' 67 | return 68 | endif 69 | 70 | if !empty(g:Hexokinase_ftDisabled) 71 | if index(g:Hexokinase_ftDisabled, &filetype) > -1 72 | return 73 | endif 74 | elseif has_key(g:, 'Hexokinase_ftEnabled') 75 | if index(g:Hexokinase_ftEnabled, &filetype) == -1 76 | return 77 | endif 78 | endif 79 | 80 | call hexokinase#v2#scraper#on() 81 | endf 82 | -------------------------------------------------------------------------------- /autoload/hexokinase/v2/scraper.vim: -------------------------------------------------------------------------------- 1 | " Used for Vim because it has a shit api 2 | let s:chan_infos = {} 3 | 4 | fun! hexokinase#v2#scraper#toggle() abort 5 | let b:hexokinase_is_on = get(b:, 'hexokinase_is_on', 0) 6 | if b:hexokinase_is_on 7 | call hexokinase#v2#scraper#off() 8 | else 9 | call hexokinase#v2#scraper#on() 10 | endif 11 | endf 12 | 13 | fun! hexokinase#v2#scraper#on() abort 14 | call s:cancel_cur_job() 15 | 16 | let b:hexokinase_is_on = 1 17 | let b:hexokinase_is_disabled = 0 18 | let tmpname = hexokinase#utils#tmpname() 19 | let fail = writefile(getbufline(bufnr('%'), 1, '$'), tmpname) 20 | if fail 21 | let b:hexokinase_is_on = 0 22 | else 23 | if has('nvim') 24 | let opts = { 25 | \ 'tmpname': tmpname, 26 | \ 'on_stdout': function('s:on_stdout'), 27 | \ 'on_stderr': function('s:on_stderr'), 28 | \ 'on_exit': function('s:on_exit'), 29 | \ 'bufnr': bufnr('%'), 30 | \ 'colours': [] 31 | \ } 32 | else 33 | let opts = { 34 | \ 'out_cb': function('s:on_stdout_vim'), 35 | \ 'close_cb': function('s:on_exit_vim'), 36 | \ } 37 | endif 38 | let cmd = [g:Hexokinase_executable_path, '-simplified', '-files', tmpname] 39 | " Neovim has multiple sign columns, in which case we don't want a 40 | " reversed output. 41 | if get(g:, 'Hexokinase_prioritizeHead', 1) 42 | \ && get(b:, 'Hexokinase_prioritizeHead', 1) 43 | \ && (index(g:Hexokinase_highlighters, 'sign_column') == -1 || &signcolumn !~# '\v(auto|yes):[2-9]') 44 | call add(cmd, '-r') 45 | endif 46 | call extend(cmd, hexokinase#utils#getPatModifications()) 47 | call add(cmd, '-bg') 48 | call add(cmd, hexokinase#utils#get_background_hex()) 49 | if !empty(g:Hexokinase_palettes) 50 | call add(cmd, '-palettes') 51 | call add(cmd, join(g:Hexokinase_palettes, ',')) 52 | endif 53 | if get(g:, 'Hexokinase_checkBoundary', 1) 54 | call add(cmd, '-boundary') 55 | endif 56 | 57 | if has('nvim') 58 | let b:hexokinase_job_id = jobstart(cmd, opts) 59 | else 60 | let b:hexokinase_job = job_start(cmd, opts) 61 | let s:chan_infos[ch_info(job_getchannel(b:hexokinase_job)).id] = { 62 | \ 'tmpname': tmpname, 63 | \ 'colours': [], 64 | \ 'bufnr': bufnr('%') 65 | \ } 66 | endif 67 | endif 68 | endf 69 | 70 | fun! hexokinase#v2#scraper#off() abort 71 | let b:hexokinase_is_on = 0 72 | let b:hexokinase_is_disabled = 1 73 | call s:cancel_cur_job() 74 | call s:clear_hl(bufnr('%')) 75 | endf 76 | 77 | fun! s:clear_hl(bufnr) abort 78 | for F in g:Hexokinase_tearDownCallbacks 79 | call F(a:bufnr) 80 | endfor 81 | endf 82 | 83 | fun! s:cancel_cur_job() abort 84 | try 85 | if has('nvim') 86 | let b:hexokinase_job_id = get(b:, 'hexokinase_job_id', -1) 87 | call chanclose(b:hexokinase_job_id) 88 | else 89 | if has_key(b:, 'hexokinase_job') 90 | call ch_close(b:hexokinase_job) 91 | endif 92 | endif 93 | catch /E90[06]/ 94 | endtry 95 | endf 96 | 97 | fun! s:on_stdout_vim(chan, line) abort 98 | let colour = s:parse_colour(a:line) 99 | if !empty(colour) 100 | call add(s:chan_infos[ch_info(a:chan).id].colours, colour) 101 | endif 102 | endf 103 | 104 | fun! s:on_exit_vim(chan) abort 105 | let info = s:chan_infos[ch_info(a:chan).id] 106 | call delete(info.tmpname) 107 | call s:clear_hl(info.bufnr) 108 | call setbufvar(info.bufnr, 'hexokinase_colours', info.colours) 109 | for F in g:Hexokinase_highlightCallbacks 110 | call F(info.bufnr) 111 | endfor 112 | endf 113 | 114 | fun! s:on_stdout(id, data, event) abort dict 115 | for line in a:data 116 | let colour = s:parse_colour(line) 117 | if !empty(colour) 118 | call add(self.colours, colour) 119 | endif 120 | endfor 121 | endf 122 | 123 | fun! s:on_stderr(id, data, event) abort dict 124 | if get(g:, 'Hexokinase_logging', 0) 125 | echohl Error | echom string(a:data) | echohl None 126 | endif 127 | endf 128 | 129 | fun! s:on_exit(id, status, event) abort dict 130 | call delete(self.tmpname) 131 | call s:clear_hl(self.bufnr) 132 | if a:status 133 | return 134 | endif 135 | call setbufvar(self.bufnr, 'hexokinase_colours', self.colours) 136 | for F in g:Hexokinase_highlightCallbacks 137 | call F(self.bufnr) 138 | endfor 139 | endf 140 | 141 | fun! s:parse_colour(line) abort 142 | let parts = split(a:line, ':') 143 | if len(parts) < 4 144 | return '' 145 | endif 146 | " If a system allows `:` inside the filename, then we join together all 147 | " parts before the final 3 (which are guaranteed to be the form 148 | " lnum:col:hex). This allows the filename to remain intact. For example, 149 | " Windows can prefix the filename with the drive (e.g. C:/foo/bar.txt) 150 | let parts = insert(parts[-3:], join(parts[:-4], ':')) 151 | 152 | return { 'lnum': parts[1], 153 | \ 'start': split(parts[2], '-')[0], 154 | \ 'end': split(parts[2], '-')[1], 155 | \ 'hex': parts[3] 156 | \ } 157 | endf 158 | -------------------------------------------------------------------------------- /doc/hexokinase.txt: -------------------------------------------------------------------------------- 1 | *hexokinase.txt* (Neo)Vim plugin for asynchronously displaying the colour of 2 | hex codes, rgb(a)? functions, hsl(a)? functions, web 3 | colours, and custom patterns 4 | 5 | Author: Adam P. Regasz-Rethy (RRethy) 6 | License: Same terms as Vim itself (see |license|) 7 | 8 | CONTENTS *hexokinase-contents* 9 | =========================================================================== 10 | 11 | Introduction.................................|hexokinase-introduction| 12 | Quick Start..................................|hexokinase-quick-start| 13 | Installation.................................|hexokinase-installation| 14 | Commands.....................................|hexokinase-commands| 15 | Configuration................................|hexokinase-configuration| 16 | Highlighters.............................|g:Hexokinase_highlighters| 17 | Custom Patterns via Palettes ............|g:Hexokinase_palettes| 18 | Patterns To Find ........................|g:Hexokinase_optInPatterns| 19 | Patterns To Ignore ......................|g:Hexokinase_optOutPatterns| 20 | FileType Specific Patterns to Find ......|g:Hexokinase_ftOptInPatterns| 21 | FileType Specific Patterns to Ignore.....|g:Hexokinase_ftOptOutPatterns| 22 | Virtual Text.............................|g:Hexokinase_virtualText| 23 | Sign Column Icon.........................|g:Hexokinase_signIcon| 24 | Refresh Events...........................|g:Hexokinase_refreshEvents| 25 | Disabled TerminalBuffers.................|g:Hexokinase_termDisabled| 26 | Disabled FileTypes.......................|g:Hexokinase_ftDisabled| 27 | Enabled FileTypes........................|g:Hexokinase_ftEnabled| 28 | Background Colour for Alpha Calculations.|g:Hexokinase_alpha_bg| 29 | Use word Boundary........................|g:Hexokinase_checkBoundary| 30 | Create Custom Highlighters...................|hexokinase-custom-highlighters| 31 | Highlight Callback.......................|hexokinase-highlight_callback| 32 | Teardown Callback........................|hexokinase-teardown_callback| 33 | FAQ..........................................|hexokinase-faq| 34 | 35 | INTRODUCTION *hexokinase-introduction* 36 | =========================================================================== 37 | 38 | This plugin will display the colour which corresponds to text on the screen. 39 | 40 | All scraping is done asynchronously via a Golang scraper. 41 | 42 | It can show the colour of 6 digit hex codes, 3 digit hex codes, rgb functions, 43 | rgba functions, hsl functions, hsla functions, web colours 44 | (https://www.w3schools.com/colors/colors_names.asp), and even custom patterns. 45 | See |g:Hexokinase_palettes| for more info on advanced pattern customization. 46 | 47 | This means the following will display a beautiful rainbow (assuming all 48 | patterns enabled): 49 | > 50 | deeppink 51 | #f00 52 | oRaNgE 53 | rgb(255, 255, 0) 54 | rgba(0, 128, 0, 1) 55 | hsl(174,72.1%,56.5%) 56 | hsla(274.6,100%,25.5%, 1) 57 | #ee82ee 58 | 59 | It can display the colour in many different ways, and can be customized to 60 | display it any way you choose. Out of the box, colours can be displayed in the 61 | sign column, as virtual text (only for Neovim), as the foreground colour for 62 | the text (there are two different types of foreground colouring), or as the 63 | background colour of the text (there are also two different types of 64 | background colouring). See |g:Hexokinase_highlighters| for more information. 65 | 66 | Note: |'termguicolors'| must be turned on and your terminal must support it. 67 | 68 | QUICK START *hexokinase-quick-start* 69 | =========================================================================== 70 | 71 | These are the three most basic parts of the plugin to get up and running. #1 72 | is a must, while #2 and #3 already have strong defaults. For more complete 73 | description of the plugin, although verbose, this help file documents 74 | everything. 75 | 76 | 1. Follow |hexokinase-installation|. 77 | 2. Choose your highlighting method, or stick with the default, 78 | |g:Hexokinase_highlighters|. 79 | 3. Choose which patterns are matched, or stick with the default, 80 | |g:Hexokinase_optInPatterns| and |g:Hexokinase_ftOptInPatterns|. 81 | 82 | INSTALLATION *hexokinase-installation* 83 | =========================================================================== 84 | 85 | Golang must be installed, for more information visit 86 | https://golang.org/doc/install. 87 | 88 | Simply run the following in the project root each time the plugin is updated: > 89 | make hexokinase 90 | < 91 | Or alternatively, leverage your plugin manager to run `make hexokinase` on update: > 92 | " vim-plug 93 | Plug 'rrethy/vim-hexokinase', { 'do': 'make hexokinase' } 94 | 95 | " minpac 96 | call minpac#add('rrethy/vim-hexokinase', { 'do': 'make hexokinase' }) 97 | 98 | " dein 99 | call dein#add('rrethy/vim-hexokinase', { 'build': 'make hexokinase' }) 100 | 101 | " etc. 102 | < 103 | |'termguicolors'| must be turned on and your terminal must support it. 104 | 105 | Note: This has been tested on MacOS. Linux should work as well. Windows is 106 | untested, if you find an issue with Windows, open an issue at 107 | https://github.com/rrethy/vim-hexokinase/issues. 108 | 109 | COMMANDS *hexokinase-commands* 110 | =========================================================================== 111 | 112 | ----------------------+------------------------------------------------- 113 | Command | Description ~ 114 | ----------------------+------------------------------------------------- 115 | `HexokinaseToggle` | Toggle the colouring 116 | `HexokinaseTurnOn` | Turn on colouring (refresh if already turned on) 117 | `HexokinaseTurnOff` | Turn off colouring 118 | ----------------------+------------------------------------------------- 119 | 120 | CONFIGURATION *hexokinase-configuration* 121 | =========================================================================== 122 | 123 | Highlighters *g:Hexokinase_highlighters* 124 | 125 | Type: |List| of |String|s 126 | How to display the colour. 127 | Checkout |hexokinase-custom-highlighters| to create your own 128 | highlighter. 129 | 130 | Default value: > 131 | " Neovim default 132 | let g:Hexokinase_highlighters = [ 'virtual' ] 133 | 134 | " Vim default 135 | let g:Hexokinase_highlighters = [ 'sign_column' ] 136 | < 137 | Possible values: > 138 | let g:Hexokinase_highlighters = [ 139 | \ 'virtual', 140 | \ 'sign_column', 141 | \ 'background', 142 | \ 'backgroundfull', 143 | \ 'foreground', 144 | \ 'foregroundfull' 145 | \ ] 146 | < 147 | Any combination of them can be used, on top of custom 148 | highlighters. 149 | 150 | "virtual" will use Neovim's virtual text feature 151 | (|nvim_buf_set_virtual_text()|) to display 152 | the colour. 153 | 154 | "sign_column" will use the |'sign_column'| to display the 155 | colour. In Vim, only one colour per line can be displayed. 156 | If you are using Neovim 0.4 or newer that supports multiple 157 | sign columns, the number of colors will respect your 158 | |'sign_column'| settings. 159 | 160 | "background" will highlight the background of certain 161 | characters, such as the parenthesis of various functions or 162 | the hash symbol for hex codes. For web colours it'll just 163 | highlight the whole background. 164 | 165 | "backgroundfull" will highlight the whole background of the 166 | appropriate text. 167 | 168 | "foreground" will act the same as "background", but as the 169 | name suggest, it'll highlight the foreground of the 170 | characters. 171 | 172 | "foregroundfull" will highlight the whole foreground of the 173 | appropriate text. 174 | 175 | Custom Patterns via Palettes *g:Hexokinase_palettes* 176 | 177 | Type: |List| of |String|s 178 | Each string is a path to a file that can be used as a 179 | palette. 180 | 181 | Sample value: > 182 | " must be absolute path 183 | let g:Hexokinase_palettes = [expand($HOME).'/path/to/file'] 184 | < 185 | A palette is a json file that looks like the following: 186 | > 187 | { 188 | "regex_pattern": "foo[0-9]bar[0-9]baz[0-9]", 189 | "colour_table": { 190 | "foo1bar1baz1": "#eb00ff", 191 | "foo2bar2baz2": "#ffeb00", 192 | "foo3bar3baz3": "#00ffeb" 193 | } 194 | } 195 | < 196 | If the key "regex_pattern" exists in the top-level, then 197 | hexokinase will look for the regex pattern in the file. Upon 198 | finding a match, it will use the "colour_table" to translate 199 | the match into a hex code. False positives are ignored. 200 | 201 | If the key "regex_pattern" does not exist in the top-level. 202 | Each key in "colour_table" will be looked for. Omitting an 203 | overly complex "regex_pattern" will improve performance, but 204 | it's unlikely to produce a noticeable difference. 205 | 206 | By using a palette, you can highlight variables which refer to 207 | colours in your code. 208 | 209 | Note: "regex_pattern" follows the regex syntax accepted by 210 | RE2, except for \C. For more information see 211 | https://github.com/google/re2/wiki/Syntax. This syntax is 212 | similar to Golang, Perl, Python, etc.. It is NOT Vimscript 213 | style regex. 214 | 215 | Patterns To Find *g:Hexokinase_optInPatterns* 216 | 217 | Type: |List| of |String|s 218 | OR 219 | Comma separated |String| with no spaces 220 | Which patterns to look for. 221 | 222 | Default value: > 223 | let g:Hexokinase_optInPatterns = 'full_hex,rgb,rgba,hsl,hsla,colour_names' 224 | < 225 | 226 | Possible values: > 227 | let g:Hexokinase_optInPatterns = [ 228 | \ 'full_hex', 229 | \ 'triple_hex', 230 | \ 'rgb', 231 | \ 'rgba', 232 | \ 'hsl', 233 | \ 'hsla', 234 | \ 'colour_names' 235 | \ ] 236 | < 237 | This option can be overridden by other configuration, this is 238 | the relevant precedence order: 239 | 1. |g:Hexokinase_ftOptOutPatterns| 240 | 2. |g:Hexokinase_ftOptInPatterns| 241 | 3. |g:Hexokinase_optOutPatterns| 242 | 4. |g:Hexokinase_optInPatterns| 243 | 244 | Patterns To Ignore *g:Hexokinase_optOutPatterns* 245 | 246 | Type: |List| of |String|s 247 | OR 248 | Comma separated |String| with no spaces 249 | Which patterns to ignore. 250 | 251 | Default value: > 252 | let g:Hexokinase_optInPatterns = '' 253 | < 254 | 255 | Possible values: > 256 | let g:Hexokinase_optOutPatterns = [ 257 | \ 'full_hex', 258 | \ 'triple_hex', 259 | \ 'rgb', 260 | \ 'rgba', 261 | \ 'hsl', 262 | \ 'hsla', 263 | \ 'colour_names' 264 | \ ] 265 | < 266 | This option can be overridden by other configuration, this is 267 | the relevant precedence order: 268 | 1. |g:Hexokinase_ftOptOutPatterns| 269 | 2. |g:Hexokinase_ftOptInPatterns| 270 | 3. |g:Hexokinase_optOutPatterns| 271 | 4. |g:Hexokinase_optInPatterns| 272 | 273 | FileType Specific Patterns to Find *g:Hexokinase_ftOptInPatterns* 274 | 275 | Type: |Dict| of |String| to |List| of |String|s 276 | Which patterns to look for for specific filetypes. 277 | 278 | Default value: > 279 | let g:Hexokinase_ftOptInPatterns = {} 280 | < 281 | This option can be overridden by other configuration, this is 282 | the relevant precedence order: 283 | 1. |g:Hexokinase_ftOptOutPatterns| 284 | 2. |g:Hexokinase_ftOptInPatterns| 285 | 3. |g:Hexokinase_optOutPatterns| 286 | 4. |g:Hexokinase_optInPatterns| 287 | 288 | FileType Specific Patterns to Ignore *g:Hexokinase_ftOptOutPatterns* 289 | 290 | Type: |Dict| of |String| to |List| of |String|s 291 | Which patterns to ignore for specific filetypes. 292 | 293 | Default value: > 294 | let g:Hexokinase_ftOptOutPatterns = {} 295 | < 296 | This option can override other configuration, this is the 297 | relevant precedence order: 298 | 1. |g:Hexokinase_ftOptOutPatterns| 299 | 2. |g:Hexokinase_ftOptInPatterns| 300 | 3. |g:Hexokinase_optOutPatterns| 301 | 4. |g:Hexokinase_optInPatterns| 302 | 303 | Virtual Text *g:Hexokinase_virtualText* 304 | 305 | Type: |String| 306 | The text to display when using virtual text for the 307 | highlighting. 308 | 309 | Default value: > 310 | let g:Hexokinase_virtualText = '■' 311 | < 312 | Note: Highlighting is done on the foreground of what is 313 | passed, so spaces will not work, instead use "█". 314 | 315 | Sign Column Icon *g:Hexokinase_signIcon* 316 | 317 | Type: |String| 318 | The text to display when using the |sign_column|. 319 | 320 | Default value: > 321 | let g:Hexokinase_signIcon = '■' 322 | < 323 | Note: Can only be one or two characters long. 324 | 325 | Note: Highlighting is done on the foreground of what is 326 | passed, so spaces will not work, instead use "█". 327 | 328 | Refresh Events *g:Hexokinase_refreshEvents* 329 | 330 | Type: |List| of |String|s 331 | Which |autocmd-events| trigger a refresh of highlighting. 332 | 333 | Default value: > 334 | let g:Hexokinase_refreshEvents = ['TextChanged', 'InsertLeave', 'BufRead'] 335 | < 336 | Disabled TerminalBuffers *g:Hexokinase_termDisabled* 337 | 338 | Type: |Integer| 339 | Do not scraped any terminal buffers. 340 | 341 | Default value: > 342 | let g:Hexokinase_termDisabled = 0 343 | < 344 | By Default, all terminal buffers are scraped. 345 | 346 | 347 | Disabled FileTypes *g:Hexokinase_ftDisabled* 348 | 349 | Type: |List| of |String|s 350 | Which FileTypes not to scrape. 351 | 352 | Default value: > 353 | let g:Hexokinase_ftDisabled = [] 354 | < 355 | By Default, all filetypes are scraped. 356 | 357 | Regex patterns are not supported. 358 | 359 | This will override |g:Hexokinase_ftEnabled|. 360 | This will be overridden by any use of |HexokinaseTurnOn|. 361 | 362 | Enabled FileTypes *g:Hexokinase_ftEnabled* 363 | 364 | Type: |List| of |String|s 365 | Which FileTypes to scrape automatically. 366 | 367 | Sample value: > 368 | let g:Hexokinase_ftEnabled = ['css', 'html', 'javascript'] 369 | < 370 | By Default, all filetypes are scraped. 371 | 372 | Regex patterns are not supported. 373 | 374 | An empty list means not filetypes are scraped automatically. 375 | To scrape all filetypes automatically, simply don't define 376 | this variable (also leave |g:Hexokinase_ftDisabled| empty). 377 | 378 | This will be overriden by |g:Hexokinase_ftDisabled|. 379 | 380 | Background Colour for Alpha Calculations *g:Hexokinase_alpha_bg* 381 | 382 | Type: |String| 383 | Hex code to use when calculating alpha for `rgba` and `hsla` 384 | functions. 385 | 386 | Default value: > 387 | g:Hexokinase_alpha_bg = '' 388 | < 389 | By default calculations are done using the background of 390 | |hl-Normal| or |hl-SignColumn|. This will override that. 391 | 392 | Note: This MUST be a valid 6 digit hex. Such as `#ffffff`. 393 | 394 | Use word Boundary *g:Hexokinase_checkBoundary* 395 | 396 | Type: 1 or 0 397 | Whether or not to discard matches which are not words. If you 398 | want absolutely everything to be highlighted regardless of 399 | context, then turn this off. This will reduce false positives. 400 | 401 | Default value: > 402 | let g:Hexokinase_checkBoundary = 1 403 | < 404 | Currently only applies to hex codes and web colours. Setting 405 | this to 1 will cause the following: > 406 | " not a match for any colour 407 | not#a#match#ffffff 408 | 409 | " not a match 410 | #fffffffail 411 | 412 | " will match only #aaaaaa 413 | #aaaaaa#ffffff#000000 414 | 415 | " will match pink but not blue or red 416 | redblue pink 417 | 418 | Executable path *g:Hexokinase_executable_path* 419 | 420 | Type: |String| 421 | Path to the `hexokinase` executable. 422 | 423 | Default value: > 424 | " relative to the plugin root 425 | g:Hexokinase_executable_path = 'hexokinase/hexokinase' 426 | < 427 | 428 | CREATE CUSTOM HIGHLIGHTERS *hexokinase-custom-highlighters* 429 | =========================================================================== 430 | 431 | To create a custom highlighter you need to create two functions with the 432 | following signatures (the name doesn't matter since it gets passed as a 433 | function reference below): 434 | 435 | Note: Check out ./autoload/hexokinase/highlighters/*.vim for examples of 436 | highlighters. Look at the functions ending in v2. 437 | 438 | highlight_callback({bufnr}) 439 | *hexokinase-highlight_callback* 440 | 441 | {bufnr} is the buffer number of the buffer that was scraped. 442 | The currently active buffer may be different since scraping is 443 | done asynchronously. 444 | 445 | `b:hexokinase_colours` will be set to a list of dictionaries 446 | with the following entries: 447 | 448 | lnum line number for the match 449 | start start column of the match (indexed from 1) 450 | end end column of the match (indexed from 1) 451 | hex six digit hex code of the colour 452 | 453 | Sample value: > 454 | echo b:hexokinase_colours 455 | => [{'lnum': '407', 'start': '1', 'end': '7', 'hex': 456 | '#ffffff'}, {'lnum': '381', 'start': '66', 'end': '72 ', 457 | 'hex': '#00ffaa'}] 458 | < 459 | Register this callback as follows: > 460 | let g:Hexokinase_highlightCallbacks = [ 461 | \ function('highlight_callback') 462 | \ ] 463 | 464 | teardown_callback({bufnr}) 465 | *hexokinase-teardown_callback* 466 | 467 | {bufnr} is the buffer number of the buffer that was scraped. 468 | The currently active buffer may be different than {bufnr} so 469 | don't rely on "bufnr('%')". 470 | 471 | This will get triggered when the highlighting is turned off by 472 | the user or when it is refreshed for a buffer. This would be 473 | the time to revert any UI changes that were made in 474 | |hexokinase-highlight_callback|. When being refreshed, the 475 | entire buffer is scraped before the callback is triggered. 476 | 477 | Register this callback as follows: > 478 | let g:Hexokinase_tearDownCallbacks = [ 479 | \ function('teardown_callback') 480 | \ ] 481 | 482 | FAQ *hexokinase-faq* 483 | =========================================================================== 484 | 485 | Q: I'm seeing grey colours when I toggle vim-hexokinase 486 | 487 | A: You need `termguicolors` to be turned on. Verify `:set termguicolors?` 488 | outputs `termguicolors`. 489 | 490 | vim:tw=78:ts=8:ft=help:norl: 491 | -------------------------------------------------------------------------------- /lua/hexokinase.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | return M 3 | -------------------------------------------------------------------------------- /plugin/hexokinase.vim: -------------------------------------------------------------------------------- 1 | " hexokinase.(n)vim - (Neo)Vim plugin for colouring hex codes 2 | " Maintainer: Adam P. Regasz-Rethy (RRethy) 3 | " Vertion 2.0 4 | 5 | if exists('g:loaded_hexokinase') 6 | finish 7 | endif 8 | 9 | let g:loaded_hexokinase = 1 10 | 11 | let g:Hexokinase_executable_path = get(g:, 'Hexokinase_executable_path', 12 | \ executable(expand(':h:h').'/hexokinase/hexokinase') 13 | \ ? expand(':h:h').'/hexokinase/hexokinase' 14 | \ : expand($GOPATH).'/bin/hexokinase') 15 | let g:Hexokinase_v2 = get(g:, 'Hexokinase_v2', 1) 16 | 17 | if g:Hexokinase_v2 18 | if executable(g:Hexokinase_executable_path) 19 | call hexokinase#v2#setup() 20 | else 21 | echohl Error | echom 'vim-hexokinase needs updating. Run `make hexokinase` in project root. See `:h hexokinase-installation` for more info.' | echohl None 22 | endif 23 | else 24 | call hexokinase#v1#setup() 25 | endif 26 | -------------------------------------------------------------------------------- /screenshot_colours.txt: -------------------------------------------------------------------------------- 1 | blue red pink orange yellow 2 | 3 | #00f #08f #0ff #0f8 #0f0 4 | 5 | #8f0 #ff0 #f80 #f00 #f08 6 | 7 | #ffffff #00f900 #08f900 8 | #0f8900 #0f0900 9 | #8f0900 #ff0900 #8f0900 10 | 11 | rgba(100%,0%,0%,1.0) rgba(255,0,0,0.5) 12 | rgba(100%,0%,0%,0.5) rgba(255,0,0,0.3) 13 | 14 | hsl(195.5, 100%, 50%) hsl(195.53, 100%, 50%) 15 | hsl(0, 0%, 100%) hsl(0, 0%, 0%) 16 | 17 | hsla(195.5, 100%, 50%, .5) hsla(195.53, 100%, 50%, .5) 18 | hsla(0, 0%, 100%, .5) hsla(0, 0%, 0%, .5) 19 | 20 | rgb(255,0,0) rgb(128,0,0) rgb(64,0,0) 21 | rgb(0,255,0) rgb(0,128,0) rgb(0,64,0) 22 | rgb(0,0,255) rgb(0,0,128) rgb(0,0,64) 23 | -------------------------------------------------------------------------------- /test_colours.txt: -------------------------------------------------------------------------------- 1 | This file lists various colors, for testing the supported color syntax 2 | 3 | green red blue 4 | 5 | #ffffffFF 6 | 7 | #AAbB11aa 8 | 9 | #fffffff 10 | 11 | #fff 12 | #000000 #333333 #666666 13 | #ffffff 14 | #999999 #cccccc #ffffff 15 | #000000ff #333333ff #666666ff 16 | #999999ff #ccccccff #ffffffff 17 | #00000088 #33333388 #66666688 18 | #99999988 #cccccc88 #ffffff88 19 | 20 | foo3bar3baz3 21 | 22 | #fff #333 #666 23 | #999 #ccc #fff 24 | #000 #333f #666f 25 | #999f #cccf #ffff 26 | #000c #333c #666c 27 | #999c #cccc #fffc 28 | #0009 #3339 #6669 29 | #9999 #ccc9 #fff9 30 | #0006 #3336 #6666 31 | #9996 #ccc6 #fff6 32 | #0003 #3333 #6663 33 | #9993 #ccc3 #fff3 34 | #0000 #3330 #6660 35 | #9990 #ccc0 #fff0 36 | 37 | #00f#08f#0ff#0f8#0f0#8f0#ff0#f80#f00#f08#f0f#80f 38 | 39 | #f00f #f00c #f009 #f006 #f003 #f000 40 | 41 | rgba(0,0,0,1.0) 42 | rgba(100%,0%,0%,1.0) #f00f #0f0f #00ff #ff00 #f0f0 #f00f 43 | rgba(255,0,0,0.5) 44 | rgba(100%,0%,0%,0.5) #f008 #0f08 #00f8 #8f00 #80f0 #800f 45 | rgba(255,0,0,0.3) 46 | rgba(100%,0%,0%,0.3) #f004 #0f04 #00f4 #4f00 #40f0 #400f 47 | 48 | 49 | rgb(255,0,0) rgb(128,0,0) rgb(64,0,0) 50 | rgb(0,255,0) rgb(0,128,0) rgb(0,64,0) 51 | rgb(0,0,255) rgb(0,0,128) rgb(0,0,64) 52 | 53 | #00f #08f #0ff #0f8 #0f0 #8f0 #ff0 #f80 #f00 #f08 #f0f #80f 54 | 55 | #00ff00 56 | #08ff00 57 | #0fff00 58 | #0f8f00 59 | #0f0f00 60 | #8f0f00 61 | #ff0f00 62 | #f80f00 63 | #f00f00 64 | #f08f00 65 | #f0ff00 66 | #80ff00 67 | #00fc00 68 | #08fc00 69 | #0ffc00 70 | #0f8c00 71 | #0f0c00 72 | #8f0c00 73 | #ff0c00 74 | #f80c00 75 | #f00c00 76 | #f08c00 77 | #f0fc00 78 | #80fc00 79 | #00f900 80 | #08f900 81 | #0ff900 82 | #0f8900 83 | #0f0900 84 | #8f0900 85 | #ff0900 86 | #f80900 87 | #f00900 88 | #f08900 89 | #f0f900 90 | #80f900 91 | #00f600 92 | #08f600 93 | #0ff600 94 | #0f8600 95 | #0f0600 96 | #8f0600 97 | #ff0600 98 | #f80600 99 | #f00600 100 | #f08600 101 | #f0f600 102 | #80f600 103 | #00f300 104 | #08f300 105 | #0ff300 106 | #0f8300 107 | #0f0300 108 | #8f0300 109 | #ff0300 110 | #f80300 111 | #f00300 112 | #f08300 113 | #f0f300 114 | #80f300 115 | #00f000 116 | #08f000 117 | #0ff000 118 | #0f8000 119 | #0f0000 120 | #8f0000 121 | #ff0000 122 | #f80000 123 | #f00000 124 | #f08000 125 | #f0f000 126 | #80f000 127 | --------------------------------------------------------------------------------