From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: john muhl via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#66159: [PATCH] Various improvements to lua-ts-mode (Bug#66159) Date: Sun, 08 Oct 2023 22:28:02 -0500 Message-ID: <87edi4mfu1.fsf@pub.pink> References: <8734ynz15f.fsf@pub.pink> <87zg0u9zn2.fsf@gmail.com> <87edi6xpvn.fsf@pub.pink> <87r0m5qw2n.fsf@gmail.com> Reply-To: john muhl Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="36248"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Andrey Listopadov , Mauro Aranda To: 66159@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Oct 09 09:10:59 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qpkPq-00097V-Lf for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 09 Oct 2023 09:10:59 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qpkPd-0005qo-A0; Mon, 09 Oct 2023 03:10:45 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpkPa-0005pw-90 for bug-gnu-emacs@gnu.org; Mon, 09 Oct 2023 03:10:42 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qpkPa-0002AG-1C for bug-gnu-emacs@gnu.org; Mon, 09 Oct 2023 03:10:42 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qpkPu-000281-65 for bug-gnu-emacs@gnu.org; Mon, 09 Oct 2023 03:11:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: john muhl Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 09 Oct 2023 07:11:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 66159 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 66159-submit@debbugs.gnu.org id=B66159.16968354478159 (code B ref 66159); Mon, 09 Oct 2023 07:11:02 +0000 Original-Received: (at 66159) by debbugs.gnu.org; 9 Oct 2023 07:10:47 +0000 Original-Received: from localhost ([127.0.0.1]:59087 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qpkPd-00027V-J0 for submit@debbugs.gnu.org; Mon, 09 Oct 2023 03:10:47 -0400 Original-Received: from out-200.mta0.migadu.com ([2001:41d0:1004:224b::c8]:64873) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qpkPY-00027J-OX for 66159@debbugs.gnu.org; Mon, 09 Oct 2023 03:10:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pub.pink; s=key1; t=1696835418; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=LRQL5RCfko2mRpkzQiFzpEXqx1D5+BpYMoMNp4ZoWAI=; b=pFPW8gDAP0bElb9GEINPK/jmHhMUytBjnffIqZ0wkIxIxDmzox3ixjZR8fOMZ/T6VwwWiJ g5KJBYuPwMk2v+OAQl+7NWX2Oln2bfcudgb8WwonRSrbr5csIL395p9OWbCCcYteFuGoid D/9Scp1z0woCnuQI9v/4DueNbAQU0tQ= X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. In-reply-to: <87r0m5qw2n.fsf@gmail.com> X-Migadu-Flow: FLOW_OUT X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:272126 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Mauro Aranda writes: > On 6/10/23 16:44, john muhl via Bug reports for GNU Emacs, the Swiss > army knife of text editors wrote: > >> +(defcustom lua-ts-inferior-history nil >> + "File used to save command history of the inferior Lua process." >> + :type '(choice (const nil) file) > > Please, give a :tag for the const option. IMO, it makes for a better > Customize UI. Fixed here and for the other choices. Andrey Listopadov writes: > john muhl writes: > >>> It seems the last patch broke the movement. >> >> The tests for those pass and are still working here. Maybe you found >> another case that needs to be improved. What is the specific problem? > > It seems so, sorry for not including this, I thought I sent this before. > Here's an example: > > > =E2=96=88for i=3D1,10 do > print(x) > end > > Pressing Pressing C-M-f (forward-sexp) puts the point here: > > for i=3D1,10 do > print(x)=E2=96=88 > end > > I think it should go over the `for' loop right to the `end'. > > Pressing Pressing C-M-b (backward-sexp), however, puts the point here: > > for i=3D1,10 do > =E2=96=88print(x) > end > > Pressing C-M-b again doesn't move the point anymore. > > Same thing happens with for-each style loop: > > =E2=96=88for k,v in pairs({1,2,3}) do > print(x) > end > > C-M-f: > > for k,v in pairs({1,2,3})=E2=96=88do > print(x) > end > > C-M-f: > > for k,v in pairs({1,2,3}) do > print(x)=E2=96=88 > end > > Backward movement manages to take the point way back to the pairs: > > C-M-b, C-M-b: > > for k,v in pairs=E2=96=88({1,2,3}) do > print(x) > end > > I went to https://devhints.io/lua and copied a bunch of examples of > other loops to the scratch buffer, and the movement is as follows: > > =E2=96=88while condition do > end > > for i =3D 1,5 do > end > > for i =3D start,finish,delta do > end > > for k,v in pairs(tab) do > end > > repeat > until condition > > -- Breaking out: > while x do > if condition then break end > end > > C-M-f: > > while condition do > end > > for i =3D 1,5 do > end > > for i =3D start,finish,delta do > end > > for k,v in pairs(tab)=E2=96=88do > end > > repeat > until condition > > -- Breaking out: > while x do > if condition then break end > end > > C-M-f: > > while condition do > end > > for i =3D 1,5 do > end > > for i =3D start,finish,delta do > end > > for k,v in pairs(tab) do > end > > repeat > until condition > > -- Breaking out: > while x do > if condition then break end=E2=96=88 > end Navigation should be all around improved now. Let me know if I missed somet= hing. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Various-improvements-to-lua-ts-mode-Bug-66159.patch >From de03aed39d67f0a14b2586e59b2b713891bc37d0 Mon Sep 17 00:00:00 2001 From: john muhl Date: Wed, 4 Oct 2023 20:46:15 -0500 Subject: [PATCH] Various improvements to lua-ts-mode (Bug#66159) * lisp/progmodes/lua-ts-mode.el (lua-ts-mode): Navigate function declarations and parenthesized expressions with *-sexp commands. (lua-ts--simple-indent-rules): Improve indentation rules. (lua-ts-mode-map): Add key bindings and menus. (lua-ts-mode-hook): Make hook available in Customize. (lua-ts-inferior-history): (lua-ts-inferior--write-history): Add option to read/write an input history file. (lua-ts-inferior-lua): (lua-ts-send-buffer): (lua-ts-send-file): (lua-ts-send-region): (lua-ts-inferior-prompt): (lua-ts-inferior-prompt-continue): Support for sending buffer, file or region to the inferior process. (lua-ts-show-process-buffer): (lua-ts-hide-process-buffer): (lua-ts-kill-process): New functions. (lua-ts-inferior-prompt-regexp): Remove option. * test/lisp/progmodes/lua-ts-mode-resources/indent.erts: * test/lisp/progmodes/lua-ts-mode-resources/movement.erts: Add tests. --- lisp/progmodes/lua-ts-mode.el | 369 +++++++-- .../lua-ts-mode-resources/indent.erts | 705 +++++++++++++++--- .../lua-ts-mode-resources/movement.erts | 156 ++-- 3 files changed, 1032 insertions(+), 198 deletions(-) diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index 030a3585158..e7a36f3bb93 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -38,7 +38,11 @@ (require 'cl-lib) (require 'rx)) +(declare-function treesit-induce-sparse-tree "treesit.c") (declare-function treesit-node-child-by-field-name "treesit.c") +(declare-function treesit-node-first-child-for-pos "treesit.c") +(declare-function treesit-node-parent "treesit.c") +(declare-function treesit-node-start "treesit.c") (declare-function treesit-node-type "treesit.c") (declare-function treesit-parser-create "treesit.c") (declare-function treesit-search-subtree "treesit.c") @@ -48,6 +52,15 @@ lua-ts :prefix "lua-ts-" :group 'languages) +(defcustom lua-ts-mode-hook nil + "Hook run after entering `lua-ts-mode'." + :type 'hook + :options '(flymake-mode + hs-minor-mode + outline-minor-mode) + :group 'lua-ts + :version "30.1") + (defcustom lua-ts-indent-offset 4 "Number of spaces for each indentation step in `lua-ts-mode'." :type 'natnum @@ -57,7 +70,7 @@ lua-ts-indent-offset (defcustom lua-ts-luacheck-program "luacheck" "Location of the Luacheck program." - :type '(choice (const nil) string) + :type '(choice (const :tag "None" nil) string) :group 'lua-ts :version "30.1") @@ -70,7 +83,7 @@ lua-ts-inferior-buffer (defcustom lua-ts-inferior-program "lua" "Program to run in the inferior Lua process." - :type '(choice (const nil) string) + :type '(choice (const :tag "None" nil) string) :group 'lua-ts :version "30.1") @@ -82,13 +95,28 @@ lua-ts-inferior-options (defcustom lua-ts-inferior-startfile nil "File to load into the inferior Lua process at startup." - :type '(choice (const nil) (file :must-match t)) + :type '(choice (const :tag "None" nil) (file :must-match t)) + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-prompt ">" + "Prompt used by the inferior Lua process." + :type 'string + :safe 'stringp + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-prompt-continue ">>" + "Continuation prompt used by the inferior Lua process." + :type 'string + :safe 'stringp :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 +(defcustom lua-ts-inferior-history nil + "File used to save command history of the inferior Lua process." + :type '(choice (const :tag "None" nil) file) + :safe 'string-or-null-p :group 'lua-ts :version "30.1") @@ -103,6 +131,12 @@ lua-ts--builtins "close" "flush" "lines" "read" "seek" "setvbuf" "write") "Lua built-in functions for tree-sitter font-locking.") +(defvar lua-ts--keywords + '("and" "do" "else" "elseif" "end" "for" "function" + "goto" "if" "in" "local" "not" "or" "repeat" + "return" "then" "until" "while") + "Lua keywords for tree-sitter font-locking and navigation.") + (defvar lua-ts--font-lock-settings (treesit-font-lock-rules :language 'lua @@ -167,13 +201,11 @@ lua-ts--font-lock-settings :language 'lua :feature 'keyword - '((break_statement) @font-lock-keyword-face + `((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"] + ,(vconcat lua-ts--keywords) @font-lock-keyword-face) :language 'lua @@ -235,27 +267,135 @@ lua-ts--font-lock-settings (defvar lua-ts--simple-indent-rules `((lua + ((or (node-is "comment") + (parent-is "comment_content") + (parent-is "string_content") + (node-is "]]")) + no-indent 0) + ((and (n-p-gp "field" "table_constructor" "arguments") + lua-ts--multi-arg-function-call-matcher) + parent lua-ts-indent-offset) + ((and (n-p-gp "}" "table_constructor" "arguments") + lua-ts--multi-arg-function-call-matcher) + parent 0) + ((or (node-is "do") + (node-is "then") + (node-is "elseif_statement") + (node-is "else_statement") + (node-is "until") + (node-is ")") + (node-is "}")) + standalone-parent 0) + ((or (and (parent-is "arguments") lua-ts--first-child-matcher) + (and (parent-is "parameters") lua-ts--first-child-matcher) + (and (parent-is "table_constructor") lua-ts--first-child-matcher)) + standalone-parent lua-ts-indent-offset) + ((or (parent-is "arguments") + (parent-is "parameters") + (parent-is "table_constructor")) + (nth-sibling 1) 0) + ((and (n-p-gp "block" "function_definition" "parenthesized_expression") + lua-ts--nested-function-block-matcher + lua-ts--nested-function-block-include-matcher) + parent lua-ts-indent-offset) + ((and (n-p-gp "block" "function_definition" "arguments") + lua-ts--nested-function-argument-matcher) + parent lua-ts-indent-offset) + ((match "function_definition" "parenthesized_expression") + standalone-parent lua-ts-indent-offset) + ((node-is "block") standalone-parent lua-ts-indent-offset) + ((parent-is "block") parent 0) + ((and (node-is "end") lua-ts--end-line-matcher) + standalone-parent lua-ts--end-indent-offset) + ((match "end" "function_declaration") parent 0) + ((and (n-p-gp "end" "function_definition" "parenthesized_expression") + lua-ts--nested-function-end-argument-matcher) + parent 0) + ((and (n-p-gp "end" "function_definition" "parenthesized_expression") + lua-ts--nested-function-block-matcher + lua-ts--nested-function-end-matcher + lua-ts--nested-function-last-function-matcher) + parent 0) + ((n-p-gp "end" "function_definition" "arguments") parent 0) + ((or (match "end" "function_definition") + (node-is "end")) + standalone-parent 0) ((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)))) +(defun lua-ts--end-line-matcher (&rest _) + "Matches if there is more than one `end' on the current line." + (> (lua-ts--end-count) 1)) + +(defun lua-ts--end-indent-offset (&rest _) + "Calculate indent offset based on `end' count." + (- (* (1- (lua-ts--end-count)) lua-ts-indent-offset))) + +(defun lua-ts--end-count () + "Count the number of `end's on the current line." + (count-matches "end" (line-beginning-position) (line-end-position))) + +(defun lua-ts--first-child-matcher (node &rest _) + "Matches if NODE is the first among its siblings." + (= (treesit-node-index node) 1)) + +(defun lua-ts--function-definition-p (node) + "Return t if NODE is a function_definition." + (equal "function_definition" (treesit-node-type node))) + +(defun lua-ts--g-g-g-parent (node) + "Return the great-great-grand-parent of NODE." + (let* ((parent (treesit-node-parent node)) + (g-parent (treesit-node-parent parent)) + (g-g-parent (treesit-node-parent g-parent))) + (treesit-node-parent g-g-parent))) + +(defun lua-ts--multi-arg-function-call-matcher (_n parent &rest _) + "Matches if PARENT has multiple arguments." + (> (treesit-node-child-count (treesit-node-parent parent)) 3)) + +(defun lua-ts--nested-function-argument-matcher (node &rest _) + "Matches if NODE is in a nested function argument." + (save-excursion + (goto-char (treesit-node-start node)) + (treesit-beginning-of-defun) + (backward-char 2) + (not (looking-at ")(")))) + +(defun lua-ts--nested-function-block-matcher (node &rest _) + "Matches if NODE is in a nested function block." + (let* ((g-g-g-parent (lua-ts--g-g-g-parent node)) + (g-g-g-type (treesit-node-type g-g-g-parent))) + (not (equal g-g-g-type "chunk")))) + +(defun lua-ts--nested-function-block-include-matcher (node _p bol &rest _) + "Matches if NODE's child at BOL is not another block." + (let* ((child (treesit-node-first-child-for-pos node bol)) + (child-type (treesit-node-type child)) + (g-g-g-type (treesit-node-type (lua-ts--g-g-g-parent node)))) + (or (equal child-type "assignment_statement") + (and (equal child-type "return_statement") + (or (equal g-g-g-type "arguments") + (and (equal g-g-g-type "expression_list") + (not (treesit-search-subtree child "function_call")))))))) + +(defun lua-ts--nested-function-end-matcher (node &rest _) + "Matches if NODE is the `end' of a nested function." + (save-excursion + (goto-char (treesit-node-start node)) + (treesit-beginning-of-defun) + (looking-at "function[[:space:]]*"))) + +(defun lua-ts--nested-function-end-argument-matcher (node &rest _) + "Matches if great-great-grandparent of NODE is arguments." + (equal "arguments" (treesit-node-type (lua-ts--g-g-g-parent node)))) + +(defun lua-ts--nested-function-last-function-matcher (_n parent &rest _) + "Matches if PARENT is the last nested function." + (let ((sparse-tree + (treesit-induce-sparse-tree parent #'lua-ts--function-definition-p))) + (= 1 (length (cadr sparse-tree))))) + (defvar lua-ts--syntax-table (let ((table (make-syntax-table))) (modify-syntax-entry ?+ "." table) @@ -352,26 +492,124 @@ lua-ts-flymake-luacheck (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)) + (unless (comint-check-proc lua-ts-inferior-buffer) + (apply #'make-comint-in-buffer + (string-replace "*" "" lua-ts-inferior-buffer) + lua-ts-inferior-buffer + lua-ts-inferior-program + lua-ts-inferior-startfile + lua-ts-inferior-options) + (when lua-ts-inferior-history + (set-process-sentinel (get-buffer-process lua-ts-inferior-buffer) + 'lua-ts-inferior--write-history)) + (with-current-buffer lua-ts-inferior-buffer (setq-local comint-input-ignoredups t + comint-input-ring-file-name lua-ts-inferior-history + comint-use-prompt-regexp 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)))))) + comint-prompt-regexp (rx-to-string `(: bol + ,lua-ts-inferior-prompt + (1+ space)))) + (comint-read-input-ring t) + (add-hook 'comint-preoutput-filter-functions + (lambda (string) + (if (equal string (concat lua-ts-inferior-prompt-continue " ")) + string ; Don't mess with continuation prompts. + (concat + ;; Filter out the extra prompt characters that + ;; accumulate in the output when sending regions + ;; to the inferior process. + (replace-regexp-in-string (rx-to-string + `(: bol + (* ,lua-ts-inferior-prompt + (? ,lua-ts-inferior-prompt) + (1+ space)) + (group (* nonl)))) + "\\1" string) + ;; Re-add the prompt for the next line. + lua-ts-inferior-prompt " ")))))) + (select-window (display-buffer lua-ts-inferior-buffer + '((display-buffer-reuse-window + display-buffer-pop-up-frame) + (reusable-frames . t)))) + (get-buffer-process (current-buffer))) + +(defun lua-ts-send-buffer () + "Send current buffer to the inferior Lua process." + (interactive) + (lua-ts-send-region (point-min) (point-max))) + +(defun lua-ts-send-file (file) + "Send contents of FILE to the inferior Lua process." + (interactive "f") + (with-temp-buffer + (insert-file-contents-literally file) + (lua-ts-send-region (point-min) (point-max)))) + +(defun lua-ts-send-region (beg end) + "Send region between BEG and END to the inferior Lua process." + (interactive "r") + (let ((string (buffer-substring-no-properties beg end)) + (proc-buffer (lua-ts-inferior-lua))) + (comint-send-string proc-buffer "print()") ; Prevent output from + (comint-send-string proc-buffer "\n") ; appearing at prompt. + (comint-send-string proc-buffer string) + (comint-send-string proc-buffer "\n"))) + +(defun lua-ts-show-process-buffer () + "Show the inferior Lua process buffer." + (interactive) + (display-buffer lua-ts-inferior-buffer)) + +(defun lua-ts-hide-process-buffer () + "Hide the inferior Lua process buffer." + (interactive) + (delete-windows-on lua-ts-inferior-buffer)) + +(defun lua-ts-kill-process () + "Kill the inferior Lua process." + (interactive) + (with-current-buffer lua-ts-inferior-buffer + (kill-buffer-and-window))) + +(defun lua-ts-inferior--write-history (process _) + "Write history file for inferior Lua PROCESS." + ;; Depending on how the process is killed the buffer may not be + ;; around anymore; e.g. `kill-buffer'. + (when-let* ((buffer (process-buffer process)) + ((buffer-live-p (process-buffer process)))) + (with-current-buffer buffer (comint-write-input-ring)))) + +(defvar lua-ts-mode-map + (let ((map (make-sparse-keymap "Lua"))) + (define-key map "\C-c\C-n" 'lua-ts-inferior-lua) + (define-key map "\C-c\C-c" 'lua-ts-send-buffer) + (define-key map "\C-c\C-l" 'lua-ts-send-file) + (define-key map "\C-c\C-r" 'lua-ts-send-region) + map) + "Keymap for `lua-ts-mode' buffers.") + +(easy-menu-define lua-ts-mode-menu lua-ts-mode-map + "Menu bar entry for `lua-ts-mode'." + `("Lua" + ["Evaluate Buffer" lua-ts-send-buffer] + ["Evaluate File" lua-ts-send-file] + ["Evaluate Region" lua-ts-send-region] + "--" + ["Start Process" lua-ts-inferior-lua] + ["Show Process Buffer" lua-ts-show-process-buffer] + ["Hide Process Buffer" lua-ts-hide-process-buffer] + ["Kill Process" lua-ts-kill-process] + "--" + ["Customize" (lambda () (interactive) (customize-group "lua-ts"))])) ;;;###autoload (define-derived-mode lua-ts-mode prog-mode "Lua" - "Major mode for editing Lua files, powered by tree-sitter." + "Major mode for editing Lua files, powered by tree-sitter. + +\\{lua-ts-mode-map}" :syntax-table lua-ts--syntax-table + (use-local-map lua-ts-mode-map) (when (treesit-ready-p 'lua) (treesit-parser-create 'lua) @@ -404,20 +642,39 @@ lua-ts-mode (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"))) + (function ,(rx (or "function_declaration" + "function_definition"))) + (keyword ,(regexp-opt lua-ts--keywords + 'symbols)) + (loop-statement ,(rx (or "do_statement" + "for_statement" + "repeat_statement" + "while_statement"))) + (sentence (or function + loop-statement + ,(rx (or "assignment_statement" + "comment" + "field" + "function_call" + "if_statement" + "return_statement" + "variable_declaration")))) + (sexp (or function + keyword + loop-statement + ,(rx (or "arguments" + "break_statement" + "expression_list" + "false" + "identifier" + "nil" + "number" + "parameters" + "parenthesized_expression" + "string" + "table_constructor" + "true" + "vararg_expression")))) (text "comment")))) ;; Imenu. diff --git a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts index 040225c8580..9797467bbe5 100644 --- a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts @@ -5,148 +5,675 @@ Code: (lua-ts-mode) (indent-region (point-min) (point-max))) -Name: Basic Indent +Name: Chunk Indent =-= - print( -0, - 1 -) + print(1) + print(2) +=-= +print(1) +print(2) +=-=-= -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 +Name: Function Indent + +=-= +function f1(n) +print(n) +return n + 1 end -f({ - x = 1, - y = 2, - z = 3, -}) +local function f2(n) +print(n) +return n * 2 +end -;(function() -return false -)() +local f3 = function(n) +print(n) +return n / 3 +end + +function f4(...) +local f = function (...) +if ok +then print(1) +else print(0) +end +end +return f +end + +function f5(...) +local f = function (...) +if ok +then +print(1) +else +print(0) +end +end +return f +end + +function f6(...) +local f = function (...) +if ok then +print(1) +else +print(0) +end +end +return f +end + +;(function () + return true + end)() =-= -print( - 0, - 1 -) +function f1(n) + print(n) + return n + 1 +end -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 +local function f2(n) + print(n) + return n * 2 +end + +local f3 = function(n) + print(n) + return n / 3 +end + +function f4(...) + local f = function (...) + if ok + then print(1) + else print(0) + end end + return f end -f({ - x = 1, - y = 2, - z = 3, -}) +function f5(...) + local f = function (...) + if ok + then + print(1) + else + print(0) + end + end + return f +end + +function f6(...) + local f = function (...) + if ok then + print(1) + else + print(0) + end + end + return f +end -;(function() - return false -)() +;(function () + return true +end)() =-=-= -Name: Argument Indent +Name: Conditional Indent =-= -function h( -string, -number, -options) -print(string, number, options) +if true then +print(true) +return 1 +elseif false then +print(false) +return -1 +else +print(nil) +return 0 end -local p = h( -"sring", - 1000, - { -cost = 2, -length = 8, - parallelism = 4, -}) +if true + then + print(true) + return 1 + elseif false + then + print(false) + return -1 + else + print(nil) + return 0 +end + +if true + then return 1 + elseif false + then return -1 + else return 0 +end =-= -function h( - string, - number, - options) - print(string, number, options) +if true then + print(true) + return 1 +elseif false then + print(false) + return -1 +else + print(nil) + return 0 end -local p = h( - "sring", - 1000, - { - cost = 2, - length = 8, - parallelism = 4, - }) +if true +then + print(true) + return 1 +elseif false +then + print(false) + return -1 +else + print(nil) + return 0 +end + +if true +then return 1 +elseif false +then return -1 +else return 0 +end =-=-= -Name: Continuation Indent +Name: Loop Indent =-= +for k,v in pairs({}) do + print(k) + print(v) +end + +for i=1,10 + do print(i) +end + +while n < 10 do + n = n + 1 + print(n) +end + +while n < 10 + do + n = n + 1 + print(n) +end + +for i=0,9 do +repeat n = n+1 + until n > 99 +end + +repeat +z = z * 2 +print(z) +until z > 12 + + for i,x in ipairs(t) do + while i < 9 + do + local n = t[x] + repeat n = n + 1 + until n > #t + while n < 99 + do + print(n) + end + end + print(t[i]) + end + +do +local a = b +print(a + 1) +end +=-= +for k,v in pairs({}) do + print(k) + print(v) +end + +for i=1,10 +do print(i) +end + +while n < 10 do + n = n + 1 + print(n) +end + +while n < 10 +do + n = n + 1 + print(n) +end + +for i=0,9 do + repeat n = n+1 + until n > 99 +end + +repeat + z = z * 2 + print(z) +until z > 12 + +for i,x in ipairs(t) do + while i < 9 + do + local n = t[x] + repeat n = n + 1 + until n > #t + while n < 99 + do + print(n) + end + end + print(t[i]) +end + +do + local a = b + print(a + 1) +end +=-=-= + +Name: Bracket Indent + +=-= +fn( + ) + +tb={ + } +=-= +fn( +) + +tb={ +} +=-=-= + +Name: Multi-line String Indent + +=-= +local s = [[ + Multi-line + string content + ]] + function f() local str = [[ multi-line string ]] ---[[ -multi-line -comment - ]] return true end =-= +local s = [[ + Multi-line + string content + ]] + function f() local str = [[ multi-line string ]] - --[[ + return true +end +=-=-= + +Name: Multi-line Comment Indent + +=-= +--[[ + Multi-line + comment content + ]] + +function f() +--[[ +multi-line + comment + ]] + return true +end +=-= +--[[ + Multi-line + comment content + ]] + +function f() +--[[ multi-line -comment + comment ]] return true end =-=-= -Name: Loop Indent +Name: Argument Indent + +=-= + h( + "string", + 1000 + ) + +local p = h( +"string", + 1000 +) + +fn(1, +2, + 3) + +fn( 1, 2, +3, 4 ) + +f({ +x = 1, +y = 2, +z = 3, +}) + +f({ x = 1, +y = 2, +z = 3, }) + +Test({ +a=1 +}) + +Test({ +a = 1, +b = 2, +}, +nil) +=-= +h( + "string", + 1000 +) + +local p = h( + "string", + 1000 +) + +fn(1, + 2, + 3) + +fn( 1, 2, + 3, 4 ) + +f({ + x = 1, + y = 2, + z = 3, +}) + +f({ x = 1, + y = 2, + z = 3, }) + +Test({ + a=1 +}) + +Test({ + a = 1, + b = 2, + }, + nil) +=-=-= + +Name: Parameter Indent =-= -for k, v in pairs({}) do - print(k, v) +function f1( +a, +b +) +print(a,b) end -while n < 10 do -n = n + 1 +local function f2(a, + b) +print(a,b) end -repeat -z = z * 2 - until z > 12 +local f3 = function( a, b, + c, d ) +print(a,b,c,d) +end =-= -for k, v in pairs({}) do - print(k, v) +function f1( + a, + b +) + print(a,b) end -while n < 10 do - n = n + 1 +local function f2(a, + b) + print(a,b) end -repeat - z = z * 2 -until z > 12 +local f3 = function( a, b, + c, d ) + print(a,b,c,d) +end +=-=-= + +Name: Table Indent + +=-= +local Other = { + First={up={Step=true,Jump=true}, + down={Step=true,Jump=true}, + left={Step=true,Jump=true}, + right={Step=true,Jump=true}}, + Second={up={Step=true,Jump=true}, + down={Step=true,Jump=true}, + left={Step=true,Jump=true}, + right={Step=true,Jump=true}}, + Third={up={Goto=true}, + down={Goto=true}, + left={Goto=true}, + right={Goto=true}} +} + +local Other = { +a = 1, + b = 2, + c = 3, +} +=-= +local Other = { + First={up={Step=true,Jump=true}, + down={Step=true,Jump=true}, + left={Step=true,Jump=true}, + right={Step=true,Jump=true}}, + Second={up={Step=true,Jump=true}, + down={Step=true,Jump=true}, + left={Step=true,Jump=true}, + right={Step=true,Jump=true}}, + Third={up={Goto=true}, + down={Goto=true}, + left={Goto=true}, + right={Goto=true}} +} + +local Other = { + a = 1, + b = 2, + c = 3, +} +=-=-= + +Code: + (lambda () + (setq indent-tabs-mode nil) + (setq lua-ts-indent-offset 4) + (lua-ts-mode) + (indent-region (point-min) (point-max))) + +Name: End Indent + +=-= +function f(x) + for y=1,x.y do + for x=1,x.z do + if x.y and x.z then + if y <= x then + y = y + 1 + end end end end + return {x,y} or {math.random(),math.random()} + end + +for y=1,x.y do + for x=1,x.z do + if x.y and x.z then + if y <= x then + y = y + 1 + end + end end end +=-= +function f(x) + for y=1,x.y do + for x=1,x.z do + if x.y and x.z then + if y <= x then + y = y + 1 + end end end end + return {x,y} or {math.random(),math.random()} +end + +for y=1,x.y do + for x=1,x.z do + if x.y and x.z then + if y <= x then + y = y + 1 + end +end end end +=-=-= + +Name: Nested Function Indent + +=-= +function a(...) + return (function (x) + return x + end)(foo(...)) +end + +function b(n) + local x = 1 + return function (i) + return function (...) + return (function (n, ...) + return function (f, ...) + return (function (...) + if ... and x < 9 then + x = x + 1 + return ... + end end)(n(f, ...)) + end, ... + end)(i(...)) +end end end + +function c(f) + local f1 = function (...) + if nil ~= ... then + return f(...) + end + end + return function (i) + return function (...) + local fn = function (n, ...) + local x = function (f, ...) + return f1(n(f, ...)) + end + return x + end + return fn(i(...)) + end + end +end + +function d(f) + local f1 = function (c, f, ...) + if ... then + if f(...) then + return ... + else + return c(f, ...) + end end end + return function (i) + return function (...) + return (function (n, ...) + local function j (f, ...) + return f1(j, f, n(f, ...)) + end + return j, ... + end)(i(...)) +end end end + +function e (n, t) + return function (i) + return function (...) + return ( + function (n, ...) + local x, y, z = 0, {} + return (function (f, ...) + return (function (i, ...) return i(i, ...) end)( + function (i, ...) + return f(function (x, ...) + return i(i, ...)(x, ...) + end, ...) + end) + end)(function (j) + return function(f, ...) + return (function (c, f, ...) + if ... then + if n+1 == x then + local y1, x1 = y, x + y, x = {}, 0 + return (function (...) + z = ... + return ... + end)(t(y1-1, x1-1, ...)) + else + x = x - 1 + return c(f, + (function (...) + z = ... + return ... + end)(t(y, x, ...))) + end + elseif x ~= 0 then + x = 0 + return z, y + end end)(j, f, n(f, ...)) + end end), ... + end)(i(...)) +end end end =-=-= diff --git a/test/lisp/progmodes/lua-ts-mode-resources/movement.erts b/test/lisp/progmodes/lua-ts-mode-resources/movement.erts index 770aa23b18d..11e86f12926 100644 --- a/test/lisp/progmodes/lua-ts-mode-resources/movement.erts +++ b/test/lisp/progmodes/lua-ts-mode-resources/movement.erts @@ -147,7 +147,7 @@ end| print(1) =-=-= -Name: forward-sentence moves over for statements +Name: forward-sentence moves over do statements =-= |do @@ -417,34 +417,6 @@ Code: 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 =-= @@ -481,41 +453,91 @@ local t = { 1, 3 }| =-=-= -Code: - (lambda () - (lua-ts-mode) - (backward-sexp 1)) +Name: forward-sexp moves over parenthesized expressions -Point-Char: | +=-= +|(function (x) return x + 1 end)(41) +=-= +(function (x) return x + 1 end)|(41) +=-=-= -Name: backward-sexp moves over blocks +Name: forward-sexp moves over function declarations =-= -local function Test() - local t = { - a = 1, - } +|function foo (x) + if false then + print "foo" + elseif true then + print "bar" + end +end +=-= +function foo (x) + if false then + print "foo" + elseif true then + print "bar" + end +end| +=-=-= - if true then - print(1) - else - print(0) - end| +Name: forward-sexp moves over do statements + +=-= +|do + print(a + 1) end =-= -local function Test() - |local t = { - a = 1, - } +do + print(a + 1) +end| +=-=-= - if true then - print(1) - else - print(0) - end +Name: forward-sexp moves over for statements + +=-= +|for k,v in pairs({}) do + print(k, v) +end +=-= +for k,v in pairs({}) do + print(k, v) +end| +=-=-= + +Name: forward-sexp moves over repeat statements + +=-= +|repeat + n = n + 1 +until n > 10 +=-= +repeat + n = n + 1 +until n > 10| +=-=-= + +Name: forward-sexp moves over while statements + +=-= +|while n < 99 +do + n = n+1 end +=-= +while n < 99 +do + n = n+1 +end| =-=-= +Code: + (lambda () + (lua-ts-mode) + (backward-sexp 1)) + +Point-Char: | + Name: backward-sexp moves over arguments =-= @@ -551,3 +573,31 @@ local t = |{ 1, 2, 3 } =-=-= + +Name: backward-sexp moves over parenthesized expressions + +=-= +(function (x) return x + 1 end)|(41) +=-= +|(function (x) return x + 1 end)(41) +=-=-= + +Name: backward-sexp moves over function declarations + +=-= +function foo (x) + if false then + print "foo" + elseif true then + print "bar" + end +end| +=-= +|function foo (x) + if false then + print "foo" + elseif true then + print "bar" + end +end +=-=-= -- 2.41.0 --=-=-=--