view lisp/view-less.el @ 4677:8f1ee2d15784

Support full Common Lisp multiple values in C. lisp/ChangeLog 2009-08-11 Aidan Kehoe <kehoea@parhasard.net> * bytecomp.el : Update this file to support full C-level multiple values. This involves: -- Four new bytecodes, and special compiler functions to compile multiple-value-call, multiple-value-list-internal, values, values-list, and, since it now needs to pass back multiple values and is a special form, throw. -- There's a new compiler variable, byte-compile-checks-on-load, which is a list of forms that are evaluated at the very start of a file, with an error thrown if any of them give nil. -- The header is now inserted *after* compilation, giving a chance for the compilation process to influence what those checks are. There is still a check done before compilation for non-ASCII characters, to try to turn off dynamic docstrings if appopriate, in `byte-compile-maybe-reset-coding'. Space is reserved for checks; comments describing the version of the byte compiler generating the file are inserted if space remains for them. * bytecomp.el (byte-compile-version): Update this, we're a newer version of the byte compiler. * byte-optimize.el (byte-optimize-funcall): Correct a comment. * bytecomp.el (byte-compile-lapcode): Discard the arg with byte-multiple-value-call. * bytecomp.el (byte-compile-checks-and-comments-space): New variable, describe how many octets to reserve for checks at the start of byte-compiled files. * cl-compat.el: Remove the fake multiple-value implementation. Have the functions that use it use the real multiple-value implementation instead. * cl-macs.el (cl-block-wrapper, cl-block-throw): Revise the byte-compile properties of these symbols to work now we've made throw into a special form; keep the byte-compile properties as anonymous lambdas, since we don't have docstrings for them. * cl-macs.el (multiple-value-bind, multiple-value-setq) (multiple-value-list, nth-value): Update these functions to work with the C support for multiple values. * cl-macs.el (values): Modify the setf handler for this to call #'multiple-value-list-internal appropriately. * cl-macs.el (cl-setf-do-store): If the store form is a cons, treat it specially as wrapping the store value. * cl.el (cl-block-wrapper): Make this an alias of #'and, not #'identity, since it needs to pass back multiple values. * cl.el (multiple-value-apply): We no longer support this, mark it obsolete. * lisp-mode.el (eval-interactive-verbose): Remove a useless space in the docstring. * lisp-mode.el (eval-interactive): Update this function and its docstring. It now passes back a list, basically wrapping any eval calls with multiple-value-list. This allows multiple values to be printed by default in *scratch*. * lisp-mode.el (prin1-list-as-multiple-values): New function, printing a list as multiple values in the manner of Bruno Haible's clisp, separating each entry with " ;\n". * lisp-mode.el (eval-last-sexp): Call #'prin1-list-as-multiple-values on the return value of #'eval-interactive. * lisp-mode.el (eval-defun): Call #'prin1-list-as-multiple-values on the return value of #'eval-interactive. * mouse.el (mouse-eval-sexp): Deal with lists corresponding to multiple values from #'eval-interactive. Call #'cl-prettyprint, which is always available, instead of sometimes calling #'pprint and sometimes falling back to prin1. * obsolete.el (obsolete-throw): New function, called from eval.c when #'funcall encounters an attempt to call #'throw (now a special form) as a function. Only needed for compatibility with 21.4 byte-code. man/ChangeLog addition: 2009-08-11 Aidan Kehoe <kehoea@parhasard.net> * cl.texi (Organization): Remove references to the obsolete multiple-value emulating code. src/ChangeLog addition: 2009-08-11 Aidan Kehoe <kehoea@parhasard.net> * bytecode.c (enum Opcode /* Byte codes */): Add four new bytecodes, to deal with multiple values. (POP_WITH_MULTIPLE_VALUES): New macro. (POP): Modify this macro to ignore multiple values. (DISCARD_PRESERVING_MULTIPLE_VALUES): New macro. (DISCARD): Modify this macro to ignore multiple values. (TOP_WITH_MULTIPLE_VALUES): New macro. (TOP_ADDRESS): New macro. (TOP): Modify this macro to ignore multiple values. (TOP_LVALUE): New macro. (Bcall): Ignore multiple values where appropriate. (Breturn): Pass back multiple values. (Bdup): Preserve multiple values. Use TOP_LVALUE with most bytecodes that assign anything to anything. (Bbind_multiple_value_limits, Bmultiple_value_call, Bmultiple_value_list_internal, Bthrow): Implement the new bytecodes. (Bgotoifnilelsepop, Bgotoifnonnilelsepop, BRgotoifnilelsepop, BRgotoifnonnilelsepop): Discard any multiple values. * callint.c (Fcall_interactively): Ignore multiple values when calling #'eval, in two places. * device-x.c (x_IO_error_handler): * macros.c (pop_kbd_macro_event): * eval.c (Fsignal): * eval.c (flagged_a_squirmer): Call throw_or_bomb_out, not Fthrow, now that the latter is a special form. * eval.c: Make Qthrow, Qobsolete_throw available as symbols. Provide multiple_value_current_limit, multiple-values-limit (the latter as specified by Common Lisp. * eval.c (For): Ignore multiple values when comparing with Qnil, but pass any multiple values back for the last arg. * eval.c (Fand): Ditto. * eval.c (Fif): Ignore multiple values when examining the result of the condition. * eval.c (Fcond): Ignore multiple values when comparing what the clauses give, but pass them back if a clause gave non-nil. * eval.c (Fprog2): Never pass back multiple values. * eval.c (FletX, Flet): Ignore multiple when evaluating what exactly symbols should be bound to. * eval.c (Fwhile): Ignore multiple values when evaluating the test. * eval.c (Fsetq, Fdefvar, Fdefconst): Ignore multiple values. * eval.c (Fthrow): Declare this as a special form; ignore multiple values for TAG, preserve them for VALUE. * eval.c (throw_or_bomb_out): Make this available to other files, now Fthrow is a special form. * eval.c (Feval): Ignore multiple values when calling a compiled function, a non-special-form subr, or a lambda expression. * eval.c (Ffuncall): If we attempt to call #'throw (now a special form) as a function, don't error, call #'obsolete-throw instead. * eval.c (make_multiple_value, multiple_value_aset) (multiple_value_aref, print_multiple_value, mark_multiple_value) (size_multiple_value): Implement the multiple_value type. Add a long comment describing our implementation. * eval.c (bind_multiple_value_limits): New function, used by the bytecode and by #'multiple-value-call, #'multiple-value-list-internal. * eval.c (multiple_value_call): New function, used by the bytecode and #'multiple-value-call. * eval.c (Fmultiple_value_call): New special form. * eval.c (multiple_value_list_internal): New function, used by the byte code and #'multiple-value-list-internal. * eval.c (Fmultiple_value_list_internal, Fmultiple_value_prog1): New special forms. * eval.c (Fvalues, Fvalues_list): New Lisp functions. * eval.c (values2): New function, for C code returning multiple values. * eval.c (syms_of_eval): Make our new Lisp functions and symbols available. * eval.c (multiple-values-limit): Make this available to Lisp. * event-msw.c (dde_eval_string): * event-stream.c (execute_help_form): * glade.c (connector): * glyphs-widget.c (glyph_instantiator_to_glyph): * glyphs.c (evaluate_xpm_color_symbols): * gui-x.c (wv_set_evalable_slot, button_item_to_widget_value): * gui.c (gui_item_value, gui_item_display_flush_left): * lread.c (check_if_suppressed): * menubar-gtk.c (menu_convert, menu_descriptor_to_widget_1): * menubar-msw.c (populate_menu_add_item): * print.c (Fwith_output_to_temp_buffer): * symbols.c (Fsetq_default): Ignore multiple values when calling Feval. * symeval.h: Add the header declarations necessary for the multiple-values implementation. * inline.c: #include symeval.h, now that it has some inline functions. * lisp.h: Update Fthrow's declaration. Make throw_or_bomb_out available to all files. * lrecord.h (enum lrecord_type): Add the multiple_value type here.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 16 Aug 2009 20:55:49 +0100
parents 1b0339b048ce
children 9058351b0236
line wrap: on
line source

