diff options
Diffstat (limited to '')
| -rw-r--r-- | .emacs.d/init.el | 15 | ||||
| -rw-r--r-- | .emacs.d/lisp/ffs/ChangeLog | 28 | ||||
| -rw-r--r-- | .emacs.d/lisp/ffs/ffs.el | 419 | ||||
| -rw-r--r-- | .emacs.d/lisp/ffs/ffsanim.el | 267 | 
4 files changed, 729 insertions, 0 deletions
| diff --git a/.emacs.d/init.el b/.emacs.d/init.el index ce05ab4..11e4fb2 100644 --- a/.emacs.d/init.el +++ b/.emacs.d/init.el @@ -954,6 +954,21 @@ Effectively a very simple light/dark theme toggle switch."  (with-eval-after-load 'emms    (setq emms-directory (b/var "emms"))) +(add-to-list 'load-path (b/lisp "ffs")) +(run-with-idle-timer 0.5 nil #'require 'ffs) +(with-eval-after-load 'ffs +  (global-set-key (kbd "C-c f s") #'ffs)) + +(defun b/export-frame () +  (interactive) +  ;; TODO: ask for fn and/or take as arg +  (let* ((fn (make-temp-file "emacs" nil ".pdf")) +         (data (x-export-frames nil 'pdf))) +    (with-temp-file fn +      (insert data)) +    (kill-new fn) +    (message fn))) +  ;;; Post initialization diff --git a/.emacs.d/lisp/ffs/ChangeLog b/.emacs.d/lisp/ffs/ChangeLog new file mode 100644 index 0000000..41d87ca --- /dev/null +++ b/.emacs.d/lisp/ffs/ChangeLog @@ -0,0 +1,28 @@ +2022-03-09  Amin Bandali  <bandali@gnu.org> + +	* ffsanim.el: Rename from ffs.el to ffsanim.el.  Revision 0.1.5. + +2022-03-06  Amin Bandali  <bandali@gnu.org> + +	* ffs.el (ffs-new-slide): Merge function into `ffs-edit-slide'. +	Revision 0.1.4. + +2022-03-05  Amin Bandali  <bandali@gnu.org> + +	* ffs.el: Implement insertion of new slide before or after the +	current slide.  Revision 0.1.3. + +2022-03-05  Amin Bandali  <bandali@gnu.org> + +	* ffs.el (ffs-edit-mode): Change to a minor mode, and use the +	source buffer's `major-mode' for the edit buffer.  Revision 0.1.2. + +2022-03-05  Amin Bandali  <bandali@gnu.org> + +	* ffs.el: Add `ffs-edit-mode' (derived from `text-mode') for the +	new ffs-edit buffer for editing slides.  Revision 0.1.1. + +2022-03-04  Amin Bandali  <bandali@gnu.org> + +	* ffs.el: Initial revision 0.1.0. + diff --git a/.emacs.d/lisp/ffs/ffs.el b/.emacs.d/lisp/ffs/ffs.el new file mode 100644 index 0000000..99f2097 --- /dev/null +++ b/.emacs.d/lisp/ffs/ffs.el @@ -0,0 +1,419 @@ +;;; ffs.el --- Form Feed Slides mode       -*- lexical-binding: t; -*- + +;; Copyright (C) 2022  Amin Bandali <bandali@gnu.org> + +;; Author: Amin Bandali <bandali@gnu.org> +;; Version: 0.1.0 +;; Keywords: outlines, tools + +;; This program 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. + +;; This program 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 this program.  If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; A simple mode for doing simple plain text presentations where the +;; slides are separated using the form feed character (). + +;; Configuration: TODO + +;; Usage: + +;; Put this file, ffs.el, in a directory in your `load-path', then add +;; something like the following to your init file: +;; +;; (require 'ffs) +;; (global-set-key (kbd "C-c f s") #'ffs) + +;; Then, open a text file/buffer that you would like you to use as the +;; source of your presentation and type `M-x ffs RET' or a keyboard +;; shortcut you defined (like the above example) to start ffs, at +;; which point you should be able to see "ffs" appear as one of the +;; currently enabled minor modes in your mode-line.  Once ffs is +;; enabled, you can invoke its various commands.  To see a list of +;; available commands, you can either type `M-x ffs- TAB' (to get a +;; completion of commands starting with the "ffs-" prefix), or see the +;; definition of `ffs-minor-mode-map' near the end of this file. + +;;; Code: + +(defgroup ffs nil +  "Minor mode for form feed-separated plain text presentations." +  :version "29.1" +  :prefix "ffs-") + +(defcustom ffs-default-face-height 370 +  "The value of the `height' property for the `default' face to use +during the ffs presentation." +  :group 'ffs +  :type '(choice (const nil) +                 (integer :value 300))) + +(defcustom ffs-edit-buffer-name "*ffs-edit*" +  "The name of the ffs-edit buffer used when editing a slide." +  :group 'ffs +  :type 'string) + +(defvar ffs--slides-buffer nil +  "The main ffs presentation slides buffer. +When the user enables ffs in a buffer using `\\[ffs]', we store a +reference to that buffer in this variable. + +As a special case, in a speaker notes buffer selected by the user +using `\\[ffs-find-speaker-notes-file]' from the main ffs slides +buffer, this variable will point to the main ffs slides buffer +rather than the speaker notes buffer.") + +(defvar ffs--notes-buffer nil +  "The ffs speaker notes buffer (only if selected). +When the user chooses (and opens) a speaker notes file using +`\\[ffs-find-speaker-notes-file]', a reference to the file's +corresponding buffer is stored in this variable, local to the +main ffs presentation slides buffer (`ffs--slides-buffer').") + +(defvar ffs--old-mode-line-format nil +  "The old value of `mode-line-format' before enabling +`ffs--no-mode-line-minor-mode'.") + +(defvar ffs--old-cursor-type nil +  "The old value of `cursor-type' before enabling +`ffs--no-cursor-minor-mode'.") + +(defvar ffs--old-default-face-height nil +  "The old value of the `default' face's `height' property before +starting the ffs presentation.") + +(define-minor-mode ffs--no-mode-line-minor-mode +  "Minor mode for hiding the mode-line." +  :lighter nil +  (if ffs--no-mode-line-minor-mode +      (progn +        (unless ffs--old-mode-line-format +          (setq-local ffs--old-mode-line-format mode-line-format)) +        (setq-local mode-line-format nil)) +    (setq-local mode-line-format ffs--old-mode-line-format) +    (when ffs--old-mode-line-format +      ffs--old-mode-line-format nil)) +  (redraw-display)) + +(define-minor-mode ffs--no-cursor-minor-mode +  "Minor mode for hiding the cursor." +  :lighter nil +  (if ffs--no-cursor-minor-mode +      (progn +        (unless ffs--old-cursor-type +          (setq-local ffs--old-cursor-type cursor-type)) +        (setq-local cursor-type nil)) +    (setq-local cursor-type ffs--old-cursor-type) +    (when ffs--old-cursor-type +      ffs--old-cursor-type nil))) + +(defun ffs--toggle-dark-mode () +  "Swap the frame background and foreground colours." +  (interactive) +  (let ((bg (frame-parameter nil 'background-color)) +        (fg (frame-parameter nil 'foreground-color))) +    (set-background-color fg) +    (set-foreground-color bg))) + +(defun ffs--goto-previous (buffer) +  "Go to the previous slide in the given BUFFER." +  (interactive) +  (with-current-buffer buffer +    (let ((n (buffer-narrowed-p))) +      (when n +        (goto-char (point-min)) +        (widen) +        (backward-page)) +      (backward-page) +      (when n (narrow-to-page))))) + +(defun ffs-goto-previous () +  "Go to the previous slide in the main ffs presentation and the +speaker notes buffer (if any)." +  (interactive) +  (ffs--goto-previous ffs--slides-buffer) +  (when ffs--notes-buffer +    (ffs--goto-previous ffs--notes-buffer) +    (redraw-display))) + +(defun ffs--goto-next (buffer) +  "Go to the next slide in the given BUFFER." +  (interactive) +  (with-current-buffer buffer +    (let ((n (buffer-narrowed-p)) +          (e (= (- (point-max) (point-min)) 0))) +      (when n +        (goto-char (point-min)) +        (widen)) +      (unless e (forward-page)) +      (when n (narrow-to-page))))) + +(defun ffs-goto-next () +  "Go to the next slide in the main ffs presentation and the +speaker notes buffer (if any)." +  (interactive) +  (ffs--goto-next ffs--slides-buffer) +  (when ffs--notes-buffer +    (ffs--goto-next ffs--notes-buffer) +    (redraw-display))) + +(defun ffs--goto-first (buffer) +  "Go to the first slide in the given BUFFER." +  (interactive) +  (with-current-buffer buffer +    (let ((n (buffer-narrowed-p))) +      (when n (widen)) +      (goto-char (point-min)) +      (when n (narrow-to-page))))) + +(defun ffs-goto-first () +  "Go to the first slide in the main ffs presentation and the +speaker notes buffer (if any)." +  (interactive) +  (ffs--goto-first ffs--slides-buffer) +  (when ffs--notes-buffer +    (ffs--goto-first ffs--notes-buffer) +    (redraw-display))) + +(defun ffs--goto-last (buffer) +  "Go to the last slide in the given BUFFER." +  (interactive) +  (let ((n (buffer-narrowed-p))) +    (when n (widen)) +    (goto-char (point-max)) +    (when n (narrow-to-page)))) + +(defun ffs-goto-last () +  "Go to the last slide in the main ffs presentation and the +speaker notes buffer (if any)." +  (interactive) +  (ffs--goto-last ffs--slides-buffer) +  (when ffs--notes-buffer +    (ffs--goto-last ffs--notes-buffer) +    (redraw-display))) + +(defun ffs-start () +  "Start the presentation." +  (interactive) +  (ffs-minor-mode 1) +  (ffs--no-mode-line-minor-mode 1) +  (ffs--no-cursor-minor-mode 1) +  (when (integerp ffs-default-face-height) +    (setq-local +     ffs--old-default-face-height +     (face-attribute 'default :height)) +    (face-remap-add-relative +     'default :height ffs-default-face-height)) +  (show-paren-local-mode -1) +  (display-battery-mode -1) +  (flyspell-mode -1) +  (narrow-to-page)) + +(defun ffs-quit () +  "Quit the presentation." +  (interactive) +  (let ((n (buffer-narrowed-p)) +        (e (= (- (point-max) (point-min)) 0))) +    (when (integerp ffs-default-face-height) +      (face-remap-add-relative +       'default :height ffs--old-default-face-height)) +    (show-paren-local-mode 1) +    (display-battery-mode 1) +    (flyspell-mode 1) +    (ffs--no-mode-line-minor-mode -1) +    (ffs--no-cursor-minor-mode -1) +    (if n +        (progn +          (goto-char (point-min)) +          (widen)) +      (ffs-minor-mode -1)) +    (when e (forward-char -1)))) + +(defun ffs-edit (&optional add-above-or-below) +  "Pop to a new buffer to edit a slide. +If ADD-ABOVE-OR-BELOW is nil or not given, we are editing an +existing slide.  Otherwise, if it is `add-above' then the new +slide will be added above/before the current slide, and if it is +`add-below' then the new slide will be added below/after the +current slide.  The logic is implemented in `ffs-edit-done'." +  (interactive) +  (let* ((b (current-buffer)) +         (m major-mode) +         (n (buffer-narrowed-p)) +         (s (if add-above-or-below      ; if we are adding a new slide +                "\n"                    ; start with just a newline +              (unless n (narrow-to-page)) +              (prog1 (buffer-string) +                (unless n (widen)))))) +    (pop-to-buffer-same-window +     (get-buffer-create ffs-edit-buffer-name)) +    (funcall m) +    (ffs-edit-minor-mode 1) +    (insert s) +    (goto-char (point-min)) +    (set-buffer-modified-p nil) +    (setq-local +     ffs--edit-source-buffer b +     ffs--new-location add-above-or-below) +    (message +     (substitute-command-keys "Edit, then use `\\[ffs-edit-done]' \ +to apply your changes or `\\[ffs-edit-discard]' to discard them.")))) + +(defun ffs-new-above () +  "Add a new slide above/before the current slide." +  (interactive) +  (ffs-edit 'add-above)) + +(defun ffs-new-below () +  "Add a new slide below/after the current slide." +  (interactive) +  (ffs-edit 'add-below)) + +(defun ffs-edit-discard () +  "Discard current ffs-edit buffer and return to the presentation." +  (interactive) +  (let ((b (current-buffer))) +    (quit-windows-on b) +    (kill-buffer b))) + +(defun ffs-edit-done () +  "Apply the ffs-edit changes and return to the presentation." +  (interactive) +  (let* (f +         (str (buffer-string)) +         (s (if (string-suffix-p "\n" str) +                str +              (concat str "\n"))) +         (l ffs--new-location)) +    (with-current-buffer ffs--edit-source-buffer +      (let ((inhibit-read-only t)) +        (save-excursion +          (cond +           ((eq l 'add-above) +            (backward-page) +            (insert (format "\n%s" s)) +            (setq f #'ffs-previous-slide)) +           ((eq l 'add-below) +            (forward-page) +            (insert (format "\n%s" s)) +            (setq f #'ffs-next-slide)) +           ((null l) +            (narrow-to-page) +            (delete-region (point-min) (point-max)) +            (insert s) +            (widen)))))) +    (ffs-edit-discard) +    (when (functionp f) +      (funcall f)))) + +(defun ffs--undo (&optional arg) +  "Like `undo', but it works even when the buffer is read-only." +  (interactive "P") +  (let ((inhibit-read-only t)) +    (undo arg))) + +(defun ffs-find-speaker-notes-file (file) +  "Prompt user for a speaker notes file, open it in a new frame." +  (interactive "Fspeakers notes buffer: ") +  (let ((b (current-buffer))) +    (save-excursion +      (find-file-other-frame file) +      (ffs-minor-mode 1) +      (setq-local +       ffs--slides-buffer b +       ffs--notes-buffer (current-buffer))) +    (setq-local ffs--notes-buffer (get-file-buffer file)))) + +(defun ffs-export-slides-to-pdf () +  (interactive) +  (with-current-buffer ffs--slides-buffer +    (ffs-goto-first) +    (let ((c 1) +          (fringe fringe-mode)) +      (fringe-mode 0) +      (while (not (eobp)) +        (let ((fn (format "%s-%03d.pdf" +                          (file-name-sans-extension (buffer-name)) +                          c)) +              (data (x-export-frames nil 'pdf))) +          (with-temp-file fn +            (insert data))) +        (setq c (+ c 1)) +        (ffs-goto-next)) +      (fringe-mode fringe)))) + +(defvar ffs-edit-minor-mode-map +  (let ((map (make-sparse-keymap))) +    (define-key map (kbd "C-c C-k") #'ffs-edit-discard) +    (define-key map (kbd "C-c C-c") #'ffs-edit-done) +    map) +  "Keymap for `ffs-edit-minor-mode'.") + +(define-minor-mode ffs-edit-minor-mode +  "Minor mode for editing a single ffs slide. +When done editing the slide, run \\[ffs-edit-done] to apply your +changes, or \\[ffs-edit-discard] to discard them." +  :group 'ffs +  :lighter " ffs-edit" +  :keymap ffs-edit-minor-mode-map +  (defvar-local ffs--edit-source-buffer nil +    "The ffs presentation buffer of the slide being edited.") +  (defvar-local ffs--new-location nil +    "The location where the new slide should be inserted. +See the docstring for `ffs-edit' for more details.")) + +(defvar ffs-minor-mode-map +  (let ((map (make-sparse-keymap))) +    (define-key map (kbd "p") #'ffs-goto-previous) +    (define-key map (kbd "n") #'ffs-goto-next) +    (define-key map (kbd "DEL") #'ffs-goto-previous) +    (define-key map (kbd "SPC") #'ffs-goto-next) +    (define-key map (kbd "[") #'ffs-goto-previous) +    (define-key map (kbd "]") #'ffs-goto-next) +    (define-key map (kbd "<") #'ffs-goto-first) +    (define-key map (kbd ">") #'ffs-goto-last) +    (define-key map (kbd "s") #'ffs-start) +    (define-key map (kbd "q") #'ffs-quit) +    (define-key map (kbd "e") #'ffs-edit) +    (define-key map (kbd "O") #'ffs-new-above) +    (define-key map (kbd "o") #'ffs-new-below) +    (define-key map (kbd "m") #'ffs--no-mode-line-minor-mode) +    (define-key map (kbd "c") #'ffs--no-cursor-minor-mode) +    (define-key map (kbd "d") #'ffs--toggle-dark-mode) +    (define-key map (kbd "N") #'narrow-to-page) +    (define-key map (kbd "W") #'widen) +    (define-key map [remap undo] #'ffs--undo) +    (define-key map (kbd "C-c n") #'ffs-find-speaker-notes-file) +    map) +  "Keymap for `ffs-minor-mode'.") + +(define-minor-mode ffs-minor-mode +  "Minor mode for form feed-separated plain text presentations." +  :group 'ffs +  :lighter " ffs" +  :keymap ffs-minor-mode-map +  (setq-local +   ffs--old-mode-line-format mode-line-format +   ffs--old-cursor-type cursor-type +   ffs--old-default-face-height +   (face-attribute 'default :height)) +  (setq buffer-read-only ffs-minor-mode)) + +(defun ffs () +  "Enable `ffs-minor-mode' for presenting the current buffer." +  (interactive) +  (ffs-minor-mode 1) +  (setq-local ffs--slides-buffer (current-buffer))) + +(provide 'ffs) +;;; ffs.el ends here diff --git a/.emacs.d/lisp/ffs/ffsanim.el b/.emacs.d/lisp/ffs/ffsanim.el new file mode 100644 index 0000000..cbf2969 --- /dev/null +++ b/.emacs.d/lisp/ffs/ffsanim.el @@ -0,0 +1,267 @@ +;;; ffsanim.el --- Form Feed Slides animate -*- lexical-binding: t; -*- + +;; Copyright (C) 2022  Amin Bandali <bandali@gnu.org> + +;; Author: Amin Bandali <bandali@gnu.org> +;; Version: 0.1.5 +;; Keywords: outlines, tools + +;; This program 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. + +;; This program 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 this program.  If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; A simple mode for doing simple plain text presentations where the +;; slides are separated using the form feed character ().  Uses +;; animate.el to animate each slide. + +;; Configuration: TODO + +;; Usage: + +;; (add-to-list 'load-path (b/lisp "ffs")) +;; (run-with-idle-timer 0.5 nil #'require 'ffsanim) +;; (with-eval-after-load 'ffsanim +;;   (defvar b/original-default-height) +;;   (defvar b/ffsanim-default-height 300) +;;   (global-set-key +;;    (kbd "C-c f s") +;;    (lambda () +;;      (interactive) +;;      (setq +;;       b/original-default-height (face-attribute 'default :height)) +;;      (set-face-attribute +;;       'default nil :height b/ffsanim-default-height) +;;      (message " ") +;;      (ffsanim))) +;;   (define-key +;;    ffsanim-mode-map (kbd "q") +;;    (lambda () +;;      (interactive) +;;      (quit-window) +;;      (set-face-attribute +;;       'default nil :height b/original-default-height) +;;      (message " ")))) + +;;; Code: + +(require 'animate) + +(defgroup ffsanim nil +  "Major mode for form feed-separated plain text presentations." +  :version "29.1" +  :prefix "ffsanim-") + +(defcustom ffsanim-buffer-name "*ffsanim*" +  "The name of the ffsanim presentation buffer." +  :group 'ffsanim +  :type 'string) + +(defcustom ffsanim-edit-buffer-name "*ffsanim-edit*" +  "The name of the ffsanim-edit buffer used when editing a slide." +  :group 'ffsanim +  :type 'string) + +(defvar ffsanim--source-buffer-name "" +  "The name of the form feed-separated \"source\" buffer for a +presentation.") + +(defun ffsanim--buffer () +  "Get the ffsanim presentation buffer." +  (get-buffer-create ffsanim-buffer-name)) + +(defmacro ffsanim-define-move-to-slide (name &optional doc &rest body) +  "Define a function for moving to a slide. +Symbol NAME is the name describing the movement. +DOC is the documentation string to use for the function." +  (declare (debug (&define name [&optional stringp] def-body)) +           (doc-string 2) (indent defun)) +  (when (and doc (not (stringp doc))) +    ;; `doc' is the first element of `body', not an actual docstring +    (push doc body) +    (setq doc nil)) +  (let* ((sn (symbol-name name)) +         (fname (intern (format "ffsanim-%s-slide" (downcase sn))))) +    `(defun ,fname () +       ,doc +       (interactive) +       (let ((s (progn +                  (pop-to-buffer-same-window +                   (get-buffer ffsanim--source-buffer-name)) +                  ,@body +                  (narrow-to-page) +                  (prog1 (buffer-string) +                    (widen) +                    (pop-to-buffer-same-window (ffsanim--buffer))))) +             (animation-buffer-name (buffer-name (ffsanim--buffer))) +             (inhibit-read-only t)) +         (animate-sequence (split-string s "\n") 0))))) + +(defun ffsanim-edit-slide (&optional add-before-or-after) +  "Pop to a new buffer to edit a slide. +If ADD-BEFORE-OR-AFTER is nil or not given, we are editing an +existing slide.  Otherwise, if it is `add-before' then the new +slide will be added before the current slide, and if it is +`add-after' then the new slide will be added after the current +slide.  The logic for handling this is in `ffsanim-edit-done'." +  (interactive) +  (let* (m +         (s (with-current-buffer (get-buffer ffsanim--source-buffer-name) +              (setq m major-mode) +              (if add-before-or-after   ; if we are adding a new slide +                  "\n"                  ; start with just a newline +                (narrow-to-page) +                (prog1 (buffer-string) +                  (widen)))))) +    (pop-to-buffer-same-window +     (get-buffer-create ffsanim-edit-buffer-name)) +    (funcall m) +    (ffsanim-edit-mode 1) +    (insert s) +    (goto-char (point-min)) +    (setq-local ffsanim--new-location add-before-or-after) +    (message +     (substitute-command-keys "Edit, then use `\\[ffsanim-edit-done]' \ +to apply your changes or `\\[ffsanim-edit-discard]' to discard them.")))) + +(defun ffsanim-edit-discard () +  "Discard current ffsanim-edit buffer and return to the presentation." +  (interactive) +  (let ((buf (current-buffer))) +    (quit-windows-on buf) +    (kill-buffer buf)) +  (pop-to-buffer-same-window (ffsanim--buffer))) + +(defun ffsanim-edit-done () +  "Apply the ffsanim-edit changes and return to the presentation." +  (interactive) +  (let* (f +         (str (buffer-string)) +         (s (if (string-suffix-p "\n" str) +                str +              (concat str "\n"))) +         (l ffsanim--new-location)) +    (with-current-buffer (get-buffer ffsanim--source-buffer-name) +      (save-excursion +        (cond +         ((eq l 'add-before) +          (backward-page) +          (insert (format "\n%s" s)) +          (setq f #'ffsanim-previous-slide)) +         ((eq l 'add-after) +          (forward-page) +          (insert (format "\n%s" s)) +          (setq f #'ffsanim-next-slide)) +         ((null l) +          (narrow-to-page) +          (delete-region (point-min) (point-max)) +          (insert s) +          (widen) +          (setq f #'ffsanim-current-slide))))) +    (ffsanim-edit-discard) +    (funcall f))) + +(defun ffsanim-new-slide-before () +  "Add a new slide before the current slide." +  (interactive) +  (ffsanim-edit-slide 'add-before)) + +(defun ffsanim-new-slide-after () +  "Add a new slide after the current slide." +  (interactive) +  (ffsanim-edit-slide 'add-after)) + +(defvar ffsanim--old-mode-line-format nil +  "The value of `mode-line-format' in the ffsanim presentation buffer +before the last call to `ffsanim--toggle-mode-line'.") + +(defun ffsanim--toggle-mode-line () +  "Toggle the display of the mode-line in the current buffer." +  (interactive) +  (if mode-line-format +      (setq-local ffsanim--old-mode-line-format mode-line-format +                  mode-line-format nil) +    (setq-local mode-line-format ffsanim--old-mode-line-format +                ffsanim--old-mode-line-format nil)) +  (redraw-display)) + +(ffsanim-define-move-to-slide previous +  "Go to the previous slide." +  (backward-page) +  (backward-page)) + +(ffsanim-define-move-to-slide next +  "Go to the next slide." +  (forward-page)) + +(ffsanim-define-move-to-slide current +  "Reload and renimate the current slide." +  nil) + +(ffsanim-define-move-to-slide first +  "Go to the first slide." +  (goto-char (point-min))) + +(ffsanim-define-move-to-slide last +  "Go to the last slide." +  (goto-char (point-max))) + +(define-derived-mode ffsanim-mode special-mode "ffsanim" +  "Major mode for form feed-separated plain text presentations." +  :group 'ffsanim +  :interative nil +  (setq-local animate-total-added-delay 0.3) +  (show-paren-local-mode -1) +  (display-battery-mode -1) +  (ffsanim--toggle-mode-line) +  (ffsanim-current-slide)) + +(defvar ffsanim-edit-mode-map +  (let ((map (make-sparse-keymap))) +    (define-key map (kbd "C-c C-k") #'ffsanim-edit-discard) +    (define-key map (kbd "C-c C-c") #'ffsanim-edit-done) +    map) +  "Keymap for `ffsanim-edit-mode'.") + +(define-minor-mode ffsanim-edit-mode +  "Minor mode for editing a single ffsanim slide. +When done editing the slide, run \\[ffsanim-edit-done] to apply your +changes, or \\[ffsanim-edit-discard] to discard them." +  :group 'ffsanim +  :lighter " ffsanim-edit" +  :keymap ffsanim-edit-mode-map +  (defvar-local ffsanim--new-location nil +    "The location where the new slide should be inserted. +See the docstring for `ffsanim-edit-slide' for more details.")) + +(define-key ffsanim-mode-map (kbd "p") #'ffsanim-previous-slide) +(define-key ffsanim-mode-map (kbd "n") #'ffsanim-next-slide) +(define-key ffsanim-mode-map (kbd "DEL") #'ffsanim-previous-slide) +(define-key ffsanim-mode-map (kbd "SPC") #'ffsanim-next-slide) +(define-key ffsanim-mode-map (kbd "g") #'ffsanim-current-slide) +(define-key ffsanim-mode-map (kbd "<") #'ffsanim-first-slide) +(define-key ffsanim-mode-map (kbd ">") #'ffsanim-last-slide) +(define-key ffsanim-mode-map (kbd "e") #'ffsanim-edit-slide) +(define-key ffsanim-mode-map (kbd "O") #'ffsanim-new-slide-before) +(define-key ffsanim-mode-map (kbd "o") #'ffsanim-new-slide-after) +(define-key ffsanim-mode-map (kbd "m") #'ffsanim--toggle-mode-line) + +(defun ffsanim () +  "Start an ffsanim presentation with current buffer as source." +  (interactive) +  (setq ffsanim--source-buffer-name (buffer-name)) +  (pop-to-buffer-same-window (ffsanim--buffer)) +  (ffsanim-mode)) + +(provide 'ffsanim) +;;; ffsanim.el ends here | 
