[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/sweeprolog f3d8bff17e: ADDED: command for renaming a varia
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/sweeprolog f3d8bff17e: ADDED: command for renaming a variable in Prolog term |
Date: |
Mon, 30 Jan 2023 00:59:47 -0500 (EST) |
branch: elpa/sweeprolog
commit f3d8bff17e011cf8eb4dfd2c9247af54f823bbe7
Author: Eshel Yaron <me@eshelyaron.com>
Commit: Eshel Yaron <me@eshelyaron.com>
ADDED: command for renaming a variable in Prolog term
* sweeprolog.el (sweeprolog-rename-variable): new command.
(sweeprolog-context-menu-rename-variable): new command used in context
menus for variables.
(sweeprolog-context-menu-for-variable): new function, used in...
(sweeprolog-context-menu-functions): add it to the list.
(sweeprolog-mode-map): bind it to C-c C-r.
* README.org (Renaming Variables): new section.
---
README.org | 29 ++++++++++++-
sweeprolog-tests.el | 15 +++++++
sweeprolog.el | 119 +++++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 155 insertions(+), 8 deletions(-)
diff --git a/README.org b/README.org
index 784c417570..db2fd018f9 100644
--- a/README.org
+++ b/README.org
@@ -1646,7 +1646,7 @@ backward to the previous match.
#+CINDEX: right click menu
In addition to the keybindings that Sweep provides for invoking its
commands, it integrates with Emacs's standard Context Menu minor mode
-to provide contextual menus that you operate with the mouse.
+to provide contextual menus that you interact with using the mouse.
- Command: context-menu-mode :: Toggle Context Menu mode. When
enabled, clicking the mouse button ~down-mouse-3~ (i.e. right-click)
@@ -1668,7 +1668,8 @@ the buffer.
If you right-click on a Prolog file specification or module name,
Sweep suggests visiting it either in the current window or in another.
If you right-click on a predicate, it lets you view its documentation
-in dedicated buffer.
+in a dedicated buffer (see also [[#prolog-help][Prolog Help]]). For
variables, it
+suggests to renaming (see .
You can further extend and customize the context menu that
~sweeprolog-mode~ provides by adding functions to the variable
@@ -1677,6 +1678,30 @@ receives the menu that is being created and a
description of the
clicked Prolog token, and it can extend the menu with entries before
it's displayed.
+** Renaming Variables
+:PROPERTIES:
+:CUSTOM_ID: rename-variable
+:DESCRIPTION: Replacing occurrences of one Prolog variable with another
+:ALT_TITLE: Renaming Variables
+:END:
+
+You can rename a Prolog variable across the current top-term with the
+following command:
+
+- Key: C-c C-r (sweeprolog-rename-variable) :: Rename a variable
+ across the topmost Prolog term at point.
+
+The command ~sweeprolog-rename-variable~, bound to ~C-c C-r~, prompts for
+two variable names and replaces all occurrences of the first variable
+in the term at point with the second. The prompt for the first (old)
+variable name provides completion based on the existing variable names
+in the current term, and it uses the variable at point as its default.
+
+If Context Menu mode is enabled, you can also rename variables by
+right-clicking on them with the mouse and selecting =Rename Variable=
+from the top of the context menu. See [[#context-menu][Context Menu]] for more
+information about context menus in Sweep.
+
* Prolog Help
:PROPERTIES:
:CUSTOM_ID: prolog-help
diff --git a/sweeprolog-tests.el b/sweeprolog-tests.el
index c1551c38a6..b766af1eaf 100644
--- a/sweeprolog-tests.el
+++ b/sweeprolog-tests.el
@@ -287,6 +287,21 @@ foo(Foo) :- bar.
(should (string= (buffer-string)
"foo(bar, (_->_;_), _):-_."))))
+(ert-deftest rename-variable ()
+ "Tests renaming varialbes."
+ (let ((temp (make-temp-file "sweeprolog-test"
+ nil
+ ".pl"
+ "foo(Bar,Baz) :- spam(Baz,Bar).")))
+ (find-file-literally temp)
+ (sweeprolog-mode)
+ (goto-char (point-min))
+ (sweeprolog-rename-variable "Bar" "Spam")
+ (sweeprolog-rename-variable "Baz" "Bar")
+ (sweeprolog-rename-variable "Spam" "Baz")
+ (should (string= (buffer-string)
+ "foo(Baz,Bar) :- spam(Bar,Baz)."))))
+
(ert-deftest forward-many-holes ()
"Tests jumping over holes with `sweeprolog-forward-hole'."
(let ((temp (make-temp-file "sweeprolog-test"
diff --git a/sweeprolog.el b/sweeprolog.el
index cddbb4f70c..e40d9cf95d 100644
--- a/sweeprolog.el
+++ b/sweeprolog.el
@@ -319,7 +319,7 @@ inserted to the input history in
`sweeprolog-top-level-mode' buffers."
"If non-nil, enable `cursor-sensor-mode' in `sweeprolog-mode'.
When enabled, `sweeprolog-mode' leverages `cursor-sensor-mode' to
-highlight all occurences of the variable at point in the current
+highlight all occurrences of the variable at point in the current
clause."
:package-version '((sweeprolog "0.4.2"))
:type 'boolean
@@ -401,12 +401,13 @@ token via its `help-echo' text property."
(define-key map (kbd "C-c C-l") #'sweeprolog-load-buffer)
(define-key map (kbd "C-c C-m") #'sweeprolog-insert-term-with-holes)
(define-key map (kbd "C-c C-o") #'sweeprolog-find-file-at-point)
- (define-key map (kbd "C-c C-s") #'sweeprolog-term-search)
(define-key map (kbd "C-c C-q") #'sweeprolog-top-level-send-goal)
+ (define-key map (kbd "C-c C-r") #'sweeprolog-rename-variable)
+ (define-key map (kbd "C-c C-s") #'sweeprolog-term-search)
(define-key map (kbd "C-c C-t") #'sweeprolog-top-level)
(define-key map (kbd "C-c C-u") #'sweeprolog-update-dependencies)
(define-key map (kbd "C-c C-`")
- (if (fboundp 'flymake-show-buffer-diagnostics) ;; Flymake
1.2.1+
+ (if (fboundp 'flymake-show-buffer-diagnostics) ;; Flymake
1.2.1+
#'sweeprolog-show-diagnostics
#'flymake-show-diagnostics-buffer))
(define-key map (kbd "C-c C-&") #'sweeprolog-async-goal)
@@ -2673,7 +2674,7 @@ modified."
start end)))
(defun sweeprolog-highlight-variable (point &optional var)
- "Highlight occurences of the variable VAR in the clause at POINT.
+ "Highlight occurrences of the variable VAR in the clause at POINT.
If VAR is nil, clear variable highlighting in the current clause
instead.
@@ -5277,6 +5278,9 @@ GOAL."
;;;; Right-Click Context Menu
+(defvar sweeprolog-context-menu-point-at-click nil
+ "Buffer position at mouse click.")
+
(defvar sweeprolog-context-menu-file-at-click nil
"Prolog file specification at mouse click.")
@@ -5286,6 +5290,9 @@ GOAL."
(defvar sweeprolog-context-menu-predicate-at-click nil
"Prolog predicate indicator at mouse click.")
+(defvar sweeprolog-context-menu-variable-at-click nil
+ "Prolog variable at mouse click.")
+
(defun sweeprolog-context-menu-find-module ()
"Find Prolog module at mouse click."
(interactive)
@@ -5316,6 +5323,13 @@ GOAL."
(interactive)
(sweeprolog-describe-predicate sweeprolog-context-menu-predicate-at-click))
+(defun sweeprolog-context-menu-rename-variable ()
+ "Rename Prolog variable at mouse click."
+ (interactive)
+ (sweeprolog-rename-variable sweeprolog-context-menu-variable-at-click
+ nil
+ sweeprolog-context-menu-point-at-click))
+
(defun sweeprolog-context-menu-for-predicate (menu tok _beg _end _point)
"Extend MENU with predicate-related commands if TOK describes one."
(pcase tok
@@ -5369,10 +5383,30 @@ GOAL."
:help ,(format "Find %s" file)
:keys "\\[sweeprolog-find-file-at-point]")))))
+(defun sweeprolog-context-menu-for-variable (menu tok beg end point)
+ "Extend MENU with file-related commands if TOK specifies one.
+BEG and END are the variable's beginning and end positions, and
+POINT is the buffer position of the mouse click."
+ (pcase tok
+ ((or "var"
+ "singleton"
+ `("goal_term" "meta" variable 0))
+ (setq sweeprolog-context-menu-point-at-click point
+ sweeprolog-context-menu-variable-at-click
+ (buffer-substring-no-properties beg end))
+ (define-key menu [sweeprolog-rename-variable]
+ `(menu-item "Rename Variable"
+ sweeprolog-context-menu-rename-variable
+ :help ,(concat "Rename variable "
+ (propertize
sweeprolog-context-menu-variable-at-click
+ 'face
(sweeprolog-variable-face)))
+ :keys "\\[sweeprolog-rename-variable]")))))
+
(defvar sweeprolog-context-menu-functions
'(sweeprolog-context-menu-for-file
sweeprolog-context-menu-for-module
- sweeprolog-context-menu-for-predicate)
+ sweeprolog-context-menu-for-predicate
+ sweeprolog-context-menu-for-variable)
"Functions that create context menu entries for Prolog tokens.
Each function receives as its arguments the menu, the Prolog
token's description, its start position, its end position, and
@@ -5387,7 +5421,7 @@ the position for which the menu is created.")
(lambda (beg end tok)
(when (<= beg point end)
(run-hook-with-args 'sweeprolog-context-menu-functions
- menu tok beg point end))))))
+ menu tok beg end point))))))
menu)
@@ -5485,6 +5519,79 @@ Deletes PROC if STRING contains an end of output marker
string."
sweeprolog-async-goal-current-goal goal))
(display-buffer buffer)))
+
+;;;; Refactoring
+
+(defun sweeprolog--variables-at-point ()
+ "Return information about variables in the Prolog term at point.
+
+Returns a cons cell (VAR-OCCURRENCES . VAR-AT-POINT).
+VAR-OCCURRENCES is an alist of elements (VAR . OCCURRENCES) where
+VAR is a variable name and OCCURRENCES is itself an alist of
+elements (BEG . END) describing the beginning and end of
+occurrences of this variable in buffer positions. VAR-AT-POINT
+is the name of the variable at point, if any."
+ (let ((point (point))
+ (vars nil)
+ (var-at-point nil))
+ (sweeprolog-analyze-term-at-point
+ (lambda (beg end arg)
+ (pcase arg
+ ((or "var"
+ "singleton"
+ `("goal_term" "meta" variable 0))
+ (let ((var (buffer-substring-no-properties beg end)))
+ (push (cons beg end)
+ (alist-get var vars nil nil #'string=))
+ (when (<= beg point end)
+ (setq var-at-point var)))))))
+ (cons vars var-at-point)))
+
+(defun sweeprolog-rename-variable (&optional old new point)
+ "Rename the variable OLD to NEW in the Prolog term at POINT.
+
+If OLD is nil, prompt for it in the minibuffer with completion.
+If NEW is nil, prompt for it as well. If POINT is nil, it
+defaults to the current point.
+
+Interactively, OLD, NEW and POINT are nil."
+ (interactive "" sweeprolog-mode)
+ (setq point (or point (point)))
+ (save-excursion
+ (goto-char point)
+ (let* ((term-var-occurrences (sweeprolog--variables-at-point))
+ (var-occurrences (car term-var-occurrences))
+ (var-at-point (cdr term-var-occurrences)))
+ (unless var-occurrences
+ (user-error "No variables to rename here!"))
+ (let* ((old-name
+ (or old
+ (completing-read
+ (concat
+ "Rename variable"
+ (when-let ((def var-at-point))
+ (concat " (default "
+ (propertize def 'face (sweeprolog-variable-face))
+ ")"))
+ ": ")
+ var-occurrences nil t nil nil var-at-point)))
+ (new-name
+ (or new
+ (read-string
+ (concat
+ "Rename "
+ (propertize old-name 'face (sweeprolog-variable-face))
+ " to: ")
+ nil nil old-name))))
+ (combine-after-change-calls
+ (dolist (old-occurrence (alist-get old-name var-occurrences
+ nil nil #'string=))
+ (let ((occurrence-beg (car old-occurrence))
+ (occurrence-end (cdr old-occurrence)))
+ (delete-region occurrence-beg occurrence-end)
+ (goto-char occurrence-beg)
+ (insert new-name))))))))
+
;;;; Footer
(provide 'sweeprolog)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [nongnu] elpa/sweeprolog f3d8bff17e: ADDED: command for renaming a variable in Prolog term,
ELPA Syncer <=