Package: emacs;
Reported by: ~johnmuhl <jm <at> pub.pink>
Date: Fri, 1 Sep 2023 06:31:03 UTC
Severity: wishlist
Tags: patch
Merged with 65672
Done: Eli Zaretskii <eliz <at> gnu.org>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: john muhl <jm <at> pub.pink> To: philipk <at> posteo.net Cc: john muhl <jm <at> pub.pink>, arstoffel <at> gmail.com, maurooaranda <at> gmail.com, 65673 <at> debbugs.gnu.org, ~emacs/emacs-devel <at> lists.sr.ht Subject: bug#65673: [PATCH] Add lua-ts-mode Date: Mon, 11 Sep 2023 10:03:13 -0500
* lisp/progmodes/lua-ts-mode.el: * test/lisp/progmodes/lua-ts-mode-resources/indent.erts: * test/lisp/progmodes/lua-ts-mode-tests.el: New file. * etc/NEWS: Mention new mode. * lisp/progmodes/eglot.el (eglot-server-programs): * lisp/progmodes/hideshow.el (hs-special-modes-alist): Support lua-ts-mode. * admin/notes/tree-sitter/build-module/batch.sh: * admin/notes/tree-sitter/build-module/build.sh: Add Lua. * test/infra/Dockerfile.emba: * test/infra/test-jobs.yml: Include 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 | 4 +- lisp/progmodes/hideshow.el | 1 + lisp/progmodes/lua-ts-mode.el | 431 ++++++++++++++ test/infra/Dockerfile.emba | 1 + test/infra/test-jobs.yml | 1 + .../lua-ts-mode-resources/indent.erts | 152 +++++ .../lua-ts-mode-resources/movement.erts | 553 ++++++++++++++++++ test/lisp/progmodes/lua-ts-mode-tests.el | 36 ++ 11 files changed, 1185 insertions(+), 2 deletions(-) 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-resources/movement.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 3c4e1472c89..9988d1eae4e 100755 --- a/admin/notes/tree-sitter/build-module/batch.sh +++ b/admin/notes/tree-sitter/build-module/batch.sh @@ -16,6 +16,7 @@ languages= 'java' '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 @@ grammardir= "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 51e89fc96dd..0b7da8b392c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -782,6 +782,10 @@ It highlight parens via ‘show-paren-mode’ and ‘blink-matching-paren’ in a user-friendly way, avoids reporting alleged paren mismatches and makes sexp navigation more intuitive. +--- +*** 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 f7c7c29c094..e2f663998d3 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -268,8 +268,8 @@ eglot-server-programs (gdscript-mode . ("localhost" 6008)) ((fortran-mode f90-mode) . ("fortls")) (futhark-mode . ("futhark" "lsp")) - (lua-mode . ,(eglot-alternatives - '("lua-language-server" "lua-lsp"))) + ((lua-mode lua-ts-mode) . ,(eglot-alternatives + '("lua-language-server" "lua-lsp"))) (zig-mode . ("zls")) ((css-mode css-ts-mode) . ,(eglot-alternatives '(("vscode-css-language-server" "--stdio") 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 @@ hs-special-modes-alist (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..071953d3d2f --- /dev/null +++ b/lisp/progmodes/lua-ts-mode.el @@ -0,0 +1,431 @@ +;;; 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)) + +(declare-function treesit-node-child-by-field-name "treesit.c") +(declare-function treesit-node-type "treesit.c") +(declare-function treesit-parser-create "treesit.c") +(declare-function treesit-search-subtree "treesit.c") + +(defgroup lua-ts nil + "Major mode for editing Lua files." + :prefix "lua-ts-" + :group 'languages) + +(defcustom lua-ts-indent-offset 4 + "Number of spaces for each indentation step in `lua-ts-mode'." + :type 'natnum + :safe 'natnump + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-luacheck-program "luacheck" + "Location of the Luacheck program." + :type '(choice (const nil) string) + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-buffer "*Lua*" + "Name of the inferior Lua buffer." + :type 'string + :safe 'stringp + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-program "lua" + "Program to run in the inferior Lua process." + :type '(choice (const nil) string) + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-options '("-i") + "Command line options for the inferior Lua process." + :type '(repeat string) + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-startfile nil + "File to load into the inferior Lua process at startup." + :type '(choice (const nil) (file :must-match t)) + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-prompt-regexp "^>>?[[:blank:]]" + "Regular expression matching the prompt of the inferior Lua process." + :type 'regexp + :group 'lua-ts + :version "30.1") + +(defvar lua-ts--builtins + '("assert" "bit32" "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" "_G" "_VERSION" + ;; 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)))))) + +(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)))) + +;;;###autoload +(defun lua-ts-inferior-lua () + "Run a Lua interpreter in an inferior process." + (interactive) + (let* ((buffer lua-ts-inferior-buffer) + (name (string-replace "*" "" buffer)) + (program lua-ts-inferior-program) + (prompt-regexp lua-ts-inferior-prompt-regexp) + (switches lua-ts-inferior-options) + (startfile lua-ts-inferior-startfile)) + (unless (comint-check-proc buffer) + (set-buffer (apply (function make-comint) name program startfile switches)) + (setq-local comint-input-ignoredups t + comint-prompt-read-only t + comint-prompt-regexp prompt-regexp + comint-use-prompt-regexp t)) + (select-window (display-buffer buffer '((display-buffer-reuse-window + display-buffer-pop-up-frame) + (reusable-frames . t)))))) + +;;;###autoload +(define-derived-mode lua-ts-mode prog-mode "Lua" + "Major mode for editing Lua files, powered by tree-sitter." + :syntax-table lua-ts--syntax-table + + (when (treesit-ready-p 'lua) + (treesit-parser-create 'lua) + + ;; 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-thing-settings + `((lua + (sentence ,(rx (or "do_statement" + "field" + "for_statement" + "function_call" + "if_statement" + "repeat_statement" + "return_statement" + "variable_declaration" + "while_statement"))) + (sexp ,(rx (or "arguments" + "block" + "parameters" + "string" + "table_constructor"))) + (text "comment")))) + + ;; 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 (seq (0+ space) + (or (seq "--[[" (0+ space) eol) + (seq symbol-start + (or "do" "for" "if" "repeat" "while" + (seq (? (seq "local" (1+ space))) + "function")) + symbol-end))))) + + (treesit-major-mode-setup)) + + (add-hook 'flymake-diagnostic-functions #'lua-ts-flymake-luacheck nil 'local)) + +(when (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-resources/movement.erts b/test/lisp/progmodes/lua-ts-mode-resources/movement.erts new file mode 100644 index 00000000000..770aa23b18d --- /dev/null +++ b/test/lisp/progmodes/lua-ts-mode-resources/movement.erts @@ -0,0 +1,553 @@ +Code: + (lambda () + (lua-ts-mode) + (beginning-of-defun 1)) + +Point-Char: | + +Name: beginning-of-defun moves to start of function declaration + +=-= +local function Test() + if true then + print(1) + else + print(0) + end| +end +=-= +|local function Test() + if true then + print(1) + else + print(0) + end +end +=-=-= + +Name: beginning-of-defun moves to start of function definition + +=-= +local t = { + f = function() + return true + end, +}| +=-= +local t = { +| f = function() + return true + end, +} +=-=-= + +Code: + (lambda () + (lua-ts-mode) + (end-of-defun 1)) + +Point-Char: | + +Name: end-of-defun moves to end of function declaration + +=-= +local function Test() + if true then + pr|int(1) + else + print(0) + end +end + +local t = Test() +=-= +local function Test() + if true then + print(1) + else + print(0) + end +end +| +local t = Test() +=-=-= + +Name: end-of-defun moves to end of function definition + +=-= +local t = { + f = function() + re|turn true + end, +} +=-= +local t = { + f = function() + return true + end|, +} +=-=-= + +Code: + (lambda () + (lua-ts-mode) + (forward-sentence 1)) + +Point-Char: | + +Name: forward-sentence moves over if statements + +=-= +function f() + |if true then + print(1) + elseif false then + print(0) + else + print(2) + end +end +=-= +function f() + if true then + print(1) + elseif false then + print(0) + else + print(2) + end| +end +=-=-= + +Name: forward-sentence moves over variable declaration + +=-= +|local n = 1 + +print(n) +=-= +local n = 1| + +print(n) +=-=-= + +Name: forward-sentence moves over for statements + +=-= +|for k, v in pairs({}) do + print(k, v) +end + +print(1) +=-= +for k, v in pairs({}) do + print(k, v) +end| + +print(1) +=-=-= + +Name: forward-sentence moves over for statements + +=-= +|do + local x = 1 + local y = 2 + + print(x, y) +end + +print(1) +=-= +do + local x = 1 + local y = 2 + + print(x, y) +end| + +print(1) +=-=-= + +Name: forward-sentence moves over while statements + +=-= +local i = 0 +|while i < 9 do + print(i) + i = i + 1 +end + +print(1) +=-= +local i = 0 +while i < 9 do + print(i) + i = i + 1 +end| + +print(1) +=-=-= + +Name: forward-sentence moves over repeat statements + +=-= +local i = 0 +|repeat + print(i) + i = i + 1 +until i > 9 + +print(1) +=-= +local i = 0 +repeat + print(i) + i = i + 1 +until i > 9| + +print(1) +=-=-= + +Name: forward-sentence moves over function calls + +=-= +|print(1) +=-= +print(1)| +=-=-= + +Name: forward-sentence moves over return statements + +=-= +function f() + |return math.random() +end +=-= +function f() + return math.random()| +end +=-=-= + +Code: + (lambda () + (lua-ts-mode) + (forward-sentence 2)) + +Name: forward-sentence moves over table fields + +=-= +local t = { + |a = 1, + b = 2, +} +=-= +local t = { + a = 1, + b = 2|, +} +=-=-= + +Code: + (lambda () + (lua-ts-mode) + (backward-sentence 1)) + +Point-Char: | + +Name: backward-sentence moves over if statements + +=-= +function f() + if true then + print(1) + elseif false then + print(0) + else + print(2) + end| +end +=-= +function f() + |if true then + print(1) + elseif false then + print(0) + else + print(2) + end +end +=-=-= + +Name: backward-sentence moves over variable declaration + +=-= +local n = 1| + +print(n) +=-= +|local n = 1 + +print(n) +=-=-= + +Name: backward-sentence moves over for statements + +=-= +for k, v in pairs({}) do + print(k, v) +end| + +print(1) +=-= +|for k, v in pairs({}) do + print(k, v) +end + +print(1) +=-=-= + +Name: backward-sentence moves over for statements + +=-= +do + local x = 1 + local y = 2 + + print(x, y) +end| + +print(1) +=-= +|do + local x = 1 + local y = 2 + + print(x, y) +end + +print(1) +=-=-= + +Name: backward-sentence moves over while statements + +=-= +local i = 0 +while i < 9 do + print(i) + i = i + 1 +end| + +print(1) +=-= +local i = 0 +|while i < 9 do + print(i) + i = i + 1 +end + +print(1) +=-=-= + +Name: backward-sentence moves over repeat statements + +=-= +local i = 0 +repeat + print(i) + i = i + 1 +until i > 9| + +print(1) +=-= +local i = 0 +|repeat + print(i) + i = i + 1 +until i > 9 + +print(1) +=-=-= + +Name: backward-sentence moves over function calls + +=-= +print(1)| +=-= +|print(1) +=-=-= + +Name: backward-sentence moves over return statements + +=-= +function f() + return math.random()| +end +=-= +function f() + |return math.random() +end +=-=-= + +Code: + (lambda () + (lua-ts-mode) + (backward-sentence 2)) + +Point-Char: | + +Name: backward-sentence moves over table fields + +=-= +local t = { + a = 1, + b = 2|, +} +=-= +local t = { + |a = 1, + b = 2, +} +=-=-= + +Code: + (lambda () + (lua-ts-mode) + (forward-sexp 1)) + +Point-Char: | + +Name: forward-sexp moves over blocks + +=-= +local function Test() + |local t = { + a = 1, + } + + if true then + print(1) + else + print(0) + end +end +=-= +local function Test() + local t = { + a = 1, + } + + if true then + print(1) + else + print(0) + end| +end +=-=-= + +Name: forward-sexp moves over arguments + +=-= +print|(1, 2, 3) +=-= +print(1, 2, 3)| +=-=-= + +Name: forward-sexp moves over parameters + +=-= +function f|(a, b) end +=-= +function f(a, b)| end +=-=-= + +Name: forward-sexp moves over strings + +=-= +print("|1, 2, 3") +=-= +print("1, 2, 3|") +=-=-= + +Name: forward-sexp moves over tables + +=-= +local t = |{ 1, + 2, + 3 } +=-= +local t = { 1, + 2, + 3 }| +=-=-= + +Code: + (lambda () + (lua-ts-mode) + (backward-sexp 1)) + +Point-Char: | + +Name: backward-sexp moves over blocks + +=-= +local function Test() + local t = { + a = 1, + } + + if true then + print(1) + else + print(0) + end| +end +=-= +local function Test() + |local t = { + a = 1, + } + + if true then + print(1) + else + print(0) + end +end +=-=-= + +Name: backward-sexp moves over arguments + +=-= +print(1, 2, 3)| +=-= +print|(1, 2, 3) +=-=-= + +Name: backward-sexp moves over parameters + +=-= +function f(a, b)| end +=-= +function f|(a, b) end +=-=-= + +Name: backward-sexp moves over strings + +=-= +print("1, 2, 3|") +=-= +print("|1, 2, 3") +=-=-= + +Name: backward-sexp moves over tables + +=-= +local t = { 1, + 2, + 3 }| +=-= +local t = |{ 1, + 2, + 3 } +=-=-= 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..d2105b66f6d --- /dev/null +++ b/test/lisp/progmodes/lua-ts-mode-tests.el @@ -0,0 +1,36 @@ +;;; 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"))) + +(ert-deftest lua-ts-mode-test-movement () + (skip-unless (treesit-ready-p 'lua)) + (ert-test-erts-file (ert-resource-file "movement.erts"))) + +(provide 'lua-ts-mode-tests) + +;;; lua-ts-mode-tests.el ends here -- 2.41.0
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.