Skip to content

Instantly share code, notes, and snippets.

@kcsongor
Last active May 17, 2021 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kcsongor/31255f8ae07dc04db1eb1944daece7a4 to your computer and use it in GitHub Desktop.
Save kcsongor/31255f8ae07dc04db1eb1944daece7a4 to your computer and use it in GitHub Desktop.
presenter.el
(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