├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── README.md ├── SyntaxRange.manifest ├── autoload └── SyntaxRange.vim ├── doc └── SyntaxRange.txt └── plugin └── SyntaxRange.vim /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: The plugin isn't working at all or shows wrong or unexpected behavior 4 | title: '' 5 | labels: '' 6 | 7 | --- 8 | **Frequent Issues** 9 | 10 | * **E117: Unknown function: ingo#...**: Have you installed the [ingo-library plugin](http://www.vim.org/scripts/script.php?script_id=4433) (or via [GitHub](https://github.com/inkarkat/vim-ingo-library)) as well, as documented in the _dependencies_ section of the readme and plugin help? 11 | * **Sudden problems after updating**: Did you check out the default _master_ branch? Unless you want to participate in feature development and alpha testing, I would recommend that you switch from _master_ to the _stable_ branch; this way, you'll only update to released versions that are (hopefully) better tested and documented. 12 | * **Neovim**: I don't explicitly consider nor test Neovim compatibility; my plugins are written for Vim. If a plugin can be made to work on Neovim with trivial changes, I wouldn't mind including them, but anything more involved should in my opinion be filed as a compatibility bug against Neovim (as its homepage proclaims: _Fully compatible with Vim's editing model and the Vimscript language._) 13 | 14 | **Describe the bug** 15 | 16 | _A clear and concise description of what the bug is._ 17 | 18 | **How to Reproduce** 19 | 20 | _Detailed steps to reproduce the behavior._ 21 | 22 | **Expected Behavior** 23 | 24 | _A clear and concise description of what you expected to happen._ 25 | 26 | **Environment** 27 | - Plugin version (e.g. stable version _1.10_) / revision _a1b2c3d4_ from the master branch 28 | - Dependency versions (e.g. [ingo-library plugin](https://github.com/inkarkat/vim-ingo-library), or external tool versions) 29 | - Vim version (e.g. _8.1.1234_) Or paste the result of `vim --version`. 30 | - OS: (e.g. _Ubuntu 18.04_, _Windows 10 1809_, _macOS 10.14_) 31 | - Install method: (e.g. manually via Vimball or ZIP file, GitHub clone as pack plugin, Plugin manager _NAME_) 32 | - Other plugins / additional context if you think this could be important 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an enhancement for the plugin 4 | title: '' 5 | labels: enhancement 6 | 7 | --- 8 | 9 | **Motivation** 10 | 11 | _A clear and concise description of what currently is hard to do._ 12 | 13 | **Request and Purpose** 14 | 15 | _A clear and concise description of what you want to happen. Possible fit criteria._ 16 | 17 | **Alternatives** 18 | 19 | _A clear and concise description of any alternative solutions or features you've considered._ 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.msgout 2 | *.msgresult 3 | *.out 4 | *.tap 5 | doc/*.description 6 | doc/*.install 7 | tags 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SYNTAX RANGE 2 | =============================================================================== 3 | _by Ingo Karkat_ 4 | 5 | DESCRIPTION 6 | ------------------------------------------------------------------------------ 7 | 8 | This plugin provides commands and functions to set up regions in the current 9 | buffer that either use a syntax different from the buffer's 'filetype', or 10 | completely ignore the syntax. 11 | 12 | ### SEE ALSO 13 | 14 | - If you also want different buffer options (like indent settings, etc.) for 15 | each syntax region, the OnSyntaxChange.vim plugin ([vimscript #4085](http://www.vim.org/scripts/script.php?script_id=4085)) allows 16 | you to dynamically change the buffer options as you move through the buffer. 17 | 18 | ### RELATED WORKS 19 | 20 | - If the highlighting doesn't work properly, you could alternatively edit the 21 | range(s) in a separate scratch buffer. Plugins like NrrwRgn ([vimscript #3075](http://www.vim.org/scripts/script.php?script_id=3075)) 22 | provide commands to set these up, with automatic syncing back to the 23 | original buffer. 24 | 25 | ### SOURCE 26 | 27 | - [The code to include a different syntax in a region is based on](http://vim.wikia.com/wiki/Different_syntax_highlighting_within_regions_of_a_file) 28 | 29 | USAGE 30 | ------------------------------------------------------------------------------ 31 | 32 | For quick, ad-hoc manipulation of the syntax withing a range of lines, the 33 | following commands are provided: 34 | 35 | :[range]SyntaxIgnore Ignore the buffer's filetype syntax for the current 36 | line / lines in [range]. (Top-level keywords will 37 | still be highlighted.) 38 | This can be a useful fix when some text fragments 39 | confuse the syntax highlighting. (For example, when 40 | buffer syntax set to an inlined here-document is 41 | negatively affected by the foreign code surrounding 42 | the here-document.) 43 | 44 | :[range]SyntaxInclude {filetype} 45 | Use the {filetype} syntax for the current line / lines 46 | in [range]. 47 | 48 | Line numbers in [range] are fixed; i.e. they do not 49 | adapt to inserted / deleted lines. But when in a 50 | range, the last line ($) is interpreted as "end of 51 | file". 52 | 53 | For finer control and use in custom mappings or syntax tweaks, the following 54 | functions can be used. You'll find the details directly in the 55 | .vim/autoload/SyntaxRange.vim implementation file. 56 | 57 | SyntaxRange#Include( {startPattern}, {endPattern}, {filetype} [, {matchGroup} [, {contains}]] ) 58 | Use the {filetype} syntax for the region defined by 59 | {startPattern} and {endPattern}. Optionally highlight 60 | {startPattern} and {endPattern} itself with 61 | {matchGroup}, and additionally allow {contains} groups 62 | inside the region. 63 | SyntaxRange#IncludeEx( {regionDefinition}, {filetype} [, {contains}] ) 64 | Use the {filetype} syntax for the region defined by 65 | {regionDefinition}. Additionally allow {contains} 66 | groups inside the region. 67 | 68 | ### EXAMPLE 69 | 70 | To highlight the text between the markers with C syntax: 71 | ``` 72 | @begin=c@ 73 | int i = 42; 74 | @end=c@ 75 | ``` 76 | 77 | To do this statically, with fixed line numbers, for the first occurrence in 78 | the file: 79 | 80 | :1;/@begin=c@/,/@end=c@/SyntaxInclude c 81 | 82 | The dynamic version will apply to all occurrences, handles changes in the line 83 | numbers, and also can make the markers themselves fade into the background: 84 | 85 | :call SyntaxRange#Include('@begin=c@', '@end=c@', 'c', 'NonText') 86 | 87 | To highlight inline patches inside emails: 88 | 89 | :call SyntaxRange#IncludeEx('start="^changeset\|^Index: \|^diff \|^--- .*\%( ----\)\@ 13 | let s:save_cpo = &cpo 14 | set cpo&vim 15 | 16 | function! SyntaxRange#Include( startPattern, endPattern, filetype, ... ) 17 | "****************************************************************************** 18 | "* PURPOSE: 19 | " Define a syntax region from a:startPattern to a:endPattern that includes the 20 | " syntax for a:filetype. For the common case, this automatically ensures that 21 | " a contained match does not extend beyond a:endPattern (though contained 22 | " syntax items with |:syn-extend| break that), and that the patterns are also 23 | " matched inside all existing (also contained) syntax items. 24 | "* ASSUMPTIONS / PRECONDITIONS: 25 | " None. 26 | "* EFFECTS / POSTCONDITIONS: 27 | " Defines a syntax region synInclude{filetype} for the current buffer. 28 | "* INPUTS: 29 | " a:startPattern Regular expression that specifies the beginning of the 30 | " region |:syn-start|. 31 | " a:endPattern Regular expression that specifies the end of the region 32 | " |:syn-end|. 33 | " a:filetype The filetype syntax to use in the region. 34 | " a:matchGroup Optional highlight group for the a:startPattern and 35 | " a:endPattern matches themselves |:syn-matchgroup|. 36 | " a:contains Optional list of syntax groups allowed to begin inside the 37 | " region |:syn-contains|. Pass "@Spell" to enable spell 38 | " checking inside the region. 39 | "* RETURN VALUES: 40 | " None. 41 | "****************************************************************************** 42 | call SyntaxRange#IncludeEx( 43 | \ printf('%s keepend start="%s" end="%s" containedin=ALL', 44 | \ (a:0 ? 'matchgroup=' . a:1 : ''), 45 | \ escape(a:startPattern, '"'), 46 | \ escape(a:endPattern, '"') 47 | \ ), 48 | \ a:filetype, 49 | \ (a:0 >= 2 ? a:2 : '') 50 | \) 51 | endfunction 52 | function! SyntaxRange#IncludeEx( regionDefinition, filetype, ... ) 53 | "****************************************************************************** 54 | "* PURPOSE: 55 | " Define a syntax region from a:regionDefinition that includes the syntax for 56 | " a:filetype. Use this extended function when you have multiple start- or end 57 | " patterns, skip patterns, want to specify match offsets, control the 58 | " containment, etc. 59 | "* ASSUMPTIONS / PRECONDITIONS: 60 | " None. 61 | "* EFFECTS / POSTCONDITIONS: 62 | " Defines a syntax region synInclude{filetype} for the current buffer. 63 | "* INPUTS: 64 | " a:regionDefinition |:syn-region| definition with at least |:syn-start| and 65 | " |:syn-end|. 66 | " a:filetype The filetype syntax to use in the region. 67 | " a:contains Optional list of syntax groups allowed to begin inside the 68 | " region |:syn-contains|. Pass "@Spell" to enable spell 69 | " checking inside the region. 70 | "* RETURN VALUES: 71 | " None. 72 | "****************************************************************************** 73 | let l:syntaxGroup = 'synInclude' . toupper(a:filetype[0]) . tolower(a:filetype[1:]) 74 | 75 | if exists('b:current_syntax') 76 | let l:current_syntax = b:current_syntax 77 | " Remove current syntax definition, as some syntax files (e.g. cpp.vim) 78 | " do nothing if b:current_syntax is defined. 79 | unlet b:current_syntax 80 | endif 81 | 82 | if ! exists('g:main_syntax') && ! empty(&l:syntax) 83 | let g:main_syntax = &l:syntax 84 | let l:hasSetMainSyntax = 1 85 | endif 86 | 87 | if ! exists('b:SyntaxRange_Included') || b:SyntaxRange_Included.changedtick != b:changedtick 88 | let b:SyntaxRange_Included = {'changedtick': b:changedtick, 'filetypes': []} 89 | endif 90 | 91 | if index(b:SyntaxRange_Included.filetypes, a:filetype) == -1 92 | execute printf('syntax include @%s syntax/%s.vim', l:syntaxGroup, a:filetype) 93 | call add(b:SyntaxRange_Included.filetypes, a:filetype) 94 | endif 95 | 96 | if exists('l:hasSetMainSyntax') 97 | unlet! g:main_syntax 98 | endif 99 | 100 | if exists('l:current_syntax') 101 | let b:current_syntax = l:current_syntax 102 | else 103 | unlet! b:current_syntax 104 | endif 105 | 106 | execute printf('syntax region %s %s contains=@%s%s', 107 | \ l:syntaxGroup, 108 | \ a:regionDefinition, 109 | \ l:syntaxGroup, 110 | \ (a:0 && ! empty(a:1) ? ',' . a:1 : '') 111 | \) 112 | endfunction 113 | 114 | 115 | function! SyntaxRange#SyntaxIgnore( startLnum, endLnum ) 116 | let [l:startLnum, l:endLnum] = [ingo#range#NetStart(a:startLnum), ingo#range#NetEnd(a:endLnum)] 117 | if l:startLnum == l:endLnum 118 | execute printf('syntax match synIgnoreLine /\%%%dl/', l:startLnum) 119 | elseif l:startLnum < l:endLnum && l:endLnum == line('$') 120 | execute printf('syntax match synIgnoreLine /\%%>%dl/', (l:startLnum - 1)) 121 | else 122 | execute printf('syntax match synIgnoreLine /\%%>%dl\%%<%dl/', (l:startLnum - 1), (l:endLnum + 1)) 123 | endif 124 | endfunction 125 | 126 | function! SyntaxRange#SyntaxInclude( startLnum, endLnum, filetype ) 127 | let [l:startLnum, l:endLnum] = [ingo#range#NetStart(a:startLnum), ingo#range#NetEnd(a:endLnum)] 128 | call SyntaxRange#Include( 129 | \ printf('\%%%dl', l:startLnum), 130 | \ (l:startLnum < l:endLnum && l:endLnum == line('$') ? 131 | \ '\%$' : 132 | \ printf('\%%%dl', (l:endLnum + 1)) 133 | \ ), 134 | \ a:filetype 135 | \) 136 | endfunction 137 | 138 | let &cpo = s:save_cpo 139 | unlet s:save_cpo 140 | " vim: set ts=8 sts=4 sw=4 noexpandtab ff=unix fdm=syntax : 141 | -------------------------------------------------------------------------------- /doc/SyntaxRange.txt: -------------------------------------------------------------------------------- 1 | *SyntaxRange.txt* Define a different filetype syntax on regions of a buffer. 2 | 3 | SYNTAX RANGE by Ingo Karkat 4 | *SyntaxRange.vim* 5 | description |SyntaxRange-description| 6 | usage |SyntaxRange-usage| 7 | installation |SyntaxRange-installation| 8 | integration |SyntaxRange-integration| 9 | limitations |SyntaxRange-limitations| 10 | known problems |SyntaxRange-known-problems| 11 | todo |SyntaxRange-todo| 12 | history |SyntaxRange-history| 13 | 14 | ============================================================================== 15 | DESCRIPTION *SyntaxRange-description* 16 | 17 | This plugin provides commands and functions to set up regions in the current 18 | buffer that either use a syntax different from the buffer's 'filetype', or 19 | completely ignore the syntax. 20 | 21 | SEE ALSO * 22 | 23 | - If you also want different buffer options (like indent settings, etc.) for 24 | each syntax region, the OnSyntaxChange.vim plugin (vimscript #4085) allows 25 | you to dynamically change the buffer options as you move through the buffer. 26 | 27 | RELATED WORKS * 28 | 29 | - If the highlighting doesn't work properly, you could alternatively edit the 30 | range(s) in a separate scratch buffer. Plugins like NrrwRgn (vimscript #3075) 31 | provide commands to set these up, with automatic syncing back to the 32 | original buffer. 33 | 34 | SOURCE * 35 | 36 | The code to include a different syntax in a region is based on 37 | http://vim.wikia.com/wiki/Different_syntax_highlighting_within_regions_of_a_file 38 | 39 | ============================================================================== 40 | USAGE *SyntaxRange-usage* 41 | 42 | For quick, ad-hoc manipulation of the syntax withing a range of lines, the 43 | following commands are provided: 44 | *:SyntaxIgnore* 45 | :[range]SyntaxIgnore Ignore the buffer's filetype syntax for the current 46 | line / lines in [range]. (Top-level keywords will 47 | still be highlighted.) 48 | This can be a useful fix when some text fragments 49 | confuse the syntax highlighting. (For example, when 50 | buffer syntax set to an inlined here-document is 51 | negatively affected by the foreign code surrounding 52 | the here-document.) 53 | *:SyntaxInclude* 54 | :[range]SyntaxInclude {filetype} 55 | Use the {filetype} syntax for the current line / lines 56 | in [range]. 57 | 58 | Line numbers in [range] are fixed; i.e. they do not 59 | adapt to inserted / deleted lines. But when in a 60 | range, the last line ($) is interpreted as "end of 61 | file". 62 | 63 | 64 | For finer control and use in custom mappings or syntax tweaks, the following 65 | functions can be used. You'll find the details directly in the 66 | .vim/autoload/SyntaxRange.vim implementation file. 67 | 68 | SyntaxRange#Include( {startPattern}, {endPattern}, {filetype} [, {matchGroup} [, {contains}]] ) 69 | Use the {filetype} syntax for the region defined by 70 | {startPattern} and {endPattern}. Optionally highlight 71 | {startPattern} and {endPattern} itself with 72 | {matchGroup}, and additionally allow {contains} groups 73 | inside the region. 74 | SyntaxRange#IncludeEx( {regionDefinition}, {filetype} [, {contains}] ) 75 | Use the {filetype} syntax for the region defined by 76 | {regionDefinition}. Additionally allow {contains} 77 | groups inside the region. 78 | 79 | EXAMPLE *SyntaxRange-example* 80 | 81 | To highlight the text between the markers with C syntax: 82 | @begin=c@ ~ 83 | int i = 42; ~ 84 | @end=c@ ~ 85 | 86 | To do this statically, with fixed line numbers, for the first occurrence in 87 | the file: > 88 | :1;/@begin=c@/,/@end=c@/SyntaxInclude c 89 | 90 | The dynamic version will apply to all occurrences, handles changes in the line 91 | numbers, and also can make the markers themselves fade into the background: > 92 | :call SyntaxRange#Include('@begin=c@', '@end=c@', 'c', 'NonText') 93 | 94 | 95 | To highlight inline patches inside emails: > 96 | :call SyntaxRange#IncludeEx('start="^changeset\|^Index: \|^diff \|^--- .*\%( ----\)\@ 113 | vim SyntaxRange*.vmb.gz 114 | :so % 115 | To uninstall, use the |:RmVimball| command. 116 | 117 | DEPENDENCIES *SyntaxRange-dependencies* 118 | 119 | - Requires Vim 7.0 or higher. 120 | - Requires the |ingo-library.vim| plugin (vimscript #4433), version 1.022 or 121 | higher. 122 | 123 | ============================================================================== 124 | INTEGRATION *SyntaxRange-integration* 125 | 126 | To automatically include a syntax in a certain {filetype}, you can put the 127 | command into a script in > 128 | ~/.vim/after/syntax/{filetype}/SyntaxInclude.vim 129 | If you want to include a syntax in several (or even all) syntaxes, you can put 130 | this into your |vimrc|: > 131 | :autocmd Syntax * call SyntaxRange#Include(...) 132 | 133 | If you have a filetype1 syntax that includes filetype2 and vice versa, you 134 | will run into |E169|: Command too recursive. This can be solved by inclusion 135 | guards around each invocation. In ~/.vim/after/syntax/filetype1.vim: > 136 | let b:loaded_filetype1_syntax_includes = 1 137 | if !exists('b:loaded_filetype2_syntax_includes') 138 | call SyntaxRange#Include('...', '...', 'filetype2') 139 | endif 140 | ... 141 | unlet b:loaded_filetype1_syntax_includes 142 | And the inverse in ~/.vim/after/syntax/filetype2.vim: > 143 | let b:loaded_filetype2_syntax_includes = 1 144 | if !exists('b:loaded_filetype1_syntax_includes') 145 | call SyntaxRange#Include('...', '...', 'filetype1') 146 | endif 147 | ... 148 | unlet b:loaded_filetype2_syntax_includes 149 | < 150 | ============================================================================== 151 | LIMITATIONS *SyntaxRange-limitations* 152 | 153 | - The original filetype's syntax may interfere with the syntax range, and vice 154 | versa. To define the range with high priority, the commands inject it with 155 | "containedin=ALL". 156 | 157 | KNOWN PROBLEMS *SyntaxRange-known-problems* 158 | 159 | TODO *SyntaxRange-todo* 160 | 161 | IDEAS *SyntaxRange-ideas* 162 | 163 | CONTRIBUTING *SyntaxRange-contribute* 164 | 165 | Report any bugs, send patches, or suggest features via the issue tracker at 166 | https://github.com/inkarkat/vim-SyntaxRange/issues or email (address below). 167 | 168 | ============================================================================== 169 | HISTORY *SyntaxRange-history* 170 | 171 | 1.04 13-Nov-2024 172 | - Allow setting additional contains groups via an optional argument to 173 | SyntaxRange#Include[Ex](). Thanks to Sergey Vlasov for sending a patch. 174 | - Rename the re-inclusion guard from b:SyntaxInclude_IncludedFiletypes (List) 175 | to b:SyntaxInclude_Included (Dict). Handle buffer reload via :edit by making 176 | it dependent on b:changedtick as well. 177 | 178 | 1.03 01-Jul-2017 179 | - SyntaxRange#Include(): Escape double quotes in a:startPattern and 180 | a:endPattern; i.e. handle the patterns transparently. Found in tmsanrinsha's 181 | fork. 182 | - ENH: Avoid to re-include same syntax file if multiple ranges are specified 183 | with :SyntaxInclude / if SyntaxRange#Include[Ex]() is invoked multiple times 184 | per buffer. Found in tmsanrinsha's fork. 185 | 186 | 1.02 23-Apr-2015 187 | - Set main_syntax to the buffer's syntax during :syntax include of the 188 | subordinate syntax script. Some scripts may make special arrangements when 189 | included. Suggested by OOO. 190 | - Handle :.SyntaxInclude and :.SyntaxIgnore on folded lines correctly. Use 191 | ingo#range#NetStart/End(). 192 | - Add dependency to ingo-library (vimscript #4433). *** You need to separately 193 | install ingo-library (vimscript #4433) version 1.022 (or higher)! *** 194 | 195 | 1.01 21-Nov-2013 196 | Avoid "E108: No such variable: b:current_syntax" when the (misbehaving) 197 | included syntax doesn't set it. Reported by o2genum at 198 | http://stackoverflow.com/a/16162412/813602. 199 | 200 | 1.00 13-Aug-2012 201 | First published version. 202 | 203 | 0.01 05-Jul-2012 204 | Started development. 205 | 206 | ============================================================================== 207 | Copyright: (C) 2012-2024 Ingo Karkat 208 | The VIM LICENSE applies to this plugin; see |copyright|. 209 | 210 | Maintainer: Ingo Karkat 211 | ============================================================================== 212 | vim:tw=78:ts=8:ft=help:norl: 213 | -------------------------------------------------------------------------------- /plugin/SyntaxRange.vim: -------------------------------------------------------------------------------- 1 | " SyntaxRange.vim: Define a different filetype syntax on regions of a buffer. 2 | " 3 | " DEPENDENCIES: 4 | " - Requires Vim 7.0 or higher. 5 | " - SyntaxRange.vim autoload script 6 | " 7 | " Copyright: (C) 2012-2017 Ingo Karkat 8 | " The VIM LICENSE applies to this script; see ':help copyright'. 9 | " 10 | " Maintainer: Ingo Karkat 11 | 12 | " Avoid installing twice or when in unsupported Vim version. 13 | if exists('g:loaded_SyntaxRange') || (v:version < 700) 14 | finish 15 | endif 16 | let g:loaded_SyntaxRange = 1 17 | 18 | command! -bar -range SyntaxIgnore call SyntaxRange#SyntaxIgnore(, ) 19 | if v:version < 703 20 | command! -bar -range -nargs=1 SyntaxInclude call SyntaxRange#SyntaxInclude(, , ) 21 | else 22 | command! -bar -range -nargs=1 -complete=syntax SyntaxInclude call SyntaxRange#SyntaxInclude(, , ) 23 | endif 24 | 25 | " vim: set ts=8 sts=4 sw=4 noexpandtab ff=unix fdm=syntax : 26 | --------------------------------------------------------------------------------