[mercury-users] Libraries and DCG convenience...

Peter Schachte schachte at cs.mu.OZ.AU
Thu Jun 24 09:54:58 AEST 1999


On Wed, Jun 23, 1999 at 10:54:16PM +1000, Robert Ernst Johann JESCHOFNIK wrote:
> > BTW, this is exactly why I took the trouble to write an emacs macro to
> > "renumber" the variables in a clause.  I use it all the time.
> 
> Would you mind posting it? :) I'm interested in anything anyone has done
> for emacs that could be of use at some stage..

Sure.  Here it is, along with supporting code.

And if you act now, we'll throw in at the bottom of this message,
absolutely free, a macro to comment out a region of code!  Now what is
this worth?

The first function is just a user interface predicate that gives
helpful prompts.  Bind this command to some key, position the cursor
over a variable, and press the key.  It'll prompt you for a variable
"prefix" (the part before the number), for a start and end suffix, and
for an increment.  It then query replaces all occurrences of all
variables in the current clause that begin with the prefix and end
with any suffix in the inclusive range with the same prefix and the
suffix incremented by the specified increment.  Negative increments
are fine.  It does the renumbering in the right order to avoid
replacing a variable more than once.

The complication of this code is actually in finding the start and end
of the current clause.  In order to do it properly, you have to go to
the beginning of the file and parse forward.  My code makes a valiant
attempt to scan backward and works fairly well, but you may want to
replace it with something simpler or more effective.  If you do make
any improvements, please send me a copy.  I'm always looking for
improvements to this code (particularly to beginning-of-clause and
prolog-backward-skip-string).

Happy hacking.

-- 
Peter Schachte                     The fantastic advances in the field of
mailto:schachte at cs.mu.OZ.AU        communication constitute a grave danger
http://www.cs.mu.oz.au/~schachte/  to the privacy of the individual.
PGP: finger schachte at 128.250.37.3      -- Earl Warren 

================================================================


(defun prolog-renumber-variable-command ()
  "renumber the suffixes of a Prolog variable in the current clause, with \
suitable defaults"
  (interactive)
  (let* ((guess (save-excursion
		  (buffer-substring
		   (progn (skip-chars-backward "A-Za-z0-9_") (point))
		   (progn (skip-chars-forward "A-Za-z0-9_")
			  (skip-chars-backward "0-9")
			  (point)))))
	 (basename (read-string "Renumber variable name: "
				(and (>= (string-to-char guess) ?A)
				     (<= (string-to-char guess) ?Z)
				     guess)))
	 (from-suffix (string-to-int
		       (read-string "First suffix to change: " "0")))
	 (to-suffix (string-to-int
		     (read-string "Last suffix to change: " "9")))
	 (delta (string-to-int
		 (read-string "Value to add to suffixes: " "1"))))
    (prolog-renumber-variable basename from-suffix to-suffix delta)))

