├── .gitignore ├── .mailmap ├── .travis.yml ├── Changes ├── LICENSE ├── README.mkdn ├── bin └── text-vimcolor ├── corpus ├── install_vims ├── profile-vim │ ├── .gitignore │ ├── expectation.txt │ ├── profile.vim │ ├── results │ │ └── .gitignore │ └── run.sh ├── prove_each_vim └── simple_test.pl ├── dist.ini ├── inc └── VimCommand.pm ├── lib └── Text │ └── VimColor.pm ├── share ├── define_all.vim ├── light.css ├── light.xsl └── mark.vim └── t ├── .vim └── syntax │ └── tvctestsyn.vim ├── 000-vim-version.t ├── all-syntax-groups.t ├── ansi.t ├── bin.t ├── compare-formats.t ├── data ├── has_tabs.pl ├── hello.c ├── table-borked.xml ├── table-sql.xml ├── table.sql ├── tvctestsyn.ansi ├── tvctestsyn.html ├── tvctestsyn.txt └── tvctestsyn.xml ├── encoding.t ├── html.t ├── input_filename.t ├── lib ├── TVC_Share.pm └── TVC_Test.pm ├── new.t ├── override-options.t ├── share-dir.t ├── tvctestsyn.t ├── untie-std-handles.t ├── vim_let.t ├── vim_options.t └── xml.t /.gitignore: -------------------------------------------------------------------------------- 1 | /Text-VimColor-* 2 | .build 3 | cover_db/ 4 | t/.viminfo 5 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Geoff Richards 2 | Randy Stauner 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: perl 2 | perl: 3 | - "5.26" 4 | - "5.20" 5 | - "5.18" 6 | - "5.8" 7 | 8 | env: 9 | global: 10 | - COVERAGE=1 11 | # Make share dir available to xt so the helpers can use lib instead of blib. 12 | - HARNESS_PERL_SWITCHES="-Mlib=t/lib -MTVC_Share" 13 | - SKIP_POD_LINKCHECK=1 14 | 15 | before_install: 16 | - '[ $TRAVIS_PERL_VERSION = 5.8 ] && unset COVERAGE || :' 17 | - eval $(curl https://travis-perl.github.io/init) --auto 18 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for Text-VimColor 2 | 3 | {{$NEXT}} 4 | 5 | 0.29 2018-12-03T00:24:10Z 6 | 7 | - Add `xhtml5` option. 8 | Thanks to Shlomi Fish! for the pull request (gh-8). 9 | 10 | 0.28 2017-08-07T03:09:07Z 11 | 12 | - Fix tests for 5.26 13 | 14 | 0.27 2017-08-07T01:42:02Z 15 | 16 | - Fix installer for 5.24.1+ 17 | 18 | 0.26 2015-03-21T04:14:25Z 19 | 20 | - Fix test failures for vim 6. 21 | - Use Test::File::ShareDir to simplify testing. 22 | 23 | 0.25 2015-02-28T23:41:39Z 24 | 25 | - Add 'all_syntax_groups' option to enable additional syntax groups 26 | instead of just the primary ones. Thanks Hinrik Örn Sigurðsson! 27 | 28 | 0.24 2014-04-13T18:16:06Z 29 | 30 | - Simplify encoding tests and mark a few as TODO 31 | while the library undergoes some refactoring. 32 | 33 | 0.23 2013-02-02T16:28:57Z 34 | 35 | - Attempt to do the right thing with character strings: 36 | Encode them in UTF-8, tell vim the file encoding (UTF-8), 37 | and return a (decoded) character string. 38 | Thanks to Ricardo Signes for the very helpful report (gh-1). 39 | 40 | 0.22 2012-10-29T23:36:29Z 41 | 42 | - The included 'text-vimcolor' script will attempt to load 43 | Win32::Console::ANSI on windows when printing ANSI to STDOUT 44 | in an attempt to make the output more useful. 45 | - Add a basic test to ensure the script still operates 46 | 47 | 0.21 2012-09-07T00:02:48Z 48 | 49 | - Add 'extra_vim_options' to be able to append options to the defaults 50 | 51 | 0.20 2012-08-11T02:05:18Z 52 | 53 | - Releasing as stable. 54 | 55 | 0.19-TRIAL 2012-07-28T03:44:54Z 56 | 57 | - Use IPC::Open3 for portability instead of doing fork/exec manually. 58 | - Various other fixes to attempt to make this usable on Windows. 59 | Thanks to Yasuhiro Matsumoto (mattn) for helping to port to Windows (gh-5). 60 | 61 | 0.18 2012-07-21T02:22:55Z 62 | 63 | [Bug Fix] 64 | - bin/text-vimcolor: Exit after printing usage when --help is specified 65 | (previous version continued to wait for STDIN). 66 | Thanks to Vyacheslav Matyukhin for the pull req (gh-6). 67 | 68 | [Installaion] 69 | - Try to show any available version information before aborting Makefile.PL 70 | 71 | 0.17 2012-03-22T02:49:27Z 72 | 73 | - Minor installation and test fixes for older systems 74 | 75 | 0.16 2012-03-21T17:38:45Z 76 | 77 | [Installation] 78 | - Simplify version detection using vim script 79 | 80 | [Testing] 81 | - Mark encoding tests as TODO tests for now (still under development) 82 | 83 | 0.15 2012-03-18T23:43:36Z 84 | 85 | [Performance] 86 | - Remove extraneous vim statement that caused delays on 87 | some files. Thanks to Joe Mullally (jhackworth) 88 | for finding this and for the vim profiling tips (gh-2). 89 | 90 | [Installation] 91 | - Abort Makefile.PL before writing Makefile if minimum vim not found 92 | - Try not to hang the installation if an old vim is found 93 | - Lower Term::ANSIColor requirement to 1.03 94 | and make bright colors normal if Term::ANSIColor version < 3 95 | 96 | [Documentation] 97 | - Document that the minimum vim version is 6. 98 | (It has been that way since 2003.) 99 | 100 | [Testing] 101 | - Allow debugging based on TEXT_VIMCOLOR_DEBUG env var 102 | - Attempt to make tests more portable across vim versions 103 | (addressing rt-75829 and a few sparse smoke reports). 104 | - Reorganize the test suite increasing coverage and number. 105 | 106 | 0.14 2011-10-20T17:09:53Z 107 | 108 | - Add test to confirm fix of rt-50646. 109 | - Silence 'untie' warnings. 110 | 111 | 0.13 2011-08-15T23:10:00Z 112 | 113 | [Prereqs] 114 | - Exit Makefile.PL early if `vim` fails to execute. 115 | (Nothing else will work after that.) 116 | - Bump required version of Term::ANSIColor to 3.0. 117 | (Please let me know if this causes problems for anyone.) 118 | 119 | [Dist Meta Changes] 120 | - Convert to Dist::Zilla for releasing 121 | - Use File::ShareDir to manage included files consistently 122 | - Simplify and organize documentation and tests 123 | 124 | 0.12 2011-08-09T19:33:16Z 125 | 126 | [Enhancements] 127 | - Add Term::ANSIColor support 128 | Closes RT #69338. 129 | - Add '-n' (no swapfile) option (thanks hinrik.sig). 130 | Closes RT #45623. 131 | 132 | [Bug Fixes] 133 | - Set $ENV{HOME} to keep user-customized syntax files from 134 | breaking tests. Closes RT #68513. 135 | - Untie STD(IN|OUT|ERR) in child process (thanks shiar). 136 | Closes RT #50646. 137 | 138 | [Maintenance Status Change] 139 | - Co-maintenance granted to Randy Stauner (RWSTAUNER) by PAUSE admins. 140 | Much appreciation to Geoff Richards (GEOFFR) for his initial work. 141 | 142 | 0.11 2006-02-19T19:32:27Z 143 | 144 | * No code changes, just packaging fixes. 145 | 146 | 0.10 2006-02-19T00:22:35Z 147 | 148 | * Be more careful about how 'exec' is called (belt & braces) 149 | 150 | * Improve error reporting. Errors printed by the 'vim' command, 151 | as well as problems reported from 'exec' (like not being able 152 | to find the program) will now be reported (by getting passed 153 | through a temporary file). Also, some 'die' calls were changed 154 | to 'croak'. 155 | 156 | * Allow the 'filetype' option to be overridden for each file 157 | processed, so that an object can be reused for multiple files 158 | of different types. 159 | 160 | * Provide a help/usage message in the text-vimcolor program. 161 | 162 | * Document which other CPAN modules use Text::VimColor, since 163 | you might find one of them be more useful than using it 164 | directly. 165 | 166 | * Various small corrections to the documentation. 167 | 168 | 0.09 2005-02-19T13:28:28Z 169 | 170 | * Allow Vim options to be set with ':let' and provide a default 171 | option to make shell scripts be interpretted as Bash syntax, 172 | since it's a superset of Bourne shell. Added corresponding 173 | options to 'text-vimcolor' script. 174 | 175 | * Added "+set nomodeline" option to Vim for belt-and-braces 176 | security. Vim shouldn't read modelines with the default 177 | configuration enforced by the other options, but there's 178 | no harm being extra cautious. Suggested by Ian Langworth. 179 | 180 | * If the 'vim' command fails, print the correct exit code in 181 | the error message. Thanks to Smylers for the fix, and for 182 | reporting all the following bugs. 183 | (closes CPAN bug #11556). 184 | 185 | * Add documentation for the 'filetype' option to 'new()'. 186 | (closes CPAN bug #11558). 187 | 188 | * Document and test for using a reference to a scalar rather 189 | than just a plain scalar as the 'string' argument to 'new()' 190 | and the argument to 'syntax_mark_string()'. It was already 191 | implemented but was mistakenly documented as a TODO. 192 | (closes CPAN bug #11557). 193 | 194 | * Document potential problem from CPAN bug #11555. 195 | 196 | 0.08 2004-02-25T22:03:17Z 197 | 198 | * Tab characters weren't comming out right (you get "^I" instead 199 | of a literal tab). Added ":set isprint+=9" to mark.vim to fix 200 | that. Spotted and patched by Mario Xerri. 201 | 202 | * For some reason the filetype wasn't getting set right, so I've 203 | changed mark.vim to do ":filetype detect" when it wasn't already 204 | detected, and that seems to make it work. 205 | 206 | * The XML output sometimes produced an extra '>' after the start 207 | tag of the root element. Fixed. 208 | 209 | * Added new file 05xml.t to the test suite and changed most of 210 | the tests to use Test::More instead of Test. 211 | 212 | 0.07 2003-12-09T19:40:11Z 213 | 214 | * Now much faster! By using the '-s' option when Vim is run, we 215 | avoid a 2 second delay while it tells us about the stdout not 216 | being connected to a terminal. This only has an effect in Vim 217 | version 6.2 or later (behaviour changed in patch 6.1.191). 218 | 219 | * Fixed a bug reported by Giuseppe Maxia. When Vim was run, it 220 | didn't do ":filetype on", so passing in a filetype explicitly 221 | didn't work. It only worked if it could auto-detect the filetype. 222 | Added a test in 't/10cmp.t' which checks this, by using a string 223 | as input (so that there's no filename to guess the file type from). 224 | 225 | 0.06 2003-12-01T18:43:13Z 226 | 227 | * The files which were in the 'shared' directory (XSLT and CSS 228 | stylesheets and the Vim script) are now in 'lib/Text/VimColor/' 229 | so that they get installed in a place the module can discover. 230 | Thanks to Giuseppe Maxia and Slaven Rezic for the tips. 231 | 232 | * Path::Class is now used (and is therefore a new dependency) to 233 | construct paths to files more portably. 234 | 235 | * Less confusing one-line description of text-vimcolor script. 236 | * Added the 'MANIFEST' file to itself, so that it gets shipped. 237 | * Distribute this ChangeLog (for my unofficial Debian package) 238 | rather than one generated out of CVS. 239 | 240 | 0.05 2003-11-26T21:59:38Z 241 | 242 | * Include README file in distribution. 243 | 244 | 0.04 2003-11-26T19:54:43Z 245 | 246 | * Fixed bug in the feature which allows us to override where the 247 | Vim script is installed. 248 | 249 | 0.03 2003-11-26T19:40:20Z 250 | 251 | * Changed the namespace of the XML output. This is definitely the 252 | final one. 253 | * Tweaked the behaviour of the 'input_filename()' method. 254 | * Minor adjustments to the documentation. 255 | * Added --debug option to the text-vimcolor program. 256 | 257 | 0.02 2003-09-27T18:28:16Z 258 | 259 | * Added a test suite, although it's not finished yet. 260 | * Deal with unexpected syntax types. 261 | * Throw an error if the input file doesn't exist. 262 | * Brought the documentation up to date. 263 | * Install the output of 'cvs2cl' as an upstream changelog. 264 | 265 | 0.0102 2003-03-13T22:26:41Z 266 | 267 | * Corrected 'Build-Depends' to not depend on Perl 5.8. 268 | * Changed 'Build-Depends' to 'Build-Depends-Indep' to keep Lintian happy. 269 | 270 | 0.0101 2003-01-04T18:44:11Z 271 | 272 | * Initial Release. 273 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is copyright (c) 2002-2006 by Geoff Richards. 2 | 3 | This software is copyright (c) 2011 by Randy Stauner. 4 | 5 | This is free software; you can redistribute it and/or modify it under 6 | the same terms as the Perl 5 programming language system itself. 7 | 8 | Terms of the Perl programming language system itself 9 | 10 | a) the GNU General Public License as published by the Free 11 | Software Foundation; either version 1, or (at your option) any 12 | later version, or 13 | b) the "Artistic License" 14 | 15 | --- The GNU General Public License, Version 1, February 1989 --- 16 | 17 | This software is Copyright (c) 2011 by Randy Stauner. 18 | 19 | This is free software, licensed under: 20 | 21 | The GNU General Public License, Version 1, February 1989 22 | 23 | GNU GENERAL PUBLIC LICENSE 24 | Version 1, February 1989 25 | 26 | Copyright (C) 1989 Free Software Foundation, Inc. 27 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 28 | 29 | Everyone is permitted to copy and distribute verbatim copies 30 | of this license document, but changing it is not allowed. 31 | 32 | Preamble 33 | 34 | The license agreements of most software companies try to keep users 35 | at the mercy of those companies. By contrast, our General Public 36 | License is intended to guarantee your freedom to share and change free 37 | software--to make sure the software is free for all its users. The 38 | General Public License applies to the Free Software Foundation's 39 | software and to any other program whose authors commit to using it. 40 | You can use it for your programs, too. 41 | 42 | When we speak of free software, we are referring to freedom, not 43 | price. Specifically, the General Public License is designed to make 44 | sure that you have the freedom to give away or sell copies of free 45 | software, that you receive source code or can get it if you want it, 46 | that you can change the software or use pieces of it in new free 47 | programs; and that you know you can do these things. 48 | 49 | To protect your rights, we need to make restrictions that forbid 50 | anyone to deny you these rights or to ask you to surrender the rights. 51 | These restrictions translate to certain responsibilities for you if you 52 | distribute copies of the software, or if you modify it. 53 | 54 | For example, if you distribute copies of a such a program, whether 55 | gratis or for a fee, you must give the recipients all the rights that 56 | you have. You must make sure that they, too, receive or can get the 57 | source code. And you must tell them their rights. 58 | 59 | We protect your rights with two steps: (1) copyright the software, and 60 | (2) offer you this license which gives you legal permission to copy, 61 | distribute and/or modify the software. 62 | 63 | Also, for each author's protection and ours, we want to make certain 64 | that everyone understands that there is no warranty for this free 65 | software. If the software is modified by someone else and passed on, we 66 | want its recipients to know that what they have is not the original, so 67 | that any problems introduced by others will not reflect on the original 68 | authors' reputations. 69 | 70 | The precise terms and conditions for copying, distribution and 71 | modification follow. 72 | 73 | GNU GENERAL PUBLIC LICENSE 74 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 75 | 76 | 0. This License Agreement applies to any program or other work which 77 | contains a notice placed by the copyright holder saying it may be 78 | distributed under the terms of this General Public License. The 79 | "Program", below, refers to any such program or work, and a "work based 80 | on the Program" means either the Program or any work containing the 81 | Program or a portion of it, either verbatim or with modifications. Each 82 | licensee is addressed as "you". 83 | 84 | 1. You may copy and distribute verbatim copies of the Program's source 85 | code as you receive it, in any medium, provided that you conspicuously and 86 | appropriately publish on each copy an appropriate copyright notice and 87 | disclaimer of warranty; keep intact all the notices that refer to this 88 | General Public License and to the absence of any warranty; and give any 89 | other recipients of the Program a copy of this General Public License 90 | along with the Program. You may charge a fee for the physical act of 91 | transferring a copy. 92 | 93 | 2. You may modify your copy or copies of the Program or any portion of 94 | it, and copy and distribute such modifications under the terms of Paragraph 95 | 1 above, provided that you also do the following: 96 | 97 | a) cause the modified files to carry prominent notices stating that 98 | you changed the files and the date of any change; and 99 | 100 | b) cause the whole of any work that you distribute or publish, that 101 | in whole or in part contains the Program or any part thereof, either 102 | with or without modifications, to be licensed at no charge to all 103 | third parties under the terms of this General Public License (except 104 | that you may choose to grant warranty protection to some or all 105 | third parties, at your option). 106 | 107 | c) If the modified program normally reads commands interactively when 108 | run, you must cause it, when started running for such interactive use 109 | in the simplest and most usual way, to print or display an 110 | announcement including an appropriate copyright notice and a notice 111 | that there is no warranty (or else, saying that you provide a 112 | warranty) and that users may redistribute the program under these 113 | conditions, and telling the user how to view a copy of this General 114 | Public License. 115 | 116 | d) You may charge a fee for the physical act of transferring a 117 | copy, and you may at your option offer warranty protection in 118 | exchange for a fee. 119 | 120 | Mere aggregation of another independent work with the Program (or its 121 | derivative) on a volume of a storage or distribution medium does not bring 122 | the other work under the scope of these terms. 123 | 124 | 3. You may copy and distribute the Program (or a portion or derivative of 125 | it, under Paragraph 2) in object code or executable form under the terms of 126 | Paragraphs 1 and 2 above provided that you also do one of the following: 127 | 128 | a) accompany it with the complete corresponding machine-readable 129 | source code, which must be distributed under the terms of 130 | Paragraphs 1 and 2 above; or, 131 | 132 | b) accompany it with a written offer, valid for at least three 133 | years, to give any third party free (except for a nominal charge 134 | for the cost of distribution) a complete machine-readable copy of the 135 | corresponding source code, to be distributed under the terms of 136 | Paragraphs 1 and 2 above; or, 137 | 138 | c) accompany it with the information you received as to where the 139 | corresponding source code may be obtained. (This alternative is 140 | allowed only for noncommercial distribution and only if you 141 | received the program in object code or executable form alone.) 142 | 143 | Source code for a work means the preferred form of the work for making 144 | modifications to it. For an executable file, complete source code means 145 | all the source code for all modules it contains; but, as a special 146 | exception, it need not include source code for modules which are standard 147 | libraries that accompany the operating system on which the executable 148 | file runs, or for standard header files or definitions files that 149 | accompany that operating system. 150 | 151 | 4. You may not copy, modify, sublicense, distribute or transfer the 152 | Program except as expressly provided under this General Public License. 153 | Any attempt otherwise to copy, modify, sublicense, distribute or transfer 154 | the Program is void, and will automatically terminate your rights to use 155 | the Program under this License. However, parties who have received 156 | copies, or rights to use copies, from you under this General Public 157 | License will not have their licenses terminated so long as such parties 158 | remain in full compliance. 159 | 160 | 5. By copying, distributing or modifying the Program (or any work based 161 | on the Program) you indicate your acceptance of this license to do so, 162 | and all its terms and conditions. 163 | 164 | 6. Each time you redistribute the Program (or any work based on the 165 | Program), the recipient automatically receives a license from the original 166 | licensor to copy, distribute or modify the Program subject to these 167 | terms and conditions. You may not impose any further restrictions on the 168 | recipients' exercise of the rights granted herein. 169 | 170 | 7. The Free Software Foundation may publish revised and/or new versions 171 | of the General Public License from time to time. Such new versions will 172 | be similar in spirit to the present version, but may differ in detail to 173 | address new problems or concerns. 174 | 175 | Each version is given a distinguishing version number. If the Program 176 | specifies a version number of the license which applies to it and "any 177 | later version", you have the option of following the terms and conditions 178 | either of that version or of any later version published by the Free 179 | Software Foundation. If the Program does not specify a version number of 180 | the license, you may choose any version ever published by the Free Software 181 | Foundation. 182 | 183 | 8. If you wish to incorporate parts of the Program into other free 184 | programs whose distribution conditions are different, write to the author 185 | to ask for permission. For software which is copyrighted by the Free 186 | Software Foundation, write to the Free Software Foundation; we sometimes 187 | make exceptions for this. Our decision will be guided by the two goals 188 | of preserving the free status of all derivatives of our free software and 189 | of promoting the sharing and reuse of software generally. 190 | 191 | NO WARRANTY 192 | 193 | 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 194 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 195 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 196 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 197 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 198 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 199 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 200 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 201 | REPAIR OR CORRECTION. 202 | 203 | 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 204 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 205 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 206 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 207 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 208 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 209 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 210 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 211 | POSSIBILITY OF SUCH DAMAGES. 212 | 213 | END OF TERMS AND CONDITIONS 214 | 215 | Appendix: How to Apply These Terms to Your New Programs 216 | 217 | If you develop a new program, and you want it to be of the greatest 218 | possible use to humanity, the best way to achieve this is to make it 219 | free software which everyone can redistribute and change under these 220 | terms. 221 | 222 | To do so, attach the following notices to the program. It is safest to 223 | attach them to the start of each source file to most effectively convey 224 | the exclusion of warranty; and each file should have at least the 225 | "copyright" line and a pointer to where the full notice is found. 226 | 227 | 228 | Copyright (C) 19yy 229 | 230 | This program is free software; you can redistribute it and/or modify 231 | it under the terms of the GNU General Public License as published by 232 | the Free Software Foundation; either version 1, or (at your option) 233 | any later version. 234 | 235 | This program is distributed in the hope that it will be useful, 236 | but WITHOUT ANY WARRANTY; without even the implied warranty of 237 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 238 | GNU General Public License for more details. 239 | 240 | You should have received a copy of the GNU General Public License 241 | along with this program; if not, write to the Free Software 242 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA 243 | 244 | 245 | Also add information on how to contact you by electronic and paper mail. 246 | 247 | If the program is interactive, make it output a short notice like this 248 | when it starts in an interactive mode: 249 | 250 | Gnomovision version 69, Copyright (C) 19xx name of author 251 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 252 | This is free software, and you are welcome to redistribute it 253 | under certain conditions; type `show c' for details. 254 | 255 | The hypothetical commands `show w' and `show c' should show the 256 | appropriate parts of the General Public License. Of course, the 257 | commands you use may be called something other than `show w' and `show 258 | c'; they could even be mouse-clicks or menu items--whatever suits your 259 | program. 260 | 261 | You should also get your employer (if you work as a programmer) or your 262 | school, if any, to sign a "copyright disclaimer" for the program, if 263 | necessary. Here a sample; alter the names: 264 | 265 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 266 | program `Gnomovision' (a program to direct compilers to make passes 267 | at assemblers) written by James Hacker. 268 | 269 | , 1 April 1989 270 | Ty Coon, President of Vice 271 | 272 | That's all there is to it! 273 | 274 | 275 | --- The Artistic License 1.0 --- 276 | 277 | This software is Copyright (c) 2011 by Randy Stauner. 278 | 279 | This is free software, licensed under: 280 | 281 | The Artistic License 1.0 282 | 283 | The Artistic License 284 | 285 | Preamble 286 | 287 | The intent of this document is to state the conditions under which a Package 288 | may be copied, such that the Copyright Holder maintains some semblance of 289 | artistic control over the development of the package, while giving the users of 290 | the package the right to use and distribute the Package in a more-or-less 291 | customary fashion, plus the right to make reasonable modifications. 292 | 293 | Definitions: 294 | 295 | - "Package" refers to the collection of files distributed by the Copyright 296 | Holder, and derivatives of that collection of files created through 297 | textual modification. 298 | - "Standard Version" refers to such a Package if it has not been modified, 299 | or has been modified in accordance with the wishes of the Copyright 300 | Holder. 301 | - "Copyright Holder" is whoever is named in the copyright or copyrights for 302 | the package. 303 | - "You" is you, if you're thinking about copying or distributing this Package. 304 | - "Reasonable copying fee" is whatever you can justify on the basis of media 305 | cost, duplication charges, time of people involved, and so on. (You will 306 | not be required to justify it to the Copyright Holder, but only to the 307 | computing community at large as a market that must bear the fee.) 308 | - "Freely Available" means that no fee is charged for the item itself, though 309 | there may be fees involved in handling the item. It also means that 310 | recipients of the item may redistribute it under the same conditions they 311 | received it. 312 | 313 | 1. You may make and give away verbatim copies of the source form of the 314 | Standard Version of this Package without restriction, provided that you 315 | duplicate all of the original copyright notices and associated disclaimers. 316 | 317 | 2. You may apply bug fixes, portability fixes and other modifications derived 318 | from the Public Domain or from the Copyright Holder. A Package modified in such 319 | a way shall still be considered the Standard Version. 320 | 321 | 3. You may otherwise modify your copy of this Package in any way, provided that 322 | you insert a prominent notice in each changed file stating how and when you 323 | changed that file, and provided that you do at least ONE of the following: 324 | 325 | a) place your modifications in the Public Domain or otherwise make them 326 | Freely Available, such as by posting said modifications to Usenet or an 327 | equivalent medium, or placing the modifications on a major archive site 328 | such as ftp.uu.net, or by allowing the Copyright Holder to include your 329 | modifications in the Standard Version of the Package. 330 | 331 | b) use the modified Package only within your corporation or organization. 332 | 333 | c) rename any non-standard executables so the names do not conflict with 334 | standard executables, which must also be provided, and provide a separate 335 | manual page for each non-standard executable that clearly documents how it 336 | differs from the Standard Version. 337 | 338 | d) make other distribution arrangements with the Copyright Holder. 339 | 340 | 4. You may distribute the programs of this Package in object code or executable 341 | form, provided that you do at least ONE of the following: 342 | 343 | a) distribute a Standard Version of the executables and library files, 344 | together with instructions (in the manual page or equivalent) on where to 345 | get the Standard Version. 346 | 347 | b) accompany the distribution with the machine-readable source of the Package 348 | with your modifications. 349 | 350 | c) accompany any non-standard executables with their corresponding Standard 351 | Version executables, giving the non-standard executables non-standard 352 | names, and clearly documenting the differences in manual pages (or 353 | equivalent), together with instructions on where to get the Standard 354 | Version. 355 | 356 | d) make other distribution arrangements with the Copyright Holder. 357 | 358 | 5. You may charge a reasonable copying fee for any distribution of this 359 | Package. You may charge any fee you choose for support of this Package. You 360 | may not charge a fee for this Package itself. However, you may distribute this 361 | Package in aggregate with other (possibly commercial) programs as part of a 362 | larger (possibly commercial) software distribution provided that you do not 363 | advertise this Package as a product of your own. 364 | 365 | 6. The scripts and library files supplied as input to or produced as output 366 | from the programs of this Package do not automatically fall under the copyright 367 | of this Package, but belong to whomever generated them, and may be sold 368 | commercially, and may be aggregated with this Package. 369 | 370 | 7. C or perl subroutines supplied by you and linked into this Package shall not 371 | be considered part of this Package. 372 | 373 | 8. The name of the Copyright Holder may not be used to endorse or promote 374 | products derived from this software without specific prior written permission. 375 | 376 | 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED 377 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 378 | MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 379 | 380 | The End 381 | 382 | -------------------------------------------------------------------------------- /README.mkdn: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/rwstauner/Text-VimColor.svg?branch=master)](https://travis-ci.org/rwstauner/Text-VimColor) 2 | [![Coverage Status](https://coveralls.io/repos/rwstauner/Text-VimColor/badge.svg?branch=master)](https://coveralls.io/r/rwstauner/Text-VimColor?branch=master) 3 | [![Kwalitee status](http://cpants.cpanauthors.org/dist/Text-VimColor.png)](http://cpants.charsbar.org/dist/overview/Text-VimColor) 4 | 5 | # NAME 6 | 7 | Text::VimColor - Syntax highlight text using Vim 8 | 9 | # VERSION 10 | 11 | version 0.29 12 | 13 | # SYNOPSIS 14 | 15 | use Text::VimColor; 16 | my $syntax = Text::VimColor->new( 17 | file => $0, 18 | filetype => 'perl', 19 | ); 20 | 21 | print $syntax->html; 22 | print $syntax->xml; 23 | print $syntax->ansi; 24 | 25 | # DESCRIPTION 26 | 27 | This module tries to markup text files according to their syntax. It can 28 | be used to produce web pages with pretty-printed colorful source code 29 | samples. It can produce output in the following formats: 30 | 31 | - HTML 32 | 33 | Valid XHTML 1.0, with the exact coloring and style left to a CSS stylesheet 34 | 35 | - XML 36 | 37 | Pieces of text are marked with XML elements in a simple vocabulary, 38 | which can be converted to other formats, for example, using XSLT 39 | 40 | - Perl array 41 | 42 | A simple Perl data structure, so that Perl code can be used to turn it 43 | into whatever is needed 44 | 45 | - ANSI Escape Sequences 46 | 47 | A string marked with [Term::ANSIColor](https://metacpan.org/pod/Term::ANSIColor) 48 | suitable for printing to a terminal. 49 | 50 | This module works by running the Vim text editor and getting it to apply its 51 | excellent syntax highlighting (aka 'font-locking') to an input file, and mark 52 | pieces of text according to whether it thinks they are comments, keywords, 53 | strings, etc. The Perl code then reads back this markup and converts it 54 | to the desired output format. 55 | 56 | This is an object-oriented module. To use it, create an object with 57 | the ["new"](#new) function (as shown in ["SYNOPSIS"](#synopsis)) and then call methods 58 | to get the markup out. 59 | 60 | # METHODS 61 | 62 | ## new 63 | 64 | my $tvc = Text::VimColor->new(%options) 65 | 66 | Returns a syntax highlighting object. Pass it a hash of options. 67 | 68 | The following options are recognized: 69 | 70 | - file 71 | 72 | The file to syntax highlight. Can be either a filename or an open file handle. 73 | 74 | Note that using a filename might allow Vim to guess the file type from its 75 | name if none is specified explicitly. 76 | 77 | If the file isn't specified while creating the object, it can be given later 78 | in a call to the ["syntax\_mark\_file"](#syntax_mark_file) method (see below), allowing a single 79 | `Text::VimColor` object to be used with multiple input files. 80 | 81 | - string 82 | 83 | Use this to pass a string to be used as the input. This is an alternative 84 | to the `file` option. A reference to a string will also work. 85 | 86 | The ["syntax\_mark\_string"](#syntax_mark_string) method is another way to use a string as input. 87 | 88 | If you provide a character (unencoded) string (recommended) 89 | it will be passed to vim encoded in UTF-8 90 | and your result will be character string. 91 | 92 | - filetype 93 | 94 | Specify the type of file Vim should expect, in case Vim's automatic 95 | detection by filename or contents doesn't get it right. This is 96 | particularly important when providing the file as a string or file 97 | handle, since Vim won't be able to use the file extension to guess 98 | the file type. 99 | 100 | The file types recognized by Vim are short strings like 'perl' or 'lisp'. 101 | They are the names of files in the 'syntax' directory in the Vim 102 | distribution. 103 | 104 | This option, whether or not it is passed to ["new"](#new), can be overridden 105 | when calling ["syntax\_mark\_file"](#syntax_mark_file) and ["syntax\_mark\_string"](#syntax_mark_string), so you can 106 | use the same object to process multiple files of different types. 107 | 108 | - all\_syntax\_groups 109 | 110 | By default, this option is disabled. That means that the highlighting will 111 | only use the following syntax groups: 112 | 113 | Comment 114 | Constant 115 | Identifier 116 | Statement 117 | PreProc 118 | Type 119 | Special 120 | Underlined 121 | Ignore 122 | Error 123 | Todo 124 | 125 | This mirrors vim's default behavior of linking more specific syntax groups 126 | to the main groups above. However, most syntax files support more specific 127 | groups, so if you want to benefit from finer-grained syntax highlighting 128 | you can turn on this option. The additional syntax groups are: 129 | 130 | Group Linked to by default 131 | --------------------------------------- 132 | String Constant 133 | Character Constant 134 | Number Constant 135 | Boolean Constant 136 | Float Constant 137 | Function Identifier 138 | Conditional Statement 139 | Repeat Statement 140 | Label Statement 141 | Operator Statement 142 | Keyword Statement 143 | Exception Statement 144 | Include PreProc 145 | Define PreProc 146 | Macro PreProc 147 | PreCondit PreProc 148 | StorageClass Type 149 | Structure Type 150 | Typedef Type 151 | Tag Special 152 | SpecialChar Special 153 | Delimiter Special 154 | SpecialComment Special 155 | Debug Special 156 | 157 | - html\_full\_page 158 | 159 | By default the ["html"](#html) output method returns a fragment of HTML, not a 160 | full file. To make useful output this must be wrapped in a `
`
161 |     element and a stylesheet must be included from somewhere.  Setting the
162 |     ["html\_full\_page"](#html_full_page) option will instead make the ["html"](#html) method return a
163 |     complete stand-alone XHTML file.
164 | 
165 |     Note that while this is useful for testing, most of the time you'll want to
166 |     put the syntax highlighted source code in a page with some other content,
167 |     in which case the default output of the ["html"](#html) method is more appropriate.
168 | 
169 | - html\_inline\_stylesheet
170 | 
171 |     Turned on by default, but has no effect unless ["html\_full\_page"](#html_full_page) is also
172 |     enabled.
173 | 
174 |     This causes the CSS stylesheet defining the colors to be used
175 |     to render the markup to be be included in the HTML output, in a
176 |     `\n";
 295 |    }
 296 |    else {
 297 |       $stylesheet =
 298 |          "{html_stylesheet_url} ||
 300 |                      "file://${\ file($self->dist_file('light.css'))->as_foreign('Unix') }") .
 301 |          "\" />\n";
 302 |    }
 303 | 
 304 |    my $head = $xhtml5
 305 |    ? <<"EOF"
 306 | 
 307 | 
 308 | 
 309 | EOF
 310 |    : <<"EOF";
 311 | 
 313 | 
 314 | EOF
 315 | 
 316 |    my $meta = $xhtml5 ? qq{} : '';
 317 |    return
 318 |    $head
 319 |    . " \n"
 320 |    . "  $title\n"
 321 |    . $meta . "\n"
 322 |    . "  $stylesheet"
 323 |    . " \n"
 324 |    . " \n\n" . "
