2 " @plugin Pinnacle Highlight group manipulation for Vim
6 " Pinnacle provides functions for manipulating |:highlight| groups.
11 " To install Pinnacle, use your plug-in management system of choice.
13 " If you don't have a "plug-in management system of choice", I recommend
14 " Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
15 " robustness. Assuming that you have Pathogen installed and configured, and that
16 " you want to install Pinnacle into `~/.vim/bundle`, you can do so with:
19 " git clone https://github.com/wincent/pinnacle.git ~/.vim/bundle/pinnacle
22 " Alternatively, if you use a Git submodule for each Vim plug-in, you could do
23 " the following after `cd`-ing into the top-level of your Git superproject:
26 " git submodule add https://github.com/wincent/pinnacle.git ~/vim/bundle/pinnacle
30 " To generate help tags under Pathogen, you can do so from inside Vim with:
33 " :call pathogen#helptags()
39 " The official Pinnacle source code repo is at:
41 " http://git.wincent.com/pinnacle.git
45 " - https://github.com/wincent/pinnacle
46 " - https://gitlab.com/wincent/pinnacle
47 " - https://bitbucket.org/ghurrell/pinnacle
49 " Official releases are listed at:
51 " http://www.vim.org/scripts/script.php?script_id=5360
56 " Copyright (c) 2016-present Greg Hurrell
58 " Permission is hereby granted, free of charge, to any person obtaining
59 " a copy of this software and associated documentation files (the
60 " "Software"), to deal in the Software without restriction, including
61 " without limitation the rights to use, copy, modify, merge, publish,
62 " distribute, sublicense, and/or sell copies of the Software, and to
63 " permit persons to whom the Software is furnished to do so, subject to
64 " the following conditions:
66 " The above copyright notice and this permission notice shall be
67 " included in all copies or substantial portions of the Software.
69 " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
70 " EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
71 " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
72 " NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
73 " LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
74 " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
75 " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
80 " ## Contributing patches
82 " Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
83 " at: https://github.com/wincent/pinnacle/pulls
85 " ## Cutting a new release
87 " At the moment the release process is manual:
89 " - Perform final sanity checks and manual testing
90 " - Update the |pinnacle-history| section of the documentation
91 " - Verify clean work tree:
100 " git tag -s -m "$VERSION release" $VERSION
103 " - Publish the code:
106 " git push origin master --follow-tags
107 " git push github master --follow-tags
110 " - Produce the release archive:
113 " git archive -o pinnacle-$VERSION.zip HEAD -- .
116 " - Upload to http://www.vim.org/scripts/script.php?script_id=5360
121 " Pinnacle is written and maintained by Greg Hurrell <greg@hurrell.net>.
123 " Other contributors that have submitted patches include (in alphabetical
131 " 0.2 (9 January 2016)
133 " - Added `pinnacle#underline`.
135 " ## 0.1 (30 March 2016)
139 " Replaces newlines with spaces.
140 function! pinnacle#sub_newlines(string) abort
141 return tr(a:string, "\r\n", ' ')
144 " Runs a command and returns the captured output as a single line.
146 " Useful when we don't want to let long lines on narrow windows produce unwanted
148 function! pinnacle#capture_line(command) abort
153 return pinnacle#sub_newlines(l:capture)
156 " Gets the current value of a highlight group.
157 function! pinnacle#capture_highlight(group) abort
158 return pinnacle#capture_line('0verbose silent highlight ' . a:group)
161 " Extracts a highlight string from a group, recursively traversing linked
162 " groups, and returns a string suitable for passing to `:highlight`.
163 function! pinnacle#extract_highlight(group) abort
164 let l:group = pinnacle#capture_highlight(a:group)
166 " Traverse links back to authoritative group.
167 while l:group =~# 'links to'
168 let l:index = stridx(l:group, 'links to') + len('links to')
169 let l:linked = strpart(l:group, l:index + 1)
170 let l:group = pinnacle#capture_highlight(l:linked)
173 " Extract the highlighting details (the bit after "xxx")
174 let l:matches = matchlist(l:group, '\<xxx\>\s\+\(.*\)')
175 let l:original = l:matches[1]
179 let s:prefix=has('gui') || has('termguicolors') ? 'gui' : 'cterm'
181 function! pinnacle#extract_bg(group) abort
182 return pinnacle#extract_component(a:group, 'bg')
185 function! pinnacle#extract_fg(group) abort
186 return pinnacle#extract_component(a:group, 'fg')
189 function! pinnacle#extract_component(group, component) abort
190 return synIDattr(synIDtrans(hlID(a:group)), a:component, s:prefix)
193 function! pinnacle#highlight(highlight) abort
195 if has_key(a:highlight, 'bg')
196 call insert(l:result, s:prefix . 'bg=' . a:highlight['bg'])
198 if has_key(a:highlight, 'fg')
199 call insert(l:result, s:prefix . 'fg=' . a:highlight['fg'])
201 if has_key(a:highlight, 'term')
202 call insert(l:result, s:prefix . '=' . a:highlight['term'])
204 return join(l:result, ' ')
207 " Returns an italicized copy of `group` suitable for passing to `:highlight`.
208 function! pinnacle#italicize(group) abort
209 return pinnacle#decorate('italic', a:group)
212 " Returns a bold copy of `group` suitable for passing to `:highlight`.
213 function! pinnacle#embolden(group) abort
214 return pinnacle#decorate('bold', a:group)
217 " Returns an underlined copy of `group` suitable for passing to `:highlight`.
218 function! pinnacle#underline(group) abort
219 return pinnacle#decorate('underline', a:group)
222 " Returns a copy of `group` decorated with `style` (eg. "bold", "italic" etc)
223 " suitable for passing to `:highlight`.
224 function! pinnacle#decorate(style, group) abort
225 let l:original = pinnacle#extract_highlight(a:group)
227 for l:lhs in ['gui', 'term', 'cterm']
228 " Check for existing setting.
229 let l:matches = matchlist(
232 \ '\(' . l:lhs . '=[^ ]\+\)' .
236 " No setting, add one with just a:style in it
237 let l:original .= ' ' . l:lhs . '=' . a:style
239 " Existing setting; check whether a:style is already in it.
240 let l:start = l:matches[1]
241 let l:value = l:matches[2]
242 let l:end = l:matches[3]
243 if l:value =~# '.*' . a:style . '.*'
246 let l:original = l:start . l:value . ',' . a:style . l:end
251 return pinnacle#sub_newlines(l:original)