Commit d6a3febd authored by Martin Rudalics's avatar Martin Rudalics
Browse files

*** empty log message ***

parent 86ec740e
;;; lisp-mode.el --- Lisp mode, and its idiosyncratic commands
;; Copyright (C) 1985, 1986, 1999, 2000, 2001, 2002, 2003, 2004,
;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: lisp, languages
;; This file is part of GNU Emacs.
;; GNU Emacs 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 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; The base major mode for editing Lisp code (used also for Emacs Lisp).
;; This mode is documented in the Emacs manual.
;;; Code:
(defvar font-lock-comment-face)
(defvar font-lock-doc-face)
(defvar font-lock-keywords-case-fold-search)
(defvar font-lock-string-face)
(defvar lisp-mode-abbrev-table nil)
(define-abbrev-table 'lisp-mode-abbrev-table ())
(defvar emacs-lisp-mode-syntax-table
(let ((table (make-syntax-table)))
(let ((i 0))
(while (< i ?0)
(modify-syntax-entry i "_ " table)
(setq i (1+ i)))
(setq i (1+ ?9))
(while (< i ?A)
(modify-syntax-entry i "_ " table)
(setq i (1+ i)))
(setq i (1+ ?Z))
(while (< i ?a)
(modify-syntax-entry i "_ " table)
(setq i (1+ i)))
(setq i (1+ ?z))
(while (< i 128)
(modify-syntax-entry i "_ " table)
(setq i (1+ i)))
(modify-syntax-entry ?\s " " table)
;; Non-break space acts as whitespace.
(modify-syntax-entry ?\x8a0 " " table)
(modify-syntax-entry ?\t " " table)
(modify-syntax-entry ?\f " " table)
(modify-syntax-entry ?\n "> " table)
;; This is probably obsolete since nowadays such features use overlays.
;; ;; Give CR the same syntax as newline, for selective-display.
;; (modify-syntax-entry ?\^m "> " table)
(modify-syntax-entry ?\; "< " table)
(modify-syntax-entry ?` "' " table)
(modify-syntax-entry ?' "' " table)
(modify-syntax-entry ?, "' " table)
(modify-syntax-entry ?@ "' " table)
;; Used to be singlequote; changed for flonums.
(modify-syntax-entry ?. "_ " table)
(modify-syntax-entry ?# "' " table)
(modify-syntax-entry ?\" "\" " table)
(modify-syntax-entry ?\\ "\\ " table)
(modify-syntax-entry ?\( "() " table)
(modify-syntax-entry ?\) ")( " table)
(modify-syntax-entry ?\[ "(] " table)
(modify-syntax-entry ?\] ")[ " table))
table))
(defvar lisp-mode-syntax-table
(let ((table (copy-syntax-table emacs-lisp-mode-syntax-table)))
(modify-syntax-entry ?\[ "_ " table)
(modify-syntax-entry ?\] "_ " table)
(modify-syntax-entry ?# "' 14b" table)
(modify-syntax-entry ?| "\" 23bn" table)
table))
(defvar lisp-imenu-generic-expression
(list
(list nil
(purecopy (concat "^\\s-*("
(eval-when-compile
(regexp-opt
'("defun" "defun*" "defsubst" "defmacro"
"defadvice" "define-skeleton"
"define-minor-mode" "define-global-minor-mode"
"define-globalized-minor-mode"
"define-derived-mode" "define-generic-mode"
"define-compiler-macro" "define-modify-macro"
"defsetf" "define-setf-expander"
"define-method-combination"
"defgeneric" "defmethod") t))
"\\s-+\\(\\(\\sw\\|\\s_\\)+\\)"))
2)
(list (purecopy "Variables")
(purecopy (concat "^\\s-*("
(eval-when-compile
(regexp-opt
'("defvar" "defconst" "defconstant" "defcustom"
"defparameter" "define-symbol-macro") t))
"\\s-+\\(\\(\\sw\\|\\s_\\)+\\)"))
2)
(list (purecopy "Types")
(purecopy (concat "^\\s-*("
(eval-when-compile
(regexp-opt
'("defgroup" "deftheme" "deftype" "defstruct"
"defclass" "define-condition" "define-widget"
"defface" "defpackage") t))
"\\s-+'?\\(\\(\\sw\\|\\s_\\)+\\)"))
2))
"Imenu generic expression for Lisp mode. See `imenu-generic-expression'.")
;; This was originally in autoload.el and is still used there.
(put 'autoload 'doc-string-elt 3)
(put 'defun 'doc-string-elt 3)
(put 'defun* 'doc-string-elt 3)
(put 'defvar 'doc-string-elt 3)
(put 'defcustom 'doc-string-elt 3)
(put 'deftheme 'doc-string-elt 2)
(put 'defconst 'doc-string-elt 3)
(put 'defmacro 'doc-string-elt 3)
(put 'defmacro* 'doc-string-elt 3)
(put 'defsubst 'doc-string-elt 3)
(put 'defstruct 'doc-string-elt 2)
(put 'define-skeleton 'doc-string-elt 2)
(put 'define-derived-mode 'doc-string-elt 4)
(put 'define-compilation-mode 'doc-string-elt 3)
(put 'easy-mmode-define-minor-mode 'doc-string-elt 2)
(put 'define-minor-mode 'doc-string-elt 2)
(put 'easy-mmode-define-global-mode 'doc-string-elt 2)
(put 'define-global-minor-mode 'doc-string-elt 2)
(put 'define-globalized-minor-mode 'doc-string-elt 2)
(put 'define-generic-mode 'doc-string-elt 7)
(put 'define-ibuffer-filter 'doc-string-elt 2)
(put 'define-ibuffer-op 'doc-string-elt 3)
(put 'define-ibuffer-sorter 'doc-string-elt 2)
(put 'lambda 'doc-string-elt 2)
(put 'defalias 'doc-string-elt 3)
(put 'defvaralias 'doc-string-elt 3)
(put 'define-category 'doc-string-elt 2)
(defvar lisp-doc-string-elt-property 'doc-string-elt
"The symbol property that holds the docstring position info.")
(defun lisp-font-lock-syntactic-face-function (state)
(if (nth 3 state)
;; This might be a (doc)string or a |...| symbol.
(let ((startpos (nth 8 state)))
(if (eq (char-after startpos) ?|)
;; This is not a string, but a |...| symbol.
nil
(let* ((listbeg (nth 1 state))
(firstsym (and listbeg
(save-excursion
(goto-char listbeg)
(and (looking-at "([ \t\n]*\\(\\(\\sw\\|\\s_\\)+\\)")
(match-string 1)))))
(docelt (and firstsym (get (intern-soft firstsym)
lisp-doc-string-elt-property))))
(if (and docelt
;; It's a string in a form that can have a docstring.
;; Check whether it's in docstring position.
(save-excursion
(when (functionp docelt)
(goto-char (match-end 1))
(setq docelt (funcall docelt)))
(goto-char listbeg)
(forward-char 1)
(condition-case nil
(while (and (> docelt 0) (< (point) startpos)
(progn (forward-sexp 1) t))
(setq docelt (1- docelt)))
(error nil))
(and (zerop docelt) (<= (point) startpos)
(progn (forward-comment (point-max)) t)
(= (point) (nth 8 state)))))
font-lock-doc-face
font-lock-string-face))))
font-lock-comment-face))
;; The LISP-SYNTAX argument is used by code in inf-lisp.el and is
;; (uselessly) passed from pp.el, chistory.el, gnus-kill.el and score-mode.el
(defun lisp-mode-variables (&optional lisp-syntax)
(when lisp-syntax
(set-syntax-table lisp-mode-syntax-table))
(setq local-abbrev-table lisp-mode-abbrev-table)
(make-local-variable 'paragraph-ignore-fill-prefix)
(setq paragraph-ignore-fill-prefix t)
(make-local-variable 'fill-paragraph-function)
(setq fill-paragraph-function 'lisp-fill-paragraph)
;; Adaptive fill mode gets the fill wrong for a one-line paragraph made of
;; a single docstring. Let's fix it here.
(set (make-local-variable 'adaptive-fill-function)
(lambda () (if (looking-at "\\s-+\"[^\n\"]+\"\\s-*$") "")))
;; Adaptive fill mode gets in the way of auto-fill,
;; and should make no difference for explicit fill
;; because lisp-fill-paragraph should do the job.
;; I believe that newcomment's auto-fill code properly deals with it -stef
;;(set (make-local-variable 'adaptive-fill-mode) nil)
(make-local-variable 'indent-line-function)
(setq indent-line-function 'lisp-indent-line)
(make-local-variable 'parse-sexp-ignore-comments)
(setq parse-sexp-ignore-comments t)
(make-local-variable 'outline-regexp)
(setq outline-regexp ";;;\\(;* [^ \t\n]\\|###autoload\\)\\|(")
(make-local-variable 'outline-level)
(setq outline-level 'lisp-outline-level)
(make-local-variable 'comment-start)
(setq comment-start ";")
(make-local-variable 'comment-start-skip)
;; Look within the line for a ; following an even number of backslashes
;; after either a non-backslash or the line beginning.
(setq comment-start-skip "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
(make-local-variable 'font-lock-comment-start-skip)
;; Font lock mode uses this only when it KNOWS a comment is starting.
(setq font-lock-comment-start-skip ";+ *")
(make-local-variable 'comment-add)
(setq comment-add 1) ;default to `;;' in comment-region
(make-local-variable 'comment-column)
(setq comment-column 40)
;; Don't get confused by `;' in doc strings when paragraph-filling.
(set (make-local-variable 'comment-use-global-state) t)
(make-local-variable 'imenu-generic-expression)
(setq imenu-generic-expression lisp-imenu-generic-expression)
(make-local-variable 'multibyte-syntax-as-symbol)
(setq multibyte-syntax-as-symbol t)
(set (make-local-variable 'syntax-begin-function) 'beginning-of-defun)
(setq font-lock-defaults
'((lisp-font-lock-keywords
lisp-font-lock-keywords-1 lisp-font-lock-keywords-2)
nil nil (("+-*/.<>=!?$%_&~^:@" . "w")) nil
(font-lock-mark-block-function . mark-defun)
(font-lock-syntactic-face-function
. lisp-font-lock-syntactic-face-function))))
(defun lisp-outline-level ()
"Lisp mode `outline-level' function."
(let ((len (- (match-end 0) (match-beginning 0))))
(if (looking-at "(\\|;;;###autoload")
1000
len)))
(defvar lisp-mode-shared-map
(let ((map (make-sparse-keymap)))
(define-key map "\e\C-q" 'indent-sexp)
(define-key map "\177" 'backward-delete-char-untabify)
;; This gets in the way when viewing a Lisp file in view-mode. As
;; long as [backspace] is mapped into DEL via the
;; function-key-map, this should remain disabled!!
;;;(define-key map [backspace] 'backward-delete-char-untabify)
map)
"Keymap for commands shared by all sorts of Lisp modes.")
(defvar emacs-lisp-mode-map
(let ((map (make-sparse-keymap "Emacs-Lisp"))
(menu-map (make-sparse-keymap "Emacs-Lisp"))
(prof-map (make-sparse-keymap))
(tracing-map (make-sparse-keymap)))
(set-keymap-parent map lisp-mode-shared-map)
(define-key map "\e\t" 'lisp-complete-symbol)
(define-key map "\e\C-x" 'eval-defun)
(define-key map "\e\C-q" 'indent-pp-sexp)
(define-key map [menu-bar emacs-lisp] (cons "Emacs-Lisp" menu-map))
(define-key menu-map [eldoc]
'(menu-item "Auto-Display Documentation Strings" eldoc-mode
:button (:toggle . (bound-and-true-p eldoc-mode))
:help "Display the documentation string for the item under cursor"))
(define-key menu-map [checkdoc]
'(menu-item "Check Documentation Strings" checkdoc
:help "Check documentation strings for style requirements"))
(define-key menu-map [re-builder]
'(menu-item "Construct Regexp" re-builder
:help "Construct a regexp interactively"))
(define-key menu-map [tracing] (cons "Tracing" tracing-map))
(define-key tracing-map [tr-a]
'(menu-item "Untrace all" untrace-all
:help "Untraces all currently traced functions"))
(define-key tracing-map [tr-uf]
'(menu-item "Untrace function..." untrace-function
:help "Untraces FUNCTION and possibly activates all remaining advice"))
(define-key tracing-map [tr-sep] '("--"))
(define-key tracing-map [tr-q]
'(menu-item "Trace function quietly..." trace-function-background
:help "Trace the function with trace output going quietly to a buffer"))
(define-key tracing-map [tr-f]
'(menu-item "Trace function..." trace-function
:help "Trace the function given as a argument"))
(define-key menu-map [profiling] (cons "Profiling" prof-map))
(define-key prof-map [prof-restall]
'(menu-item "Remove Instrumentation for All Functions" elp-restore-all
:help "Restore the original definitions of all functions being profiled"))
(define-key prof-map [prof-restfunc]
'(menu-item "Remove Instrumentation for Function..." elp-restore-function
:help "Restore an instrumented function to its original definition"))
(define-key prof-map [sep-rem] '("--"))
(define-key prof-map [prof-resall]
'(menu-item "Reset Counters for All Functions" elp-reset-all
:help "Reset the profiling information for all functions being profiled"))
(define-key prof-map [prof-resfunc]
'(menu-item "Reset Counters for Function..." elp-reset-function
:help "Reset the profiling information for a function"))
(define-key prof-map [prof-res]
'(menu-item "Show Profiling Results" elp-results
:help "Display current profiling results"))
(define-key prof-map [prof-pack]
'(menu-item "Instrument Package..." elp-instrument-package
:help "Instrument for profiling all function that start with a prefix"))
(define-key prof-map [prof-func]
'(menu-item "Instrument Function..." elp-instrument-function
:help "Instrument a function for profiling"))
(define-key menu-map [edebug-defun]
'(menu-item "Instrument Function for Debugging" edebug-defun
:help "Evaluate the top level form point is in, stepping through with Edebug"
:keys "C-u C-M-x"))
(define-key menu-map [separator-byte] '("--"))
(define-key menu-map [disas]
'(menu-item "Disassemble byte compiled object..." disassemble
:help "Print disassembled code for OBJECT in a buffer"))
(define-key menu-map [byte-recompile]
'(menu-item "Byte-recompile Directory..." byte-recompile-directory
:help "Recompile every `.el' file in DIRECTORY that needs recompilation"))
(define-key menu-map [emacs-byte-compile-and-load]
'(menu-item "Byte-compile And Load" emacs-lisp-byte-compile-and-load
:help "Byte-compile the current file (if it has changed), then load compiled code"))
(define-key menu-map [byte-compile]
'(menu-item "Byte-compile This File" emacs-lisp-byte-compile
:help "Byte compile the file containing the current buffer"))
(define-key menu-map [separator-eval] '("--"))
(define-key menu-map [ielm]
'(menu-item "Interactive Expression Evaluation" ielm
:help "Interactively evaluate Emacs Lisp expressions"))
(define-key menu-map [eval-buffer]
'(menu-item "Evaluate Buffer" eval-buffer
:help "Execute the current buffer as Lisp code"))
(define-key menu-map [eval-region]
'(menu-item "Evaluate Region" eval-region
:help "Execute the region as Lisp code"
:enable mark-active))
(define-key menu-map [eval-sexp]
'(menu-item "Evaluate Last S-expression" eval-last-sexp
:help "Evaluate sexp before point; print value in minibuffer"))
(define-key menu-map [separator-format] '("--"))
(define-key menu-map [comment-region]
'(menu-item "Comment Out Region" comment-region
:help "Comment or uncomment each line in the region"
:enable mark-active))
(define-key menu-map [indent-region]
'(menu-item "Indent Region" indent-region
:help "Indent each nonblank line in the region"
:enable mark-active))
(define-key menu-map [indent-line] '("Indent Line" . lisp-indent-line))
map)
"Keymap for Emacs Lisp mode.
All commands in `lisp-mode-shared-map' are inherited by this map.")
(defun emacs-lisp-byte-compile ()
"Byte compile the file containing the current buffer."
(interactive)
(if buffer-file-name
(byte-compile-file buffer-file-name)
(error "The buffer must be saved in a file first")))
(defun emacs-lisp-byte-compile-and-load ()
"Byte-compile the current file (if it has changed), then load compiled code."
(interactive)
(or buffer-file-name
(error "The buffer must be saved in a file first"))
(require 'bytecomp)
;; Recompile if file or buffer has changed since last compilation.
(if (and (buffer-modified-p)
(y-or-n-p (format "Save buffer %s first? " (buffer-name))))
(save-buffer))
(let ((compiled-file-name (byte-compile-dest-file buffer-file-name)))
(if (file-newer-than-file-p compiled-file-name buffer-file-name)
(load-file compiled-file-name)
(byte-compile-file buffer-file-name t))))
(defcustom emacs-lisp-mode-hook nil
"Hook run when entering Emacs Lisp mode."
:options '(turn-on-eldoc-mode imenu-add-menubar-index checkdoc-minor-mode)
:type 'hook
:group 'lisp)
(defcustom lisp-mode-hook nil
"Hook run when entering Lisp mode."
:options '(imenu-add-menubar-index)
:type 'hook
:group 'lisp)
(defcustom lisp-interaction-mode-hook nil
"Hook run when entering Lisp Interaction mode."
:options '(turn-on-eldoc-mode)
:type 'hook
:group 'lisp)
(defun emacs-lisp-mode ()
"Major mode for editing Lisp code to run in Emacs.
Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs. Semicolons start comments.
\\{emacs-lisp-mode-map}
Entry to this mode calls the value of `emacs-lisp-mode-hook'
if that value is non-nil."
(interactive)
(kill-all-local-variables)
(use-local-map emacs-lisp-mode-map)
(set-syntax-table emacs-lisp-mode-syntax-table)
(setq major-mode 'emacs-lisp-mode)
(setq mode-name "Emacs-Lisp")
(lisp-mode-variables)
(setq imenu-case-fold-search nil)
(run-mode-hooks 'emacs-lisp-mode-hook))
(put 'emacs-lisp-mode 'custom-mode-group 'lisp)
(defvar lisp-mode-map
(let ((map (make-sparse-keymap))
(menu-map (make-sparse-keymap "Lisp")))
(set-keymap-parent map lisp-mode-shared-map)
(define-key map "\e\C-x" 'lisp-eval-defun)
(define-key map "\C-c\C-z" 'run-lisp)
(define-key map [menu-bar lisp] (cons "Lisp" menu-map))
(define-key menu-map [run-lisp]
'(menu-item "Run inferior Lisp" run-lisp
:help "Run an inferior Lisp process, input and output via buffer `*inferior-lisp*'"))
(define-key menu-map [ev-def]
'(menu-item "Eval defun" lisp-eval-defun
:help "Send the current defun to the Lisp process made by M-x run-lisp"))
(define-key menu-map [ind-sexp]
'(menu-item "Indent sexp" indent-sexp
:help "Indent each line of the list starting just after point"))
map)
"Keymap for ordinary Lisp mode.
All commands in `lisp-mode-shared-map' are inherited by this map.")
(defun lisp-mode ()
"Major mode for editing Lisp code for Lisps other than GNU Emacs Lisp.
Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs. Semicolons start comments.
\\{lisp-mode-map}
Note that `run-lisp' may be used either to start an inferior Lisp job
or to switch back to an existing one.
Entry to this mode calls the value of `lisp-mode-hook'
if that value is non-nil."
(interactive)
(kill-all-local-variables)
(use-local-map lisp-mode-map)
(setq major-mode 'lisp-mode)
(setq mode-name "Lisp")
(lisp-mode-variables)
(make-local-variable 'comment-start-skip)
(setq comment-start-skip
"\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\)\\(;+\\|#|\\) *")
(make-local-variable 'font-lock-keywords-case-fold-search)
(setq font-lock-keywords-case-fold-search t)
(setq imenu-case-fold-search t)
(set-syntax-table lisp-mode-syntax-table)
(run-mode-hooks 'lisp-mode-hook))
(put 'lisp-mode 'find-tag-default-function 'lisp-find-tag-default)
(defun lisp-find-tag-default ()
(let ((default (find-tag-default)))
(when (stringp default)
(if (string-match ":+" default)
(substring default (match-end 0))
default))))
;; Used in old LispM code.
(defalias 'common-lisp-mode 'lisp-mode)
;; This will do unless inf-lisp.el is loaded.
(defun lisp-eval-defun (&optional and-go)
"Send the current defun to the Lisp process made by \\[run-lisp]."
(interactive)
(error "Process lisp does not exist"))
(defvar lisp-interaction-mode-map
(let ((map (make-sparse-keymap))
(menu-map (make-sparse-keymap "Lisp-Interaction")))
(set-keymap-parent map lisp-mode-shared-map)
(define-key map "\e\C-x" 'eval-defun)
(define-key map "\e\C-q" 'indent-pp-sexp)
(define-key map "\e\t" 'lisp-complete-symbol)
(define-key map "\n" 'eval-print-last-sexp)
(define-key map [menu-bar lisp-interaction] (cons "Lisp-Interaction" menu-map))
(define-key menu-map [eval-defun]
'(menu-item "Evaluate Defun" eval-defun
:help "Evaluate the top-level form containing point, or after point"))
(define-key menu-map [eval-print-last-sexp]
'(menu-item "Evaluate and print" eval-print-last-sexp
:help "Evaluate sexp before point; print value into current buffer"))
(define-key menu-map [edebug-defun-lisp-interaction]
'(menu-item "Instrument Function for Debugging" edebug-defun
:help "Evaluate the top level form point is in, stepping through with Edebug"
:keys "C-u C-M-x"))
(define-key menu-map [indent-pp-sexp]
'(menu-item "Indent or Pretty-Print" indent-pp-sexp
:help "Indent each line of the list starting just after point, or prettyprint it"))
(define-key menu-map [lisp-complete-symbol]
'(menu-item "Complete Lisp Symbol" lisp-complete-symbol
:help "Perform completion on Lisp symbol preceding point"))
map)
"Keymap for Lisp Interaction mode.
All commands in `lisp-mode-shared-map' are inherited by this map.")
(defvar lisp-interaction-mode-abbrev-table lisp-mode-abbrev-table)
(define-derived-mode lisp-interaction-mode emacs-lisp-mode "Lisp Interaction"
"Major mode for typing and evaluating Lisp forms.
Like Lisp mode except that \\[eval-print-last-sexp] evals the Lisp expression
before point, and prints its value into the buffer, advancing point.
Note that printing is controlled by `eval-expression-print-length'
and `eval-expression-print-level'.
Commands:
Delete converts tabs to spaces as it moves back.
Paragraphs are separated only by blank lines.
Semicolons start comments.
\\{lisp-interaction-mode-map}
Entry to this mode calls the value of `lisp-interaction-mode-hook'
if that value is non-nil.")
(defun eval-print-last-sexp ()
"Evaluate sexp before point; print value into current buffer.
If `eval-expression-debug-on-error' is non-nil, which is the default,
this command arranges for all errors to enter the debugger.
Note that printing the result is controlled by the variables
`eval-expression-print-length' and `eval-expression-print-level',
which see."
(interactive)
(let ((standard-output (current-buffer)))
(terpri)
(eval-last-sexp t)
(terpri)))
(defun last-sexp-setup-props (beg end value alt1 alt2)
"Set up text properties for the output of `eval-last-sexp-1'.
BEG and END are the start and end of the output in current-buffer.
VALUE is the Lisp value printed, ALT1 and ALT2 are strings for the
alternative printed representations that can be displayed."
(let ((map (make-sparse-keymap)))
(define-key map "\C-m" 'last-sexp-toggle-display)
(define-key map [down-mouse-2] 'mouse-set-point)
(define-key map [mouse-2] 'last-sexp-toggle-display)
(add-text-properties
beg end
`(printed-value (,value ,alt1 ,alt2)
mouse-face highlight
keymap ,map
help-echo "RET, mouse-2: toggle abbreviated display"
rear-nonsticky (mouse-face keymap help-echo
printed-value)))))
(defun last-sexp-toggle-display (&optional arg)
"Toggle between abbreviated and unabbreviated printed representations."
(interactive "P")
(save-restriction
(widen)
(let ((value (get-text-property (point) 'printed-value)))
(when value
(let ((beg (or (previous-single-property-change (min (point-max) (1+ (point)))
'printed-value)
(point)))
(end (or (next-single-char-property-change (point) 'printed-value) (point)))
(standard-output (current-buffer))
(point (point)))
(delete-region beg end)
(insert (nth 1 value))
(or (= beg point)
(setq point (1- (point))))
(last-sexp-setup-props beg (point)
(nth 0 value)
(nth 2 value)
(nth 1 value))
(goto-char (min (point-max) point)))))))
(defun prin1-char (char)
"Return a string representing CHAR as a character rather than as an integer.
If CHAR is not a character, return nil."
(and (integerp char)
(eventp char)
(let ((c (event-basic-type char))
(mods (event-modifiers char))
string)
;; Prevent ?A from turning into ?\S-a.