]> git.rkrishnan.org Git - .emacs.d.git/blob - emacs/screencast.el
ec9ec0afc335a6e576e35bd25fbc9a568f81265d
[.emacs.d.git] / emacs / screencast.el
1 ;;; screencast.el --- demonstrate the capabilities of Emacs
2
3 ;; Copyright (C) 2009 ESBEN Andreasen <esbenandreasen@gmail.com>
4
5 ;; Authors: Esben Andreasen <esbenandreasen@gmail.com>
6
7 ;; Keywords: demo screencast
8
9 ;; This file is not an official part of Emacs.
10
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with this program; if not, you can either send email to this
23 ;; program's maintainer or write to: The Free Software Foundation,
24 ;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
25
26 ;;; Commentary:
27
28 ;; This file allows you to create video-like sessions, which
29 ;; demonstrates the capabilities of Emacs.
30
31 ;;; Usage:
32
33 ;; Install this file to an appropriate directory in your load-path,
34 ;; and add these expressions to your ~/.emacs
35
36 ;; (auto-load 'screencast "screencast")
37
38 ;; Try it out by evaluating (screencast-screencast-producer) and (screencast-screencast-user)
39
40 ;; Your own screencast files should have a (require 'screencast)
41
42 ;;; Conventions:
43
44 ;; PRODUCER : creates a screencast
45
46 ;; USER     : sees a screencast
47
48 ;; producer sections in this document contains variables which the producer
49 ;; should modify as need be, and functions to be called during the creation of a
50 ;; screencast
51
52 ;;; Change-log:
53
54 ;; 1.0: core functionality
55
56 ;; 1.1: PRODUCER ADDITIONS:
57 ;;      public variables which contain information about the current screencast
58 ;;      ability to change last-command and last-command-char
59 ;;      ability to use let and flet, while still outputting command descriptions
60 ;;      ability to create blinking sections to move the attention towards those
61 ;;      ability to show the region as if transient-mark-mode was on
62 ;;
63 ;;      split the screencasts for the producer into a basic and an advanced
64 ;;      voice synthesizing of typed text. Requires festival to be installed.
65 ;;      global speed control
66 ;;      typed strings in screencasts can not contain tabs and newlines
67 ;;; Code:
68
69 (defconst screencast-message-buffer-name "*Screencast Messages*"
70   "The name of the buffer to put messages from the screencast in")
71
72 (defconst screencast-version 1.1 "The version number of the screencast-mode")
73
74 (defconst screencast-speed-relation-speech-type 18.0
75   "When this is correctly adjusted, speech and typing should end
76 at the same time. Lower values means faster speech.")
77 ;;;; BEGIN USER VARIABLES
78 (defvar screencast-pause-length 2 "The length of a pause ('p) in the screencast")
79
80 (defvar screencast-pause-char-length 0.12
81   "The time between each typed character in the function `screencast-insert-with-delay'")
82
83 (defvar screencast-pause-command-length 3
84   "The time between the announcement of the function call, and the call itself.")
85
86 (defvar screencast-speech nil "If non-nil, slowly typed strings are read aloud")
87
88 (defvar screencast-speed 1.0 "How fast the screencast should be. Higher values equals higher speed. This can not be changed _during_ the screencast.") 
89 ;;;; BEGIN PRODUCER VARIABLES
90 ;; these variables should be changed as needed by the producer
91
92 (defvar screencast-dont-print-list '(
93                                      progn 
94                                       let
95                                       flet
96                                       save-excursion
97                                       save-window-excursion
98                                       i
99                                       screencast-producer-insert-with-delay
100                                       screencast-producer-set-last-command
101                                       screencast-producer-set-last-char
102                                       screencast-producer-new-buffer
103                                       screencast-producer-show-region
104                                       screencast-producer-blink-regions)
105   "A list of lists of function names which aren't printed as
106   being evaluated in the messages, this includes all producer
107   functions by default")
108
109 (defvar screencast-producer-blink-time 0.5
110   "The time a blink lasts.")
111
112 ;; variables which can be read during run-time to obtain information about the
113 ;; current screencast
114 (defvar screencast-producer-nopause nil
115   "Variable to be used for producer functions if they are using
116  pauses, they should deactivate the pause if this variable is non-nil.")
117
118 (defvar screencast-producer-command-buffer nil
119   "Variable to be used for producer functions if they are using
120  need the current command-buffer.")
121
122 (defvar screencast-producer-step-number 0
123   "Variable to be used for producer functions if they need to
124 know the current step number. 
125 This is a _COPY_ of the value the screencast uses!")
126
127 (defvar screencast-producer-beginat 0
128   "Variable to be used for producer functions if they need to
129   know where the screencast is supposed to be using pauses at")
130 ;;;; END PRODUCER VARIABLES
131
132
133 ;;;; BEGIN MODE
134 (defvar screencast-mode-map 
135   (let ((map (make-sparse-keymap)))
136     (define-key map (kbd "RET") 'screencast-goto-step)
137     map)
138   "Keymap for `screencast-mode'."
139   )
140
141 (define-derived-mode screencast-mode nil "screencast"
142   "Major mode for viewing screencasts."
143   (auto-fill-mode 1)
144   )
145 ;;;; END MODE
146
147 ;;;; BEGIN PRODUCER FUNCTIONS
148 (defun screencast-producer-insert-with-delay (string)
149   "Screencast producer function. _i_nserts STRING with a delay between each character.
150 See `screencast-insert-with-delay' for more details."
151   (let ((screencast-speech nil))
152     (screencast-insert-with-delay string screencast-producer-nopause)))
153
154 (defalias 'i 'screencast-producer-insert-with-delay
155   "Short name for `screencast-producer-insert-with-delay'.
156 This is chosen as it improves readability a lot in the screencast-source.")
157
158 (defun screencast-producer-set-last-command (f last) 
159   "Sets the last-command to LAST before evaluating F.
160 Also prints the info about F, like it would have done normally." 
161   (screencast-producer-show-command (car f))
162   (eval-with-last f last)
163   )
164
165 (defun eval-with-last (f last)
166   (eval (list 'progn
167               ;; wtf? that's the only way it works (lines can be permuted!)
168               '(setq last-command last)
169               '(setq this-command last)
170               f)))
171
172 (defun screencast-producer-set-last-char (char f) 
173   "Sets the last-command to CHAR before evaluating F.
174 Also prints the info about F, like it would have done normally."
175   (screencast-producer-show-command (car f))
176   (eval (list 'progn 
177               '(setq last-command-char (string-to-char char))
178               f)))
179
180 (defun screencast-producer-show-command (command)
181   "Shows the COMMAND, and how it can be called in the message-buffer."
182   (pop-to-buffer (get-buffer screencast-message-buffer-name))
183   (screencast-show-command command
184                            screencast-producer-step-number
185                            screencast-producer-command-buffer)
186   (pop-to-buffer (get-buffer screencast-producer-command-buffer)))
187
188 (defun screencast-producer-new-buffer (list command-buffer-name)
189   "Screencast producer function. Creates an new screencast with
190  COMMAND-BUFFER-NAME as the command-buffer.  The message-buffer
191  remains the same.  Once the inner screencast ends, the original
192  command-buffer regains its status.
193
194
195 IMPORTANT: 
196
197 You are responsible for killing the `COMMAND-BUFFER'
198 before the outermost screencast ends, otherwise you'll receive
199 the modified buffer the next time you run the outermost
200 screencast."
201   ;; we want to start an 'inner screencast', but the current buffer is the
202   ;; command-buffer, and the expected starting buffer is the
203   ;; screencast-message-buffer
204   (pop-to-buffer (get-buffer screencast-message-buffer-name))
205   (screencast-internal list 
206                        (get-buffer command-buffer-name)
207                        screencast-producer-beginat)
208   )
209
210 (defun screencast-producer-show-region (beg end)
211   "Marks the currently active region as if transient mark mode was on."
212   (unless screencast-producer-nopause
213     (let ((overlay (make-overlay beg end)))
214       (overlay-put overlay 'face (cons beg end))
215       ;; unless there's a LOT of regions, the blinks will be synchronous
216       (run-with-timer screencast-pause-length nil 'delete-overlay overlay)
217       )
218     (sit-for screencast-pause-length)
219     )
220   )
221
222 (defun screencast-producer-blink-regions (regions)
223   "The REGIONS will blink.
224 A region is a pair: (beg . end)."
225   (unless screencast-producer-nopause
226     (dotimes (n 5)
227       (dolist (region regions)
228         (let ((overlay (make-overlay (car region) (cdr region))))
229           (overlay-put overlay 'face 'region)
230           ;; unless there's a LOT of regions, the blinks will be synchronous
231           (run-with-timer screencast-producer-blink-time nil 'delete-overlay overlay))
232         )
233       (sit-for (* 2 screencast-producer-blink-time)) 
234       )))
235
236 ;;;; END PRODUCER FUNCTIONS
237 ;;;; BEGIN CORE
238 (defun make-region-clickable (beg end action &optional key)
239   "Makes the chosen region clickable, executing chosen action.
240 Default key is [mouse-1]."
241   (let ((map (make-sparse-keymap))
242         (keyc (if key
243                   key
244                 [mouse-1]))
245         )
246     (define-key map keyc action)
247     (put-text-property 
248      beg 
249      end
250      'keymap map))
251   )
252
253 (defun screencast-fontify-step-region ()
254   "Fontifies regions with step-references.
255 To be called immediately after functions which put step-numbers
256 in the message-buffer. Will fontify from the beginning of the
257 line with the step number to the end of the buffer."
258   (save-excursion
259     (goto-char (point-max))
260     (let ((beg (search-backward-regexp "^Step [[:digit:]]+:" (point-min))))
261       (screencast-put-shadow-and-make-clickable beg (point-max))
262       )))
263
264 (defun screencast-put-shadow-and-make-clickable (beg end)
265   "The region between BEG and END becomes shadowed and clickable.
266 `screencast-goto-step' is evalled when clicked"
267   (add-text-properties beg (- end 0)
268                        (list
269                         'face 'shadow
270                         'mouse-face 'highlight 
271                         'help-echo "mouse-1: continue from this step"
272                         ))
273   (make-region-clickable beg (- end 0) 'screencast-goto-step))
274
275 (defun screencast-get-step ()
276   "Returns the step-number of a step-reference region.
277 If not in step-reference region, returns nil" 
278
279   (if
280       ;; check if we are at a step-reference region
281       (save-excursion
282         (goto-char (line-end-position))
283         (or
284          ;; first line
285          (search-backward-regexp "^Step [[:digit:]]+:" (line-beginning-position) t)
286          ;; second line
287          (search-backward-regexp "^  Callable with:" (line-beginning-position) t)))
288       ;; get the step number
289       (save-excursion
290         (search-backward-regexp "^Step \\([[:digit:]]+\\):")
291         (let ((beg (match-beginning 1))
292               (end (match-end 1)))
293           (string-to-number
294            (buffer-substring-no-properties  beg end))))
295     ;; not in step-reference region
296     nil))
297
298 (defun repeat-string (s n)
299   (apply 'concat (make-list n s)))
300
301 (defun screencast-make-break (nopause)
302   (screencast-newline-only-once)
303   (newline)
304   (screencast-line)
305   (newline)
306   (screencast-pause-maybe nopause)
307   (screencast-pause-maybe nopause)
308   )
309
310 (defun screencast-pause-maybe (nopause &optional length)
311   "Pauses the program, unless NOPAUSE is non-nil.
312     If length is nil, a default pause LENGTH is used."
313   (unless nopause
314     (let ((l (if length
315                  length
316                screencast-pause-length)))
317       (sit-for l))))
318
319 (defun n-first (n list)
320   "The n first elements of a list."
321   (loop for x in list repeat n collect x))
322
323 (defun buffer-recreate (buffer-name)
324   "Kills the buffer with BUFFER-NAME, and recreates it."
325   (let ((buffer (get-buffer buffer-name)))
326     (when buffer
327       (when (buffer-file-name buffer)
328         (save-excursion
329           (set-buffer buffer)
330           (unless (let ((start (substring-no-properties buffer-name 0 1)))
331                     (or (string= start " ") (string= start "*")))
332             (save-buffer)))
333         (kill-buffer buffer-name)))
334     (get-buffer-create buffer-name))
335   )
336 (defun screencast-goto-step (&optional arg)
337   "Restarts the screencast at the chosen ARG step. Default is the first step."
338   (interactive "p")
339   (let ((step (if (not (= 1 arg))
340                   arg
341                 (screencast-get-step)))
342         ;; bug? using (point), standing at point max gives nil values! 
343         (list (get-text-property (point-min) 'screencast-list))
344         (name (get-text-property (point-min) 'screencast-command-buffer-name)))
345     ;;     (print step)
346     ;;     (print list)
347     ;;     (print name)
348     (screencast list name 
349                 -1 ; we just ran the screencast, so version should be no problem      
350                 (if step
351                     (- step 1)    ; the command just before!
352                   
353                   0))
354     ))
355
356 (defun screencast-newline-only-once ()
357   "Inserts a newline at point if, and only if the current line is nonempty."
358   (unless (= (line-beginning-position) (line-end-position))
359     (newline))
360   )
361
362 (defun screencast-make-region-clickable (beg end action &optional key)
363   "Makes the chosen region clickable, executing chosen action.
364 Default key is [mouse-1]."
365   (let ((map (make-sparse-keymap))
366         (keyc (if key
367                   key
368                 [mouse-1]))
369         )
370     (define-key map keyc action)
371     (put-text-property 
372      beg 
373      end
374      'keymap map))
375   )
376
377 (defun screencast-show-command (com step command-buffer)
378   "Inserts the STEP number and key-binding for a command, COM."
379   (screencast-newline-only-once)
380   (insert "Step " (number-to-string step) ": `" (symbol-name com) "'")
381   (newline) 
382   (insert "  Callable with: ") 
383   (insert (where-is-return com command-buffer))
384   (screencast-fontify-step-region)
385   (newline)
386   )
387
388 (defun screencast-line (&optional length)
389   (let ((l (if length
390                length
391              25)))
392     (screencast-newline-only-once)
393     (insert (repeat-string "-" l))
394     (center-line)
395     (newline)
396     ))
397
398 (defun screencast-header ()
399   (screencast-newline-only-once)
400   (newline)
401   (screencast-line 50)
402   (newline))
403
404 (defun screencast-speech-start (string nopause)
405   "Starts the speech-synthesizer with STRING, unless NOPAUSE is nonnil.
406 Also requires `screencast-speech' to be non-nil.
407 The speech speed depends on the typing speed (`screencast-speed-relation-speech-type')."
408   (when (and (not nopause) screencast-speech)
409     (let* ((duration (concat 
410                       "-b \"(Parameter.set 'Duration_Stretch " 
411                       (number-to-string (* screencast-pause-char-length
412                                            screencast-speed-relation-speech-type)) ")\""))
413            (tosay (replace-regexp-in-string "'" "'\"'\"'" string))
414            (say (concat "-b '(SayText \"" tosay "\")'"))
415            )
416       (save-window-excursion
417         (shell-command
418          (concat "festival " duration " " say "&"))
419         ))))
420
421 (defun screencast-speech-wait-for (nopause)
422   "Blocks until the speech synthesizer is done speaking."
423   (when (and (not nopause) screencast-speech)
424     (shell-command "while [ `pgrep festival` ] ; do sleep 0.1; done;")
425     (sit-for 0.1))                      ; needed
426   )
427
428 (defun screencast-insert-with-delay (string &optional nopause)
429   "Inserts STRING with a delay between each character.
430 If NOPAUSE is non-nil, the delay will be 0.
431
432 The pause between each character is given by `screencast-pause-char-length'."
433   (let ((string (screencast-strip-newlines-and-normalize-whitespace string)))
434     (screencast-speech-start string nopause)
435     (let ((l (string-to-list string)))
436       (dolist (c l)
437         (insert c)
438         ;; simple filling. If the char position equals fill-column. The
439         ;; whole word is moved to the next line.
440         (when (and (= (- (line-end-position) (line-beginning-position)) fill-column))
441           (search-backward " ") 
442           (insert "\n ") ; two space indentation as the previous space is moved too
443           (end-of-line)  ; ?
444           )
445         (screencast-pause-maybe nopause screencast-pause-char-length)))
446     (screencast-speech-wait-for nopause)
447     )
448   )
449
450 (defun screencast-strip-newlines-and-normalize-whitespace (string)
451   "Replaces all newlines and tabs in STRING by a single
452 whitespace, also collapses multiple whitespaces."
453   (replace-regexp-in-string "[ ]+" " " (replace-regexp-in-string "\n" " " string)))
454
455 (defalias 'screencast 'screencast-producer-screencast "Renaming for simplicity")
456
457 (defun screencast-producer-screencast (list command-buffer-name
458                                             version &optional beginat init)
459   "Prints and evaluates a list, LIST, of strings and functions in a tempo humans can follow.
460 The strings in LIST is printed to the screencast-message-buffer.
461 Functions are evaluated in the buffer named COMMAND-BUFFER-NAME.
462 VERSION is the version of screencast-mode the screencast is
463 written for, older versions of screencast-mode might not support
464 everything in newer screencasts.  
465 The first BEGINAT elements of the list will be done without
466 delays.  
467 INIT is a list of functions to be evaluated in the message-buffer
468 prior to the first message"
469   (when (> version screencast-version)
470     (error 
471      (concat "The version of the screencast (" (number-to-string
472                                                 version) ") is newer than the version of the screencast-mode
473 itself (" (number-to-string screencast-version) "). You might still be able
474 to run the screencast successfully though, just change the
475 screencasts version number to try it out.")))
476
477
478   ;; preparations:
479   (let* (
480          ;; speed adjustments
481          (screencast-pause-length (/ screencast-pause-length
482                                      screencast-speed))
483          (screencast-pause-char-length (/
484                                         screencast-pause-char-length
485                                         screencast-speed))
486          (screencast-pause-command-length (/
487                                            screencast-pause-command-length
488                                            screencast-speed))
489          ;; buffers
490          (message-buffer (buffer-recreate screencast-message-buffer-name))
491          (command-buffer (if (string= command-buffer-name 
492                                       screencast-message-buffer-name)
493                              message-buffer
494                            (buffer-recreate command-buffer-name)))
495          ;; numbers
496          (screencast-step-number 0)
497          (beginat (if beginat
498                       beginat
499                     0)))
500     (delete-other-windows)
501     (split-window-horizontally)
502     (switch-to-buffer message-buffer)
503     (pop-to-buffer message-buffer)
504     (display-buffer command-buffer)
505     (screencast-mode)
506     (toggle-read-only 0)
507     ;; evaluate all the functions of init
508     (dolist (f init)
509       (eval f))
510
511     ;; show
512     (screencast-internal list command-buffer beginat)
513     ;; save the arguments in the buffer
514     (add-text-properties (point-min) (point-max)
515                          (list 'screencast-list list
516                                'screencast-command-buffer-name command-buffer-name))
517     (toggle-read-only 1)
518     )
519   )
520
521 (defun screencast-internal (list command-buffer beginat)
522   "The internal version of screencast, refer to the documentation string
523     there."
524   ;; producer variables
525   (setq screencast-producer-command-buffer command-buffer)
526   (setq screencast-producer-beginat beginat)
527   ;; make sure we are visiting the file in case it is needed (e.g. compile!)
528   (save-excursion
529     (set-buffer command-buffer)
530     (unless (buffer-file-name)
531       (set-visited-file-name (buffer-name))
532       ))
533   ;; for each element in the list
534   (dolist (c list)
535     (let ((nopause
536            (if (>= screencast-step-number beginat)
537                nil
538              t)))
539       ;; producer variables        
540       (setq screencast-producer-nopause nopause) 
541       (setq screencast-producer-step-number screencast-step-number) 
542       (cond
543        ((symbolp c)
544         ;; special symbols
545         (cond
546          ((eq 's c)                     ; step
547           (screencast-newline-only-once)
548           (insert "Step " (number-to-string screencast-step-number) ":")
549           (screencast-fontify-step-region)
550           )
551          ((eq 'l c)                     ; line
552           (screencast-line))
553          ((eq 'n c)                     ; newline
554           (newline))
555          ((eq 'p c)                     ; pause 
556           (screencast-pause-maybe nopause))
557          ((eq 'b c)                     ; break
558           (screencast-make-break nopause)
559           )
560          (t
561           (error (concat "Screencast-internal encountered an error: Unknown symbol: " (symbol-name c)))))
562         )
563        ((listp c)
564         ;; function
565         (progn
566           (unless (member (car c) screencast-dont-print-list) ; these need no print
567             (screencast-show-command (car c) screencast-step-number command-buffer)
568             )
569           (unless nopause     
570             (screencast-pause-maybe nopause screencast-pause-command-length) ; pause
571             )
572           (if (member (car c) '(let flet)) 
573               (progn
574                 ;; we want the environment - but also to print the commands! 
575                 (eval (list (car c)     ; the members above
576                             (cadr c)    ;the lets of flets
577                             '(screencast-internal (cddr c) command-buffer beginat))) ;the rest
578                 )
579             ;; evaluate standard
580             (progn 
581               ;; save excursion style which allows for inner screencasts
582               (pop-to-buffer command-buffer)
583               (eval c)
584               (pop-to-buffer screencast-message-buffer-name)))
585           (pop-to-buffer screencast-message-buffer-name) ; needed to regain real focus!
586           ))
587        ((stringp c)
588         ;; it's a string - instert it.
589         (screencast-insert-with-delay c nopause))
590        (t
591         (error (concat "I don't know what to do with element:" c)))
592        )
593       (setq screencast-step-number (+ 1 screencast-step-number)) ; inc the step number
594       )
595     )
596   )
597
598 (defun where-is-return (definition buffer)
599   "A modification of where-is, which returns the message-string instead of printing it.
600   Also skips the removes name from the output.
601   BUFFER is the buffer to call where-is in."
602   (save-excursion
603     (set-buffer buffer)
604     (let ((func (indirect-function definition))
605           (defs nil)
606           (return-string ""))
607       ;; In DEFS, find all symbols that are aliases for DEFINITION.
608       (mapatoms (lambda (symbol)
609                   (and (fboundp symbol)
610                        (not (eq symbol definition))
611                        (eq func (condition-case ()
612                                     (indirect-function symbol)
613                                   (error symbol)))
614                        (push symbol defs))))
615       ;; Look at all the symbols--first DEFINITION,
616       ;; then its aliases.
617       (dolist (symbol (cons definition defs))
618         (let* ((remapped (command-remapping symbol))
619                (keys (where-is-internal
620                       symbol overriding-local-map nil nil remapped))
621                (keys (mapconcat 'key-description keys ", "))
622                string)
623           (setq string
624                 (if t
625                     (if (> (length keys) 0)
626                         (if remapped
627                             (format "%s (%s) (remapped from %s)"
628                                     keys remapped symbol)
629                           (format "%s" keys))
630                       (format "M-x %s RET" symbol))
631                   (if (> (length keys) 0)
632                       (if remapped
633                           (format "%s is remapped to %s which is on %s"
634                                   symbol remapped keys)
635                         (format "%s is on %s" symbol keys))
636                     ;; If this is the command the user asked about,
637                     ;; and it is not on any key, say so.
638                     ;; For other symbols, its aliases, say nothing
639                     ;; about them unless they are on keys.
640                     (if (eq symbol definition)
641                         (format "%s is not on any key" symbol)))))
642           (when string
643             (unless (eq symbol definition)
644               (setq return-string (concat return-string ";\n its alias "))) ;
645             (setq return-string (concat return-string string)))))
646       return-string)))
647 ;;;; END CORE
648
649 ;;;; BEGIN DOCUMENTATION
650 (defconst screencast-screencast-text-producer
651   '(
652     "Hello, this is the screencast for creating your own
653     screencasts."  n
654     "If you create a list (first argument) of strings, each
655     string will be typed to the message buffer (this buffer), at
656     a human-readable pace."  n
657     "If you put a 'p in the list, a pause will be inserted. "  p
658     p p p p "See?" p p
659     l
660     "(The above line was inserted instantly with the symbol 'l)"
661     n
662     "(Blank lines can be inserted using the 'n symbol, newlines
663     in strings are removed)" n n n
664     "All of the above is combined in the symbol 'b, which creates
665     a break in the screencast. This could be used between two
666     different sections for instance."  b
667     "You can also put functions in the list, these will be
668     evaluated in the command-buffer (second argument)."  n
669     "The function is written as a list, with the function name
670     first, and the arguments after that, e.g. '(backward-char
671     2)."  n n p
672     "Each time a function is evaluated, a message is displayed in
673     the message buffer, using the where-is function."  n
674     "In addition to this a step-number is displayed, this
675     step-number corresponds to the functions position in the
676     list."  n
677     "Let's try out some functions:" n
678     "((insert \"THIS IS AN INSERTION\n\") will be evaluated)" p
679     (insert "THIS IS AN INSERTION\n")
680     "You can call the special function `screencast-producer-insert-with-delay', aliased to `i' to insert with delay in the command-buffer."n
681     (i
682      "this is also an insertion, but it is done at typing speed")
683     "Hmm.." p p "let's delete the line we just typed in the
684     command buffer [[(kill-whole-line 1)]]"
685     (kill-whole-line 1)
686     "Notice the keybindings which are displayed."  b
687     "The fourth (optional) argument given to the screencast
688     function is the step-number to start using pauses, and output
689     to the message buffer at, e.g. it is a fast-forward. Which is
690     _very_ nice when producing a screencast."  n
691     "These step-numbers can also be printed separately in the
692     message-buffer using the 's symbol in the list."  n s n
693     "See?"  b
694     "Once you have finished a screencast and want it published,
695     you can record it as a video (.ogv) using
696     `screencast-record'."n
697     "As a part of the recording - the
698     font-size (`screencast-record-font') is changed, as well as
699     the fill-column variable (`screencast-record-fill-column')
700     for improved readability on a video."n
701     "As a consequence, you should _never_ use fill-paragraph and
702     the like, to get a nicely formatted source-file."n
703     "But the Emacs community will benefit the most if you publish
704     the screencast file itself - so please do!"n
705     "You can publish it at
706     http://www.emacswiki.org/emacs/ScreencastSources" b
707     "This screencast should cover the basic options for creating
708     a screencast, and can be seen in the constant
709     `screencast-screencast-text-producer'."n
710     "A screencast covering the more advanced functions of
711     screencast is available in the function
712     `screencast-screencast-producer-advanced'."  b
713     "Happy screencasting!"  )
714   "The text the screencast-screencast-producer is based upon")
715
716 (defconst screencast-screencast-text-user '(
717                                             "Hello, welcome to the screencast for viewing screencasts in
718     screencast mode."n
719     "Screencasts are like movies, they type some explanatory
720     text (like this), and executes functions in order to show you
721     the capabilities of different tools in Emacs."n
722     "Once a screencast has finished, you can move the cursor to
723     an executed function and press RET or MOUSE-1 to review the
724     screencast from that step."n
725     "Alternatively you can use the numeric prefix argument to
726     pinpoint the step to begin at."n
727     "If no prefix argument is given, and point isn't at an
728     executed function, the screencast is restarted from the first
729     step."  ))
730
731 (defconst screencast-screencast-text-producer-advanced 
732   '(
733     "This screencast covers the advanced functions of screencast-mode."n
734     "Please read the documentation for the functions as well."n
735     "Regarding the functions and variables in this file:"n
736     "You, as a producer, are supposed to be using the functions starting with `screencast-producer-' (and `screencast' itself ofcourse), they are tailored for ease of use. The others are for internal use - and there's no guarantee they are stable throughout versions."
737     b
738     "It is possible to use multiple command-buffers:"
739     (screencast-producer-new-buffer 
740      '((i "I'm a new command-buffer"))
741      "new-command-buffer")
742     (progn (kill-buffer "new-command-buffer"))
743     "It is done via the function `screencast-producer-new-buffer' which takes a list and a buffer - almost like the screencast function itself. "
744     b
745     "If you don't want to document everything you do, for instance moving the cursor, you can put the functions you want to \"hide\" inside a `progn'."
746     b
747     "If you need temporary variables or functions (for instance when you need to override a function which uses the mini-buffer), you can just put in a `let' or `flet'"
748     b
749     "If you need to modify the last-command-char (for self-insert-commands) or the last-command (for continued killing) there's also support for that:"n
750     "Use `screencast-producer-set-last-char'  or `screencast-producer-set-last-command'"
751     "The text the screencast-screencast-producer-advanced is based upon"))
752
753 (defun screencast-screencast-producer-advanced(&optional arg)
754   "Displays the screencast for creating advanced screencasts."
755   (interactive "P")
756   (apply (if arg
757              'screencast-record
758            'screencast)
759          screencast-screencast-text-producer-advanced "screencast-screencast-producer" 1.1 ()))
760
761 (defun screencast-screencast-producer(&optional arg)
762   "Displays the screencast for creating screencasts."
763   (interactive "P")
764   (apply (if arg
765              'screencast-record
766            'screencast)
767          screencast-screencast-text-producer "screencast-screencast-producer" 1 ()))
768
769 (defun screencast-screencast-user(&optional arg)
770   "Displays the screencast for using screencasts."
771   (interactive "P")
772   (apply (if arg
773              'screencast-record
774            'screencast)
775          screencast-screencast-text-user "screencast-screencast-user" 1 ()))
776 ;;;; END DOCUMENTATION
777 (provide 'screencast)
778