";
 325 | }
 326 | 
 327 | # Return a string safe to put in XML text or attribute values.  It doesn't
 328 | # escape single quotes (') because we don't use those to quote
 329 | # attribute values.
 330 | sub _xml_escape
 331 | {
 332 |    my ($s) = @_;
 333 |    $s =~ s/&/&/g;
 334 |    $s =~ s//>/g;
 336 |    $s =~ s/"/"/g;
 337 |    return $s;
 338 | }
 339 | 
 340 | # Actually run Vim and turn the script's output into a datastructure.
 341 | sub _do_markup
 342 | {
 343 |    my ($self) = @_;
 344 |    my $vim_syntax_script = $self->dist_file('mark.vim');
 345 |    my $vim_define_all = $self->dist_file('define_all.vim');
 346 | 
 347 |    croak "Text::VimColor syntax script '$vim_syntax_script' not installed"
 348 |       unless -f $vim_syntax_script && -r $vim_syntax_script;
 349 | 
 350 |    if ($DEBUG) {
 351 |       print STDERR __PACKAGE__."::_do_markup: script: $vim_syntax_script\n";
 352 |    }
 353 | 
 354 |   my $encoding = $self->{encoding} || '';
 355 |   my $binmode = ':raw';
 356 | 
 357 |    my $filename = $self->{file};
 358 |    my $input_is_temporary = 0;
 359 | 
 360 |    if (ref $self->{file}) {
 361 |       my $fh;
 362 |       ($fh, $filename) = tempfile();
 363 |       $input_is_temporary = 1;
 364 | 
 365 |       binmode $self->{file};
 366 |       binmode $fh;
 367 |       copy($self->{file}, $fh);
 368 |    }
 369 |    elsif (exists $self->{string}) {
 370 |       my $fh;
 371 |       ($fh, $filename) = tempfile();
 372 |       $input_is_temporary = 1;
 373 | 
 374 |       my $string = (ref $self->{string} ? ${ $self->{string} } : $self->{string});
 375 | 
 376 |       if( HAVE_ENCODING ){
 377 |         if( utf8::is_utf8($string) ){
 378 |           $encoding ||= 'UTF-8';
 379 |           $binmode = ":encoding($encoding)"
 380 |             if $encoding;
 381 |         }
 382 |       }
 383 | 
 384 |       binmode $fh, $binmode;
 385 |       print $fh $string;
 386 |    }
 387 |    else {
 388 |       croak "input file '$filename' not found"
 389 |          unless -f $filename;
 390 |       croak "input file '$filename' not accessible"
 391 |          unless -r $filename;
 392 |    }
 393 | 
 394 |    # Create a temp file to put the output in.
 395 |    my ($out_fh, $out_filename) = tempfile();
 396 | 
 397 |    # Create a temp file for the 'script', which is given to vim
 398 |    # with the -s option.  This is necessary because it tells Vim not
 399 |    # to delay for 2 seconds after displaying a message.
 400 |    my ($script_fh, $script_filename) = tempfile();
 401 |    my $filetype = $self->{filetype};
 402 |    my $filetype_set = defined $filetype ? ":set filetype=$filetype" : '';
 403 |    my $vim_let = $self->{vim_let};
 404 | 
 405 |   # on linux '-s' is fast and '--cmd' adds the 2-second startup delay
 406 |   # are there situations where --cmd is necessary or useful?
 407 |   # XXX: for debugging, may be removed in the future
 408 |   my $use_cmd_opt = $ENV{TEXT_VIMCOLOR_CMD_OPT};
 409 | 
 410 |   # Specify filename as argument to command (rather than using :edit in script).
 411 |   # If using --cmd then the filename needs to be in the script.
 412 |   # For some reason windows doesn't seem to like the filename being in the arg list.
 413 |   # Are there other times that this is needed?
 414 |   my $file_as_arg = ($use_cmd_opt || $^O ne 'MSWin32');
 415 | 
 416 |   my @script_lines = (
 417 |     map { "$_\n" }
 418 |       # The default 'encoding' comes from env so set it explicitly to avoid
 419 |       # conversion from 'encoding' to 'fileencoding'.
 420 |       # Set 'fileencodings' so vim doesn't try to choose.
 421 |       # Set 'nomodified' after 'fenc' so vim doesn't prompt for unsaved changes.
 422 |       ($encoding ?
 423 |         ":set encoding=$encoding fileencodings=$encoding fileencoding=$encoding nomodified"
 424 |         : ()),
 425 | 
 426 |       # do :edit before :let or the buffer variables may get reset
 427 |       (!$file_as_arg ? ":edit $filename" : ()),
 428 | 
 429 |       (
 430 |         map  { ":let $_=$vim_let->{$_}" }
 431 |         grep { defined  $vim_let->{$_} }
 432 |           keys %$vim_let
 433 |       ),
 434 | 
 435 |       ':filetype on',
 436 |        $filetype_set,
 437 |        $self->{all_syntax_groups} ? ":source $vim_define_all" : (),
 438 |       ":source $vim_syntax_script",
 439 |       ":write! $out_filename",
 440 |       ':qall!',
 441 |   );
 442 | 
 443 |   print STDERR map { __PACKAGE__ . " | $_" } @script_lines if $DEBUG;
 444 | 
 445 |    print $script_fh @script_lines;
 446 |    close $script_fh;
 447 | 
 448 |   # TODO: it seems we may need to localize and delete $ENV{LANG}
 449 |   # to enable encodings other than utf-8 to work.
 450 |    $self->_run(
 451 |       $self->{vim_command},
 452 |       $self->vim_options,
 453 |       ($file_as_arg ? $filename : ()),
 454 |       (
 455 |         $use_cmd_opt
 456 |           ? ( '--cmd' => "silent! so $script_filename" )
 457 |           : ( '-s'    => $script_filename )
 458 |       ),
 459 |    );
 460 | 
 461 |    unlink $filename
 462 |       if $input_is_temporary;
 463 |    unlink $out_filename;
 464 |    unlink $script_filename;
 465 | 
 466 |   binmode $out_fh, $binmode;
 467 | 
 468 |    my $data = do { local $/; <$out_fh> };
 469 | 
 470 |    # Convert line endings to ones appropriate for the current platform.
 471 |    $data =~ s/\x0D\x0A?/\n/g;
 472 | 
 473 |    my $syntax = [];
 474 |    LOOP: {
 475 |       _add_markup($syntax, $1, $2), redo LOOP
 476 |          if $data =~ /\G>(.*?)>(.*?)<\1]+)/cgs;
 479 |    }
 480 | 
 481 |    $self->{syntax} = $syntax;
 482 | }
 483 | 
 484 | # Given an array ref ($syntax), we add a new syntax chunk to it, unescaping
 485 | # the text and making sure that consecutive chunks of the same type are
 486 | # merged.
 487 | sub _add_markup
 488 | {
 489 |    my ($syntax, $type, $text) = @_;
 490 | 
 491 |    # Ignore types we don't know about.  At least one syntax file (xml.vim)
 492 |    # can produce these.  It happens when a syntax type isn't 'linked' to
 493 |    # one of the predefined types.
 494 |    $type = ''
 495 |       unless exists $SYNTAX_TYPE{$type};
 496 | 
 497 |    # Unescape ampersands and pointies.
 498 |    $text =~ s/&l//g;
 500 |    $text =~ s/&a/&/g;
 501 | 
 502 |    if (@$syntax && $syntax->[-1][0] eq $type) {
 503 |       # Concatenate consecutive bits of the same type.
 504 |       $syntax->[-1][1] .= $text;
 505 |    }
 506 |    else {
 507 |       # A new chunk of marked-up text.
 508 |       push @$syntax, [ $type, $text ];
 509 |    }
 510 | }
 511 | 
 512 | # This is a private internal method which runs a program.
 513 | # It takes a list of the program name and arguments.
 514 | sub _run
 515 | {
 516 |    my ($self, $prog, @args) = @_;
 517 | 
 518 |    if ($DEBUG) {
 519 |       print STDERR __PACKAGE__."::_run: $prog " .
 520 |             join(' ', map { "'$_'" } @args) . "\n";
 521 |    }
 522 | 
 523 |   {
 524 |     my ($in, $out) = (Symbol::gensym(), Symbol::gensym());
 525 |     my $err_fh = Symbol::gensym();
 526 | 
 527 |     my $pid = IPC::Open3::open3($in, $out, $err_fh, $prog => @args);
 528 | 
 529 |     # close these to avoid any ambiguity that might cause this to block
 530 |     # (see also the paragraph about "select" in IPC::Open3)
 531 |     close($in);
 532 |     close($out);
 533 | 
 534 |     # read handle before waitpid to avoid hanging on older systems
 535 |     my $errout = do { local $/; <$err_fh> };
 536 | 
 537 |       my $gotpid = waitpid($pid, 0);
 538 |       croak "couldn't run the program '$prog'" if $gotpid == -1;
 539 |       my $error = $? >> 8;
 540 |       if ($error) {
 541 |          $errout =~ s/\n+\z//;
 542 |          my $details = $errout eq '' ? '' :
 543 |                        "\nVim wrote this error output:\n$errout\n";
 544 |          croak "$prog returned an error code of '$error'$details";
 545 |       }
 546 |    }
 547 | }
 548 | 
 549 | sub vim_options {
 550 |   my ($self) = @_;
 551 |   return (
 552 |     @{ $self->{vim_options} },
 553 |     @{ $self->{extra_vim_options} },
 554 |   );
 555 | }
 556 | 
 557 | 1;
 558 | 
 559 | =head1 SYNOPSIS
 560 | 
 561 |    use Text::VimColor;
 562 |    my $syntax = Text::VimColor->new(
 563 |       file => $0,
 564 |       filetype => 'perl',
 565 |    );
 566 | 
 567 |    print $syntax->html;
 568 |    print $syntax->xml;
 569 |    print $syntax->ansi;
 570 | 
 571 | =head1 DESCRIPTION
 572 | 
 573 | This module tries to markup text files according to their syntax.  It can
 574 | be used to produce web pages with pretty-printed colorful source code
 575 | samples.  It can produce output in the following formats:
 576 | 
 577 | =over 4
 578 | 
 579 | =item HTML
 580 | 
 581 | Valid XHTML 1.0, with the exact coloring and style left to a CSS stylesheet
 582 | 
 583 | =item XML
 584 | 
 585 | Pieces of text are marked with XML elements in a simple vocabulary,
 586 | which can be converted to other formats, for example, using XSLT
 587 | 
 588 | =item Perl array
 589 | 
 590 | A simple Perl data structure, so that Perl code can be used to turn it
 591 | into whatever is needed
 592 | 
 593 | =item ANSI Escape Sequences
 594 | 
 595 | A string marked with L
 596 | suitable for printing to a terminal.
 597 | 
 598 | =back
 599 | 
 600 | This module works by running the Vim text editor and getting it to apply its
 601 | excellent syntax highlighting (aka 'font-locking') to an input file, and mark
 602 | pieces of text according to whether it thinks they are comments, keywords,
 603 | strings, etc.  The Perl code then reads back this markup and converts it
 604 | to the desired output format.
 605 | 
 606 | This is an object-oriented module.  To use it, create an object with
 607 | the L function (as shown in L) and then call methods
 608 | to get the markup out.
 609 | 
 610 | =method new
 611 | 
 612 |   my $tvc = Text::VimColor->new(%options)
 613 | 
 614 | Returns a syntax highlighting object.  Pass it a hash of options.
 615 | 
 616 | The following options are recognized:
 617 | 
 618 | =over 4
 619 | 
 620 | =item file
 621 | 
 622 | The file to syntax highlight.  Can be either a filename or an open file handle.
 623 | 
 624 | Note that using a filename might allow Vim to guess the file type from its
 625 | name if none is specified explicitly.
 626 | 
 627 | If the file isn't specified while creating the object, it can be given later
 628 | in a call to the L method (see below), allowing a single
 629 | C object to be used with multiple input files.
 630 | 
 631 | =item string
 632 | 
 633 | Use this to pass a string to be used as the input.  This is an alternative
 634 | to the C option.  A reference to a string will also work.
 635 | 
 636 | The L method is another way to use a string as input.
 637 | 
 638 | If you provide a character (unencoded) string (recommended)
 639 | it will be passed to vim encoded in UTF-8
 640 | and your result will be character string.
 641 | 
 642 | =item filetype
 643 | 
 644 | Specify the type of file Vim should expect, in case Vim's automatic
 645 | detection by filename or contents doesn't get it right.  This is
 646 | particularly important when providing the file as a string or file
 647 | handle, since Vim won't be able to use the file extension to guess
 648 | the file type.
 649 | 
 650 | The file types recognized by Vim are short strings like 'perl' or 'lisp'.
 651 | They are the names of files in the 'syntax' directory in the Vim
 652 | distribution.
 653 | 
 654 | This option, whether or not it is passed to L, can be overridden
 655 | when calling L and L, so you can
 656 | use the same object to process multiple files of different types.
 657 | 
 658 | =item all_syntax_groups
 659 | 
 660 | By default, this option is disabled. That means that the highlighting will
 661 | only use the following syntax groups:
 662 | 
 663 |   Comment
 664 |   Constant
 665 |   Identifier
 666 |   Statement
 667 |   PreProc
 668 |   Type
 669 |   Special
 670 |   Underlined
 671 |   Ignore
 672 |   Error
 673 |   Todo
 674 | 
 675 | This mirrors vim's default behavior of linking more specific syntax groups
 676 | to the main groups above. However, most syntax files support more specific
 677 | groups, so if you want to benefit from finer-grained syntax highlighting
 678 | you can turn on this option. The additional syntax groups are:
 679 | 
 680 |   Group             Linked to by default
 681 |   ---------------------------------------
 682 |   String            Constant
 683 |   Character         Constant
 684 |   Number            Constant
 685 |   Boolean           Constant
 686 |   Float             Constant
 687 |   Function          Identifier
 688 |   Conditional       Statement
 689 |   Repeat            Statement
 690 |   Label             Statement
 691 |   Operator          Statement
 692 |   Keyword           Statement
 693 |   Exception         Statement
 694 |   Include           PreProc
 695 |   Define            PreProc
 696 |   Macro             PreProc
 697 |   PreCondit         PreProc
 698 |   StorageClass      Type
 699 |   Structure         Type
 700 |   Typedef           Type
 701 |   Tag               Special
 702 |   SpecialChar       Special
 703 |   Delimiter         Special
 704 |   SpecialComment    Special
 705 |   Debug             Special
 706 | 
 707 | =item html_full_page
 708 | 
 709 | By default the L output method returns a fragment of HTML, not a
 710 | full file.  To make useful output this must be wrapped in a C<< 
 >>
 711 | element and a stylesheet must be included from somewhere.  Setting the
 712 | L option will instead make the L method return a
 713 | complete stand-alone XHTML file.
 714 | 
 715 | Note that while this is useful for testing, most of the time you'll want to
 716 | put the syntax highlighted source code in a page with some other content,
 717 | in which case the default output of the L method is more appropriate.
 718 | 
 719 | =item html_inline_stylesheet
 720 | 
 721 | Turned on by default, but has no effect unless L is also
 722 | enabled.
 723 | 
 724 | This causes the CSS stylesheet defining the colors to be used
 725 | to render the markup to be be included in the HTML output, in a
 726 | C<< !s);
