Package: emacs;
Reported by: ~johnmuhl <jm <at> pub.pink>
Date: Fri, 1 Sep 2023 06:31:02 UTC
Severity: wishlist
Tags: patch
Merged with 65673
Done: Eli Zaretskii <eliz <at> gnu.org>
Bug is archived. No further changes may be made.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: ~johnmuhl <johnmuhl <at> git.sr.ht> To: bug-gnu-emacs <at> gnu.org Cc: ~emacs/emacs-devel <at> lists.sr.ht Subject: [PATCH emacs 1/1] Add lua-ts-mode Date: Thu, 31 Aug 2023 16:32:06 -0500
From: john muhl <jm <at> pub.pink> * test/lisp/progmodes/lua-ts-mode-tests.el: * test/lisp/progmodes/lua-ts-mode-resources/indent.ert: * lisp/progmodes/lua-ts-mode.el: New file. * lisp/progmodes/eglot.el (eglot-server-programs): * lisp/progmodes/hideshow.el (hs-special-modes-alist): Add support for lua-ts-mode. * admin/notes/tree-sitter/build-module/batch.sh: * admin/notes/tree-sitter/build-module/build.sh: Add Lua grammar. * test/infra/Dockerfile.emba: * test/infra/test-jobs.yml: Add lua-ts-mode tests. --- admin/notes/tree-sitter/build-module/batch.sh | 1 + admin/notes/tree-sitter/build-module/build.sh | 3 + etc/NEWS | 4 + lisp/progmodes/eglot.el | 2 +- lisp/progmodes/hideshow.el | 1 + lisp/progmodes/lua-ts-mode.el | 457 ++++++++++++++++++ test/infra/Dockerfile.emba | 1 + test/infra/test-jobs.yml | 1 + .../lua-ts-mode-resources/indent.erts | 152 ++++++ test/lisp/progmodes/lua-ts-mode-tests.el | 32 ++ 10 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 lisp/progmodes/lua-ts-mode.el create mode 100644 test/lisp/progmodes/lua-ts-mode-resources/indent.erts create mode 100644 test/lisp/progmodes/lua-ts-mode-tests.el diff --git a/admin/notes/tree-sitter/build-module/batch.sh b/admin/notes/tree-sitter/build-module/batch.sh index 1d4076564dc..685a35c269d 100755 --- a/admin/notes/tree-sitter/build-module/batch.sh +++ b/admin/notes/tree-sitter/build-module/batch.sh @@ -15,6 +15,7 @@ languages=( 'html' 'javascript' 'json' + 'lua' 'python' 'rust' 'toml' diff --git a/admin/notes/tree-sitter/build-module/build.sh b/admin/notes/tree-sitter/build-module/build.sh index 0832875168b..969187b7f92 100755 --- a/admin/notes/tree-sitter/build-module/build.sh +++ b/admin/notes/tree-sitter/build-module/build.sh @@ -42,6 +42,9 @@ case "${lang}" in "heex") org="phoenixframework" ;; + "lua") + org="MunifTanjim" + ;; "typescript") sourcedir="tree-sitter-typescript/typescript/src" grammardir="tree-sitter-typescript/typescript" diff --git a/etc/NEWS b/etc/NEWS index 9a98db8c83a..1a40a62615b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -730,6 +730,10 @@ A major mode based on the tree-sitter library for editing HEEx files. A major mode based on the tree-sitter library for editing Elixir files. +--- +*** New major mode 'lua-ts-mode'. +A major mode based on the tree-sitter library for editing Lua files. + --- ** The highly accessible Modus themes collection has eight items. The 'modus-operandi' and 'modus-vivendi' are the main themes that have diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 65daa0941d5..f249e3c81b4 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -237,7 +237,7 @@ chosen (interactively or automatically)." (gdscript-mode . ("localhost" 6008)) ((fortran-mode f90-mode) . ("fortls")) (futhark-mode . ("futhark" "lsp")) - (lua-mode . ,(eglot-alternatives + ((lua-mode lua-ts-mode) . ,(eglot-alternatives '("lua-language-server" "lua-lsp"))) (zig-mode . ("zls")) ((css-mode css-ts-mode) diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el index b878986d7a4..78e39fad740 100644 --- a/lisp/progmodes/hideshow.el +++ b/lisp/progmodes/hideshow.el @@ -264,6 +264,7 @@ This has effect only if `search-invisible' is set to `open'." (java-ts-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (js-ts-mode "{" "}" "/[*/]" nil) + (lua-ts-mode "{\\|\\[\\[" "}\\|\\]\\]" "--" nil) (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil) ;; Add more support here. )) diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el new file mode 100644 index 00000000000..76d1781b30e --- /dev/null +++ b/lisp/progmodes/lua-ts-mode.el @@ -0,0 +1,457 @@ +;;; lua-ts-mode.el --- Major mode for editing Lua files -*- lexical-binding: t -*- + +;; Copyright (C) 2023 Free Software Foundation, Inc. + +;; Author: John Muhl <jm <at> pub.pink> +;; Created: June 27, 2023 +;; Keywords: lua languages tree-sitter + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This package provides `lua-ts-mode' which is a major mode for Lua +;; files that uses Tree Sitter to parse the language. +;; +;; This package is compatible with and tested against the grammar +;; for Lua found at https://github.com/MunifTanjim/tree-sitter-lua + +;;; Code: + +(require 'comint) +(require 'treesit) + +(eval-when-compile + (require 'cl-lib) + (require 'rx)) + +(defcustom lua-ts-indent-offset 4 + "Number of spaces for each indentation step in `lua-ts-mode'." + :type 'integer + :safe 'integerp + :group 'lua + :version "30.1") + +(defcustom lua-ts-luacheck-program "luacheck" + "Location of the Luacheck program." + :type 'string + :group 'lua + :version "30.1") + +(defcustom lua-ts-lua-manual + (if (file-readable-p "/usr/share/doc/lua/manual.html") + "file:///usr/share/doc/lua/manual.html" "") + "Location of the Lua `manual.html' file." + :type 'string + :safe 'stringp + :group 'lua + :version "30.1") + +(defcustom inferior-lua-buffer "*Lua*" + "Name of the inferior Lua buffer." + :type 'string + :safe 'stringp + :group 'lua + :version "30.1") + +(defcustom inferior-lua-interpreter "lua" + "Program to run in the inferior Lua process." + :type 'string + :safe 'stringp + :group 'lua + :version "30.1") + +(defcustom inferior-lua-switches "-i" + "Command line options for the inferior Lua process." + :type 'string + :safe 'stringp + :group 'lua + :version "30.1") + +(defcustom inferior-lua-startfile "" + "File to load into the inferior Lua process at startup." + :type 'string + :safe 'stringp + :group 'lua + :version "30.1") + +(defcustom inferior-lua-prompt-regexp "^>>?[[:blank:]]" + "Regular expression matching the prompt of the inferior Lua process." + :type 'regexp + :group 'lua + :version "30.1") + +(defvar lua-ts--builtins + '("assert" "collectgarbage" "coroutine" "debug" "dofile" + "error" "getmetatable" "io" "ipairs" "load" "loadfile" + "math" "next" "os" "package" "pairs" "pcall" "print" + "rawequal" "rawget" "rawlen" "rawset" "require" "select" + "setmetatable" "string" "table" "tonumber" "tostring" + "type" "utf8" "warn" "xpcall" + ;; methods for file handlers + "close" "flush" "lines" "read" "seek" "setvbuf" "write") + "Lua built-in functions for tree-sitter font-locking.") + +(defvar lua-ts--font-lock-settings + (treesit-font-lock-rules + :language 'lua + :feature 'bracket + '(["(" ")" "[" "]" "{" "}"] @font-lock-bracket-face) + + :language 'lua + :feature 'delimiter + '(["," ";"] @font-lock-delimiter-face) + + :language 'lua + :feature 'escape + '((escape_sequence) @font-lock-escape-face) + + :language 'lua + :feature 'constant + '((variable_list + attribute: (attribute (["<" ">"] (identifier)))) + @font-lock-constant-face) + + :language 'lua + :feature 'operator + '(["and" "not" "or" "+" "-" "*" "/" "%" "^" + "#" "==" "~=" "<=" ">=" "<" ">" "=" "&" + "~" "|" "<<" ">>" "//" ".."] + @font-lock-operator-face + (vararg_expression) @font-lock-operator-face) + + :language 'lua + :feature 'property + '((field name: (identifier) @font-lock-property-name-face) + (dot_index_expression + field: (identifier) @font-lock-property-use-face)) + + :language 'lua + :feature 'builtin + `(((identifier) @font-lock-builtin-face + (:match ,(regexp-opt lua-ts--builtins 'symbols) + @font-lock-builtin-face))) + + :language 'lua + :feature 'function + '((function_call name: (identifier) @font-lock-function-call-face) + (function_call + name: (method_index_expression + method: (identifier) @font-lock-function-call-face)) + (function_call + name: (dot_index_expression + table: (identifier) @font-lock-function-call-face))) + + :language 'lua + :feature 'punctuation + '(["." ":"] @font-lock-punctuation-face) + + :language 'lua + :feature 'variable + '((function_call + arguments: (arguments (identifier)) + @font-lock-variable-use-face) + (function_call + name: (method_index_expression + table: (identifier) @font-lock-variable-use-face)) + (goto_statement (identifier) @font-lock-variable-use-face)) + + :language 'lua + :feature 'assignment + '((variable_list (identifier) @font-lock-variable-name-face)) + + :language 'lua + :feature 'number + '((number) @font-lock-number-face) + + :language 'lua + :feature 'keyword + '((break_statement) @font-lock-keyword-face + (true) @font-lock-constant-face + (false) @font-lock-constant-face + (nil) @font-lock-constant-face + ["and" "do" "else" "elseif" "end" "for" "function" + "goto" "if" "in" "local" "not" "or" "repeat" + "return" "then" "until" "while"] + @font-lock-keyword-face) + + :language 'lua + :feature 'string + '((string) @font-lock-string-face) + + :language 'lua + :feature 'comment + '((comment) @font-lock-comment-face + (hash_bang_line) @font-lock-comment-face) + + :language 'lua + :feature 'definition + '((function_declaration + name: (identifier) @font-lock-function-name-face) + (parameters + name: (identifier) @font-lock-variable-name-face) + (label_statement) @font-lock-variable-name-face) + + :language 'lua + :feature 'error + :override t + '((ERROR) @font-lock-warning-face)) + "Tree-sitter font-lock settings for `lua-ts-mode'.") + +(defvar lua-ts--simple-indent-rules + `((lua + ((parent-is "chunk") column-0 0) + ((node-is "comment_end") column-0 0) + ((parent-is "block") parent-bol 0) + ((node-is "}") parent-bol 0) + ((node-is ")") parent-bol 0) + ((node-is "else_statement") parent-bol 0) + ((node-is "elseif_statement") parent-bol 0) + ((node-is "end") parent-bol 0) + ((node-is "until") parent-bol 0) + ((parent-is "for_statement") parent-bol lua-ts-indent-offset) + ((parent-is "function_declaration") parent-bol lua-ts-indent-offset) + ((parent-is "function_definition") parent-bol lua-ts-indent-offset) + ((parent-is "if_statement") parent-bol lua-ts-indent-offset) + ((parent-is "else_statement") parent-bol lua-ts-indent-offset) + ((parent-is "repeat_statement") parent-bol lua-ts-indent-offset) + ((parent-is "while_statement") parent-bol lua-ts-indent-offset) + ((parent-is "table_constructor") parent-bol lua-ts-indent-offset) + ((parent-is "arguments") parent-bol lua-ts-indent-offset) + ((parent-is "parameters") parent-bol lua-ts-indent-offset) + ((parent-is "ERROR") no-indent 0)))) + +(defvar lua-ts--syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- ". 12" table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?% "." table) + (modify-syntax-entry ?^ "." table) + (modify-syntax-entry ?~ "." table) + (modify-syntax-entry ?< "." table) + (modify-syntax-entry ?> "." table) + (modify-syntax-entry ?/ "." table) + (modify-syntax-entry ?* "." table) + (modify-syntax-entry ?\n ">" table) + (modify-syntax-entry ?\' "\"" table) + (modify-syntax-entry ?\" "\"" table) + table) + "Syntax table for `lua-ts-mode'.") + +(defun lua-ts--defun-name-function (node) + "Return the defun name of NODE. +Return nil if there is no name or if NODE is not a defun node." + (let ((child (treesit-node-child-by-field-name node "name"))) + (pcase (treesit-node-type node) + ((or "function_declaration" "function_definition") + (treesit-node-text child t)) + ("variable_declaration" + (if child + (treesit-node-text child t) + (treesit-node-text + (treesit-node-child-by-field-name + (treesit-search-subtree node "assignment_statement" nil nil 1) + "name")))) + ("field" + (and (treesit-search-subtree node "function_definition" nil nil 1) + (treesit-node-text child t)))))) + +(defun lua-ts--builtin-p (node) + "Return t if the NODE is a builtin or nil if not." + (let ((name (pcase (treesit-node-type node) + ("dot_index_expression" + (car (string-split (treesit-node-text node t) "\\." t))) + ("function_call" + (let* ((child (treesit-node-child-by-field-name node "name")) + (text (treesit-node-text child t))) + (if (string-match-p ":" text) + (cadr (string-split text ":" t)) + text)))))) + (and name (string-match-p (regexp-opt lua-ts--builtins 'words) name)))) + +(defvar-local lua-ts--flymake-process nil) + +(defun lua-ts-flymake-luacheck (report-fn &rest _args) + "Luacheck backend for Flymake. +Calls REPORT-FN directly." + (when (process-live-p lua-ts--flymake-process) + (kill-process lua-ts--flymake-process)) + (let ((source (current-buffer))) + (save-restriction + (widen) + (setq lua-ts--flymake-process + (make-process + :name "lua-ts-flymake-luacheck" + :noquery t + :connection-type 'pipe + :buffer (generate-new-buffer " *lua-ts-flymake-luacheck*") + :command `(,lua-ts-luacheck-program + "--codes" "--ranges" "--formatter" "plain" "-") + :sentinel + (lambda (proc _event) + (when (eq 'exit (process-status proc)) + (unwind-protect + (if (with-current-buffer source + (eq proc lua-ts--flymake-process)) + (with-current-buffer (process-buffer proc) + (goto-char (point-min)) + (cl-loop + while (search-forward-regexp + (rx (seq bol + (0+ alnum) ":" + (group (1+ digit)) ":" + (group (1+ digit)) "-" + (group (1+ digit)) ": " + (group (0+ nonl)) + eol)) + nil t) + for line = (string-to-number (match-string 1)) + for beg = (string-to-number (match-string 2)) + for end = (string-to-number (match-string 3)) + for msg = (match-string 4) + for type = (if (string-match "^(W" msg) + :warning + :error) + when (and beg end) + collect (flymake-make-diagnostic source + (cons line beg) + (cons line (1+ end)) + type + msg) + into diags + finally (funcall report-fn diags))) + (flymake-log :warning "Canceling obsolete check %s" proc)) + (kill-buffer (process-buffer proc))))))) + (process-send-region lua-ts--flymake-process (point-min) (point-max)) + (process-send-eof lua-ts--flymake-process)))) + +(defun lua-ts-documentation-at-point () + "Show documentation of function at point in Lua manual." + (interactive) + (unless (string-blank-p lua-ts-lua-manual) + (let ((character-before (char-to-string (char-before))) + id) + (save-excursion + ;; When point is mid-word `treesit-thing-at-point' + ;; may return the parent node of the thing at point. + (unless (or (bolp) + (not (string-match-p "[[:alnum:]]" character-before))) + (backward-word)) + (let ((node (treesit-thing-at-point 'builtin nil))) + (setq id (pcase (treesit-node-type node) + ("dot_index_expression" (treesit-node-text node t)) + ("function_call" + (let* ((child (treesit-node-child-by-field-name node "name")) + (name (treesit-node-text child t))) + (if (string-match-p ":" name) + (replace-regexp-in-string "^.*:" "file:" name) + name))))))) + (when id (browse-url (concat lua-ts-lua-manual "#pdf-" id)))))) + +;;;###autoload +(defun inferior-lua () + "Run the Lua interpreter in an inferior process." + (interactive) + (let ((buffer (get-buffer-create inferior-lua-buffer)) + (program inferior-lua-interpreter) + (switches inferior-lua-switches) + (startfile (unless (string-blank-p inferior-lua-startfile) + (expand-file-name inferior-lua-startfile)))) + (make-comint-in-buffer program buffer program startfile switches) + (with-current-buffer buffer + (setq-local comint-input-ignoredups t + comint-prompt-read-only t + comint-prompt-regexp inferior-lua-prompt-regexp + comint-use-prompt-regexp t)) + (pop-to-buffer buffer))) + +;;;###autoload +(define-derived-mode lua-ts-mode prog-mode "Lua" + "Major mode for editing Lua files, powered by tree-sitter." + :group 'lua + :syntax-table lua-ts--syntax-table + + (when (treesit-ready-p 'lua) + (treesit-parser-create 'lua) + + (setq-local treesit-thing-settings + '((lua . ((builtin lua-ts--builtin-p))))) + + ;; Comments. + (setq-local comment-start "--") + (setq-local comment-start-skip "--\\s-*") + (setq-local comment-end "") + + ;; Font-lock. + (setq-local treesit-font-lock-settings lua-ts--font-lock-settings) + + (setq-local treesit-font-lock-feature-list + '((comment definition) + (keyword property string) + (assignment builtin constant number) + (bracket + delimiter + escape + function + operator + punctuation + variable))) + + ;; Indent. + (setq-local treesit-simple-indent-rules lua-ts--simple-indent-rules) + + ;; Navigation. + (setq-local treesit-defun-name-function #'lua-ts--defun-name-function) + + (setq-local treesit-defun-type-regexp + (rx (or "function_declaration" "function_definition"))) + + (setq-local treesit-sentence-type-regexp + (rx (or "do_statement" "while_statement" "repeat_statement" + "if_statement" "for_statement" "variable_declaration"))) + + (setq-local treesit-sexp-type-regexp + (rx (or "arguments" "comment" "string" "table_constructor"))) + + ;; Imenu. + (setq-local treesit-simple-imenu-settings + `(("Variable" ,(rx bos "variable_declaration" eos) nil nil) + ("Function" ,(rx bos + (or "function_declaration" + "function_definition" + "field") + eos) + nil nil))) + + ;; Which-function. + (setq-local which-func-functions (treesit-defun-at-point)) + + ;; Outline. + (setq-local outline-regexp + (rx (or "--[[" "do" "for" "if" "repeat" "while" + (seq (** 0 1 "local ") "function")))) + + (treesit-major-mode-setup)) + + (add-hook 'flymake-diagnostic-functions #'lua-ts-flymake-luacheck nil 'local)) + +(if (treesit-ready-p 'lua) + (add-to-list 'auto-mode-alist '("\\.lua\\'" . lua-ts-mode))) + +(provide 'lua-ts-mode) + +;;; lua-ts-mode.el ends here diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba index 584e4444dc1..e29098ec270 100644 --- a/test/infra/Dockerfile.emba +++ b/test/infra/Dockerfile.emba @@ -126,6 +126,7 @@ RUN src/emacs -Q --batch \ (java "https://github.com/tree-sitter/tree-sitter-java") \ (javascript "https://github.com/tree-sitter/tree-sitter-javascript") \ (json "https://github.com/tree-sitter/tree-sitter-json") \ + (lua "https://github.com/MunifTanjim/tree-sitter-lua") \ (python "https://github.com/tree-sitter/tree-sitter-python") \ (ruby "https://github.com/tree-sitter/tree-sitter-ruby") \ (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") \ diff --git a/test/infra/test-jobs.yml b/test/infra/test-jobs.yml index 2f6e0dab4d5..1f5d607eda4 100644 --- a/test/infra/test-jobs.yml +++ b/test/infra/test-jobs.yml @@ -580,6 +580,7 @@ test-src-inotify: lisp/progmodes/go-ts-mode-tests.log lisp/progmodes/heex-ts-mode-tests.log lisp/progmodes/java-ts-mode-tests.log + lisp/progmodes/lua-ts-mode-tests.log lisp/progmodes/ruby-ts-mode-tests.log lisp/progmodes/typescript-ts-mode-tests.log src/treesit-tests.log diff --git a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts new file mode 100644 index 00000000000..040225c8580 --- /dev/null +++ b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts @@ -0,0 +1,152 @@ +Code: + (lambda () + (setq indent-tabs-mode nil) + (setq lua-ts-indent-offset 2) + (lua-ts-mode) + (indent-region (point-min) (point-max))) + +Name: Basic Indent + +=-= + print( +0, + 1 +) + +local function f(o) + if o.x > o.y then + return o.x +elseif o.y > o.z then + return o.y + else +return o.z + end +end + +f({ + x = 1, + y = 2, + z = 3, +}) + +;(function() +return false +)() +=-= +print( + 0, + 1 +) + +local function f(o) + if o.x > o.y then + return o.x + elseif o.y > o.z then + return o.y + else + return o.z + end +end + +f({ + x = 1, + y = 2, + z = 3, +}) + +;(function() + return false +)() +=-=-= + +Name: Argument Indent + +=-= +function h( +string, +number, +options) +print(string, number, options) +end + +local p = h( +"sring", + 1000, + { +cost = 2, +length = 8, + parallelism = 4, +}) +=-= +function h( + string, + number, + options) + print(string, number, options) +end + +local p = h( + "sring", + 1000, + { + cost = 2, + length = 8, + parallelism = 4, + }) +=-=-= + +Name: Continuation Indent + +=-= +function f() + local str = [[ + multi-line + string + ]] +--[[ +multi-line +comment + ]] +return true +end +=-= +function f() + local str = [[ + multi-line + string + ]] + --[[ +multi-line +comment + ]] + return true +end +=-=-= + +Name: Loop Indent + +=-= +for k, v in pairs({}) do + print(k, v) +end + +while n < 10 do +n = n + 1 +end + +repeat +z = z * 2 + until z > 12 +=-= +for k, v in pairs({}) do + print(k, v) +end + +while n < 10 do + n = n + 1 +end + +repeat + z = z * 2 +until z > 12 +=-=-= diff --git a/test/lisp/progmodes/lua-ts-mode-tests.el b/test/lisp/progmodes/lua-ts-mode-tests.el new file mode 100644 index 00000000000..62ec2652ba8 --- /dev/null +++ b/test/lisp/progmodes/lua-ts-mode-tests.el @@ -0,0 +1,32 @@ +;;; lua-ts-mode-tests.el --- Tests for lua-ts-mode -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. + +;;; Code: + +(require 'ert) +(require 'ert-x) +(require 'treesit) + +(ert-deftest lua-ts-mode-test-indentation () + (skip-unless (treesit-ready-p 'lua)) + (ert-test-erts-file (ert-resource-file "indent.erts"))) + +(provide 'lua-ts-mode-tests) + +;;; lua-ts-mode-tests.el ends here -- 2.38.5
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.