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 #10 received at 65672 <at> debbugs.gnu.org (full text, mbox):
From: Philip Kaludercic <philipk <at> posteo.net> To: ~johnmuhl <johnmuhl <at> git.sr.ht> Cc: ~johnmuhl <jm <at> pub.pink>, ~emacs/emacs-devel <at> lists.sr.ht, 65673 <at> debbugs.gnu.org, 65672 <at> debbugs.gnu.org Subject: Re: bug#65673: [PATCH emacs 0/1] Add lua-ts-mode Date: Sat, 02 Sep 2023 12:14:26 +0000
~johnmuhl <johnmuhl <at> git.sr.ht> writes: > 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") Could this fall back to some online manual? > + > +(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") Are you sure that any string is safe? That would include "rm -rf ~". > +(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 The :group is redundant here, it will automatically use the last defgroup defined in the file. > + :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
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.