179 | 
180 |     if( $val ){
181 |       like $val, $re, "style: $key";
182 |     }
183 |     else {
184 |       ok 0, "failed to match $type style for $key";
185 |       diag $html;
186 |     }
187 |   }
188 | }
189 | 
190 | sub record_test {
191 |   my $key = pop @_;
192 |   my $t = find_test(@_);
193 |   die "unknown test: @_ $key"
194 |     unless $t && exists $t->{ $key };
195 |   $t->{ $key }++;
196 | }
197 | 
198 | sub find_test {
199 |   my $find = $tests;
200 |   $find = $find->{ $_ } for @_;
201 |   $find;
202 | }
203 | 
204 | sub check_all_tested {
205 |   my $check = find_test(@_);
206 |   is( (scalar grep { $_ < 1 } values %$check), 0,
207 |     "all options tested for @_");
208 | }
209 | 


--------------------------------------------------------------------------------
/t/input_filename.t:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | 
 3 | use strict;
 4 | use warnings;
 5 | use Test::More 0.88;
 6 | use lib 't/lib';
 7 | use TVC_Test;
 8 | 
 9 | is tvc()->input_filename, undef,
10 |   'undef without filename or string specified';
11 | 
12 | my $file = file(qw(t data hello.c))->stringify;
13 | 
14 | is tvc(file => $file)->input_filename, $file,
15 |   'matches file provided';
16 | 
17 | open(my $fh, '<', $file);
18 | 
19 | is tvc(file => $fh)->input_filename, undef,
20 |   'undef for handles';
21 | 
22 | close $fh;
23 | 
24 | is tvc(string => 'if(1){}')->input_filename, undef,
25 |   'undef when input is a string';
26 | 
27 | done_testing;
28 | 


