emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[nongnu] elpa/lua-mode d7eaa8e 403/468: Add lua-backward-up-list command


From: Philip Kaludercic
Subject: [nongnu] elpa/lua-mode d7eaa8e 403/468: Add lua-backward-up-list command
Date: Thu, 5 Aug 2021 04:59:17 -0400 (EDT)

branch: elpa/lua-mode
commit d7eaa8e4e63f7292483e047b1f811403006dafe8
Author: immerrr <immerrr+lua@gmail.com>
Commit: immerrr <immerrr+lua@gmail.com>

    Add lua-backward-up-list command
---
 lua-mode.el          | 32 +++++++++++++++++++
 test/test-generic.el | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/utils.el        | 58 ++++++++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+)

diff --git a/lua-mode.el b/lua-mode.el
index 107dbc4..f7b1513 100644
--- a/lua-mode.el
+++ b/lua-mode.el
@@ -333,6 +333,7 @@ If the latter is nil, the keymap translates into 
`lua-mode-map' verbatim.")
                 #'lua-electric-match))
             lua--electric-indent-chars))
     (define-key result-map [menu-bar lua-mode] (cons "Lua" lua-mode-menu))
+    (define-key result-map [remap backward-up-list] 'lua-backward-up-list)
 
     ;; FIXME: see if the declared logic actually works
     ;; handle prefix-keyed bindings:
@@ -1288,6 +1289,37 @@ previous one even though it looked like an 
end-of-statement.")
       (beginning-of-line)
       (re-search-forward (concat "\\s *" lua-block-starter-regexp) line-end 
t))))
 
+(defun lua-backward-up-list ()
+  "Goto starter/opener of the block that contains point."
+  (interactive)
+  (let ((start-pos (point))
+        end-pos)
+    (or
+     ;; Return parent block opener token if it exists.
+     (cl-loop
+      ;; Search indentation modifier backward, return nil on failure.
+      always (lua-find-regexp 'backward lua-indentation-modifier-regexp)
+      ;; Fetch info about the found token
+      for token = (match-string-no-properties 0)
+      for token-info = (lua-get-block-token-info token)
+      for token-type = (lua-get-token-type token-info)
+      ;; If the token is a close token, continue to skip its opener. If not
+      ;; close, stop and return found token.
+      while (eq token-type 'close)
+      ;; Find matching opener to skip it and continue from beginning. Return 
nil
+      ;; on failure.
+      always (let ((position (lua-find-matching-token-word token 'backward)))
+               (and position (goto-char position)))
+      finally return token-info)
+     (progn
+       (setq end-pos (point))
+       (goto-char start-pos)
+       (signal 'scan-error
+               (list "Block open token not found"
+                     ;; If start-pos == end-pos, the "obstacle" is current
+                     (if (eql start-pos end-pos) start-pos (match-beginning 0))
+                     (if (eql start-pos end-pos) start-pos (match-end 0))))))))
+
 (defun lua-is-continuing-statement-p (&optional parse-start)
   "Return non-nil if the line at PARSE-START continues a statement.
 
diff --git a/test/test-generic.el b/test/test-generic.el
index d0356b7..1afcadc 100644
--- a/test/test-generic.el
+++ b/test/test-generic.el
@@ -107,3 +107,91 @@ local bar = require (\"bar\")
                      (funcall imenu-create-index-function))
              :to-equal '(("Requires" . ("foo" "bar")))))))
 
+
+(describe "lua-backward-up-list"
+  (it "doesn't move point when no parent block open token exists"
+    (expect "foo = bar<2><1>"
+            :with-point-at "<1>"
+            :after-executing (condition-case nil
+                                 (lua-backward-up-list)
+                               (scan-error nil))
+            :to-end-up-at "<2>"))
+
+  (it "doesn't move point when cannot skip intermediate close token"
+    (expect "foo, bar = baz}, qux<2><1>"
+            :with-point-at "<1>"
+            :after-executing (condition-case nil
+                                 (lua-backward-up-list)
+                               (scan-error nil))
+            :to-end-up-at "<2>"))
+
+  (it "works for ("
+    (expect "foo<2>(<1>"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "works for {"
+    (expect "\
+local foo = <2>{
+   1,
+   2,<1>
+   3,
+}"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "works for else"
+    (expect "if foo then 123 <2>else 456<1> end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "works for if/else/end"
+    (expect "if foo then 123 <2>else 456<1> end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "works for do blocks"
+    (expect "while foo <2>do print(123) <1>end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "works for while/do"
+    (expect "<2>while foo <1>do print(123) end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "skips complete while/do block"
+    (expect "<2>do while true do print(123) end <1>end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "skips complete repeat/until block"
+    (expect "<2>do repeat print(123) until foo <1>end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "skips complete if/elseif/else/end block"
+    (expect "<2>do if foo then bar() elseif baz() then qux() else quux() end 
<1>end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "skips from else to previous then"
+    (expect "if foo <2>then bar() <1>else baz() end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>"))
+
+  (it "skips from end to previous else"
+    (expect "if foo then bar() <2>else baz() <1>end"
+            :with-point-at "<1>"
+            :after-executing (lua-backward-up-list)
+            :to-end-up-at "<2>")))
diff --git a/test/utils.el b/test/utils.el
index b5ef98e..d641cc8 100644
--- a/test/utils.el
+++ b/test/utils.el
@@ -170,3 +170,61 @@ This is a mere typing/reading aid for lua-mode's font-lock 
tests."
         (indent-tabs-mode nil)
         (font-lock-verbose nil))
     (equal strs (lua-get-indented-strs strs))))
+
+(defun with-point-at-matcher (&rest args)
+  (let* (lua-code
+         origin-placeholder
+         (origin-marker (make-marker))
+         target-placeholder
+         (target-marker (make-marker))
+         body
+         last-elt
+         result
+         message
+         )
+    (cl-dolist (elt args)
+      (cond
+       ((eq last-elt :lua-code)
+        (setq lua-code (funcall elt)
+              last-elt nil))
+       ((eq last-elt :with-point-at)
+        (setq origin-placeholder (funcall elt)
+              last-elt nil))
+       ((eq last-elt :to-end-up-at)
+        (setq target-placeholder (funcall elt)
+              last-elt nil))
+       ((eq last-elt :after-executing)
+        ;; No funcall here, funcall when the buffer is set up.
+        (setq body elt
+              last-elt nil))
+       (t
+        (setq last-elt (if (functionp elt) (funcall elt) elt)))))
+
+    (with-lua-buffer
+     (insert lua-code)
+
+     (goto-char (point-min))
+     (set-marker target-marker (search-forward target-placeholder))
+     (replace-match "")
+
+     (goto-char (point-min))
+     (set-marker origin-marker (search-forward origin-placeholder))
+     (replace-match "")
+
+     (funcall body)
+
+     (setq result (equal (point) (marker-position target-marker)))
+     (setq message
+           (if result
+          (format "Expected point not to be here:\n\n%s|%s"
+                  (buffer-substring-no-properties (point-min) (point))
+                  (buffer-substring-no-properties (point) (point-max)))
+        (format "Expected point to be 
here:\n============\n%s|%s\n============\n\nInstead it was 
here:\n============\n%s|%s\n============"
+                (buffer-substring-no-properties (point-min) (marker-position 
target-marker))
+                (buffer-substring-no-properties (marker-position 
target-marker) (point-max))
+                (buffer-substring-no-properties (point-min) (point))
+                (buffer-substring-no-properties (point) (point-max)))))
+     (cons result message))))
+
+(buttercup-define-matcher :with-point-at (&rest args)
+  (apply #'with-point-at-matcher `(:lua-code ,(car args) :with-point-at ,@(cdr 
args))))



reply via email to

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