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: 30.0.50; lua-ts-mode semantic indentation problems Date: Tue, 03 Oct 2023 10:04:56 -0500 Message-ID: <87ttr73fuz.fsf@pub.pink> References: <87fs36vvxl.fsf@gmail.com> <87v8bz3905.fsf@pub.pink> <878r8vwm9v.fsf@gmail.com> <87il7z5g3g.fsf@pub.pink> <87lecs4ttm.fsf@gmail.com> <87fs302oz3.fsf@pub.pink> <87wmw83qg2.fsf@gmail.com> <874jj847dr.fsf@pub.pink> 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="18940"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 66159@debbugs.gnu.org, Eli Zaretskii To: Andrey Listopadov Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Oct 03 17:07:05 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 1qngzI-0004Yw-Oi for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 03 Oct 2023 17:07:05 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qngz1-0007vo-7P; Tue, 03 Oct 2023 11:06:47 -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 1qngyz-0007vS-Uv for bug-gnu-emacs@gnu.org; Tue, 03 Oct 2023 11:06:45 -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 1qngyz-0005pB-MI for bug-gnu-emacs@gnu.org; Tue, 03 Oct 2023 11:06:45 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qngzG-0004y1-CT for bug-gnu-emacs@gnu.org; Tue, 03 Oct 2023 11:07: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: Tue, 03 Oct 2023 15:07: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.169634561519081 (code B ref 66159); Tue, 03 Oct 2023 15:07:02 +0000 Original-Received: (at 66159) by debbugs.gnu.org; 3 Oct 2023 15:06:55 +0000 Original-Received: from localhost ([127.0.0.1]:40570 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qngz8-0004xg-Oc for submit@debbugs.gnu.org; Tue, 03 Oct 2023 11:06:55 -0400 Original-Received: from out-209.mta0.migadu.com ([91.218.175.209]:30960) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qngz5-0004xV-L9 for 66159@debbugs.gnu.org; Tue, 03 Oct 2023 11:06:53 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pub.pink; s=key1; t=1696345592; 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=w73klHk0dX5h/mkusqXhpqdOwflAGIOfn+uQ/ljKEKU=; b=WGWMfXfhxm90vVSYWTMR++x7qVLb22ZBkgnb2smw48E9B6qhyS5Gh3fpkkvtdeKHOekCSn 2/+PiCJtqUmJFizZJQEf5cnGxPL1PWzvaLd54BcSe0Nqapi8T0O/CEfSsUINwP5cl19qxB xc0FtHA6vnQwvkPDiV/rMD27i+apUnI= X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. In-reply-to: <874jj847dr.fsf@pub.pink> 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:271713 Archived-At: --=-=-= Content-Type: text/plain Whoops. Looks like I forgot to update the patch before sending. This one should be better. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Various-improvements-in-lus-ts-mode-Bug-66159.patch >From 4ee42d82557e188537693c3a27b2246ed690c2a6 Mon Sep 17 00:00:00 2001 From: john muhl Date: Sat, 23 Sep 2023 10:49:11 -0500 Subject: [PATCH] Various improvements in lus-ts-mode (Bug#66159) * lisp/progmodes/lua-ts-mode.el (lua-ts--first-child) (lua-ts--end-indent-offset) (lua-ts--simple-indent-rules): Improve indentation. (lua-ts-inferior--write-history) (lua-ts-inferior-lua): Improve inferior Lua interaction. (lua-ts-mode-map): Add keymap. (lua-ts-mode-menu): Add menu. (lua-ts-mode): Add mode map and improve sexp navigation. (lua-ts-send-buffer) (lua-ts-send-file) (lua-ts-send-line) (lua-ts-send-region) (lua-ts-show-process-buffer) (lua-ts-hide-process-buffer) (lua-ts-kill-process): New functions. (lua-ts-mode-hook) (lua-ts-inferior-prompt-regexp) (lua-ts-inferior-prompt) (lua-ts-inferior-prompt-continue) (lua-ts-inferior-history): New variables. --- lisp/progmodes/lua-ts-mode.el | 210 ++++++++++++++++-- .../lua-ts-mode-resources/indent.erts | 199 +++++++++++++++++ .../lua-ts-mode-resources/movement.erts | 56 +++++ 3 files changed, 441 insertions(+), 24 deletions(-) diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index 030a3585158..d1930d9f2b1 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -39,7 +39,9 @@ (require 'rx)) (declare-function treesit-node-child-by-field-name "treesit.c") +(declare-function treesit-node-first-child-for-pos "treesit.c") (declare-function treesit-node-type "treesit.c") +(declare-function treesit-node-start "treesit.c") (declare-function treesit-parser-create "treesit.c") (declare-function treesit-search-subtree "treesit.c") @@ -48,6 +50,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 @@ -86,9 +97,22 @@ lua-ts-inferior-startfile :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-prompt ">" + "The prompt of the inferior Lua process." + :type 'string + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-prompt-continue ">>" + "The continuation prompt of the inferior Lua process." + :type 'string + :group 'lua-ts + :version "30.1") + +(defcustom lua-ts-inferior-history nil + "File used to save command history of the inferior Lua process." + :type '(choice (const nil) file) + :safe 'string-or-null-p :group 'lua-ts :version "30.1") @@ -233,27 +257,65 @@ lua-ts--font-lock-settings '((ERROR) @font-lock-warning-face)) "Tree-sitter font-lock settings for `lua-ts-mode'.") +(defun lua-ts--first-child (node _p _b &rest _) + "Matches if NODE is the first among its siblings." + (= (treesit-node-index node) 1)) + +(defun lua-ts--end-indent-offset (_n _p _b &rest _) + "Calculate indent offset based on `end' count." + (let* ((beg (line-beginning-position)) + (end (line-end-position)) + (count (count-matches "end" beg end))) + (- (* (1- count) lua-ts-indent-offset)))) + (defvar lua-ts--simple-indent-rules `((lua + ((n-p-gp "end" "function_definition" "arguments") + parent 0) + ((n-p-gp "end" "function_definition" "parenthesized_expression") + parent 0) + ((and (n-p-gp "block" "function_definition" "arguments") + (lambda (_n parent &rest _) + (save-excursion + (goto-char (treesit-node-start parent)) + (backward-char 2) + (not (looking-at ")"))))) + parent lua-ts-indent-offset) + ((and (n-p-gp "block" "function_definition" "parenthesized_expression") + (lambda (node _p bol &rest _) + (equal "assignment_statement" + (treesit-node-type + (treesit-node-first-child-for-pos node bol))))) + parent lua-ts-indent-offset) ((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 "do") standalone-parent 0) + ((node-is "then") standalone-parent 0) ((node-is "else_statement") parent-bol 0) ((node-is "elseif_statement") parent-bol 0) - ((node-is "end") parent-bol 0) + ((node-is "end") parent-bol lua-ts--end-indent-offset) ((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 "function_definition") standalone-parent lua-ts-indent-offset) + ((parent-is "parenthesized_expression") + standalone-parent 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) + ((and (parent-is "table_constructor") lua-ts--first-child) + parent-bol lua-ts-indent-offset) + ((parent-is "table_constructor") (nth-sibling 1) 0) + ((and (parent-is "arguments") lua-ts--first-child) + parent-bol lua-ts-indent-offset) + ((parent-is "arguments") (nth-sibling 1) 0) + ((and (parent-is "parameters") lua-ts--first-child) + parent-bol lua-ts-indent-offset) + ((parent-is "parameters") (nth-sibling 1) 0) ((parent-is "ERROR") no-indent 0)))) (defvar lua-ts--syntax-table @@ -348,30 +410,128 @@ lua-ts-flymake-luacheck (process-send-region lua-ts--flymake-process (point-min) (point-max)) (process-send-eof lua-ts--flymake-process)))) +(defun lua-ts-inferior--write-history (process _event) + "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 buffer))) + (with-current-buffer buffer (comint-write-input-ring)))) + ;;;###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)))))) + (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 comint-prompt-regexp (rx-to-string `(: bol + ,lua-ts-inferior-prompt + space))) + (setq-local comint-input-ignoredups t) + (setq-local comint-input-ring-file-name lua-ts-inferior-history) + (setq-local comint-prompt-read-only t) + (setq-local comint-use-prompt-regexp t) + (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) + 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-window) + (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))) + +(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) @@ -415,7 +575,9 @@ lua-ts-mode "while_statement"))) (sexp ,(rx (or "arguments" "block" + "function_declaration" "parameters" + "parenthesized_expression" "string" "table_constructor"))) (text "comment")))) diff --git a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts index 040225c8580..c407d3400f8 100644 --- a/test/lisp/progmodes/lua-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/lua-ts-mode-resources/indent.erts @@ -32,6 +32,22 @@ f({ ;(function() return false )() + +function foo (e) + if e == nil + then return 1000 + else return e + end +end + +function foo (e) + if e == nil + then + return 1000 + else + return e + end +end =-= print( 0, @@ -57,6 +73,22 @@ f({ ;(function() return false )() + +function foo (e) + if e == nil + then return 1000 + else return e + end +end + +function foo (e) + if e == nil + then + return 1000 + else + return e + end +end =-=-= Name: Argument Indent @@ -77,6 +109,13 @@ cost = 2, length = 8, parallelism = 4, }) + +fn(1, +2, + 3) + +fn(1, 2, +3) =-= function h( string, @@ -93,6 +132,13 @@ local p = h( length = 8, parallelism = 4, }) + +fn(1, + 2, + 3) + +fn(1, 2, + 3) =-=-= Name: Continuation Indent @@ -130,10 +176,20 @@ for k, v in pairs({}) do print(k, v) end +for i=1,10 + do + print(i) +end + while n < 10 do n = n + 1 end +while n < 10 + do + n = n + 1 +end + repeat z = z * 2 until z > 12 @@ -142,11 +198,154 @@ for k, v in pairs({}) do print(k, v) end +for i=1,10 +do + print(i) +end + while n < 10 do n = n + 1 end +while n < 10 +do + n = n + 1 +end + repeat z = z * 2 until z > 12 =-=-= + +Name: Parameter Indent + +=-= +fn(a, +b) + +fn(a, b, +c) + +fn( +a, +b +) +=-= +fn(a, + b) + +fn(a, b, + c) + +fn( + a, + b +) +=-=-= + +Code: + (lambda () + (setq indent-tabs-mode nil) + (setq lua-ts-indent-offset 4) + (lua-ts-mode) + (indent-region (point-min) (point-max))) + +Name: Table Indent + +=-= +local Recipe = { + Floor={up={Floor=true,Wall=true}, + down={Floor=true,Wall=true}, + left={Floor=true,Wall=true}, + right={Floor=true,Wall=true}}, + Wall={up={Floor=true,Wall=true}, + down={Floor=true,Wall=true}, + left={Floor=true,Wall=true}, + right={Floor=true,Wall=true}}, + Corridor={up={Corridoor=true}, + down={Corridoor=true}, + left={Corridoor=true}, + right={Corridoor=true}} +} + +local Other = { +a = 1, + b = 2, + c = 3, +} +=-= +local Recipe = { + Floor={up={Floor=true,Wall=true}, + down={Floor=true,Wall=true}, + left={Floor=true,Wall=true}, + right={Floor=true,Wall=true}}, + Wall={up={Floor=true,Wall=true}, + down={Floor=true,Wall=true}, + left={Floor=true,Wall=true}, + right={Floor=true,Wall=true}}, + Corridor={up={Corridoor=true}, + down={Corridoor=true}, + left={Corridoor=true}, + right={Corridoor=true}} +} + +local Other = { + a = 1, + b = 2, + c = 3, +} +=-=-= + +Name: Single Line End + +=-= +function lowest_entropy_cell(world) + local lowest,res=math.huge,nil + for y=1,world.height do + for x=1,world.width do + local cell=world:get(x,y) + if cell.is_set then + local e=cell_enthropy(cell) + trace(e) + if e <= lowest then + lowest,res=e,{x,y} + end end end end + return res or {math.random(w.w),math.random(w.h)} +end + +for y=1,world.height do + for x=1,world.width do + local cell=world:get(x,y) + if cell.is_set then + local e=cell_enthropy(cell) + trace(e) + if e <= lowest then + lowest,res=e,{x,y} + end + end end end +=-= +function lowest_entropy_cell(world) + local lowest,res=math.huge,nil + for y=1,world.height do + for x=1,world.width do + local cell=world:get(x,y) + if cell.is_set then + local e=cell_enthropy(cell) + trace(e) + if e <= lowest then + lowest,res=e,{x,y} + end end end end + return res or {math.random(w.w),math.random(w.h)} +end + +for y=1,world.height do + for x=1,world.width do + local cell=world:get(x,y) + if cell.is_set then + local e=cell_enthropy(cell) + trace(e) + if e <= lowest then + lowest,res=e,{x,y} + end +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..afebe93de3f 100644 --- a/test/lisp/progmodes/lua-ts-mode-resources/movement.erts +++ b/test/lisp/progmodes/lua-ts-mode-resources/movement.erts @@ -481,6 +481,34 @@ local t = { 1, 3 }| =-=-= +Name: forward-sexp moves over parenthesized expressions + +=-= +|(function (x) return x + 1 end)(41) +=-= +(function (x) return x + 1 end)|(41) +=-=-= + +Name: forward-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| +=-=-= + Code: (lambda () (lua-ts-mode) @@ -551,3 +579,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 --=-=-=--