--------------------------------------------------------------------------------
/t/lib/TVC_Share.pm:
--------------------------------------------------------------------------------
 1 | use strict;
 2 | use warnings;
 3 | 
 4 | package # no_index
 5 |   TVC_Share;
 6 | 
 7 | # Use a separate module to initiate the test share dir
 8 | # so that we can pass a simple -MTVC_Share to perl for subprocesses.
 9 | 
10 | use Test::File::ShareDir::Dist { 'Text-VimColor' => 'share/' };
11 | 
12 | 1;
13 | 


--------------------------------------------------------------------------------
/t/lib/TVC_Test.pm:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | use strict;
 3 | use warnings;
 4 | 
 5 | package # hide from indexer
 6 |   TVC_Test;
 7 | 
 8 | use Path::Class 0.04 qw( file dir ); # mkpath
 9 | use TVC_Share;
10 | 
11 | sub perl {
12 |   qx{$^X -Ilib -It/lib -MTVC_Share @_};
13 | }
14 | 
15 | # don't allow user-customized syntax files to throw off test results
16 | $ENV{HOME} = dir('t')->absolute;
17 | 
18 | if( $^O eq 'MSWin32' ){
19 |   $ENV{USERPROFILE} = $ENV{HOME};
20 | 
21 |   # NOTE: we'll need to simulate cp -r if we ever add any other files
22 |   my ($src, $dest) =
23 |     map { file(t => $_, qw(syntax tvctestsyn.vim)) }
24 |       qw( .vim vimfiles );
25 | 
26 |   if( !-e $dest ){
27 |     $dest->parent->mkpath;
28 |     require File::Copy; # core
29 |     File::Copy::copy($src, $dest);
30 |   }
31 | }
32 | 
33 | use Text::VimColor;
34 | use Path::Class qw(file dir);
35 | use Exporter ();
36 | our @ISA = qw(Exporter);
37 | our @EXPORT = qw(
38 |   ansi_color
39 |   file
40 |   dir
41 |   perl
42 |   slurp_data
43 |   syntax_type_exists
44 |   tvc
45 |   xml_minus_filename
46 | );
47 | 
48 | sub ansi_color {
49 |   $Text::VimColor::ANSI_COLORS{ $_[0] };
50 | }
51 | 
52 | sub slurp_data {
53 |   my ($filename) = @_;
54 |   $filename = file('t', 'data', $filename)->stringify;
55 |   open my $file, '<', $filename
56 |     or die "error opening file '$filename': $!";
57 | 
58 |   return do { local $/; <$file> };
59 | }
60 | 
61 | sub syntax_type_exists {
62 |   exists $Text::VimColor::SYNTAX_TYPE{ $_[0] };
63 | }
64 | 
65 | sub tvc {
66 |   main::new_ok('Text::VimColor', [@_])
67 | }
68 | 
69 | sub xml_minus_filename {
70 |   my ($xml) = @_;
71 |   $xml =~ s{^()}{$1$2}s;
72 |   $xml;
73 | }
74 | 
75 | 1;
76 | 


