summaryrefslogtreecommitdiff
path: root/.emacs.d/lisp/lua-mode.el
diff options
context:
space:
mode:
Diffstat (limited to '.emacs.d/lisp/lua-mode.el')
-rw-r--r--.emacs.d/lisp/lua-mode.el991
1 files changed, 636 insertions, 355 deletions
diff --git a/.emacs.d/lisp/lua-mode.el b/.emacs.d/lisp/lua-mode.el
index 640e490..2d6a2d5 100644
--- a/.emacs.d/lisp/lua-mode.el
+++ b/.emacs.d/lisp/lua-mode.el
@@ -11,16 +11,16 @@
11;; Paul Du Bois <pld-lua@gelatinous.com> and 11;; Paul Du Bois <pld-lua@gelatinous.com> and
12;; Aaron Smith <aaron-lua@gelatinous.com>. 12;; Aaron Smith <aaron-lua@gelatinous.com>.
13;; 13;;
14;; URL: http://immerrr.github.com/lua-mode 14;; URL: https://immerrr.github.io/lua-mode
15;; Version: 20151025 15;; Version: 20210802
16;; Package-Requires: ((emacs "24.3")) 16;; Package-Requires: ((emacs "24.3"))
17;; 17;;
18;; This file is NOT part of Emacs. 18;; This file is NOT part of Emacs.
19;; 19;;
20;; This program is free software; you can redistribute it and/or 20;; This program is free software; you can redistribute it and/or modify
21;; modify it under the terms of the GNU General Public License 21;; it under the terms of the GNU General Public License as published by
22;; as published by the Free Software Foundation; either version 2 22;; the Free Software Foundation, either version 3 of the License, or
23;; of the License, or (at your option) any later version. 23;; (at your option) any later version.
24;; 24;;
25;; This program is distributed in the hope that it will be useful, 25;; This program is distributed in the hope that it will be useful,
26;; but WITHOUT ANY WARRANTY; without even the implied warranty of 26;; but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,15 +28,13 @@
28;; GNU General Public License for more details. 28;; GNU General Public License for more details.
29;; 29;;
30;; You should have received a copy of the GNU General Public License 30;; You should have received a copy of the GNU General Public License
31;; along with this program; if not, write to the Free Software 31;; along with this program. If not, see <https://www.gnu.org/licenses/>.
32;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
33;; MA 02110-1301, USA.
34 32
35;; Keywords: languages, processes, tools 33;; Keywords: languages, processes, tools
36 34
37;; This field is expanded to commit SHA, date & associated heads/tags during 35;; This field is expanded to commit SHA and commit date during the
38;; archive creation. 36;; archive creation.
39;; Revision: $Format:%h (%cD %d)$ 37;; Revision: $Format:%h (%cD)$
40;; 38;;
41 39
42;;; Commentary: 40;;; Commentary:
@@ -53,6 +51,12 @@
53;; - Var `lua-indent-string-contents': 51;; - Var `lua-indent-string-contents':
54;; set to `t` if you like to have contents of multiline strings to be 52;; set to `t` if you like to have contents of multiline strings to be
55;; indented like comments 53;; indented like comments
54;; - Var `lua-indent-nested-block-content-align':
55;; set to `nil' to stop aligning the content of nested blocks with the
56;; open parenthesis
57;; - Var `lua-indent-close-paren-align':
58;; set to `t' to align close parenthesis with the open parenthesis,
59;; rather than with the beginning of the line
56;; - Var `lua-mode-hook': 60;; - Var `lua-mode-hook':
57;; list of functions to execute when lua-mode is initialized 61;; list of functions to execute when lua-mode is initialized
58;; - Var `lua-documentation-url': 62;; - Var `lua-documentation-url':
@@ -115,7 +119,7 @@
115 119
116 (lua-name (symbol (seq (+ (any alpha "_")) (* (any alnum "_"))))) 120 (lua-name (symbol (seq (+ (any alpha "_")) (* (any alnum "_")))))
117 (lua-funcname (seq lua-name (* ws "." ws lua-name) 121 (lua-funcname (seq lua-name (* ws "." ws lua-name)
118 (opt ws ":" ws lua-name))) 122 (opt ws ":" ws lua-name)))
119 (lua-funcheader 123 (lua-funcheader
120 ;; Outer (seq ...) is here to shy-group the definition 124 ;; Outer (seq ...) is here to shy-group the definition
121 (seq (or (seq (symbol "function") ws (group-n 1 lua-funcname)) 125 (seq (or (seq (symbol "function") ws (group-n 1 lua-funcname))
@@ -123,15 +127,26 @@
123 (symbol "function"))))) 127 (symbol "function")))))
124 (lua-number 128 (lua-number
125 (seq (or (seq (+ digit) (opt ".") (* digit)) 129 (seq (or (seq (+ digit) (opt ".") (* digit))
126 (seq (* digit) (opt ".") (+ digit))) 130 (seq (* digit) (opt ".") (+ digit)))
127 (opt (regexp "[eE][+-]?[0-9]+")))) 131 (opt (regexp "[eE][+-]?[0-9]+"))))
128 (lua-assignment-op (seq "=" (or buffer-end (not (any "="))))) 132 (lua-assignment-op (seq "=" (or buffer-end (not (any "=")))))
129 (lua-token (or "+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">=" "<" 133 (lua-operator (or "+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">=" "<"
130 ">" "=" ";" ":" "," "." ".." "...")) 134 ">" "=" ";" ":" "," "." ".." "..."))
135 (lua-keyword-operator (symbol "and" "not" "or"))
131 (lua-keyword 136 (lua-keyword
132 (symbol "and" "break" "do" "else" "elseif" "end" "for" "function" 137 (symbol "break" "do" "else" "elseif" "end" "for" "function"
133 "goto" "if" "in" "local" "not" "or" "repeat" "return" 138 "goto" "if" "in" "local" "repeat" "return"
134 "then" "until" "while")))) 139 "then" "until" "while"))
140 (lua-up-to-9-variables
141 (seq (group-n 1 lua-name) ws
142 (? "," ws (group-n 2 lua-name) ws
143 (? "," ws (group-n 3 lua-name) ws
144 (? "," ws (group-n 4 lua-name) ws
145 (? "," ws (group-n 5 lua-name) ws
146 (? "," ws (group-n 6 lua-name) ws
147 (? "," ws (group-n 7 lua-name) ws
148 (? "," ws (group-n 8 lua-name) ws
149 (? "," ws (group-n 9 lua-name) ws))))))))))))
135 150
136 (defmacro lua-rx (&rest regexps) 151 (defmacro lua-rx (&rest regexps)
137 (eval `(rx-let ,lua--rx-bindings 152 (eval `(rx-let ,lua--rx-bindings
@@ -185,7 +200,7 @@ element is itself expanded with `lua-rx-to-string'. "
185 (setq form (if (eq 1 (length form)) 200 (setq form (if (eq 1 (length form))
186 (car form) 201 (car form)
187 (append '(or) form))) 202 (append '(or) form)))
188 (and (fboundp 'rx-form) ; Silence Emacs 27's byte-compiler. 203 (and (fboundp 'rx-form) ; Silence Emacs 27's byte-compiler.
189 (rx-form `(seq symbol-start ,form symbol-end) rx-parent))) 204 (rx-form `(seq symbol-start ,form symbol-end) rx-parent)))
190 205
191 (setq lua-rx-constituents (copy-sequence rx-constituents)) 206 (setq lua-rx-constituents (copy-sequence rx-constituents))
@@ -208,14 +223,25 @@ element is itself expanded with `lua-rx-to-string'. "
208 (opt (regexp "[eE][+-]?[0-9]+")))) 223 (opt (regexp "[eE][+-]?[0-9]+"))))
209 (lua-assignment-op 224 (lua-assignment-op
210 :rx (seq "=" (or buffer-end (not (any "="))))) 225 :rx (seq "=" (or buffer-end (not (any "=")))))
211 (lua-token 226 (lua-operator
212 :rx (or "+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">=" "<" 227 :rx (or "+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">=" "<"
213 ">" "=" ";" ":" "," "." ".." "...")) 228 ">" "=" ";" ":" "," "." ".." "..."))
229 (lua-keyword-operator
230 :rx (symbol "and" "not" "or"))
214 (lua-keyword 231 (lua-keyword
215 :rx (symbol "and" "break" "do" "else" "elseif" "end" "for" "function" 232 :rx (symbol "break" "do" "else" "elseif" "end" "for" "function"
216 "goto" "if" "in" "local" "not" "or" "repeat" "return" 233 "goto" "if" "in" "local" "repeat" "return"
217 "then" "until" "while"))) 234 "then" "until" "while"))
218 )))) 235 (lua-up-to-9-variables
236 :rx (seq (group-n 1 lua-name) ws
237 (? "," ws (group-n 2 lua-name) ws
238 (? "," ws (group-n 3 lua-name) ws
239 (? "," ws (group-n 4 lua-name) ws
240 (? "," ws (group-n 5 lua-name) ws
241 (? "," ws (group-n 6 lua-name) ws
242 (? "," ws (group-n 7 lua-name) ws
243 (? "," ws (group-n 8 lua-name) ws
244 (? "," ws (group-n 9 lua-name) ws)))))))))))))))
219 245
220 246
221;; Local variables 247;; Local variables
@@ -241,7 +267,11 @@ element is itself expanded with `lua-rx-to-string'. "
241 :group 'lua) 267 :group 'lua)
242 268
243(defcustom lua-default-application "lua" 269(defcustom lua-default-application "lua"
244 "Default application to run in Lua process." 270 "Default application to run in Lua process.
271
272Can be a string, where it denotes a command to be executed to
273start Lua process, or a (HOST . PORT) cons, that can be used to
274connect to Lua process running remotely."
245 :type '(choice (string) 275 :type '(choice (string)
246 (cons string integer)) 276 (cons string integer))
247 :group 'lua) 277 :group 'lua)
@@ -279,7 +309,7 @@ Should be a list of strings."
279 "The active Lua process") 309 "The active Lua process")
280 310
281(defvar lua-process-buffer nil 311(defvar lua-process-buffer nil
282 "Buffer used for communication with the Lua process") 312 "Buffer used for communication with the Lua process.")
283 313
284(defun lua--customize-set-prefix-key (prefix-key-sym prefix-key-val) 314(defun lua--customize-set-prefix-key (prefix-key-sym prefix-key-val)
285 (cl-assert (eq prefix-key-sym 'lua-prefix-key)) 315 (cl-assert (eq prefix-key-sym 'lua-prefix-key))
@@ -327,13 +357,13 @@ If the latter is nil, the keymap translates into `lua-mode-map' verbatim.")
327 #'lua-electric-match)) 357 #'lua-electric-match))
328 lua--electric-indent-chars)) 358 lua--electric-indent-chars))
329 (define-key result-map [menu-bar lua-mode] (cons "Lua" lua-mode-menu)) 359 (define-key result-map [menu-bar lua-mode] (cons "Lua" lua-mode-menu))
360 (define-key result-map [remap backward-up-list] 'lua-backward-up-list)
330 361
331 ;; FIXME: see if the declared logic actually works
332 ;; handle prefix-keyed bindings: 362 ;; handle prefix-keyed bindings:
333 ;; * if no prefix, set prefix-map as parent, i.e. 363 ;; * if no prefix, set prefix-map as parent, i.e.
334 ;; if key is not defined look it up in prefix-map 364 ;; if key is not defined look it up in prefix-map
335 ;; * if prefix is set, bind the prefix-map to that key 365 ;; * if prefix is set, bind the prefix-map to that key
336 (if (boundp 'lua-prefix-key) 366 (if lua-prefix-key
337 (define-key result-map (vector lua-prefix-key) lua-prefix-mode-map) 367 (define-key result-map (vector lua-prefix-key) lua-prefix-mode-map)
338 (set-keymap-parent result-map lua-prefix-mode-map)) 368 (set-keymap-parent result-map lua-prefix-mode-map))
339 result-map) 369 result-map)
@@ -372,8 +402,8 @@ If the latter is nil, the keymap translates into `lua-mode-map' verbatim.")
372 ;; NOTE: this doesn't traverse `compilation-search-path' when 402 ;; NOTE: this doesn't traverse `compilation-search-path' when
373 ;; looking for filename. 403 ;; looking for filename.
374 (not (file-exists-p (expand-file-name 404 (not (file-exists-p (expand-file-name
375 filename 405 filename
376 (when directory (expand-file-name directory)))))) 406 (when directory (expand-file-name directory))))))
377 (setq ad-return-value (current-buffer)) 407 (setq ad-return-value (current-buffer))
378 ad-do-it)) 408 ad-do-it))
379 409
@@ -397,7 +427,24 @@ Usually, stdin:XX line number points to nowhere."
397 "If non-nil, contents of multiline string will be indented. 427 "If non-nil, contents of multiline string will be indented.
398Otherwise leading amount of whitespace on each line is preserved." 428Otherwise leading amount of whitespace on each line is preserved."
399 :group 'lua 429 :group 'lua
400 :type 'boolean) 430 :type 'boolean
431 :safe #'booleanp)
432
433(defcustom lua-indent-nested-block-content-align t
434 "If non-nil, the contents of nested blocks are indented to
435align with the column of the opening parenthesis, rather than
436just forward by `lua-indent-level'."
437 :group 'lua
438 :type 'boolean
439 :safe #'booleanp)
440
441(defcustom lua-indent-close-paren-align t
442 "If non-nil, close parenthesis are aligned with their open
443parenthesis. If nil, close parenthesis are aligned to the
444beginning of the line."
445 :group 'lua
446 :type 'boolean
447 :safe #'booleanp)
401 448
402(defcustom lua-jump-on-traceback t 449(defcustom lua-jump-on-traceback t
403 "*Jump to innermost traceback location in *lua* buffer. When this 450 "*Jump to innermost traceback location in *lua* buffer. When this
@@ -476,118 +523,38 @@ traceback location."
476 "offset"))))) 523 "offset")))))
477 524
478 (cl-labels 525 (cl-labels
479 ((module-name-re (x) 526 ((module-name-re (x)
480 (concat "\\(?1:\\_<" 527 (concat "\\(?1:\\_<"
481 (if (listp x) (car x) x) 528 (if (listp x) (car x) x)
482 "\\_>\\)")) 529 "\\_>\\)"))
483 (module-members-re (x) (if (listp x) 530 (module-members-re (x) (if (listp x)
484 (concat "\\(?:[ \t]*\\.[ \t]*" 531 (concat "\\(?:[ \t]*\\.[ \t]*"
485 "\\_<\\(?2:" 532 "\\_<\\(?2:"
486 (regexp-opt (cdr x)) 533 (regexp-opt (cdr x))
487 "\\)\\_>\\)?") 534 "\\)\\_>\\)?")
488 ""))) 535 "")))
489 536
490 (concat 537 (concat
491 ;; common prefix: 538 ;; common prefix:
492 ;; - beginning-of-line 539 ;; - beginning-of-line
493 ;; - or neither of [ '.', ':' ] to exclude "foo.string.rep" 540 ;; - or neither of [ '.', ':' ] to exclude "foo.string.rep"
494 ;; - or concatenation operator ".." 541 ;; - or concatenation operator ".."
495 "\\(?:^\\|[^:. \t]\\|[.][.]\\)" 542 "\\(?:^\\|[^:. \t]\\|[.][.]\\)"
496 ;; optional whitespace 543 ;; optional whitespace
497 "[ \t]*" 544 "[ \t]*"
498 "\\(?:" 545 "\\(?:"
499 ;; any of modules/functions 546 ;; any of modules/functions
500 (mapconcat (lambda (x) (concat (module-name-re x) 547 (mapconcat (lambda (x) (concat (module-name-re x)
501 (module-members-re x))) 548 (module-members-re x)))
502 modules 549 modules
503 "\\|") 550 "\\|")
504 "\\)")))) 551 "\\)"))))
505 552
506 "A regexp that matches Lua builtin functions & variables. 553 "A regexp that matches Lua builtin functions & variables.
507 554
508This is a compilation of 5.1, 5.2 and 5.3 builtins taken from the 555This is a compilation of 5.1, 5.2 and 5.3 builtins taken from the
509index of respective Lua reference manuals.") 556index of respective Lua reference manuals.")
510 557
511(eval-and-compile
512 (defun lua-make-delimited-matcher (elt-regexp sep-regexp end-regexp)
513 "Construct matcher function for `font-lock-keywords' to match a sequence.
514
515It's supposed to match sequences with following EBNF:
516
517ELT-REGEXP { SEP-REGEXP ELT-REGEXP } END-REGEXP
518
519The sequence is parsed one token at a time. If non-nil is
520returned, `match-data' will have one or more of the following
521groups set according to next matched token:
522
5231. matched element token
5242. unmatched garbage characters
5253. misplaced token (i.e. SEP-REGEXP when ELT-REGEXP is expected)
5264. matched separator token
5275. matched end token
528
529Blanks & comments between tokens are silently skipped.
530Groups 6-9 can be used in any of argument regexps."
531 (let*
532 ((delimited-matcher-re-template
533 "\\=\\(?2:.*?\\)\\(?:\\(?%s:\\(?4:%s\\)\\|\\(?5:%s\\)\\)\\|\\(?%s:\\(?1:%s\\)\\)\\)")
534 ;; There's some magic to this regexp. It works as follows:
535 ;;
536 ;; A. start at (point)
537 ;; B. non-greedy match of garbage-characters (?2:)
538 ;; C. try matching separator (?4:) or end-token (?5:)
539 ;; D. try matching element (?1:)
540 ;;
541 ;; Simple, but there's a trick: pt.C and pt.D are embraced by one more
542 ;; group whose purpose is determined only after the template is
543 ;; formatted (?%s:):
544 ;;
545 ;; - if element is expected, then D's parent group becomes "shy" and C's
546 ;; parent becomes group 3 (aka misplaced token), so if D matches when
547 ;; an element is expected, it'll be marked with warning face.
548 ;;
549 ;; - if separator-or-end-token is expected, then it's the opposite:
550 ;; C's parent becomes shy and D's will be matched as misplaced token.
551 (elt-expected-re (format delimited-matcher-re-template
552 3 sep-regexp end-regexp "" elt-regexp))
553 (sep-or-end-expected-re (format delimited-matcher-re-template
554 "" sep-regexp end-regexp 3 elt-regexp)))
555
556 (lambda (end)
557 (let* ((prev-elt-p (match-beginning 1))
558 (prev-end-p (match-beginning 5))
559
560 (regexp (if prev-elt-p sep-or-end-expected-re elt-expected-re))
561 (comment-start (lua-comment-start-pos (syntax-ppss)))
562 (parse-stop end))
563
564 ;; If token starts inside comment, or end-token was encountered, stop.
565 (when (and (not comment-start)
566 (not prev-end-p))
567 ;; Skip all comments & whitespace. forward-comment doesn't have boundary
568 ;; argument, so make sure point isn't beyond parse-stop afterwards.
569 (while (and (< (point) end)
570 (forward-comment 1)))
571 (goto-char (min (point) parse-stop))
572
573 ;; Reuse comment-start variable to store beginning of comment that is
574 ;; placed before line-end-position so as to make sure token search doesn't
575 ;; enter that comment.
576 (setq comment-start
577 (lua-comment-start-pos
578 (save-excursion
579 (parse-partial-sexp (point) parse-stop
580 nil nil nil 'stop-inside-comment)))
581 parse-stop (or comment-start parse-stop))
582
583 ;; Now, let's match stuff. If regular matcher fails, declare a span of
584 ;; non-blanks 'garbage', and the next iteration will start from where the
585 ;; garbage ends. If couldn't match any garbage, move point to the end
586 ;; and return nil.
587 (or (re-search-forward regexp parse-stop t)
588 (re-search-forward "\\(?1:\\(?2:[^ \t]+\\)\\)" parse-stop 'skip)
589 (prog1 nil (goto-char end)))))))))
590
591 558
592(defvar lua-font-lock-keywords 559(defvar lua-font-lock-keywords
593 `(;; highlight the hash-bang line "#!/foo/bar/lua" as comment 560 `(;; highlight the hash-bang line "#!/foo/bar/lua" as comment
@@ -598,59 +565,67 @@ Groups 6-9 can be used in any of argument regexps."
598 . font-lock-constant-face) 565 . font-lock-constant-face)
599 566
600 ;; Keywords 567 ;; Keywords
601 (,(lua-rx lua-keyword) 568 (,(lua-rx (or lua-keyword lua-keyword-operator))
602 . font-lock-keyword-face) 569 . font-lock-keyword-face)
603 570
604 ;; Labels used by the "goto" statement 571 ;; Labels used by the "goto" statement
605 ;; Highlights the following syntax: ::label:: 572 ;; Highlights the following syntax: ::label::
606 (,(lua-rx "::" ws lua-name ws "::") 573 (,(lua-rx "::" ws lua-name ws "::")
607 . font-lock-constant-face) 574 . font-lock-constant-face)
608 575
609 ;; Highlights the name of the label in the "goto" statement like 576 ;; Highlights the name of the label in the "goto" statement like
610 ;; "goto label" 577 ;; "goto label"
611 (,(lua-rx (symbol (seq "goto" ws+ (group-n 1 lua-name)))) 578 (,(lua-rx (symbol (seq "goto" ws+ (group-n 1 lua-name))))
612 (1 font-lock-constant-face)) 579 (1 font-lock-constant-face))
613 580
614 ;; Highlight Lua builtin functions and variables 581 ;; Highlight Lua builtin functions and variables
615 (,lua--builtins 582 (,lua--builtins
616 (1 font-lock-builtin-face) (2 font-lock-builtin-face nil noerror)) 583 (1 font-lock-builtin-face) (2 font-lock-builtin-face nil noerror))
617 584
618 ("^[ \t]*\\_<for\\_>" 585 (,(lua-rx (symbol "for") ws+ lua-up-to-9-variables)
619 (,(lua-make-delimited-matcher (lua-rx lua-name) "," 586 (1 font-lock-variable-name-face)
620 (lua-rx (or (symbol "in") lua-assignment-op))) 587 (2 font-lock-variable-name-face nil noerror)
621 nil nil 588 (3 font-lock-variable-name-face nil noerror)
622 (1 font-lock-variable-name-face nil noerror) 589 (4 font-lock-variable-name-face nil noerror)
623 (2 font-lock-warning-face t noerror) 590 (5 font-lock-variable-name-face nil noerror)
624 (3 font-lock-warning-face t noerror))) 591 (6 font-lock-variable-name-face nil noerror)
625 592 (7 font-lock-variable-name-face nil noerror)
626 ;; Handle local variable/function names 593 (8 font-lock-variable-name-face nil noerror)
627 ;; local blalba, xyzzy = 594 (9 font-lock-variable-name-face nil noerror))
628 ;; ^^^^^^ ^^^^^
629 ;;
630 ;; local function foobar(x,y,z)
631 ;; ^^^^^^
632 ;; local foobar = function(x,y,z)
633 ;; ^^^^^^
634 ("^[ \t]*\\_<local\\_>"
635 (0 font-lock-keyword-face)
636
637 ;; (* nonl) at the end is to consume trailing characters or otherwise they
638 ;; delimited matcher would attempt to parse them afterwards and wrongly
639 ;; highlight parentheses as incorrect variable name characters.
640 (,(lua-rx point ws lua-funcheader (* nonl))
641 nil nil
642 (1 font-lock-function-name-face nil noerror))
643 595
644 (,(lua-make-delimited-matcher (lua-rx lua-name) "," 596 (,(lua-rx (symbol "function") (? ws+ lua-funcname) ws "(" ws lua-up-to-9-variables)
645 (lua-rx lua-assignment-op)) 597 (1 font-lock-variable-name-face)
646 nil nil 598 (2 font-lock-variable-name-face nil noerror)
647 (1 font-lock-variable-name-face nil noerror) 599 (3 font-lock-variable-name-face nil noerror)
648 (2 font-lock-warning-face t noerror) 600 (4 font-lock-variable-name-face nil noerror)
649 (3 font-lock-warning-face t noerror))) 601 (5 font-lock-variable-name-face nil noerror)
602 (6 font-lock-variable-name-face nil noerror)
603 (7 font-lock-variable-name-face nil noerror)
604 (8 font-lock-variable-name-face nil noerror)
605 (9 font-lock-variable-name-face nil noerror))
650 606
651 (,(lua-rx (or bol ";") ws lua-funcheader) 607 (,(lua-rx lua-funcheader)
652 (1 font-lock-function-name-face)) 608 (1 font-lock-function-name-face))
653 609
610 ;; local x, y, z
611 ;; local x = .....
612 ;;
613 ;; NOTE: this is intentionally below funcheader matcher, so that in
614 ;;
615 ;; local foo = function() ...
616 ;;
617 ;; "foo" is fontified as function-name-face, and variable-name-face is not applied.
618 (,(lua-rx (symbol "local") ws+ lua-up-to-9-variables)
619 (1 font-lock-variable-name-face)
620 (2 font-lock-variable-name-face nil noerror)
621 (3 font-lock-variable-name-face nil noerror)
622 (4 font-lock-variable-name-face nil noerror)
623 (5 font-lock-variable-name-face nil noerror)
624 (6 font-lock-variable-name-face nil noerror)
625 (7 font-lock-variable-name-face nil noerror)
626 (8 font-lock-variable-name-face nil noerror)
627 (9 font-lock-variable-name-face nil noerror))
628
654 (,(lua-rx (or (group-n 1 629 (,(lua-rx (or (group-n 1
655 "@" (symbol "author" "copyright" "field" "release" 630 "@" (symbol "author" "copyright" "field" "release"
656 "return" "see" "usage" "description")) 631 "return" "see" "usage" "description"))
@@ -662,13 +637,14 @@ Groups 6-9 can be used in any of argument regexps."
662 "Default expressions to highlight in Lua mode.") 637 "Default expressions to highlight in Lua mode.")
663 638
664(defvar lua-imenu-generic-expression 639(defvar lua-imenu-generic-expression
665 `((nil ,(lua-rx (or bol ";") ws (opt (seq (symbol "local") ws)) lua-funcheader) 1)) 640 `(("Requires" ,(lua-rx (or bol ";") ws (opt (seq (symbol "local") ws)) (group-n 1 lua-name) ws "=" ws (symbol "require")) 1)
641 (nil ,(lua-rx (or bol ";") ws (opt (seq (symbol "local") ws)) lua-funcheader) 1))
666 "Imenu generic expression for lua-mode. See `imenu-generic-expression'.") 642 "Imenu generic expression for lua-mode. See `imenu-generic-expression'.")
667 643
668(defvar lua-sexp-alist '(("then" . "end") 644(defvar lua-sexp-alist '(("then" . "end")
669 ("function" . "end") 645 ("function" . "end")
670 ("do" . "end") 646 ("do" . "end")
671 ("repeat" . "until"))) 647 ("repeat" . "until")))
672 648
673(defvar lua-mode-abbrev-table nil 649(defvar lua-mode-abbrev-table nil
674 "Abbreviation table used in lua-mode buffers.") 650 "Abbreviation table used in lua-mode buffers.")
@@ -709,11 +685,11 @@ Groups 6-9 can be used in any of argument regexps."
709 :syntax-table lua-mode-syntax-table 685 :syntax-table lua-mode-syntax-table
710 :group 'lua 686 :group 'lua
711 (setq-local font-lock-defaults '(lua-font-lock-keywords ;; keywords 687 (setq-local font-lock-defaults '(lua-font-lock-keywords ;; keywords
712 nil ;; keywords-only 688 nil ;; keywords-only
713 nil ;; case-fold 689 nil ;; case-fold
714 nil ;; syntax-alist 690 nil ;; syntax-alist
715 nil ;; syntax-begin 691 nil ;; syntax-begin
716 )) 692 ))
717 693
718 (setq-local syntax-propertize-function 694 (setq-local syntax-propertize-function
719 'lua--propertize-multiline-bounds) 695 'lua--propertize-multiline-bounds)
@@ -733,7 +709,7 @@ Groups 6-9 can be used in any of argument regexps."
733 ;; If electric-indent-chars is not defined, electric indentation is done 709 ;; If electric-indent-chars is not defined, electric indentation is done
734 ;; via `lua-mode-map'. 710 ;; via `lua-mode-map'.
735 (setq-local electric-indent-chars 711 (setq-local electric-indent-chars
736 (append electric-indent-chars lua--electric-indent-chars))) 712 (append electric-indent-chars lua--electric-indent-chars)))
737 713
738 714
739 ;; setup menu bar entry (XEmacs style) 715 ;; setup menu bar entry (XEmacs style)
@@ -770,7 +746,7 @@ Groups 6-9 can be used in any of argument regexps."
770 "Insert character and adjust indentation." 746 "Insert character and adjust indentation."
771 (interactive "P") 747 (interactive "P")
772 (let (blink-paren-function) 748 (let (blink-paren-function)
773 (self-insert-command (prefix-numeric-value arg))) 749 (self-insert-command (prefix-numeric-value arg)))
774 (if lua-electric-flag 750 (if lua-electric-flag
775 (lua-indent-line)) 751 (lua-indent-line))
776 (blink-matching-open)) 752 (blink-matching-open))
@@ -826,22 +802,41 @@ This function replaces previous prefix-key binding with a new one."
826 "Returns true if the point is in a string." 802 "Returns true if the point is in a string."
827 (save-excursion (elt (syntax-ppss pos) 3))) 803 (save-excursion (elt (syntax-ppss pos) 3)))
828 804
829(defun lua-comment-start-pos (parsing-state) 805(defun lua--containing-double-hyphen-start-pos ()
806 "Return position of the beginning comment delimiter (--).
807
808Emacs syntax framework does not consider comment delimiters as
809part of the comment itself, but for this package it is useful to
810consider point as inside comment when it is between the two hyphens"
811 (and (eql (char-before) ?-)
812 (eql (char-after) ?-)
813 (1- (point))))
814
815(defun lua-comment-start-pos (&optional parsing-state)
830 "Return position of comment containing current point. 816 "Return position of comment containing current point.
831 817
832If point is not inside a comment, return nil." 818If point is not inside a comment, return nil."
833 (and parsing-state (nth 4 parsing-state) (nth 8 parsing-state))) 819 (unless parsing-state (setq parsing-state (syntax-ppss)))
820 (and
821 ;; Not a string
822 (not (nth 3 parsing-state))
823 ;; Syntax-based comment
824 (or (and (nth 4 parsing-state) (nth 8 parsing-state))
825 (lua--containing-double-hyphen-start-pos))))
834 826
835(defun lua-comment-or-string-p (&optional pos) 827(defun lua-comment-or-string-p (&optional pos)
836 "Returns true if the point is in a comment or string." 828 "Returns true if the point is in a comment or string."
837 (save-excursion (let ((parse-result (syntax-ppss pos))) 829 (save-excursion (let ((parse-result (syntax-ppss pos)))
838 (or (elt parse-result 3) (elt parse-result 4))))) 830 (or (elt parse-result 3) (lua-comment-start-pos parse-result)))))
839 831
840(defun lua-comment-or-string-start-pos (&optional pos) 832(defun lua-comment-or-string-start-pos (&optional pos)
841 "Returns start position of string or comment which contains point. 833 "Returns start position of string or comment which contains point.
842 834
843If point is not inside string or comment, return nil." 835If point is not inside string or comment, return nil."
844 (save-excursion (elt (syntax-ppss pos) 8))) 836 (save-excursion
837 (when pos (goto-char pos))
838 (or (elt (syntax-ppss pos) 8)
839 (lua--containing-double-hyphen-start-pos))))
845 840
846;; They're propertized as follows: 841;; They're propertized as follows:
847;; 1. generic-comment 842;; 1. generic-comment
@@ -885,23 +880,15 @@ If none can be found before reaching LIMIT, return nil."
885 ;; inside strings or comments ending either at EOL or at valid token. 880 ;; inside strings or comments ending either at EOL or at valid token.
886 (and (setq last-search-matched 881 (and (setq last-search-matched
887 (re-search-forward lua-ml-begin-regexp limit 'noerror)) 882 (re-search-forward lua-ml-begin-regexp limit 'noerror))
888 883 ;; Ensure --[[ is not inside a comment or string.
889 ;; Handle triple-hyphen '---[[' situation in which the multiline
890 ;; opener should be skipped.
891 ;; 884 ;;
892 ;; In HYPHEN1-HYPHEN2-BRACKET1-BRACKET2 situation (match-beginning 885 ;; This includes "---[[" sequence, in which "--" at the beginning
893 ;; 0) points to HYPHEN1, but if there's another hyphen before 886 ;; creates a single-line comment, and thus "-[[" is no longer a
894 ;; HYPHEN1, standard syntax table will only detect comment-start 887 ;; multi-line opener.
895 ;; at HYPHEN2.
896 ;; 888 ;;
897 ;; We could check for comment-start at HYPHEN2, but then we'd have 889 ;; XXX: need to ensure syntax-ppss beyond (match-beginning 0) is
898 ;; to flush syntax-ppss cache to remove the result saying that at 890 ;; not calculated, or otherwise we'll need to flush the cache.
899 ;; HYPHEN2 there's no comment or string, because under some 891 (lua-comment-or-string-start-pos (match-beginning 0))))
900 ;; circumstances that would hide the fact that we put a
901 ;; comment-start property at HYPHEN1.
902 (or (lua-comment-or-string-start-pos (match-beginning 0))
903 (and (eq ?- (char-after (match-beginning 0)))
904 (eq ?- (char-before (match-beginning 0)))))))
905 892
906 last-search-matched)) 893 last-search-matched))
907 894
@@ -968,23 +955,70 @@ Return the amount the indentation changed by."
968 0 955 0
969 lua-indent-level)))))) 956 lua-indent-level))))))
970 957
971(defun lua-find-regexp (direction regexp &optional limit ignore-p) 958
959(defun lua--signum (x)
960 "Return 1 if X is positive, -1 if negative, 0 if zero."
961 ;; XXX: backport from cl-extras for Emacs24
962 (cond ((> x 0) 1) ((< x 0) -1) (t 0)))
963
964(defun lua--ensure-point-within-limit (limit backward)
965 "Return non-nil if point is within LIMIT going forward.
966
967With BACKWARD non-nil, return non-nil if point is within LIMIT
968going backward.
969
970If point is beyond limit, move it onto limit."
971 (if (= (lua--signum (- (point) limit))
972 (if backward 1 -1))
973 t
974 (goto-char limit)
975 nil))
976
977
978(defun lua--escape-from-string (&optional backward)
979 "Move point outside of string if it is inside one.
980
981By default, point is placed after the string, with BACKWARD it is
982placed before the string."
983 (interactive)
984 (let ((parse-state (syntax-ppss)))
985 (when (nth 3 parse-state)
986 (if backward
987 (goto-char (nth 8 parse-state))
988 (parse-partial-sexp (point) (line-end-position) nil nil (syntax-ppss) 'syntax-table))
989 t)))
990
991
992(defun lua-find-regexp (direction regexp &optional limit)
972 "Searches for a regular expression in the direction specified. 993 "Searches for a regular expression in the direction specified.
994
973Direction is one of 'forward and 'backward. 995Direction is one of 'forward and 'backward.
974By default, matches in comments and strings are ignored, but what to ignore is 996
975configurable by specifying ignore-p. If the regexp is found, returns point 997Matches in comments and strings are ignored. If the regexp is
976position, nil otherwise. 998found, returns point position, nil otherwise."
977ignore-p returns true if the match at the current point position should be 999 (let ((search-func (if (eq direction 'forward)
978ignored, nil otherwise."
979 (let ((ignore-func (or ignore-p 'lua-comment-or-string-p))
980 (search-func (if (eq direction 'forward)
981 're-search-forward 're-search-backward)) 1000 're-search-forward 're-search-backward))
982 (case-fold-search nil)) 1001 (case-fold-search nil))
983 (catch 'found 1002 (cl-loop
984 (while (funcall search-func regexp limit t) 1003 always (or (null limit)
985 (if (and (not (funcall ignore-func (match-beginning 0))) 1004 (lua--ensure-point-within-limit limit (not (eq direction 'forward))))
986 (not (funcall ignore-func (match-end 0)))) 1005 always (funcall search-func regexp limit 'noerror)
987 (throw 'found (point))))))) 1006 for match-beg = (match-beginning 0)
1007 for match-end = (match-end 0)
1008 while (or (lua-comment-or-string-p match-beg)
1009 (lua-comment-or-string-p match-end))
1010 do (let ((parse-state (syntax-ppss)))
1011 (cond
1012 ;; Inside a string
1013 ((nth 3 parse-state)
1014 (lua--escape-from-string (not (eq direction 'forward))))
1015 ;; Inside a comment
1016 ((nth 4 parse-state)
1017 (goto-char (nth 8 parse-state))
1018 (when (eq direction 'forward)
1019 (forward-comment 1)))))
1020 finally return (point))))
1021
988 1022
989(defconst lua-block-regexp 1023(defconst lua-block-regexp
990 (eval-when-compile 1024 (eval-when-compile
@@ -1050,7 +1084,7 @@ TOKEN-TYPE determines where the token occurs on a statement. open indicates that
1050 1084
1051(defun lua-get-token-type (token-info) 1085(defun lua-get-token-type (token-info)
1052 "Returns the relevant match regexp from token info" 1086 "Returns the relevant match regexp from token info"
1053 (nth 3 token-info)) 1087 (nth 3 token-info))
1054 1088
1055(defun lua-backwards-to-block-begin-or-end () 1089(defun lua-backwards-to-block-begin-or-end ()
1056 "Move backwards to nearest block begin or end. Returns nil if not successful." 1090 "Move backwards to nearest block begin or end. Returns nil if not successful."
@@ -1159,29 +1193,74 @@ If optional NOREPORT is non-nil, it won't flag an error if there
1159is no block open/close open." 1193is no block open/close open."
1160 (interactive) 1194 (interactive)
1161 ;; search backward to the beginning of the keyword if necessary 1195 ;; search backward to the beginning of the keyword if necessary
1162 (if (eq (char-syntax (following-char)) ?w) 1196 (when (and (eq (char-syntax (following-char)) ?w)
1163 (re-search-backward "\\_<" nil t)) 1197 (not (looking-at "\\_<")))
1198 (re-search-backward "\\_<" nil t))
1164 (let ((position (lua-goto-matching-block-token))) 1199 (let ((position (lua-goto-matching-block-token)))
1165 (if (and (not position) 1200 (if (and (not position)
1166 (not noreport)) 1201 (not noreport))
1167 (error "Not on a block control keyword or brace") 1202 (error "Not on a block control keyword or brace")
1168 position))) 1203 position)))
1169 1204
1205(defun lua-skip-ws-and-comments-backward (&optional limit)
1206 "Move point back skipping all whitespace and comments.
1207
1208If LIMIT is given, stop at it or before.
1209
1210Return non-nil if moved point."
1211 (interactive)
1212 (unless (lua-string-p)
1213 (let ((start-pos (point))
1214 (comment-start-pos (lua-comment-start-pos)))
1215 (setq limit (min (point) (or limit (point-min))))
1216 (when comment-start-pos
1217 (goto-char (max limit comment-start-pos)))
1218 (when (< limit (point)) (forward-comment (- limit (point))))
1219 (when (< (point) limit) (goto-char limit))
1220 (when (/= start-pos (point))
1221 (point)))))
1222
1223(defun lua-skip-ws-and-comments-forward (&optional limit)
1224 "Move point forward skipping all whitespace and comments.
1225
1226If LIMIT is given, stop at it or before.
1227
1228Return non-nil if moved point."
1229 (interactive)
1230 (unless (lua-string-p)
1231 (let ((start-pos (point))
1232 (comment-start-pos (lua-comment-start-pos)))
1233 (setq limit (max (point) (or limit (point-max))))
1234 ;; Escape from current comment. It is necessary to use "while" because
1235 ;; luadoc parameters have non-comment face, and parse-partial-sexp with
1236 ;; 'syntax-table flag will stop on them.
1237 (when comment-start-pos
1238 (goto-char comment-start-pos)
1239 (forward-comment 1))
1240 (when (< (point) limit) (forward-comment (- limit (point))))
1241 (when (< limit (point)) (goto-char limit))
1242 (when (/= start-pos (point))
1243 (point)))))
1244
1245
1170(defun lua-forward-line-skip-blanks (&optional back) 1246(defun lua-forward-line-skip-blanks (&optional back)
1171 "Move 1 line forward (back if BACK is non-nil) skipping blank lines. 1247 "Move 1 line forward/backward and skip all insignificant ws/comment lines.
1172 1248
1173Moves point 1 line forward (or backward) skipping lines that contain 1249Moves point 1 line forward (or backward) skipping lines that contain
1174no Lua code besides comments. The point is put to the beginning of 1250no Lua code besides comments. The point is put to the beginning of
1175the line. 1251the line.
1176 1252
1177Returns final value of point as integer or nil if operation failed." 1253Returns final value of point as integer or nil if operation failed."
1178 (catch 'found 1254 (let ((start-pos (point)))
1179 (while t 1255 (if back
1180 (unless (eql (forward-line (if back -1 1)) 0) ;; 0 means success 1256 (progn
1181 (throw 'found nil)) 1257 (beginning-of-line)
1182 (unless (or (looking-at "\\s *\\(--.*\\)?$") 1258 (lua-skip-ws-and-comments-backward))
1183 (lua-comment-or-string-p)) 1259 (forward-line)
1184 (throw 'found (point)))))) 1260 (lua-skip-ws-and-comments-forward))
1261 (beginning-of-line)
1262 (when (> (count-lines start-pos (point)) 0)
1263 (point))))
1185 1264
1186(eval-when-compile 1265(eval-when-compile
1187 (defconst lua-operator-class 1266 (defconst lua-operator-class
@@ -1190,17 +1269,17 @@ Returns final value of point as integer or nil if operation failed."
1190(defconst lua-cont-eol-regexp 1269(defconst lua-cont-eol-regexp
1191 (eval-when-compile 1270 (eval-when-compile
1192 (concat 1271 (concat
1193 "\\(\\_<" 1272 "\\(?:\\(?1:\\_<"
1194 (regexp-opt '("and" "or" "not" "in" "for" "while" 1273 (regexp-opt '("and" "or" "not" "in" "for" "while"
1195 "local" "function" "if" "until" "elseif" "return") 1274 "local" "function" "if" "until" "elseif" "return")
1196 t) 1275 t)
1197 "\\_>\\|" 1276 "\\_>\\)\\|"
1198 "\\(^\\|[^" lua-operator-class "]\\)" 1277 "\\(?:^\\|[^" lua-operator-class "]\\)\\(?2:"
1199 (regexp-opt '("+" "-" "*" "/" "%" "^" ".." "==" 1278 (regexp-opt '("+" "-" "*" "/" "%" "^" ".." "=="
1200 "=" "<" ">" "<=" ">=" "~=" "." ":" 1279 "=" "<" ">" "<=" ">=" "~=" "." ":"
1201 "&" "|" "~" ">>" "<<" "~") 1280 "&" "|" "~" ">>" "<<" "~" ",")
1202 t) 1281 t)
1203 "\\)" 1282 "\\)\\)"
1204 "\\s *\\=")) 1283 "\\s *\\="))
1205 "Regexp that matches the ending of a line that needs continuation. 1284 "Regexp that matches the ending of a line that needs continuation.
1206 1285
@@ -1212,14 +1291,14 @@ an optional whitespace till the end of the line.")
1212 (eval-when-compile 1291 (eval-when-compile
1213 (concat 1292 (concat
1214 "\\=\\s *" 1293 "\\=\\s *"
1215 "\\(\\_<" 1294 "\\(?:\\(?1:\\_<"
1216 (regexp-opt '("and" "or" "not") t) 1295 (regexp-opt '("and" "or" "not" "in") t)
1217 "\\_>\\|" 1296 "\\_>\\)\\|\\(?2:"
1218 (regexp-opt '("+" "-" "*" "/" "%" "^" ".." "==" 1297 (regexp-opt '("," "+" "-" "*" "/" "%" "^" ".." "=="
1219 "=" "<" ">" "<=" ">=" "~=" "." ":" 1298 "=" "<" ">" "<=" ">=" "~=" "." ":"
1220 "&" "|" "~" ">>" "<<" "~") 1299 "&" "|" "~" ">>" "<<" "~")
1221 t) 1300 t)
1222 "\\($\\|[^" lua-operator-class "]\\)" 1301 "\\)\\(?:$\\|[^" lua-operator-class "]\\)"
1223 "\\)")) 1302 "\\)"))
1224 "Regexp that matches a line that continues previous one. 1303 "Regexp that matches a line that continues previous one.
1225 1304
@@ -1231,44 +1310,101 @@ previous one even though it looked like an end-of-statement.")
1231(defun lua-last-token-continues-p () 1310(defun lua-last-token-continues-p ()
1232 "Return non-nil if the last token on this line is a continuation token." 1311 "Return non-nil if the last token on this line is a continuation token."
1233 (let ((line-begin (line-beginning-position)) 1312 (let ((line-begin (line-beginning-position))
1234 (line-end (line-end-position))) 1313 return-value)
1235 (save-excursion 1314 (save-excursion
1236 (end-of-line) 1315 (end-of-line)
1237 ;; we need to check whether the line ends in a comment and 1316 (lua-skip-ws-and-comments-backward line-begin)
1238 ;; skip that one. 1317 (setq return-value (and (re-search-backward lua-cont-eol-regexp line-begin t)
1239 (while (lua-find-regexp 'backward "-" line-begin 'lua-string-p) 1318 (or (match-beginning 1)
1240 (if (looking-at "--") 1319 (match-beginning 2))))
1241 (setq line-end (point)))) 1320 (if (and return-value
1242 (goto-char line-end) 1321 (string-equal (match-string-no-properties 0) "return"))
1243 (re-search-backward lua-cont-eol-regexp line-begin t)))) 1322 ;; "return" keyword is ambiguous and depends on next token
1323 (unless (save-excursion
1324 (goto-char (match-end 0))
1325 (forward-comment (point-max))
1326 (and
1327 ;; Not continuing: at end of file
1328 (not (eobp))
1329 (or
1330 ;; "function" keyword: it is a continuation, e.g.
1331 ;;
1332 ;; return
1333 ;; function() return 123 end
1334 ;;
1335 (looking-at (lua-rx (symbol "function")))
1336 ;; Looking at semicolon or any other keyword: not continuation
1337 (not (looking-at (lua-rx (or ";" lua-keyword)))))))
1338 (setq return-value nil)))
1339 return-value)))
1340
1244 1341
1245(defun lua-first-token-continues-p () 1342(defun lua-first-token-continues-p ()
1246 "Return non-nil if the first token on this line is a continuation token." 1343 "Return non-nil if the first token on this line is a continuation token."
1247 (let ((line-end (line-end-position))) 1344 (let ((line-end (line-end-position)))
1248 (save-excursion 1345 (save-excursion
1249 (beginning-of-line) 1346 (beginning-of-line)
1347 (lua-skip-ws-and-comments-forward line-end)
1250 ;; if first character of the line is inside string, it's a continuation 1348 ;; if first character of the line is inside string, it's a continuation
1251 ;; if strings aren't supposed to be indented, `lua-calculate-indentation' won't even let 1349 ;; if strings aren't supposed to be indented, `lua-calculate-indentation' won't even let
1252 ;; the control inside this function 1350 ;; the control inside this function
1253 (re-search-forward lua-cont-bol-regexp line-end t)))) 1351 (and
1352 (re-search-forward lua-cont-bol-regexp line-end t)
1353 (or (match-beginning 1)
1354 (match-beginning 2))))))
1254 1355
1255(defconst lua-block-starter-regexp
1256 (eval-when-compile
1257 (concat
1258 "\\(\\_<"
1259 (regexp-opt '("do" "while" "repeat" "until" "if" "then"
1260 "else" "elseif" "end" "for" "local") t)
1261 "\\_>\\)")))
1262 1356
1263(defun lua-first-token-starts-block-p () 1357(defun lua--backward-up-list-noerror ()
1264 "Return non-nil if the first token on this line is a block starter token." 1358 "Safe version of lua-backward-up-list that does not signal an error."
1265 (let ((line-end (line-end-position))) 1359 (condition-case nil
1266 (save-excursion 1360 (lua-backward-up-list)
1267 (beginning-of-line) 1361 (scan-error nil)))
1268 (re-search-forward (concat "\\s *" lua-block-starter-regexp) line-end t)))) 1362
1363
1364(defun lua-backward-up-list ()
1365 "Goto starter/opener of the block that contains point."
1366 (interactive)
1367 (let ((start-pos (point))
1368 end-pos)
1369 (or
1370 ;; Return parent block opener token if it exists.
1371 (cl-loop
1372 ;; Search indentation modifier backward, return nil on failure.
1373 always (lua-find-regexp 'backward lua-indentation-modifier-regexp)
1374 ;; Fetch info about the found token
1375 for token = (match-string-no-properties 0)
1376 for token-info = (lua-get-block-token-info token)
1377 for token-type = (lua-get-token-type token-info)
1378 ;; If the token is a close token, continue to skip its opener. If not
1379 ;; close, stop and return found token.
1380 while (eq token-type 'close)
1381 ;; Find matching opener to skip it and continue from beginning.
1382 ;;
1383 ;; Return nil on failure.
1384 always (let ((position (lua-find-matching-token-word token 'backward)))
1385 (and position (goto-char position)))
1386 finally return token-info)
1387 (progn
1388 (setq end-pos (point))
1389 (goto-char start-pos)
1390 (signal 'scan-error
1391 (list "Block open token not found"
1392 ;; If start-pos == end-pos, the "obstacle" is current
1393 (if (eql start-pos end-pos) start-pos (match-beginning 0))
1394 (if (eql start-pos end-pos) start-pos (match-end 0))))))))
1395
1396(defun lua--continuation-breaking-line-p ()
1397 "Return non-nil if looking at token(-s) that forbid continued line."
1398 (save-excursion
1399 (lua-skip-ws-and-comments-forward (line-end-position))
1400 (looking-at (lua-rx (or (symbol "do" "while" "repeat" "until"
1401 "if" "then" "elseif" "else"
1402 "for" "local")
1403 lua-funcheader)))))
1269 1404
1270(defun lua-is-continuing-statement-p (&optional parse-start) 1405
1271 "Return non-nil if the line at PARSE-START continues a statement. 1406(defun lua-is-continuing-statement-p-1 ()
1407 "Return non-nil if current lined continues a statement.
1272 1408
1273More specifically, return the point in the line that is continued. 1409More specifically, return the point in the line that is continued.
1274The criteria for a continuing statement are: 1410The criteria for a continuing statement are:
@@ -1276,17 +1412,71 @@ The criteria for a continuing statement are:
1276* the last token of the previous line is a continuing op, 1412* the last token of the previous line is a continuing op,
1277 OR the first token of the current line is a continuing op 1413 OR the first token of the current line is a continuing op
1278 1414
1415* the expression is not enclosed by a parentheses/braces/brackets"
1416 (let (prev-line continuation-pos parent-block-opener)
1417 (save-excursion (setq prev-line (lua-forward-line-skip-blanks 'back)))
1418 (and prev-line
1419 (not (lua--continuation-breaking-line-p))
1420 (save-excursion
1421 (or
1422 ;; Binary operator or keyword that implies continuation.
1423 (and (setq continuation-pos
1424 (or (lua-first-token-continues-p)
1425 (save-excursion (and (goto-char prev-line)
1426 ;; check last token of previous nonblank line
1427 (lua-last-token-continues-p)))))
1428 (not
1429 ;; Operators/keywords does not create continuation inside some blocks:
1430 (and
1431 (setq parent-block-opener (car-safe (lua--backward-up-list-noerror)))
1432 (or
1433 ;; - inside parens/brackets
1434 (member parent-block-opener '("(" "["))
1435 ;; - inside braces if it is a comma
1436 (and (eq (char-after continuation-pos) ?,)
1437 (equal parent-block-opener "{")))))
1438 continuation-pos))))))
1439
1440
1441(defun lua-is-continuing-statement-p (&optional parse-start)
1442 "Returns non-nil if the line at PARSE-START should be indented as continuation line.
1443
1444This true is when the line :
1445
1446* is continuing a statement itself
1447
1448* starts with a 1+ block-closer tokens, an top-most block opener is on a continuation line
1279" 1449"
1280 (let ((prev-line nil)) 1450 (save-excursion
1281 (save-excursion 1451 (if parse-start (goto-char parse-start))
1282 (if parse-start (goto-char parse-start)) 1452
1283 (save-excursion (setq prev-line (lua-forward-line-skip-blanks 'back))) 1453 ;; If line starts with a series of closer tokens, whether or not the line
1284 (and prev-line 1454 ;; is a continuation line is decided by the opener line, e.g.
1285 (not (lua-first-token-starts-block-p)) 1455 ;;
1286 (or (lua-first-token-continues-p) 1456 ;; x = foo +
1287 (and (goto-char prev-line) 1457 ;; long_function_name(
1288 ;; check last token of previous nonblank line 1458 ;; long_parameter_1,
1289 (lua-last-token-continues-p))))))) 1459 ;; long_parameter_2,
1460 ;; long_parameter_3,
1461 ;; ) + long_function_name2({
1462 ;; long_parameter_1,
1463 ;; long_parameter_2,
1464 ;; long_parameter_3,
1465 ;; })
1466 ;;
1467 ;; Final line, "})" is a continuation line, but it is decided by the
1468 ;; opener line, ") + long_function_name2({", which in its turn is decided
1469 ;; by the "long_function_name(" line, which is a continuation line
1470 ;; because the line before it ends with a binary operator.
1471 (cl-loop
1472 ;; Go to opener line
1473 while (and (lua--goto-line-beginning-rightmost-closer)
1474 (lua--backward-up-list-noerror))
1475 ;; If opener line is continuing, repeat. If opener line is not
1476 ;; continuing, return nil.
1477 always (lua-is-continuing-statement-p-1)
1478 ;; We get here if there was no opener to go to: check current line.
1479 finally return (lua-is-continuing-statement-p-1))))
1290 1480
1291(defun lua-make-indentation-info-pair (found-token found-pos) 1481(defun lua-make-indentation-info-pair (found-token found-pos)
1292 "Create a pair from FOUND-TOKEN and FOUND-POS for indentation calculation. 1482 "Create a pair from FOUND-TOKEN and FOUND-POS for indentation calculation.
@@ -1305,7 +1495,8 @@ Don't use standalone."
1305 (cons 'relative lua-indent-level)) 1495 (cons 'relative lua-indent-level))
1306 1496
1307 ;; block openers 1497 ;; block openers
1308 ((member found-token (list "{" "(" "[")) 1498 ((and lua-indent-nested-block-content-align
1499 (member found-token (list "{" "(" "[")))
1309 (save-excursion 1500 (save-excursion
1310 (let ((found-bol (line-beginning-position))) 1501 (let ((found-bol (line-beginning-position)))
1311 (forward-comment (point-max)) 1502 (forward-comment (point-max))
@@ -1326,9 +1517,10 @@ Don't use standalone."
1326 ;; nullify a previous then if on the same line. 1517 ;; nullify a previous then if on the same line.
1327 ((member found-token (list "until" "elseif")) 1518 ((member found-token (list "until" "elseif"))
1328 (save-excursion 1519 (save-excursion
1329 (let ((line (line-number-at-pos))) 1520 (let* ((line-beginning (line-beginning-position))
1330 (if (and (lua-goto-matching-block-token found-pos 'backward) 1521 (same-line (and (lua-goto-matching-block-token found-pos 'backward)
1331 (= line (line-number-at-pos))) 1522 (<= line-beginning (point)))))
1523 (if same-line
1332 (cons 'remove-matching 0) 1524 (cons 'remove-matching 0)
1333 (cons 'relative 0))))) 1525 (cons 'relative 0)))))
1334 1526
@@ -1337,23 +1529,41 @@ Don't use standalone."
1337 ;; either the next line will be indented correctly, or the end on the same 1529 ;; either the next line will be indented correctly, or the end on the same
1338 ;; line will remove the effect of the else. 1530 ;; line will remove the effect of the else.
1339 ((string-equal found-token "else") 1531 ((string-equal found-token "else")
1340 (save-excursion 1532 (save-excursion
1341 (let ((line (line-number-at-pos))) 1533 (let* ((line-beginning (line-beginning-position))
1342 (if (and (lua-goto-matching-block-token found-pos 'backward) 1534 (same-line (and (lua-goto-matching-block-token found-pos 'backward)
1343 (= line (line-number-at-pos))) 1535 (<= line-beginning (point)))))
1344 (cons 'replace-matching (cons 'relative lua-indent-level)) 1536 (if same-line
1345 (cons 'relative lua-indent-level))))) 1537 (cons 'replace-matching (cons 'relative lua-indent-level))
1538 (cons 'relative lua-indent-level)))))
1346 1539
1347 ;; Block closers. If they are on the same line as their openers, they simply 1540 ;; Block closers. If they are on the same line as their openers, they simply
1348 ;; eat up the matching indentation modifier. Otherwise, they pull 1541 ;; eat up the matching indentation modifier. Otherwise, they pull
1349 ;; indentation back to the matching block opener. 1542 ;; indentation back to the matching block opener.
1350 ((member found-token (list ")" "}" "]" "end")) 1543 ((member found-token (list ")" "}" "]" "end"))
1351 (save-excursion 1544 (save-excursion
1352 (let ((line (line-number-at-pos))) 1545 (let* ((line-beginning (line-beginning-position))
1353 (lua-goto-matching-block-token found-pos 'backward) 1546 (same-line (and (lua-goto-matching-block-token found-pos 'backward)
1354 (if (/= line (line-number-at-pos)) 1547 (<= line-beginning (point))))
1355 (lua-calculate-indentation-info (point)) 1548 (opener-pos (point))
1356 (cons 'remove-matching 0))))) 1549 opener-continuation-offset)
1550 (if same-line
1551 (cons 'remove-matching 0)
1552 (back-to-indentation)
1553 (setq opener-continuation-offset
1554 (if (lua-is-continuing-statement-p-1) lua-indent-level 0))
1555
1556 ;; Accumulate indentation up to opener, including indentation. If
1557 ;; there were no other indentation modifiers until said opener,
1558 ;; ensure there is no continuation after the closer.
1559 `(multiple . ((absolute . ,(- (current-indentation) opener-continuation-offset))
1560 ,@(when (/= opener-continuation-offset 0)
1561 (list (cons 'continued-line opener-continuation-offset)))
1562 ,@(delete nil (list (lua-calculate-indentation-info-1 nil opener-pos)))
1563 (cancel-continued-line . nil)))))))
1564
1565 ((member found-token '("do" "then"))
1566 `(multiple . ((cancel-continued-line . nil) (relative . ,lua-indent-level))))
1357 1567
1358 ;; Everything else. This is from the original code: If opening a block 1568 ;; Everything else. This is from the original code: If opening a block
1359 ;; (match-data 1 exists), then push indentation one level up, if it is 1569 ;; (match-data 1 exists), then push indentation one level up, if it is
@@ -1365,8 +1575,8 @@ Don't use standalone."
1365 ;; end of a block matched 1575 ;; end of a block matched
1366 (- lua-indent-level)))))) 1576 (- lua-indent-level))))))
1367 1577
1368(defun lua-add-indentation-info-pair (pair info) 1578(defun lua-add-indentation-info-pair (pair info-list)
1369 "Add the given indentation info PAIR to the list of indentation INFO. 1579 "Add the given indentation info PAIR to the list of indentation INFO-LIST.
1370This function has special case handling for two tokens: remove-matching, 1580This function has special case handling for two tokens: remove-matching,
1371and replace-matching. These two tokens are cleanup tokens that remove or 1581and replace-matching. These two tokens are cleanup tokens that remove or
1372alter the effect of a previously recorded indentation info. 1582alter the effect of a previously recorded indentation info.
@@ -1380,17 +1590,27 @@ and the cdr of the replace-matching info is added in its place. This is used
1380when a middle-of the block (the only case is 'else') is seen on the same line 1590when a middle-of the block (the only case is 'else') is seen on the same line
1381the block is opened." 1591the block is opened."
1382 (cond 1592 (cond
1593 ( (eq 'multiple (car pair))
1594 (let ((info-pair-elts (cdr pair)))
1595 (while info-pair-elts
1596 (setq info-list (lua-add-indentation-info-pair (car info-pair-elts) info-list)
1597 info-pair-elts (cdr info-pair-elts)))
1598 info-list))
1599 ( (eq 'cancel-continued-line (car pair))
1600 (if (eq (caar info-list) 'continued-line)
1601 (cdr info-list)
1602 info-list))
1383 ( (eq 'remove-matching (car pair)) 1603 ( (eq 'remove-matching (car pair))
1384 ; Remove head of list 1604 ;; Remove head of list
1385 (cdr info)) 1605 (cdr info-list))
1386 ( (eq 'replace-matching (car pair)) 1606 ( (eq 'replace-matching (car pair))
1387 ; remove head of list, and add the cdr of pair instead 1607 ;; remove head of list, and add the cdr of pair instead
1388 (cons (cdr pair) (cdr info))) 1608 (cons (cdr pair) (cdr info-list)))
1389 ( (listp (cdr-safe pair)) 1609 ( (listp (cdr-safe pair))
1390 (nconc pair info)) 1610 (nconc pair info-list))
1391 ( t 1611 ( t
1392 ; Just add the pair 1612 ;; Just add the pair
1393 (cons pair info)))) 1613 (cons pair info-list))))
1394 1614
1395(defun lua-calculate-indentation-info-1 (indentation-info bound) 1615(defun lua-calculate-indentation-info-1 (indentation-info bound)
1396 "Helper function for `lua-calculate-indentation-info'. 1616 "Helper function for `lua-calculate-indentation-info'.
@@ -1413,10 +1633,11 @@ The effect of each token can be either a shift relative to the current
1413indentation level, or indentation to some absolute column. This information 1633indentation level, or indentation to some absolute column. This information
1414is collected in a list of indentation info pairs, which denote absolute 1634is collected in a list of indentation info pairs, which denote absolute
1415and relative each, and the shift/column to indent to." 1635and relative each, and the shift/column to indent to."
1416 (let (indentation-info) 1636 (let (indentation-info cont-stmt-pos)
1417 1637 (while (setq cont-stmt-pos (lua-is-continuing-statement-p))
1418 (while (lua-is-continuing-statement-p) 1638 (lua-forward-line-skip-blanks 'back)
1419 (lua-forward-line-skip-blanks 'back)) 1639 (when (< cont-stmt-pos (point))
1640 (goto-char cont-stmt-pos)))
1420 1641
1421 ;; calculate indentation modifiers for the line itself 1642 ;; calculate indentation modifiers for the line itself
1422 (setq indentation-info (list (cons 'absolute (current-indentation)))) 1643 (setq indentation-info (list (cons 'absolute (current-indentation))))
@@ -1438,7 +1659,7 @@ and relative each, and the shift/column to indent to."
1438 1659
1439 ;; if it's the first non-continued line, subtract one level 1660 ;; if it's the first non-continued line, subtract one level
1440 (when (eq (car (car indentation-info)) 'continued-line) 1661 (when (eq (car (car indentation-info)) 'continued-line)
1441 (pop indentation-info))) 1662 (push (cons 'stop-continued-line (- lua-indent-level)) indentation-info)))
1442 1663
1443 ;; add modifiers found in this continuation line 1664 ;; add modifiers found in this continuation line
1444 (setq indentation-info 1665 (setq indentation-info
@@ -1448,19 +1669,29 @@ and relative each, and the shift/column to indent to."
1448 indentation-info)) 1669 indentation-info))
1449 1670
1450 1671
1451(defun lua-accumulate-indentation-info (info) 1672(defun lua-accumulate-indentation-info (reversed-indentation-info)
1452 "Accumulates the indentation information previously calculated by 1673 "Accumulates the indentation information previously calculated by
1453lua-calculate-indentation-info. Returns either the relative indentation 1674lua-calculate-indentation-info. Returns either the relative indentation
1454shift, or the absolute column to indent to." 1675shift, or the absolute column to indent to."
1455 (let ((info-list (reverse info)) 1676 (let (indentation-info
1456 (type 'relative) 1677 (type 'relative)
1457 (accu 0)) 1678 (accu 0))
1679 ;; Aggregate all neighbouring relative offsets, reversing the INFO list.
1680 (cl-dolist (elt reversed-indentation-info)
1681 (if (and (eq (car elt) 'relative)
1682 (eq (caar indentation-info) 'relative))
1683 (setcdr (car indentation-info) (+ (cdar indentation-info) (cdr elt)))
1684 (push elt indentation-info)))
1685
1686 ;; Aggregate indentation info, taking 'absolute modifiers into account.
1458 (mapc (lambda (x) 1687 (mapc (lambda (x)
1459 (setq accu (if (eq 'absolute (car x)) 1688 (let ((new-val (cdr x)))
1460 (progn (setq type 'absolute) 1689 (if (eq 'absolute (car x))
1461 (cdr x)) 1690 (progn (setq type 'absolute
1462 (+ accu (cdr x))))) 1691 accu new-val))
1463 info-list) 1692 (setq accu (+ accu new-val)))))
1693 indentation-info)
1694
1464 (cons type accu))) 1695 (cons type accu)))
1465 1696
1466(defun lua-calculate-indentation-block-modifier (&optional parse-end) 1697(defun lua-calculate-indentation-block-modifier (&optional parse-end)
@@ -1510,6 +1741,7 @@ one."
1510 ;; right hand side 1741 ;; right hand side
1511 (or "{" 1742 (or "{"
1512 "function" 1743 "function"
1744 "("
1513 (seq (group-n 1 (eval lua--function-name-rx) (* blank)) 1745 (seq (group-n 1 (eval lua--function-name-rx) (* blank))
1514 (any "({"))))))) 1746 (any "({")))))))
1515 1747
@@ -1551,6 +1783,27 @@ left-shifter expression. "
1551 (looking-at lua--left-shifter-regexp) 1783 (looking-at lua--left-shifter-regexp)
1552 (= old-point (match-end 1)))))) 1784 (= old-point (match-end 1))))))
1553 1785
1786(defun lua--goto-line-beginning-rightmost-closer (&optional parse-start)
1787 (let (case-fold-search pos line-end-pos return-val)
1788 (save-excursion
1789 (if parse-start (goto-char parse-start))
1790 (setq line-end-pos (line-end-position))
1791 (back-to-indentation)
1792 (unless (lua-comment-or-string-p)
1793 (cl-loop while (and (<= (point) line-end-pos)
1794 (looking-at lua-indentation-modifier-regexp))
1795 for token-info = (lua-get-block-token-info (match-string 0))
1796 for token-type = (lua-get-token-type token-info)
1797 while (not (eq token-type 'open))
1798 do (progn
1799 (setq pos (match-beginning 0)
1800 return-val token-info)
1801 (goto-char (match-end 0))
1802 (forward-comment (line-end-position))))))
1803 (when pos
1804 (progn
1805 (goto-char pos)
1806 return-val))))
1554 1807
1555 1808
1556(defun lua-calculate-indentation-override (&optional parse-start) 1809(defun lua-calculate-indentation-override (&optional parse-start)
@@ -1562,26 +1815,44 @@ line containing block-open token for the last block-close token
1562in the sequence. 1815in the sequence.
1563 1816
1564If not, return nil." 1817If not, return nil."
1565 (let (case-fold-search token-info block-token-pos) 1818 (let (case-fold-search rightmost-closer-info opener-info opener-pos)
1566 (save-excursion 1819 (save-excursion
1567 (if parse-start (goto-char parse-start)) 1820 (when (and (setq rightmost-closer-info (lua--goto-line-beginning-rightmost-closer parse-start))
1821 (setq opener-info (lua--backward-up-list-noerror))
1822 ;; Ensure opener matches closer.
1823 (string-match (lua-get-token-match-re rightmost-closer-info 'backward)
1824 (car opener-info)))
1568 1825
1569 (back-to-indentation) 1826 ;; Special case: "middle" tokens like for/do, while/do, if/then,
1570 (unless (lua-comment-or-string-p) 1827 ;; elseif/then: corresponding "end" or corresponding "else" must be
1571 (while 1828 ;; unindented to the beginning of the statement, which is not
1572 (and (looking-at lua-indentation-modifier-regexp) 1829 ;; necessarily the same as beginning of string that contains "do", e.g.
1573 (setq token-info (lua-get-block-token-info (match-string 0))) 1830 ;;
1574 (not (eq 'open (lua-get-token-type token-info)))) 1831 ;; while (
1575 (setq block-token-pos (match-beginning 0)) 1832 ;; foo and
1576 (goto-char (match-end 0)) 1833 ;; bar) do
1577 (skip-syntax-forward " " (line-end-position))) 1834 ;; hello_world()
1835 ;; end
1836 (setq opener-pos (point))
1837 (when (/= (- opener-pos (line-beginning-position)) (current-indentation))
1838 (unless (or
1839 (and (string-equal (car opener-info) "do")
1840 (member (car (lua--backward-up-list-noerror)) '("while" "for")))
1841 (and (string-equal (car opener-info) "then")
1842 (member (car (lua--backward-up-list-noerror)) '("if" "elseif"))))
1843 (goto-char opener-pos)))
1844
1845 ;; (let (cont-stmt-pos)
1846 ;; (while (setq cont-stmt-pos (lua-is-continuing-statement-p))
1847 ;; (goto-char cont-stmt-pos)))
1848 ;; Exception cases: when the start of the line is an assignment,
1849 ;; go to the start of the assignment instead of the matching item
1850 (if (and lua-indent-close-paren-align
1851 (member (car opener-info) '("{" "(" "["))
1852 (not (lua-point-is-after-left-shifter-p)))
1853 (current-column)
1854 (current-indentation))))))
1578 1855
1579 (when (lua-goto-matching-block-token block-token-pos 'backward)
1580 ;; Exception cases: when the start of the line is an assignment,
1581 ;; go to the start of the assignment instead of the matching item
1582 (if (lua-point-is-after-left-shifter-p)
1583 (current-indentation)
1584 (current-column)))))))
1585 1856
1586(defun lua-calculate-indentation () 1857(defun lua-calculate-indentation ()
1587 "Return appropriate indentation for current line as Lua code." 1858 "Return appropriate indentation for current line as Lua code."
@@ -1689,11 +1960,11 @@ This function just searches for a `end' at the beginning of a line."
1689 (goto-char (point-min)) 1960 (goto-char (point-min))
1690 (while (re-search-forward "[\"'\\\t\\\n]" nil t) 1961 (while (re-search-forward "[\"'\\\t\\\n]" nil t)
1691 (cond 1962 (cond
1692 ((string= (match-string 0) "\n") 1963 ((string= (match-string 0) "\n")
1693 (replace-match "\\\\n")) 1964 (replace-match "\\\\n"))
1694 ((string= (match-string 0) "\t") 1965 ((string= (match-string 0) "\t")
1695 (replace-match "\\\\t")) 1966 (replace-match "\\\\t"))
1696 (t 1967 (t
1697 (replace-match "\\\\\\&" t)))) 1968 (replace-match "\\\\\\&" t))))
1698 (concat "'" (buffer-string) "'")))) 1969 (concat "'" (buffer-string) "'"))))
1699 1970
@@ -1706,32 +1977,33 @@ This function just searches for a `end' at the beginning of a line."
1706PROGRAM defaults to NAME, which defaults to `lua-default-application'. 1977PROGRAM defaults to NAME, which defaults to `lua-default-application'.
1707When called interactively, switch to the process buffer." 1978When called interactively, switch to the process buffer."
1708 (interactive) 1979 (interactive)
1709 (or switches
1710 (setq switches lua-default-command-switches))
1711 (setq name (or name (if (consp lua-default-application) 1980 (setq name (or name (if (consp lua-default-application)
1712 (car lua-default-application) 1981 (car lua-default-application)
1713 lua-default-application))) 1982 lua-default-application)))
1714 (setq program (or program lua-default-application)) 1983 (setq program (or program lua-default-application))
1715 (setq lua-process-buffer (apply 'make-comint name program startfile switches)) 1984 ;; don't re-initialize if there already is a lua process
1716 (setq lua-process (get-buffer-process lua-process-buffer)) 1985 (unless (comint-check-proc (format "*%s*" name))
1717 (set-process-query-on-exit-flag lua-process nil) 1986 (setq lua-process-buffer (apply #'make-comint name program startfile
1718 (with-current-buffer lua-process-buffer 1987 (or switches lua-default-command-switches)))
1719 ;; wait for prompt 1988 (setq lua-process (get-buffer-process lua-process-buffer))
1720 (while (not (lua-prompt-line)) 1989 (set-process-query-on-exit-flag lua-process nil)
1721 (accept-process-output (get-buffer-process (current-buffer))) 1990 (with-current-buffer lua-process-buffer
1722 (goto-char (point-max))) 1991 ;; enable error highlighting in stack traces
1723 ;; send initialization code 1992 (require 'compile)
1724 (lua-send-string lua-process-init-code) 1993 (setq lua--repl-buffer-p t)
1994 (make-local-variable 'compilation-error-regexp-alist)
1995 (setq compilation-error-regexp-alist
1996 (cons (list lua-traceback-line-re 1 2)
1997 compilation-error-regexp-alist))
1998 (compilation-shell-minor-mode 1)
1999 (setq-local comint-prompt-regexp lua-prompt-regexp)
1725 2000
1726 ;; enable error highlighting in stack traces 2001 ;; Don't send initialization code until seeing the prompt to ensure that
1727 (require 'compile) 2002 ;; the interpreter is ready.
1728 (setq lua--repl-buffer-p t) 2003 (while (not (lua-prompt-line))
1729 (make-local-variable 'compilation-error-regexp-alist) 2004 (accept-process-output (get-buffer-process (current-buffer)))
1730 (setq compilation-error-regexp-alist 2005 (goto-char (point-max)))
1731 (cons (list lua-traceback-line-re 1 2) 2006 (lua-send-string lua-process-init-code)))
1732 compilation-error-regexp-alist))
1733 (compilation-shell-minor-mode 1)
1734 (setq-local comint-prompt-regexp lua-prompt-regexp))
1735 2007
1736 ;; when called interactively, switch to process buffer 2008 ;; when called interactively, switch to process buffer
1737 (if (called-interactively-p 'any) 2009 (if (called-interactively-p 'any)
@@ -1739,8 +2011,7 @@ When called interactively, switch to the process buffer."
1739 2011
1740(defun lua-get-create-process () 2012(defun lua-get-create-process ()
1741 "Return active Lua process creating one if necessary." 2013 "Return active Lua process creating one if necessary."
1742 (unless (comint-check-proc lua-process-buffer) 2014 (lua-start-process)
1743 (lua-start-process))
1744 lua-process) 2015 lua-process)
1745 2016
1746(defun lua-kill-process () 2017(defun lua-kill-process ()
@@ -1868,12 +2139,22 @@ Create a Lua process if one doesn't already exist."
1868 (when (buffer-live-p lua-process-buffer) 2139 (when (buffer-live-p lua-process-buffer)
1869 (delete-windows-on lua-process-buffer))) 2140 (delete-windows-on lua-process-buffer)))
1870 2141
2142(defun lua--funcname-char-p (c)
2143 "Check if character C is part of a function name.
2144Return nil if C is nil. See `lua-funcname-at-point'."
2145 (and c (string-match-p "\\`[A-Za-z_.]\\'" (string c))))
2146
1871(defun lua-funcname-at-point () 2147(defun lua-funcname-at-point ()
1872 "Get current Name { '.' Name } sequence." 2148 "Get current Name { '.' Name } sequence."
1873 ;; FIXME: copying/modifying syntax table for each call may incur a penalty 2149 (when (or (lua--funcname-char-p (char-before))
1874 (with-syntax-table (copy-syntax-table) 2150 (lua--funcname-char-p (char-after)))
1875 (modify-syntax-entry ?. "_") 2151 (save-excursion
1876 (current-word t))) 2152 (save-match-data
2153 (re-search-backward "\\`\\|[^A-Za-z_.]")
2154 ;; NOTE: `point' will be either at the start of the buffer or on a
2155 ;; non-symbol character.
2156 (re-search-forward "\\([A-Za-z_]+\\(?:\\.[A-Za-z_]+\\)*\\)")
2157 (match-string-no-properties 1)))))
1877 2158
1878(defun lua-search-documentation () 2159(defun lua-search-documentation ()
1879 "Search Lua documentation for the word at the point." 2160 "Search Lua documentation for the word at the point."