(defun prolog-renumber-variable (basename from-suffix to-suffix delta)
  "renumber the suffixes of a Prolog variable in the current clause"
  (interactive "sRenumber variable name: 
nFirst suffix to change: 
nLast suffix to change: 
nValue to add to suffixes: ")
  (if (< to-suffix from-suffix)
      (let ((temp to-suffix))
	(setq to-suffix from-suffix)
	(setq from-suffix temp)))
  (save-excursion
    (save-restriction
      (let ((limit (clause-region 1))
	    suffix increment sentinal)
	(cond ((< delta 0)
	       (setq increment 1)
	       (setq suffix from-suffix)
	       (setq sentinal (1+ to-suffix)))
	      (t
	       (setq increment -1)
	       (setq suffix to-suffix)
	       (setq sentinal (1- from-suffix))))
	(narrow-to-region (point) limit)
	(while (/= suffix sentinal)
	  (goto-char (point-min))
	  (query-replace (concat basename suffix)
			 (concat basename (+ suffix delta))
			 t)
	  (setq suffix (+ suffix increment)))))))


(defun clause-region (n)
  "returns the position of the beginning of the current clause and puts point
at the end of the n-th clause.  If n is negative, return the position of
the end of the current clause, and put point at the beginning of the -n-th
clause."
  (cond ((< n 0)
	 (beginning-of-clause 1)
	 (end-of-clause 1)
	 (prog1 (point)
	   (beginning-of-clause n)))
	((> n 0)
	 (end-of-clause 1)
	 (beginning-of-clause 1)
	 (prog1 (point)
	   (end-of-clause n)))))

(defun beginning-of-clause (&optional arg noerr)
  "Move backward to next beginning-of-clause.  With argument, do this that
many times.  If argument is negative, move forward.  Returns t unless search
stops due to end of buffer."
  (interactive "p")
  (if (null arg) (setq arg 1))
  (cond ((< arg 0)
	 (and (end-of-clause (- 1 arg) noerr)
	      (beginning-of-clause 1)))
	(t (let ((start (point))
		 ch)
	     (while (and (> arg 0)
			 (re-search-backward "^[a-z]\\|^:-\\|\\*/\\|['\"]"
					     nil t))
	       (goto-char (match-beginning 0))
	       (cond ((looking-at "^[a-z:]")
		      (setq arg (1- arg)))
		     ((save-excursion
			(backward-char 2)
			(looking-at "0'"))
		      (backward-char 2))
		     ((looking-at "\\*/")
		      (search-backward "/*"))
		     ((or (eq (setq ch (following-char)) ?\") (eq ch ?\'))
		      (prolog-backward-skip-string ch))))
	     (if (= arg 0) t
	       (progn
		 (goto-char start)
		 (if noerr nil
		   (error "beginning of buffer encountered"))))))))


(defun end-of-clause (&optional arg noerr)
  "Move forward to next end-of-clause.  With argument, do this that many 
times.  If argument is negative, move backward.  Returns t unless search
stops due to end of buffer."
  (interactive "p")
  (if (null arg) (setq arg 1))
  (cond ((< arg 0)
	 (and (beginning-of-clause (- 1 arg) noerr)
	      (end-of-clause 1)))
	(t (let ((start (point))
		 ch)
	     (while (and (> arg 0)
			 (re-search-forward
			  "\\.[ \t\n]\\|/\\*\\|%\\|0'\\|['\"]" nil t))
	       (goto-char (match-beginning 0))
	       (cond ((looking-at "\\.[ \t\n]")
		      (setq arg (1- arg))
		      (forward-char))
		     ((looking-at "/\\*")
		      (search-forward "*/"))
		     ((looking-at "%")
		      (end-of-line))
		     ((looking-at "0'")
		      (forward-char 3))
		     ((or (eq (setq ch (following-char)) ?\") (eq ch ?\'))
		      (prolog-forward-skip-string ch))))
	     (if (= arg 0)
		 (progn (beginning-of-line 2) t)
	       (progn (goto-char start)
		      (if noerr nil
			(error "end of buffer encountered"))))))))



(defun prolog-backward-skip-string (delim &optional noerr)
  "Skip backward over a string delimited by arg character.  Handles using
a doubled quote character to quote the quote.  Tries to handle
Prolog's radix notation (e.g., 16'ff = 255).  To handle this, we
assume that multi-line quoted atoms do not end in a digit.  If it
appears the end quote is in an end-of-line comment, move to the
beginning of the eol comment.  This is a bit tricky, because it's hard
to tell a % inside a quote from quote in an eol comment.  We use the
heuristic that most quoted atoms and strings are contained entirely in
a line, so if there is a matching quote on the same line, then we
assume that's the matching quote.  If not, we assume the quote is in a
comment and move to its beginning.

Returns the character position of the beginning of the string and
moves there, if we find it; returns t if we don't but what we're on
looks like a radix string or a quote in an eol comment, in which case
it moves left of the radix or %.  If we don't find the beginning and
there's no excuse for it, we signal an error, unless noerr is non-nil,
in which case return nil."
  (let ((poss-radix (progn (backward-char) (looking-at "[0-9]'")))
	(search-string (concat (char-to-string delim) "\\|\\\%\\|^"))
	(start-pos (point))
	moved-lines comment-start pos)
    (while (cond ((not (setq pos (re-search-backward search-string)))
		  nil)
		 ((and (looking-at "%") (not moved-lines))
		  ;; comment may include the quote we're trying to match
		  (setq comment-start (point))
		  (setq pos nil)
		  t)
		 ((bolp)
		  (setq moved-lines t)
		  (cond ((or poss-radix comment-start) 
			 (setq pos nil)
			 nil)
			(t (backward-char) t)))
		 (t (eq (preceding-char) delim))))
    (cond (pos (point))
	  (poss-radix
	   (goto-char start-pos)
	   (skip-chars-backward "0-9")
	   t)
	  (comment-start)
	  (noerr nil)
	  (t (error "unbegun quoted %s" 
		    (if (eq delim ?\') "atom" "string"))))))



(defvar prolog-comment-out-string "% "
  "*String to insert at beginning of a line to comment it out.  See

(defun prolog-comment-region (start end uncomment)
  "Comment out all lines in the current region.  With a prefix arg, removes
the comment prefix from all lines in region.  The variable
prolog-comment-out-string specifies the string to insert at the front of
each line to comment it out."
  (interactive "*r
P")
  (if (> start end)
      (let ((save start))
	(setq start end)
	(setq end save)))
  (save-excursion
    (goto-char end)
    (beginning-of-line)
    (if uncomment
	(let ((len (length prolog-comment-out-string)))
	  (while (>= (point) start)
	    (cond ((looking-at prolog-comment-out-string)
		   (delete-char len))
		  ((eq (following-char) ?%)
		   (delete-char 1)))
	    (beginning-of-line 0)))
      (while (>= (point) start)
	(insert prolog-comment-out-string)
	(beginning-of-line 0)))))
	    


--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list