--------------------------------------------------------------------------------
/t/new.t:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | 
 3 | use strict;
 4 | use warnings;
 5 | use Test::More;
 6 | use lib 't/lib';
 7 | use TVC_Test;
 8 | 
 9 | # string or file, not both
10 | is eval { Text::VimColor->new( file => 'foo', string => 'bar') }, undef,
11 |   "new() dies when given both 'string' and 'file'";
12 | like $@, qr/only one of the 'file' or 'string' options/,
13 |   "the 'string' and 'file' options should be mutually exclusive";
14 | 
15 | # neither (causes marked() to die)
16 | my $syntax = Text::VimColor->new;
17 | isa_ok($syntax, 'Text::VimColor');
18 | 
19 | is eval { $syntax->marked; 1 }, undef,
20 |   'without a filename or string specified, marked() should die';
21 | like $@, qr/an input file or string must be specified/,
22 |   'error message states that intput is required';
23 | 
24 | # We should get a sensible error message if the named file isn't there.
25 | is eval { Text::VimColor->new( file => 'file-that-does-not.exist' ) }, undef,
26 |   'new dies when the specified file does not exist';
27 | like($@, qr/input file '.*' not found/,
28 |   "check we get the right error if the file doesn't exist");
29 | 
30 | # test default and custom options
31 | foreach my $test (
32 |   [vim_command              => 'vim', '/specific/vim'],
33 |   # vim_options has it's own script
34 |   [html_inline_stylesheet   => 1, 0],
35 |   [xml_root_element         => 1, 0],
36 |   # vim_let has it's own script
37 | ){
38 |   my ($name, $default, $override) = @$test;
39 |   # don't look, we're breaking encapsulation
40 |   is tvc(                  )->{ $name }, $default,  "default $name";
41 |   is tvc($name => $override)->{ $name }, $override, "override $name";
42 | }
43 | 
44 | done_testing;
45 | 


--------------------------------------------------------------------------------
/t/override-options.t:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | # Test that options in calls syntax_mark_file() and syntax_mark_string()
 3 | # override the ones passed to new().
 4 | 
 5 | use strict;
 6 | use warnings;
 7 | use Test::More;
 8 | use lib 't/lib';
 9 | use TVC_Test;
10 | 
11 | plan tests => 4;
12 | 
13 | my $syntax = Text::VimColor->new(
14 |    filetype => 'perl',
15 | );
16 | 
17 | my $input_filename  = file('t', 'data', 'table.sql')->stringify;
18 | my $input           = slurp_data('table.sql');
19 | my $expected_sql    = slurp_data('table-sql.xml');
20 | my $expected_borked = slurp_data('table-borked.xml');
21 | 
22 | $syntax->syntax_mark_file($input_filename, filetype => 'sql');
23 | my $output = xml_minus_filename($syntax->xml);
24 | is($output, $expected_sql, 'syntax_mark_file options override defaults');
25 | 
26 | $syntax->syntax_mark_file($input_filename);
27 | $output = xml_minus_filename($syntax->xml);
28 | is($output, $expected_borked, 'syntax_mark_file goes back to defaults');
29 | 
30 | $syntax->syntax_mark_string($input, filetype => 'sql');
31 | is($syntax->xml, $expected_sql, 'syntax_mark_string options override defaults');
32 | 
33 | $syntax->syntax_mark_string($input);
34 | is($syntax->xml, $expected_borked, 'syntax_mark_string is back to defaults');
35 | 


