;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Some Emacs Macros to toggle through an online demonstration ;;; planned in the BRICS CoW meeting on 18/05/2000 ;;; ;;; Synopsis: ;;; STANDALONE --- is required to work without other ;;; non-standard emacs packages around (!) ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;; ------------------------------ ;; USAGE: ;; ------------------------------ ;; After loading the demo library (load-demo), you should call ;; M-x init-demo ;; in order to get the shortcut-keys locally. ;; ;; Steer with the following keys: ;; C-n : goto next command; execute ;; C-j : toggle to next command (no execution - yet) ;; C-u : toggle to previous command (no execution - yet) ;; C-p : re-do same command (no execution - yet) ;; C-o : start over this demo ;; ---------------------------------------------------------------------- ;; ;; a demo is a list, where ;; * the first element denotes the position ;; * the second element denotes the name ;; * the rest is a bunch of strings to be inserted interactively ;; if they are not strings, they are assumed to be lists, where ;; - lists starting with M-x have an executable command as their cdr ;; ;;; ///////////////////////////////////////////////////////////// ;;; @TABLE OF CONTENTS: [TOCD: 19:54 19 Sep 2001] ;;; ;;; [0.1] Colors (Laptop) ;;; [0.2] Hilit-Recenter ;;; [0.2.1] unclean FIXES ;;; [1] Emacs definitions (from my-lisp-macros) ;;; [1.1] String to Number ;;; [1.2] Random ;;; [2] Libraries ;;; [2.1] Variable Definitions ;;; [3] DEMOS DEMOS DEMOS ;;; [3.1] Fun stuff: keyfakes ;;; ///////////////////////////////////////////////////////// ;;; @FILE: demo.el ;;; @PLACE: BRICS AArhus; host:harald ;;; @FORMAT: emacs lisp ;;; @AUTHOR: M. Oliver M'o'ller ;;; @BEGUN: 08/05/2000 ;;; @VERSION: V 1.0 Thu Jan 10 17:17:25 2002 ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (setq max-lisp-eval-depth 2000) ;;; ////////////////////////////////////////////// ;;; [0.1] Colors (Laptop) ;;; ////////////////////////////////////////////// (set-background-color "black") (set-foreground-color "cyan") (set-border-color "wheat") (set-cursor-color "red") (set-mouse-color "yellow") (defvar *color-is-white* nil) (defun toggle-colors () (interactive) (if (null *color-is-white*) (progn (setq *color-is-white* t) (set-background-color "white") (set-foreground-color "MidnightBlue")) (progn (setq *color-is-white* nil) (set-background-color "black") (set-foreground-color "cyan")))) (global-set-key [f7] #'toggle-colors) ;;; ////////////////////////////////////////////// ;;; [0.2] Hilit-Recenter ;;; ////////////////////////////////////////////// (message "** Loading Libraries...") (setq load-path (append (list "~/Demo" ) load-path)) (require 'custom) (require 'hilit19) (require 'comint) (require 'completion) (initialize-completions) ;;; //////////////////////////////////// ;;; [0.2.1] unclean FIXES ;;; //////////////////////////////////// (defmacro custom-declare-variable (&rest r) (cons 'custom-declare r)) (defun cddr (x) (cdr (cdr x))) ;; ------------------------------------------------------------------------- (message "** Loaded Libraries.") ;; ------------------------------------------------------------------------- ;;; ////////////////////////////////////////////////////////////////// ;;; [1] Emacs definitions (from my-lisp-macros) ;;; ////////////////////////////////////////////////////////////////// (defun my-string-pos-char (s pos) (aref s pos)) (defmacro scon (&rest args) (list 'let (list (list 's "") (list 'a (list 'quote args))) (list 'while (list 'not (list 'null 'a)) (list 'setq 's (list 'format "%s%s" 's (list 'eval (list 'car 'a)))) (list 'setq 'a (list 'cdr 'a))) 's)) (defmacro my-loop-for-i-from-downto-do (start end &rest exec) (list 'let (list (list 'i start) (list 'ex 'nil)) (list 'while (list '>= 'i end) (list 'setq 'ex (list 'quote exec)) (list 'while (list 'not (list 'null 'ex)) (list 'eval (list 'car 'ex)) (list 'setq 'ex (list 'cdr 'ex))) (list 'setq 'i (list '- 'i 1)) ))) (defun my-member (element list &rest cmp) (let ((comparison (if (null cmp) 'equal (car cmp)))) (if (null list) nil (if (funcall comparison (car list) element) t (my-member element (cdr list) comparison))))) (defun my-c-to-string (s) (format "%c" s)) (defun my-substring (s from &rest to-rest) (let ((res nil) (to (if to-rest (car to-rest) (length s)))) (my-loop-for-i-from-downto-do (min (- (length s) 1) to) from (setq res (cons (my-string-pos-char s i) res))) (eval (cons 'scon (mapcar #'my-c-to-string res))))) (setq load-path (cons (my-substring (pwd) 10) (cons "~/emacs" load-path))) (defun my-insert-char (c) (insert (format "%c" c))) (defun my-string-to-charlist (s) (let ((res nil)) (my-loop-for-i-from-downto-do (- (length s) 1) 0 (setq res (cons (my-string-pos-char s i) res))) res)) (defmacro my-loop-for-e-in-do (list &rest exec) (list 'let (list (list 'e 'nil) (list 'l list) (list 'ex 'nil)) (list 'while (list 'not (list 'listp 'l)) (list 'setq 'l (list 'eval 'l))) (list 'while (list 'not (list 'null 'l)) (list 'setq 'e (list 'car 'l)) (list 'setq 'l (list 'cdr 'l)) (list 'setq 'ex (list 'quote exec)) (list 'while (list 'not (list 'null 'ex)) (list 'eval (list 'car 'ex)) (list 'setq 'ex (list 'cdr 'ex))) ))) ;;; ////////////////////////////////////////////// ;;; [1.1] String to Number ;;; ////////////////////////////////////////////// (defun my-string-to-number (s &rest base) "Converts a string to a number, relative to a given base (2-36). If no base is given, it is assumed to be to base 10. The digits greater than 9 are assumed to be a,b,c,...z (upper or lowercase). Returns -1 if it fails." (let ((l (my-string-to-charlist s)) (base (if (null base) 10 (car base))) (res 0) (digit -1) (fault nil)) (my-loop-for-e-in-do l (cond ((and (<= 48 e) (<= e 57)) (setq digit (- e 48))) ((and (<= (aref "a" 0) e) (<= e (aref "z" 0))) (setq digit (+ 10 (- e (aref "a" 0))))) ((and (<= (aref "A" 0) e) (<= e (aref "Z" 0))) (setq digit (+ 10 (- e (aref "A" 0))))) (t (setq digit -1))) (if (or (< digit 0) (>= digit base)) (setq fault t) (setq res (+ digit (* base res))))) (if fault -1 res))) (defun my-hex-string-to-number (s) "Converts a hexadecimal string to a (elisp) number." (my-string-to-number s 16)) ;;; ////////////////////////////////////////////// ;;; [1.2] Random ;;; ////////////////////////////////////////////// (defvar *emacs-allows-large-integers* nil) (defvar my-random-seed 2821 "*Random") (defun get-random-seed () (interactive) (let ((pos nil) (name (buffer-name)) (res nil) (call-command (format "date -u +%s7%s12312345" "%S" "%S"))) (switch-to-buffer "*scratch*") (end-of-buffer) (setq pos (point-marker)) (shell-command call-command t) (goto-char pos) (forward-char 1) (setq pos (point-marker)) ;; (beginning-of-line) (forward-char 5) (kill-ring-save pos (point-marker)) (setq res (car kill-ring)) (goto-char pos) (backward-char 1) (kill-line 2) (switch-to-buffer name) (setq my-random-seed (my-string-to-number res)) (message (format "New Random Seed:%d" my-random-seed)) my-random-seed )) (defvar my-random-mod (if *emacs-allows-large-integers* 3952463048630778659 32003)) (defvar my-random-offset 777);;; (get-random-seed)) ;; (get-random-seed)) (defun my-random (&rest n) (let ((m (if (null n) 256 (car n)))) (setq my-random-seed (mod (+ my-random-offset (* my-random-seed my-random-seed)) my-random-mod)) (mod my-random-seed m))) ;;; ////////////////////////////////////////////////////////////////// ;;; [2] Libraries ;;; ////////////////////////////////////////////////////////////////// (require 'cl) (require 'cwb) ;(load-library "complete") ;(load-library "completion") ;(load-library "my-lisp-macros") ;(load-library "cwb") ;;; ////////////////////////////////////////////// ;;; [2.1] Variable Definitions ;;; ////////////////////////////////////////////// ;;; nil for immediate insert (defvar *fake-typing-with-speed* 0.6 "*\nIf non-nil, doe fake typing. The value is the average approximate delay in tenth-seconds.") (defvar *allow-fake-typing-nexttime* t "Auxillary varible to allow and block (when toggeling) the fake typing.") (defvar *allow-random-typos* 0.01 "*\nBold men cannot type...") (defvar *demo-allow-delay-via-timers* nil "If non-nil, all the delay is caused by timers (and the library timers is loaded). If false, the function artificial-delay is used instead. NOTE that the setting of the *fake-typing-with-speed* has to be adjusted, for it does not reflect a \"second\" any more, but some delay specific to your machine (and dependend on whether you compiled the demo.el file or not.") (defvar *demo-line-where-to-recenter* 20 "*If *demo-allow-delay-via-timers* it nil, then the screen refresh will be done around this line (sorry, seems to be necessary to specify this).") (defvar *active-demo*) (defvar *demo-pos* (point-marker)) (defvar *demo-last-inserted-pos* nil) (defvar *empty-demo* '(0 "EMPTY" " ")) (if *demo-allow-delay-via-timers* (require 'timer)) ;;; ////////////////////////////////////////////////////////////////// ;;; [3] DEMOS DEMOS DEMOS ;;; ////////////////////////////////////////////////////////////////// (defvar *iben-usage-demo* *empty-demo*) (setq *iben-usage-demo* '( 0 "IBEN-usage" ;; ---------------------------------------- "/users/btools/IBEN/bin/iben" "vars x y z" "f := (x & y) | z" "satisfy f" "print f" "show f" "quit" )) (defvar *cwb-cow-demo* *empty-demo*) (setq *cwb-cow-demo* '( 0 "CWB-Cow-demo" ;; ---------------------------------------- (M-x run-cwb) "clear ;" "** Start daVinci" (M-x (lambda () (message "demo: Starting daVinci....") (cwb-graph-display))) "agent X = a.X + b.X ;" "states(X) ;" "statesexp(X) ;" "random(10,X) ;" "** Now display the agent X" (M-x (lambda () (message "demo: displaying agent X") (cwb-graph-graph "X"))) "** checking trace-equivalence " "mayeq(X, a.X) ; " "mayeq(X, tau.X) ; " "** Making Coffee.... " (M-x (lambda () (message "demo: loading file coffee.cwb") (cwb-load-file "coffee.cwb"))) "** Smelling Coffee.... " "agent GoodMachine ;" (M-x (lambda () (message "demo: displaying coffee") (cwb-graph-graph "BadMachine") (cwb-graph-add-graph "GoodMachine") )) "mayeq(GoodMachine,BadMachine) ;" "strongeq(GoodMachine,BadMachine) ;" "strongeq(GoodMachine | Consumer , BadMachine | Consumer ) ;" "random(10, GoodMachine | Consumer ) ;" "strongeq( (GoodMachine|Consumer)\\Drinks , (BadMachine|Consumer)\\Drinks ) ;" "** Additional Equalities" "strongeq(a.0, a.0 + tau.a.0) ;" " eq(a.0, a.0 + tau.a.0) ;" "strongeq(a.(b.0 + tau.c.0) , a.(b.0 + tau.c.0) + a.c.0) ;" " eq(a.(b.0 + tau.c.0) , a.(b.0 + tau.c.0) + a.c.0) ;" "** Some simple mu-formulas" "checkprop(GoodMachine, [tau]T) ;" "checkprop(BadMachine, [tau]T) ;" "checkprop(GoodMachine, min(Z. T | <->Z) ) ;" "checkprop(GoodMachine, min(Z. [-coffee]F | (<->T & [-]Z)) ) ;" "checkprop( BadMachine, min(Z. [-coffee]F | (<->T & [-]Z)) ) ;" "** Loading file: Dekker.cwb" (M-x (lambda () (message "demo: loading file Dekker.cwb") (cwb-load-file "Dekker.cwb"))) "print; " "** show a Memory Cell" (M-x (lambda () (message "demo: displaying agent B1_false") (cwb-graph-graph "B1_false"))) "** show Process 1" (M-x (lambda () (message "demo: displaying agent Process_1") (cwb-graph-graph "Process_1"))) "prop DeadlockFree ;" "cp(System,DeadlockFree) ;" "prop Only_loop_1 ;" "cp(System,Only_loop_1) ;" "prop Imply_Bell_1_0 ;" "cp(System,Imply_Bell_1_0) ;" "** END of demo" "** REALLY END of demo..." "** ****************************************" "** ****************************************" )) (defvar *list-of-demos*) (setq *list-of-demos* (list *cwb-cow-demo* *iben-usage-demo* )) (setq *active-demo* (car *list-of-demos*)) ;;; ////////////////////////////////////////////////////////////////// ;;;[2] Functions to Run the Demos ;;; ////////////////////////////////////////////////////////////////// (defun dummy-fac (i) "Dummy function factorial; will not be correct for integers greater than 10 due to overflow. Serves as a mean to construct delays." (if (< i 2) 1 (* i (dummy-fac (- i 1))))) (defun artificial-delay (n) (my-loop-for-i-from-downto-do n 1 (dummy-fac 100))) (defun active-demo-next (&rest args) "insert the next demo line" (interactive) (let ((allow-macros (if (null args) t (car args)))) (setq *demo-pos* (point-marker)) (let ((now (nth (car *active-demo*) (cddr *active-demo*)))) (cond ((stringp now) (if (and *fake-typing-with-speed* *allow-fake-typing-nexttime*) (typing-like-insert now *fake-typing-with-speed*) (insert now)) (insert " ") (backward-char 1) (setq *demo-last-inserted-pos* (point-marker))) ((null allow-macros) (insert " ") (backward-char 1)) ((and (listp now) (eq (car now) 'M-x)) (eval (cdr now)) (insert " ") (backward-char 1) (beep) (artificial-delay 10) (beep) (setq *demo-last-inserted-pos* nil) ) (t (message (format "Sorry - Cannot do position %d in %s") (car *active-demo*) (cadr *active-demo*))) )) (setq *active-demo* (cons (mod (+ 1 (car *active-demo*)) (length (cddr *active-demo*))) (cdr *active-demo*)) *allow-fake-typing-nexttime* t))) (defun run-cwb () (cwb) (message "**** Please do **** : init-demo ") ) (defun toggle-demo-next () "replace the last demo line with the next one" (interactive) (if (equal (point-marker) *demo-last-inserted-pos*) (progn (goto-char *demo-pos*) (kill-line))) (setq *allow-fake-typing-nexttime* nil) (active-demo-next nil)) (defun toggle-demo-previous () "replace the last demo line with the next one" (interactive) (if (equal (point-marker) *demo-last-inserted-pos*) (progn (goto-char *demo-pos*) (kill-line))) (setq *allow-fake-typing-nexttime* nil) (setq *active-demo* (cons (mod (- (car *active-demo*) 2) (length (cddr *active-demo*))) (cdr *active-demo*))) (active-demo-next nil)) (defun toggle-demo-same () "replace the last demo line with the next one" (interactive) (if (equal (point-marker) *demo-last-inserted-pos*) (progn (goto-char *demo-pos*) (kill-line))) (setq *allow-fake-typing-nexttime* nil) (setq *active-demo* (cons (mod (- (car *active-demo*) 1) (length (cddr *active-demo*))) (cdr *active-demo*))) (active-demo-next nil)) (defun restart-active-demo () (interactive) (setq *demo-last-inserted-pos* nil) (setq *allow-fake-typing-nexttime* t) (setq *active-demo* (cons 0 (cdr *active-demo*))) (message (format "Demo \"%s\" restarted." (cadr *active-demo*)))) ;;; ////////////////////////////////////////////// ;;; [3.1] Fun stuff: keyfakes ;;; ////////////////////////////////////////////// (defun compute-char-class (c) (cond ;; -- lowercase ------------------------------ ((my-member c '(113 97 122 ) '=) 10) ((my-member c '(119 115 120 ) '=) 11) ((my-member c '(101 100 99 ) '=) 12) ((my-member c '(114 102 118 116 103 98 ) '=) 13) ((my-member c '(121 104 110 117 106 109) '=) 16) ((my-member c '(105 107 44) '=) 17) ((my-member c '(111 108 46) '=) 18) ((my-member c '(112 59 47 39 91 93) '=) 19) ;; -- uppercase ------------------------------ ((my-member c '(90 65 81) '=) 10) ((my-member c '(88 83 87) '=) 11) ((my-member c '(67 68 69 ) '=) 12) ((my-member c '(86 70 82 66 71 84 ) '=) 13) ((my-member c '(78 72 89 77 74 85 ) '=) 16) ((my-member c '(60 75 73 ) '=) 17) ((my-member c '(62 76 79 ) '=) 18) ((my-member c '(63 58 80 34 123 125) '=) 19) ((and (<= 32 c) (< c 42)) 1) ;; upper line + space ((and (<= 42 c) (< c 64)) 2) ;; numbers ((and (<= 123 c)(< c 127)) 2) ;; some special chars ;; ((and (<= 64 c) (< c 97)) 3) ;; ordinary alphabet ;; ((and (<= 97 c) (< c 123)) 4) ;; shifted alphabet (t 0))) (defun compute-key-distance-factor (cc dd) "Returns a value in (0..1]" (let ((c (compute-char-class cc)) (d (compute-char-class dd))) (cond ((or (= d 0) (= c 0)) 1.0) ((= c d) 0.9) ((and (= c 1) (= d 2)) 0.9) ((and (= c 1) (= d 10)) 0.8) ((and (= c 1) (= d 11)) 0.8) ((and (= c 1) (= d 12)) 0.8) ((and (= c 1) (= d 13)) 0.8) ((and (= c 1) (= d 16)) 0.8) ((and (= c 1) (= d 17)) 0.8) ((and (= c 1) (= d 18)) 0.8) ((and (= c 1) (= d 19)) 0.8) ((and (= c 2) (= d 10)) 0.8) ((and (= c 2) (= d 11)) 0.8) ((and (= c 2) (= d 12)) 0.8) ((and (= c 2) (= d 13)) 0.8) ((and (= c 2) (= d 16)) 0.8) ((and (= c 2) (= d 17)) 0.8) ((and (= c 2) (= d 18)) 0.8) ((and (= c 2) (= d 19)) 0.8) ((and (= c 10) (= d 11)) 0.35) ((and (= c 10) (= d 12)) 0.4) ((and (= c 10) (= d 13)) 0.5) ((and (= c 10) (= d 16)) 0.2) ((and (= c 10) (= d 17)) 0.3) ((and (= c 10) (= d 18)) 0.45) ((and (= c 10) (= d 19)) 0.5) ((and (= c 11) (= d 12)) 0.2) ((and (= c 11) (= d 13)) 0.4) ((and (= c 11) (= d 16)) 0.2) ((and (= c 11) (= d 17)) 0.3) ((and (= c 11) (= d 18)) 0.3) ((and (= c 11) (= d 19)) 0.5) ((and (= c 12) (= d 13)) 0.2) ((and (= c 12) (= d 16)) 0.2) ((and (= c 12) (= d 17)) 0.2) ((and (= c 12) (= d 18)) 0.3) ((and (= c 12) (= d 19)) 0.4) ((and (= c 13) (= d 16)) 0.2) ((and (= c 13) (= d 17)) 0.3) ((and (= c 13) (= d 18)) 0.4) ((and (= c 13) (= d 19)) 0.5) ((and (= c 16) (= d 17)) 0.2) ((and (= c 16) (= d 18)) 0.3) ((and (= c 16) (= d 19)) 0.5) ((and (= c 17) (= d 18)) 0.3) ((and (= c 17) (= d 19)) 0.5) ((and (= c 18) (= d 19)) 0.6) (t 1.0) ))) (defun typing-like-insert (string &rest speed) "Inserts a string in a similar-to-human typing way. If *demo-allow-delay-via-timers* is non-nil, this is done via setting up timers to do the insertion job (i.e. you can still *TYPE* during this process, but it will end up at the end of the typed line and the order of your letters might be scramled.) If *demo-allow-delay-via-timers* is nil, the delay is done explicitly by keeping emacs occupied, everything you typed just goes to the keyboard buffer (i.e. the order is right, but it might be truncated, if the buffer was full). " (interactive) (let ((delay (if (null speed) 0.3 (car speed))) (chars (my-string-to-charlist string)) (this-buffer (current-buffer)) (prev 0) (typo-length 0) (orig-typo-length 0) (added-delay 0) (sum 0)) (while (not (null chars)) (if (and *allow-random-typos* (<= typo-length 0) (> (my-random 1000) (- 1000 (* 1000 *allow-random-typos*)))) (progn (setq typo-length 1) (while (= 1 (my-random 2)) (setq typo-length (+ 1 typo-length))) (setq orig-typo-length typo-length))) (if (> typo-length 0) (setq chars (cons (+ 54 (my-random (- 122 54))) chars))) (setq added-delay (* (my-random 3) ;; stutter... (* 0.2 (/ (my-random (* delay 1000.0)) 1000)) (* 0.8 (/ (my-random (* delay 1000.0)) 1000) (compute-key-distance-factor prev (car chars))))) (setq sum (+ sum added-delay)) ;; (message (format "%f" sum)) ;; (message (format "%d" (my-random (floor (* delay 1000))))) (setq prev (car chars)) (if *demo-allow-delay-via-timers* (run-with-timer sum nil (list 'lambda (list ) (list 'my-insert-char (list 'car 'chars)))) (progn (artificial-delay (floor added-delay)) (my-insert-char (car chars)) ;;(redraw-display) ;;(display-buffer this-buffer) (hilit-recenter *demo-line-where-to-recenter*) )) (setq chars (cdr chars)) (if (= 1 typo-length) (while (> orig-typo-length 0) (setq added-delay (* 0.2 (/ (my-random (* delay 1000.0)) 1000))) (setq sum (+ sum added-delay)) (if *demo-allow-delay-via-timers* (run-with-timer sum nil (list 'lambda (list ) (list 'delete-backward-char 1))) (progn (artificial-delay (floor added-delay)) (delete-backward-char 1) (hilit-recenter *demo-line-where-to-recenter*) ;;(redraw-display) ;;(display-buffer this-buffer) )) (setq orig-typo-length (- orig-typo-length 1)) )) (setq typo-length (- typo-length 1)) ))) ;;; ---------------------------------------------------------------------- (fset 'init-demo [?\M-x ?g ?l ?o ?b ?a ?l ?- ?s ?e ?t ?- ?k ?e ?y return ?\C-n ?a ?c ?t ?i ?v ?e ?- ?d ?e ?m ?o ?- ?n ?e ?x ?t return ?\M-x ?g ?l ?o ?b ?a ?l ?- ?s ?e ?t ?- ?k ?e ?y return ?\C-j ?t ?o ?g ?g ?l ?e ?- ?d ?e ?m ?o ?- ?n ?e ?x ?t return ?\M-x ?g ?l ?o ?b ?a ?l ?- ?s ?e ?t ?- ?k ?e ?y return ?\C-u ?t ?o ?g ?g ?l ?e ?- ?d ?e ?m ?o ?- ?p ?r ?e ?v ?i ?o ?u ?s return ?\M-x ?g ?l ?o ?b ?a ?l ?- ?s ?e ?t ?- ?k ?e ?y return ?\C-p ?t ?o ?g ?g ?l ?e ?- ?d ?e ?m ?o ?- ?s ?a ?m ?e return ?\M-x ?g ?l ?o ?b ?a ?l ?- ?s ?e ?t ?- ?k ?e ?y return ?\C-o ?r ?e ?s ?t ?a ?r ?t ?- ?a ?c ?t ?i ?v ?e ?- ?d ?e ?m ?o return ?\M-x ?g ?l ?o ?b ?a ?l ?- ?s ?e ?t ?- ?k ?e ?y return C-return ?c ?o ?m ?p ?l ?e ?t ?e return ]) (message "** Call init-demo to start **") (defun zzz () (interactive) (typing-like-insert "This buffer is for notes you don't want to save, and for Lisp evaluation. If you want to create a file, visit that file with C-x C-f, then enter the text in that file's own buffer.")) ;; ------------------------------------------------------------------------- (provide 'demo)