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

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

[nongnu] elpa/sweeprolog 3c2a4d0477 1/2: Support defining DCG non-termin


From: ELPA Syncer
Subject: [nongnu] elpa/sweeprolog 3c2a4d0477 1/2: Support defining DCG non-terminals in sweeprolog-insert-term-dwim
Date: Mon, 21 Nov 2022 11:59:54 -0500 (EST)

branch: elpa/sweeprolog
commit 3c2a4d04775c8040b05dd0e1ec6e65abb16fd932
Author: Eshel Yaron <me@eshelyaron.com>
Commit: Eshel Yaron <me@eshelyaron.com>

    Support defining DCG non-terminals in sweeprolog-insert-term-dwim
    
    * sweep.pl (sweep_color_normalized_/4): expose DCG term "kind" to
    Elisp.
    * sweeprolog.el (sweeprolog-new-predicate-location-function): change
    expected function signature.
    (sweeprolog-default-new-predicate-location)
    (sweeprolog-new-predicate-location-above-current): update arguments.
    (sweeprolog-maybe-define-predicate): support defining DCGs.
---
 .gitignore          |  2 ++
 NEWS.org            | 34 +++++++++++++++-----
 sweep.pl            |  3 ++
 sweeprolog-tests.el | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 sweeprolog.el       | 53 +++++++++++++++++++++++-------
 5 files changed, 162 insertions(+), 22 deletions(-)

diff --git a/.gitignore b/.gitignore
index ee9db441d1..dd499e604d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,5 @@
 /#sweep.pl#
 /sweeprolog-tests.elc
 /sweeprolog.elc
+/.dir-locals.el
+/NEWS.md
diff --git a/NEWS.org b/NEWS.org
index 8bc9bff191..cae8769da7 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -11,17 +11,35 @@ SWI-Prolog in Emacs.
 For further details, please consult the manual:
 <https://eshelyaron.com/sweep.html>.
 
+* Version 0.8.11 on 2022-11-21
+
+** ~sweeprolog-new-predicate-location-function~ signature changed
+
+The function specified by ~sweeprolog-new-predicate-location-function~
+should now take three arguments, namely the functor, arity and neck of
+the new predicate, instead of taking only the predicate indicator as a
+sole argument.
+
+** ~sweeprolog-insert-term-dwim~ now supports defining undefined DCG 
non-terminals
+
+Defining a previously undefined predicate with
+~sweeprolog-insert-term-dwim~ now analyzes the context of the undefined
+predicate invocation to determine if it is expected to be a DCG
+non-terminal, in which case an appropriate non-terminal definition is
+inserted instead of a regular predicate.
+
 * Version 0.8.10 on 2022-11-21
 
 ** ~sweeprolog-top-level-signal-current~ now calls ~trace/0~ by default
 
-Calling ~sweeprolog-top-level-signal-current~ (e.g. with ~C-c C-c~) now
-signals the top-level thread with the goal specified by the user
-option ~sweeprolog-top-level-signal-default-goal~, instead of prompting
-for a goal.  By default this user option is set to ~"trace"~, causing
-the top-level thread to enter trace mode.  To have
-~sweeprolog-top-level-signal-current~ prompt for a different goal on
-invocation, call it with a prefix argument, i.e. ~C-u C-c C-c~.
+Calling ~sweeprolog-top-level-signal-current~ (~C-c C-c~ in
+~sweeprolog-top-level~ buffers) now signals the top-level thread with
+the goal specified by the user option
+~sweeprolog-top-level-signal-default-goal~, instead of prompting for a
+goal.  By default this user option is set to ~"trace"~, causing the
+top-level thread to enter trace mode.  To have
+~sweeprolog-top-level-signal-current~ prompt for a different goal
+instead, call it with a prefix argument, i.e. ~C-u C-c C-c~.
 
 ** Fixes
 
@@ -32,7 +50,7 @@ invocation, call it with a prefix argument, i.e. ~C-u C-c 
C-c~.
 
 * Version 0.8.9 on 2022-11-19
 
