Last active
May 17, 2021 13:59
-
-
Save kcsongor/31255f8ae07dc04db1eb1944daece7a4 to your computer and use it in GitHub Desktop.
presenter.el
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defgroup presenter nil | |
"Present source code in emacs.") | |
(defface presenter-slide-marker-face | |
'((t)) | |
"Highlight slide marker." | |
:group 'presenter) | |
(set-face-attribute 'presenter-slide-marker-face nil :height 1.0 :inherit 'font-lock-warning-face) | |
(defface presenter-header-1 | |
'((t)) | |
"Highlight header 1" | |
:group 'presenter) | |
(set-face-attribute 'presenter-header-1 nil :inherit 'default :foreground 'unspecified :height 2.0) | |
(defface presenter-header-2 | |
'((t)) | |
"Highlight header 2" | |
:group 'presenter) | |
(set-face-attribute 'presenter-header-2 nil :inherit 'default :foreground 'unspecified :height 1.5) | |
(defface presenter-header-3 | |
'((t)) | |
"Highlight header 3" | |
:group 'presenter) | |
(set-face-attribute 'presenter-header-3 nil :inherit 'default :foreground 'unspecified :height 1.1) | |
(defvar-local presenter/current-slide 0) | |
(defvar-local presenter/slides nil) | |
(defvar presenter--invisibility-spec nil) | |
(defvar-local presenter/tag-regexp "{- \\(FACE\\|ENDFACE\\|START\\|END\\) [^}]+}") | |
(defun presenter/hide-tags () | |
(interactive) | |
(presenter--overlay-tags) | |
(add-to-invisibility-spec 'presenter--invisibility-spec)) | |
(defun presenter/show-tags () | |
(interactive) | |
(remove-overlays) | |
(remove-from-invisibility-spec 'presenter--invisibility-spec)) | |
(defun presenter--overlay-tags () | |
(save-excursion | |
(goto-char (point-min)) | |
(while (re-search-forward presenter/tag-regexp nil t) | |
(overlay-put (make-overlay (match-beginning 0) (match-end 0)) | |
'invisible 'presenter--invisibility-spec)) | |
(goto-char (point-min)) | |
(while (re-search-forward "^-- [*][*]?[*]? " nil t) | |
(overlay-put (make-overlay (match-beginning 0) (match-end 0)) | |
'invisible 'presenter--invisibility-spec)))) | |
(defun presenter/make-start-tag (name) | |
"Make start tag of NAME." | |
(concat "{- START " name " -}")) | |
(defun presenter/make-end-tag (name) | |
"Make end tag of NAME." | |
(concat "{- END " name " -}")) | |
(defun presenter--line-selection-p () | |
(when (boundp 'evil-visual-selection) | |
(eq evil-visual-selection 'line))) | |
(defun presenter/define-slide (start end name) | |
"Define a new slide with NAME starting at START, ending at END." | |
(interactive "r\nsSlide name: ") | |
(save-excursion | |
(let ((start-tag (presenter/make-start-tag name)) | |
(end-tag (presenter/make-end-tag name))) | |
(cond | |
((presenter--line-selection-p) | |
(goto-char start) | |
(newline) | |
(previous-line) | |
(insert start-tag) | |
(goto-char (+ 1 end (length start-tag))) | |
(newline) | |
(previous-line) | |
(insert end-tag)) | |
(t | |
(goto-char start) | |
(insert start-tag) | |
(goto-char (+ end (length start-tag))) | |
(insert end-tag)))) | |
(add-to-list 'presenter/slides name t) | |
(add-file-local-variable 'presenter/slides presenter/slides))) | |
(defun presenter/find-slide (slide) | |
"Find SLIDE and narrow to it." | |
(interactive (list (completing-read "Slide> " presenter/slides))) | |
"Find SLIDE." | |
(widen) | |
(goto-char (point-min)) | |
(re-search-forward (presenter/make-start-tag slide) nil t) | |
(let ((start (match-end 0))) | |
(re-search-forward (presenter/make-end-tag slide) nil t) | |
(let ((end (match-beginning 0))) | |
(narrow-to-region start end) | |
(beginning-of-buffer)))) | |
(defun presenter/go-slide () | |
"Go to current slide." | |
(interactive) | |
;; (set-face-attribute 'talk-marker nil :height 1.0 :foreground "#1D1F21") | |
(let ((current (nth presenter/current-slide presenter/slides))) | |
(cond ((stringp current) | |
(presenter/find-slide (nth presenter/current-slide presenter/slides)))))) | |
(defun presenter/next () | |
"Go to next slide." | |
(interactive) | |
(presentation--set-next-slide) | |
(presenter/go-slide)) | |
(defun presenter/previous () | |
"Go to previous slide." | |
(interactive) | |
(presentation--set-previous-slide) | |
(presenter/go-slide)) | |
(defun presentation--set-next-slide () | |
"Set current-slide to the next slide (handles wraparound)." | |
(setq presenter/current-slide (min (- (length presenter/slides) 1) (+ presenter/current-slide 1)))) | |
(defun presentation--set-previous-slide () | |
"Set current-slide to the previous slide (handles wraparound)." | |
(setq presenter/current-slide (max 0 (- presenter/current-slide 1)))) | |
(define-minor-mode presentation-mode | |
"Give a presentation." | |
:keymap | |
'(([left] . presenter/previous) | |
([right] . presenter/next))) | |
(defun presentation-mode-enter () | |
(setq presenter/current-slide 0) | |
(hi-lock-mode 1) | |
(presenter/hide-tags) | |
(presenter/go-slide) | |
) | |
(defun presentation-mode-exit () | |
(presenter/show-tags) | |
(widen)) | |
(add-hook 'presentation-mode-hook | |
(lambda () | |
(if presentation-mode (presentation-mode-enter) | |
(presentation-mode-exit)))) | |
(provide 'presenter) | |
;;; presenter.el ends here |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment