diff options
| author | Vincenzo Pupillo | 2025-07-10 17:20:34 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2025-08-09 15:57:04 +0300 |
| commit | e1fd7b5d89ec7f2df40fa01bf4041c0d1df147b4 (patch) | |
| tree | 80b3644ccfaacc1b0c5c11eb1b350432d0099f87 | |
| parent | 3fb8ffe61eacb73df17f2a4a6c2ac240951a289b (diff) | |
| download | emacs-e1fd7b5d89ec7f2df40fa01bf4041c0d1df147b4.tar.gz emacs-e1fd7b5d89ec7f2df40fa01bf4041c0d1df147b4.zip | |
`php-ts-mode' depends on `mhtml-ts-mode' instead of JS,CSS and HTML
The direct dependence on js-ts-mode, css-ts-mode and html-ts-mode
has now been replaced by 'mhtml-ts-mode'.
Additional benefits are:
1. Imenu now exposes symbols for all of all languages,
2. navigation now works correctly for all languages,
3. outline works for all languages.
Additional new features are:
1. indentation of PHP in mixed buffers with HTML now works much
better and allows three different behaviors, an option allows you to
choose the behavior.
2. a new feature shows where PHP ini files are both locally and
remotely, if the buffer is associated with a remote PHP file.
* etc/NEWS: Mention the rationale for those changes, the new command,
and the new options.
* lisp/textmodes/mhtml-ts-mode.el (mhtml-ts-mode--range-settings): New
variable that store range settings.
(mhtml-ts-mode--treesit-aggregated-outline-predicate): New variable
that store outline predicates.
(mhtml-ts-mode): Use those two new variables.
* lisp/progmodes/php-ts-mode.el: Update doc string. Removed old
dependencies.
(php-ts-mode--language-source-alist): Updated parsers version.
(php-ts-mode-install-parsers): Removed old dependencies, now relies
on (mhtml-ts-mode-install-parsers). Update doc string.
(php-ts-mode-js-css-indent-offset): Update doc string.
(php-ts-mode-css-fontify-colors): Removed option, now relies on
'php-ts-mode-css-fontify-colors'.
(php-ts-mode-html-indent-offset): New user option.
(php-ts-mode-html-relative-indent): New user option.
(php-ts-mode-php-default-executable): Assume \"php\" instead of
\"/usr/bin/php\" if 'executable-find' fails.
(php-ts-mode-php-config): Fix tag.
(php-ts-mode-find-sibling-rules): New user option with the rules for
finding siblings of a file.
(php-ts-mode-phpdoc-highlight-errors): New user option, if non-nil
highlight unkown PHPDOC nodes.
(php-ts-mode--indent-style-setter): Indentation fix.
(php-ts-mode-indent-style): Indentation fix.
(php-ts-mode-flymake-php): Indentation fix.
(php-ts-mode--executable): Indentation fix.
(php-ts-mode-show-ini): New command that show the locations of PHP
ini files.
(php-ts-mode--get-indent-style): Indentation fix.
(php-ts-mode--set-indent-property): Indentation fix.
(php-ts-mode-set-style): Indentation fix.
(php-ts-mode--get-parser-ranges): Indentation fix.
(php-ts-mode--possibly-braceless-keyword-re): Removed no longer
used constant.
(php-ts-mode--open-statement-group-heuristic): Removed no longer
used function.
(php-ts-mode--else-heuristic): Indentation fix.
(php-ts-mode--first-sibling): Indentation fix.
(php-ts-mode--js-css-tag-bol): Function removed, now using
'mhtml-ts-mode--js-css-tag-bol'.
(php-ts-mode--parent-html-bol): Removed no longer used
function.
(php-ts-mode--parent-html-heuristic): Now more reliably handles
the mixed indentation of PHP and HTML. The new option
'php-ts-mode-html-relative-indent' changes the behavior of the
function. When 'php-ts-mode-html-relative-indent' is 't' the new
option 'php-ts-mode-html-indent-offset' controls the offset of PHP
code relative to HTML tags.
(php-ts-mode--array-element-heuristic): Indentation fix.
(php-ts-mode--anchor-prev-sibling): Indentation fix..
(php-ts-mode--indent-styles): The indentation rules for 'program'
and 'text_interpolation' are now common to all indentation styles,
thanks to the new version of 'php-ts-mode-arent-html-heuristic'.
New rules for 'namespace_use_clause', 'use_declaration',
'use_list', 'attribute_group' and 'string_content'.
(php-ts-mode--prettify-symbols-alist): New variable to support
'prettify-symbols-alist'.
(php-ts-mode--test-visibility-modifier-operation-clause-p): Rename ...
(php-ts-mode--test-visibility-modifier-operation-p): ... to this more
correct name.
(php-ts-mode--test-property-hook-clause-p): Rename ...
(php-ts-mode--test-property-hook-p): ... to this more correct name.
(php-ts-mode--test-relative-name-p): New function to test if
'relative_name' is supported by the PHP parser.
(php-ts-mode--font-lock-settings): Use the new function for highlight
'relative_name'. Highlight 'error_suppression_expression'.
Refactoring using the renamed functions. Indentation fix.
(php-ts-mode--custom-html-font-lock-settings): Replace the rules with
'mhtml-ts-mode--treesit-font-lock-settings'. Fix docs string.
(php-ts-mode--phpdoc-font-lock-settings): Added support for "array"
and "list" array_type. New "phpdoc-error" feature to highlight
unknown nodes via new 'php-ts-mode--phpdoc-fontify-error' function.
(php-ts-mode--colorize-css-value): Removed function no longer used,
now highlighting is handled directly by 'mhtml-ts-mode'.
(php-ts-mode--phpdoc-fontify-error): New function used by
'php-ts-mode--phpdoc-font-lock-settings'.
(php-ts-mode--parent-object): Indentation fix.
(php-ts-mode--defun-name-separator): Indentation fix.
(php-ts-mode--defun-object-name): Indentation fix.
(php-ts-mode--defun-name): The function now also returns the defun
name of 'mhtml-ts-mode'.
(php-ts-mode--treesit-defun-type-regexp): New regexp for
'treesit-defun-type-regexp' support.
(php-ts-mode--indent-defun): Indentation fix.
(php-ts-mode--defun-valid-p): Fix indentation.
(php-ts-mode--comment-indent-new-line): Indentation fix.
(php-ts-mode--comment-current-plist): New local variable that stores
the state of the PHP comment style.
(php-ts-mode--comment-setup): The function now handles changing, for
different languages, comment styles, using
"php-ts-mode--comment-current-plist" to store and retrieve the comment
style for the PHP language.
(php-ts-mode-comment-setup): Now store the PHP comment style in
'php-ts-mode--comment-current-plist'.
(php-ts-mode-menu): Indentation fix.
(php-ts-mode): Replace dependency from JS, CSS and HTML width
'mhtml-ts-mode'. Navigation, Imenu and Outline now support PHP, HTML,
Javascript and CSS. Added support for 'prettify-symbol-mode'.
Added support for 'electric-layout-rules'.
(php-ts-mode-run-php-webserver, php-ts-mode--webserver-read-args)
(php-ts-mode--webserver-read-args, inferior-php-ts-mode, run-php)
(inferior-php-ts-mode-startup, php-ts-mode-inferior--write-history)
(php-ts-mode-send-region): Indentation fixes.
(Bug#78994)
| -rw-r--r-- | etc/NEWS | 34 | ||||
| -rw-r--r-- | lisp/progmodes/php-ts-mode.el | 1622 | ||||
| -rw-r--r-- | lisp/textmodes/mhtml-ts-mode.el | 78 |
3 files changed, 927 insertions, 807 deletions
| @@ -932,6 +932,12 @@ option controls how much is indented for method chaining. | |||
| 932 | ** PHP-ts mode | 932 | ** PHP-ts mode |
| 933 | 933 | ||
| 934 | --- | 934 | --- |
| 935 | *** 'php-ts-mode' now depends on 'mhtml-ts-mode'. | ||
| 936 | The direct dependency on js-ts-mode, css-ts-mode and html-ts-mode has | ||
| 937 | now been replaced by ‘mhtml-ts-mode’. Navigation, Outline and Imenu | ||
| 938 | work for all languages and code maintenance is easier. | ||
| 939 | |||
| 940 | --- | ||
| 935 | *** 'php-ts-mode-run-php-webserver' can now accept a custom "php.ini" file. | 941 | *** 'php-ts-mode-run-php-webserver' can now accept a custom "php.ini" file. |
| 936 | You can use the new optional argument CONFIG when calling | 942 | You can use the new optional argument CONFIG when calling |
| 937 | 'php-ts-mode-run-php-webserver' to pass an alternative "php.ini" file to | 943 | 'php-ts-mode-run-php-webserver' to pass an alternative "php.ini" file to |
| @@ -939,6 +945,34 @@ the built-in Web server. Interactively, when invoked with a prefix | |||
| 939 | argument, 'php-ts-mode-run-php-webserver' prompts for the config file as | 945 | argument, 'php-ts-mode-run-php-webserver' prompts for the config file as |
| 940 | well as for other connection parameters. | 946 | well as for other connection parameters. |
| 941 | 947 | ||
| 948 | --- | ||
| 949 | *** The option 'php-ts-mode-css-fontify-colors' has been removed. | ||
| 950 | 'mhtml-ts-mode-css-fontify-colors' replaces this option. | ||
| 951 | |||
| 952 | --- | ||
| 953 | *** New user option 'php-ts-mode-html-relative-indent'. | ||
| 954 | In buffers containing both PHP and HTML, this option allows you to | ||
| 955 | define how the PHP code should be indented relative to the position of | ||
| 956 | the HTML tags. | ||
| 957 | |||
| 958 | --- | ||
| 959 | *** New user option 'php-ts-mode-html-indent-offset'. | ||
| 960 | Offset of PHP code block relative to HTML tags. | ||
| 961 | |||
| 962 | --- | ||
| 963 | *** New user option 'php-ts-mode-find-sibling-rules'. | ||
| 964 | Rules for finding siblings of a PHP file. | ||
| 965 | |||
| 966 | --- | ||
| 967 | *** New user option 'php-ts-mode-phpdoc-highlight-errors'. | ||
| 968 | When non nil, it highlights unknown PHPDOC tags using | ||
| 969 | 'font-lock-warning-face' so that the user can identify them more easily. | ||
| 970 | |||
| 971 | --- | ||
| 972 | *** New command 'php-ts-mode-show-ini'. | ||
| 973 | Show the location of the PHP ini files, if the buffer is associated to a remote | ||
| 974 | PHP file show the remote PHP ini files. | ||
| 975 | |||
| 942 | ** Rust-ts mode | 976 | ** Rust-ts mode |
| 943 | 977 | ||
| 944 | --- | 978 | --- |
diff --git a/lisp/progmodes/php-ts-mode.el b/lisp/progmodes/php-ts-mode.el index a01e4d66fba..d45226ad5e9 100644 --- a/lisp/progmodes/php-ts-mode.el +++ b/lisp/progmodes/php-ts-mode.el | |||
| @@ -25,12 +25,12 @@ | |||
| 25 | ;;; Tree-sitter language versions | 25 | ;;; Tree-sitter language versions |
| 26 | ;; | 26 | ;; |
| 27 | ;; php-ts-mode has been tested with the following grammars and version: | 27 | ;; php-ts-mode has been tested with the following grammars and version: |
| 28 | ;; - tree-sitter-phpdoc: v0.1.5 | 28 | ;; - tree-sitter-phpdoc: v0.1.6 |
| 29 | ;; - tree-sitter-css: v0.23.1-1-g6a442a3 | 29 | ;; - tree-sitter-css: v0.23.1-1-g6a442a3 |
| 30 | ;; - tree-sitter-jsdoc: v0.23.2 | 30 | ;; - tree-sitter-jsdoc: v0.23.2 |
| 31 | ;; - tree-sitter-javascript: v0.23.1-2-g108b2d4 | 31 | ;; - tree-sitter-javascript: v0.23.1-2-g108b2d4 |
| 32 | ;; - tree-sitter-html: v0.23.2-1-gd9219ad | 32 | ;; - tree-sitter-html: v0.23.2-1-gd9219ad |
| 33 | ;; - tree-sitter-php: v0.23.11 | 33 | ;; - tree-sitter-php: v0.23.12 |
| 34 | ;; | 34 | ;; |
| 35 | ;; We try our best to make builtin modes work with latest grammar | 35 | ;; We try our best to make builtin modes work with latest grammar |
| 36 | ;; versions, so a more recent grammar has a good chance to work too. | 36 | ;; versions, so a more recent grammar has a good chance to work too. |
| @@ -42,7 +42,7 @@ | |||
| 42 | ;; for editing PHP files with embedded HTML, JavaScript, CSS and phpdoc. | 42 | ;; for editing PHP files with embedded HTML, JavaScript, CSS and phpdoc. |
| 43 | ;; Tree Sitter is used to parse each of these languages. | 43 | ;; Tree Sitter is used to parse each of these languages. |
| 44 | ;; | 44 | ;; |
| 45 | ;; Please note that this package requires `html-ts-mode', which | 45 | ;; Please note that this package requires `mhtml-ts-mode', which |
| 46 | ;; registers itself as the major mode for editing HTML. | 46 | ;; registers itself as the major mode for editing HTML. |
| 47 | ;; | 47 | ;; |
| 48 | ;; This package is compatible and has been tested with the following | 48 | ;; This package is compatible and has been tested with the following |
| @@ -69,9 +69,7 @@ | |||
| 69 | 69 | ||
| 70 | (require 'treesit) | 70 | (require 'treesit) |
| 71 | (require 'c-ts-common) ;; For comment indent and filling. | 71 | (require 'c-ts-common) ;; For comment indent and filling. |
| 72 | (require 'html-ts-mode) ;; for embed html | 72 | (require 'mhtml-ts-mode) ;; For embed html, css and js. |
| 73 | (require 'css-mode) ;; for embed css into html | ||
| 74 | (require 'js) ;; for embed javascript into html | ||
| 75 | (require 'comint) | 73 | (require 'comint) |
| 76 | (treesit-declare-unavailable-functions) | 74 | (treesit-declare-unavailable-functions) |
| 77 | 75 | ||
| @@ -83,10 +81,10 @@ | |||
| 83 | ;;; Install treesitter language parsers | 81 | ;;; Install treesitter language parsers |
| 84 | (defvar php-ts-mode--language-source-alist | 82 | (defvar php-ts-mode--language-source-alist |
| 85 | '((php "https://github.com/tree-sitter/tree-sitter-php" | 83 | '((php "https://github.com/tree-sitter/tree-sitter-php" |
| 86 | :commit "43aad2b9a98aa8e603ea0cf5bb630728a5591ad8" | 84 | :commit "f7cf7348737d8cff1b13407a0bfedce02ee7b046" |
| 87 | :source-dir "php/src") | 85 | :source-dir "php/src") |
| 88 | (phpdoc "https://github.com/claytonrcarter/tree-sitter-phpdoc" | 86 | (phpdoc "https://github.com/claytonrcarter/tree-sitter-phpdoc" |
| 89 | :commit "fe3202e468bc17332bec8969f2b50ff1f1da3a46")) | 87 | :commit "03bb10330704b0b371b044e937d5cc7cd40b4999")) |
| 90 | "Treesitter language parsers required by `php-ts-mode'. | 88 | "Treesitter language parsers required by `php-ts-mode'. |
| 91 | You can customize `treesit-language-source-alist' if you want | 89 | You can customize `treesit-language-source-alist' if you want |
| 92 | to stick to a specific commit and/or use different parsers.") | 90 | to stick to a specific commit and/or use different parsers.") |
| @@ -97,9 +95,10 @@ to stick to a specific commit and/or use different parsers.") | |||
| 97 | (defun php-ts-mode-install-parsers () | 95 | (defun php-ts-mode-install-parsers () |
| 98 | "Install all the required treesitter parsers. | 96 | "Install all the required treesitter parsers. |
| 99 | `treesit-language-source-alist' defines which parsers to install. | 97 | `treesit-language-source-alist' defines which parsers to install. |
| 100 | It's pre-filled by loading \"html-ts-mode\", \"css-mode\", \"js\"." | 98 | It's pre-filled by loading \"mhtml-ts-mode\"." |
| 101 | (interactive) | 99 | (interactive) |
| 102 | (dolist (lang '(php phpdoc html css javascript jsdoc)) | 100 | (mhtml-ts-mode-install-parsers) |
| 101 | (dolist (lang '(php phpdoc)) | ||
| 103 | (treesit-install-language-grammar lang))) | 102 | (treesit-install-language-grammar lang))) |
| 104 | 103 | ||
| 105 | ;;; Custom variables | 104 | ;;; Custom variables |
| @@ -118,25 +117,63 @@ It's pre-filled by loading \"html-ts-mode\", \"css-mode\", \"js\"." | |||
| 118 | 117 | ||
| 119 | (defcustom php-ts-mode-js-css-indent-offset 2 | 118 | (defcustom php-ts-mode-js-css-indent-offset 2 |
| 120 | "JavaScript and CSS indent spaces related to the <script> and <style> HTML tags. | 119 | "JavaScript and CSS indent spaces related to the <script> and <style> HTML tags. |
| 121 | By default should have same value as `html-ts-mode-indent-offset'." | 120 | It is advisable to have this have the same value as |
| 121 | `mhtml-ts-mode-js-css-indent-offset'." | ||
| 122 | :tag "PHP javascript or css indent offset" | 122 | :tag "PHP javascript or css indent offset" |
| 123 | :version "30.1" | 123 | :version "30.1" |
| 124 | :type 'integer | 124 | :type 'integer |
| 125 | :safe 'integerp) | 125 | :safe 'integerp) |
| 126 | 126 | ||
| 127 | (defcustom php-ts-mode-css-fontify-colors t | 127 | (defcustom php-ts-mode-html-indent-offset 2 |
| 128 | "Whether CSS colors should be fontified using the color as the background. | 128 | "The number of spaces to indent PHP code relative to HTML tags. |
| 129 | If non-nil, text representing a CSS color will be fontified | 129 | It is advisable to have this have the same value as |
| 130 | such that its background is the color itself. | 130 | `mhtml-ts-mode-js-css-indent-offset'." |
| 131 | Works like `css--fontify-region'." | 131 | :tag "PHP indent offset relative to HTML" |
| 132 | :tag "PHP colors the CSS properties values." | 132 | :version "31.1" |
| 133 | :version "30.1" | 133 | :type 'integer |
| 134 | :type 'boolean | 134 | :safe 'integerp) |
| 135 | :safe 'booleanp) | ||
| 136 | 135 | ||
| 137 | (defcustom php-ts-mode-php-default-executable (or (executable-find "php") "/usr/bin/php") | 136 | (defcustom php-ts-mode-html-relative-indent t |
| 138 | "The default PHP executable." | 137 | "How PHP code is indented relative to the HTML tags. |
| 139 | :tag "PHP Executable" | 138 | |
| 139 | When t, the default, indentation looks like: | ||
| 140 | |||
| 141 | <html> | ||
| 142 | ... | ||
| 143 | <div> | ||
| 144 | <?php | ||
| 145 | ?> | ||
| 146 | </div> | ||
| 147 | |||
| 148 | When nil, indentation of the tag body starts just below the | ||
| 149 | tag, like: | ||
| 150 | |||
| 151 | <html> | ||
| 152 | ... | ||
| 153 | <div> | ||
| 154 | <?php | ||
| 155 | ?> | ||
| 156 | </div> | ||
| 157 | |||
| 158 | When `ignore', the tag body starts in the first column, like: | ||
| 159 | |||
| 160 | <html> | ||
| 161 | ... | ||
| 162 | <div> | ||
| 163 | <?php | ||
| 164 | ?> | ||
| 165 | </div>" | ||
| 166 | :type '(choice | ||
| 167 | (const :tag "Indent starts just below the HTML tag" nil) | ||
| 168 | (const :tag "Indent relative to the HTML tag" t) | ||
| 169 | (const :tag "Always in the first column" ignore)) | ||
| 170 | :safe 'symbolp | ||
| 171 | :tag "PHP indent relative to HTML" | ||
| 172 | :version "31.1") | ||
| 173 | |||
| 174 | (defcustom php-ts-mode-php-default-executable (or (executable-find "php") "php") | ||
| 175 | "The default file name of the PHP executable." | ||
| 176 | :tag "PHP executable" | ||
| 140 | :version "30.1" | 177 | :version "30.1" |
| 141 | :type 'file) | 178 | :type 'file) |
| 142 | 179 | ||
| @@ -148,7 +185,7 @@ If non-nil, `php-ts-mode--executable' looks for this instead of \"php\".") | |||
| 148 | "The location of php.ini file. | 185 | "The location of php.ini file. |
| 149 | If nil the default one is used to run the embedded webserver or | 186 | If nil the default one is used to run the embedded webserver or |
| 150 | inferior PHP process." | 187 | inferior PHP process." |
| 151 | :tag "PHP Init file" | 188 | :tag "PHP init file" |
| 152 | :version "30.1" | 189 | :version "30.1" |
| 153 | :type '(choice (const :tag "Default init file" nil) file)) | 190 | :type '(choice (const :tag "Default init file" nil) file)) |
| 154 | 191 | ||
| @@ -198,6 +235,29 @@ Useful for testing code against multiple simultaneous requests." | |||
| 198 | :type '(choice (const :tag "None" nil) file) | 235 | :type '(choice (const :tag "None" nil) file) |
| 199 | :safe 'string-or-null-p) | 236 | :safe 'string-or-null-p) |
| 200 | 237 | ||
| 238 | (defcustom php-ts-mode-find-sibling-rules | ||
| 239 | (list (list (rx "src/" (group (+ not-newline) "/") (group (+ (not "/"))) ".php") "tests/\\1\\2Test.php") | ||
| 240 | (list (rx "tests/" (group (+ not-newline) "/") (group (+ (not "/"))) "Test.php") "src/\\1\\2.php")) | ||
| 241 | "Rules for finding sibling files. See `find-sibling-rules' for the | ||
| 242 | form of the value. | ||
| 243 | As a default, the rules try to find the corresponding test of the | ||
| 244 | current source file and vice versa. Source files are assumed to be in | ||
| 245 | src/, and tests of in tests/. Many frameworks have a folder | ||
| 246 | arrangement similar to this." | ||
| 247 | :type '(alist :key-type (regexp :tag "Match") | ||
| 248 | :value-type (repeat (string :tag "Expansion"))) | ||
| 249 | :tag "PHP find sibling rules" | ||
| 250 | :version "31.1") | ||
| 251 | |||
| 252 | (defcustom php-ts-mode-phpdoc-highlight-errors nil | ||
| 253 | "Highlight tags unknown to the phpdoc parser. | ||
| 254 | If nil try to highlight even incorrect nodes as if they were correct, | ||
| 255 | otherwise show phpdoc error using a `font-lock-warning-face'." | ||
| 256 | :tag "PHPDOC face for unknown tags or errors." | ||
| 257 | :version "31.1" | ||
| 258 | :type 'boolean | ||
| 259 | :safe 'booleanp) | ||
| 260 | |||
| 201 | (defvar php-ts-mode--inferior-prompt "php >" | 261 | (defvar php-ts-mode--inferior-prompt "php >" |
| 202 | "Prompt used by PHP inferior process.") | 262 | "Prompt used by PHP inferior process.") |
| 203 | 263 | ||
| @@ -210,9 +270,9 @@ SYM should be `php-ts-mode-indent-style', and VAL should be a style | |||
| 210 | symbol." | 270 | symbol." |
| 211 | (set-default sym val) | 271 | (set-default sym val) |
| 212 | (dolist (buffer (buffer-list)) | 272 | (dolist (buffer (buffer-list)) |
| 213 | (with-current-buffer buffer | 273 | (with-current-buffer buffer |
| 214 | (when (derived-mode-p 'php-ts-mode) | 274 | (when (derived-mode-p 'php-ts-mode) |
| 215 | (php-ts-mode-set-style val))))) | 275 | (php-ts-mode-set-style val))))) |
| 216 | 276 | ||
| 217 | ;; taken from c-ts-mode | 277 | ;; taken from c-ts-mode |
| 218 | (defun php-ts-indent-style-safep (style) | 278 | (defun php-ts-indent-style-safep (style) |
| @@ -235,12 +295,12 @@ follows the form of `treesit-simple-indent-rules'." | |||
| 235 | :tag "PHP indent style" | 295 | :tag "PHP indent style" |
| 236 | :version "30.1" | 296 | :version "30.1" |
| 237 | :type '(choice (const :tag "PSR-2/PSR-12" psr2) | 297 | :type '(choice (const :tag "PSR-2/PSR-12" psr2) |
| 238 | (const :tag "PEAR" pear) | 298 | (const :tag "PEAR" pear) |
| 239 | (const :tag "Drupal" drupal) | 299 | (const :tag "Drupal" drupal) |
| 240 | (const :tag "WordPress" wordpress) | 300 | (const :tag "WordPress" wordpress) |
| 241 | (const :tag "Symfony" symfony) | 301 | (const :tag "Symfony" symfony) |
| 242 | (const :tag "Zend" zend) | 302 | (const :tag "Zend" zend) |
| 243 | (function :tag "A function for user customized style" ignore)) | 303 | (function :tag "A function for user customized style" ignore)) |
| 244 | :set #'php-ts-mode--indent-style-setter | 304 | :set #'php-ts-mode--indent-style-setter |
| 245 | :safe #'php-ts-indent-style-safep) | 305 | :safe #'php-ts-indent-style-safep) |
| 246 | 306 | ||
| @@ -258,52 +318,52 @@ Calls REPORT-FN directly." | |||
| 258 | (when (process-live-p php-ts-mode--flymake-process) | 318 | (when (process-live-p php-ts-mode--flymake-process) |
| 259 | (kill-process php-ts-mode--flymake-process)) | 319 | (kill-process php-ts-mode--flymake-process)) |
| 260 | (let ((source (current-buffer)) | 320 | (let ((source (current-buffer)) |
| 261 | (diagnostics-pattern (eval-when-compile | 321 | (diagnostics-pattern (eval-when-compile |
| 262 | (rx bol (? "PHP ") ;; every diagnostic line start with PHP | 322 | (rx bol (? "PHP ") ;; every diagnostic line start with PHP |
| 263 | (group (or "Fatal" "Parse")) ;; 1: type | 323 | (group (or "Fatal" "Parse")) ;; 1: type |
| 264 | " error:" (+ (syntax whitespace)) | 324 | " error:" (+ (syntax whitespace)) |
| 265 | (group (+? nonl)) ;; 2: msg | 325 | (group (+? nonl)) ;; 2: msg |
| 266 | " in " (group (+? nonl)) ;; 3: file | 326 | " in " (group (+? nonl)) ;; 3: file |
| 267 | " on line " (group (+ num)) ;; 4: line | 327 | " on line " (group (+ num)) ;; 4: line |
| 268 | eol)))) | 328 | eol)))) |
| 269 | (save-restriction | 329 | (save-restriction |
| 270 | (widen) | 330 | (widen) |
| 271 | (setq php-ts-mode--flymake-process | 331 | (setq php-ts-mode--flymake-process |
| 272 | (make-process | 332 | (make-process |
| 273 | :name "php-ts-mode-flymake" | 333 | :name "php-ts-mode-flymake" |
| 274 | :noquery t | 334 | :noquery t |
| 275 | :connection-type 'pipe | 335 | :connection-type 'pipe |
| 276 | :buffer (generate-new-buffer " *php-ts-mode-flymake*") | 336 | :buffer (generate-new-buffer " *php-ts-mode-flymake*") |
| 277 | :command `(,(php-ts-mode--executable) | 337 | :command `(,(php-ts-mode--executable) |
| 278 | "-l" "-d" "display_errors=0") | 338 | "-l" "-d" "display_errors=0") |
| 279 | :sentinel | 339 | :sentinel |
| 280 | (lambda (proc _event) | 340 | (lambda (proc _event) |
| 281 | (when (eq 'exit (process-status proc)) | 341 | (when (eq 'exit (process-status proc)) |
| 282 | (unwind-protect | 342 | (unwind-protect |
| 283 | (if (with-current-buffer source | 343 | (if (with-current-buffer source |
| 284 | (eq proc php-ts-mode--flymake-process)) | 344 | (eq proc php-ts-mode--flymake-process)) |
| 285 | (with-current-buffer (process-buffer proc) | 345 | (with-current-buffer (process-buffer proc) |
| 286 | (goto-char (point-min)) | 346 | (goto-char (point-min)) |
| 287 | (let (diags) | 347 | (let (diags) |
| 288 | (while (search-forward-regexp | 348 | (while (search-forward-regexp |
| 289 | diagnostics-pattern | 349 | diagnostics-pattern |
| 290 | nil t) | 350 | nil t) |
| 291 | (let* ((beg | 351 | (let* ((beg |
| 292 | (car (flymake-diag-region | 352 | (car (flymake-diag-region |
| 293 | source | 353 | source |
| 294 | (string-to-number (match-string 4))))) | 354 | (string-to-number (match-string 4))))) |
| 295 | (end | 355 | (end |
| 296 | (cdr (flymake-diag-region | 356 | (cdr (flymake-diag-region |
| 297 | source | 357 | source |
| 298 | (string-to-number (match-string 4))))) | 358 | (string-to-number (match-string 4))))) |
| 299 | (msg (match-string 2)) | 359 | (msg (match-string 2)) |
| 300 | (type :error)) | 360 | (type :error)) |
| 301 | (push (flymake-make-diagnostic | 361 | (push (flymake-make-diagnostic |
| 302 | source beg end type msg) | 362 | source beg end type msg) |
| 303 | diags))) | 363 | diags))) |
| 304 | (funcall report-fn diags))) | 364 | (funcall report-fn diags))) |
| 305 | (flymake-log :warning "Canceling obsolete check %s" proc)) | 365 | (flymake-log :warning "Canceling obsolete check %s" proc)) |
| 306 | (kill-buffer (process-buffer proc))))))) | 366 | (kill-buffer (process-buffer proc))))))) |
| 307 | (process-send-region php-ts-mode--flymake-process (point-min) (point-max)) | 367 | (process-send-region php-ts-mode--flymake-process (point-min) (point-max)) |
| 308 | (process-send-eof php-ts-mode--flymake-process)))) | 368 | (process-send-eof php-ts-mode--flymake-process)))) |
| 309 | 369 | ||
| @@ -317,23 +377,55 @@ it searches locally. If `php-ts-mode-alternative-php-program-name' is | |||
| 317 | non-nil, it searches for this program instead of the usual `php'. | 377 | non-nil, it searches for this program instead of the usual `php'. |
| 318 | If the search fails, it returns `php-ts-mode-php-default-executable'." | 378 | If the search fails, it returns `php-ts-mode-php-default-executable'." |
| 319 | (or (executable-find | 379 | (or (executable-find |
| 320 | (or php-ts-mode-alternative-php-program-name "php") t) | 380 | (or php-ts-mode-alternative-php-program-name "php") t) |
| 321 | php-ts-mode-php-default-executable)) | 381 | php-ts-mode-php-default-executable)) |
| 382 | |||
| 383 | (defun php-ts-mode-show-ini () | ||
| 384 | "Pop a buffer showing the PHP configuration file names." | ||
| 385 | (interactive) | ||
| 386 | (let ((buffer (get-buffer-create "*PHP ini*")) | ||
| 387 | (button-action (lambda (_) (find-file-at-point))) | ||
| 388 | (remote (file-remote-p default-directory))) | ||
| 389 | (with-current-buffer buffer | ||
| 390 | (view-mode -1) | ||
| 391 | (erase-buffer) | ||
| 392 | (shell-command (concat (php-ts-mode--executable) " --ini") buffer) | ||
| 393 | ;; Remove useless ',' at end of some rows. | ||
| 394 | (while (re-search-forward "," nil t) | ||
| 395 | (replace-match "" nil nil)) | ||
| 396 | (goto-char (point-min)) | ||
| 397 | (while (re-search-forward | ||
| 398 | "[a-zA-Z]?[:]?[/\\].+" | ||
| 399 | nil t) | ||
| 400 | (let ((start (match-beginning 0)) | ||
| 401 | (end (match-end 0))) | ||
| 402 | ;; If PHP is on a remote machine, the path must be preceded | ||
| 403 | ;; by the remote identifier. | ||
| 404 | (when remote | ||
| 405 | (goto-char start) | ||
| 406 | (insert remote) | ||
| 407 | (setq end (+ end (length remote))) | ||
| 408 | (goto-char end)) | ||
| 409 | (make-button start end 'action button-action))) | ||
| 410 | (goto-char (point-min)) | ||
| 411 | (view-mode +1)) | ||
| 412 | (when buffer | ||
| 413 | (pop-to-buffer buffer)))) | ||
| 322 | 414 | ||
| 323 | (defun php-ts-mode--get-indent-style () | 415 | (defun php-ts-mode--get-indent-style () |
| 324 | "Helper function to set indentation style. | 416 | "Helper function to set indentation style. |
| 325 | MODE can be `psr2', `pear', `drupal', `wordpress', `symfony', `zend'." | 417 | MODE can be `psr2', `pear', `drupal', `wordpress', `symfony', `zend'." |
| 326 | (let ((style | 418 | (let ((style |
| 327 | (if (functionp php-ts-mode-indent-style) | 419 | (if (functionp php-ts-mode-indent-style) |
| 328 | (funcall php-ts-mode-indent-style) | 420 | (funcall php-ts-mode-indent-style) |
| 329 | (cl-case php-ts-mode-indent-style | 421 | (cl-case php-ts-mode-indent-style |
| 330 | (psr2 (alist-get 'psr2 (php-ts-mode--indent-styles))) | 422 | (psr2 (alist-get 'psr2 (php-ts-mode--indent-styles))) |
| 331 | (pear (alist-get 'pear (php-ts-mode--indent-styles))) | 423 | (pear (alist-get 'pear (php-ts-mode--indent-styles))) |
| 332 | (drupal (alist-get 'drupal (php-ts-mode--indent-styles))) | 424 | (drupal (alist-get 'drupal (php-ts-mode--indent-styles))) |
| 333 | (wordpress (alist-get 'wordpress (php-ts-mode--indent-styles))) | 425 | (wordpress (alist-get 'wordpress (php-ts-mode--indent-styles))) |
| 334 | (symfony (alist-get 'symfony (php-ts-mode--indent-styles))) | 426 | (symfony (alist-get 'symfony (php-ts-mode--indent-styles))) |
| 335 | (zend (alist-get 'zend (php-ts-mode--indent-styles))) | 427 | (zend (alist-get 'zend (php-ts-mode--indent-styles))) |
| 336 | (t (alist-get 'psr2 (php-ts-mode--indent-styles))))))) | 428 | (t (alist-get 'psr2 (php-ts-mode--indent-styles))))))) |
| 337 | `((php ,@style)))) | 429 | `((php ,@style)))) |
| 338 | 430 | ||
| 339 | (defun php-ts-mode--prompt-for-style () | 431 | (defun php-ts-mode--prompt-for-style () |
| @@ -357,23 +449,23 @@ in this Emacs session." | |||
| 357 | "Set the offset, tab, etc. according to STYLE." | 449 | "Set the offset, tab, etc. according to STYLE." |
| 358 | (cl-case style | 450 | (cl-case style |
| 359 | (psr2 (setq php-ts-mode-indent-offset 4 | 451 | (psr2 (setq php-ts-mode-indent-offset 4 |
| 360 | tab-width 4 | 452 | tab-width 4 |
| 361 | indent-tabs-mode nil)) | 453 | indent-tabs-mode nil)) |
| 362 | (pear (setq php-ts-mode-indent-offset 4 | 454 | (pear (setq php-ts-mode-indent-offset 4 |
| 363 | tab-width 4 | 455 | tab-width 4 |
| 364 | indent-tabs-mode nil)) | 456 | indent-tabs-mode nil)) |
| 365 | (drupal (setq php-ts-mode-indent-offset 2 | 457 | (drupal (setq php-ts-mode-indent-offset 2 |
| 366 | tab-width 2 | 458 | tab-width 2 |
| 367 | indent-tabs-mode nil)) | 459 | indent-tabs-mode nil)) |
| 368 | (wordpress (setq php-ts-mode-indent-offset 4 | 460 | (wordpress (setq php-ts-mode-indent-offset 4 |
| 369 | tab-width 4 | 461 | tab-width 4 |
| 370 | indent-tabs-mode t)) | 462 | indent-tabs-mode t)) |
| 371 | (symfony (setq php-ts-mode-indent-offset 4 | 463 | (symfony (setq php-ts-mode-indent-offset 4 |
| 372 | tab-width 4 | 464 | tab-width 4 |
| 373 | indent-tabs-mode nil)) | 465 | indent-tabs-mode nil)) |
| 374 | (zend (setq php-ts-mode-indent-offset 4 | 466 | (zend (setq php-ts-mode-indent-offset 4 |
| 375 | tab-width 4 | 467 | tab-width 4 |
| 376 | indent-tabs-mode nil)))) | 468 | indent-tabs-mode nil)))) |
| 377 | 469 | ||
| 378 | (defun php-ts-mode-set-style (style) | 470 | (defun php-ts-mode-set-style (style) |
| 379 | "Set the PHP indent style of the current buffer to STYLE. | 471 | "Set the PHP indent style of the current buffer to STYLE. |
| @@ -386,13 +478,13 @@ To set the default indent style globally, use | |||
| 386 | ((equal php-ts-mode-indent-style style) | 478 | ((equal php-ts-mode-indent-style style) |
| 387 | (message "The style is already %s" style));; nothing to do | 479 | (message "The style is already %s" style));; nothing to do |
| 388 | (t (progn | 480 | (t (progn |
| 389 | (setq-local php-ts-mode-indent-style style) | 481 | (setq-local php-ts-mode-indent-style style) |
| 390 | (php-ts-mode--set-indent-property style) | 482 | (php-ts-mode--set-indent-property style) |
| 391 | (let ((rules (assq-delete-all 'php treesit-simple-indent-rules)) | 483 | (let ((rules (assq-delete-all 'php treesit-simple-indent-rules)) |
| 392 | (new-style (car (treesit--indent-rules-optimize | 484 | (new-style (car (treesit--indent-rules-optimize |
| 393 | (php-ts-mode--get-indent-style))))) | 485 | (php-ts-mode--get-indent-style))))) |
| 394 | (setq treesit-simple-indent-rules (cons new-style rules)) | 486 | (setq treesit-simple-indent-rules (cons new-style rules)) |
| 395 | (message "Switch to %s style" style)))))) | 487 | (message "Switch to %s style" style)))))) |
| 396 | 488 | ||
| 397 | (defun php-ts-mode--get-parser-ranges () | 489 | (defun php-ts-mode--get-parser-ranges () |
| 398 | "Return the ranges covered by the parsers. | 490 | "Return the ranges covered by the parsers. |
| @@ -401,9 +493,9 @@ To set the default indent style globally, use | |||
| 401 | current buffer, the ranges covered by each parser. | 493 | current buffer, the ranges covered by each parser. |
| 402 | Useful for debugging." | 494 | Useful for debugging." |
| 403 | (let ((ranges) | 495 | (let ((ranges) |
| 404 | (parsers (treesit-parser-list nil nil t))) | 496 | (parsers (treesit-parser-list nil nil t))) |
| 405 | (if (not parsers) | 497 | (if (not parsers) |
| 406 | (message "At least one parser must be initialized")) | 498 | (message "At least one parser must be initialized")) |
| 407 | (cl-loop | 499 | (cl-loop |
| 408 | for parser in parsers | 500 | for parser in parsers |
| 409 | do (push (list parser (treesit-parser-included-ranges parser)) ranges) | 501 | do (push (list parser (treesit-parser-included-ranges parser)) ranges) |
| @@ -442,27 +534,6 @@ Useful for debugging." | |||
| 442 | 534 | ||
| 443 | ;;; Indent | 535 | ;;; Indent |
| 444 | 536 | ||
| 445 | (defconst php-ts-mode--possibly-braceless-keyword-re | ||
| 446 | (regexp-opt '("if" "for" "foreach" "while" "do") 'symbols) | ||
| 447 | "Regexp matching keywords optionally followed by an opening brace.") | ||
| 448 | |||
| 449 | (defun php-ts-mode--open-statement-group-heuristic (node _parent bol &rest _) | ||
| 450 | "Heuristic matcher for statement-group without closing bracket. | ||
| 451 | |||
| 452 | Return `php-ts-mode-indent-offset' plus 1 when BOL is after | ||
| 453 | `php-ts-mode--possibly-braceless-keyword-re', otherwise return 0. It's | ||
| 454 | useful for matching incomplete compound_statement or colon_block. | ||
| 455 | PARENT is NODE's parent, BOL is the beginning of non-whitespace | ||
| 456 | characters of the current line." | ||
| 457 | (and (null node) | ||
| 458 | (save-excursion | ||
| 459 | (forward-line -1) | ||
| 460 | (if (re-search-forward | ||
| 461 | php-ts-mode--possibly-braceless-keyword-re | ||
| 462 | bol t) | ||
| 463 | (+ 1 php-ts-mode-indent-offset) | ||
| 464 | 0)))) | ||
| 465 | |||
| 466 | ;; taken from c-ts-mode | 537 | ;; taken from c-ts-mode |
| 467 | (defun php-ts-mode--else-heuristic (node parent bol &rest _) | 538 | (defun php-ts-mode--else-heuristic (node parent bol &rest _) |
| 468 | "Heuristic matcher for when \"else\" is followed by a closing bracket. | 539 | "Heuristic matcher for when \"else\" is followed by a closing bracket. |
| @@ -471,10 +542,10 @@ PARENT is NODE's parent, BOL is the beginning of non-whitespace | |||
| 471 | characters of the current line." | 542 | characters of the current line." |
| 472 | (and (null node) | 543 | (and (null node) |
| 473 | (save-excursion | 544 | (save-excursion |
| 474 | (forward-line -1) | 545 | (forward-line -1) |
| 475 | (looking-at (rx (* whitespace) "else" (* whitespace) eol))) | 546 | (looking-at (rx (* whitespace) "else" (* whitespace) eol))) |
| 476 | (let ((next-node (treesit-node-first-child-for-pos parent bol))) | 547 | (let ((next-node (treesit-node-first-child-for-pos parent bol))) |
| 477 | (equal (treesit-node-type next-node) "}")))) | 548 | (equal (treesit-node-type next-node) "}")))) |
| 478 | 549 | ||
| 479 | ;; taken from c-ts-mode | 550 | ;; taken from c-ts-mode |
| 480 | (defun php-ts-mode--first-sibling (node parent &rest _) | 551 | (defun php-ts-mode--first-sibling (node parent &rest _) |
| @@ -485,26 +556,11 @@ such that it's on its own line. NODE is the node to match and | |||
| 485 | PARENT is its parent." | 556 | PARENT is its parent." |
| 486 | (let ((prev-sibling (treesit-node-prev-sibling node t))) | 557 | (let ((prev-sibling (treesit-node-prev-sibling node t))) |
| 487 | (or (null prev-sibling) | 558 | (or (null prev-sibling) |
| 488 | (save-excursion | ||
| 489 | (goto-char (treesit-node-start prev-sibling)) | ||
| 490 | (<= (line-beginning-position) | ||
| 491 | (treesit-node-start parent) | ||
| 492 | (line-end-position)))))) | ||
| 493 | |||
| 494 | (defun php-ts-mode--js-css-tag-bol (_node parent &rest _) | ||
| 495 | "Find the first non-space characters of html tags <script> or <style>. | ||
| 496 | |||
| 497 | Return `line-beginning-position' when `treesit-node-at' is HTML or PHP. | ||
| 498 | Otherwise go to the PARENT and search backward for <script> or <style> tags. | ||
| 499 | Should be used only for Javascript or CSS indenting rules. | ||
| 500 | NODE, ignored, is the node to match and PARENT is its parent." | ||
| 501 | (let ((lang (treesit-language-at (point)))) | ||
| 502 | (if (or (eq lang 'javascript) | ||
| 503 | (eq lang 'css)) | ||
| 504 | (save-excursion | 559 | (save-excursion |
| 505 | (goto-char (treesit-node-start parent)) | 560 | (goto-char (treesit-node-start prev-sibling)) |
| 506 | (re-search-backward "<script.*>\\|<style.*>" nil t)) | 561 | (<= (line-beginning-position) |
| 507 | (line-beginning-position)))) | 562 | (treesit-node-start parent) |
| 563 | (line-end-position)))))) | ||
| 508 | 564 | ||
| 509 | (defun php-ts-mode--parent-eol (_node parent &rest _) | 565 | (defun php-ts-mode--parent-eol (_node parent &rest _) |
| 510 | "Find the last non-space characters of the PARENT of the current NODE. | 566 | "Find the last non-space characters of the PARENT of the current NODE. |
| @@ -514,50 +570,33 @@ NODE is the node to match and PARENT is its parent." | |||
| 514 | (goto-char (treesit-node-start parent)) | 570 | (goto-char (treesit-node-start parent)) |
| 515 | (line-end-position))) | 571 | (line-end-position))) |
| 516 | 572 | ||
| 517 | (defun php-ts-mode--parent-html-bol (node parent bol &rest _) | ||
| 518 | "Find the first non-space characters of the HTML tags before NODE. | ||
| 519 | |||
| 520 | When NODE is nil call `php-ts-mode--open-statement-group-heuristic'. | ||
| 521 | PARENT is NODE's parent, BOL is the beginning of non-whitespace | ||
| 522 | characters of the current line." | ||
| 523 | (if (null node) | ||
| 524 | ;; If NODE is nil it could be an open statement-group. | ||
| 525 | (php-ts-mode--open-statement-group-heuristic node parent bol) | ||
| 526 | (save-excursion | ||
| 527 | (let ((html-node (treesit-search-forward node "text" t))) | ||
| 528 | (if html-node | ||
| 529 | (let ((end-html (treesit-node-end html-node))) | ||
| 530 | (goto-char end-html) | ||
| 531 | (backward-word) | ||
| 532 | (back-to-indentation) | ||
| 533 | (point)) | ||
| 534 | (treesit-node-start parent)))))) | ||
| 535 | |||
| 536 | (defun php-ts-mode--parent-html-heuristic (node parent bol &rest _) | 573 | (defun php-ts-mode--parent-html-heuristic (node parent bol &rest _) |
| 537 | "Return position based on html indentation. | 574 | "Return position based on html indentation. |
| 538 | 575 | ||
| 539 | Returns 0 if the NODE is after the </html>, otherwise returns the | 576 | Return 0 if the NODE is after the </html>. If |
| 540 | indentation point of the last word before the NODE, plus the indentation | 577 | `php-ts-mode-html-relative-indent' is not nil return the indentation |
| 541 | offset. If there is no HTML tag, it returns the beginning of the | 578 | point of the last word before the NODE, plus the indentation offset, |
| 542 | parent. When NODE is nil call `php-ts-mode--open-statement-group-heuristic'. | 579 | otherwise return only the indentation point. If there is no HTML tag, |
| 543 | It can be used when you want to indent PHP code relative to the HTML. | 580 | it returns the beginning of the parent. When NODE is nil it behaves |
| 544 | PARENT is NODE's parent, BOL is the beginning of non-whitespace | 581 | like \"prev-siblings\" of `treesit-simple-indent-presets'. It can be |
| 545 | characters of the current line." | 582 | used when you want to indent PHP code relative to the HTML. PARENT is |
| 546 | (if (null node) | 583 | NODE's parent, BOL is the beginning of non-whitespace characters of |
| 547 | ;; If NODE is nil it could be an open statement-group. | 584 | the current line." |
| 548 | (php-ts-mode--open-statement-group-heuristic node parent bol) | 585 | (save-excursion |
| 549 | (let ((html-node (treesit-search-forward node "text" t))) | 586 | (cond |
| 550 | (if html-node | 587 | ((eq php-ts-mode-html-relative-indent 'ignore) (line-beginning-position)) |
| 551 | (let ((end-html (treesit-node-end html-node))) | 588 | ((search-backward "</html>" (treesit-node-start parent) t 1) (line-beginning-position)) |
| 552 | (save-excursion | 589 | ((null node) (apply (alist-get 'prev-sibling treesit-simple-indent-presets) node parent bol nil)) |
| 553 | (goto-char end-html) | 590 | (t (when-let* ((html-node (treesit-search-forward node "text" t)) |
| 554 | (backward-word) | 591 | (end-html (treesit-node-end html-node))) |
| 555 | (back-to-indentation) | 592 | (goto-char end-html) |
| 556 | (if (search-forward "</html>" end-html t 1) | 593 | ;; go to the start of the last tag |
| 557 | 0 | 594 | ;; of the "text" node |
| 558 | (+ (point) php-ts-mode-indent-offset)))) | 595 | (backward-word) |
| 559 | ;; Maybe it's better to use bol? | 596 | (back-to-indentation) |
| 560 | (treesit-node-start parent))))) | 597 | (if php-ts-mode-html-relative-indent |
| 598 | (+ (point) php-ts-mode-html-indent-offset) | ||
| 599 | (point))))))) | ||
| 561 | 600 | ||
| 562 | (defun php-ts-mode--array-element-heuristic (_node parent _bol &rest _) | 601 | (defun php-ts-mode--array-element-heuristic (_node parent _bol &rest _) |
| 563 | "Return of the position of the first element of the array. | 602 | "Return of the position of the first element of the array. |
| @@ -565,21 +604,20 @@ characters of the current line." | |||
| 565 | PARENT is NODE's parent, BOL is the beginning of non-whitespace | 604 | PARENT is NODE's parent, BOL is the beginning of non-whitespace |
| 566 | characters of the current line." | 605 | characters of the current line." |
| 567 | (let ((parent-start | 606 | (let ((parent-start |
| 568 | (treesit-node-start parent)) | 607 | (treesit-node-start parent)) |
| 569 | (parent-first-child-start | 608 | (parent-first-child-start |
| 570 | (treesit-node-start (treesit-node-child parent 2)))) | 609 | (treesit-node-start (treesit-node-child parent 2)))) |
| 571 | (if (equal | 610 | (if (equal |
| 572 | (line-number-at-pos parent-start) | 611 | (line-number-at-pos parent-start) |
| 573 | (line-number-at-pos parent-first-child-start)) | 612 | (line-number-at-pos parent-first-child-start)) |
| 574 | ;; if array_creation_expression and the first | 613 | ;; if array_creation_expression and the first |
| 575 | ;; array_element_initializer are on the same same line | 614 | ;; array_element_initializer are on the same same line |
| 576 | parent-first-child-start | 615 | parent-first-child-start |
| 577 | ;; else return parent-bol plus the offset | 616 | ;; else return parent-bol plus the offset |
| 578 | (save-excursion | 617 | (save-excursion |
| 579 | (goto-char (treesit-node-start parent)) | 618 | (goto-char (treesit-node-start parent)) |
| 580 | (back-to-indentation) | 619 | (back-to-indentation) |
| 581 | (+ (point) php-ts-mode-indent-offset))))) | 620 | (+ (point) php-ts-mode-indent-offset))))) |
| 582 | |||
| 583 | 621 | ||
| 584 | (defun php-ts-mode--anchor-first-sibling (_node parent _bol &rest _) | 622 | (defun php-ts-mode--anchor-first-sibling (_node parent _bol &rest _) |
| 585 | "Return the start of the first child of a sibling of PARENT. | 623 | "Return the start of the first child of a sibling of PARENT. |
| @@ -590,14 +628,14 @@ sibling. Otherwise return the start of the first sibling. | |||
| 590 | PARENT is NODE's parent, BOL is the beginning of non-whitespace | 628 | PARENT is NODE's parent, BOL is the beginning of non-whitespace |
| 591 | characters of the current line." | 629 | characters of the current line." |
| 592 | (let ((first-sibling-start | 630 | (let ((first-sibling-start |
| 593 | (treesit-node-start (treesit-node-child parent 0))) | 631 | (treesit-node-start (treesit-node-child parent 0))) |
| 594 | (first-sibling-child-start | 632 | (first-sibling-child-start |
| 595 | (treesit-node-start (treesit-node-child parent 1)))) | 633 | (treesit-node-start (treesit-node-child parent 1)))) |
| 596 | (if (equal | 634 | (if (equal |
| 597 | (line-number-at-pos first-sibling-start) | 635 | (line-number-at-pos first-sibling-start) |
| 598 | (line-number-at-pos first-sibling-child-start)) | 636 | (line-number-at-pos first-sibling-child-start)) |
| 599 | ;; if are on the same line return the child start | 637 | ;; if are on the same line return the child start |
| 600 | first-sibling-child-start | 638 | first-sibling-child-start |
| 601 | first-sibling-start))) | 639 | first-sibling-start))) |
| 602 | 640 | ||
| 603 | ;; adapted from c-ts-mode--anchor-prev-sibling | 641 | ;; adapted from c-ts-mode--anchor-prev-sibling |
| @@ -610,150 +648,158 @@ doesn't have a child. | |||
| 610 | PARENT is NODE's parent, BOL is the beginning of non-whitespace | 648 | PARENT is NODE's parent, BOL is the beginning of non-whitespace |
| 611 | characters of the current line." | 649 | characters of the current line." |
| 612 | (when-let* ((prev-sibling | 650 | (when-let* ((prev-sibling |
| 613 | (or (treesit-node-prev-sibling node t) | 651 | (or (treesit-node-prev-sibling node t) |
| 614 | (treesit-node-prev-sibling | 652 | (treesit-node-prev-sibling |
| 615 | (treesit-node-first-child-for-pos parent bol) t) | 653 | (treesit-node-first-child-for-pos parent bol) t) |
| 616 | (treesit-node-child parent -1 t))) | 654 | (treesit-node-child parent -1 t))) |
| 617 | (continue t)) | 655 | (continue t)) |
| 618 | (save-excursion | 656 | (save-excursion |
| 619 | (while (and prev-sibling continue) | 657 | (while (and prev-sibling continue) |
| 620 | (goto-char (treesit-node-start prev-sibling)) | 658 | (goto-char (treesit-node-start prev-sibling)) |
| 621 | (if (looking-back (rx bol (* whitespace)) | 659 | (if (looking-back (rx bol (* whitespace)) |
| 622 | (line-beginning-position)) | 660 | (line-beginning-position)) |
| 623 | (setq continue nil) | 661 | (setq continue nil) |
| 624 | (setq prev-sibling | 662 | (setq prev-sibling |
| 625 | (treesit-node-prev-sibling prev-sibling))))) | 663 | (treesit-node-prev-sibling prev-sibling))))) |
| 626 | (treesit-node-start prev-sibling))) | 664 | (treesit-node-start prev-sibling))) |
| 627 | 665 | ||
| 628 | (defun php-ts-mode--indent-styles () | 666 | (defun php-ts-mode--indent-styles () |
| 629 | "Indent rules supported by `php-ts-mode'." | 667 | "Indent rules supported by `php-ts-mode'." |
| 630 | (let ((common | 668 | (let ((common |
| 631 | `((php-ts-mode--else-heuristic prev-line php-ts-mode-indent-offset) | 669 | `(;; Handle indentation relatives to HTML. |
| 632 | 670 | ;; ((parent-is "program") php-ts-mode--parent-html-heuristic 0) | |
| 633 | ((query "(ERROR (ERROR)) @indent") column-0 0) | 671 | ;; ((parent-is "text_interpolation") php-ts-mode--parent-html-heuristic 0) |
| 634 | 672 | ((or (parent-is "program") | |
| 635 | ((node-is ")") parent-bol 0) | 673 | (parent-is "text_interpolation")) |
| 636 | ((node-is "]") parent-bol 0) | 674 | php-ts-mode--parent-html-heuristic 0) |
| 637 | ((node-is "else_clause") parent-bol 0) | 675 | |
| 638 | ((node-is "case_statement") parent-bol php-ts-mode-indent-offset) | 676 | (php-ts-mode--else-heuristic prev-line php-ts-mode-indent-offset) |
| 639 | ((node-is "default_statement") parent-bol php-ts-mode-indent-offset) | 677 | |
| 640 | ((parent-is "default_statement") parent-bol php-ts-mode-indent-offset) | 678 | ((query "(ERROR (ERROR)) @indent") parent-bol 0) |
| 641 | ((and | 679 | |
| 642 | (parent-is "expression_statement") | 680 | ((node-is ")") parent-bol 0) |
| 643 | (node-is ";")) | 681 | ((node-is "]") parent-bol 0) |
| 644 | parent-bol 0) | 682 | ((node-is "else_clause") parent-bol 0) |
| 645 | ((parent-is "expression_statement") parent-bol php-ts-mode-indent-offset) | 683 | ((node-is "case_statement") parent-bol php-ts-mode-indent-offset) |
| 646 | ;; `c-ts-common-looking-at-star' has to come before | 684 | ((node-is "default_statement") parent-bol php-ts-mode-indent-offset) |
| 647 | ;; `c-ts-common-comment-2nd-line-matcher'. | 685 | ((parent-is "default_statement") parent-bol php-ts-mode-indent-offset) |
| 648 | ((and (parent-is "comment") c-ts-common-looking-at-star) | 686 | ((and |
| 649 | c-ts-common-comment-start-after-first-star -1) | 687 | (parent-is "expression_statement") |
| 650 | (c-ts-common-comment-2nd-line-matcher | 688 | (node-is ";")) |
| 651 | c-ts-common-comment-2nd-line-anchor | 689 | parent-bol 0) |
| 652 | 1) | 690 | ((parent-is "expression_statement") parent-bol php-ts-mode-indent-offset) |
| 653 | ((parent-is "comment") prev-adaptive-prefix 0) | 691 | ;; `c-ts-common-looking-at-star' has to come before |
| 654 | 692 | ;; `c-ts-common-comment-2nd-line-matcher'. | |
| 655 | ((parent-is "method_declaration") parent-bol 0) | 693 | ((and (parent-is "comment") c-ts-common-looking-at-star) |
| 656 | ((node-is "class_interface_clause") parent-bol php-ts-mode-indent-offset) | 694 | c-ts-common-comment-start-after-first-star -1) |
| 657 | ((query "(class_interface_clause (name) @indent)") php-ts-mode--parent-eol 1) | 695 | (c-ts-common-comment-2nd-line-matcher |
| 658 | ((query "(class_interface_clause (qualified_name) @indent)") | 696 | c-ts-common-comment-2nd-line-anchor |
| 659 | parent-bol php-ts-mode-indent-offset) | 697 | 1) |
| 660 | ((parent-is "class_declaration") parent-bol 0) | 698 | ((parent-is "comment") prev-adaptive-prefix 0) |
| 699 | |||
| 700 | ((parent-is "method_declaration") parent-bol 0) | ||
| 701 | ((node-is "class_interface_clause") parent-bol php-ts-mode-indent-offset) | ||
| 702 | ((query "(class_interface_clause (name) @indent)") php-ts-mode--parent-eol 1) | ||
| 703 | ((query "(class_interface_clause (qualified_name) @indent)") | ||
| 704 | parent-bol php-ts-mode-indent-offset) | ||
| 705 | ((parent-is "class_declaration") parent-bol 0) | ||
| 661 | ((parent-is "namespace_use_declaration") parent-bol php-ts-mode-indent-offset) | 706 | ((parent-is "namespace_use_declaration") parent-bol php-ts-mode-indent-offset) |
| 662 | ((parent-is "namespace_use_group") parent-bol php-ts-mode-indent-offset) | 707 | ((node-is "namespace_use_clause") parent-bol php-ts-mode-indent-offset) |
| 663 | ((parent-is "function_definition") parent-bol 0) | 708 | ((or (parent-is "use_declaration") |
| 664 | ((parent-is "member_call_expression") first-sibling php-ts-mode-indent-offset) | 709 | (parent-is "use_list")) |
| 665 | ((parent-is "conditional_expression") parent-bol php-ts-mode-indent-offset) | 710 | parent-bol php-ts-mode-indent-offset) |
| 666 | ((parent-is "assignment_expression") parent-bol php-ts-mode-indent-offset) | 711 | ((parent-is "function_definition") parent-bol 0) |
| 667 | ((parent-is "array_creation_expression") parent-bol php-ts-mode-indent-offset) | 712 | ((parent-is "member_call_expression") first-sibling php-ts-mode-indent-offset) |
| 668 | ((parent-is "parenthesized_expression") first-sibling 1) | 713 | ((parent-is "conditional_expression") parent-bol php-ts-mode-indent-offset) |
| 669 | ((parent-is "binary_expression") parent 0) | 714 | ((parent-is "assignment_expression") parent-bol php-ts-mode-indent-offset) |
| 670 | ((or (parent-is "arguments") | 715 | ((parent-is "array_creation_expression") parent-bol php-ts-mode-indent-offset) |
| 671 | (parent-is "formal_parameters")) | 716 | ((parent-is "attribute_group") parent-bol php-ts-mode-indent-offset) |
| 672 | parent-bol php-ts-mode-indent-offset) | 717 | ((parent-is "parenthesized_expression") first-sibling 1) |
| 673 | 718 | ((parent-is "binary_expression") parent 0) | |
| 674 | ((query "(for_statement (assignment_expression left: (_)) @indent)") | 719 | ((or (parent-is "arguments") |
| 675 | parent-bol php-ts-mode-indent-offset) | 720 | (parent-is "formal_parameters")) |
| 676 | ((query "(for_statement (binary_expression left: (_)) @indent)") | 721 | parent-bol php-ts-mode-indent-offset) |
| 677 | parent-bol php-ts-mode-indent-offset) | 722 | |
| 678 | ((query "(for_statement (update_expression (_)) @indent)") | 723 | ((query "(for_statement (assignment_expression left: (_)) @indent)") |
| 679 | parent-bol php-ts-mode-indent-offset) | 724 | parent-bol php-ts-mode-indent-offset) |
| 680 | ((query "(function_call_expression arguments: (_) @indent)") | 725 | ((query "(for_statement (binary_expression left: (_)) @indent)") |
| 681 | parent php-ts-mode-indent-offset) | 726 | parent-bol php-ts-mode-indent-offset) |
| 682 | ((query "(member_call_expression arguments: (_) @indent)") | 727 | ((query "(for_statement (update_expression (_)) @indent)") |
| 683 | parent php-ts-mode-indent-offset) | 728 | parent-bol php-ts-mode-indent-offset) |
| 684 | ((query "(scoped_call_expression name: (_) @indent)") | 729 | ((query "(function_call_expression arguments: (_) @indent)") |
| 685 | parent php-ts-mode-indent-offset) | 730 | parent php-ts-mode-indent-offset) |
| 686 | ((parent-is "scoped_property_access_expression") | 731 | ((query "(member_call_expression arguments: (_) @indent)") |
| 687 | parent php-ts-mode-indent-offset) | 732 | parent php-ts-mode-indent-offset) |
| 688 | 733 | ((query "(scoped_call_expression name: (_) @indent)") | |
| 689 | ;; Closing bracket. Must stay here, the rule order matter. | 734 | parent php-ts-mode-indent-offset) |
| 690 | ((node-is "}") standalone-parent 0) | 735 | ((parent-is "scoped_property_access_expression") |
| 691 | ;; handle multiple single line comment that start at the and of a line | 736 | parent php-ts-mode-indent-offset) |
| 692 | ((match "comment" "declaration_list") php-ts-mode--anchor-prev-sibling 0) | 737 | |
| 693 | ((parent-is "declaration_list") column-0 php-ts-mode-indent-offset) | 738 | ;; Closing bracket. Must stay here, the rule order matter. |
| 694 | 739 | ((node-is "}") standalone-parent 0) | |
| 695 | ((parent-is "initializer_list") parent-bol php-ts-mode-indent-offset) | 740 | ;; handle multiple single line comment that start at the and of a line |
| 696 | 741 | ((match "comment" "declaration_list") php-ts-mode--anchor-prev-sibling 0) | |
| 697 | ;; Statement in {} blocks. | 742 | ((parent-is "declaration_list") column-0 php-ts-mode-indent-offset) |
| 698 | ((or (and (or (parent-is "compound_statement") | 743 | |
| 744 | ((parent-is "initializer_list") parent-bol php-ts-mode-indent-offset) | ||
| 745 | |||
| 746 | ;; Statement in {} blocks. | ||
| 747 | ((or (and (or (parent-is "compound_statement") | ||
| 699 | (parent-is "colon_block")) | 748 | (parent-is "colon_block")) |
| 700 | ;; If the previous sibling(s) are not on their | 749 | ;; If the previous sibling(s) are not on their |
| 701 | ;; own line, indent as if this node is the first | 750 | ;; own line, indent as if this node is the first |
| 702 | ;; sibling | 751 | ;; sibling |
| 703 | php-ts-mode--first-sibling) | 752 | php-ts-mode--first-sibling) |
| 704 | (or (match null "compound_statement") | 753 | (or (match null "compound_statement") |
| 705 | (match null "colon_block"))) | 754 | (match null "colon_block"))) |
| 706 | standalone-parent php-ts-mode-indent-offset) | 755 | standalone-parent php-ts-mode-indent-offset) |
| 707 | ((or (parent-is "compound_statement") | 756 | ((or (parent-is "compound_statement") |
| 708 | (parent-is "colon_block")) | 757 | (parent-is "colon_block")) |
| 709 | parent-bol php-ts-mode-indent-offset) | 758 | parent-bol php-ts-mode-indent-offset) |
| 710 | ;; Opening bracket. | 759 | ;; Opening bracket. |
| 711 | ((or (node-is "compound_statement") | 760 | ((or (node-is "compound_statement") |
| 712 | (node-is "colon_block")) | 761 | (node-is "colon_block")) |
| 713 | standalone-parent php-ts-mode-indent-offset) | 762 | standalone-parent php-ts-mode-indent-offset) |
| 714 | 763 | ||
| 715 | ((parent-is "match_block") parent-bol php-ts-mode-indent-offset) | 764 | ((parent-is "match_block") parent-bol php-ts-mode-indent-offset) |
| 716 | ((parent-is "switch_block") parent-bol 0) | 765 | ((parent-is "switch_block") parent-bol 0) |
| 717 | 766 | ||
| 718 | ;; These rules are for cases where the body is bracketless. | 767 | ;; These rules are for cases where the body is bracketless. |
| 719 | ((match "while" "do_statement") parent-bol 0) | 768 | ((match "while" "do_statement") parent-bol 0) |
| 720 | ;; rule for PHP alternative syntax | 769 | ;; rule for PHP alternative syntax |
| 721 | ((or (node-is "else_if_clause") | 770 | ((or (node-is "else_if_clause") |
| 722 | (node-is "endif") | 771 | (node-is "endif") |
| 723 | (node-is "endfor") | 772 | (node-is "endfor") |
| 724 | (node-is "endforeach") | 773 | (node-is "endforeach") |
| 725 | (node-is "endwhile")) | 774 | (node-is "endwhile")) |
| 726 | parent-bol 0) | 775 | parent-bol 0) |
| 727 | ((or (parent-is "if_statement") | 776 | ((or (parent-is "if_statement") |
| 728 | (parent-is "else_clause") | 777 | (parent-is "else_clause") |
| 729 | (parent-is "for_statement") | 778 | (parent-is "for_statement") |
| 730 | (parent-is "foreach_statement") | 779 | (parent-is "foreach_statement") |
| 731 | (parent-is "while_statement") | 780 | (parent-is "while_statement") |
| 732 | (parent-is "do_statement") | 781 | (parent-is "do_statement") |
| 733 | (parent-is "switch_statement") | 782 | (parent-is "switch_statement") |
| 734 | (parent-is "case_statement") | 783 | (parent-is "case_statement") |
| 735 | (parent-is "empty_statement")) | 784 | (parent-is "empty_statement")) |
| 736 | parent-bol php-ts-mode-indent-offset) | 785 | parent-bol php-ts-mode-indent-offset) |
| 786 | |||
| 787 | ;; Do not touch the indentation inside a multiline the strings. | ||
| 788 | ((parent-is "string_content") no-indent 0) | ||
| 737 | 789 | ||
| 738 | ;; Workaround: handle "for" open statement group. Currently | 790 | ;; Workaround: handle "for" open statement group. Currently |
| 739 | ;; the grammar handles it differently than other control structures. | 791 | ;; the grammar handles it differently than other control structures. |
| 740 | (no-node php-ts-mode--open-statement-group-heuristic 0)))) | 792 | (no-node prev-sibling 0)))) |
| 741 | `((psr2 | 793 | `((psr2 |
| 742 | ((parent-is "program") php-ts-mode--open-statement-group-heuristic 0) | ||
| 743 | ((parent-is "text_interpolation") column-0 0) | ||
| 744 | ((parent-is "function_call_expression") parent-bol php-ts-mode-indent-offset) | 794 | ((parent-is "function_call_expression") parent-bol php-ts-mode-indent-offset) |
| 745 | ,@common) | 795 | ,@common) |
| 746 | (pear | 796 | (pear |
| 747 | ((parent-is "program") php-ts-mode--parent-html-heuristic 0) | ||
| 748 | ((parent-is "text_interpolation") php-ts-mode--parent-html-heuristic 0) | ||
| 749 | ((or (node-is "case_statement") | 797 | ((or (node-is "case_statement") |
| 750 | (node-is "default_statement")) | 798 | (node-is "default_statement")) |
| 751 | parent-bol 0) | 799 | parent-bol 0) |
| 752 | ((parent-is "binary_expression") parent-bol php-ts-mode-indent-offset) | 800 | ((parent-is "binary_expression") parent-bol php-ts-mode-indent-offset) |
| 753 | ,@common) | 801 | ,@common) |
| 754 | (drupal | 802 | (drupal |
| 755 | ((parent-is "program") php-ts-mode--parent-html-heuristic 0) | ||
| 756 | ((parent-is "text_interpolation") php-ts-mode--parent-html-bol 0) | ||
| 757 | ((parent-is "if_statement") parent-bol 0) | 803 | ((parent-is "if_statement") parent-bol 0) |
| 758 | ((parent-is "binary_expression") parent-bol php-ts-mode-indent-offset) | 804 | ((parent-is "binary_expression") parent-bol php-ts-mode-indent-offset) |
| 759 | ((parent-is "function_call_expression") parent-bol php-ts-mode-indent-offset) | 805 | ((parent-is "function_call_expression") parent-bol php-ts-mode-indent-offset) |
| @@ -762,8 +808,6 @@ characters of the current line." | |||
| 762 | ((parent-is "function_call_expression") parent-bol php-ts-mode-indent-offset) | 808 | ((parent-is "function_call_expression") parent-bol php-ts-mode-indent-offset) |
| 763 | ,@common) | 809 | ,@common) |
| 764 | (wordpress | 810 | (wordpress |
| 765 | ((parent-is "program") php-ts-mode--parent-html-bol 0) | ||
| 766 | ((parent-is "text_interpolation") php-ts-mode--parent-html-bol 0) | ||
| 767 | ,@common) | 811 | ,@common) |
| 768 | (zend | 812 | (zend |
| 769 | ((parent-is "class_interface_clause") php-ts-mode--anchor-first-sibling 0) | 813 | ((parent-is "class_interface_clause") php-ts-mode--anchor-first-sibling 0) |
| @@ -838,6 +882,14 @@ characters of the current line." | |||
| 838 | "__toString" "__invoke" "__set_state" "__clone" "__debugInfo") | 882 | "__toString" "__invoke" "__set_state" "__clone" "__debugInfo") |
| 839 | "PHP predefined magic methods.") | 883 | "PHP predefined magic methods.") |
| 840 | 884 | ||
| 885 | (defconst php-ts-mode--prettify-symbols-alist | ||
| 886 | '(("<=" . ?≤) | ||
| 887 | (">=" . ?≥) | ||
| 888 | ("->" . ?→) | ||
| 889 | ("=>" . ?⇒) | ||
| 890 | ("::" . ?∷)) | ||
| 891 | "Value for `prettify-symbols-alist' in `php-ts-mode'.") | ||
| 892 | |||
| 841 | (defun php-ts-mode--test-namespace-name-as-prefix-p () | 893 | (defun php-ts-mode--test-namespace-name-as-prefix-p () |
| 842 | "Return t if namespace_name_as_prefix is a named node, nil otherwise." | 894 | "Return t if namespace_name_as_prefix is a named node, nil otherwise." |
| 843 | (treesit-query-valid-p 'php "(namespace_name_as_prefix)")) | 895 | (treesit-query-valid-p 'php "(namespace_name_as_prefix)")) |
| @@ -850,14 +902,18 @@ characters of the current line." | |||
| 850 | "Return t if namespace_use_group_clause is a named node, nil otherwise." | 902 | "Return t if namespace_use_group_clause is a named node, nil otherwise." |
| 851 | (treesit-query-valid-p 'php "(namespace_use_group_clause)")) | 903 | (treesit-query-valid-p 'php "(namespace_use_group_clause)")) |
| 852 | 904 | ||
| 853 | (defun php-ts-mode--test-visibility-modifier-operation-clause-p () | 905 | (defun php-ts-mode--test-visibility-modifier-operation-p () |
| 854 | "Return t if (visibility_modifier (operation)) is defined, nil otherwise." | 906 | "Return t if (visibility_modifier (operation)) is defined, nil otherwise." |
| 855 | (treesit-query-valid-p 'php "(visibility_modifier (operation))")) | 907 | (treesit-query-valid-p 'php "(visibility_modifier (operation))")) |
| 856 | 908 | ||
| 857 | (defun php-ts-mode--test-property-hook-clause-p () | 909 | (defun php-ts-mode--test-property-hook-p () |
| 858 | "Return t if property_hook is a named node, nil otherwise." | 910 | "Return t if property_hook is a named node, nil otherwise." |
| 859 | (treesit-query-valid-p 'php "(property_hook)")) | 911 | (treesit-query-valid-p 'php "(property_hook)")) |
| 860 | 912 | ||
| 913 | (defun php-ts-mode--test-relative-name-p () | ||
| 914 | "Return t if relative_name is a named node, nil otherwise." | ||
| 915 | (treesit-query-valid-p 'php "(relative_name)")) | ||
| 916 | |||
| 861 | (defun php-ts-mode--font-lock-settings () | 917 | (defun php-ts-mode--font-lock-settings () |
| 862 | "Tree-sitter font-lock settings." | 918 | "Tree-sitter font-lock settings." |
| 863 | (treesit-font-lock-rules | 919 | (treesit-font-lock-rules |
| @@ -866,7 +922,7 @@ characters of the current line." | |||
| 866 | :feature 'keyword | 922 | :feature 'keyword |
| 867 | :override t | 923 | :override t |
| 868 | `([,@php-ts-mode--keywords] @font-lock-keyword-face | 924 | `([,@php-ts-mode--keywords] @font-lock-keyword-face |
| 869 | ,@(when (php-ts-mode--test-visibility-modifier-operation-clause-p) | 925 | ,@(when (php-ts-mode--test-visibility-modifier-operation-p) |
| 870 | '((visibility_modifier (operation) @font-lock-builtin-face))) | 926 | '((visibility_modifier (operation) @font-lock-builtin-face))) |
| 871 | (var_modifier) @font-lock-builtin-face) | 927 | (var_modifier) @font-lock-builtin-face) |
| 872 | 928 | ||
| @@ -882,8 +938,8 @@ characters of the current line." | |||
| 882 | ;; predefined constant or built in constant (part of PHP core) | 938 | ;; predefined constant or built in constant (part of PHP core) |
| 883 | ((name) @font-lock-builtin-face | 939 | ((name) @font-lock-builtin-face |
| 884 | (:match ,(rx-to-string | 940 | (:match ,(rx-to-string |
| 885 | `(: bos (or ,@php-ts-mode--predefined-constant) eos)) | 941 | `(: bos (or ,@php-ts-mode--predefined-constant) eos)) |
| 886 | @font-lock-builtin-face)) | 942 | @font-lock-builtin-face)) |
| 887 | ;; user defined constant | 943 | ;; user defined constant |
| 888 | ((name) @font-lock-constant-face | 944 | ((name) @font-lock-constant-face |
| 889 | (:match "\\`_*[A-Z][0-9A-Z_]+\\'" @font-lock-constant-face)) | 945 | (:match "\\`_*[A-Z][0-9A-Z_]+\\'" @font-lock-constant-face)) |
| @@ -917,7 +973,8 @@ characters of the current line." | |||
| 917 | (member_access_expression | 973 | (member_access_expression |
| 918 | name: (_) @font-lock-variable-name-face) | 974 | name: (_) @font-lock-variable-name-face) |
| 919 | (scoped_property_access_expression | 975 | (scoped_property_access_expression |
| 920 | scope: (name) @font-lock-constant-face)) | 976 | scope: (name) @font-lock-constant-face) |
| 977 | (error_suppression_expression (name) @font-lock-property-name-face)) | ||
| 921 | 978 | ||
| 922 | :language 'php | 979 | :language 'php |
| 923 | :feature 'string | 980 | :feature 'string |
| @@ -966,28 +1023,28 @@ characters of the current line." | |||
| 966 | name: (_) @font-lock-type-face) | 1023 | name: (_) @font-lock-type-face) |
| 967 | (function_definition | 1024 | (function_definition |
| 968 | name: (_) @font-lock-function-name-face) | 1025 | name: (_) @font-lock-function-name-face) |
| 969 | ,@(when (php-ts-mode--test-property-hook-clause-p) | 1026 | ,@(when (php-ts-mode--test-property-hook-p) |
| 970 | '((property_hook (name) @font-lock-function-name-face))) | 1027 | '((property_hook (name) @font-lock-function-name-face))) |
| 971 | (method_declaration | 1028 | (method_declaration |
| 972 | name: (_) @font-lock-function-name-face) | 1029 | name: (_) @font-lock-function-name-face) |
| 973 | (method_declaration | 1030 | (method_declaration |
| 974 | name: (name) @font-lock-builtin-face | 1031 | name: (name) @font-lock-builtin-face |
| 975 | (:match ,(rx-to-string | 1032 | (:match ,(rx-to-string |
| 976 | `(: bos (or ,@php-ts-mode--class-magic-methods) eos)) | 1033 | `(: bos (or ,@php-ts-mode--class-magic-methods) eos)) |
| 977 | @font-lock-builtin-face)) | 1034 | @font-lock-builtin-face)) |
| 978 | ("=>") @font-lock-keyword-face | 1035 | ("=>") @font-lock-keyword-face |
| 979 | (object_creation_expression | 1036 | (object_creation_expression |
| 980 | (name) @font-lock-type-face) | 1037 | (name) @font-lock-type-face) |
| 981 | ,@(when (php-ts-mode--test-namespace-name-as-prefix-p) | 1038 | ,@(when (php-ts-mode--test-namespace-name-as-prefix-p) |
| 982 | '((namespace_name_as_prefix "\\" @font-lock-delimiter-face) | 1039 | '((namespace_name_as_prefix "\\" @font-lock-delimiter-face) |
| 983 | (namespace_name_as_prefix | 1040 | (namespace_name_as_prefix |
| 984 | (namespace_name (name)) @font-lock-type-face))) | 1041 | (namespace_name (name)) @font-lock-type-face))) |
| 985 | ,@(if (php-ts-mode--test-namespace-aliasing-clause-p) | 1042 | ,@(if (php-ts-mode--test-namespace-aliasing-clause-p) |
| 986 | '((namespace_aliasing_clause (name) @font-lock-type-face)) | 1043 | '((namespace_aliasing_clause (name) @font-lock-type-face)) |
| 987 | '((namespace_use_clause alias: (name) @font-lock-type-face))) | 1044 | '((namespace_use_clause alias: (name) @font-lock-type-face))) |
| 988 | ,@(when (not (php-ts-mode--test-namespace-use-group-clause-p)) | 1045 | ,@(when (not (php-ts-mode--test-namespace-use-group-clause-p)) |
| 989 | '((namespace_use_group | 1046 | '((namespace_use_group |
| 990 | (namespace_use_clause (name) @font-lock-type-face)))) | 1047 | (namespace_use_clause (name) @font-lock-type-face)))) |
| 991 | (namespace_use_clause (name) @font-lock-type-face) | 1048 | (namespace_use_clause (name) @font-lock-type-face) |
| 992 | (namespace_name "\\" @font-lock-delimiter-face) | 1049 | (namespace_name "\\" @font-lock-delimiter-face) |
| 993 | (namespace_name (name) @font-lock-type-face) | 1050 | (namespace_name (name) @font-lock-type-face) |
| @@ -1035,7 +1092,9 @@ characters of the current line." | |||
| 1035 | (use_as_clause (name) @font-lock-property-use-face) | 1092 | (use_as_clause (name) @font-lock-property-use-face) |
| 1036 | ,@(when (not (php-ts-mode--test-namespace-name-as-prefix-p)) | 1093 | ,@(when (not (php-ts-mode--test-namespace-name-as-prefix-p)) |
| 1037 | '((qualified_name prefix: "\\" @font-lock-delimiter-face))) | 1094 | '((qualified_name prefix: "\\" @font-lock-delimiter-face))) |
| 1038 | (qualified_name (name) @font-lock-constant-face)) | 1095 | (qualified_name (name) @font-lock-constant-face) |
| 1096 | ,@(when (php-ts-mode--test-relative-name-p) | ||
| 1097 | '((relative_name (name) @font-lock-constant-face)))) | ||
| 1039 | 1098 | ||
| 1040 | :language 'php | 1099 | :language 'php |
| 1041 | :feature 'property | 1100 | :feature 'property |
| @@ -1061,35 +1120,17 @@ characters of the current line." | |||
| 1061 | ;;; Font-lock helpers | 1120 | ;;; Font-lock helpers |
| 1062 | 1121 | ||
| 1063 | (defconst php-ts-mode--custom-html-font-lock-settings | 1122 | (defconst php-ts-mode--custom-html-font-lock-settings |
| 1064 | (treesit-font-lock-rules | 1123 | (treesit-replace-font-lock-feature-settings |
| 1065 | :language 'html | 1124 | (treesit-font-lock-rules |
| 1066 | :override t | 1125 | :language 'html |
| 1067 | :feature 'comment | 1126 | :override t |
| 1068 | `((comment) @font-lock-comment-face | 1127 | :feature 'comment |
| 1069 | ;; handle shebang path and others type of comment | 1128 | '((comment) @font-lock-comment-face |
| 1070 | (document (text) @font-lock-comment-face)) | 1129 | ;; handle shebang path and others type of comment |
| 1071 | 1130 | (document (text) @font-lock-comment-face))) | |
| 1072 | :language 'html | 1131 | mhtml-ts-mode--treesit-font-lock-settings) |
| 1073 | :override t | ||
| 1074 | :feature 'keyword | ||
| 1075 | `("doctype" @font-lock-keyword-face) | ||
| 1076 | |||
| 1077 | :language 'html | ||
| 1078 | :override t | ||
| 1079 | :feature 'definition | ||
| 1080 | `((tag_name) @font-lock-function-name-face) | ||
| 1081 | |||
| 1082 | :language 'html | ||
| 1083 | :override 'append | ||
| 1084 | :feature 'string | ||
| 1085 | `((quoted_attribute_value) @font-lock-string-face) | ||
| 1086 | |||
| 1087 | :language 'html | ||
| 1088 | :override t | ||
| 1089 | :feature 'property | ||
| 1090 | `((attribute_name) @font-lock-variable-name-face)) | ||
| 1091 | "Tree-sitter Font-lock settings for HTML when embedded in PHP. | 1132 | "Tree-sitter Font-lock settings for HTML when embedded in PHP. |
| 1092 | Like `html-ts-mode--font-lock-settings' but adapted for `php-ts-mode'.") | 1133 | Like `mhtml-ts-mode--font-lock-settings' but adapted for `php-ts-mode'.") |
| 1093 | 1134 | ||
| 1094 | (defvar php-ts-mode--phpdoc-font-lock-settings | 1135 | (defvar php-ts-mode--phpdoc-font-lock-settings |
| 1095 | (treesit-font-lock-rules | 1136 | (treesit-font-lock-rules |
| @@ -1102,8 +1143,9 @@ Like `html-ts-mode--font-lock-settings' but adapted for `php-ts-mode'.") | |||
| 1102 | :feature 'type | 1143 | :feature 'type |
| 1103 | :override t | 1144 | :override t |
| 1104 | '((union_type | 1145 | '((union_type |
| 1105 | [(array_type) (primitive_type) (named_type) (optional_type)] @font-lock-type-face) | 1146 | [(primitive_type) (named_type) (optional_type)] @font-lock-type-face) |
| 1106 | ([(array_type) (primitive_type) (named_type) (optional_type)] @font-lock-type-face) | 1147 | (array_type ["array" "list"] @font-lock-keyword-face) |
| 1148 | ([(primitive_type) (named_type) (optional_type)] @font-lock-type-face) | ||
| 1107 | (fqsen (name) @font-lock-function-name-face)) | 1149 | (fqsen (name) @font-lock-function-name-face)) |
| 1108 | 1150 | ||
| 1109 | :language 'phpdoc | 1151 | :language 'phpdoc |
| @@ -1118,27 +1160,13 @@ Like `html-ts-mode--font-lock-settings' but adapted for `php-ts-mode'.") | |||
| 1118 | :language 'phpdoc | 1160 | :language 'phpdoc |
| 1119 | :feature 'variable | 1161 | :feature 'variable |
| 1120 | :override t | 1162 | :override t |
| 1121 | '((variable_name (name) @font-lock-variable-name-face))) | 1163 | '((variable_name (name) @font-lock-variable-name-face)) |
| 1122 | "Tree-sitter font-lock settings for phpdoc.") | ||
| 1123 | 1164 | ||
| 1124 | (defun php-ts-mode--colorize-css-value (node override start end &rest _) | 1165 | :language 'phpdoc |
| 1125 | "Colorize CSS property value like `css--fontify-region'. | 1166 | :feature 'phpdoc-error |
| 1126 | For NODE, OVERRIDE, START, and END, see `treesit-font-lock-rules'." | 1167 | :override t |
| 1127 | (if (and php-ts-mode-css-fontify-colors | 1168 | '((ERROR) @php-ts-mode--phpdoc-fontify-error)) |
| 1128 | (string-equal "plain_value" (treesit-node-type node))) | 1169 | "Tree-sitter font-lock settings for phpdoc.") |
| 1129 | (let ((color (css--compute-color start (treesit-node-text node t)))) | ||
| 1130 | (when color | ||
| 1131 | (with-silent-modifications | ||
| 1132 | (add-text-properties | ||
| 1133 | (treesit-node-start node) (treesit-node-end node) | ||
| 1134 | (list 'face (list :background color | ||
| 1135 | :foreground (readable-foreground-color | ||
| 1136 | color) | ||
| 1137 | :box '(:line-width -1))))))) | ||
| 1138 | (treesit-fontify-with-override | ||
| 1139 | (treesit-node-start node) (treesit-node-end node) | ||
| 1140 | 'font-lock-variable-name-face | ||
| 1141 | override start end))) | ||
| 1142 | 1170 | ||
| 1143 | (defun php-ts-mode--fontify-error (node override start end &rest _) | 1171 | (defun php-ts-mode--fontify-error (node override start end &rest _) |
| 1144 | "Fontify the error nodes. | 1172 | "Fontify the error nodes. |
| @@ -1148,6 +1176,13 @@ For NODE, OVERRIDE, START, and END, see `treesit-font-lock-rules'." | |||
| 1148 | 'font-lock-warning-face | 1176 | 'font-lock-warning-face |
| 1149 | override start end)) | 1177 | override start end)) |
| 1150 | 1178 | ||
| 1179 | (defun php-ts-mode--phpdoc-fontify-error (node override start end &rest _) | ||
| 1180 | "Fontify the phpdoc error nodes. | ||
| 1181 | Most of the error are only tag non handled by the phpdoc parser. | ||
| 1182 | For NODE, OVERRIDE, START, and END, see `treesit-font-lock-rules'." | ||
| 1183 | (when php-ts-mode-phpdoc-highlight-errors | ||
| 1184 | (php-ts-mode--fontify-error node override start end))) | ||
| 1185 | |||
| 1151 | 1186 | ||
| 1152 | ;;; Imenu | 1187 | ;;; Imenu |
| 1153 | 1188 | ||
| @@ -1157,92 +1192,106 @@ For NODE, OVERRIDE, START, and END, see `treesit-font-lock-rules'." | |||
| 1157 | node | 1192 | node |
| 1158 | (lambda (n) | 1193 | (lambda (n) |
| 1159 | (member (treesit-node-type n) | 1194 | (member (treesit-node-type n) |
| 1160 | '("class_declaration" | 1195 | '("class_declaration" |
| 1161 | "enum_declaration" | 1196 | "enum_declaration" |
| 1162 | "function_definition" | 1197 | "function_definition" |
| 1163 | "interface_declaration" | 1198 | "interface_declaration" |
| 1164 | "method_declaration" | 1199 | "method_declaration" |
| 1165 | "namespace_definition" | 1200 | "namespace_definition" |
| 1166 | "trait_declaration"))))) | 1201 | "trait_declaration"))))) |
| 1167 | 1202 | ||
| 1168 | (defun php-ts-mode--defun-name-separator (node) | 1203 | (defun php-ts-mode--defun-name-separator (node) |
| 1169 | "Return a separator to connect object name, based on NODE type." | 1204 | "Return a separator to connect object name, based on NODE type." |
| 1170 | (let ((node-type (treesit-node-type node))) | 1205 | (let ((node-type (treesit-node-type node))) |
| 1171 | (cond ((member node-type '("function_definition" "method_declaration")) | 1206 | (cond ((member node-type '("function_definition" "method_declaration")) |
| 1172 | "()::") | 1207 | "()::") |
| 1173 | ((member node-type '("class_declaration" "enum_declaration" "trait_declaration")) | 1208 | ((member node-type '("class_declaration" "enum_declaration" "trait_declaration")) |
| 1174 | "::") | 1209 | "::") |
| 1175 | (t "\\")))) | 1210 | (t "\\")))) |
| 1176 | 1211 | ||
| 1177 | (defun php-ts-mode--defun-object-name (node node-text) | 1212 | (defun php-ts-mode--defun-object-name (node node-text) |
| 1178 | "Compose the full name of a NODE that is a PHP variable, method, class etc. | 1213 | "Compose the full name of a NODE that is a PHP variable, method, class etc. |
| 1179 | If the NODE has a parent, it recursively concat the parent names with NODE-TEXT, | 1214 | If the NODE has a parent, it recursively concat the parent names with NODE-TEXT, |
| 1180 | otherwise it returns NODE-TEXT." | 1215 | otherwise it returns NODE-TEXT." |
| 1181 | (let* ((parent-node (php-ts-mode--parent-object node)) | 1216 | (let* ((parent-node (php-ts-mode--parent-object node)) |
| 1182 | (parent-node-text | 1217 | (parent-node-text |
| 1183 | (treesit-node-text | 1218 | (treesit-node-text |
| 1184 | (treesit-node-child-by-field-name parent-node "name") t)) | 1219 | (treesit-node-child-by-field-name parent-node "name") t)) |
| 1185 | (parent-node-separator (php-ts-mode--defun-name-separator parent-node))) | 1220 | (parent-node-separator (php-ts-mode--defun-name-separator parent-node))) |
| 1186 | (if parent-node | 1221 | (if parent-node |
| 1187 | (progn | 1222 | (progn |
| 1188 | (setq parent-node-text | 1223 | (setq parent-node-text |
| 1189 | (php-ts-mode--defun-object-name | 1224 | (php-ts-mode--defun-object-name |
| 1190 | parent-node | 1225 | parent-node |
| 1191 | parent-node-text)) | 1226 | parent-node-text)) |
| 1192 | (concat parent-node-text parent-node-separator node-text)) | 1227 | (concat parent-node-text parent-node-separator node-text)) |
| 1193 | node-text))) | 1228 | node-text))) |
| 1194 | 1229 | ||
| 1195 | (defun php-ts-mode--defun-name (node) | 1230 | (defun php-ts-mode--defun-name (node) |
| 1196 | "Return the defun name of NODE. | 1231 | "Return the defun name of NODE. |
| 1197 | Return nil if the NODE has no field “name” or if NODE is not a defun node." | 1232 | Return nil if the NODE has no field “name” or if NODE is not a defun node." |
| 1198 | (let ((child (treesit-node-child-by-field-name node "name"))) | 1233 | (let ((lang (treesit-node-language node)) |
| 1199 | (cl-case (intern (treesit-node-type node)) | 1234 | (child (treesit-node-child-by-field-name node "name"))) |
| 1200 | (class_declaration (treesit-node-text child t)) | 1235 | (if (eq lang 'php) |
| 1201 | (trait_declaration (treesit-node-text child t)) | 1236 | (cl-case (intern (treesit-node-type node)) |
| 1202 | (interface_declaration (treesit-node-text child t)) | 1237 | (class_declaration (treesit-node-text child t)) |
| 1203 | (namespace_definition (treesit-node-text child t)) | 1238 | (trait_declaration (treesit-node-text child t)) |
| 1204 | (enum_declaration (treesit-node-text child t)) | 1239 | (interface_declaration (treesit-node-text child t)) |
| 1205 | (function_definition (treesit-node-text child t)) | 1240 | (namespace_definition (treesit-node-text child t)) |
| 1206 | (method_declaration | 1241 | (enum_declaration (treesit-node-text child t)) |
| 1207 | (php-ts-mode--defun-object-name node (treesit-node-text child t))) | 1242 | (function_definition (treesit-node-text child t)) |
| 1208 | (variable_name | 1243 | (method_declaration |
| 1209 | (php-ts-mode--defun-object-name node (treesit-node-text node t))) | 1244 | (php-ts-mode--defun-object-name node (treesit-node-text child t))) |
| 1210 | (const_element | 1245 | (variable_name |
| 1211 | (php-ts-mode--defun-object-name | 1246 | (php-ts-mode--defun-object-name node (treesit-node-text node t))) |
| 1212 | node | 1247 | (const_element |
| 1213 | (treesit-node-text (treesit-node-child node 0) t)))))) | 1248 | (php-ts-mode--defun-object-name |
| 1249 | node | ||
| 1250 | (treesit-node-text (treesit-node-child node 0) t)))) | ||
| 1251 | (mhtml-ts-mode--defun-name node)))) | ||
| 1214 | 1252 | ||
| 1215 | 1253 | ||
| 1216 | ;;; Defun navigation | 1254 | ;;; Defun navigation |
| 1217 | 1255 | ||
| 1256 | (defvar php-ts-mode--treesit-defun-type-regexp | ||
| 1257 | (rx bos (or "class_declaration" | ||
| 1258 | "enum_declaration" | ||
| 1259 | "function_definition" | ||
| 1260 | "interface_declaration" | ||
| 1261 | "method_declaration" | ||
| 1262 | "namespace_definition" | ||
| 1263 | "trait_declaration") | ||
| 1264 | eos) | ||
| 1265 | "Settings for `treesit-defun-type-regexp'.") | ||
| 1266 | |||
| 1218 | (defun php-ts-mode--indent-defun () | 1267 | (defun php-ts-mode--indent-defun () |
| 1219 | "Indent the current top-level declaration syntactically. | 1268 | "Indent the current top-level declaration syntactically. |
| 1220 | `treesit-defun-type-regexp' defines what constructs to indent." | 1269 | `treesit-defun-type-regexp' defines what constructs to indent." |
| 1221 | (interactive "*") | 1270 | (interactive "*") |
| 1222 | (when-let* ((orig-point (point-marker)) | 1271 | (when-let* ((orig-point (point-marker)) |
| 1223 | (node (treesit-defun-at-point))) | 1272 | (node (treesit-defun-at-point))) |
| 1224 | (indent-region (treesit-node-start node) | 1273 | (indent-region (treesit-node-start node) |
| 1225 | (treesit-node-end node)) | 1274 | (treesit-node-end node)) |
| 1226 | (goto-char orig-point))) | 1275 | (goto-char orig-point))) |
| 1227 | 1276 | ||
| 1228 | (defun php-ts-mode--defun-valid-p (node) | 1277 | (defun php-ts-mode--defun-valid-p (node) |
| 1229 | "Return non-nil if NODE is a valid defun node. | 1278 | "Return non-nil if NODE is a valid defun node. |
| 1230 | Ie, NODE is not nested." | 1279 | Ie, NODE is not nested." |
| 1231 | (not (and (member (treesit-node-type node) | 1280 | (not (and (member (treesit-node-type node) |
| 1232 | '("variable_name" | 1281 | '("variable_name" |
| 1233 | "const_element" | 1282 | "const_element" |
| 1234 | "enum_declaration" | 1283 | "enum_declaration" |
| 1235 | "union_declaration" | 1284 | "union_declaration" |
| 1236 | "declaration")) | 1285 | "declaration")) |
| 1237 | ;; If NODE's type is one of the above, make sure it is | 1286 | ;; If NODE's type is one of the above, make sure it is |
| 1238 | ;; top-level. | 1287 | ;; top-level. |
| 1239 | (treesit-node-top-level | 1288 | (treesit-node-top-level |
| 1240 | node (rx (or "variable_name" | 1289 | node (rx (or "variable_name" |
| 1241 | "const_element" | 1290 | "const_element" |
| 1242 | "function_definition" | 1291 | "function_definition" |
| 1243 | "enum_declaration" | 1292 | "enum_declaration" |
| 1244 | "union_declaration" | 1293 | "union_declaration" |
| 1245 | "declaration")))))) | 1294 | "declaration")))))) |
| 1246 | 1295 | ||
| 1247 | 1296 | ||
| 1248 | ;;; Filling | 1297 | ;;; Filling |
| @@ -1253,39 +1302,63 @@ Like `c-ts-common-comment-indent-new-line', but handle the | |||
| 1253 | less common PHP-style # comment. SOFT works the same as in | 1302 | less common PHP-style # comment. SOFT works the same as in |
| 1254 | `comment-indent-new-line'." | 1303 | `comment-indent-new-line'." |
| 1255 | (if (save-excursion | 1304 | (if (save-excursion |
| 1256 | ;; Line start with # or ## or ###... | 1305 | ;; Line start with # or ## or ###... |
| 1257 | (beginning-of-line) | 1306 | (beginning-of-line) |
| 1258 | (re-search-forward | 1307 | (re-search-forward |
| 1259 | (rx "#" (group (* (any "#")) (* " "))) | 1308 | (rx "#" (group (* (any "#")) (* " "))) |
| 1260 | (line-end-position) | 1309 | (line-end-position) |
| 1261 | t nil)) | 1310 | t nil)) |
| 1262 | (let ((offset (- (match-beginning 0) (line-beginning-position))) | 1311 | (let ((offset (- (match-beginning 0) (line-beginning-position))) |
| 1263 | (comment-prefix (match-string 0)) | 1312 | (comment-prefix (match-string 0)) |
| 1264 | (insert-line-break | 1313 | (insert-line-break |
| 1265 | (lambda () | 1314 | (lambda () |
| 1266 | (delete-horizontal-space) | 1315 | (delete-horizontal-space) |
| 1267 | (if soft | 1316 | (if soft |
| 1268 | (insert-and-inherit ?\n) | 1317 | (insert-and-inherit ?\n) |
| 1269 | (newline 1))))) | 1318 | (newline 1))))) |
| 1270 | (funcall insert-line-break) | 1319 | (funcall insert-line-break) |
| 1271 | (delete-region (line-beginning-position) (point)) | 1320 | (delete-region (line-beginning-position) (point)) |
| 1272 | (insert | 1321 | (insert |
| 1273 | (make-string offset ?\s) | 1322 | (make-string offset ?\s) |
| 1274 | comment-prefix)) | 1323 | comment-prefix)) |
| 1275 | ;; other style of comments | 1324 | ;; other style of comments |
| 1276 | (c-ts-common-comment-indent-new-line soft))) | 1325 | (c-ts-common-comment-indent-new-line soft))) |
| 1277 | 1326 | ||
| 1278 | (defun php-ts-mode-comment-setup () | 1327 | (defvar-local php-ts-mode--comment-current-plist |
| 1279 | "Set up local variables for PHP comment. | 1328 | '(:php nil :comment-start "// " :comment-end "") |
| 1280 | Depends on `c-ts-common-comment-setup'." | 1329 | "Store the current state of PHP comment configuration. |
| 1281 | (c-ts-common-comment-setup) | 1330 | `mhtml-ts-mode' changes the comment configuration when switching |
| 1282 | (setq-local c-ts-common--comment-regexp "comment" | 1331 | between HTML, Css and Javascript, so we have to do the same when |
| 1283 | comment-line-break-function #'php-ts-mode--comment-indent-new-line | 1332 | switching back to PHP. |
| 1284 | comment-style 'extra-line | 1333 | The prop :php must be t if we are in a PHP or PHPDOC range.") |
| 1285 | comment-start-skip (rx (or (seq "#" (not (any "["))) | 1334 | |
| 1286 | (seq "/" (+ "/")) | 1335 | (defun php-ts-mode--comment-setup (&optional force) |
| 1287 | (seq "/" (+ "*"))) | 1336 | "Set up local variables for comments. |
| 1288 | (* (syntax whitespace))))) | 1337 | If FORCE is t setup comment for PHP. Depends on |
| 1338 | `mhtml-ts-mode--comment-setup' and | ||
| 1339 | `mhtml-ts-mode--comment-current-lang'." | ||
| 1340 | (let ((lang (treesit-language-at (point)))) | ||
| 1341 | (if (and (or (eq lang 'php) (eq lang 'phpdoc) force) | ||
| 1342 | (eq (plist-get php-ts-mode--comment-current-plist :php) nil)) | ||
| 1343 | ;; do setup only if the previous language isn't PHP | ||
| 1344 | (progn | ||
| 1345 | (plist-put php-ts-mode--comment-current-plist :php t) | ||
| 1346 | (c-ts-common-comment-setup) | ||
| 1347 | (setq-local c-ts-common--comment-regexp "comment" | ||
| 1348 | comment-line-break-function #'php-ts-mode--comment-indent-new-line | ||
| 1349 | comment-style 'extra-line | ||
| 1350 | comment-start (plist-get php-ts-mode--comment-current-plist :comment-start) | ||
| 1351 | comment-end (plist-get php-ts-mode--comment-current-plist :comment-end) | ||
| 1352 | comment-start-skip (rx (or (seq "#" (not (any "["))) | ||
| 1353 | (seq "/" (+ "/")) | ||
| 1354 | (seq "/" (+ "*"))) | ||
| 1355 | (* (syntax whitespace))) | ||
| 1356 | ;; reset the state of mhtml-ts-mode--comment-setup | ||
| 1357 | mhtml-ts-mode--comment-current-lang nil)) | ||
| 1358 | ;; otherwise set comment style for other languages. | ||
| 1359 | (plist-put php-ts-mode--comment-current-plist :php nil) | ||
| 1360 | (setq-local comment-style 'indent) ; this is the default for mhtml-ts-mode. | ||
| 1361 | (mhtml-ts-mode--comment-setup)))) | ||
| 1289 | 1362 | ||
| 1290 | 1363 | ||
| 1291 | ;;; Modes | 1364 | ;;; Modes |
| @@ -1293,15 +1366,20 @@ Depends on `c-ts-common-comment-setup'." | |||
| 1293 | (defun php-ts-mode-set-comment-style () | 1366 | (defun php-ts-mode-set-comment-style () |
| 1294 | "Set a different comment style." | 1367 | "Set a different comment style." |
| 1295 | (interactive) | 1368 | (interactive) |
| 1296 | (setq-local comment-start | 1369 | (let ((lang (treesit-language-at (point)))) |
| 1297 | (completing-read | 1370 | (when (or (eq lang 'php) (eq lang 'phpdoc)) |
| 1298 | "Choose comment style: " | 1371 | (setq-local comment-start |
| 1299 | '("/**" "//" "/*" "#") nil t nil nil "// ")) | 1372 | (completing-read |
| 1300 | (cond | 1373 | "Choose comment style: " |
| 1301 | ((equal comment-start "/*") (setq-local comment-end "*/")) | 1374 | '("/**" "// " "/*" "# ") nil t nil nil "// ")) |
| 1302 | ((equal comment-start "//") (setq-local comment-end "")) | 1375 | (cond |
| 1303 | ((equal comment-start "#") (setq-local comment-end "")) | 1376 | ((equal comment-start "/*") (setq-local comment-end "*/")) |
| 1304 | ((equal comment-start "/**") (setq-local comment-end "*/")))) | 1377 | ((equal comment-start "// ") (setq-local comment-end "")) |
| 1378 | ((equal comment-start "# ") (setq-local comment-end "")) | ||
| 1379 | ((equal comment-start "/**") (setq-local comment-end "*/"))) | ||
| 1380 | ;; store the value in order to recover when switch to php from other languages. | ||
| 1381 | (plist-put php-ts-mode--comment-current-plist :comment-start comment-start) | ||
| 1382 | (plist-put php-ts-mode--comment-current-plist :comment-end comment-end)))) | ||
| 1305 | 1383 | ||
| 1306 | (defvar-keymap php-ts-mode-map | 1384 | (defvar-keymap php-ts-mode-map |
| 1307 | :doc "Keymap for `php-ts-mode' buffers." | 1385 | :doc "Keymap for `php-ts-mode' buffers." |
| @@ -1321,7 +1399,7 @@ Depends on `c-ts-common-comment-setup'." | |||
| 1321 | :enable mark-active | 1399 | :enable mark-active |
| 1322 | :help "Comment out the region between the mark and point"] | 1400 | :help "Comment out the region between the mark and point"] |
| 1323 | ["Uncomment Region" (comment-region (region-beginning) | 1401 | ["Uncomment Region" (comment-region (region-beginning) |
| 1324 | (region-end) '(4)) | 1402 | (region-end) '(4)) |
| 1325 | :enable mark-active | 1403 | :enable mark-active |
| 1326 | :help "Uncomment the region between the mark and point"] | 1404 | :help "Uncomment the region between the mark and point"] |
| 1327 | ["Indent Top-level Expression" php-ts-mode--indent-defun | 1405 | ["Indent Top-level Expression" php-ts-mode--indent-defun |
| @@ -1336,7 +1414,7 @@ Depends on `c-ts-common-comment-setup'." | |||
| 1336 | ["Set Indentation Style..." php-ts-mode-set-style | 1414 | ["Set Indentation Style..." php-ts-mode-set-style |
| 1337 | :help "Set PHP indentation style for current buffer"] | 1415 | :help "Set PHP indentation style for current buffer"] |
| 1338 | ["Show Current Style Name"(message "Indentation Style: %s" | 1416 | ["Show Current Style Name"(message "Indentation Style: %s" |
| 1339 | php-ts-mode-indent-style) | 1417 | php-ts-mode-indent-style) |
| 1340 | :help "Show the name of the PHP indentation style for current buffer"] | 1418 | :help "Show the name of the PHP indentation style for current buffer"] |
| 1341 | ["Set Comment Style" php-ts-mode-set-comment-style | 1419 | ["Set Comment Style" php-ts-mode-set-comment-style |
| 1342 | :help "Choose PHP comment style between block and line comments"]) | 1420 | :help "Choose PHP comment style between block and line comments"]) |
| @@ -1377,114 +1455,98 @@ Depends on `c-ts-common-comment-setup'." | |||
| 1377 | function))) | 1455 | function))) |
| 1378 | 1456 | ||
| 1379 | ;;;###autoload | 1457 | ;;;###autoload |
| 1380 | (define-derived-mode php-ts-mode prog-mode "PHP" | 1458 | (define-derived-mode php-ts-mode prog-mode |
| 1459 | '("PHP" | ||
| 1460 | (:eval (let ((lang (treesit-language-at (point)))) | ||
| 1461 | (cond ((eq lang 'html) "+HTML") | ||
| 1462 | ((eq lang 'javascript) "+HTML+JS") | ||
| 1463 | ((eq lang 'css) "+HTML+CSS"))))) | ||
| 1381 | "Major mode for editing PHP, powered by tree-sitter." | 1464 | "Major mode for editing PHP, powered by tree-sitter." |
| 1382 | :syntax-table php-ts-mode--syntax-table | 1465 | :syntax-table php-ts-mode--syntax-table |
| 1383 | 1466 | ||
| 1467 | ;; TODO: wouldn't better to delegate the check and the | ||
| 1468 | ;; init of the mhtml parser to mhtml-ts-mode? | ||
| 1384 | (if (not (and | 1469 | (if (not (and |
| 1385 | (treesit-ensure-installed 'php) | 1470 | (treesit-ensure-installed 'php) |
| 1386 | (treesit-ensure-installed 'phpdoc) | 1471 | (treesit-ensure-installed 'phpdoc) |
| 1387 | (treesit-ensure-installed 'html) | 1472 | (treesit-ensure-installed 'html) |
| 1388 | (treesit-ensure-installed 'javascript) | 1473 | (treesit-ensure-installed 'javascript) |
| 1389 | (treesit-ensure-installed 'jsdoc) | 1474 | (treesit-ensure-installed 'jsdoc) |
| 1390 | (treesit-ensure-installed 'css))) | 1475 | (treesit-ensure-installed 'css))) |
| 1391 | (error "Tree-sitter for PHP isn't | 1476 | (error "Tree-sitter for PHP isn't |
| 1392 | available. You can install the parsers with M-x | 1477 | available. You can install the parsers with M-x |
| 1393 | `php-ts-mode-install-parsers'") | 1478 | `php-ts-mode-install-parsers'") |
| 1394 | 1479 | ||
| 1395 | ;; phpdoc is a local parser, don't create a parser for it | 1480 | ;; phpdoc is a local parser, don't create a parser for it |
| 1481 | ;; create the parser needed by mhtml-ts-mode | ||
| 1396 | (treesit-parser-create 'html) | 1482 | (treesit-parser-create 'html) |
| 1397 | (treesit-parser-create 'css) | 1483 | (treesit-parser-create 'css) |
| 1398 | (treesit-parser-create 'javascript) | 1484 | (treesit-parser-create 'javascript) |
| 1399 | 1485 | ||
| 1400 | ;; define the injected parser ranges | 1486 | ;; define the injected parser ranges |
| 1401 | (setq-local treesit-range-settings | 1487 | (setq-local treesit-range-settings |
| 1402 | (treesit-range-rules | 1488 | (append |
| 1403 | :embed 'phpdoc | 1489 | (treesit-range-rules |
| 1404 | :host 'php | 1490 | :embed 'phpdoc |
| 1405 | :local t | 1491 | :host 'php |
| 1406 | '(((comment) @cap | 1492 | :local t |
| 1407 | (:match "/\\*\\*" @cap))) | 1493 | '(((comment) @cap |
| 1408 | 1494 | (:match "/\\*\\*" @cap))) | |
| 1409 | :embed 'html | 1495 | |
| 1410 | :host 'php | 1496 | :embed 'html |
| 1411 | '((program (text) @cap) | 1497 | :host 'php |
| 1412 | (text_interpolation (text) @cap)) | 1498 | '((program (text) @cap) |
| 1413 | 1499 | (text_interpolation (text) @cap))) | |
| 1414 | :embed 'javascript | 1500 | ;; inject the range rules from mhtml-ts-mode |
| 1415 | :host 'html | 1501 | mhtml-ts-mode--range-settings)) |
| 1416 | :offset '(1 . -1) | ||
| 1417 | '((script_element | ||
| 1418 | (start_tag (tag_name)) | ||
| 1419 | (raw_text) @cap)) | ||
| 1420 | |||
| 1421 | :embed 'jsdoc | ||
| 1422 | :host 'javascript | ||
| 1423 | :local t | ||
| 1424 | `(((comment) @cap | ||
| 1425 | (:match ,js--treesit-jsdoc-beginning-regexp @cap))) | ||
| 1426 | |||
| 1427 | :embed 'css | ||
| 1428 | :host 'html | ||
| 1429 | :offset '(1 . -1) | ||
| 1430 | '((style_element | ||
| 1431 | (start_tag (tag_name)) | ||
| 1432 | (raw_text) @cap)))) | ||
| 1433 | 1502 | ||
| 1434 | ;; Navigation. | 1503 | ;; Navigation. |
| 1435 | (setq-local treesit-defun-type-regexp | ||
| 1436 | (regexp-opt '("class_declaration" | ||
| 1437 | "enum_declaration" | ||
| 1438 | "function_definition" | ||
| 1439 | "interface_declaration" | ||
| 1440 | "method_declaration" | ||
| 1441 | "namespace_definition" | ||
| 1442 | "trait_declaration"))) | ||
| 1443 | |||
| 1444 | (setq-local treesit-defun-name-function #'php-ts-mode--defun-name) | 1504 | (setq-local treesit-defun-name-function #'php-ts-mode--defun-name) |
| 1445 | 1505 | ||
| 1446 | (setq-local treesit-thing-settings | 1506 | (setq-local treesit-thing-settings |
| 1447 | `((php | 1507 | (append |
| 1448 | (defun ,treesit-defun-type-regexp) | 1508 | `((php |
| 1449 | (sexp (not (or (and named | 1509 | (defun ,php-ts-mode--treesit-defun-type-regexp) |
| 1450 | ,(rx bos (or "program" | 1510 | (sexp (not (or (and named |
| 1451 | "comment") | 1511 | ,(rx bos (or "program" |
| 1452 | eos)) | 1512 | "comment") |
| 1453 | (and anonymous | 1513 | eos)) |
| 1454 | ,(rx bos (or "{" "}" "[" "]" | 1514 | (and anonymous |
| 1455 | "(" ")" ",") | 1515 | ,(rx bos (or "{" "}" "[" "]" |
| 1456 | eos))))) | 1516 | "(" ")" ",") |
| 1457 | (list | 1517 | eos))))) |
| 1458 | ,(rx bos (or "namespace_use_group" | 1518 | (list |
| 1459 | "enum_declaration_list" | 1519 | ,(rx bos (or "namespace_use_group" |
| 1460 | "declaration_list" | 1520 | "enum_declaration_list" |
| 1461 | "property_hook_list" | 1521 | "declaration_list" |
| 1462 | "use_list" | 1522 | "property_hook_list" |
| 1463 | "anonymous_function_use_clause" | 1523 | "use_list" |
| 1464 | "formal_parameters" | 1524 | "anonymous_function_use_clause" |
| 1465 | "match_block" | 1525 | "formal_parameters" |
| 1466 | "switch_block" | 1526 | "match_block" |
| 1467 | "compound_statement" | 1527 | "switch_block" |
| 1468 | "parenthesized_expression" | 1528 | "compound_statement" |
| 1469 | "_array_destructing" | 1529 | "parenthesized_expression" |
| 1470 | "arguments" | 1530 | "_array_destructing" |
| 1471 | "_complex_string_part") | 1531 | "arguments" |
| 1472 | eos)) | 1532 | "_complex_string_part") |
| 1473 | (sentence ,(regexp-opt | 1533 | eos)) |
| 1474 | '("break_statement" | 1534 | (sentence ,(regexp-opt |
| 1475 | "case_statement" | 1535 | '("break_statement" |
| 1476 | "continue_statement" | 1536 | "case_statement" |
| 1477 | "declaration" | 1537 | "continue_statement" |
| 1478 | "default_statement" | 1538 | "declaration" |
| 1479 | "do_statement" | 1539 | "default_statement" |
| 1480 | "expression_statement" | 1540 | "do_statement" |
| 1481 | "for_statement" | 1541 | "expression_statement" |
| 1482 | "if_statement" | 1542 | "for_statement" |
| 1483 | "return_statement" | 1543 | "if_statement" |
| 1484 | "switch_statement" | 1544 | "return_statement" |
| 1485 | "while_statement" | 1545 | "switch_statement" |
| 1486 | "statement"))) | 1546 | "while_statement" |
| 1487 | (text ,(regexp-opt '("comment" "text")))))) | 1547 | "statement"))) |
| 1548 | (text ,(regexp-opt '("comment" "text"))))) | ||
| 1549 | mhtml-ts-mode--treesit-thing-settings)) | ||
| 1488 | 1550 | ||
| 1489 | ;; Indent. | 1551 | ;; Indent. |
| 1490 | (when (eq php-ts-mode-indent-style 'wordpress) | 1552 | (when (eq php-ts-mode-indent-style 'wordpress) |
| @@ -1493,75 +1555,91 @@ Depends on `c-ts-common-comment-setup'." | |||
| 1493 | (setq-local c-ts-common-indent-offset 'php-ts-mode-indent-offset) | 1555 | (setq-local c-ts-common-indent-offset 'php-ts-mode-indent-offset) |
| 1494 | (setq-local treesit-simple-indent-rules (php-ts-mode--get-indent-style)) | 1556 | (setq-local treesit-simple-indent-rules (php-ts-mode--get-indent-style)) |
| 1495 | (setq-local treesit-simple-indent-rules | 1557 | (setq-local treesit-simple-indent-rules |
| 1496 | (append treesit-simple-indent-rules | 1558 | (append treesit-simple-indent-rules |
| 1497 | php-ts-mode--phpdoc-indent-rules | 1559 | php-ts-mode--phpdoc-indent-rules |
| 1498 | html-ts-mode--indent-rules | 1560 | `((html ,@(alist-get 'html |
| 1499 | ;; Extended rules for js and css, to | 1561 | (mhtml-ts-mode--treesit-indent-rules)))) |
| 1500 | ;; indent appropriately when injected | 1562 | ;; Replace rules for js and css, to |
| 1501 | ;; into html | 1563 | ;; indent appropriately when injected |
| 1502 | `((javascript ((parent-is "program") | 1564 | ;; into html. |
| 1503 | php-ts-mode--js-css-tag-bol | 1565 | (treesit-simple-indent-modify-rules |
| 1504 | php-ts-mode-js-css-indent-offset) | 1566 | 'javascript |
| 1505 | ,@(cdr (car js--treesit-indent-rules)))) | 1567 | `((javascript ((parent-is "program") |
| 1506 | `((css ((parent-is "stylesheet") | 1568 | mhtml-ts-mode--js-css-tag-bol |
| 1507 | php-ts-mode--js-css-tag-bol | 1569 | php-ts-mode-js-css-indent-offset))) |
| 1508 | php-ts-mode-js-css-indent-offset) | 1570 | `((javascript |
| 1509 | ,@(cdr (car css--treesit-indent-rules)))))) | 1571 | ,@(alist-get 'javascript |
| 1572 | (mhtml-ts-mode--treesit-indent-rules))))) | ||
| 1573 | |||
| 1574 | (treesit-simple-indent-modify-rules | ||
| 1575 | 'css | ||
| 1576 | `((css ((parent-is "stylesheet") | ||
| 1577 | mhtml-ts-mode--js-css-tag-bol | ||
| 1578 | php-ts-mode-js-css-indent-offset))) | ||
| 1579 | `((css | ||
| 1580 | ,@(alist-get 'css | ||
| 1581 | (mhtml-ts-mode--treesit-indent-rules))))) | ||
| 1582 | )) | ||
| 1510 | 1583 | ||
| 1511 | ;; Comment | 1584 | ;; Comment |
| 1512 | (php-ts-mode-comment-setup) | 1585 | (php-ts-mode--comment-setup t) ; Init the comment setup for PHP |
| 1586 | ;; Allow the comment machinery to automatically switch between the | ||
| 1587 | ;; various comment styles supported by `php-ts-mode'. | ||
| 1588 | (setq-local comment-setup-function #'php-ts-mode--comment-setup) | ||
| 1513 | 1589 | ||
| 1514 | ;; PHP vars are case-sensitive | 1590 | ;; PHP vars are case-sensitive |
| 1515 | (setq-local case-fold-search t) | 1591 | (setq-local case-fold-search t) |
| 1516 | 1592 | ||
| 1517 | ;; Electric | 1593 | ;; Electric |
| 1518 | (setq-local electric-indent-chars | 1594 | (setq-local electric-indent-chars |
| 1519 | (append "{}():;," electric-indent-chars)) | 1595 | (append "{}():;," electric-indent-chars)) |
| 1596 | |||
| 1597 | (setq-local electric-layout-rules | ||
| 1598 | '((?\; . after) (?\{ . after) (?\} . before))) | ||
| 1520 | 1599 | ||
| 1521 | ;; Imenu/Which-function | 1600 | ;; Imenu/Which-function |
| 1522 | (setq-local treesit-simple-imenu-settings | 1601 | (setq-local treesit-aggregated-simple-imenu-settings |
| 1523 | '(("Class" "\\`class_declaration\\'" nil nil) | 1602 | (append |
| 1524 | ("Enum" "\\`enum_declaration\\'" nil nil) | 1603 | '((php ("Class" "\\`class_declaration\\'" nil nil) |
| 1525 | ("Function" "\\`function_definition\\'" nil nil) | 1604 | ("Enum" "\\`enum_declaration\\'" nil nil) |
| 1526 | ("Interface" "\\`interface_declaration\\'" nil nil) | 1605 | ("Function" "\\`function_definition\\'" nil nil) |
| 1527 | ("Method" "\\`method_declaration\\'" nil nil) | 1606 | ("Interface" "\\`interface_declaration\\'" nil nil) |
| 1528 | ("Namespace" "\\`namespace_definition\\'" nil nil) | 1607 | ("Method" "\\`method_declaration\\'" nil nil) |
| 1529 | ("Trait" "\\`trait_declaration\\'" nil nil) | 1608 | ("Namespace" "\\`namespace_definition\\'" nil nil) |
| 1530 | ("Variable" "\\`variable_name\\'" nil nil) | 1609 | ("Trait" "\\`trait_declaration\\'" nil nil) |
| 1531 | ("Constant" "\\`const_element\\'" nil nil))) | 1610 | ("Variable" "\\`variable_name\\'" nil nil) |
| 1611 | ("Constant" "\\`const_element\\'" nil nil))) | ||
| 1612 | mhtml-ts-mode--treesit-aggregated-simple-imenu-settings)) | ||
| 1532 | 1613 | ||
| 1533 | ;; Outline | 1614 | ;; Outline |
| 1534 | (setq-local treesit-outline-predicate | 1615 | (setq-local treesit-aggregated-outline-predicate |
| 1535 | (rx bos (or "class_declaration" | 1616 | (append |
| 1536 | "function_definition" | 1617 | `((php . ,(rx bos (or "class_declaration" |
| 1537 | "interface_declaration" | 1618 | "function_definition" |
| 1538 | "method_declaration" | 1619 | "interface_declaration" |
| 1539 | "namespace_definition" | 1620 | "method_declaration" |
| 1540 | "trait_declaration") | 1621 | "namespace_definition" |
| 1541 | eos)) | 1622 | "trait_declaration") |
| 1623 | eos)) | ||
| 1624 | (phpdoc . ,(rx bos "document" eos))) | ||
| 1625 | mhtml-ts-mode--treesit-aggregated-outline-predicate)) | ||
| 1542 | 1626 | ||
| 1543 | ;; Font-lock. | 1627 | ;; Font-lock. |
| 1544 | (setq-local treesit-font-lock-settings | 1628 | (setq-local treesit-font-lock-settings |
| 1545 | (append (php-ts-mode--font-lock-settings) | 1629 | (append |
| 1546 | php-ts-mode--custom-html-font-lock-settings | 1630 | (php-ts-mode--font-lock-settings) |
| 1547 | js--treesit-font-lock-settings | 1631 | php-ts-mode--custom-html-font-lock-settings |
| 1548 | (append | 1632 | php-ts-mode--phpdoc-font-lock-settings)) |
| 1549 | ;; Rule for coloring CSS property values. | ||
| 1550 | ;; Placed before `css--treesit-settings' | ||
| 1551 | ;; to win against the same rule contained therein. | ||
| 1552 | (treesit-font-lock-rules | ||
| 1553 | :language 'css | ||
| 1554 | :override t | ||
| 1555 | :feature 'variable | ||
| 1556 | '((plain_value) @php-ts-mode--colorize-css-value)) | ||
| 1557 | css--treesit-settings) | ||
| 1558 | php-ts-mode--phpdoc-font-lock-settings)) | ||
| 1559 | 1633 | ||
| 1560 | (setq-local treesit-font-lock-feature-list php-ts-mode--feature-list) | 1634 | (setq-local treesit-font-lock-feature-list php-ts-mode--feature-list) |
| 1635 | (setq-local prettify-symbols-alist php-ts-mode--prettify-symbols-alist) | ||
| 1561 | 1636 | ||
| 1562 | ;; Align. | 1637 | ;; Align. |
| 1563 | (setq-local align-indent-before-aligning t) | 1638 | (setq-local align-indent-before-aligning t) |
| 1564 | 1639 | ||
| 1640 | ;; Find files | ||
| 1641 | (setq-local find-sibling-rules php-ts-mode-find-sibling-rules) | ||
| 1642 | |||
| 1565 | ;; should be the last one | 1643 | ;; should be the last one |
| 1566 | (setq-local treesit-primary-parser (treesit-parser-create 'php)) | 1644 | (setq-local treesit-primary-parser (treesit-parser-create 'php)) |
| 1567 | (treesit-major-mode-setup) | 1645 | (treesit-major-mode-setup) |
| @@ -1570,11 +1648,11 @@ Depends on `c-ts-common-comment-setup'." | |||
| 1570 | 1648 | ||
| 1571 | ;;;###autoload | 1649 | ;;;###autoload |
| 1572 | (defun php-ts-mode-run-php-webserver (&optional port | 1650 | (defun php-ts-mode-run-php-webserver (&optional port |
| 1573 | hostname | 1651 | hostname |
| 1574 | document-root | 1652 | document-root |
| 1575 | router-script | 1653 | router-script |
| 1576 | num-of-workers | 1654 | num-of-workers |
| 1577 | config) | 1655 | config) |
| 1578 | "Run PHP built-in web server. | 1656 | "Run PHP built-in web server. |
| 1579 | 1657 | ||
| 1580 | PORT: Port number of built-in web server, default `php-ts-mode-ws-port'. | 1658 | PORT: Port number of built-in web server, default `php-ts-mode-ws-port'. |
| @@ -1595,46 +1673,46 @@ Interactively, when invoked with prefix argument, always prompt for | |||
| 1595 | PORT, HOSTNAME, DOCUMENT-ROOT, ROUTER-SCRIPT, NUM-OF-WORKERS and | 1673 | PORT, HOSTNAME, DOCUMENT-ROOT, ROUTER-SCRIPT, NUM-OF-WORKERS and |
| 1596 | CONFIG." | 1674 | CONFIG." |
| 1597 | (interactive (when current-prefix-arg | 1675 | (interactive (when current-prefix-arg |
| 1598 | (php-ts-mode--webserver-read-args))) | 1676 | (php-ts-mode--webserver-read-args))) |
| 1599 | (let* ((port (or | 1677 | (let* ((port (or |
| 1600 | port | 1678 | port |
| 1601 | php-ts-mode-ws-port | 1679 | php-ts-mode-ws-port |
| 1602 | (php-ts-mode--webserver-read-args 'port))) | 1680 | (php-ts-mode--webserver-read-args 'port))) |
| 1603 | (hostname (or | 1681 | (hostname (or |
| 1604 | hostname | 1682 | hostname |
| 1605 | php-ts-mode-ws-hostname | 1683 | php-ts-mode-ws-hostname |
| 1606 | (php-ts-mode--webserver-read-args 'hostname))) | 1684 | (php-ts-mode--webserver-read-args 'hostname))) |
| 1607 | (document-root (or | 1685 | (document-root (or |
| 1608 | document-root | 1686 | document-root |
| 1609 | php-ts-mode-ws-document-root | 1687 | php-ts-mode-ws-document-root |
| 1610 | (php-ts-mode--webserver-read-args 'document-root))) | 1688 | (php-ts-mode--webserver-read-args 'document-root))) |
| 1611 | (config (or config | 1689 | (config (or config |
| 1612 | (when php-ts-mode-php-config | 1690 | (when php-ts-mode-php-config |
| 1613 | (expand-file-name php-ts-mode-php-config)))) | 1691 | (expand-file-name php-ts-mode-php-config)))) |
| 1614 | (host (format "%s:%d" hostname port)) | 1692 | (host (format "%s:%d" hostname port)) |
| 1615 | (name (format "PHP web server on: %s" host)) | 1693 | (name (format "PHP web server on: %s" host)) |
| 1616 | (buf-name (format "*%s*" name)) | 1694 | (buf-name (format "*%s*" name)) |
| 1617 | (args (delq | 1695 | (args (delq |
| 1618 | nil | 1696 | nil |
| 1619 | (list "-S" host | 1697 | (list "-S" host |
| 1620 | "-t" document-root | 1698 | "-t" document-root |
| 1621 | (when config | 1699 | (when config |
| 1622 | (format "-c %s" config)) | 1700 | (format "-c %s" config)) |
| 1623 | router-script))) | 1701 | router-script))) |
| 1624 | (process-environment | 1702 | (process-environment |
| 1625 | (nconc (cond | 1703 | (nconc (cond |
| 1626 | (num-of-workers | 1704 | (num-of-workers |
| 1627 | (list | 1705 | (list |
| 1628 | (format "PHP_CLI_SERVER_WORKERS=%d" num-of-workers))) | 1706 | (format "PHP_CLI_SERVER_WORKERS=%d" num-of-workers))) |
| 1629 | (php-ts-mode-ws-workers | 1707 | (php-ts-mode-ws-workers |
| 1630 | (list | 1708 | (list |
| 1631 | (format "PHP_CLI_SERVER_WORKERS=%d" php-ts-mode-ws-workers)))) | 1709 | (format "PHP_CLI_SERVER_WORKERS=%d" php-ts-mode-ws-workers)))) |
| 1632 | process-environment))) | 1710 | process-environment))) |
| 1633 | (if (get-buffer buf-name) | 1711 | (if (get-buffer buf-name) |
| 1634 | (message "Switch to already running web server into buffer %s" buf-name) | 1712 | (message "Switch to already running web server into buffer %s" buf-name) |
| 1635 | (message "Run PHP built-in web server with args %s into buffer %s" | 1713 | (message "Run PHP built-in web server with args %s into buffer %s" |
| 1636 | (string-join args " ") | 1714 | (string-join args " ") |
| 1637 | buf-name) | 1715 | buf-name) |
| 1638 | (apply #'make-comint name (php-ts-mode--executable) nil args)) | 1716 | (apply #'make-comint name (php-ts-mode--executable) nil args)) |
| 1639 | (funcall | 1717 | (funcall |
| 1640 | (if (called-interactively-p 'interactive) #'display-buffer #'get-buffer) | 1718 | (if (called-interactively-p 'interactive) #'display-buffer #'get-buffer) |
| @@ -1647,45 +1725,45 @@ CONFIG." | |||
| 1647 | The optional TYPE can be the symbol \"port\", \"hostname\", \"document-root\", | 1725 | The optional TYPE can be the symbol \"port\", \"hostname\", \"document-root\", |
| 1648 | \"router-script\", \"num-workers\" or \"config\", otherwise it requires all of them." | 1726 | \"router-script\", \"num-workers\" or \"config\", otherwise it requires all of them." |
| 1649 | (let ((ask-port (lambda () | 1727 | (let ((ask-port (lambda () |
| 1650 | (read-number "Port: " (or | 1728 | (read-number "Port: " (or |
| 1651 | php-ts-mode-ws-port | 1729 | php-ts-mode-ws-port |
| 1652 | 3000)))) | 1730 | 3000)))) |
| 1653 | (ask-hostname (lambda () | 1731 | (ask-hostname (lambda () |
| 1654 | (read-string "Hostname: " | 1732 | (read-string "Hostname: " |
| 1655 | (or | 1733 | (or |
| 1656 | php-ts-mode-ws-hostname | 1734 | php-ts-mode-ws-hostname |
| 1657 | "localhost")))) | 1735 | "localhost")))) |
| 1658 | (ask-document-root (lambda () | 1736 | (ask-document-root (lambda () |
| 1659 | (expand-file-name | 1737 | (expand-file-name |
| 1660 | (read-directory-name "Document root: " | 1738 | (read-directory-name "Document root: " |
| 1661 | (file-name-directory | 1739 | (file-name-directory |
| 1662 | (or (buffer-file-name) | 1740 | (or (buffer-file-name) |
| 1663 | default-directory)))))) | 1741 | default-directory)))))) |
| 1664 | (ask-router-script (lambda () | 1742 | (ask-router-script (lambda () |
| 1665 | (expand-file-name | 1743 | (expand-file-name |
| 1666 | (read-file-name "Router script: " | 1744 | (read-file-name "Router script: " |
| 1667 | (file-name-directory | 1745 | (file-name-directory |
| 1668 | (or (buffer-file-name) | 1746 | (or (buffer-file-name) |
| 1669 | default-directory)))))) | 1747 | default-directory)))))) |
| 1670 | (ask-num-workers (lambda () | 1748 | (ask-num-workers (lambda () |
| 1671 | (let ((num-workers | 1749 | (let ((num-workers |
| 1672 | (read-number | 1750 | (read-number |
| 1673 | "Number of workers (less then 2 means no workers): " | 1751 | "Number of workers (less then 2 means no workers): " |
| 1674 | (or php-ts-mode-ws-workers 0)))) | 1752 | (or php-ts-mode-ws-workers 0)))) |
| 1675 | ;; num-workers must be >= 2 or nil | 1753 | ;; num-workers must be >= 2 or nil |
| 1676 | ;; otherwise PHP's built-in web server will not start. | 1754 | ;; otherwise PHP's built-in web server will not start. |
| 1677 | (if (> num-workers 1) | 1755 | (if (> num-workers 1) |
| 1678 | num-workers | 1756 | num-workers |
| 1679 | nil)))) | 1757 | nil)))) |
| 1680 | (ask-config (lambda() | 1758 | (ask-config (lambda() |
| 1681 | (let ((file-name (expand-file-name | 1759 | (let ((file-name (expand-file-name |
| 1682 | (read-file-name "Alternative php.ini: " | 1760 | (read-file-name "Alternative php.ini: " |
| 1683 | (file-name-directory | 1761 | (file-name-directory |
| 1684 | (or (buffer-file-name) | 1762 | (or (buffer-file-name) |
| 1685 | default-directory)))))) | 1763 | default-directory)))))) |
| 1686 | (if (string= "" (file-name-directory file-name)) | 1764 | (if (string= "" (file-name-directory file-name)) |
| 1687 | nil | 1765 | nil |
| 1688 | file-name))))) | 1766 | file-name))))) |
| 1689 | (cl-case type | 1767 | (cl-case type |
| 1690 | (port (funcall ask-port)) | 1768 | (port (funcall ask-port)) |
| 1691 | (hostname (funcall ask-hostname)) | 1769 | (hostname (funcall ask-hostname)) |
| @@ -1694,21 +1772,21 @@ The optional TYPE can be the symbol \"port\", \"hostname\", \"document-root\", | |||
| 1694 | (num-of-workers (funcall ask-num-workers)) | 1772 | (num-of-workers (funcall ask-num-workers)) |
| 1695 | (config (funcall ask-config)) | 1773 | (config (funcall ask-config)) |
| 1696 | (t (list | 1774 | (t (list |
| 1697 | (funcall ask-port) | 1775 | (funcall ask-port) |
| 1698 | (funcall ask-hostname) | 1776 | (funcall ask-hostname) |
| 1699 | (funcall ask-document-root) | 1777 | (funcall ask-document-root) |
| 1700 | (funcall ask-router-script) | 1778 | (funcall ask-router-script) |
| 1701 | (funcall ask-num-workers) | 1779 | (funcall ask-num-workers) |
| 1702 | (funcall ask-config)))))) | 1780 | (funcall ask-config)))))) |
| 1703 | 1781 | ||
| 1704 | (define-derived-mode inferior-php-ts-mode comint-mode "Inferior PHP" | 1782 | (define-derived-mode inferior-php-ts-mode comint-mode "Inferior PHP" |
| 1705 | "Major mode for PHP inferior process." | 1783 | "Major mode for PHP inferior process." |
| 1706 | (setq-local scroll-conservatively 1 | 1784 | (setq-local scroll-conservatively 1 |
| 1707 | comint-input-ring-file-name php-ts-mode-inferior-history | 1785 | comint-input-ring-file-name php-ts-mode-inferior-history |
| 1708 | comint-input-ignoredups t | 1786 | comint-input-ignoredups t |
| 1709 | comint-prompt-read-only t | 1787 | comint-prompt-read-only t |
| 1710 | comint-use-prompt-regexp t | 1788 | comint-use-prompt-regexp t |
| 1711 | comint-prompt-regexp (concat "^" php-ts-mode--inferior-prompt " ")) | 1789 | comint-prompt-regexp (concat "^" php-ts-mode--inferior-prompt " ")) |
| 1712 | (comint-read-input-ring t)) | 1790 | (comint-read-input-ring t)) |
| 1713 | 1791 | ||
| 1714 | 1792 | ||
| @@ -1726,24 +1804,24 @@ and `php-ts-mode-php-config' respectively, control which PHP interpreter is run. | |||
| 1726 | Prompt for CMD if `php-ts-mode-php-executable' is nil. | 1804 | Prompt for CMD if `php-ts-mode-php-executable' is nil. |
| 1727 | Optional CONFIG, if supplied, is the php.ini file to use." | 1805 | Optional CONFIG, if supplied, is the php.ini file to use." |
| 1728 | (interactive (when current-prefix-arg | 1806 | (interactive (when current-prefix-arg |
| 1729 | (list | 1807 | (list |
| 1730 | (read-string "Run PHP: " (php-ts-mode--executable)) | 1808 | (read-string "Run PHP: " (php-ts-mode--executable)) |
| 1731 | (expand-file-name | 1809 | (expand-file-name |
| 1732 | (read-file-name "With config: " php-ts-mode-php-config))))) | 1810 | (read-file-name "With config: " php-ts-mode-php-config))))) |
| 1733 | (let* ((php-prog (php-ts-mode--executable)) | 1811 | (let* ((php-prog (php-ts-mode--executable)) |
| 1734 | (buffer (get-buffer-create php-ts-mode-inferior-php-buffer)) | 1812 | (buffer (get-buffer-create php-ts-mode-inferior-php-buffer)) |
| 1735 | (cmd (or | 1813 | (cmd (or |
| 1736 | cmd | 1814 | cmd |
| 1737 | php-prog | 1815 | php-prog |
| 1738 | (read-string "Run PHP: " php-prog))) | 1816 | (read-string "Run PHP: " php-prog))) |
| 1739 | (config (or | 1817 | (config (or |
| 1740 | config | 1818 | config |
| 1741 | (and php-ts-mode-php-config | 1819 | (and php-ts-mode-php-config |
| 1742 | (expand-file-name php-ts-mode-php-config))))) | 1820 | (expand-file-name php-ts-mode-php-config))))) |
| 1743 | (unless (comint-check-proc buffer) | 1821 | (unless (comint-check-proc buffer) |
| 1744 | (with-current-buffer buffer | 1822 | (with-current-buffer buffer |
| 1745 | (inferior-php-ts-mode-startup cmd config) | 1823 | (inferior-php-ts-mode-startup cmd config) |
| 1746 | (inferior-php-ts-mode))) | 1824 | (inferior-php-ts-mode))) |
| 1747 | (when buffer | 1825 | (when buffer |
| 1748 | (pop-to-buffer buffer)))) | 1826 | (pop-to-buffer buffer)))) |
| 1749 | 1827 | ||
| @@ -1752,39 +1830,39 @@ Optional CONFIG, if supplied, is the php.ini file to use." | |||
| 1752 | CMD is the command to run. Optional CONFIG, if supplied, is the php.ini | 1830 | CMD is the command to run. Optional CONFIG, if supplied, is the php.ini |
| 1753 | file to use." | 1831 | file to use." |
| 1754 | (setq-local php-ts-mode--inferior-php-process | 1832 | (setq-local php-ts-mode--inferior-php-process |
| 1755 | (apply #'make-comint-in-buffer | 1833 | (apply #'make-comint-in-buffer |
| 1756 | (string-replace "*" "" php-ts-mode-inferior-php-buffer) | 1834 | (string-replace "*" "" php-ts-mode-inferior-php-buffer) |
| 1757 | php-ts-mode-inferior-php-buffer | 1835 | php-ts-mode-inferior-php-buffer |
| 1758 | cmd | 1836 | cmd |
| 1759 | nil | 1837 | nil |
| 1760 | (delq | 1838 | (delq |
| 1761 | nil | 1839 | nil |
| 1762 | (list | 1840 | (list |
| 1763 | (when config | 1841 | (when config |
| 1764 | (format "-c %s" config)) | 1842 | (format "-c %s" config)) |
| 1765 | "-a")))) | 1843 | "-a")))) |
| 1766 | (add-hook 'comint-preoutput-filter-functions | 1844 | (add-hook 'comint-preoutput-filter-functions |
| 1767 | (lambda (string) | 1845 | (lambda (string) |
| 1768 | (let ((prompt (concat php-ts-mode--inferior-prompt " "))) | 1846 | (let ((prompt (concat php-ts-mode--inferior-prompt " "))) |
| 1769 | (if (member | 1847 | (if (member |
| 1770 | string | 1848 | string |
| 1771 | (list prompt "php { " "php ( " "/* > " "Interactive shell\n\n")) | 1849 | (list prompt "php { " "php ( " "/* > " "Interactive shell\n\n")) |
| 1772 | string | 1850 | string |
| 1773 | (let (;; Filter out prompts characters that accumulate when sending | 1851 | (let (;; Filter out prompts characters that accumulate when sending |
| 1774 | ;; regions to the inferior process. | 1852 | ;; regions to the inferior process. |
| 1775 | (clean-string | 1853 | (clean-string |
| 1776 | (replace-regexp-in-string | 1854 | (replace-regexp-in-string |
| 1777 | (rx-to-string `(or | 1855 | (rx-to-string `(or |
| 1778 | (+ "php >" (opt space)) | 1856 | (+ "php >" (opt space)) |
| 1779 | (+ "php {" (opt space)) | 1857 | (+ "php {" (opt space)) |
| 1780 | (+ "php (" (opt space)) | 1858 | (+ "php (" (opt space)) |
| 1781 | (+ "/*" (1+ space) (1+ ">") (opt space)))) | 1859 | (+ "/*" (1+ space) (1+ ">") (opt space)))) |
| 1782 | "" string))) | 1860 | "" string))) |
| 1783 | ;; Re-add the prompt for the next line, if isn't empty. | 1861 | ;; Re-add the prompt for the next line, if isn't empty. |
| 1784 | (if (string= clean-string "") | 1862 | (if (string= clean-string "") |
| 1785 | "" | 1863 | "" |
| 1786 | (concat (string-chop-newline clean-string) "\n" prompt)))))) | 1864 | (concat (string-chop-newline clean-string) "\n" prompt)))))) |
| 1787 | nil t) | 1865 | nil t) |
| 1788 | (when php-ts-mode-inferior-history | 1866 | (when php-ts-mode-inferior-history |
| 1789 | (set-process-sentinel | 1867 | (set-process-sentinel |
| 1790 | (get-buffer-process php-ts-mode-inferior-php-buffer) | 1868 | (get-buffer-process php-ts-mode-inferior-php-buffer) |
| @@ -1796,7 +1874,7 @@ file to use." | |||
| 1796 | ;; Depending on how the process is killed the buffer may not be | 1874 | ;; Depending on how the process is killed the buffer may not be |
| 1797 | ;; around anymore; e.g. `kill-buffer'. | 1875 | ;; around anymore; e.g. `kill-buffer'. |
| 1798 | (when-let* ((buffer (process-buffer process)) | 1876 | (when-let* ((buffer (process-buffer process)) |
| 1799 | ((buffer-live-p (process-buffer process)))) | 1877 | ((buffer-live-p (process-buffer process)))) |
| 1800 | (with-current-buffer buffer (comint-write-input-ring)))) | 1878 | (with-current-buffer buffer (comint-write-input-ring)))) |
| 1801 | 1879 | ||
| 1802 | (defun php-ts-mode-send-region (beg end) | 1880 | (defun php-ts-mode-send-region (beg end) |
| @@ -1804,12 +1882,12 @@ file to use." | |||
| 1804 | (interactive "r") | 1882 | (interactive "r") |
| 1805 | (if (buffer-live-p php-ts-mode--inferior-php-process) | 1883 | (if (buffer-live-p php-ts-mode--inferior-php-process) |
| 1806 | (progn | 1884 | (progn |
| 1807 | (php-ts-mode-show-process-buffer) | 1885 | (php-ts-mode-show-process-buffer) |
| 1808 | (comint-send-string php-ts-mode--inferior-php-process "\n") | 1886 | (comint-send-string php-ts-mode--inferior-php-process "\n") |
| 1809 | (comint-send-string | 1887 | (comint-send-string |
| 1810 | php-ts-mode--inferior-php-process | 1888 | php-ts-mode--inferior-php-process |
| 1811 | (buffer-substring-no-properties beg end)) | 1889 | (buffer-substring-no-properties beg end)) |
| 1812 | (comint-send-string php-ts-mode--inferior-php-process "\n")) | 1890 | (comint-send-string php-ts-mode--inferior-php-process "\n")) |
| 1813 | (message "Invoke run-php first!"))) | 1891 | (message "Invoke run-php first!"))) |
| 1814 | 1892 | ||
| 1815 | (defun php-ts-mode-send-buffer () | 1893 | (defun php-ts-mode-send-buffer () |
diff --git a/lisp/textmodes/mhtml-ts-mode.el b/lisp/textmodes/mhtml-ts-mode.el index 6b261205409..66bb27ced10 100644 --- a/lisp/textmodes/mhtml-ts-mode.el +++ b/lisp/textmodes/mhtml-ts-mode.el | |||
| @@ -333,7 +333,8 @@ NODE and PARENT are ignored." | |||
| 333 | "function_declaration" | 333 | "function_declaration" |
| 334 | "lexical_declaration" | 334 | "lexical_declaration" |
| 335 | "element" | 335 | "element" |
| 336 | "rule_set")) | 336 | "rule_set" |
| 337 | "keyframe_block")) | ||
| 337 | "Settings for `treesit-defun-type-regexp'.") | 338 | "Settings for `treesit-defun-type-regexp'.") |
| 338 | 339 | ||
| 339 | ;; In order to support `prettify-symbols-mode', just `append' the prettify | 340 | ;; In order to support `prettify-symbols-mode', just `append' the prettify |
| @@ -348,13 +349,11 @@ NODE and PARENT are ignored." | |||
| 348 | (defun mhtml-ts-mode--defun-name (node) | 349 | (defun mhtml-ts-mode--defun-name (node) |
| 349 | "Return the defun name of NODE. | 350 | "Return the defun name of NODE. |
| 350 | Return nil if there is no name or if NODE is not a defun node." | 351 | Return nil if there is no name or if NODE is not a defun node." |
| 351 | (let ((html-name (html-ts-mode--defun-name node)) | 352 | (let ((lang (treesit-node-language node))) |
| 352 | (js-name (js--treesit-defun-name node)) | ||
| 353 | (css-name (css--treesit-defun-name node))) | ||
| 354 | (cond | 353 | (cond |
| 355 | (html-name html-name) | 354 | ((eq lang 'html) (html-ts-mode--defun-name node)) |
| 356 | (js-name js-name) | 355 | ((eq lang 'javascript) (js--treesit-defun-name node)) |
| 357 | (css-name css-name)))) | 356 | ((eq lang 'css) (css--treesit-defun-name node))))) |
| 358 | 357 | ||
| 359 | (defvar-local mhtml-ts-mode--comment-current-lang nil) | 358 | (defvar-local mhtml-ts-mode--comment-current-lang nil) |
| 360 | 359 | ||
| @@ -432,6 +431,41 @@ Calls REPORT-FN directly. Requires tidy." | |||
| 432 | (process-send-region mhtml-ts-mode--flymake-process (point-min) (point-max)) | 431 | (process-send-region mhtml-ts-mode--flymake-process (point-min) (point-max)) |
| 433 | (process-send-eof mhtml-ts-mode--flymake-process))))) | 432 | (process-send-eof mhtml-ts-mode--flymake-process))))) |
| 434 | 433 | ||
| 434 | (defvar mhtml-ts-mode--range-settings | ||
| 435 | (append | ||
| 436 | (treesit-range-rules | ||
| 437 | :embed 'javascript | ||
| 438 | :host 'html | ||
| 439 | '((script_element | ||
| 440 | (start_tag (tag_name)) | ||
| 441 | (raw_text) @cap)) | ||
| 442 | |||
| 443 | ;; Another rule could be added that when it matches an | ||
| 444 | ;; attribute_value that has as its parent an | ||
| 445 | ;; attribute_name "style" it captures it and then | ||
| 446 | ;; passes it to the css parser. | ||
| 447 | :embed 'css | ||
| 448 | :host 'html | ||
| 449 | '((style_element | ||
| 450 | (start_tag (tag_name)) | ||
| 451 | (raw_text) @cap))) | ||
| 452 | |||
| 453 | ;; jsdoc is not mandatory for js-ts-mode, so we respect this by | ||
| 454 | ;; adding jsdoc range rules only when jsdoc is available. | ||
| 455 | (when (treesit-ensure-installed 'jsdoc) | ||
| 456 | (treesit-range-rules | ||
| 457 | :embed 'jsdoc | ||
| 458 | :host 'javascript | ||
| 459 | :local t | ||
| 460 | `(((comment) @cap | ||
| 461 | (:match ,js--treesit-jsdoc-beginning-regexp @cap))))))) | ||
| 462 | |||
| 463 | (defvar mhtml-ts-mode--treesit-aggregated-outline-predicate | ||
| 464 | `((html . ,#'html-ts-mode--outline-predicate) | ||
| 465 | (javascript . ,js-ts-mode--outline-predicate) | ||
| 466 | (css . ,css-ts-mode--outline-predicate)) | ||
| 467 | "Settings for `treesit-aggregated-outline-predicate'.") | ||
| 468 | |||
| 435 | ;;;###autoload | 469 | ;;;###autoload |
| 436 | (define-derived-mode mhtml-ts-mode html-ts-mode | 470 | (define-derived-mode mhtml-ts-mode html-ts-mode |
| 437 | '("HTML+" (:eval (let ((lang (treesit-language-at (point)))) | 471 | '("HTML+" (:eval (let ((lang (treesit-language-at (point)))) |
| @@ -475,35 +509,11 @@ Powered by tree-sitter." | |||
| 475 | ;; Multi-language modes must set the primary parser. | 509 | ;; Multi-language modes must set the primary parser. |
| 476 | (setq-local treesit-primary-parser (treesit-parser-create 'html)) | 510 | (setq-local treesit-primary-parser (treesit-parser-create 'html)) |
| 477 | 511 | ||
| 478 | (setq-local treesit-range-settings | 512 | (setq-local treesit-range-settings mhtml-ts-mode--range-settings) |
| 479 | (treesit-range-rules | ||
| 480 | :embed 'javascript | ||
| 481 | :host 'html | ||
| 482 | '((script_element | ||
| 483 | (start_tag (tag_name)) | ||
| 484 | (raw_text) @cap)) | ||
| 485 | |||
| 486 | ;; Another rule could be added that when it matches an | ||
| 487 | ;; attribute_value that has as its parent an | ||
| 488 | ;; attribute_name "style" it captures it and then | ||
| 489 | ;; passes it to the css parser. | ||
| 490 | :embed 'css | ||
| 491 | :host 'html | ||
| 492 | '((style_element | ||
| 493 | (start_tag (tag_name)) | ||
| 494 | (raw_text) @cap)))) | ||
| 495 | 513 | ||
| 496 | ;; jsdoc is not mandatory for js-ts-mode, so we respect this by | 514 | ;; jsdoc is not mandatory for js-ts-mode, so we respect this by |
| 497 | ;; adding jsdoc range rules only when jsdoc is available. | 515 | ;; adding jsdoc range rules only when jsdoc is available. |
| 498 | (when (treesit-ensure-installed 'jsdoc) | 516 | (when (treesit-ensure-installed 'jsdoc) |
| 499 | (setq-local treesit-range-settings | ||
| 500 | (append treesit-range-settings | ||
| 501 | (treesit-range-rules | ||
| 502 | :embed 'jsdoc | ||
| 503 | :host 'javascript | ||
| 504 | :local t | ||
| 505 | `(((comment) @cap | ||
| 506 | (:match ,js--treesit-jsdoc-beginning-regexp @cap)))))) | ||
| 507 | (setq-local c-ts-common--comment-regexp | 517 | (setq-local c-ts-common--comment-regexp |
| 508 | js--treesit-jsdoc-comment-regexp)) | 518 | js--treesit-jsdoc-comment-regexp)) |
| 509 | 519 | ||
| @@ -563,9 +573,7 @@ Powered by tree-sitter." | |||
| 563 | mhtml-ts-mode--treesit-aggregated-simple-imenu-settings) | 573 | mhtml-ts-mode--treesit-aggregated-simple-imenu-settings) |
| 564 | 574 | ||
| 565 | (setq-local treesit-aggregated-outline-predicate | 575 | (setq-local treesit-aggregated-outline-predicate |
| 566 | `((html . ,#'html-ts-mode--outline-predicate) | 576 | mhtml-ts-mode--treesit-aggregated-outline-predicate) |
| 567 | (javascript . ,js-ts-mode--outline-predicate) | ||
| 568 | (css . ,css-ts-mode--outline-predicate))) | ||
| 569 | 577 | ||
| 570 | (treesit-major-mode-setup) | 578 | (treesit-major-mode-setup) |
| 571 | 579 | ||