;;; view-less.el --- Minor mode for browsing files with keybindings like `less'

;; Copyright (C) 1994, 1995 Tinker Systems and INS Engineering Corp.

;; Author: Jonathan Stigelman <stig@hackvan.com>
;; Maintainer: XEmacs Development Team
;; Keywords: wp, unix

;; This file is part of XEmacs.
;;
;; XEmacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2 of the License, or
;; (at your option) any later version.
;;
;; XEmacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with XEmacs; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

;;; Synched up with: Not in FSF.

;;; Commentary:

;; This mode is for browsing files without changing them.  Keybindings
;; similar to those used by the less(1) program are used.
;;
;; Originally written for v18 by David Gudeman (gudeman@arizona.edu)
;; Mods by Bengt Martensson, to closely resemble less (July 1987)
;;
;; If you would like all write-protected files to be visited in view-mode,
;; then add the following to your .emacs file:
;;
;;      (add-hook 'find-file-hooks 'auto-view-mode)

;;; Code:

(defvar view-search-string ""
  "Last string searched for with view-search functions.")

(defvar view-search-arg 1
  "Argument to last view search.")

(defvar view-default-lines 10
  "Default value for the \"d\" and \"u\" commands in view-mode")

;;;###autoload
(defvar view-minor-mode nil
  "Non-nil when view-mode is active.  Call `view-mode' to toggle.")
