unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* comint-read-only prompt
@ 2004-04-30  3:10 Luc Teirlinck
  0 siblings, 0 replies; only message in thread
From: Luc Teirlinck @ 2004-04-30  3:10 UTC (permalink / raw)


I recently replaced the read-only ielm prompt with an optional comint
read-only prompt, disabled by default, except in ielm buffers, where
it is enabled by default (but customizable).  It protects against
three kinds of accidents: overshooting a preceding prompt with
backspace (or other backwards deletion commands), accidentally yanking
something into a prompt (happens to me regularly, since usually a
trailing space is invisibly part of the prompt) and overshooting a
newline preceding a prompt with forward deletion commands, say C-d.
Remember that any comint-prompt, not just the trailing one, can be
used to enter (usually edited old) commands.

But often one _wants_ to delete prompts, to "clean up" a comint buffer.

The following additional patches to comint.el and ielm.el would allow
to override the read-only-ness of the comint prompt using the commands
`comint-kill-whole-line' and `comint-kill-region', without any risk of
producing annoying mutilated or displaced prompts or inappropriate
read-only properties in the process.  For comint-kill-whole-line, this
is pretty much automatic anyway.  For comint-kill-region, all or none
of a prompt must be deleted and all remaining prompts must remain at
the beginning of a line.  Otherwise, it copies the text to the
kill-ring, but does not delete anything.

comint-kill-region only differs from kill-region in that it ignores
read-only properties, if it is safe to do so.

comint-kill-whole-line actually differs from kill-whole-line in two
ways: it ignores both read-only and field properties.

The patch below does not provide any bindings for the two commands, it
just suggests that people bind them to the usual keys for kill-region
and kill-whole-line, in those comint modes for which they use the
read-only-prompt.

If there are no objections, I will install.

===File ~/comint-diff=======================================
*** comint.el	28 Apr 2004 22:27:38 -0500	1.296
--- comint.el	29 Apr 2004 20:48:44 -0500	
***************
*** 173,180 ****
  
  (defcustom comint-prompt-read-only nil
    "If non-nil, the comint prompt is read only.
  This does not affect existing prompts.
! Certain derived modes may override this option."
    :type 'boolean
    :group 'comint
    :version "21.4")