--------------------------------------------------------------------------------
/t/share-dir.t:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | 
 3 | use strict;
 4 | use warnings;
 5 | use Test::More;
 6 | use lib 't/lib';
 7 | use TVC_Test;
 8 | 
 9 | my %files =
10 |   map { ($_ => Text::VimColor->dist_file($_)) }
11 |     qw(
12 |       define_all.vim
13 |       light.css
14 |       light.xsl
15 |       mark.vim
16 |     );
17 | 
18 | plan tests => scalar keys %files;
19 | 
20 | while( my ($name, $path) = each %files ){
21 |   ok( -e $path, "dist file '$name' exists at $path")
22 | }
23 | 


--------------------------------------------------------------------------------
/t/tvctestsyn.t:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | # Test exact output against a syntax file we define.
 3 | 
 4 | use strict;
 5 | use warnings;
 6 | use Test::More;
 7 | use lib 't/lib';
 8 | use TVC_Test;
 9 | 
10 | # clear out possible user customizations that could upset the tests
11 | $ENV{TEXT_VIMCOLOR_ANSI} = '';
12 | 
13 | my @formats = qw(
14 |   html
15 |   xml
16 | );
17 | 
18 | my $have_ansicolor = eval { require Term::ANSIColor; };
19 | 
20 | push @formats, 'ansi'
21 |   if $have_ansicolor;
22 | 
23 | my $filetype = 'tvctestsyn';
24 | my $syntax = Text::VimColor->new(
25 |   filetype => $filetype,
26 | );
27 | 
28 | $syntax->syntax_mark_string(slurp_data("$filetype.txt"));
29 | 
30 | my %data = map { ($_ => slurp_data("$filetype.$_")) } @formats;
31 | 
32 | SKIP: {
33 |   # count it as a skipped test rather than just not doing it
34 |   skip 'Term::ANSIColor required to test ansi output', 1
35 |     if !$have_ansicolor;
36 | 
37 |   # NOTE: this hack is very specific and very fragile
38 |   $data{ansi} =~ s/\e\[95m/\e\[35m/g
39 |     if $data{ansi} && eval { Term::ANSIColor->VERSION < 3; };
40 | }
41 | 
42 | is $syntax->$_, $data{$_}, "got expected marked text from $_"
43 |   for @formats;
44 | 
45 | is_deeply
46 |   $syntax->marked,
47 |   [
48 |     [ 'Special',     "#" ],
49 |     [ '',            " " ],
50 |     [ 'Identifier',  "Text" ],
51 |     [ 'Special',     "::" ],
52 |     [ 'Identifier',  "VimColor" ],
53 |     [ '',            " test file " ],
54 |     [ 'Special',     "#" ],
55 |     [ '',            "\n\nMarked with " ],
56 |     [ 'Constant',    "t/.vim/syntax/tvctestsyn.vim" ],
57 |     [ '',            "\nthis file is used for reliably testing syntax marking\n" ],
58 |     [ 'Special',     "(" ],
59 |     [ 'Comment',     "rather than relying on an external " ],
60 |     [ 'Todo',        "vim" ],
61 |     [ 'Comment',     " file " ],
62 |     [ 'Type',        "that" ],
63 |     [ 'Comment',     " may change" ],
64 |     [ 'Special',     ")" ],
65 |     [ '',            ".\n                                    \\/\n" ],
66 |     [ 'Special',     "(" ],
67 |     [ 'Type',        "this" ],
68 |     [ 'Comment',     " line ends with whitespace " ],
69 |     [ 'Statement',   "->" ],
70 |     [ 'Special',     ")" ],
71 |     [ '',            "  \n                                    /\\\n\n" ],
72 |     [ 'Special',     "(" ],
73 |     [ 'Comment',     " " ],
74 |     [ 'Todo',        "vim" ],
75 |     [ 'Comment',     ": set ft=tvctestsyn : " ],
76 |     [ 'Special',     ")" ],
77 |     [ '',            "\n" ],
78 |   ],
79 |   'got expected arrayref structure for tvctestsyn';
80 | 
81 | done_testing;
82 | 


--------------------------------------------------------------------------------
/t/untie-std-handles.t:
--------------------------------------------------------------------------------
 1 | use strict;
 2 | use warnings;
 3 | use Test::More;
 4 | use lib 't/lib';
 5 | use TVC_Test;
 6 | 
 7 | # windows prints everything when STDIN is tied, don't know why
 8 | plan skip_all => "Skipped on windows"
 9 |   if $^O eq 'MSWin32';
10 | 
11 | # IPC::Open3 handles this now, but keep this as a regression test for rt-50646
12 | 
13 | my $tie = 'Tie::StdHandle';
14 | plan skip_all => "$tie required for this test"
15 |   unless eval "require $tie";
16 | 
17 | plan tests => 1;
18 | 
19 | tie *STDOUT, $tie;
20 | 
21 | my $marked = Text::VimColor->new(filetype => 'perl', string => "1\n")->marked;
22 | 
23 | is_deeply $marked, [[Constant => 1], ['', "\n"]], 'marked with tied handle';
24 | 


--------------------------------------------------------------------------------
/t/vim_let.t:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | # Check that things which should produce identical output do.
 3 | 
 4 | use strict;
 5 | use warnings;
 6 | use Test::More 0.88;
 7 | use lib 't/lib';
 8 | use TVC_Test;
 9 | 
10 | # test vars set via new() or vim_let()
11 | {
12 |   my %let = %Text::VimColor::VIM_LET;
13 | 
14 |   ok scalar keys %let, 'there are some default vars';
15 | 
16 |   is_deeply tvc()->{vim_let}, \%let, 'default vim_let vars';
17 | 
18 |   my %extras = (foo => 'bar', baz => 'qux');
19 | 
20 |   is_deeply
21 |     tvc(vim_let => { %extras })->{vim_let},
22 |     { %let, %extras },
23 |     'additional vim_let vars';
24 | 
25 |   is_deeply tvc(vim_let => {})->{vim_let}, \%let, 'no additional vim_let vars';
26 | 
27 |   my $tvc = tvc();
28 |   $tvc->vim_let(%extras);
29 | 
30 |   is_deeply
31 |     $tvc->{vim_let},
32 |     { %let, %extras },
33 |     'additional vim_let vars added via method';
34 | }
35 | 
36 | # TODO: get the vim command args and verify that vim_let(foo => undef) excludes foo
37 | 
38 | SKIP: {
39 | 
40 | # test the actual effects of different vim_let vars
41 | # (using shell vs bash as an example)
42 | 
43 | # Text::VimColor historically set b:is_bash.
44 | # We'll test that functionality with our custom syntax for portability.
45 | 
46 | my $input            = "# vim\nisbash\n";
47 | my ($expected_bash_output, $expected_sh_output) =
48 |   map {
49 |     qq[] .
50 |     qq[# vim\n$_\n\n]
51 |   }
52 |     'isbash',
53 |     'isbash';
54 | 
55 | foreach my $test (
56 |   [$expected_bash_output, undef,
57 |     'by default shell should enable bash features'],
58 |   [$expected_sh_output,   { 'b:is_bash' => undef },
59 |     'shell should disable bash features with b:is_bash=undef'],
60 |   [$expected_sh_output,   { foo => '"bar"', 'b:is_bash' => undef },
61 |     'disable bash features with { foo => "bar", b:is_bash => undef }'],
62 |   [$expected_bash_output, { 'b:is_bash' => 1 },
63 |     'shell should enable bash features with b:is_bash=1'],
64 | ){
65 |   my ($exp, $let, $desc) = @$test;
66 |   my $filetype = 'tvctestsyn';
67 | 
68 |   # First test setting 'let' values in the constructor.
69 |   {
70 |     my $syntax = Text::VimColor->new(
71 |       string   => $input,
72 |       filetype => $filetype,
73 |       ( $let ? (vim_let => $let) : ()),
74 |     );
75 |     is $syntax->xml, $exp, "$desc via new()";
76 |   }
77 | 
78 |   # now test setting 'let' values with the 'vim_let' method.
79 |   {
80 |     my $syntax = Text::VimColor->new;
81 |     $syntax->vim_let(%$let) if $let;
82 |     $syntax->syntax_mark_string($input, filetype => $filetype);
83 |     is $syntax->xml, $exp, "$desc via vim_let()";
84 |   }
85 | }
86 | 
87 | } # skip (vim < 6.3)
88 | 
89 | done_testing;
90 | 


--------------------------------------------------------------------------------
/t/vim_options.t:
--------------------------------------------------------------------------------
 1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
 2 | 
 3 | use strict;
 4 | use warnings;
 5 | use Test::More;
 6 | use lib 't/lib';
 7 | use TVC_Test;
 8 | 
 9 | my @defaults = @Text::VimColor::VIM_OPTIONS;
10 | 
11 | # sanity check
12 | test_expected_options();
13 | 
14 | is_deeply
15 |   [ tvc(vim_options => [text => vim => 'color'])->vim_options ],
16 |   [qw(text vim color)],
17 |   'overwrite vim_options';
18 | 
19 | is_deeply
20 |   [ tvc(vim_options => [@defaults, '+set fenc=utf-8'])->vim_options ],
21 |   [@defaults, '+set fenc=utf-8'],
22 |   'overwrite vim_options with defaults plus one extra';
23 | 
24 | is_deeply
25 |   [ tvc(extra_vim_options => ['+set fenc=utf-8'])->vim_options ],
26 |   [@defaults, '+set fenc=utf-8'],
27 |   'use extra_vim_options to get the same effect';
28 | 
29 | {
30 |   local @Text::VimColor::VIM_OPTIONS = qw(local vim options);
31 |   is_deeply
32 |     [ tvc()->vim_options ],
33 |     [qw(local vim options)],
34 |     'use localized @Text::VimColor::VIM_OPTIONS for backward compatibility';
35 | 
36 |   is_deeply
37 |     [ tvc(extra_vim_options => ['foo'])->vim_options ],
38 |     [qw(local vim options foo)],
39 |     'use localized @Text::VimColor::VIM_OPTIONS for backward compatibility';
40 | }
41 | 
42 | # after all that the defaults are still the defaults:
43 | is_deeply
44 |   [ tvc()->vim_options ],
45 |   [@defaults],
46 |   'default vim_options';
47 | 
48 | is_deeply
49 |   [ tvc(extra_vim_options => ['bar'])->vim_options ],
50 |   [@defaults, 'bar'],
51 |   'default vim_options plus extra_vim_options';
52 | 
53 | # make sure nothing has altered them
54 | test_expected_options();
55 | 
56 | done_testing;
57 | 
58 | # these values could theoretically change, but they probably won't
59 | sub test_expected_options {
60 |   is_deeply
61 |     [ @defaults[1..4] ],
62 |     [-i => 'NONE', -u => 'NONE'],
63 |     'default vim options disable .vimrc and .viminfo';
64 | 
65 |   ok scalar grep { /\+set nomodeline/ } @defaults, 'nomodeline set in default vim options';
66 | }
67 | 


--------------------------------------------------------------------------------
/t/xml.t:
--------------------------------------------------------------------------------
  1 | # vim: set ts=2 sts=2 sw=2 expandtab smarttab:
  2 | # Check that the XML output is correct.
  3 | # Also checks that tabs aren't tampered with.
  4 | 
  5 | use strict;
  6 | use warnings;
  7 | use Test::More;
  8 | use lib 't/lib';
  9 | use TVC_Test;
 10 | use IO::File;
 11 | use Path::Class qw( file );
 12 | 
 13 | my $NS = 'http://ns.laxan.com/text-vimcolor/1';
 14 | my %SYNTYPES = map { $_ => 1 } qw(
 15 |    Comment Constant Identifier Statement Preproc
 16 |    Type Special Underlined Error Todo
 17 | );
 18 | 
 19 | my @EXPECTED_PERL_SYN = qw(
 20 |    Comment
 21 |    Statement Identifier
 22 |    Statement Constant Statement
 23 |    Statement Constant Identifier Constant
 24 |    Constant Special Constant
 25 | );
 26 | # vim will guess that string input is 'conf'
 27 | my @EXPECTED_NOFT_SYN = qw(
 28 |    Comment
 29 |    Constant
 30 |    Constant
 31 | );
 32 | 
 33 | eval " use XML::Parser ";
 34 | if ($@) {
 35 |    plan skip_all => 'XML::Parser module required for these tests.';
 36 |    exit 0;
 37 | }
 38 | else {
 39 |    plan tests => 12;
 40 | }
 41 | 
 42 | # Syntax color a Perl program, and check the XML output for well-formedness
 43 | # and validity.  The tests are run with and without a root element in the
 44 | # output, and with both filename and string as input.
 45 | my $filename = file(qw( t data has_tabs.pl ))->stringify;
 46 | my $file = IO::File->new($filename, 'r')
 47 |    or die "error opening file '$filename': $!";
 48 | my $data = do { local $/; <$file> };
 49 | 
 50 | # The value of these tests is not vim's filetype detection, so set it
 51 | # explicitly for portability across vim versions - rwstauner 2012-03-17
 52 | my $syntax = Text::VimColor->new(
 53 |    file => $filename,
 54 |    filetype => 'perl',
 55 | );
 56 | my $syntax_noroot = Text::VimColor->new(
 57 |    file => $filename, xml_root_element => 0,
 58 |    filetype => 'perl',
 59 | );
 60 | my $syntax_str = Text::VimColor->new(
 61 |    string => $data,
 62 |    filetype => 'conf',
 63 | );
 64 | my $syntax_str_noroot = Text::VimColor->new(
 65 |    string => $data, xml_root_element => 0,
 66 |    filetype => 'conf',
 67 | );
 68 | 
 69 | my %syntax = (
 70 |    'no root element, filename input' => $syntax_noroot,
 71 |    'no root element, string input' => $syntax_str_noroot,
 72 |    'root element, filename input' => $syntax,
 73 |    'root element, string input' => $syntax_str,
 74 | );
 75 | 
 76 | # These are filled in by the handler subs below.
 77 | my $text;
 78 | my $root_elem_count;
 79 | my $inside_element;
 80 | my @syntax_types;
 81 | 
 82 | my $parser = XML::Parser->new(
 83 |    Handlers => {
 84 |       Start => \&handle_start,
 85 |       End => \&handle_end,
 86 |       Char => \&handle_text,
 87 |       Default => \&handle_default,
 88 |    },
 89 | );
 90 | 
 91 | foreach my $test_type (sort keys %syntax) {
 92 |    #diag("Doing XML tests for configuration '$test_type'.");
 93 |    my $syn = $syntax{$test_type};
 94 |    my $xml = $syn->xml;
 95 | 
 96 |    # The ones without root elements need to be faked.
 97 |    if ($test_type =~ /no root/) {
 98 |       $xml = "$xml";
 99 |    }
100 | 
101 |    # Reset globals.
102 |    # These get modified by the Handler subs in the next call to $parser->parse.
103 |    $text = '';
104 |    $root_elem_count = 0;
105 |    $inside_element = 0;
106 |    @syntax_types = ();
107 | 
108 |    $parser->parse($xml);
109 | 
110 |    is($text, $data,
111 |       "check that text from XML output matches original");
112 |    is($root_elem_count, 1,
113 |       "there should only be one root element");
114 | 
115 |   my $expected = ($test_type =~ /string/)
116 |     # Only expected to find string literals and comments.
117 |     ? \@EXPECTED_NOFT_SYN
118 |     : \@EXPECTED_PERL_SYN;
119 | 
120 |   is_deeply($expected, \@syntax_types,
121 |     "syntax types marked in the right order for '$test_type'")
122 |       or diag explain { exp => $expected, got => \@syntax_types };
123 | }
124 | 
125 | 
126 | sub handle_text
127 | {
128 |    my ($expat, $s) = @_;
129 |    $text .= $s;
130 | }
131 | 
132 | sub handle_start
133 | {
134 |    my ($expat, $element, %attr) = @_;
135 |    $element =~ /^syn:(.*)\z/
136 |       or fail("element <$element> has wrong prefix"), return;
137 |    $element = $1;
138 | 
139 |    fail("element  shouldn't be nested in something")
140 |       if $inside_element;
141 | 
142 |    if ($element eq 'syntax') {
143 |       ++$root_elem_count;
144 |       fail("namespace declaration missing from root element")
145 |          unless $attr{'xmlns:syn'};
146 |       fail("wrong namespace declaration in root element")
147 |          unless $attr{'xmlns:syn'} eq $NS;
148 |    }
149 |    else {
150 |       $inside_element = 1;
151 |       fail("bad element ")
152 |          if !$SYNTYPES{$element};
153 |       fail("element  shouldn't have any attributes")
154 |          if keys %attr;
155 | 
156 |       # HACK: ignore more than a single line of comments at the beginning
157 |       # of the file (which might be added dynamically during build).
158 |       # can be removed if this gets merged (or we stop using Prepender):
159 |       # https://github.com/jquelin/dist-zilla-plugin-prepender/pull/1
160 |       return if @syntax_types == 1 && $element eq 'Comment';
161 | 
162 |       push @syntax_types, $element;
163 |    }
164 | }
165 | 
166 | sub handle_end
167 | {
168 |    my ($expat, $element) = @_;
169 |    $element =~ /^syn:(.*)\z/
170 |       or fail("element <$element> has wrong prefix"), return;
171 |    $element = $1;
172 | 
173 |    $inside_element = 0;
174 | 
175 |    if ($element ne 'syntax' && !$SYNTYPES{$element}) {
176 |       fail("bad element ");
177 |       return;
178 |    }
179 | }
180 | 
181 | sub handle_default
182 | {
183 |    my ($expat, $s) = @_;
184 |    return unless $s =~ /\S/;
185 |    die "unexpected XML event for text '$s'\n";
186 | }
187 | 


--------------------------------------------------------------------------------