diff options
| author | Po Lu | 2022-12-11 09:34:03 +0800 |
|---|---|---|
| committer | Po Lu | 2022-12-11 09:34:03 +0800 |
| commit | 6d6ca47aba7b72d2a770d7ed01c849d3cc729e21 (patch) | |
| tree | e8181f7188a3a74147549b7ba76ea9c3a696259c | |
| parent | e08564432918aa87b49da58ac90bb43718424364 (diff) | |
| parent | 44c5f3614973d8dc389ddcdc1b3f8ab1c809194d (diff) | |
| download | emacs-6d6ca47aba7b72d2a770d7ed01c849d3cc729e21.tar.gz emacs-6d6ca47aba7b72d2a770d7ed01c849d3cc729e21.zip | |
Merge from origin/emacs-29
44c5f361497 ; Fix two byte-compiler warnings
a8ee046fb50 Ensure 'package-vc--version' always returns a version
022ab1061b2 Ensure 'package-vc--main-file' always returns an existing...
357fe91996b Check if package already exists before installing from ch...
5e8bc79f6b2 ; Fix reference in docstring to 'package-vc-install-from-...
af88b00b19c Refresh the package quickstart file in package-vc
5a092c8e461 ; * admin/notes/tree-sitter/starter-guide (Indent): Minor...
ebef8905b0d Make indirect buffers use tree-sitter parsers of their ba...
8f53fa10d94 Fontify "this" as a keyword in c++-ts-mode (bug#59924)
8de8f1dc051 Add class_body indentation for typescript (bug#59680)
839341d7370 Make more granular defun-type-regexp (bug#59873)
8f49137c9bf Add dockerfile-ts-mode (Bug#59894)
1014bcc8e32 Fix fontification of method-invocations in js-ts-mode (bu...
7141920c6af Fix escape-sequence feature in typescript-ts-mode (bug#59...
4df35e3491c Improve fontification in csharp-ts-mode (bug#59909)
33a8415eb7e Use 'project--value-in-dir' for 'project-vc-include-untra...
594267395d5 Update Turkish Hello
940d9070e97 Support newer glib versions (Bug#59061)
0bd26abf7fb ; * doc/misc/use-package.texi: Fix @file.
bcf235acd58 Merge branch 'emacs-29' of git.savannah.gnu.org:/srv/git/...
2ea7a357fd1 ; * doc/misc/use-package.texi: Fix @acronym.
d268ab1c5d7 Bring back the project--value-in-dir logic
25 files changed, 413 insertions, 79 deletions
diff --git a/admin/notes/tree-sitter/build-module/batch.sh b/admin/notes/tree-sitter/build-module/batch.sh index d45f37f4b64..6dce000caa6 100755 --- a/admin/notes/tree-sitter/build-module/batch.sh +++ b/admin/notes/tree-sitter/build-module/batch.sh | |||
| @@ -5,6 +5,7 @@ languages=( | |||
| 5 | 'cpp' | 5 | 'cpp' |
| 6 | 'css' | 6 | 'css' |
| 7 | 'c-sharp' | 7 | 'c-sharp' |
| 8 | 'dockerfile' | ||
| 8 | 'go' | 9 | 'go' |
| 9 | 'html' | 10 | 'html' |
| 10 | 'javascript' | 11 | 'javascript' |
diff --git a/admin/notes/tree-sitter/build-module/build.sh b/admin/notes/tree-sitter/build-module/build.sh index d562f1a7846..cc31e3f6f02 100755 --- a/admin/notes/tree-sitter/build-module/build.sh +++ b/admin/notes/tree-sitter/build-module/build.sh | |||
| @@ -14,11 +14,15 @@ echo "Building ${lang}" | |||
| 14 | 14 | ||
| 15 | ### Retrieve sources | 15 | ### Retrieve sources |
| 16 | 16 | ||
| 17 | namespace="tree-sitter" | ||
| 17 | repo="tree-sitter-${lang}" | 18 | repo="tree-sitter-${lang}" |
| 18 | sourcedir="tree-sitter-${lang}/src" | 19 | sourcedir="tree-sitter-${lang}/src" |
| 19 | grammardir="tree-sitter-${lang}" | 20 | grammardir="tree-sitter-${lang}" |
| 20 | 21 | ||
| 21 | case "${lang}" in | 22 | case "${lang}" in |
| 23 | "dockerfile") | ||
| 24 | namespace="camdencheek" | ||
| 25 | ;; | ||
| 22 | "typescript") | 26 | "typescript") |
| 23 | sourcedir="tree-sitter-typescript/typescript/src" | 27 | sourcedir="tree-sitter-typescript/typescript/src" |
| 24 | grammardir="tree-sitter-typescript/typescript" | 28 | grammardir="tree-sitter-typescript/typescript" |
| @@ -30,7 +34,7 @@ case "${lang}" in | |||
| 30 | ;; | 34 | ;; |
| 31 | esac | 35 | esac |
| 32 | 36 | ||
| 33 | git clone "https://github.com/tree-sitter/${repo}.git" \ | 37 | git clone "https://github.com/${namespace}/${repo}.git" \ |
| 34 | --depth 1 --quiet | 38 | --depth 1 --quiet |
| 35 | cp "${grammardir}"/grammar.js "${sourcedir}" | 39 | cp "${grammardir}"/grammar.js "${sourcedir}" |
| 36 | # We have to go into the source directory to compile, because some | 40 | # We have to go into the source directory to compile, because some |
diff --git a/admin/notes/tree-sitter/starter-guide b/admin/notes/tree-sitter/starter-guide index 123dabd9f29..a6a4c647f23 100644 --- a/admin/notes/tree-sitter/starter-guide +++ b/admin/notes/tree-sitter/starter-guide | |||
| @@ -282,7 +282,7 @@ For MATHCER we have | |||
| 282 | NODE-INDEX-MIN NODE-INDEX-MAX) | 282 | NODE-INDEX-MIN NODE-INDEX-MAX) |
| 283 | 283 | ||
| 284 | => checks everything. If an argument is nil, don’t match that. Eg, | 284 | => checks everything. If an argument is nil, don’t match that. Eg, |
| 285 | (match nil nil TYPE) is the same as (parent-is TYPE) | 285 | (match nil TYPE) is the same as (parent-is TYPE) |
| 286 | 286 | ||
| 287 | For ANCHOR we have | 287 | For ANCHOR we have |
| 288 | 288 | ||
diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index 3223875320a..af7be2ebf36 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi | |||
| @@ -409,6 +409,13 @@ Create a parser for the specified @var{buffer} and @var{language} | |||
| 409 | By default, this function reuses a parser if one already exists for | 409 | By default, this function reuses a parser if one already exists for |
| 410 | @var{language} in @var{buffer}, but if @var{no-reuse} is | 410 | @var{language} in @var{buffer}, but if @var{no-reuse} is |
| 411 | non-@code{nil}, this function always creates a new parser. | 411 | non-@code{nil}, this function always creates a new parser. |
| 412 | |||
| 413 | If that buffer is an indirect buffer, its base buffer is used instead. | ||
| 414 | That is, indirect buffers use their base buffer's parsers. If the | ||
| 415 | base buffer is narrowed, an indirect buffer might not be able to | ||
| 416 | retrieve information of the portion of the buffer text that are | ||
| 417 | invisible in the base buffer. Lisp programs should widen as necessary | ||
| 418 | should they want to use a parser in an indirect buffer. | ||
| 412 | @end defun | 419 | @end defun |
| 413 | 420 | ||
| 414 | Given a parser, we can query information about it. | 421 | Given a parser, we can query information about it. |
| @@ -447,7 +454,8 @@ tree incrementally. | |||
| 447 | @defun treesit-parser-list &optional buffer | 454 | @defun treesit-parser-list &optional buffer |
| 448 | This function returns the parser list of @var{buffer}. If | 455 | This function returns the parser list of @var{buffer}. If |
| 449 | @var{buffer} is @code{nil} or omitted, it defaults to the current | 456 | @var{buffer} is @code{nil} or omitted, it defaults to the current |
| 450 | buffer. | 457 | buffer. If that buffer is an indirect buffer, its base buffer is used |
| 458 | instead. That is, indirect buffers use their base buffer's parsers. | ||
| 451 | @end defun | 459 | @end defun |
| 452 | 460 | ||
| 453 | @defun treesit-parser-delete parser | 461 | @defun treesit-parser-delete parser |
diff --git a/doc/misc/use-package.texi b/doc/misc/use-package.texi index daf27ec5bbc..d3b6ee99003 100644 --- a/doc/misc/use-package.texi +++ b/doc/misc/use-package.texi | |||
| @@ -190,7 +190,7 @@ immediately. In most cases, this is not necessary or desirable, as | |||
| 190 | that will slow down Emacs startup. Instead, you should try to set | 190 | that will slow down Emacs startup. Instead, you should try to set |
| 191 | things up so that packages are only loaded when they are actually | 191 | things up so that packages are only loaded when they are actually |
| 192 | needed (a.k.a. ``autoloading''). If you have installed a package from | 192 | needed (a.k.a. ``autoloading''). If you have installed a package from |
| 193 | @acronym{GNU ELPA} that provides it's own autoloads, it is often | 193 | @acronym{GNU} @acronym{ELPA} that provides it's own autoloads, it is often |
| 194 | enough to say: | 194 | enough to say: |
| 195 | 195 | ||
| 196 | @lisp | 196 | @lisp |
| @@ -1273,7 +1273,7 @@ cells, or a string or regexp. | |||
| 1273 | The following example reproduces the default @code{ruby-mode} | 1273 | The following example reproduces the default @code{ruby-mode} |
| 1274 | configuration, exactly as it is in Emacs out-of-the-box. That mode is | 1274 | configuration, exactly as it is in Emacs out-of-the-box. That mode is |
| 1275 | enabled automatically when a file whose name matches the regexp | 1275 | enabled automatically when a file whose name matches the regexp |
| 1276 | @code{"\\.rb\\'"} (a file with the @samp{.rb} extension), or when the | 1276 | @code{"\\.rb\\'"} (a file with the @file{.rb} extension), or when the |
| 1277 | first line of the file (known as the ``shebang'') matches the string | 1277 | first line of the file (known as the ``shebang'') matches the string |
| 1278 | @code{"ruby"}: | 1278 | @code{"ruby"}: |
| 1279 | 1279 | ||
| @@ -114,7 +114,7 @@ Thai (ภาษาไทย) สวัสดีครับ / สวัสดี | |||
| 114 | Tibetan (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎ | 114 | Tibetan (བོད་སྐད་) བཀྲ་ཤིས་བདེ་ལེགས༎ |
| 115 | Tigrigna (ትግርኛ) ሰላማት | 115 | Tigrigna (ትግርኛ) ሰላማት |
| 116 | Tirhuta (𑒞𑒱𑒩𑒯𑒳𑒞𑒰) 𑒣𑓂𑒩𑒢𑒰𑒧 / 𑒮𑒲𑒞𑒰𑒩𑒰𑒧 | 116 | Tirhuta (𑒞𑒱𑒩𑒯𑒳𑒞𑒰) 𑒣𑓂𑒩𑒢𑒰𑒧 / 𑒮𑒲𑒞𑒰𑒩𑒰𑒧 |
| 117 | Turkish (Türkçe) Merhaba | 117 | Turkish (Türkçe) Esenlikler / Merhaba |
| 118 | Ukrainian (українська) Вітаю / Добрий день! / Привіт | 118 | Ukrainian (українська) Вітаю / Добрий день! / Привіт |
| 119 | Vietnamese (tiếng Việt) Chào bạn | 119 | Vietnamese (tiếng Việt) Chào bạn |
| 120 | Wancho (𞋒𞋀𞋉𞋃𞋕) 𞋂𞋈𞋛 | 120 | Wancho (𞋒𞋀𞋉𞋃𞋕) 𞋂𞋈𞋛 |
| @@ -79,6 +79,11 @@ After manually editing 'eshell-aliases-file', you can use | |||
| 79 | 79 | ||
| 80 | * New Modes and Packages in Emacs 30.1 | 80 | * New Modes and Packages in Emacs 30.1 |
| 81 | 81 | ||
| 82 | ** New major mode 'dockerfile-ts-mode'. | ||
| 83 | A major mode based on the tree-sitter library for editing | ||
| 84 | Dockerfiles. It includes support for font-locking, indentation, Imenu, | ||
| 85 | and which-func. | ||
| 86 | |||
| 82 | 87 | ||
| 83 | * Incompatible Lisp Changes in Emacs 30.1 | 88 | * Incompatible Lisp Changes in Emacs 30.1 |
| 84 | 89 | ||
diff --git a/lib-src/seccomp-filter.c b/lib-src/seccomp-filter.c index 7e54b878a22..69b56aed5c5 100644 --- a/lib-src/seccomp-filter.c +++ b/lib-src/seccomp-filter.c | |||
| @@ -342,6 +342,8 @@ main (int argc, char **argv) | |||
| 342 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (eventfd2)); | 342 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (eventfd2)); |
| 343 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (wait4)); | 343 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (wait4)); |
| 344 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (poll)); | 344 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (poll)); |
| 345 | RULE (SCMP_ACT_ALLOW, SCMP_SYS (pidfd_open), | ||
| 346 | SCMP_A1_32 (SCMP_CMP_EQ, 0)); | ||
| 345 | 347 | ||
| 346 | /* Don't allow creating sockets (network access would be extremely | 348 | /* Don't allow creating sockets (network access would be extremely |
| 347 | dangerous), but also don't crash. */ | 349 | dangerous), but also don't crash. */ |
diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el index 299964c6924..db54e0e130e 100644 --- a/lisp/emacs-lisp/package-vc.el +++ b/lisp/emacs-lisp/package-vc.el | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | (eval-when-compile (require 'rx)) | 50 | (eval-when-compile (require 'rx)) |
| 51 | (eval-when-compile (require 'inline)) | 51 | (eval-when-compile (require 'inline)) |
| 52 | (eval-when-compile (require 'map)) | 52 | (eval-when-compile (require 'map)) |
| 53 | (eval-when-compile (require 'cl-lib)) | ||
| 53 | (require 'package) | 54 | (require 'package) |
| 54 | (require 'lisp-mnt) | 55 | (require 'lisp-mnt) |
| 55 | (require 'vc) | 56 | (require 'vc) |
| @@ -293,21 +294,41 @@ asynchronously." | |||
| 293 | (insert-file-contents main-file) | 294 | (insert-file-contents main-file) |
| 294 | (package-strip-rcs-id | 295 | (package-strip-rcs-id |
| 295 | (or (lm-header "package-version") | 296 | (or (lm-header "package-version") |
| 296 | (lm-header "version")))) | 297 | (lm-header "version") |
| 298 | "0"))) | ||
| 297 | "0")) | 299 | "0")) |
| 298 | 300 | ||
| 299 | (defun package-vc--main-file (pkg-desc) | 301 | (defun package-vc--main-file (pkg-desc) |
| 300 | "Return the name of the main file for PKG-DESC." | 302 | "Return the name of the main file for PKG-DESC." |
| 301 | (cl-assert (package-vc-p pkg-desc)) | 303 | (cl-assert (package-vc-p pkg-desc)) |
| 302 | (let ((pkg-spec (package-vc--desc->spec pkg-desc)) | 304 | (let* ((pkg-spec (package-vc--desc->spec pkg-desc)) |
| 303 | (name (symbol-name (package-desc-name pkg-desc)))) | 305 | (name (symbol-name (package-desc-name pkg-desc))) |
| 304 | (or (plist-get pkg-spec :main-file) | 306 | (directory (file-name-concat |
| 305 | (expand-file-name | 307 | (or (package-desc-dir pkg-desc) |
| 306 | (concat name ".el") | 308 | (expand-file-name name package-user-dir)) |
| 307 | (file-name-concat | 309 | (plist-get pkg-spec :lisp-dir))) |
| 308 | (or (package-desc-dir pkg-desc) | 310 | (file (or (plist-get pkg-spec :main-file) |
| 309 | (expand-file-name name package-user-dir)) | 311 | (expand-file-name |
| 310 | (plist-get pkg-spec :lisp-dir)))))) | 312 | (concat name ".el") |
| 313 | directory)))) | ||
| 314 | (if (file-exists-p file) file | ||
| 315 | ;; The following heuristic is only necessary when fetching a | ||
| 316 | ;; repository with URL that would break the above assumptions. | ||
| 317 | ;; Concrete example: https://github.com/sachac/waveform-el does | ||
| 318 | ;; not have a file waveform-el.el, but a file waveform.el, so we | ||
| 319 | ;; try and find the closest match. | ||
| 320 | (let ((distance most-positive-fixnum) (best nil)) | ||
| 321 | (dolist (alt (directory-files directory t "\\.el\\'" t)) | ||
| 322 | (let ((sd (string-distance file alt))) | ||
| 323 | (when (and (not (string-match-p (rx (or (: "-autoloads.el") | ||
| 324 | (: "-pkg.el")) | ||
| 325 | eos) | ||
| 326 | alt)) | ||
| 327 | (< sd distance)) | ||
| 328 | (when (< sd distance) | ||
| 329 | (setq distance (string-distance file alt) | ||
| 330 | best alt))))) | ||
| 331 | best)))) | ||
| 311 | 332 | ||
| 312 | (defun package-vc--generate-description-file (pkg-desc pkg-file) | 333 | (defun package-vc--generate-description-file (pkg-desc pkg-file) |
| 313 | "Generate a package description file for PKG-DESC and write it to PKG-FILE." | 334 | "Generate a package description file for PKG-DESC and write it to PKG-FILE." |
| @@ -466,6 +487,7 @@ documentation and marking the package as installed." | |||
| 466 | (package--save-selected-packages | 487 | (package--save-selected-packages |
| 467 | (cons (package-desc-name pkg-desc) | 488 | (cons (package-desc-name pkg-desc) |
| 468 | package-selected-packages)) | 489 | package-selected-packages)) |
| 490 | (package--quickstart-maybe-refresh) | ||
| 469 | 491 | ||
| 470 | ;; Confirm that the installation was successful | 492 | ;; Confirm that the installation was successful |
| 471 | (let ((main-file (package-vc--main-file pkg-desc))) | 493 | (let ((main-file (package-vc--main-file pkg-desc))) |
| @@ -710,11 +732,11 @@ regular package, but it will not remove a VC package." | |||
| 710 | (defun package-vc-checkout (pkg-desc directory &optional rev) | 732 | (defun package-vc-checkout (pkg-desc directory &optional rev) |
| 711 | "Clone the sources for PKG-DESC into DIRECTORY and visit that directory. | 733 | "Clone the sources for PKG-DESC into DIRECTORY and visit that directory. |
| 712 | Unlike `package-vc-install', this does not yet set up the package | 734 | Unlike `package-vc-install', this does not yet set up the package |
| 713 | for use with Emacs; use `package-vc-link-directory' for setting | 735 | for use with Emacs; use `package-vc-install-from-checkout' for |
| 714 | the package up after this function finishes. | 736 | setting the package up after this function finishes. Optional |
| 715 | Optional argument REV means to clone a specific version of the | 737 | argument REV means to clone a specific version of the package; it |
| 716 | package; it defaults to the last version available from the | 738 | defaults to the last version available from the package's |
| 717 | package's repository. If REV has the special value | 739 | repository. If REV has the special value |
| 718 | `:last-release' (interactively, the prefix argument), that stands | 740 | `:last-release' (interactively, the prefix argument), that stands |
| 719 | for the last released version of the package." | 741 | for the last released version of the package." |
| 720 | (interactive | 742 | (interactive |
| @@ -753,6 +775,10 @@ name from the base name of DIR." | |||
| 753 | (package-vc--archives-initialize) | 775 | (package-vc--archives-initialize) |
| 754 | (let* ((name (or name (file-name-base (directory-file-name dir)))) | 776 | (let* ((name (or name (file-name-base (directory-file-name dir)))) |
| 755 | (pkg-dir (expand-file-name name package-user-dir))) | 777 | (pkg-dir (expand-file-name name package-user-dir))) |
| 778 | (when (file-exists-p pkg-dir) | ||
| 779 | (if (yes-or-no-p (format "Overwrite previous checkout for package `%s'?" name)) | ||
| 780 | (package--delete-directory pkg-dir) | ||
| 781 | (error "There already exists a checkout for %s" name))) | ||
| 756 | (make-symbolic-link (expand-file-name dir) pkg-dir) | 782 | (make-symbolic-link (expand-file-name dir) pkg-dir) |
| 757 | (package-vc--unpack-1 | 783 | (package-vc--unpack-1 |
| 758 | (package-desc-create | 784 | (package-desc-create |
diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el index 1bffdf3513a..f3665c3f1a4 100644 --- a/lisp/gnus/gnus-icalendar.el +++ b/lisp/gnus/gnus-icalendar.el | |||
| @@ -603,7 +603,7 @@ is searched." | |||
| 603 | (when file | 603 | (when file |
| 604 | (switch-to-buffer (find-file file)) | 604 | (switch-to-buffer (find-file file)) |
| 605 | (goto-char (org-find-entry-with-id (gnus-icalendar-event:uid event))) | 605 | (goto-char (org-find-entry-with-id (gnus-icalendar-event:uid event))) |
| 606 | (org-show-entry)))) | 606 | (org-fold-show-entry)))) |
| 607 | 607 | ||
| 608 | 608 | ||
| 609 | (defun gnus-icalendar--update-org-event (event reply-status &optional org-file) | 609 | (defun gnus-icalendar--update-org-event (event reply-status &optional org-file) |
diff --git a/lisp/language/european.el b/lisp/language/european.el index 937215074bc..18b72bd3b2b 100644 --- a/lisp/language/european.el +++ b/lisp/language/european.el | |||
| @@ -585,7 +585,7 @@ and it selects the Spanish tutorial.")) | |||
| 585 | (nonascii-translation . iso-8859-9) | 585 | (nonascii-translation . iso-8859-9) |
| 586 | (unibyte-display . iso-latin-5) | 586 | (unibyte-display . iso-latin-5) |
| 587 | (input-method . "turkish-postfix") | 587 | (input-method . "turkish-postfix") |
| 588 | (sample-text . "Turkish (Türkçe) Merhaba") | 588 | (sample-text . "Turkish (Türkçe) Esenlikler / Merhaba") |
| 589 | (setup-function . turkish-case-conversion-enable) | 589 | (setup-function . turkish-case-conversion-enable) |
| 590 | (exit-function . turkish-case-conversion-disable) | 590 | (exit-function . turkish-case-conversion-disable) |
| 591 | (documentation . "Support for Turkish. | 591 | (documentation . "Support for Turkish. |
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 7b41718a745..824325d83e0 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el | |||
| @@ -234,14 +234,14 @@ MODE is either `c' or `cpp'." | |||
| 234 | (false) @font-lock-constant-face | 234 | (false) @font-lock-constant-face |
| 235 | (null) @font-lock-constant-face | 235 | (null) @font-lock-constant-face |
| 236 | ,@(when (eq mode 'cpp) | 236 | ,@(when (eq mode 'cpp) |
| 237 | '((this) @font-lock-constant-face | 237 | '((nullptr) @font-lock-constant-face))) |
| 238 | (nullptr) @font-lock-constant-face))) | ||
| 239 | 238 | ||
| 240 | :language mode | 239 | :language mode |
| 241 | :feature 'keyword | 240 | :feature 'keyword |
| 242 | `([,@(c-ts-mode--keywords mode)] @font-lock-keyword-face | 241 | `([,@(c-ts-mode--keywords mode)] @font-lock-keyword-face |
| 243 | ,@(when (eq mode 'cpp) | 242 | ,@(when (eq mode 'cpp) |
| 244 | '((auto) @font-lock-keyword-face))) | 243 | '((auto) @font-lock-keyword-face |
| 244 | (this) @font-lock-keyword-face))) | ||
| 245 | 245 | ||
| 246 | :language mode | 246 | :language mode |
| 247 | :feature 'operator | 247 | :feature 'operator |
diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index d0465b26f05..8a7313b1ce8 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el | |||
| @@ -818,7 +818,13 @@ compilation and evaluation time conflicts." | |||
| 818 | 818 | ||
| 819 | :language 'c-sharp | 819 | :language 'c-sharp |
| 820 | :feature 'delimiter | 820 | :feature 'delimiter |
| 821 | '((["," ":" ";"]) @font-lock-delimiter-face))) | 821 | '((["," ":" ";"]) @font-lock-delimiter-face) |
| 822 | |||
| 823 | :language 'c-sharp | ||
| 824 | :feature 'escape-sequence | ||
| 825 | :override t | ||
| 826 | '((escape_sequence) @font-lock-escape-face | ||
| 827 | (ERROR) @font-lock-warning-face))) | ||
| 822 | 828 | ||
| 823 | ;;;###autoload | 829 | ;;;###autoload |
| 824 | (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode)) | 830 | (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode)) |
| @@ -926,7 +932,7 @@ Key bindings: | |||
| 926 | (setq-local treesit-font-lock-settings csharp-ts-mode--font-lock-settings) | 932 | (setq-local treesit-font-lock-settings csharp-ts-mode--font-lock-settings) |
| 927 | (setq-local treesit-font-lock-feature-list | 933 | (setq-local treesit-font-lock-feature-list |
| 928 | '(( comment definition) | 934 | '(( comment definition) |
| 929 | ( keyword string type) | 935 | ( keyword string escape-sequence type) |
| 930 | ( attribute constant expression literal) | 936 | ( attribute constant expression literal) |
| 931 | ( bracket delimiter))) | 937 | ( bracket delimiter))) |
| 932 | 938 | ||
diff --git a/lisp/progmodes/dockerfile-ts-mode.el b/lisp/progmodes/dockerfile-ts-mode.el new file mode 100644 index 00000000000..e08387ad969 --- /dev/null +++ b/lisp/progmodes/dockerfile-ts-mode.el | |||
| @@ -0,0 +1,176 @@ | |||
| 1 | ;;; dockerfile-ts-mode.el --- tree-sitter support for Dockerfiles -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2022 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author : Randy Taylor <dev@rjt.dev> | ||
| 6 | ;; Maintainer : Randy Taylor <dev@rjt.dev> | ||
| 7 | ;; Created : December 2022 | ||
| 8 | ;; Keywords : dockerfile languages tree-sitter | ||
| 9 | |||
| 10 | ;; This file is part of GNU Emacs. | ||
| 11 | |||
| 12 | ;; GNU Emacs is free software: you can redistribute it and/or modify | ||
| 13 | ;; it under the terms of the GNU General Public License as published by | ||
| 14 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 15 | ;; (at your option) any later version. | ||
| 16 | |||
| 17 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | ;; GNU General Public License for more details. | ||
| 21 | |||
| 22 | ;; You should have received a copy of the GNU General Public License | ||
| 23 | ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | ;; | ||
| 27 | |||
| 28 | ;;; Code: | ||
| 29 | |||
| 30 | (require 'treesit) | ||
| 31 | (eval-when-compile (require 'rx)) | ||
| 32 | |||
| 33 | (declare-function treesit-parser-create "treesit.c") | ||
| 34 | (declare-function treesit-induce-sparse-tree "treesit.c") | ||
| 35 | (declare-function treesit-node-child "treesit.c") | ||
| 36 | (declare-function treesit-node-start "treesit.c") | ||
| 37 | (declare-function treesit-node-type "treesit.c") | ||
| 38 | |||
| 39 | (defvar dockerfile-ts-mode--syntax-table | ||
| 40 | (let ((table (make-syntax-table))) | ||
| 41 | (modify-syntax-entry ?# "<" table) | ||
| 42 | (modify-syntax-entry ?\n ">" table) | ||
| 43 | table) | ||
| 44 | "Syntax table for `dockerfile-ts-mode'.") | ||
| 45 | |||
| 46 | (defvar dockerfile-ts-mode--indent-rules | ||
| 47 | `((dockerfile | ||
| 48 | ((parent-is "copy_instruction") (nth-sibling 1) 0) | ||
| 49 | ((parent-is "env_instruction") (nth-sibling 1) 0) | ||
| 50 | ((parent-is "expose_instruction") (nth-sibling 1) 0) | ||
| 51 | ((parent-is "label_instruction") (nth-sibling 1) 0) | ||
| 52 | ((parent-is "shell_command") first-sibling 0) | ||
| 53 | ((parent-is "string_array") first-sibling 1))) | ||
| 54 | "Tree-sitter indent rules.") | ||
| 55 | |||
| 56 | (defvar dockerfile-ts-mode--keywords | ||
| 57 | '("ADD" "ARG" "AS" "CMD" "COPY" "CROSS_BUILD" "ENTRYPOINT" "ENV" | ||
| 58 | "EXPOSE" "FROM" "HEALTHCHECK" "LABEL" "MAINTAINER" "ONBUILD" "RUN" | ||
| 59 | "SHELL" "STOPSIGNAL" "USER" "VOLUME" "WORKDIR") | ||
| 60 | "Dockerfile keywords for tree-sitter font-locking.") | ||
| 61 | |||
| 62 | (defvar dockerfile-ts-mode--font-lock-settings | ||
| 63 | (treesit-font-lock-rules | ||
| 64 | :language 'dockerfile | ||
| 65 | :feature 'bracket | ||
| 66 | '((["[" "]"]) @font-lock-bracket-face) | ||
| 67 | |||
| 68 | :language 'dockerfile | ||
| 69 | :feature 'comment | ||
| 70 | '((comment) @font-lock-comment-face) | ||
| 71 | |||
| 72 | :language 'dockerfile | ||
| 73 | :feature 'delimiter | ||
| 74 | '(([","]) @font-lock-delimiter-face) | ||
| 75 | |||
| 76 | :language 'dockerfile | ||
| 77 | :feature 'image-spec | ||
| 78 | '((image_spec) @font-lock-constant-face) | ||
| 79 | |||
| 80 | :language 'dockerfile | ||
| 81 | :feature 'keyword | ||
| 82 | `([,@dockerfile-ts-mode--keywords] @font-lock-keyword-face) | ||
| 83 | |||
| 84 | :language 'dockerfile | ||
| 85 | :feature 'number | ||
| 86 | '((expose_port) @font-lock-number-face) | ||
| 87 | |||
| 88 | :language 'dockerfile | ||
| 89 | :feature 'operator | ||
| 90 | '((["="]) @font-lock-operator-face) | ||
| 91 | |||
| 92 | :language 'dockerfile | ||
| 93 | :feature 'string | ||
| 94 | '((double_quoted_string) @font-lock-string-face) | ||
| 95 | |||
| 96 | :language 'dockerfile | ||
| 97 | :feature 'error | ||
| 98 | :override t | ||
| 99 | '((ERROR) @font-lock-warning-face)) | ||
| 100 | "Tree-sitter font-lock settings.") | ||
| 101 | |||
| 102 | (defun dockerfile-ts-mode--imenu () | ||
| 103 | "Return Imenu alist for the current buffer." | ||
| 104 | (let* ((node (treesit-buffer-root-node)) | ||
| 105 | (stage-tree (treesit-induce-sparse-tree | ||
| 106 | node "from_instruction" | ||
| 107 | nil 1000))) | ||
| 108 | `(("Stage" . ,(dockerfile-ts-mode--imenu-1 stage-tree))))) | ||
| 109 | |||
| 110 | (defun dockerfile-ts-mode--imenu-1 (node) | ||
| 111 | "Helper for `dockerfile-ts-mode--imenu'. | ||
| 112 | Find string representation for NODE and set marker, then recurse | ||
| 113 | the subtrees." | ||
| 114 | (let* ((ts-node (car node)) | ||
| 115 | (children (cdr node)) | ||
| 116 | (subtrees (mapcan #'dockerfile-ts-mode--imenu-1 | ||
| 117 | children)) | ||
| 118 | (name (when ts-node | ||
| 119 | (pcase (treesit-node-type ts-node) | ||
| 120 | ("from_instruction" (treesit-node-text | ||
| 121 | (treesit-node-child ts-node 1) t))))) | ||
| 122 | (marker (when ts-node | ||
| 123 | (set-marker (make-marker) | ||
| 124 | (treesit-node-start ts-node))))) | ||
| 125 | (cond | ||
| 126 | ((or (null ts-node) (null name)) subtrees) | ||
| 127 | (subtrees | ||
| 128 | `((,name ,(cons name marker) ,@subtrees))) | ||
| 129 | (t | ||
| 130 | `((,name . ,marker)))))) | ||
| 131 | |||
| 132 | ;;;###autoload | ||
| 133 | (add-to-list 'auto-mode-alist | ||
| 134 | `(,(rx (| | ||
| 135 | (: "Dockerfile" (? "." (* nonl))) | ||
| 136 | (: "." (any "dD") "ockerfile")) | ||
| 137 | eol) | ||
| 138 | . dockerfile-ts-mode)) | ||
| 139 | |||
| 140 | ;;;###autoload | ||
| 141 | (define-derived-mode dockerfile-ts-mode prog-mode "Dockerfile" | ||
| 142 | "Major mode for editing Dockerfiles, powered by tree-sitter." | ||
| 143 | :group 'dockerfile | ||
| 144 | :syntax-table dockerfile-ts-mode--syntax-table | ||
| 145 | |||
| 146 | (when (treesit-ready-p 'dockerfile) | ||
| 147 | (treesit-parser-create 'dockerfile) | ||
| 148 | |||
| 149 | ;; Comments. | ||
| 150 | (setq-local comment-start "# ") | ||
| 151 | (setq-local comment-end "") | ||
| 152 | (setq-local comment-start-skip (rx "#" (* (syntax whitespace)))) | ||
| 153 | |||
| 154 | ;; Imenu. | ||
| 155 | (setq-local imenu-create-index-function | ||
| 156 | #'dockerfile-ts-mode--imenu) | ||
| 157 | (setq-local which-func-functions nil) | ||
| 158 | |||
| 159 | ;; Indent. | ||
| 160 | (setq-local treesit-simple-indent-rules | ||
| 161 | dockerfile-ts-mode--indent-rules) | ||
| 162 | |||
| 163 | ;; Font-lock. | ||
| 164 | (setq-local treesit-font-lock-settings | ||
| 165 | dockerfile-ts-mode--font-lock-settings) | ||
| 166 | (setq-local treesit-font-lock-feature-list | ||
| 167 | '((comment) | ||
| 168 | (keyword string) | ||
| 169 | (image-spec number) | ||
| 170 | (bracket delimiter error operator))) | ||
| 171 | |||
| 172 | (treesit-major-mode-setup))) | ||
| 173 | |||
| 174 | (provide 'dockerfile-ts-mode) | ||
| 175 | |||
| 176 | ;;; dockerfile-ts-mode.el ends here | ||
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index a53f62fc565..2ef022992e7 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -236,7 +236,7 @@ chosen (interactively or automatically)." | |||
| 236 | . ,(eglot-alternatives '(("vscode-css-language-server" "--stdio") | 236 | . ,(eglot-alternatives '(("vscode-css-language-server" "--stdio") |
| 237 | ("css-languageserver" "--stdio")))) | 237 | ("css-languageserver" "--stdio")))) |
| 238 | (html-mode . ,(eglot-alternatives '(("vscode-html-language-server" "--stdio") ("html-languageserver" "--stdio")))) | 238 | (html-mode . ,(eglot-alternatives '(("vscode-html-language-server" "--stdio") ("html-languageserver" "--stdio")))) |
| 239 | (dockerfile-mode . ("docker-langserver" "--stdio")) | 239 | ((dockerfile-mode dockerfile-ts-mode) . ("docker-langserver" "--stdio")) |
| 240 | ((clojure-mode clojurescript-mode clojurec-mode) | 240 | ((clojure-mode clojurescript-mode clojurec-mode) |
| 241 | . ("clojure-lsp")) | 241 | . ("clojure-lsp")) |
| 242 | ((csharp-mode csharp-ts-mode) | 242 | ((csharp-mode csharp-ts-mode) |
diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index 23e166ee4c3..9155a7fff25 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el | |||
| @@ -321,7 +321,15 @@ the subtrees." | |||
| 321 | (append "{}():;," electric-indent-chars)) | 321 | (append "{}():;," electric-indent-chars)) |
| 322 | 322 | ||
| 323 | ;; Navigation. | 323 | ;; Navigation. |
| 324 | (setq-local treesit-defun-type-regexp "declaration") | 324 | (setq-local treesit-defun-type-regexp |
| 325 | (regexp-opt '("method_declaration" | ||
| 326 | "class_declaration" | ||
| 327 | "record_declaration" | ||
| 328 | "interface_declaration" | ||
| 329 | "enum_declaration" | ||
| 330 | "import_declaration" | ||
| 331 | "package_declaration" | ||
| 332 | "module_declaration"))) | ||
| 325 | 333 | ||
| 326 | ;; Font-lock. | 334 | ;; Font-lock. |
| 327 | (setq-local treesit-font-lock-settings java-ts-mode--font-lock-settings) | 335 | (setq-local treesit-font-lock-settings java-ts-mode--font-lock-settings) |
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 45dfef372cd..f7318c481a2 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el | |||
| @@ -3545,6 +3545,20 @@ This function is intended for use in `after-change-functions'." | |||
| 3545 | 3545 | ||
| 3546 | :language 'javascript | 3546 | :language 'javascript |
| 3547 | :override t | 3547 | :override t |
| 3548 | :feature 'property | ||
| 3549 | ;; This needs to be before function-name feature, because methods | ||
| 3550 | ;; can be both property and function-name, and we want them in | ||
| 3551 | ;; function-name face. | ||
| 3552 | `((property_identifier) @font-lock-property-face | ||
| 3553 | |||
| 3554 | (pair value: (identifier) @font-lock-variable-name-face) | ||
| 3555 | |||
| 3556 | ((shorthand_property_identifier) @font-lock-property-face) | ||
| 3557 | |||
| 3558 | ((shorthand_property_identifier_pattern) @font-lock-property-face)) | ||
| 3559 | |||
| 3560 | :language 'javascript | ||
| 3561 | :override t | ||
| 3548 | :feature 'expression | 3562 | :feature 'expression |
| 3549 | `((assignment_expression | 3563 | `((assignment_expression |
| 3550 | left: [(identifier) @font-lock-function-name-face | 3564 | left: [(identifier) @font-lock-function-name-face |
| @@ -3611,18 +3625,7 @@ This function is intended for use in `after-change-functions'." | |||
| 3611 | :language 'javascript | 3625 | :language 'javascript |
| 3612 | :feature 'escape-sequence | 3626 | :feature 'escape-sequence |
| 3613 | :override t | 3627 | :override t |
| 3614 | '((escape_sequence) @font-lock-escape-face) | 3628 | '((escape_sequence) @font-lock-escape-face)) |
| 3615 | |||
| 3616 | :language 'javascript | ||
| 3617 | :override t | ||
| 3618 | :feature 'property | ||
| 3619 | `((property_identifier) @font-lock-property-face | ||
| 3620 | |||
| 3621 | (pair value: (identifier) @font-lock-variable-name-face) | ||
| 3622 | |||
| 3623 | ((shorthand_property_identifier) @font-lock-property-face) | ||
| 3624 | |||
| 3625 | ((shorthand_property_identifier_pattern) @font-lock-property-face))) | ||
| 3626 | "Tree-sitter font-lock settings.") | 3629 | "Tree-sitter font-lock settings.") |
| 3627 | 3630 | ||
| 3628 | (defun js--fontify-template-string (node override start end &rest _) | 3631 | (defun js--fontify-template-string (node override start end &rest _) |
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 38d4fdad5fc..016dfdd5b4d 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el | |||
| @@ -515,7 +515,8 @@ project backend implementation of `project-external-roots'.") | |||
| 515 | (marker-re | 515 | (marker-re |
| 516 | (mapconcat | 516 | (mapconcat |
| 517 | (lambda (m) (format "\\(%s\\)" (wildcard-to-regexp m))) | 517 | (lambda (m) (format "\\(%s\\)" (wildcard-to-regexp m))) |
| 518 | (append backend-markers project-vc-extra-root-markers) | 518 | (append backend-markers |
| 519 | (project--value-in-dir 'project-vc-extra-root-markers dir)) | ||
| 519 | "\\|")) | 520 | "\\|")) |
| 520 | (locate-dominating-stop-dir-regexp | 521 | (locate-dominating-stop-dir-regexp |
| 521 | (or vc-ignore-dir-regexp locate-dominating-stop-dir-regexp)) | 522 | (or vc-ignore-dir-regexp locate-dominating-stop-dir-regexp)) |
| @@ -535,7 +536,7 @@ project backend implementation of `project-external-roots'.") | |||
| 535 | project) | 536 | project) |
| 536 | (when (and | 537 | (when (and |
| 537 | (eq backend 'Git) | 538 | (eq backend 'Git) |
| 538 | project-vc-merge-submodules | 539 | (project--vc-merge-submodules-p root) |
| 539 | (project--submodule-p root)) | 540 | (project--submodule-p root)) |
| 540 | (let* ((parent (file-name-directory (directory-file-name root)))) | 541 | (let* ((parent (file-name-directory (directory-file-name root)))) |
| 541 | (setq root (vc-call-backend 'Git 'root parent)))) | 542 | (setq root (vc-call-backend 'Git 'root parent)))) |
| @@ -582,7 +583,7 @@ project backend implementation of `project-external-roots'.") | |||
| 582 | (cl-defmethod project-files ((project (head vc)) &optional dirs) | 583 | (cl-defmethod project-files ((project (head vc)) &optional dirs) |
| 583 | (mapcan | 584 | (mapcan |
| 584 | (lambda (dir) | 585 | (lambda (dir) |
| 585 | (let ((ignores project-vc-ignores) | 586 | (let ((ignores (project--value-in-dir 'project-vc-ignores (nth 2 project))) |
| 586 | (backend (cadr project))) | 587 | (backend (cadr project))) |
| 587 | (when backend | 588 | (when backend |
| 588 | (require (intern (concat "vc-" (downcase (symbol-name backend)))))) | 589 | (require (intern (concat "vc-" (downcase (symbol-name backend)))))) |
| @@ -608,13 +609,16 @@ project backend implementation of `project-external-roots'.") | |||
| 608 | (defvar vc-git-use-literal-pathspecs) | 609 | (defvar vc-git-use-literal-pathspecs) |
| 609 | (pcase backend | 610 | (pcase backend |
| 610 | (`Git | 611 | (`Git |
| 611 | (let ((default-directory (expand-file-name (file-name-as-directory dir))) | 612 | (let* ((default-directory (expand-file-name (file-name-as-directory dir))) |
| 612 | (args '("-z")) | 613 | (args '("-z")) |
| 613 | (vc-git-use-literal-pathspecs nil) | 614 | (vc-git-use-literal-pathspecs nil) |
| 614 | files) | 615 | (include-untracked (project--value-in-dir |
| 616 | 'project-vc-include-untracked | ||
| 617 | dir)) | ||
| 618 | files) | ||
| 615 | (setq args (append args | 619 | (setq args (append args |
| 616 | '("-c" "--exclude-standard") | 620 | '("-c" "--exclude-standard") |
| 617 | (and project-vc-include-untracked '("-o")))) | 621 | (and include-untracked '("-o")))) |
| 618 | (when extra-ignores | 622 | (when extra-ignores |
| 619 | (setq args (append args | 623 | (setq args (append args |
| 620 | (cons "--" | 624 | (cons "--" |
| @@ -647,7 +651,7 @@ project backend implementation of `project-external-roots'.") | |||
| 647 | (split-string | 651 | (split-string |
| 648 | (apply #'vc-git--run-command-string nil "ls-files" args) | 652 | (apply #'vc-git--run-command-string nil "ls-files" args) |
| 649 | "\0" t))) | 653 | "\0" t))) |
| 650 | (when project-vc-merge-submodules | 654 | (when (project--vc-merge-submodules-p default-directory) |
| 651 | ;; Unfortunately, 'ls-files --recurse-submodules' conflicts with '-o'. | 655 | ;; Unfortunately, 'ls-files --recurse-submodules' conflicts with '-o'. |
| 652 | (let* ((submodules (project--git-submodules)) | 656 | (let* ((submodules (project--git-submodules)) |
| 653 | (sub-files | 657 | (sub-files |
| @@ -665,10 +669,13 @@ project backend implementation of `project-external-roots'.") | |||
| 665 | ;; XXX: Better solutions welcome, but this seems cheap enough. | 669 | ;; XXX: Better solutions welcome, but this seems cheap enough. |
| 666 | (delete-consecutive-dups files))) | 670 | (delete-consecutive-dups files))) |
| 667 | (`Hg | 671 | (`Hg |
| 668 | (let ((default-directory (expand-file-name (file-name-as-directory dir))) | 672 | (let* ((default-directory (expand-file-name (file-name-as-directory dir))) |
| 669 | (args (list (concat "-mcard" (and project-vc-include-untracked "u")) | 673 | (include-untracked (project--value-in-dir |
| 670 | "--no-status" | 674 | 'project-vc-include-untracked |
| 671 | "-0"))) | 675 | dir)) |
| 676 | (args (list (concat "-mcard" (and include-untracked "u")) | ||
| 677 | "--no-status" | ||
| 678 | "-0"))) | ||
| 672 | (when extra-ignores | 679 | (when extra-ignores |
| 673 | (setq args (nconc args | 680 | (setq args (nconc args |
| 674 | (mapcan | 681 | (mapcan |
| @@ -681,6 +688,11 @@ project backend implementation of `project-external-roots'.") | |||
| 681 | (lambda (s) (concat default-directory s)) | 688 | (lambda (s) (concat default-directory s)) |
| 682 | (split-string (buffer-string) "\0" t))))))) | 689 | (split-string (buffer-string) "\0" t))))))) |
| 683 | 690 | ||
| 691 | (defun project--vc-merge-submodules-p (dir) | ||
| 692 | (project--value-in-dir | ||
| 693 | 'project-vc-merge-submodules | ||
| 694 | dir)) | ||
| 695 | |||
| 684 | (defun project--git-submodules () | 696 | (defun project--git-submodules () |
| 685 | ;; 'git submodule foreach' is much slower. | 697 | ;; 'git submodule foreach' is much slower. |
| 686 | (condition-case nil | 698 | (condition-case nil |
| @@ -722,7 +734,7 @@ project backend implementation of `project-external-roots'.") | |||
| 722 | (condition-case nil | 734 | (condition-case nil |
| 723 | (vc-call-backend backend 'ignore-completion-table root) | 735 | (vc-call-backend backend 'ignore-completion-table root) |
| 724 | (vc-not-supported () nil))))) | 736 | (vc-not-supported () nil))))) |
| 725 | project-vc-ignores | 737 | (project--value-in-dir 'project-vc-ignores root) |
| 726 | (mapcar | 738 | (mapcar |
| 727 | (lambda (dir) | 739 | (lambda (dir) |
| 728 | (concat dir "/")) | 740 | (concat dir "/")) |
| @@ -753,9 +765,16 @@ DIRS must contain directory names." | |||
| 753 | ;; Sidestep the issue of expanded/abbreviated file names here. | 765 | ;; Sidestep the issue of expanded/abbreviated file names here. |
| 754 | (cl-set-difference files dirs :test #'file-in-directory-p)) | 766 | (cl-set-difference files dirs :test #'file-in-directory-p)) |
| 755 | 767 | ||
| 768 | (defun project--value-in-dir (var dir) | ||
| 769 | (with-temp-buffer | ||
| 770 | (setq default-directory dir) | ||
| 771 | (let ((enable-local-variables :all)) | ||
| 772 | (hack-dir-local-variables-non-file-buffer)) | ||
| 773 | (symbol-value var))) | ||
| 774 | |||
| 756 | (cl-defmethod project-buffers ((project (head vc))) | 775 | (cl-defmethod project-buffers ((project (head vc))) |
| 757 | (let* ((root (expand-file-name (file-name-as-directory (project-root project)))) | 776 | (let* ((root (expand-file-name (file-name-as-directory (project-root project)))) |
| 758 | (modules (unless (or project-vc-merge-submodules | 777 | (modules (unless (or (project--vc-merge-submodules-p root) |
| 759 | (project--submodule-p root)) | 778 | (project--submodule-p root)) |
| 760 | (mapcar | 779 | (mapcar |
| 761 | (lambda (m) (format "%s%s/" root m)) | 780 | (lambda (m) (format "%s%s/" root m)) |
diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index 243f6146ae7..8c4364ecc5b 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el | |||
| @@ -89,6 +89,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." | |||
| 89 | ((parent-is "object") parent-bol typescript-ts-mode-indent-offset) | 89 | ((parent-is "object") parent-bol typescript-ts-mode-indent-offset) |
| 90 | ((parent-is "object_type") parent-bol typescript-ts-mode-indent-offset) | 90 | ((parent-is "object_type") parent-bol typescript-ts-mode-indent-offset) |
| 91 | ((parent-is "enum_body") parent-bol typescript-ts-mode-indent-offset) | 91 | ((parent-is "enum_body") parent-bol typescript-ts-mode-indent-offset) |
| 92 | ((parent-is "class_body") parent-bol typescript-ts-mode-indent-offset) | ||
| 92 | ((parent-is "arrow_function") parent-bol typescript-ts-mode-indent-offset) | 93 | ((parent-is "arrow_function") parent-bol typescript-ts-mode-indent-offset) |
| 93 | ((parent-is "parenthesized_expression") parent-bol typescript-ts-mode-indent-offset) | 94 | ((parent-is "parenthesized_expression") parent-bol typescript-ts-mode-indent-offset) |
| 94 | 95 | ||
| @@ -361,8 +362,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." | |||
| 361 | (setq-local treesit-font-lock-settings | 362 | (setq-local treesit-font-lock-settings |
| 362 | (typescript-ts-mode--font-lock-settings 'typescript)) | 363 | (typescript-ts-mode--font-lock-settings 'typescript)) |
| 363 | (setq-local treesit-font-lock-feature-list | 364 | (setq-local treesit-font-lock-feature-list |
| 364 | '((comment declaration) | 365 | '((comment declaration keyword string escape-sequence) |
| 365 | (keyword string) | ||
| 366 | (constant expression identifier number pattern property) | 366 | (constant expression identifier number pattern property) |
| 367 | (bracket delimiter))) | 367 | (bracket delimiter))) |
| 368 | 368 | ||
| @@ -396,8 +396,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." | |||
| 396 | (setq-local treesit-font-lock-settings | 396 | (setq-local treesit-font-lock-settings |
| 397 | (typescript-ts-mode--font-lock-settings 'tsx)) | 397 | (typescript-ts-mode--font-lock-settings 'tsx)) |
| 398 | (setq-local treesit-font-lock-feature-list | 398 | (setq-local treesit-font-lock-feature-list |
| 399 | '((comment declaration) | 399 | '((comment declaration keyword string escape-sequence) |
| 400 | (keyword string) | ||
| 401 | (constant expression identifier jsx number pattern property) | 400 | (constant expression identifier jsx number pattern property) |
| 402 | (bracket delimiter))) | 401 | (bracket delimiter))) |
| 403 | 402 | ||
diff --git a/src/treesit.c b/src/treesit.c index 8b485ca4ece..d361a3da932 100644 --- a/src/treesit.c +++ b/src/treesit.c | |||
| @@ -384,7 +384,18 @@ init_treesit_functions (void) | |||
| 384 | mysteriously drops. 3) what if a user uses so many stuff that the | 384 | mysteriously drops. 3) what if a user uses so many stuff that the |
| 385 | default cache size (20) is not enough and we end up thrashing? | 385 | default cache size (20) is not enough and we end up thrashing? |
| 386 | These are all imaginary scenarios but they are not impossible | 386 | These are all imaginary scenarios but they are not impossible |
| 387 | :-) */ | 387 | :-) |
| 388 | |||
| 389 | Parsers in indirect buffers: We make indirect buffers to share the | ||
| 390 | parser of its base buffer. Indirect buffers and their base buffer | ||
| 391 | share the same buffer content but not other buffer attributes. If | ||
| 392 | they have separate parser lists, changes made in an indirect buffer | ||
| 393 | will only update parsers of that indirect buffer, and not parsers | ||
| 394 | in the base buffer or other indirect buffers, and vice versa. We | ||
| 395 | could keep track of all the base and indirect buffers, and update | ||
| 396 | all of their parsers, but ultimately decide to take a simpler | ||
| 397 | approach, which is to make indirect buffers share their base | ||
| 398 | buffer's parser list. The discussion can be found in bug#59693. */ | ||
| 388 | 399 | ||
| 389 | 400 | ||
| 390 | /*** Initialization */ | 401 | /*** Initialization */ |
| @@ -697,9 +708,10 @@ void | |||
| 697 | treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, | 708 | treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, |
| 698 | ptrdiff_t new_end_byte) | 709 | ptrdiff_t new_end_byte) |
| 699 | { | 710 | { |
| 700 | Lisp_Object parser_list; | 711 | struct buffer *base_buffer = current_buffer; |
| 701 | 712 | if (current_buffer->base_buffer) | |
| 702 | parser_list = BVAR (current_buffer, ts_parser_list); | 713 | base_buffer = current_buffer->base_buffer; |
| 714 | Lisp_Object parser_list = BVAR (base_buffer, ts_parser_list); | ||
| 703 | 715 | ||
| 704 | FOR_EACH_TAIL_SAFE (parser_list) | 716 | FOR_EACH_TAIL_SAFE (parser_list) |
| 705 | { | 717 | { |
| @@ -1252,12 +1264,16 @@ DEFUN ("treesit-parser-create", | |||
| 1252 | 1, 3, 0, | 1264 | 1, 3, 0, |
| 1253 | doc: /* Create and return a parser in BUFFER for LANGUAGE. | 1265 | doc: /* Create and return a parser in BUFFER for LANGUAGE. |
| 1254 | 1266 | ||
| 1255 | The parser is automatically added to BUFFER's parser list, as | 1267 | The parser is automatically added to BUFFER's parser list, as returned |
| 1256 | returned by `treesit-parser-list'. | 1268 | by `treesit-parser-list'. LANGUAGE is a language symbol. If BUFFER |
| 1257 | LANGUAGE is a language symbol. If BUFFER is nil or omitted, it | 1269 | is nil or omitted, it defaults to the current buffer. If BUFFER |
| 1258 | defaults to the current buffer. If BUFFER already has a parser for | 1270 | already has a parser for LANGUAGE, return that parser, but if NO-REUSE |
| 1259 | LANGUAGE, return that parser, but if NO-REUSE is non-nil, always | 1271 | is non-nil, always create a new parser. |
| 1260 | create a new parser. */) | 1272 | |
| 1273 | If that buffer is an indirect buffer, its base buffer is used instead. | ||
| 1274 | That is, indirect buffers use their base buffer's parsers. Lisp | ||
| 1275 | programs should widen as necessary should they want to use a parser in | ||
| 1276 | an indirect buffer. */) | ||
| 1261 | (Lisp_Object language, Lisp_Object buffer, Lisp_Object no_reuse) | 1277 | (Lisp_Object language, Lisp_Object buffer, Lisp_Object no_reuse) |
| 1262 | { | 1278 | { |
| 1263 | treesit_initialize (); | 1279 | treesit_initialize (); |
| @@ -1271,16 +1287,21 @@ create a new parser. */) | |||
| 1271 | CHECK_BUFFER (buffer); | 1287 | CHECK_BUFFER (buffer); |
| 1272 | buf = XBUFFER (buffer); | 1288 | buf = XBUFFER (buffer); |
| 1273 | } | 1289 | } |
| 1290 | if (buf->base_buffer) | ||
| 1291 | buf = buf->base_buffer; | ||
| 1292 | |||
| 1274 | treesit_check_buffer_size (buf); | 1293 | treesit_check_buffer_size (buf); |
| 1275 | 1294 | ||
| 1276 | /* See if we can reuse a parser. */ | 1295 | /* See if we can reuse a parser. */ |
| 1277 | for (Lisp_Object tail = BVAR (buf, ts_parser_list); | 1296 | if (NILP (no_reuse)) |
| 1278 | NILP (no_reuse) && !NILP (tail); | ||
| 1279 | tail = XCDR (tail)) | ||
| 1280 | { | 1297 | { |
| 1281 | struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail)); | 1298 | Lisp_Object tail = BVAR (buf, ts_parser_list); |
| 1282 | if (EQ (parser->language_symbol, language)) | 1299 | FOR_EACH_TAIL (tail) |
| 1283 | return XCAR (tail); | 1300 | { |
| 1301 | struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail)); | ||
| 1302 | if (EQ (parser->language_symbol, language)) | ||
| 1303 | return XCAR (tail); | ||
| 1304 | } | ||
| 1284 | } | 1305 | } |
| 1285 | 1306 | ||
| 1286 | /* Load language. */ | 1307 | /* Load language. */ |
| @@ -1329,7 +1350,10 @@ DEFUN ("treesit-parser-list", | |||
| 1329 | Ftreesit_parser_list, Streesit_parser_list, | 1350 | Ftreesit_parser_list, Streesit_parser_list, |
| 1330 | 0, 1, 0, | 1351 | 0, 1, 0, |
| 1331 | doc: /* Return BUFFER's parser list. | 1352 | doc: /* Return BUFFER's parser list. |
| 1332 | BUFFER defaults to the current buffer. */) | 1353 | |
| 1354 | BUFFER defaults to the current buffer. If that buffer is an indirect | ||
| 1355 | buffer, its base buffer is used instead. That is, indirect buffers | ||
| 1356 | use their base buffer's parsers. */) | ||
| 1333 | (Lisp_Object buffer) | 1357 | (Lisp_Object buffer) |
| 1334 | { | 1358 | { |
| 1335 | struct buffer *buf; | 1359 | struct buffer *buf; |
| @@ -1340,6 +1364,9 @@ BUFFER defaults to the current buffer. */) | |||
| 1340 | CHECK_BUFFER (buffer); | 1364 | CHECK_BUFFER (buffer); |
| 1341 | buf = XBUFFER (buffer); | 1365 | buf = XBUFFER (buffer); |
| 1342 | } | 1366 | } |
| 1367 | if (buf->base_buffer) | ||
| 1368 | buf = buf->base_buffer; | ||
| 1369 | |||
| 1343 | /* Return a fresh list so messing with that list doesn't affect our | 1370 | /* Return a fresh list so messing with that list doesn't affect our |
| 1344 | internal data. */ | 1371 | internal data. */ |
| 1345 | Lisp_Object return_list = Qnil; | 1372 | Lisp_Object return_list = Qnil; |
diff --git a/test/lisp/progmodes/project-resources/.dir-locals.el b/test/lisp/progmodes/project-resources/.dir-locals.el new file mode 100644 index 00000000000..a311b7efa9a --- /dev/null +++ b/test/lisp/progmodes/project-resources/.dir-locals.el | |||
| @@ -0,0 +1 @@ | |||
| ((nil . ((project-vc-ignores . ("etc"))))) | |||
diff --git a/test/lisp/progmodes/project-resources/etc b/test/lisp/progmodes/project-resources/etc new file mode 100644 index 00000000000..dd7999bd3dd --- /dev/null +++ b/test/lisp/progmodes/project-resources/etc | |||
| @@ -0,0 +1 @@ | |||
| etc \ No newline at end of file | |||
diff --git a/test/lisp/progmodes/project-resources/foo b/test/lisp/progmodes/project-resources/foo new file mode 100644 index 00000000000..19102815663 --- /dev/null +++ b/test/lisp/progmodes/project-resources/foo | |||
| @@ -0,0 +1 @@ | |||
| foo \ No newline at end of file | |||
diff --git a/test/lisp/progmodes/project-tests.el b/test/lisp/progmodes/project-tests.el index c3b886873d3..8814f30b047 100644 --- a/test/lisp/progmodes/project-tests.el +++ b/test/lisp/progmodes/project-tests.el | |||
| @@ -41,7 +41,7 @@ quoted directory names (Bug#47799)." | |||
| 41 | (skip-unless (executable-find "grep")) | 41 | (skip-unless (executable-find "grep")) |
| 42 | (ert-with-temp-directory directory | 42 | (ert-with-temp-directory directory |
| 43 | (let ((default-directory directory) | 43 | (let ((default-directory directory) |
| 44 | (project-current-inhibit-prompt t) | 44 | (project-current-directory-override t) |
| 45 | (project-find-functions nil) | 45 | (project-find-functions nil) |
| 46 | (project-list-file | 46 | (project-list-file |
| 47 | (expand-file-name "projects" directory)) | 47 | (expand-file-name "projects" directory)) |
| @@ -139,4 +139,17 @@ When `project-ignores' includes a name matching project dir." | |||
| 139 | (should-not (null project)) | 139 | (should-not (null project)) |
| 140 | (should (string-match-p "/test/lisp/\\'" (project-root project))))) | 140 | (should (string-match-p "/test/lisp/\\'" (project-root project))))) |
| 141 | 141 | ||
| 142 | (ert-deftest project-vc-supports-project-in-different-dir () | ||
| 143 | "Check that it picks up dir-locals settings from somewhere else." | ||
| 144 | (skip-unless (eq (vc-responsible-backend default-directory) 'Git)) | ||
| 145 | (let* ((dir (ert-resource-directory)) | ||
| 146 | (_ (vc-file-clearprops dir)) | ||
| 147 | (project-vc-extra-root-markers '(".dir-locals.el")) | ||
| 148 | (project (project-current nil dir))) | ||
| 149 | (should-not (null project)) | ||
| 150 | (should (string-match-p "/test/lisp/progmodes/project-resources/\\'" (project-root project))) | ||
| 151 | (should (member "etc" (project-ignores project dir))) | ||
| 152 | (should (equal '(".dir-locals.el" "foo") | ||
| 153 | (mapcar #'file-name-nondirectory (project-files project)))))) | ||
| 154 | |||
| 142 | ;;; project-tests.el ends here | 155 | ;;; project-tests.el ends here |
diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el index aba12759c34..1cc2217bd3b 100644 --- a/test/src/treesit-tests.el +++ b/test/src/treesit-tests.el | |||
| @@ -161,6 +161,40 @@ | |||
| 161 | (should (treesit-node-eq root-node root-node)) | 161 | (should (treesit-node-eq root-node root-node)) |
| 162 | (should (not (treesit-node-eq root-node doc-node)))))) | 162 | (should (not (treesit-node-eq root-node doc-node)))))) |
| 163 | 163 | ||
| 164 | (ert-deftest treesit-indirect-buffer () | ||
| 165 | "Tests for indirect buffers." | ||
| 166 | (skip-unless (treesit-language-available-p 'json)) | ||
| 167 | (let ((base (get-buffer-create "*treesit test*")) | ||
| 168 | parser indirect) | ||
| 169 | (unwind-protect | ||
| 170 | (progn | ||
| 171 | (with-current-buffer base | ||
| 172 | (setq indirect (clone-indirect-buffer "*treesit test 1*" nil))) | ||
| 173 | (with-current-buffer indirect | ||
| 174 | (setq parser (treesit-parser-create 'json))) | ||
| 175 | ;; 1. Parser created in the indirect buffer should be | ||
| 176 | ;; actually be created in the base buffer. | ||
| 177 | (with-current-buffer base | ||
| 178 | (should (equal (list parser) | ||
| 179 | (treesit-parser-list))) | ||
| 180 | (insert "[1,2,3]")) | ||
| 181 | ;; Change in the base buffer should be reflected in the | ||
| 182 | ;; indirect buffer. | ||
| 183 | (with-current-buffer indirect | ||
| 184 | (should (eq (treesit-node-end | ||
| 185 | (treesit-buffer-root-node)) | ||
| 186 | 8)) | ||
| 187 | (erase-buffer)) | ||
| 188 | ;; Change in the indirect buffer should be reflected in the | ||
| 189 | ;; base buffer. | ||
| 190 | (with-current-buffer base | ||
| 191 | (should (eq (treesit-node-end | ||
| 192 | (treesit-buffer-root-node)) | ||
| 193 | 1)) | ||
| 194 | (erase-buffer))) | ||
| 195 | (kill-buffer base) | ||
| 196 | (kill-buffer indirect)))) | ||
| 197 | |||
| 164 | (ert-deftest treesit-query-api () | 198 | (ert-deftest treesit-query-api () |
| 165 | "Tests for query API." | 199 | "Tests for query API." |
| 166 | (skip-unless (treesit-language-available-p 'json)) | 200 | (skip-unless (treesit-language-available-p 'json)) |