├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── LICENSE ├── README.md ├── autoload └── highlighturl.vim ├── doc └── highlighturl.txt ├── plugin └── highlighturl.vim └── test └── default_pattern.vim /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | name: Test 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | vim: 16 | - v8.2.0000 17 | - v8.1.0000 18 | - v8.0.0000 19 | steps: 20 | - name: Checkout code 21 | uses: actions/checkout@v3 22 | - name: Checkout vim-themis 23 | uses: actions/checkout@v3 24 | with: 25 | repository: thinca/vim-themis 26 | path: vim-themis 27 | - name: Setup Vim 28 | uses: rhysd/action-setup-vim@v1 29 | id: vim 30 | with: 31 | version: ${{ matrix.vim }} 32 | - name: Test 33 | env: 34 | THEMIS_VIM: ${{ steps.vim.outputs.executable }} 35 | run: ./vim-themis/bin/themis --reporter spec 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /doc/tags 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2022 itchyny 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-highlighturl 2 | ## URL highlight everywhere 3 | ![vim-highlighturl](https://raw.githubusercontent.com/wiki/itchyny/vim-highlighturl/image/image.png) 4 | 5 | ## Installation 6 | Install with your favorite plugin manager. 7 | 8 | ## Author 9 | itchyny (https://github.com/itchyny) 10 | 11 | ## License 12 | This software is released under the MIT License, see LICENSE. 13 | -------------------------------------------------------------------------------- /autoload/highlighturl.vim: -------------------------------------------------------------------------------- 1 | " ============================================================================= 2 | " Filename: autoload/highlighturl.vim 3 | " Author: itchyny 4 | " License: MIT License 5 | " Last Change: 2022/04/28 09:31:53. 6 | " ============================================================================= 7 | 8 | let s:save_cpo = &cpo 9 | set cpo&vim 10 | 11 | let s:urlcursor = v:version < 704 || v:version == 704 && !has('patch682') 12 | 13 | function! s:get(name, default) abort 14 | return get(b:, 'highlighturl_' . a:name, get(g:, 'highlighturl_' . a:name, a:default)) 15 | endfunction 16 | 17 | function! highlighturl#default_pattern() abort 18 | return '\v\c%(%(h?ttps?|sftp|ftps?|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)%(' 19 | \.'[&:#*@~%_\-=?!+;/0-9a-z]+%(%([.;/?]|[.][.]+)[&:#*@~%_\-=?!+/0-9a-z]+|:\d+|' 20 | \.',%(%(%(h?ttps?|sftp|ftps?|file|ssh|git)://|[a-z]+[@][a-z]+[.][a-z]+:)@![0-9a-z]+))*|' 21 | \.'\([&:#*@~%_\-=?!+;/.0-9a-z]*\)|\[[&:#*@~%_\-=?!+;/.0-9a-z]*\]|' 22 | \.'\{%([&:#*@~%_\-=?!+;/.0-9a-z]*|\{[&:#*@~%_\-=?!+;/.0-9a-z]*\})\})+' 23 | endfunction 24 | 25 | function! highlighturl#get_url_highlight(cursor) abort 26 | let cursor = a:cursor ? '_cursor' : '' 27 | let term = s:get('term' . cursor, s:get('term_underline', s:get('underline', 1)) ? 'underline' : 'NONE') 28 | let cterm = s:get('cterm' . cursor, s:get('cterm_underline', s:get('underline', 1)) ? 'underline' : 'NONE') 29 | let ctermfg = s:get('ctermfg' . cursor, &background ==# 'dark' ? '44' : '31') 30 | let gui = s:get('gui' . cursor, s:get('gui_underline', s:get('underline', 1)) ? 'underline' : 'NONE') 31 | let guifg = s:get('guifg' . cursor, &background ==# 'dark' ? '#00dfdf' : '#002f5f') 32 | return 'term=' . term . ' cterm=' . cterm . ' ctermfg=' . ctermfg . ' gui=' . gui . ' guifg=' . guifg 33 | endfunction 34 | 35 | function! highlighturl#set_highlight() abort 36 | call highlighturl#set_url_highlight() 37 | if s:urlcursor 38 | call highlighturl#set_urlcursor_highlight() 39 | endif 40 | endfunction 41 | 42 | function! highlighturl#set_url_highlight() abort 43 | execute 'highlight default HighlightUrl' highlighturl#get_url_highlight(0) 44 | endfunction 45 | 46 | function! highlighturl#set_urlcursor_highlight() abort 47 | redir => out 48 | silent! highlight CursorLine 49 | redir END 50 | let outstr = substitute(out, '\n', '', 'g') 51 | let cbg = matchstr(outstr, 'ctermbg=\S\+') 52 | let gbg = matchstr(outstr, 'guibg=\S\+') 53 | execute 'highlight default HighlightUrlCursor' highlighturl#get_url_highlight(1) cbg gbg 54 | endfunction 55 | 56 | function! highlighturl#delete_url_match() abort 57 | for m in getmatches() 58 | if m.group ==# 'HighlightUrl' || m.group ==# 'HighlightUrlCursor' 59 | call matchdelete(m.id) 60 | endif 61 | endfor 62 | endfunction 63 | 64 | function! highlighturl#set_url_match() abort 65 | call highlighturl#delete_url_match() 66 | if s:get('enable', get(s:, 'enable', 1)) 67 | if !hlexists('HighlightUrl') 68 | call highlighturl#set_highlight() 69 | endif 70 | let pattern = s:get('pattern', highlighturl#default_pattern()) 71 | call matchadd('HighlightUrl', pattern, s:get('url_priority', 15)) 72 | if s:urlcursor 73 | call highlighturl#set_urlcursor_match() 74 | endif 75 | endif 76 | endfunction 77 | 78 | let s:line = {} 79 | let s:cursorline = {} 80 | function! highlighturl#check_urlcursor() abort 81 | if get(s:line, bufnr('')) != line('.') || get(s:cursorline, bufnr('')) != &l:cursorline 82 | call highlighturl#set_urlcursor_match() 83 | endif 84 | endfunction 85 | 86 | let s:match_id = {} 87 | function! highlighturl#set_urlcursor_match() abort 88 | let bufnr = bufnr('') 89 | let s:line[bufnr] = line('.') 90 | let s:cursorline[bufnr] = &l:cursorline 91 | if has_key(s:match_id, bufnr) 92 | silent! call matchdelete(s:match_id[bufnr]) 93 | endif 94 | if s:get('enable', get(s:, 'enable', 1)) 95 | let name = &l:cursorline ? 'HighlightUrlCursor': 'HighlightUrl' 96 | let pattern = '\%' . line('.') . 'l' . s:get('pattern', highlighturl#default_pattern()) 97 | let s:match_id[bufnr] = matchadd(name, pattern, s:get('url_cursor_priority', 20)) 98 | endif 99 | endfunction 100 | 101 | function! highlighturl#refresh() abort 102 | let save_winnr = winnr() 103 | for winnr in range(1, winnr('$')) 104 | silent! noautocmd execute winnr 'wincmd w' 105 | unlet! b:highlighturl_enable 106 | call highlighturl#set_url_match() 107 | endfor 108 | silent! noautocmd execute save_winnr 'wincmd w' 109 | return '' 110 | endfunction 111 | 112 | function! highlighturl#enable() abort 113 | let s:enable = 1 114 | call highlighturl#refresh() 115 | return '' 116 | endfunction 117 | 118 | function! highlighturl#disable() abort 119 | let s:enable = 0 120 | call highlighturl#refresh() 121 | return '' 122 | endfunction 123 | 124 | function! highlighturl#toggle() abort 125 | if get(s:, 'enable', 1) 126 | call highlighturl#disable() 127 | else 128 | call highlighturl#enable() 129 | endif 130 | return '' 131 | endfunction 132 | 133 | function! highlighturl#enable_local() abort 134 | let b:highlighturl_enable = 1 135 | call highlighturl#set_url_match() 136 | return '' 137 | endfunction 138 | 139 | function! highlighturl#disable_local() abort 140 | let b:highlighturl_enable = 0 141 | call highlighturl#set_url_match() 142 | return '' 143 | endfunction 144 | 145 | function! highlighturl#toggle_local() abort 146 | if s:get('enable', get(s:, 'enable', 1)) 147 | call highlighturl#disable_local() 148 | else 149 | call highlighturl#enable_local() 150 | endif 151 | return '' 152 | endfunction 153 | 154 | let &cpo = s:save_cpo 155 | unlet s:save_cpo 156 | -------------------------------------------------------------------------------- /doc/highlighturl.txt: -------------------------------------------------------------------------------- 1 | *highlighturl.txt* URL highlight everywhere 2 | 3 | Version: 0.1 4 | Author: itchyny (https://github.com/itchyny) 5 | License: MIT License 6 | Repository: https://github.com/itchyny/vim-highlighturl 7 | Last Change: 2015/03/25 08:22:38. 8 | 9 | CONTENTS *highlighturl-contents* 10 | 11 | Introduction |highlighturl-introduction| 12 | Options |highlighturl-options| 13 | Functions |highlighturl-functions| 14 | Examples |highlighturl-examples| 15 | Changelog |highlighturl-changelog| 16 | 17 | ============================================================================== 18 | INTRODUCTION *highlighturl-introduction* 19 | This *highlighturl* plugin highlights URLs everywhere. That's it. 20 | 21 | ------------------------------------------------------------------------------ 22 | OPTIONS *highlighturl-options* 23 | 24 | g:highlighturl_enable *g:highlighturl_enable* 25 | Enables the URL highlight everywhere. You can set this variable to 0 26 | in vimrc if you do not want the URL highlight. If you want to enable 27 | or disable the highlight feature after starting up, instead of 28 | setting this variable, use the functions |highlighturl#enable()| and 29 | |highlighturl#disable()|. 30 | The default value is 1. 31 | 32 | g:highlighturl_pattern *g:highlighturl_pattern* 33 | You can configure the URL pattern with this variable. Set a regular 34 | expression to this variable. 35 | The default value is complicated. You can see the value by 36 | |highlighturl#default_pattern()|. 37 | 38 | g:highlighturl_url_priority *g:highlighturl_url_priority* 39 | The priority used for the URL highlight. 40 | The default value is 15. 41 | 42 | g:highlighturl_url_cursor_priority *g:highlighturl_url_cursor_priority* 43 | The priority used for the URL under the cursor line. 44 | The default value is 20. 45 | 46 | g:highlighturl_underline *g:highlighturl_underline* 47 | If you do not want the under line for the URL highlight, set this 48 | variable to 0. 49 | The default value is 1. 50 | 51 | g:highlighturl_ctermfg *g:highlighturl_ctermfg* 52 | The highlight color of the URL highlight for ctermfg. 53 | The default value is 44 if |'background'| is dark and 31 otherwise. 54 | 55 | g:highlighturl_guifg *g:highlighturl_guifg* 56 | The highlight color of the URL highlight for guifg. 57 | The default value is #00dfdf if |'background'| is dark and #002f5f 58 | otherwise. 59 | 60 | ------------------------------------------------------------------------------ 61 | FUNCTIONS *highlighturl-functions* 62 | 63 | highlighturl#enable() *highlighturl#enable()* 64 | Enables the URL highlight. 65 | 66 | highlighturl#disable() *highlighturl#disable()* 67 | Disables the URL highlight. 68 | 69 | highlighturl#toggle() *highlighturl#toggle()* 70 | Toggles the URL highlight. 71 | 72 | highlighturl#enable_local() *highlighturl#enable_local()* 73 | Enables the URL highlight in the current buffer. 74 | 75 | highlighturl#disable_local() *highlighturl#disable_local()* 76 | Disables the URL highlight in the current buffer. 77 | 78 | highlighturl#toggle_local() *highlighturl#toggle_local()* 79 | Toggles the URL highlight in the current buffer. 80 | 81 | highlighturl#default_pattern() *highlighturl#default_pattern()* 82 | Returns the default URL pattern. 83 | 84 | ------------------------------------------------------------------------------ 85 | EXAMPLES *highlighturl-examples* 86 | 87 | Do not load this plugin. > 88 | let g:loaded_highlighturl = 1 89 | < 90 | Load this plugin (so that you can enable the highlight later) but disable the 91 | URL highlight. > 92 | let g:highlighturl_enable = 0 93 | < 94 | Remove the underline from the URL highlight. > 95 | let g:highlighturl_underline = 0 96 | < 97 | Disable the URL highlight in markdown and text filetypes. > 98 | augroup highlighturl-filetype 99 | autocmd! 100 | autocmd FileType markdown,text call highlighturl#disable_local() 101 | augroup END 102 | < 103 | Enable the URL highlight only in JavaScript and HTML filetypes. > 104 | let g:highlighturl_enable = 0 105 | augroup highlighturl-filetype 106 | autocmd! 107 | autocmd FileType javascript,html call highlighturl#enable_local() 108 | augroup END 109 | < 110 | ============================================================================== 111 | CHANGELOG *highlighturl-changelog* 112 | 113 | 0.1 2014-01-24 114 | - Use buffer variables instead of window variables. 115 | - Do not call highlighturl#check_urlcursor() for newer Vim. 116 | 117 | 0.0 2014-01-11 118 | - Initial commit. 119 | 120 | ============================================================================== 121 | vim:tw=78:sw=4:ts=8:ft=help:norl:noet: 122 | -------------------------------------------------------------------------------- /plugin/highlighturl.vim: -------------------------------------------------------------------------------- 1 | " ============================================================================= 2 | " Filename: plugin/highlighturl.vim 3 | " Author: itchyny 4 | " License: MIT License 5 | " Last Change: 2015/03/25 02:53:16. 6 | " ============================================================================= 7 | 8 | if exists('g:loaded_highlighturl') || v:version < 700 || !exists('*matchadd') 9 | finish 10 | endif 11 | let g:loaded_highlighturl = 1 12 | 13 | let s:save_cpo = &cpo 14 | set cpo&vim 15 | 16 | augroup highlighturl 17 | autocmd! 18 | autocmd VimEnter,ColorScheme * call highlighturl#set_highlight() 19 | autocmd VimEnter,FileType,BufEnter,WinEnter * call highlighturl#set_url_match() 20 | if v:version < 704 || v:version == 704 && !has('patch682') 21 | autocmd CursorMoved,CursorMovedI * call highlighturl#check_urlcursor() 22 | endif 23 | augroup END 24 | 25 | let &cpo = s:save_cpo 26 | unlet s:save_cpo 27 | -------------------------------------------------------------------------------- /test/default_pattern.vim: -------------------------------------------------------------------------------- 1 | let s:suite = themis#suite('default_pattern') 2 | let s:assert = themis#helper('assert') 3 | 4 | function! s:suite.default_pattern() 5 | let test_cases = [ 6 | \ ['example.com', ''], 7 | \ ['http://example.com', 'http://example.com'], 8 | \ ['URL is http://example.com.', 'http://example.com'], 9 | \ ['(http://example.com)', 'http://example.com'], 10 | \ ['(http://example.com/sample/(foo_bar))', 'http://example.com/sample/(foo_bar)'], 11 | \ ['(http://example.com/sample/(foo_bar)baz)', 'http://example.com/sample/(foo_bar)baz'], 12 | \ ['(http://example.com/sample/(foo_bar)baz/qux)', 'http://example.com/sample/(foo_bar)baz/qux'], 13 | \ ['[http://example.com/sample/[foo][]]', 'http://example.com/sample/[foo][]'], 14 | \ ['{http://example.com/sample/{foo}}', 'http://example.com/sample/{foo}'], 15 | \ ['{http://example.com/sample/{{bar}}}', 'http://example.com/sample/{{bar}}'], 16 | \ ['http://example.com/_0123456789/sample?foo=bar&baz=qux,', 'http://example.com/_0123456789/sample?foo=bar&baz=qux'], 17 | \ ['https://example.com:9000/sample_sample?foo=bar&baz=qux#id,', 'https://example.com:9000/sample_sample?foo=bar&baz=qux#id'], 18 | \ ['https://example.com', 'https://example.com'], 19 | \ ['https://example.com/foo;', 'https://example.com/foo;'], 20 | \ ['https://example.com/foo..bar', 'https://example.com/foo..bar'], 21 | \ ['https://example.com,', 'https://example.com'], 22 | \ ['https://example.com,https://example.com', 'https://example.com'], 23 | \ ['https://example.com/a,b', 'https://example.com/a,b'], 24 | \ ['https://example.com,htttps://example.com', 'https://example.com,htttps://example.com'], 25 | \ ['https://example.com,http:/', 'https://example.com,http:/'], 26 | \ ['https://example.com/,git@github.com:sample/test', 'https://example.com/'], 27 | \ ['https://example.com?q=https://example.com', 'https://example.com?q=https://example.com'], 28 | \ ['ttp://example.com', 'ttp://example.com'], 29 | \ ['[ftp://www.example.com]', 'ftp://www.example.com'], 30 | \ ['ftps://www.example.com', 'ftps://www.example.com'], 31 | \ ['sftp://www.example.com', 'sftp://www.example.com'], 32 | \ ['Invalid sftps scheme: adjust to ftps: sftps://www.example.com', 'ftps://www.example.com'], 33 | \ ['git@github.com:sample/test,', 'git@github.com:sample/test'], 34 | \ ['HTTPS://EXAMPLE.COM', 'HTTPS://EXAMPLE.COM'], 35 | \ ] 36 | let pattern = highlighturl#default_pattern() 37 | for [str, expected] in test_cases 38 | call s:assert.equal(matchstr(str, pattern), expected) 39 | endfor 40 | endfunction 41 | --------------------------------------------------------------------------------