[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)