(make-variable-buffer-local 'view-minor-mode)

;;;###autoload
(defvar view-minor-mode-map
  (let ((map (make-keymap)))
    (set-keymap-name map 'view-minor-mode-map)
    (suppress-keymap map)
    (define-key map "-" 'negative-argument)
    (define-key map " " 'scroll-up)
    (define-key map "f" 'scroll-up)
    (define-key map "b" 'scroll-down)
    (define-key map 'backspace 'scroll-down)
    (define-key map 'delete 'scroll-down)
    (define-key map "\r" 'view-scroll-lines-up)
    (define-key map "\n" 'view-scroll-lines-up)
    (define-key map "e" 'view-scroll-lines-up)
    (define-key map "j" 'view-scroll-lines-up)
    (define-key map "y" 'view-scroll-lines-down)
    (define-key map "k" 'view-scroll-lines-down)
    (define-key map "d" 'view-scroll-some-lines-up)
    (define-key map "u" 'view-scroll-some-lines-down)
    (define-key map "r" 'recenter)
    (define-key map "t" 'toggle-truncate-lines)
    (define-key map "N" 'view-buffer)
    (define-key map "E" 'view-file)
    (define-key map "P" 'view-buffer)
    (define-key map "!" 'shell-command)
    (define-key map "|" 'shell-command-on-region)
    (define-key map "=" 'what-line)
    (define-key map "?" 'view-search-backward)
    (define-key map "h" 'view-mode-describe)
    (define-key map "s" 'view-repeat-search)
    (define-key map "n" 'view-repeat-search)
    (define-key map "/" 'view-search-forward)
    (define-key map "\\" 'view-search-backward)
    (define-key map "g" 'view-goto-line)
    (define-key map "G" 'view-last-windowful)
    (define-key map "%" 'view-goto-percent)
    (define-key map "p" 'view-goto-percent)
    (define-key map "m" 'point-to-register)
    (define-key map "'" 'register-to-point)
    (define-key map "C" 'view-cleanup-backspaces)
    (define-key map "\C-c\C-c" 'view-quit)
    ;; #### - should this use substitute-command-keys?
    (define-key map "\C-x\C-q" 'view-quit-toggle-ro)
    (define-key map "q" 'view-quit)
    map
    ))

;;;###autoload
(defcustom view-mode-line-string " View"
  "*String to display in the modeline when View mode is active.
Set this to nil if you don't want a modeline indicator."
  :type '(choice string
		 (const :tag "none" nil)))

(add-minor-mode 'view-minor-mode 
		'view-mode-line-string 
		view-minor-mode-map)

;;;###autoload
(defvar view-mode-map
  (let ((map (copy-keymap view-minor-mode-map)))
    (set-keymap-name map 'view-mode-map)
    map))

;;;###autoload
(defun view-file (filename &optional other-window-p)
  "Find FILENAME, enter view mode.  With prefix arg OTHER-WINDOW-P, use other window."
  (interactive "fView File: \nP")
  (let ((old-p (get-file-buffer filename))
	(obuf (current-buffer)))
    (if other-window-p
	(find-file-other-window filename)
      (find-file filename))
    (view-mode (if other-window-p nil obuf)
	       (if old-p nil 'kill-buffer))
    nil))

;;;###autoload
(defun view-buffer (buffer &optional other-window-p)
  "Switch to BUFFER, enter view mode.  With prefix arg use other window."
  (interactive "bView Buffer: \nP")
  (let ((obuf (current-buffer)))
    (if other-window-p
	(switch-to-buffer-other-window buffer)
      (switch-to-buffer buffer))
    (view-mode (if other-window-p nil obuf)
	       (if other-window-p nil 'bury-buffer))))

;;;###autoload
(defun view-file-other-window (filename)
  "Find FILENAME in other window, and enter view mode."
  (interactive "fView File: ")
  (view-file filename t))

;;;###autoload
(defun view-buffer-other-window (buffer)
  "Switch to BUFFER in another window, and enter view mode."
  (interactive "bView Buffer: ")
  (view-buffer buffer t))

(defun view-brief-help ()
  (message
   (substitute-command-keys
    "\\<view-minor-mode-map>\\[scroll-up] = page forward; \\[scroll-down] = page back; \
\\[view-mode-describe] = help; \\[view-quit] = quit.")))

(defvar view-major-mode)
(defvar view-exit-position)
(defvar view-prev-buffer)
(defvar view-exit-action)
(defvar view-old-buffer-read-only)

;;;###autoload
(defun view-minor-mode (&optional prev-buffer exit-action)
  "Minor mode for viewing text, with bindings like `less'.
Commands are:
\\<view-minor-mode-map>
0..9	prefix args
-	prefix minus
\\[scroll-up]	page forward
\\[scroll-down]	page back
\\[view-scroll-lines-up]	scroll prefix-arg lines forward, default 1.
\\[view-scroll-lines-down]	scroll prefix-arg lines backward, default 1.
\\[view-scroll-some-lines-down]	scroll prefix-arg lines backward, default 10.
\\[view-scroll-some-lines-up]	scroll prefix-arg lines forward, default 10.
\\[what-line]	print line number
\\[view-mode-describe]	print this help message
\\[view-search-forward]	regexp search, uses previous string if you just hit RET
\\[view-search-backward]	as above but searches backward
\\[view-repeat-search]	repeat last search
\\[view-goto-line]	goto line prefix-arg, default 1
\\[view-last-windowful]	goto line prefix-arg, default last line
\\[view-goto-percent]	goto a position by percentage
\\[toggle-truncate-lines]	toggle truncate-lines
\\[view-file]	view another file
\\[view-buffer]	view another buffer
\\[view-cleanup-backspaces]	cleanup backspace constructions
\\[shell-command]	execute a shell command
\\[shell-command-on-region]\
	execute a shell command with the region as input
\\[view-quit]	exit view-mode, and bury the current buffer.

If invoked with the optional (prefix) arg non-nil, view-mode cleans up
backspace constructions.

More precisely:
\\{view-minor-mode-map}"
  (interactive)

  (make-local-variable 'view-default-lines)
  (set (make-local-variable 'view-exit-position)      (point))
  (set (make-local-variable 'view-prev-buffer)   prev-buffer)
  (set (make-local-variable 'view-exit-action)   exit-action)
  (set (make-local-variable 'view-old-buffer-read-only)     buffer-read-only)
  (add-hook (make-local-variable 'change-major-mode-hook)
	    'view-fixup-read-only)
  (setq view-minor-mode  t
	buffer-read-only t)
  (view-brief-help))

;;;###autoload
(defun view-mode (&optional prev-buffer exit-action clean-bs)
  "View the current buffer using view-minor-mode.  This exists to be 99.9%
compatible with the implementations of `view-mode' in view.el and older
versions of view-less.el."
  (interactive (list nil 'bury-buffer current-prefix-arg))
  ;; #### - The first two arguments provide compatibility with view.el (and
  ;; thus FSFmacs), while the third argument as a prefix argument maintains
  ;; interactive compatibility with older versions of view-less.  --Stig
  (if clean-bs (cleanup-backspaces))
  (view-minor-mode prev-buffer exit-action))

;;;###autoload
(defun view-major-mode (&optional prev-buffer exit-action clean-bs)
  "View the current buffer using view-mode, as a major mode.
This function has a nonstandard name because `view-mode' is wrongly
named but is like this for compatibility reasons."
  ;; #### - The first two arguments provide compatibility with view.el (and
  ;; thus FSFmacs), while the third argument as a prefix argument maintains
  ;; interactive compatibility with older versions of view-less.  --Stig
  (interactive (list nil 'bury-buffer current-prefix-arg))
  (kill-all-local-variables)
  (use-local-map view-mode-map)
  (setq major-mode 'view-mode)
  (set (make-local-variable 'view-exit-position)      (point))
  (set (make-local-variable 'view-prev-buffer)   prev-buffer)
  (set (make-local-variable 'view-exit-action)   exit-action)
  (set (make-local-variable 'view-old-buffer-read-only)     buffer-read-only)
  (set (make-local-variable 'view-major-mode) t)
  (setq buffer-read-only t)
  (if clean-bs (cleanup-backspaces))
  (run-hooks 'view-mode-hook))

;;;###autoload
(defun auto-view-mode ()
  "If the file of the current buffer is not writable, call view-mode.
This is meant to be added to `find-file-hooks'."
  (or (file-writable-p buffer-file-name)
      (view-minor-mode)))

(defun view-fixup-read-only ()
  ;; doing M-x normal mode should NOT leave the buffer read-only
  (and (boundp 'view-old-buffer-read-only)
       (progn (setq buffer-read-only view-old-buffer-read-only)
	      (kill-local-variable 'view-old-buffer-read-only))))

(defun view-quit-toggle-ro ()
  "Exit view mode and execute the global binding of the key that invoked this
command.  Normally, this will toggle the state of `buffer-read-only', perhaps
invoking some version-control mechanism."
  (interactive)
  (setq view-exit-position nil)
  ;; Kludge so this works as advertised.  Stig, why can't you write
  ;; bug-free code???
  (let ((buffer-read-only buffer-read-only))
    (view-quit t))
  ;; no longer in view-minor-mode, so the keymap has changed...
  (call-interactively (key-binding (this-command-keys))))

(defun view-quit (&optional no-exit-action)
  "Exit view mode.  With prefix argument, keep the current buffer selected."
  (interactive "P")
  (view-fixup-read-only)
  (setq view-minor-mode nil)
  (if view-exit-position (goto-char view-exit-position))
  (if (and (boundp 'view-major-mode) view-major-mode)
      (fundamental-mode)
    (let ((pbuf view-prev-buffer)
	  (exitact view-exit-action))
      (if no-exit-action
	  nil
	(if exitact (funcall exitact (current-buffer)))
	(if pbuf (switch-to-buffer pbuf))))))

;; #### - similar to what's in man.el and this ought to be written in C anyway...  --Stig
(defun cleanup-backspaces ()
  "Cleanup backspace constructions.
_^H and ^H_ sequences are deleted.  x^Hx sequences are turned into x for all
characters x.  ^^H| and |^H^ sequences are turned into ^.  +^Ho and o^H+ are
turned into (+)."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (= (following-char) ?\C-h)
      (delete-char 1))
    (while (search-forward "\C-h" nil t)
      (backward-char 2)
      (cond ((looking-at "_\C-h\\|\\(.\\)\C-h\\1\\||\C-h\\^")
	     (delete-char 2))
	    ((looking-at ".\C-h_\\|\\^\C-h|")
	     (forward-char 1)
	     (delete-char 2))
	    ((looking-at "+\C-ho\\|o\C-h+")
	     (delete-char 3)
	     (insert "(+)"))
	    ((looking-at "|\C-h-")
	     (delete-char 3)
	     (insert "*"))
	    (t (forward-char 2))))))

(defun view-cleanup-backspaces ()
  "Cleanup backspaces and if buffer is currently unmodified, don't flag it
as a modified buffer.  This works even if the buffer is read-only."
  (interactive)
  (let ((buffer-read-only)
	(buf-mod (buffer-modified-p)))
    (cleanup-backspaces)
    ;; #### - THIS IS PROBABLY A REALLY DANGEROUS THING TO DO IN A MINOR MODE!!
    (set-buffer-modified-p buf-mod)))

;;;###autoload
(defun toggle-truncate-lines (&optional p)
  "Toggles the values of truncate-lines.
Positive prefix arg sets, negative disables."
  (interactive "P")
  (setq truncate-lines (if p
			   (> (prefix-numeric-value p) 0)
			 (not truncate-lines)))
  (recenter))

(defun view-scroll-lines-up (p)
  "Scroll up prefix-arg lines, default 1."
  (interactive "p")
  (scroll-up p))

(defun view-scroll-lines-down (p)
  "Scroll down prefix-arg lines, default 1."
  (interactive "p")
  (scroll-up (- p)))

(defun view-scroll-some-lines-down (&optional n)
  "Scroll down prefix-arg lines, default 10, or last argument."
  (interactive "p")
  (if (> n 1) (setq view-default-lines n))
  (scroll-down view-default-lines))

(defun view-scroll-some-lines-up (&optional n)
  "Scroll up prefix-arg lines, default 10, or last argument."
  (interactive "p")
  (if (> n 1) (setq view-default-lines n))
  (scroll-up view-default-lines))

(defun view-goto-line (&optional n)
  "Goto prefix arg line N.  N = 1 by default.."
  (interactive "p")
  (goto-line n))

(defun view-last-windowful (&optional n)
  "Goto prefix arg line N or the first line of the last windowful in buffer."
  (interactive "p")
  (if current-prefix-arg
      (goto-line n)
    (end-of-buffer)
    (recenter -1)
    (move-to-window-line 0)))

(defun view-goto-percent (&optional percent)
  "Set mark and go to a position PERCENT way into the current buffer."
  (interactive "p")
  (set-mark-command nil)
  (goto-char (+ (point-min) (/ (* percent (- (point-max) (point-min))) 100)))
  (beginning-of-line))

(defun view-mode-describe ()
  (interactive)
  (let ((mode-name "View")
	(major-mode 'view-mode))
    (describe-mode)))

(defun view-search-forward (s p)
  "Search forward for REGEXP.  If regexp is empty, use last search string.
With prefix ARG, search forward that many occurrences."
  (interactive "sView search: \np")
  (unwind-protect
      (re-search-forward
       (if (string-equal "" s) view-search-string s) nil nil p)
    (setq view-search-arg p)
    (or (string-equal "" s)
	(setq view-search-string s))))

(defun view-search-backward (s p)
  "Search backward for REGEXP.  If regexp is empty, use last search string.
With prefix ARG, search forward that many occurrences."
  (interactive "sView search backward: \np")
  (view-search-forward s (- p)))

(defun view-repeat-search (p)
  "Repeat last view search command.  If a prefix arg is given, use that
instead of the previous arg, if the prefix is just a -, then take the
negative of the last prefix arg."
  (interactive "P")
  (view-search-forward
   view-search-string
   (cond ((null p) view-search-arg)
	 ((eq p '-) (- view-search-arg))
	 (t (prefix-numeric-value p)))))

(provide 'view)
(provide 'view-less)

;;; view-less.el ends here