diff --git a/README b/README deleted file mode 100644 index c078dd4..0000000 --- a/README +++ /dev/null @@ -1,3 +0,0 @@ -This is a mirror of http://www.vim.org/scripts/script.php?script_id=2874 - -This is an updated version of the php.vim syntax file distributed with VIM. The list of PHP constants, functions, and classes was updated to be current with PHP 5.3. Many new classes were added in the 5.2 branch and the distributed version only covers up to 5.1.4. In addition I simplified the file, removing several sections that are not often used (at least by me) such as automatic folding of all control structures and ASP tags support. I also removed several switches designed for b/c with VIM 5.X and 6.X. As an addition I have included the PHP file I used to generate the constant, function, class list. It uses reflection to mine out these items from your PHP installation and generate part of the php.vim script. Before running open up the file and adjust the output file location and the list of extensions to generate syntax for. Then run "php php_vimgen.php" from your shell. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c54122a --- /dev/null +++ b/README.md @@ -0,0 +1,143 @@ +php.vim +======= + +An up-to-date Vim syntax for PHP. + +_This project is a fork of [php.vim--Garvin][php.vim-garvin] which in turn is an update of the [php.vim][php.vim-original] script which in turn is an updated version of the php.vim syntax file distributed with Vim. **Whew!**_ + +Installation +------------ + +If you don't have a preferred installation method, [vim-plug] is quick and simple. With [vim-plug installed], add the following to your `vimrc` (if you are a NeoVim user, see the [FAQ page][neovim-faq] for help): + +```vim +Plug 'StanAngeloff/php.vim' +``` + +If you are using Git, please be aware [the original repository this project was forked from][php.vim-garvin] contains bad timezone in some of the commits. You'll need to fetch with `fsckObjects` disabled: + +```sh +git clone -c fetch.fsckObjects=false git@github.com:StanAngeloff/php.vim.git +``` + +Unless you specify `-c fetch.fsckObjects=false` as an option to `git clone`, you may see `badTimezone: invalid author/committer line - bad time zone` in the output and the cloning will [fail](https://github.com/StanAngeloff/php.vim/issues/96). + +Configuration +------------- + +`php.vim` comes with sensible defaults for most use cases. Below is a list of some interesting configuration options you may tweak. Refer to the [source code][php.vim-source] for additional options. + +- `g:php_version_id`, + `b:php_version_id` + + Default: `g:php_version_id = 70300` + + The PHP version the Vim syntax should adhere to. This currently determines how strict [Heredoc/Nowdoc syntax](https://www.php.net/manual/en/migration73.new-features.php#migration73.new-features.core.heredoc) should be. The format of the Vim variable follows the [PHP predefined constant `PHP_VERSION_ID`](https://www.php.net/manual/en/reserved.constants.php#constant.php-version-id). + +- `g:php_syntax_extensions_enabled`, `g:php_syntax_extensions_disabled` + `b:php_syntax_extensions_enabled`, `b:php_syntax_extensions_disabled` + + Default: `g:php_syntax_extensions_enabled = ["bcmath", "bz2", "core", "curl", "date", "dom", "ereg", "gd", "gettext", "hash", "iconv", "json", "libxml", "mbstring", "mcrypt", "mhash", "mysql", "mysqli", "openssl", "pcre", "pdo", "pgsql", "phar", "reflection", "session", "simplexml", "soap", "sockets", "spl", "sqlite3", "standard", "tokenizer", "wddx", "xml", "xmlreader", "xmlwriter", "zip", "zlib"]` + + A list of PHP extension names (lowercase) for which highlighting of built-in functions, constants, classes and interfaces is enabled / disabled. + + If you are **not** interested in highlighting **any** built-in functions/constants/etc., set `g:php_syntax_extensions_enabled` to an empty list `[]`. + + If you are **not** interested in highlighting built-in functions/constants/etc. for a subset of PHP extensions, set `g:php_syntax_extensions_enabled` to a list of extensions you wish to disable, e.g., `["mcrypt"]`. + +- `php_var_selector_is_identifier` + + Default: `0` + + Set this to a truthy value (e.g., `1`) to include the dollar sign `$` as part of the highlighting group for a PHP variable. + +- `php_html_load`, `php_html_in_heredoc`, `php_html_in_nowdoc` + + Default: `1` (NOTE: setting `php_html_load` to a truthy value takes precedence and overrides both `php_html_in_heredoc` & `php_html_in_nowdoc`) + + Set to a falsy value (e.g., `0`) to disable embedding HTML in PHP. Doing so may yield significant speed-ups of syntax highlighting. + + This should not affect HTML highlighting in templating languages, such as [Blade]. + +- `php_sql_query`, `php_sql_heredoc`, `php_sql_nowdoc` + + Default: `1` + + Set to a falsy value (e.g., `0`) to disable SQL syntax in PHP. Doing so may yield moderate speed-ups of syntax highlighting. + +### Projects of interest + +`php.vim` pairs nicely with: + +- [`phpfolding.vim`](https://github.com/rayburgemeestre/phpfolding.vim): _Automatic folding of PHP functions, classes, … (also folds related PhpDoc)_ +- [`PHP-Indenting-for-VIm`](https://github.com/2072/PHP-Indenting-for-VIm): _The official VIm indent script for PHP_ + +### Overriding highlighting + +Syntax highlighting can be controlled at a fine-grained level. For example, all text in PHP comments is highlighted as `phpComment` by default, however there are smaller syntax groups you can tweak, e.g., how PHPDoc `@tags` appear. There are [several syntax groups you can choose from](syntax-groups). + +Example: Overriding PHP `@tags` and `$parameters` in comments to appear as a different highlighting group, giving them distinct colouring: + +```vim +" Put this function at the very end of your vimrc file. + +function! PhpSyntaxOverride() + " Put snippet overrides in this function. + hi! link phpDocTags phpDefine + hi! link phpDocParam phpType +endfunction + +augroup phpSyntaxOverride + autocmd! + autocmd FileType php call PhpSyntaxOverride() +augroup END +``` + +#### Snippets + +You may add the code snippets below to your `PhpSyntaxOverride` function (see above for instructions on how to create this function). + +##### Colourising namespace separator in `use`, `extends` and `implements` + +If you wish to highlight the namespace separator `\` differently ([original request](https://github.com/StanAngeloff/php.vim/issues/63)): + +```vim +hi phpUseNamespaceSeparator guifg=#808080 guibg=NONE gui=NONE +hi phpClassNamespaceSeparator guifg=#808080 guibg=NONE gui=NONE +``` + +##### Colourising parentheses + +If you wish to highlight `(` and `)` differently ([original request](https://github.com/StanAngeloff/php.vim/issues/31#issuecomment-52879108)): + +```vim +syn match phpParentOnly "[()]" contained containedin=phpParent +hi phpParentOnly guifg=#f08080 guibg=NONE gui=NONE +``` + +Developing +---------- + +When you install `php.vim` using your preferred installation method, all the needed files are already in place. + +If you wish to rebuild the syntax file with a more recent version of PHP available on the [Docker Hub], you should use the provided `Dockerfile` to do so: + +```bash +docker build --no-cache --force-rm -f attic/Dockerfile -t php.vim . +cat syntax/php.vim | docker run --rm -i php.vim > syntax/php.vim.new +docker rmi php.vim +mv syntax/php.vim.new syntax/php.vim +``` + +NOTE: If the updated syntax file fails to load and is corrupted, try loading `syntax/php.vim` in your favourite editor and ensure line endings are set to Unix `\n`. + + + [php.vim-garvin]: https://github.com/vim-scripts/php.vim--Garvin + [php.vim-original]: http://www.vim.org/scripts/script.php?script_id=2874 + [vim-plug]: https://github.com/junegunn/vim-plug + [vim-plug installed]: https://github.com/junegunn/vim-plug#installation + [neovim-faq]: https://github.com/neovim/neovim/wiki/FAQ#where-should-i-put-my-config-vimrc + [php.vim-source]: https://github.com/StanAngeloff/php.vim/blob/master/syntax/php.vim#L35 + [Blade]: https://github.com/jwalton512/vim-blade + [syntax-groups]: https://github.com/StanAngeloff/php.vim/blob/41c36f7f/syntax/php.vim#L804 + [Docker Hub]: https://docs.docker.com/samples/library/php/ diff --git a/attic/0-bootstrap.inc.php b/attic/0-bootstrap.inc.php new file mode 100644 index 0000000..ac2d7d4 --- /dev/null +++ b/attic/0-bootstrap.inc.php @@ -0,0 +1,6 @@ + + * + * @author Paul Garvin + * @copyright Copyright 2009 Paul Garvin + * @license http://www.opensource.org/licenses/mit-license.php MIT License + * + * Loosely based on Paul Garvin original script. + * + * For the full copyright and license information, + * please view the LICENSE file that was distributed with this source code. + */ + +require __DIR__ . '/0-bootstrap.inc.php'; + +# Parse the configuration file associated with this script. +$configuration = parse_ini_file(__DIR__ . '/syntax.ini', /* $process_sections = */ true); + +# Process extensions and serialize built-in functions, constants, classes and interfaces. +$extensions = array(); + +foreach ($configuration['extensions'] as $extensionName => $isEnabled) { + if (! $isEnabled) { + continue; + } + + try { + $reflect = new \ReflectionExtension($extensionName); + + $collected = array( + 'name' => $reflect->getName(), + 'versions' => array(sprintf('%d.%d.%d', PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION)), + 'classes' => array(), + 'functions' => array_keys($reflect->getFunctions()), + 'constants' => array_diff(array_keys($reflect->getConstants()), array('TRUE', 'FALSE', 'NULL')), + ); + + foreach ($reflect->getClasses() as $extensionClass) { + $collected['classes'][] = $extensionClass->getName(); + $collected['constants'] = array_unique(array_merge($collected['constants'], array_keys($extensionClass->getConstants()))); + } + + $extensions[$extensionName] = $collected; + } catch (ReflectionException $e) { + file_put_contents('php://stderr', sprintf('[ERROR] [PHP %d.%d] %\'.12s: %s.' . PHP_EOL, PHP_MAJOR_VERSION, PHP_MINOR_VERSION, $extensionName, rtrim($e->getMessage(), ' ?!.'))); + } +} + +echo serialize($extensions) . PHP_EOL; diff --git a/attic/20-generate.php b/attic/20-generate.php new file mode 100644 index 0000000..f7afdb9 --- /dev/null +++ b/attic/20-generate.php @@ -0,0 +1,103 @@ + false]); + foreach ($unserialized as $extension => &$collected) { + if (! isset($extensions[$extension])) { + $extensions[$extension] = $collected; + continue; + } + + $extensions[$extension] = array( + 'name' => $extensions[$extension]['name'], + 'versions' => array_merge($extensions[$extension]['versions'], $collected['versions']), + 'classes' => array_merge($extensions[$extension]['classes'], $collected['classes']), + 'functions' => array_merge($extensions[$extension]['functions'], $collected['functions']), + 'constants' => array_merge($extensions[$extension]['constants'], $collected['constants']), + ); + } +} + +foreach ($extensions as &$collected) { + $collected['classes'] = array_unique($collected['classes']); + $collected['functions'] = array_unique($collected['functions']); + $collected['constants'] = array_unique($collected['constants']); + + sort($collected['classes'], SORT_NATURAL); + sort($collected['functions'], SORT_NATURAL); + sort($collected['constants'], SORT_NATURAL); + + $versions = array_merge($versions, $collected['versions']); +} + +$versions = array_unique($versions); +sort($versions, SORT_NATURAL); + +$blocks = array( + 'extensions' => array(), + 'last-modified' => sprintf( + '%s, PHP %s', + date('r' /* RFC 2822 */), + implode(/* $glue = */ ', ', $versions) + ), +); + +$blocks['extensions'][] = 'if ! exists("g:php_syntax_extensions_enabled")'; +$blocks['extensions'][] = sprintf(' let g:php_syntax_extensions_enabled = ["%s"]', implode(/* $glue = */ '", "', array_map('strtolower', array_keys($extensions)))); +$blocks['extensions'][] = 'endif'; + +$blocks['extensions'][] = 'if ! exists("g:php_syntax_extensions_disabled")'; +$blocks['extensions'][] = ' let g:php_syntax_extensions_disabled = []'; +$blocks['extensions'][] = 'endif'; + +$ifExtensionEnabled = function ($extensionName) { + return sprintf( + 'if ' . + 'index(g:php_syntax_extensions_enabled, "%1$s") >= 0 && ' . + 'index(g:php_syntax_extensions_disabled, "%1$s") < 0 && ' . + '( ! exists("b:php_syntax_extensions_enabled") || index(b:php_syntax_extensions_enabled, "%1$s") >= 0) && ' . + '( ! exists("b:php_syntax_extensions_disabled") || index(b:php_syntax_extensions_disabled, "%1$s") < 0)', + strtolower($extensionName) + ); +}; + +$blocks['extensions'][] = 'syn case match'; + +foreach ($extensions as $extension) { + if (! count($extension['constants'])) { + continue; + } + + $blocks['extensions'][] = $ifExtensionEnabled($extension['name']); + $blocks['extensions'][] = sprintf('" %s constants', $extension['name']); + $blocks['extensions'][] = sprintf('syn keyword phpConstants %s contained', implode(/* $glue = */ ' ', $extension['constants'])); + $blocks['extensions'][] = 'endif'; +} + +$blocks['extensions'][] = 'syn case ignore'; + +foreach ($extensions as $extension) { + if (! count($extension['functions']) && ! count($extension['classes'])) { + continue; + } + + $blocks['extensions'][] = $ifExtensionEnabled($extension['name']); + + if (count($extension['functions'])) { + $blocks['extensions'][] = sprintf('" %s functions', $extension['name']); + $blocks['extensions'][] = sprintf('syn keyword phpFunctions %s contained', implode(/* $glue = */ ' ', $extension['functions'])); + } + if (count($extension['classes'])) { + $blocks['extensions'][] = sprintf('" %s classes and interfaces', $extension['name']); + $blocks['extensions'][] = sprintf('syn keyword phpClasses %s contained', implode(/* $glue = */ ' ', $extension['classes'])); + } + + $blocks['extensions'][] = 'endif'; +} + +echo serialize($blocks); diff --git a/attic/30-update.php b/attic/30-update.php new file mode 100644 index 0000000..8c9f9cc --- /dev/null +++ b/attic/30-update.php @@ -0,0 +1,71 @@ + false]); + +# Read the existing syntax file with block markers in it. +# +$template = file_get_contents($argv[1]); + +# Clean up any previously defined blocks. +$template = preg_replace( + sprintf( + '/(@block\([\'"](%s)[\'"]\)["\r\n\t ]*).*?(["\r\n\t ]*@endblock)\b/ism', + implode(/* $glue = */ '|', array_keys($blocks)) + ), + "\\1___\\2___\\3", + $template +); + +# Update block contents in the template. +foreach ($blocks as $blockName => $lines) { + $template = str_ireplace( + sprintf('___%s___', $blockName), + rtrim(is_array($lines) ? implode(/* $glue = */ "\n", $lines) : $lines), + $template + ); +} + +$template = preg_replace_callback( + '/ + (?"\s*@copy\s+(?[a-zA-Z0-9_]+)(?(\s+(strip_maximum_size))+)?) + (?