At the end of each sprint, each of us demonstrate our accomplishments. These reviews often incorporate the following trifecta:
- Presentations explaining the technology and whatnot
- Source code reviews…correctly highlighted and interactive
- Executing the code in a shell
During my sprint reviews, I noticed I used my org-mode-formatted
files, eshell and source code buffers… In other words, I was
always in Emacs. However, fat-fingering or mentally burping delayed
the gratification for my audience while I laboriously typed. I
originally solved this problem by predefining each “step” as an
Emacs Lisp function, and then had another function execute each
function when I hit an advance key (F12
).
After I had amassed a small army of helper functions, I packaged it as
demo-it
, because I lack the imagination to come up with anything more
clever.
See the following videos as examples of what can be done:
- Emacs: An Introduction for the Curious
- Literate DevOps Programming
- Learn You Some Lisp for Great Good
Using this project is a four step process:
- Load the library in your own Elisp source code file
- Create zero or more helper functions that “do things”, or use the functions provided by this project.
- Order the functions by calling
(demo-it-create)
- Call
demo-it-start
to begin the fun.
Press the space for each step, or call demo-it-end
to end early.
For instance:
(require 'demo-it)
(defun my-demo-step/show-code ()
"Helper demo function that displays some source code and
advances the presentation at the same time."
(demo-it-load-file "example/example.py")
(demo-it-presentation-advance))
;; Order the functions and forms for this presentation:
(demo-it-create (demo-it-presentation "example/example.org")
my-demo-step/show-code
demo-it-presentation-return ; close file and advance
(demo-it-run-in-eshell "python example/example.py"))
(demo-it-start)
The `demo-it-create’ is a macro that stores a single demonstration. Calling it a second time replaces any previously created demonstrations.
Each “step” given to the demo-it-create
macro can be one of the
following:
- Expression typically calling a helper function, for instance:
(demo-it-presentation "example/example.org")
- Name of a function to call that does multiple actions, for instance:
demo-it-presentation-return
- a string referring to a key-binding to run, for instance:
"C-x C-f example.el "
- a property that affects demonstration behavior, see the Demonstration Options or Customization
Note: Any Emacs function can be called, either by name or as part
of an expression. These functions can be standard functions,
supplied by this demo-it
package, or even ones you write. ;-)
The following list of keywords can be passed to demo-it-create
to
override various Customization settings:
:simple-mode
uses mode where space advances demonstration.:advance-mode
uses mode whereF12
advances demonstration.:use-shell
chooses a standardshell
command line interface when running the demo-it-start-shell command.:use-shell
chooses to use the built-in Emacs shell, which Emacs uses find more comfortable when subjected to Windows systems.:eshell
is an alias for:use-eshell.
:shell
is an alias for:user-shell
.:windows-on-right
defaults to opening auxiliary windows on the right side of the frame (see demo-it-load-file and other helper functions for examples).:windows-on-side
is an alias for:windows-on-right
.:windows-on-left
like the above, but defaults to the left side of the frame.:windows-below
opens other windows at the bottom of the current frame.:windows-above
opens other windows at the top of the current frame.:fullscreen
starts the demonstration with the current frame in fullscreen mode.:single-window
deletes other windows when started, and restores those windows when the demonstration completes.:text-small
starts presentations and other files in a slightly smaller font that the current default. Yeah, it seems like a nice idea to offer it, but I wonder if that is really helpful as a default for a demonstration.:text-normal
starts presentations and other loaded files in the default font and size.:text-medium
starts presentations and other loaded files in a slight larger font size (technically scaled at 1).:text-large
scales presentations and other loaded files at 2.:text-x-large
scales loaded files at 3.:text-xx-large
scales loaded files at 4 … go figure.:text-huge
scales newly loaded files at 5. Got a big monitor or very few words, I see.:insert-slow
shell commands (and other calls to demo-it-insert function) are inserted character by character as if a hacker who never took a typing class in middle school was typing the text.:insert-medium
shell commands and other text are inserted as if a medium-grade nerd with sufficient typing skills entered them.:insert-fast
shell commands are entered like a typist, but to an audience with the attention span of a gerbil.:insert-quickly
shell commands are instantly entered, and the audience is spared the gimmickry of yet-another Emacs feature.:show-mode-line
leaves the mode-line alone for presentations and files loaded by the demonstration package.:hide-mode-line
hides the mode line so neckbeards pay attention to your demonstration and quit straining to see what minor modes you prefer. Still using paredit, I see.:hide-org-markers
hides the asterisks, slashes, and other markup characters that format text, but still shows the text in bold and italics.:show-org-markers
displays org-mode presentations as you wrote it.:variable-width
uses a variable width font for presentations because we want to make the vi users cry.:fixed-width
displays org-mode presentations with your default monospaced font for ultra nerd cred. You may need this feature if source code in your presentation.:show-block-headers
Should the#+begin
and#+end
markers be shown? If you are trying to talk about literate devops then, the answer is yes, show them the way you see them.:hide-block-headers
Hides the#+begin
and#+end
markers, but shows the glorious source code inside. Currently, also shows the surrounding#+HEADER
entries, so beware.
Once the demonstration has been created using demo-it-create
,
start it by calling demo-it-start
, as this will invoke the
first step.
Typically, pressing the SPACE
or RETURN
key will advance to the
next step, but this depends on which of the Demo Modes was chosen.
A deprecated version of demo-it-start
allows you to pass in a list
of the steps, but creating this list can be problematic, so you’ll
get more mileage from the demo-it-create
macro.
Some demonstrations are so complete that pressing the space bar to advance to each step is sufficient. However, this project can be used as a helper where each step merely sets up an environment where some Emacs feature or source code can be elaborated with personal prestidigitation. In this case, using the space and return to advance the demonstration would limit what can be demonstrated manually.
So demo-it
contains two minor modes, and starting a
demonstration, one of the following minor mode is chosen.
The choice is either made by setting the global customization
value, , or by passing the following keyword to demo-it-create
.
:simple-mode
:advance-mode
The standard minor mode for demonstrations, has the following key features:
Space
orReturn
advances to the next demonstration stepq
turns off this mode, allowing you to type normally. Calldemo-it-mode
to resume this modeQ
ends the demonstration
Note: In this mode, clicking the mouse on the right-side of the screen will advance the demonstration, while clicking elsewhere, repositions the cursor.
The advanced mode is used when the demo-it
project simply sets
up an environment, where you want most keys available to enter
commands manually. This mode has the following key features:
F12
advances to the next step in the demonstrationM-F12
ends the demonstration
Why yes, while called advanced is certainly has limited features.
This project relies on other projects to do most of the heavy
lifting for using org-mode
files as the basis of a presentation,
especially the org-tree-slide project, which displays each section
under a header as the sole contents of a buffer.
The following functions can be added to your demonstration to control the display of the presentation.
(file &optional size style section)
Loads the given org-mode
file as a presentation. This
automatically calls org-tree-slide if available.
This function takes an optional size
parameter to specifies the
text scale. If nil
, this defaults to the value set in
demo-it–text-scale customization variable.
The optional style
parameter can be set to either :variable for
variable font pitch, :blocks for diminished headers on org-blocks,
or :both to enable both features. This is a deprecated, legacy
feature, since it is easier and clearer to either use the
customization variables:
The final parameter, section
, is a string containing the name of
an org-mode
header to specify as the first section to display.
Undoes the display settings made to the presentation buffer.
Makes the last running presentation the current buffer, deletes
other windows, and advances to the next org-mode
section.
Similar to calling demo-it-presentation-return in that the latest specified presentation becomes the current buffer and all other windows are deleted.
However, the presentation is not advanced to the next section.
Advances the currently running presentation to the next section, but doesn’t change focus to the window. Any further commands happen in the current window.
This function is useful if a presentation discusses multiple commands, then you can advance through them while other commands actually perform the action (like executing commands in a shell).
As an example, the following demonstration will live-code while the presentation discusses each part:
(demo-it-create (demo-it-presentation "elisp-cookbook.org")
(demo-it-load-file "elisp-example.el")
; Advance to next section that talks about defun:
demo-it-presentation-advance
; Start coding an Emacs Lisp function:
(demo-it-insert "def") ; Begin yasnippet template
"TAB" ; Trigger yasnippet
(demo-it-insert "some-func") ; The function name
"TAB" ; Advance to parameters
(demo-it-insert "x y") ; parameters
"TAB" ; Advance to parameters
(demo-it-insert "Example function.")
"TAB" ; Advance to interactive
(demo-it-insert " ") ; No need for this section
"TAB" ; Advance to function body
; Advance to next section to talk about if statements
demo-it-presentation-advance
(demo-it-insert "if") ; Begin next template
"TAB" ; Trigger yasnippet
(demo-it-insert "(eq x y)") ; predicate expression
"TAB" ; Advance to if body
) ;; etc.
Given a string parameter, phrase
, as a regular expression, this
function highlights a phrase in the presentation buffer without
changing the current buffer. This is
useful to highlight bullet point items while executing appropriate
code.
The color
parameter is a face from the hi-lock
project,
e.g. :hi-yellow.
Note: This unhighlights previous highlighted phrases.
Call demo-it-presentation-unhighlight-all
if you just want to
remove the highlighting.
Demonstration similar to calling demo-it-presentation, in that it
presents an org-mode
file as a full-screen presentation. In this
form, the demonstration doesn’t do anything more than advance
through the presentation, and calling either demo-it-create
or
demo-it-start
is not needed.
This function begins a minor-mode where the space or return key
advances the presentation to the next section. In this mode, the
q
disables this mode, and Q
quits the demonstration and
presentation.
While the standard customization variables configure the
presentation display style, this function accepts a size
parameter to set the text scaling size.
The optional style
parameter can be set to either :variable for
variable font pitch, :blocks for diminished headers on org-blocks,
or :both to enable both features.
While a simple call to find-file
is often sufficient to display a
file in Emacs, the following functions can be helpful for showing
files and source code during a demonstration.
These functions often take the following optional parameters, and in the spirit of DRY, we will specify them here:
The optional side
parameter specifies the side of the frame to
display the new window. Acceptable values can one of the following
keywords:
:above
:below
:left
:right
:side
is a synomym for:right
:none
loads the file in the current buffer.
If nil
, defaults is to use the customized value of
demo-it–open-windows.
The optional size
parameter takes an integer and specifies the
text scale. If nil
, this defaults to the value set in
demo-it–text-scale customization variable.
The width
parameter specifies the size of
the new window, which is either the width of a side window, or
the height if the window is :above
or :below
.
Calling this function with a file, first splits the root frame into a side window and loads the file into that window.
Keep in mind, that calling it a second time will result in further
splitting of the root window. Call delete-window
or
demo-it-presentation-return-noadvance, or close the window
while also updating the presentation with demo-it-presentation-return.
The optional parameters this function takes are described above.
Splits window and loads a file, but also narrows to particular region.
If the type
parameter is set to :line
, then the start
and
end
parameters specify the first and last lines of the region to
narrow. If type
is set to :char
, then start
and end
refer
to specific character positions.
The other optional parameters this function takes are described above.
See demo-it-load-fancy-file for an alternative version.
Splits the root frame and loads a file
specified by the first
parameter in that window (see demo-it-load-file), however, this
function can use the
fancy narrow to
highlight part of the buffer (if it has been loaded), otherwise, it
behaves like demo-it-load-part-file and narrows to the area specified.
If the second parameter, type
is a string that specifies a
function name (available via imenu
), then it highlights
that function.
If type
is a :line
, then the next two parameters, start
and end
specifies the beginning or ending lines.
If type
is :char
, then start
and end
are exact buffer
positions, which you can determine by evaluating (M-;
) the
following expression:
(kill-new (int-to-string (point)))
The optional parameters side
and size
are
described above.
Note: This function simply detects if the fancy-narrow
package
has been loaded. The demonstration will need to issue a require
.
Loads a file as an image (or any other special file) in another window without a mode line or fringe.
The optional parameters this function takes are described above.
Loads two files in either two windows on top of each other on the
right side of the screen, or two windows below (depending on the
value of the side
, which should either be :below
or :side
.
The other optional parameter, size
is described above.
What Emacs-sponsored demonstration would be complete without being
able to run the application you created. While your demonstration
could easily call shell-command
, starting a shell, and having
Emacs type the commands makes a demonstration appear more real and
interactive.
The typing abilities when inserting text are not very realistic, as it simply picks a random delay between each letter. What is lacking, however, it clacking should of the switches going off while the letter appears (PRs are acceptable).
The following functions can be added to your demonstration to enter
commands in a shell (both your default shell, as well as the Eshell
is supported by setting the demo-it–shell-or-eshell variable or
giving demo-it-create
one of the following keyword configurations:
:use-shell
:use-eshell
Starts a shell or eshell instance, in a particular directory and executes the given command. The command can be entered into the shell with a slight random delay intended to mimic a person typing. This speed of this is specified by demo-it–insert-text-speed.
The optional name
parameter labels the buffer, and defaults to
Shell
.
The other optional parameters this function takes are described above.
Run shell command in a shell previously started with
demo-it-start-shell. If a name
is not specified, it defaults to
name, Shell
.
The optional speed
parameter overrides the customization value
set by demo-it–insert-text-speed, or the text-speed related
keyword given to demo-it-create
.
Call to display the shell buffer if the shell window of a given
name
has been hidden. If name
is not specified, it defaults to
Shell
.
The other optional parameters this function takes are described above.
Perhaps you want to regale your audience with your programmatic prowess, but don’t dare attempt to do live-coding in front of live individuals? Yes, even creating a series of yasnippets can result in some serious embarrassment (and compiler errors) if you fat-finger any of the fields.
Have no fear, just create a series of entries that contains calls to
demo-it-insert
, as this function inserts a string into the current
buffer as if you were typing it by hand (this is called by
demo-it-run-in-shell).
The following demo-it
example uses this function as well as
the def
yasnippet for Ruby and particular keystrokes to move from
field to field:
(demo-it-create (find-file "foobar.rb")
(demo-it-insert "def")
(yas-expand)
(demo-it-insert "hello")
"TAB TAB"
(demo-it-insert "name")
"TAB"
(demo-it-insert "\"Hello, #{name}\"" :fast))
The optional speed
parameter is described above.
Note: The previous version of demo-it
offered specialized
feature for inserting text where each string to entered was put in
a hashmap, demo-it-text-entries
, and the entries were inserted
with calls to a dedicated function, demo-it-insert-text
. However,
the above seems to work just as well without a special function, so
it has been deprecated and removed.
The following are useful functions that don’t fit in the previous sections, so consider this the miscellaeous section.
Calling this command ends the current demonstration by disabling
the mode (see Demo Modes), resetting the values inflicted on the presentation buffer
as well as restoring the window arrangement to their original glory
before demo-it-start
was called.
This function is typically called by one of the Demo Modes to execute the next step in the current demonstration.
However, this function can be called to jump to a particular STEP
by specifying a step number to the optional parameter, step
. This
can also be done with a prefix, e.g. C-6 <F12> to run the 6th step.
Keep in mind that normally step functions expect a particular state to be established, so calling this function to jump to a particular step may not work as intended.
Why yes, we do want to figure out a good mechanism for establishing a state for each called step, but that be a wee-bit challenging.
Re-executes the previous step in the current demonstration.
Note, this doesn’t handle the concept of the state of the Emacs system, so calling this function interactively does not rewind and re-executes, it just re-executes given the current Emacs state.
Displays a message about the expected function (that is, the function that will be run) during the next step. This can be useful when you’ve lost your way, and ask yourself, How did I get here?
Of course, you may ask yourself, How do I work this?
And you may ask yourself, Where is that large automobile? \
And you may tell yourself, This is not my beautiful house! \
And you may tell yourself, This is not my beautiful wife!
Hides the mode line for a current buffer. This is done by setting
the mode-line-format
to nil
, but also saves off the value so
that it can be restored by calling demo-it-show-mode-line.
Shows the mode line of the current buffer, if it was previously hidden with a call to demo-it-hide-mode-line.
Displays a file as the demonstration’s title, e.g. displayed with a larger-than-life font without a mode line, etc. Typically, a specially-formatted org-mode file would do the job, but any file, including an image will work.
The size
parameter specifies the text scale, which ignores the
demo-it–text-scale customization setting and defaults to :huge
(or 5x your normal text font size).
When demonstrating Emacs features, you may want to display the
keystroke you type. Yes, you could (and probably should) use a
package like mwe-log-commands by Michael Weber, but you can’t
really use that sort of feature with demo-it
, as you’d just log a
bunch of spacebars bound to demo-it-step.
What you really want is to display the key you wanted to type.
For that, you’ll want to end your step function with a call to
demo-it-message-keybinding
, as it will take two strings, where
the first one is the “key” and the other is a function or command
that it normally calls.
For instance:
(defun my-demo/dired-a-directory ()
"Opens a `dired' buffer on a particular directory.
This is a step function that I add to demo-it-create."
(dired (expand-file-name "~/work"))
(demo-it-message-keybinding "C-x d" "dired"))
This sort of step function would be added to demo-it-create
as
a simple symbol, like:
(demo-it-create ;; :keybindings
;; other functions and expressions
my-demo/dired-a-directory
;; other functions and expressions
)
Can use the fancy-narrow package to highlight a particular section. If the package is not available, it simply narrows to that area. If called interactively, this highlights the region (if active) or the current function.
If the first parameter, type-or-fn
is a string, this specifies
the name of a function to highlight.
If it is a :line
, then the next two parameters, start
and end
specifies the beginning or ending lines.
If it is :char
, then start
and end
are exact buffer
positions, which you can determine by evaluating (M-;
) the
following expression:
(kill-new (int-to-string (point)))
If type-or-fn
is nil
and the region is active, highlight the
region.
If none of the following match, simply select the function the point is currently in.
Note: While this function checks to see if the package is available and loaded, it does not actually do the loading (or the installing of the package), for that, you will need to do something like:
(require 'fancy-narrow)
The following is a list of custom variables that can be set through
the standard Emacs customization feature (under the demo-it
group).
Note, each custom value may be overridden with a magic symbol to the
demo-it-create macro or with a parameter to many functions.
The keymap-specific minor mode to use when a demonstration
starts. Should either be set to the symbol, :simple-mode
for using
the space to advance to next step and q
to exit the demonstration,
or :advanced-mode
, where F12
advances.
Defaults to :simple-mode
This setting can be overridden by a keyword to demo-it-create
:
:simple-mode
:advanced-mode
When opening up a shell, this customization value specifies whether
it should run the shell
or eshell
command.
Should be set to one of the following keywords:
:shell
:eshell
Defaults to :eshell
This setting can be overridden by the following keywords to
demo-it-create
macro:
:use-eshell
:use-shell
When opening side windows, split the frame on a particular side. Should be set to one of the following keywords:
:above
:below
:left
:right
The keyword, :side
is a synonym for :right
.
Defaults to :right
This setting can be overridden by one of the following keywords
passed to demo-it-create
:
:windows-on-side
:windows-on-right
:windows-on-left
:windows-below
:windows-above
The size of side windows to open. This is the width if the window
is opened on one of the sides (:left
or :right
), or the height
if the window is opened :above
or :below
.
Defaults to 80
Sets the default text scale when opening files in side windows (see demo-it–open-windows). While this can be set to an integer, it can also be set to one of the following keywords:
:small
, set to a text scale of -1:normal
, set to a text scale of 0:medium
, set to a text scale of 1:large
, set to a text scale of 2:x-large
, set to a text scale of 3:xx-large
, set to a text scale of 4:huge
, set to a text scale of 5
It defaults to :large
(a text-scale-set
value of 2
).
This customization value can be overridden with one of the
following keywords passed to demo-it-create
:
:text-small
:text-normal
:text-medium
:text-large
:text-x-large
:text-xx-large
:text-huge
A boolean setting that if set to a non-nil value, demonstrations
start with the current frame in fullscreen mode. Defaults to
false
.
This customization value can be overridden with :fullscreen
keyword passed to demo-it-create
.
A boolean setting that if non-nil, deletes other windows to start
the demonstration with a current buffer window being the only
displayed window. Defaults to t
.
This customization value can be overridden with :single-window
keyword passed to demo-it-create
.
If set to a nil value (false), the mode-line is hidden for any
presentation files (this doesn’t affect other files opened with the
demo-it-load-file). Defaults to t
.
This customization value can be overridden with either of the
following keywords passed to demo-it-create
:
:show-mode-line
:hide-mode-line
If set to a non-nil value, surrounding asterisks, underlines and
slashes that define an org-mode
textual formats in a presentation
are displayed. Otherwise those characters hidden, even though the
effects of bolding and italics are still shown. Defaults to t
.
This customization value can be overridden with either of the
following keywords passed to demo-it-create
:
:show-org-markers
:hide-org-markers
If set to a non-nil value, a variable-width font is used when
displaying org-mode
presentation files, otherwise the standard
fixed-width font is used. Defaults to nil
.
This customization value can be overridden with either of the
following keywords passed to demo-it-create
:
:variable-width
:fixed-width
If set to a non-nil value, the start and ending lines of org-mode
blocks are shown during a presentation, otherwise these lines are
hidden, but the contents within the blocks are still shown.
This currently only hides these lines:
#+BEGIN_SRC ... #+END_SRC
Other surrounding header values, like #+HEADERS:
may still be seen.
This defaults to t
, however, this customization value can be
overridden with either of the following keywords passed to
demo-it-create
:
:show-block-headers
:hide-block-headers
The functions, demo-it-run-in-shell, demo-it-start-shell, and demo-it-insert, enters the text into the shell as if a human were typing it. This value specifies the speed at which that text is inserted into the shell.
This can set to one of the following keywords:
:instant
to insert text with no delay:slow
:medium
:fast
Defaults to :medium
.
This can also specify a tuple of two integer values for the random
number of milliseconds between those two values to delay before
inserting each character, for instance, the :medium
delay has a
lower value of 30 milliseconds, and an upper delay of 500.
This manual is for demo-it
(version {{{version}}},
{{{updated}}}), a project for running demonstrations within Emacs.
Copyright @@texinfo:@copyright{}@@ 2016, Howard Abrams
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.
For those of you trying to read this online, this index is generated and only available within Emacs. If you are reading this from within Emacs, well-done.