; Given a groff lecture notes doc, turn it into a 32-pt lecture doc. ; This involves the following processing: ; (1) Change the header to be 32 pt, and define slide macros. ; (2) Do the clerical changing of groff commands, e.g., ".le" => ".lec" ; (3) Slidify a lecture, by figuring out where page breaks should go. ; (4) Provide an optional "animate" transform, that generates multiple ; pages per slide, with each successive page adding the next item. ; (5) Do some NLP to shorten phrases and sentences. ; ; As of 29mar11, only (2) is done. ; ; ; Some groff debugging stuff that may come in handy: ; .tm \n[L1] ; .tm \n[L\n[LL]] ; .nr L\n[LL] -1 ; .af L\n[LL] I ; .tm \n[L\n[LL]] ; ; ; 20jul11 Update: OK, it looks like the description under "Old Algorithm" below ; is pretty much a POS. There are a number of problems, the most significant ; of which is that on non-continuing slides, the numbered top line needs to be ; preceded with a decrement of the enumerator reg, so the number stays the same ; as the lines are added one by one. Have a look at the first couple slides in ; 101/lectures/slides/week1/all.me for a concrete example. ; ; I'm not exactly sure of the best approach to this problem. One possibility ; is to focus on .(L X ... .)L X bracketed lists, rather than individual ; slides. I'm not really sure that this will solve the problem with continuing ; vs non-continuing slides. For that, some specific logic is most likely ; needed, including perhaps a parameterized function that takes as ; "is-continuing" parm. One of the problems with the "Old Algorithm" may well ; be that I was trying to punk out and get something done in isolation, without ; having (all of) the necessary steps. ; ; What needs to happen is to go through a concrete lecture example and ; determine the different configurations for each slide, vis a vis slide ; animation. The above-cited 101 week 1 slides are a pretty good example, with ; a number of varying slide formats. A general solution strategy may go ; something like this: (1) clearly define each different configuration; (2) ; determine how to recognize a configuration from the content of a .bp-bounded ; slide; (3) write a slidifying function for each configuration, or one or more ; parameterized functions to do the slidification. ; ; Old Algorithm: ; ; Animate a slide, bounded by ".bp" commands. In terms of cursor starting ; position, "bounded by" means the slide to work on is determined as follows: ; ; * If the cursor is on the "." of a ".bp", then the identified slide ; extends from that .bp to the next .bp, or the end of the buffer if there ; is no following .bp. ; ; * If the cursor is not on the "." of a ".bp", then the identified slide is ; that which is bounded by the immediately preceding .bp, and the ; immediately following .bp, or end of buffer. ; ; Note that this requires a ".bp" in front of the first slide. This is ; reasonable given the typical structure of slide presentations, with the first ; .bp after title page, which typically won't need to be animated. If it does, ; we can stick an artificial .bp in front of it. We might require a .bp after ; the last slide, but this is a bit funky, since it will put a blank page at the ; end of the presentation. This actually may not be that bad, or even useful, ; since it will visually identify when we're done with a particular slide set. ; At this point, however, we have ".bp" or (eob) as legal end-of-slide ; delimiters. ; For the identified slide, start by adding a slide with just the header. Then ; generate additional slides by adding each ".lec" or ".eec" delimited item to ; successive slides, until the full slide is reached. ; (setq item-enumerator-re-search-string "^\\.lec\\|^\\.eec") (setq slide-delim-search-string "^\\.bp\\|^\\.lcont") (defun animate-slide() (interactive) ; Narrow the buffer to the slide bounded above and below by ".bps", with ; eob being OK as the end bound if we're on the last slide. (narrow-buf-to-slide) ; Stick the whole slide in s, and stay at the beginning of the buffer. (end-of-buffer) (setq e (point)) (beginning-of-buffer) (setq s (buffer-substring (point) e)) ; While there are still items in s, stick in a copy of s, minus its last ; item. (setq items-left t) (while items-left ; Since I don't know how to do functional re search, we'll just stick ; in a copy of the buffer to do the re search, and if it fails, nuke ; the buffer we just stuck in. (insert s) (backward-char 1) (narrow-buf-to-slide) (end-of-buffer) ; OK, we've stuck it in and we're sitting at the end. Do the search, ; and if we find an item, nuke it. If we find no item, nuke the whole ; itemless slide. (if (search-backward-regexp item-enumerator-re-search-string nil t) ; Find end of item by searching for first following groff command, ; and nuking the item (progn (setq bi (point)) (forward-char 1) (if (not (search-forward-regexp "^\\." nil t)) (end-of-buffer)) (beginning-of-line) (kill-region bi (point)) ) ; If no item, nuke the whole new slide buf, and set the loop guard to ; false. (progn (beginning-of-buffer) (setq b (point)) (end-of-buffer) (kill-region b (point)) (setq items-left nil) ) ) ; OK, we've nuked the last item, if there was one. If in fact there ; was one, then stick the contents of the current narrowed buffer ; into s, and we'll go round again in the loop. (end-of-buffer) (setq e (point)) (beginning-of-buffer) (setq s (buffer-substring (point) e)) ) ) ; Narrow the buffer to the region bounded by ".bp"s. If we're on ".bp" line, ; consider this line to be the beginning of the slide. Otherwise, the ; beginning of the slide is nearest preceding ".bp", or the beginning of buffer ; if there's no preceding ".bp". The end of the slide is the nearest following ; ".bp", or the end of buffer if there's no following ".bp". ; ; When the narrowing is done, the upper .bp is there, the ending .bp is not. ; ; Oh, and BTW, every place I've said ".bp" so far henceforth, I mean ``".bp" or ; ".lcont"'', which value is stored in slide-delim-search-string. (defun narrow-buf-to-slide () (interactive) ; Get the contents of the first three chars of the current line (beginning-of-line) (setq p (point)) (forward-char 3) (setq l (buffer-substring p (point))) ; Check if we're on a ".bp" line. (if (or (string= l ".bp") (string= l ".lc")) ; Set b to the beginning of the .bp line, then go to the end for a ; clean search for the ending .bp. (progn (setq b p) (end-of-line) ) ; If we're not on a ".bp" line, set b to the nearest preceding ".bp", ; or the beginning of the buffer if there's no preceding ".bp". Do the ; end-of-line clean search thing again, as necessary. (if (search-backward-regexp slide-delim-search-string nil t) (progn (setq b (point)) (end-of-line)) (setq b 0) ) ) ; Move to the next ".bp", or eob if none. (if (not (search-forward-regexp slide-delim-search-string nil t)) (end-of-buffer) (beginning-of-line) ) (narrow-to-region b (point)) ; Finish up at the beginning of the slide buffer, for good measure. (beginning-of-buffer) ) ; Assume buffer has been narrowed to a slide. Animate the chunk of items from ; point to eob. Do this by inserting the region from the top of the buffer to ; point, followed by the contents of the end-list var. At some point we could ; auto-gen the value of end-var by finding the begin-list groff command, but ; I've had enough of this hacking for now. ; ; To facilitate successive execution, move point to the next item enumerator, ; if any. (defun animate-following-items () (interactive) (setq p (point)) (beginning-of-buffer) (setq b (point)) (goto-char p) (insert (concat (buffer-substring b (point)))) (end-of-line) (search-forward-regexp item-enumerator-re-search-string nil t) (beginning-of-line) (insert (concat end-list "\n")) (beginning-of-line) )