]> git.eshelyaron.com Git - sweep.git/commitdiff
ADDED: numeric argument for sweeprolog-forward/backward-hole
authorEshel Yaron <me@eshelyaron.com>
Thu, 26 Jan 2023 15:21:09 +0000 (17:21 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sat, 28 Jan 2023 16:31:59 +0000 (18:31 +0200)
* sweeprolog.el (sweeprolog-count-holes): new command, counts holes
in the current buffer.
(sweeprolog-forward-hole, sweeprolog-backward-hole): new numeric
argument, corresponding to the prefix argument when called
interactively.  With positive/negative numeric argument, move over
that many holes.  With zero numeric argument, call
sweeprolog-count-holes instead.

README.org
sweeprolog-tests.el
sweeprolog.el

index d306ddb0bf3ce3381d29dae0ef7e2b14674ce601..67d436cec013b56bbe2bd8bf7b2c6a368e8ccf35 100644 (file)
@@ -998,10 +998,15 @@ Use these commands to move between holes in the current Prolog buffer:
 
 #+KINDEX: C-c C-i
 - Key: C-c TAB (sweeprolog-forward-hole) :: Move point to the next
-  hole in the buffer.
+  hole in the buffer and select it as the region.  With numeric prefix
+  argument /n/, move forward over /n/ - 1 holes and select the next one.
 #+KINDEX: C-c C-S-i
 - Key: C-c S-TAB (sweeprolog-backward-hole) :: Move point to the
-  previous hole in the buffer.
+  previous hole in the buffer and select it as the region.  With
+  numeric prefix argument /n/, move backward over /n/ - 1 holes and select
+  the next one.
+- Key: C-0 C-c TAB (sweeprolog-count-holes) :: Display the number of
+  holes that are present in the buffer.
 - Command: sweeprolog-forward-hole-on-tab-mode :: Toggle moving to the
   next hole in the buffer with ~TAB~ if the current line is already
   properly indented.
@@ -1010,9 +1015,18 @@ To jump to the next hole in a ~sweeprolog-mode~ buffer, use the command
 ~M-x sweeprolog-forward-hole~, bound by default to ~C-c TAB~ (or ~C-c C-i~).
 This command sets up the region to cover the next hole after point
 leaving the cursor at right after the hole.  To jump to the previous
-hole instead, use ~sweeprolog-backward-hole~ or call
+hole use ~C-c S-TAB~ (~sweeprolog-backward-hole~), or call
 ~sweeprolog-forward-hole~ with a negative prefix argument (~C-- C-c TAB~).
 
+You can also call ~sweeprolog-forward-hole~ and ~sweeprolog-backward-hole~
+with a numeric prefix argument to jump over the specified number of
+holes.  For example, typing ~C-3 C-c TAB~ skips the next two holes in
+the buffer and selects the third as the region.  As a special case, if
+you call these commands with a zero prefix argument (~C-0 C-c TAB~),
+they invoke the command ~sweeprolog-count-holes~ instead of jumping.
+This command counts how many holes are left in the current buffer and
+reports its finding via a message in the echo area.
+
 When the minor mode ~sweeprolog-forward-hole-on-tab-mode~ is enabled,
 the ~TAB~ key is bound to a command moves to the next hole when called
 in a properly indented line (otherwise it indents the line).  This
index e44ccca1501bdda0acb59661204e91949a017d42..c4e3b1fc8f87c9a32aef6a28cbf1acc55d59763d 100644 (file)
@@ -287,6 +287,29 @@ foo(Foo) :- bar.
     (should (string= (buffer-string)
                      "foo(bar, (_->_;_), _):-_."))))
 