--- 173,197 ----
  
  (defcustom comint-prompt-read-only nil
    "If non-nil, the comint prompt is read only.
+ The read only region includes the newline before the prompt.
  This does not affect existing prompts.
! Certain derived modes may override this option.
! 
! If you set this option to t, then the safe way to temporarily
! override the read-only-ness of comint prompts is to call
! `comint-kill-whole-line' or `comint-kill-region' with no
! narrowing in effect.  This way you will be certain that none of
! the remaining prompts will be accidentally messed up.  You may
! wish to put something like the following in your `.emacs' file:
! 
! \(add-hook 'comint-mode-hook
! 	  '(lambda ()
! 	     (define-key comint-mode-map \"\C-w\" 'comint-kill-region)
! 	     (define-key comint-mode-map [C-S-backspace]
! 	       'comint-kill-whole-line)))
! 
! If you sometimes use comint-mode on text-only terminals or with `emacs-nw',
! you might wish to use another binding for `comint-kill-whole-line'."
    :type 'boolean
    :group 'comint
    :version "21.4")
***************
*** 2311,2316 ****
--- 2328,2410 ----
      (just-one-space)))
  
  \f
+ ;; Support editing with `comint-promt-read-only' set to t.
+ 
+ (defun comint-update-fence ()
+   "Update read-only status of newline before point.
+ The `fence' read-only property is used to indicate that a newline
+ is read-only for no other reason than to \"fence off\" a
+ following front-sticky read-only region.  This is used to
+ implement comint read-only prompts.  If the text after a newline
+ changes, the read-only status of that newline may need updating.
+ That is what this function does.
+ 
+ This function does nothing if point is not at the beginning of a
+ line, or is at the beginning of the accessible portion of the buffer.
+ Otherwise, if the character after point has a front-sticky
+ read-only property, then the preceding newline is given a
+ read-only property of `fence', unless it already is read-only.
+ If the character after point does not have a front-sticky
+ read-only property, any read-only property of `fence' on the
+ preceding newline is removed."
+   (let* ((pt (point)) (lst (get-text-property pt 'front-sticky)))
+     (and (bolp)
+ 	 (not (bobp))
+ 	 (if (and (get-text-property pt 'read-only)
+ 		  (if (listp lst) (memq 'read-only lst) t))
+ 	     (unless (get-text-property (1- pt) 'read-only)
+ 	       (put-text-property (1- pt) pt 'read-only 'fence))
+ 	   (when (eq (get-text-property (1- pt) 'read-only) 'fence)
+ 	     (remove-list-of-text-properties (1- pt) pt '(read-only)))))))
+ 
+ (defun comint-kill-whole-line (&optional arg)
+   "Kill current line, ignoring read-only and field properties.
+ With prefix arg, kill that many lines starting from the current line.
+ If arg is negative, kill backward.  Also kill the preceding newline,
+ instead of the trailing one.  \(This is meant to make C-x z work well
+ with negative arguments.)
+ If arg is zero, kill current line but exclude the trailing newline.
+ The read-only status of newlines is updated with `comint-update-fence',
+ if necessary."
+   (interactive "p")
+   (let ((inhibit-read-only t) (inhibit-field-text-motion t))
+     (kill-whole-line arg)
+     (when (>= arg 0) (comint-update-fence))))
+ 
+ (defun comint-kill-region (beg end &optional yank-handler)
+   "Like `kill-region', but ignores read-only properties, if safe.
+ This command assumes that the buffer contains read-only
+ \"prompts\" which are regions with front-sticky read-only
+ properties at the beginning of a line, with the preceding newline
+ being read-only to protect the prompt.  This is true of the
+ comint prompts if `comint-prompt-read-only' is non-nil.  This
+ command will not delete the region if this would create mutilated
+ or out of place prompts.  That is, if any part of a prompt is
+ deleted, the entire prompt must be deleted and all remaining
+ prompts should stay at the beginning of a line.  If this is not
+ the case, this command just calls `kill-region' with all
+ read-only properties intact.  The read-only status of newlines is
+ updated using `comint-update-fence', if necessary."
+   (interactive "r")
+   (save-excursion
+     (let* ((true-beg (min beg end))
+ 	   (true-end (max beg end))
+ 	   (beg-bolp (progn (goto-char true-beg) (bolp)))
+ 	   (beg-lst (get-text-property true-beg 'front-sticky))
+ 	   (beg-bad (and (get-text-property true-beg 'read-only)
+ 			 (if (listp beg-lst) (memq 'read-only beg-lst) t)))
+ 	   (end-bolp (progn (goto-char true-end) (bolp)))
+ 	   (end-lst (get-text-property true-end 'front-sticky))
+ 	   (end-bad (and (get-text-property true-end 'read-only)
+ 			 (if (listp end-lst) (memq 'read-only end-lst) t))))
+       (if (or (and (not beg-bolp) (or beg-bad end-bad))
+ 	      (and (not end-bolp) end-bad))
+ 	  (kill-region beg end yank-handler)
+ 	(let ((inhibit-read-only t))
+ 	  (kill-region beg end yank-handler)
+ 	  (comint-update-fence))))))
+ 
+ \f
  ;; Support for source-file processing commands.
  ;;============================================================================
  ;; Many command-interpreters (e.g., Lisp, Scheme, Soar) have
============================================================

===File ~/ielm-diff=========================================
*** ielm.el	26 Apr 2004 22:33:56 -0500	1.42
--- ielm.el	29 Apr 2004 19:32:52 -0500	
***************
*** 51,59 ****
  
  (defcustom ielm-prompt-read-only t
    "If non-nil, the IELM prompt is read only.
  Setting this variable does not affect existing IELM runs.
  This works by setting the buffer-local value of `comint-prompt-read-only'.
! Setting that value directly affects new prompts in the current buffer."
    :type 'boolean
    :group 'ielm
    :version "21.4")
--- 51,80 ----
  
  (defcustom ielm-prompt-read-only t
    "If non-nil, the IELM prompt is read only.
+ The read only region includes the newline before the prompt.
  Setting this variable does not affect existing IELM runs.
  This works by setting the buffer-local value of `comint-prompt-read-only'.
! Setting that value directly affects new prompts in the current buffer.
! 
! If this option is enabled, then the safe way to temporarily
! override the read-only-ness of ielm prompts is to call
! `comint-kill-whole-line' or `comint-kill-region' with no
! narrowing in effect.  This way you will be certain that none of
! the remaining prompts will be accidentally messed up.  You may
! wish to put something like the following in your `.emacs' file:
! 
! \(add-hook 'ielm-mode-hook
! 	  '(lambda ()
! 	     (define-key ielm-map \"\C-w\" 'comint-kill-region)
! 	     (define-key ielm-map [C-S-backspace]
! 	       'comint-kill-whole-line)))
! 
! If you set `comint-prompt-read-only' to t, you might wish to use
! `comint-mode-hook' and `comint-mode-map' instead of
! `ielm-mode-hook' and `ielm-map'.  That will affect all comint
! buffers, including ielm buffers.  If you sometimes use ielm on
! text-only terminals or with `emacs -nw', you might wish to use
! another binding for `comint-kill-whole-line'."
    :type 'boolean
    :group 'ielm
    :version "21.4")
============================================================

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-04-30  3:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-04-30  3:10 comint-read-only prompt Luc Teirlinck

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).