bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#65673: [PATCH] Add lua-ts-mode


From: Philip Kaludercic
Subject: bug#65673: [PATCH] Add lua-ts-mode
Date: Sun, 10 Sep 2023 11:12:49 +0000

john muhl <jm@pub.pink> writes:

> * 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                 | 419 +++++++++++++
>  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, 1173 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..b7fe71c5fe2
> --- /dev/null
> +++ b/lisp/progmodes/lua-ts-mode.el
> @@ -0,0 +1,419 @@
> +;;; lua-ts-mode.el --- Major mode for editing Lua files -*- lexical-binding: 
> t -*-
> +
> +;; Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +;; Author: John Muhl <jm@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 'natnum
> +  :safe 'natnump
> +  :group 'lua

You still need a defgroup for the package.

> +  :version "30.1")
> +
> +(defcustom lua-ts-luacheck-program (executable-find "luacheck")

It is better not to hard-code the path to lua during loading, in case
the executable is moved around, since you will basically always still be
querying PATH when starting a new process.

> +  "Location of the Luacheck program."
> +  :type '(choice (const nil) (file :must-match t))

Which is why I think that this shouldn't be a file.

> +  :group 'lua
> +  :version "30.1")
> +
> +(defcustom lua-ts-inferior-buffer "Lua"

How about "*Lua*"?

> +  "Name of the inferior Lua buffer."
> +  :type 'string
> +  :safe 'stringp
> +  :group 'lua
> +  :version "30.1")
> +
> +(defcustom lua-ts-inferior-program (executable-find "lua")

Same here.

> +  "Program to run in the inferior Lua process."
> +  :type '(choice (const nil) (file :must-match t))
> +  :group 'lua
> +  :version "30.1")
> +
> +(defcustom lua-ts-inferior-options '("-i")
> +  "Command line options for the inferior Lua process."
> +  :type '(repeat string)
> +  :group 'lua
> +  :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
> +  :version "30.1")
> +
> +(defcustom lua-ts-inferior-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" "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* ((name lua-ts-inferior-buffer)
> +         (buffer (concat "*" name "*"))
> +         (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))
> +    (pop-to-buffer buffer)))

I believe that `display-buffer-pop-up-frame' is the preferred alternative
to `pop-to-buffer' these days.

> +
> +;;;###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 (** 0 1 (seq "local" (1+ space)))

aka (? (seq "local" (1+ space))), right?

> +                                           "function"))
> +                                  symbol-end)))))
> +
> +    (treesit-major-mode-setup))
> +
> +  (add-hook 'flymake-diagnostic-functions #'lua-ts-flymake-luacheck nil 
> 'local))
> +
> +(if (treesit-ready-p 'lua)

I would say writing this with `when' would be cleaner.

> +    (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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]