+(ert-deftest forward-many-holes ()
+  "Tests jumping over holes with `sweeprolog-forward-hole'."
+  (let ((temp (make-temp-file "sweeprolog-test"
+                              nil
+                              ".pl"
+                              "\n"
+                              )))
+    (find-file-literally temp)
+    (sweeprolog-mode)
+    (goto-char (point-min))
+    (sweeprolog-insert-term-with-holes ":-" 2)
+    (deactivate-mark)
+    (goto-char (point-max))
+    (sweeprolog-insert-term-with-holes ":-" 2)
+    (goto-char (point-min))
+    (should (= (sweeprolog-count-holes) 4))
+    (sweeprolog-forward-hole 2)
+    (should (= (point) 5))
+    (sweeprolog-forward-hole -1)
+    (should (= (point) 2))
+    (sweeprolog-forward-hole -2)
+    (should (= (point) 8))))
+
 (ert-deftest plunit-testset-skeleton ()
   "Tests inserting PlUnit test-set blocks."
   (let ((temp (make-temp-file "sweeprolog-test"
index 893a77b51b7229dba0d1989340832928e587bcf2..0cec3c681f7a8c9580d133f9e02796c79ea11905 100644 (file)
@@ -506,6 +506,8 @@ token via its `help-echo' text property."
       (eq major-mode 'sweeprolog-mode) ]
     [ "Search Term" sweeprolog-term-search
       (derived-mode-p 'sweeprolog-mode)]
+    [ "Count Holes" sweeprolog-count-holes
+      (derived-mode-p 'sweeprolog-mode)]
     "--"
     [ "Set Prolog Flag" sweeprolog-set-prolog-flag t ]
     [ "Install Prolog Package" sweeprolog-pack-install t ]
@@ -3094,6 +3096,25 @@ is the prefix argument."
         (setq end (1+ end)))
       (1+ end))))
 
+
+(defun sweeprolog-count-holes (&optional interactive)
+  "Count holes in the current buffer and return the total number.
+If INTERACTIVE is non-nil, as it is when called interactively,
+also print a message with the result."
+  (interactive (list t) sweeprolog-mode)
+  (save-excursion
+    (goto-char (point-min))
+    (let ((hole nil) (count 0))
+      (while (setq hole (sweeprolog--next-hole))
+        (goto-char (cdr hole))
+        (setq count (1+ count)))
+      (when interactive
+        (message "%s %s left in buffer %s."
+                 (if (zerop count) "No" count)
+                 (ngettext "hole" "holes" count)
+                 (buffer-name)))
+      count)))
+
 (defun sweeprolog--next-hole (&optional wrap)
   "Return the bounds of the next hole in the current buffer.
 
@@ -3127,10 +3148,12 @@ point and the end of the buffer."
 
 When WRAP in non-nil, wrap around if no holes are found between
 point and the beginning of the buffer."
+  (when (and (< (point-min) (point))
+             (sweeprolog-at-hole-p (1- (point))))
+    (forward-char -1)
+    (while (and (sweeprolog-at-hole-p) (not (bobp)))
+      (forward-char -1)))
   (let ((start (point)))
-    (when (use-region-p)
-      (goto-char (region-beginning))
-      (deactivate-mark))
     (when (sweeprolog--backward-wrap wrap)
       (if-let ((current-hole-beg (sweeprolog-beginning-of-hole)))
           (cons current-hole-beg
@@ -3138,7 +3161,7 @@ point and the beginning of the buffer."
         (let ((point (point)))
           (while (not (or (sweeprolog-at-hole-p) (bobp)))
             (forward-char -1))
-          (if (bobp)
+          (if (and (bobp) (not (sweeprolog-at-hole-p)))
               (or (and wrap
                        (save-restriction
                          (goto-char (point-max))
@@ -3148,44 +3171,37 @@ point and the beginning of the buffer."
             (cons (sweeprolog-beginning-of-hole)
                   (sweeprolog-end-of-hole))))))))
 
-(defun sweeprolog--forward-hole (&optional wrap)
-  (if-let ((hole (sweeprolog--next-hole wrap))
-           (beg  (car hole))
-           (end  (cdr hole)))
-      (progn
-        (goto-char end)
-        (push-mark beg t t))
-    (user-error "No holes following point")))
-
-(defun sweeprolog--backward-hole (&optional wrap)
-  (if-let ((hole (sweeprolog--previous-hole wrap))
-           (beg  (car hole))
-           (end  (cdr hole)))
-      (progn
-        (goto-char end)
-        (push-mark beg t t))
-    (user-error "No holes before point")))
+(defun sweeprolog-backward-hole (&optional n)
+  "Move point to the previous Nth hole in the current buffer.
+If N is 0, display the number of holes in the current buffer by
+calling `sweeprolog-count-holes' instead.
 
-(defun sweeprolog-backward-hole (&optional arg)
-  "Move point to the previous hole in a `sweeprolog-mode' buffer.
-
-With negative prefix argument ARG, move to the next hole
-instead."
+See also `sweeprolog-forward-hole'."
   (interactive "p" sweeprolog-mode)
-  (setq arg (or arg 1))
-  (sweeprolog-forward-hole (- arg)))
+  (sweeprolog-forward-hole (- (or n 1))))
 
-(defun sweeprolog-forward-hole (&optional arg)
-  "Move point to the next hole in a `sweeprolog-mode' buffer.
+(defun sweeprolog-forward-hole (&optional n)
+  "Move point to the next Nth hole in the current buffer.
+If N is 0, display the number of holes in the current buffer by
+calling `sweeprolog-count-holes' instead.
 
-With negative prefix argument ARG, move to the previous hole
-instead."
+See also `sweeprolog-backward-hole'."
   (interactive "p" sweeprolog-mode)
-  (setq arg (or arg 1)
-        deactivate-mark nil)
-  (if (> 0 arg)
-      (sweeprolog--backward-hole t)
-    (sweeprolog--forward-hole t)))
+  (setq n (or n 1))
+  (if (zerop n)
+      (sweeprolog-count-holes t)
+    (let* ((func (if (< 0 n)
+                     #'sweeprolog--next-hole
+                   #'sweeprolog--previous-hole))
+           (hole (funcall func t)))
+      (unless hole
+        (user-error "No holes in buffer %s" (buffer-name)))
+      (goto-char (cdr hole))
+      (dotimes (_ (1- (abs n)))
+        (setq hole (funcall func t))
+        (goto-char (cdr hole)))
+      (setq deactivate-mark nil)
+      (push-mark (car hole) t t))))
 
 (put 'sweeprolog-backward-hole
      'repeat-map