-** Predicate completions now use holes for arguments
+** Predicate completions now uses holes for arguments
 
 When completing a predicate with ~completion-at-point~ (~C-M-i~) and
 choosing a predicate that takes arguments, holes are inserted is place
diff --git a/sweep.pl b/sweep.pl
index 84f6dbc9b0..1342485706 100644
--- a/sweep.pl
+++ b/sweep.pl
@@ -481,6 +481,9 @@ sweep_color_normalized_(Offset, syntax_error, 
[Message0,Start0-End0|_], ["syntax
 sweep_color_normalized_(_, comment, [Kind0|_], ["comment"|Kind]) :-
     !,
     atom_string(Kind0, Kind).
+sweep_color_normalized_(_, dcg, [Kind0|_], ["dcg"|Kind]) :-
+    !,
+    atom_string(Kind0, Kind).
 sweep_color_normalized_(_, qq_content, [Type0|_], ["qq_content"|Type]) :-
     !,
     atom_string(Type0, Type).
diff --git a/sweeprolog-tests.el b/sweeprolog-tests.el
index 4fa1a4f87e..0a0f723073 100644
--- a/sweeprolog-tests.el
+++ b/sweeprolog-tests.el
@@ -434,6 +434,92 @@ foo :- bar.
 foo :- Body.
 "))))
 
+(ert-deftest dwim-define-nested-phrase- ()
+  "Tests complex undefined predicate scenario"
+  (let ((temp (make-temp-file "sweeprolog-test"
+                              nil
+                              "pl"
+                              "
+foo --> {baz, phrase(bar, Baz)}.
+"
+                              )))
+    (find-file-literally temp)
+    (sweeprolog-mode)
+    (goto-char (point-max))
+    (backward-word 2)
+    (sweeprolog-insert-term-dwim)
+    (call-interactively #'kill-region)
+    (insert "foo")
+    (should (string= (buffer-string)
+                     "
+foo --> {baz, phrase(bar, Baz)}.
+
+bar --> foo.
+"
+                     ))))
+
+(ert-deftest dwim-define-phrase-non-terminal ()
+  "Tests defining an undefined DCG non-terminal from a clause."
+  (let ((temp (make-temp-file "sweeprolog-test"
+                              nil
+                              "pl"
+                              "
+foo :- phrase(bar, Baz).
+"
+                              )))
+    (find-file-literally temp)
+    (sweeprolog-mode)
+    (goto-char (point-max))
+    (backward-word 2)
+    (sweeprolog-insert-term-dwim)
+    (call-interactively #'kill-region)
+    (insert "foo")
+    (should (string= (buffer-string)
+                     "
+foo :- phrase(bar, Baz).
+
+bar --> foo.
+"
+                     ))))
+
+(ert-deftest dwim-define-braces-predicate ()
+  "Tests defining an undefined predicate from a DCG non-terminal."
+  (with-temp-buffer
+    (sweeprolog-mode)
+    (insert "
+foo --> {bar}.
+")
+    (backward-word)
+    (sweeprolog-insert-term-dwim)
+    (call-interactively #'kill-region)
+    (insert "foo")
+    (should (string= (buffer-string)
+                     "
+foo --> {bar}.
+
+bar :- foo.
+"
+                     ))))
+
+(ert-deftest dwim-define-non-terminal ()
+  "Tests defining an undefined DCG non-terminal."
+  (with-temp-buffer
+    (sweeprolog-mode)
+    (insert "
+foo --> bar.
+")
+    (backward-word)
+    (sweeprolog-insert-term-dwim)
+    (call-interactively #'kill-region)
+    (insert "foo")
+    (should (string= (buffer-string)
+                     "
+foo --> bar.
+
+bar --> foo.
+"
+                     ))))
+
 (ert-deftest dwim-define-predicate ()
   "Tests defining a new predicate with `sweeprolog-insert-term-dwim'."
   (with-temp-buffer
@@ -450,7 +536,8 @@ foo :- bar.
 foo :- bar.
 
 bar :- foo.
-"))))
+"
+                     ))))
 
 
 (ert-deftest dwim-define-predicate-above ()
@@ -475,7 +562,8 @@ bar :- foo.
 %!  foo is det.
 
 foo :- bar.
-"))))
+"
+                     ))))
 
 (ert-deftest end-of-top-term-with-univ ()
   "Tests detecting the fullstop in presence of `=..'."
diff --git a/sweeprolog.el b/sweeprolog.el
index dc489791ca..0dce7857aa 100644
--- a/sweeprolog.el
+++ b/sweeprolog.el
@@ -314,10 +314,17 @@ clause."
 (defcustom sweeprolog-new-predicate-location-function
   #'sweeprolog-default-new-predicate-location
   "Function used to choose a location for a new predicate definition.
-It should take one argument, the name of the new predicate given
-as a string, and move point to a suitable position in the current
-buffer where the new predicate defintion should be inserted."
-  :package-version '((sweeprolog "0.8.6"))
+
+It should take three arguments describing the new predicate,
+FUNCTOR, ARITY and NECK, and move point to a suitable position in
+the current buffer where the new predicate defintion should be
+inserted.
+
+FUNCTOR is the predicate name given as a string, ARITY is its
+arity given as an integer, and NECK is the neck operator of the
+predicate (e.g. \":-\" for regular clauses and \"-->\" for DCG
+non-terminals)."
+  :package-version '((sweeprolog "0.8.11"))
   :type '(choice (const    :tag "Below Current Predicate"
                         sweeprolog-default-new-predicate-location)
                  (const    :tag "Above Current Predicate"
@@ -2626,22 +2633,44 @@ instead."
                               neck)
     t))
 
-(defun sweeprolog-default-new-predicate-location (_pred)
+(defun sweeprolog-default-new-predicate-location (&rest _)
   (sweeprolog-end-of-predicate-at-point))
 
-(defun sweeprolog-new-predicate-location-above-current (_pred)
+(defun sweeprolog-new-predicate-location-above-current (&rest _)
   (sweeprolog-beginning-of-predicate-at-point)
   (let ((last (or (caddr (sweeprolog-last-token-boundaries))
                   (point-min))))
     (while (re-search-backward (rx bol "%" (or "%" "!")) last t))))
 
 (defun sweeprolog-maybe-define-predicate (point _kind _beg _end)
-  (when-let ((pred (sweeprolog-identifier-at-point point)))
-    (unless (sweeprolog-predicate-properties pred)
-      (funcall sweeprolog-new-predicate-location-function pred)
-      (let ((functor-arity (sweeprolog--mfn-to-functor-arity pred)))
-        (sweeprolog-insert-clause (car functor-arity)
-                                  (cdr functor-arity)))
+  (let ((functor nil)
+        (arity nil)
+        (neck ":-"))
+    (sweeprolog-analyze-term-at-point
+     (lambda (beg end arg)
+       (pcase arg
+         (`("goal_term" "undefined" ,f ,a)
+          (when (<= beg point end)
+            (setq functor f
+                  arity   a)))
+         ("neck"
+          (setq neck
+                (buffer-substring-no-properties beg end)))
+         (`("goal_term" "built_in" "phrase" ,a)
+          (when (and (<= beg point end)
+                     (member a '(2 3))
+                     (string= neck ":-"))
+            (setq neck "-->")))
+         (`("dcg" . "plain")
+          (when (and (<= beg point end)
+                     (string= neck "-->"))
+            (setq neck ":-"))))))
+    (when functor
+      (funcall sweeprolog-new-predicate-location-function
+               functor arity neck)
+      (sweeprolog-insert-clause functor
+                                (- arity (if (string= neck "-->") 2 0))
+                                neck)
       t)))
 
 (defun sweeprolog-insert-term-dwim (&optional point)



reply via email to

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