├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.org ├── LICENSE ├── README.org ├── demo-it-custom.el ├── demo-it-extras.el ├── demo-it-present.el ├── demo-it-tests.el ├── demo-it.el ├── demo-it.info ├── demo-it.org ├── demo-it.texi ├── demonstration ├── a-demo.el └── a-demo.org ├── dir ├── example ├── error-example.el ├── example-code.el ├── example-code.py ├── example-code.rb ├── example-files.el ├── example-files.org ├── example-shell.el ├── example-shell.org ├── example-title.org ├── example.el ├── example.org ├── example.py ├── example.rb ├── kbd-example.el ├── pdx-emacs.png └── setq-example.el └── snippets └── demo-it /.gitignore: -------------------------------------------------------------------------------- 1 | /tags 2 | /TAGS 3 | *.elc 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) -------------------------------------------------------------------------------- /CONTRIBUTING.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Contributing to this Project 2 | #+AUTHOR: Howard Abrams 3 | #+EMAIL: howard.abrams@gmail.com 4 | #+DATE: 2016 Oct 01 5 | 6 | I created this project based on my own needs and desires, and I'm 7 | mildly stunned that others are interested enough in creating 8 | demonstrations in Emacs, so I definitely want to work with others on 9 | this. So... contributions are always welcome, no matter how large or 10 | small. This file contains the guidelines I ask all contributors to 11 | follow. 12 | 13 | - For any contributions to my experimental =v2= track, please create a 14 | topic branch based off that =v2= branch, push said topic branch onto 15 | your fork and submit your pull request from that branch. 16 | 17 | - Wanna contribute a bug fix to my primary =1.x= track, please create 18 | a topic branch based off our =master= branch, push said topic branch 19 | onto your fork and submit your pull request from that branch. 20 | 21 | * Code of Conduct 22 | 23 | I want to keep this project open and inclusive. So I ask that before 24 | you contribute, you read and follow our [[file:CODE_OF_CONDUCT.md][Code of Conduct]]. 25 | 26 | * Found an Issue? 27 | 28 | I definitely want to hear from you! 29 | 30 | If you find a bug in the source code or a mistake in the docs, you 31 | can help me by submitting an issue to the [[https://github.com/howardabrams/demo-it/issues][repository]]. 32 | 33 | Want to contribute with a fix? Thank you. Please, submit a 34 | [[https://github.com/howardabrams/demo-it/pulls][pull request]]. 35 | 36 | *Want a Feature?* Similarly to finding an issue, enter details for a 37 | [[https://github.com/howardabrams/demo-it/issues][feature request]], but feel free to fork this repository and try to 38 | give me more details with [[https://github.com/howardabrams/demo-it/pulls][pull request]]. 39 | 40 | *Note:* While the [[file:demo-it-tests.el][unit tests]] are hardly sufficient, please make sure 41 | your PR doesn't break any. Better yet, add more to that! 42 | 43 | * Developing 44 | 45 | As you can imagine, testing this code is difficult to automate. 46 | Some tests for state-less functions can be found in 47 | [[file:demo-it-tests.el][demo-it-tests.el]]. 48 | 49 | Since the base [[file:demo-it.el][demo-it.el]] code is now broken into multiple subfiles, 50 | issuing a =(require)= won't work without the following: 51 | 52 | #+BEGIN_SRC elisp :results silent 53 | (add-to-list 'load-path (expand-file-name ".")) 54 | #+END_SRC 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | At the end of each sprint, each of us demonstrate accomplishments. 2 | These reviews often incorporate the following trifecta: 3 | 4 | * Presentations explaining the technology and other frobnications 5 | * Source code, correctly highlighted and perhaps interactive 6 | * Executing the code, preferably in a shell to maintain nerd cred 7 | 8 | During my sprint reviews, I noticed I used my org-mode-formatted 9 | files, eshell and source code buffers... always in Emacs. 10 | However, fat-fingering or mentally burping delayed the 11 | gratification for my audience while I laboriously typed. 12 | I solved this problem by predefining each "step" as an Emacs Lisp 13 | function, and had another function execute each /step function/ when I 14 | hit an /advance/ key (=F12=). 15 | 16 | After I had amassed a small army of /helper functions/, I packaged it as 17 | =demo-it=, because I lack the imagination to come up with anything more 18 | clever. 19 | 20 | See the following videos as examples of what can be done: 21 | 22 | * [[http://www.youtube.com/watch?v=B6jfrrwR10k][Emacs: An Introduction for the Curious]] 23 | * [[https://www.youtube.com/watch?v=dljNabciEGg][Literate DevOps Programming]] 24 | * [[https://www.youtube.com/watch?v=_l1oj5CEh7k][Learn You Some Lisp for Great Good]] 25 | 26 | Click the following image for a quicker example: 27 | 28 | #+HTML: Example and Demonstration 29 | 30 | Using this project is a four step process: 31 | 32 | 1. Load the library in your own Elisp source code file 33 | 2. Create zero or more helper functions that "do things", or use the 34 | functions provided by this project. 35 | 3. Order the functions by calling =(demo-it-create step-1 step-2 ...)= 36 | 4. Call =demo-it-start= to kick off the fun. 37 | 38 | Press space for each step, or call =demo-it-end= to end earlier. 39 | 40 | For instance: 41 | 42 | #+BEGIN_SRC elisp 43 | (require 'demo-it) ;; Load this library of functions 44 | 45 | (defun my-demo-step/show-code () 46 | "Helper demo function that displays some source code and 47 | advances the presentation at one time." 48 | (demo-it-load-file "example/example.py" :right) 49 | (demo-it-presentation-advance)) 50 | 51 | ;; Order the functions and forms for this presentation: 52 | (demo-it-create (demo-it-presentation "example/example.org") 53 | my-demo-step/show-code 54 | demo-it-presentation-return ; close file and advance 55 | (demo-it-run-in-eshell "python example/example.py")) 56 | 57 | (demo-it-start) 58 | #+END_SRC 59 | 60 | Each "step" given to =demo-it-create= can be one of the following: 61 | 62 | - an expression typically calling a helper function 63 | - a name of a function to call that does multiple actions 64 | - a string referring to a key-binding to run 65 | - a property that affects demonstration behavior 66 | 67 | This package has a collection of helping functions, that can either be 68 | called directly as part of an expression, or embedded in a 69 | demonstration /step function/. For a more complete example, see 70 | [[file:example/example.el][example.el]] or the other examples in the [[file:example][example directory]]. 71 | 72 | Finally, read the [[file:demo-it.org][documentation]] (which is available as an Info manual). 73 | 74 | * Historical Record 75 | 76 | The initial release, while published on MELPA, was rather an ad hoc 77 | collection of functions, poorly organized and barely documented. 78 | Sorry about that. I really didn't think any one would care enough to 79 | use it. 80 | 81 | *Version 2* of this project attempted to remedy those shortcomings, 82 | cleaning and standardizing the /interface/ of functions. Also included 83 | is the following features: 84 | 85 | - Simplification of a demonstration's construction. Originally 86 | each step essentially required a helper function, but now, we can 87 | specify full expressions directly into =demo-it-create=. 88 | 89 | - Default behavior is now based on customized preferences instead of 90 | hard-coded values. Functions still accept optional values to 91 | override those defaults. Also the =demo-it-create= macro accepts 92 | demo-level overrides of the customized preferences. 93 | 94 | - Described every function [[file:demo-it.org][both online]] and as an Info manual, with 95 | lots of examples for the step functions. 96 | 97 | *Version 3* is a plan to have each step more repeatable. Currently, 98 | each step assumes a state built by the previous steps, which makes 99 | developing, debugging, and reversing difficult. 100 | -------------------------------------------------------------------------------- /demo-it-custom.el: -------------------------------------------------------------------------------- 1 | ;;; DEMO-IT-CUSTOM --- The project's custom variables 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright © 2016, Howard Abrams, all rights reserved. 5 | ;; Created: 19 September 2016 6 | ;; 7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 | ;; 9 | ;;; Commentary: 10 | ;; 11 | ;; Two ways to set default properties and demonstration settings. 12 | ;; First, by setting the value on customized values, and 13 | ;; Second, by passing in a mnemonic value with `demo-it-create', 14 | ;; See the `demo-it--set-property' for the mapping. 15 | ;; 16 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 17 | ;; 18 | ;; This program is free software; you can redistribute it and/or 19 | ;; modify it under the terms of the GNU General Public License as 20 | ;; published by the Free Software Foundation; either version 3, or 21 | ;; (at your option) any later version. 22 | ;; 23 | ;; This program is distributed in the hope that it will be useful, 24 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 | ;; General Public License for more details. 27 | ;; 28 | ;; You should have received a copy of the GNU General Public License 29 | ;; along with this program; see the file COPYING. If not, write to 30 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 31 | ;; Floor, Boston, MA 02110-1301, USA. 32 | ;; 33 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 34 | ;; 35 | ;;; Code: 36 | 37 | (defgroup demo-it nil 38 | "Customizations and behaviors for demonstrations." 39 | :prefix "demo-it-" 40 | :group 'applications 41 | :link '(url-link :tag "Github" "https://github.com/howardabrams/demo-it")) 42 | 43 | (defcustom demo-it--keymap-mode-style :simple-mode 44 | "The keymap-specific minor mode to use when a demonstration 45 | starts. Should either be :simple-mode for using the space to 46 | advance to next step and `q' to exit the demonstration, 47 | or :advanced-mode, where advances." 48 | :type '(choice (const :tag "simple" :simple-mode) 49 | (const :tag "advanced" :advanced-mode)) 50 | :group 'demo-it) 51 | 52 | (defcustom demo-it--shell-or-eshell :eshell 53 | "When opening up a shell, should this run the `shell' or `eshell' command." 54 | :type '(choice (const :tag "shell" :shell) 55 | (const :tag "eshell" :eshell)) 56 | :group 'demo-it) 57 | 58 | (defcustom demo-it--open-windows :right 59 | "When opening side windows, split the frame on a particular 60 | side, like `:below' or on the `:right'." 61 | :type '(choice (const :tag "above" :above) 62 | (const :tag "below" :below) 63 | (const :tag "left" :left) 64 | (const :tag "right" :right)) 65 | :group 'demo-it) 66 | 67 | (defcustom demo-it--open-windows-size 80 68 | "The size of the window to open. This is the width if the 69 | window is opened on one of the sides (:left or :right), or the 70 | height if the window is opened :above or :below." 71 | :type '(integer)) 72 | 73 | (defcustom demo-it--text-scale 2 74 | "Sets the default text scale when opening files." 75 | :type '(choice integer 76 | (const :tag "small" -1) 77 | (const :tag "normal" 0) 78 | (const :tag "medium" 1) 79 | (const :tag "large" 2) 80 | (const :tag "x-large" 3) 81 | (const :tag "xx-large" 4) 82 | (const :tag "huge" 5)) 83 | :group 'demo-it) 84 | 85 | (defcustom demo-it--start-fullscreen nil 86 | "If non-nil, start the demonstration with the frame in fullscreen mode." 87 | :type '(boolean) 88 | :group 'demo-it) 89 | 90 | (defcustom demo-it--start-single-window t 91 | "If non-nil, delete other windows to start the demonstration with a single buffer window." 92 | :type '(boolean) 93 | :group 'demo-it) 94 | 95 | (defcustom demo-it--presentation-hide-mode-line t 96 | "If non-nil, shows the mode-line during a presentation, 97 | otherwise the mode-line is hidden from view." 98 | :type '(boolean)) 99 | 100 | (defcustom demo-it--presentation-hide-org-markers t 101 | "If non-nil, shows the surrounding asterisks, underlines and 102 | slashes that define an `org-mode' textual formats, otherwise 103 | these characters hidden, even though the effects of bolding and 104 | italics are shown." 105 | :type '(boolean)) 106 | 107 | (defcustom demo-it--presentation-variable-width nil 108 | "If non-nil, uses a variable-width font for `org-mode' presentation files, 109 | otherwise the continues to use the standard fixed-width font." 110 | :type '(boolean)) 111 | 112 | (defcustom demo-it--presentation-hide-org-blocks t 113 | "If non-nil, shows the `#+BEGIN_SRC' and `#+END_SRC' code 114 | blocks in an `org-mode' presentation file, otherwise these lines 115 | are hidden, but the contents within the blocks are still shown." 116 | :type '(boolean)) 117 | 118 | (defun demo-it--presentation-variable-width-p (&optional style) 119 | "Predicate return `t' if STYLE is either `:variable' or `:both' 120 | or the customization setting, 121 | `demo-it--presentation-variable-width' is true. Otherwise, STYLE 122 | can be `:fixed'." 123 | (if (eq style :fixed) 124 | nil 125 | (when (or (eq style :variable) 126 | (eq style :both) 127 | demo-it--presentation-variable-width) 128 | t))) 129 | 130 | (defun demo-it--presentation-hide-blocks-p (&optional style) 131 | "Predicate return `t' if STYLE is either `:block' or `:both' 132 | or the customization setting, `demo-it--presentation-hide-org-blocks' 133 | is non-nil." 134 | (when (or (eq style :block) (eq style :blocks) 135 | (eq style :both) 136 | demo-it--presentation-hide-org-blocks) 137 | t)) 138 | 139 | (defcustom demo-it--insert-text-speed :medium 140 | "The speed at which some functions insert text into the shell 141 | and other place. This can be :instant for instantaneous, 142 | or :slow, :medium or :fast. 143 | 144 | This can also be a tuple of two integer values for the random 145 | number of milliseconds between inserting each character." 146 | :type '(choice (const :tag "fast" :fast) 147 | (const :tag "faster" :faster) 148 | (const :tag "medium" :medium) 149 | (const :tag "slow" :slow) 150 | (const :tag "instant" :instant)) 151 | :group 'demo-it) 152 | 153 | (defun demo-it--get-insert-text-speed (&optional speed) 154 | "The tuple of the lower and upper limits for the insert speed 155 | based on the symbol stored in `demo-it--insert-text-speed'. 156 | The optional value for SPEED override the default value." 157 | (let ((requested-speed (or speed demo-it--insert-text-speed))) 158 | (pcase requested-speed 159 | ((or :faster :insert-faster) '(1 . 10)) 160 | ((or :fast :insert-fast) '(10 . 100)) 161 | ((or :medium :insert-medium) '(30 . 500)) 162 | ((or :slow :insert-slow) '(200 . 1000)) 163 | (_ requested-speed)))) 164 | 165 | (defun demo-it--get-text-scale (&optional size) 166 | "Returns SIZE if SIZE is an integer, otherwise, returns an 167 | integer matching the symbol specified by SIZE, e.g. `:large'." 168 | (let ((requested-size (or size demo-it--text-scale))) 169 | (pcase requested-size 170 | ((or :small :text-small) -1) 171 | ((or :normal :text-normal) 0) 172 | ((or :medium :text-medium) 1) 173 | ((or :large :text-large) 2) 174 | ((or :x-large :text-x-large) 3) 175 | ((or :xx-large :text-xx-large) 4) 176 | ((or :huge :text-huge) 5) 177 | (_ requested-size)))) 178 | 179 | (defun demo-it--set-property (prop) 180 | "Sets a particular property, specified by keyword, PROP to t." 181 | (pcase prop 182 | (:simple-mode (setq demo-it--keymap-mode-style :simple-mode)) 183 | (:advance-mode (setq demo-it--keymap-mode-style :advanced-mode)) 184 | (:advanced-mode (setq demo-it--keymap-mode-style :advanced-mode)) 185 | 186 | (:use-eshell (setq demo-it--shell-or-eshell :eshell)) 187 | (:use-shell (setq demo-it--shell-or-eshell :shell)) 188 | (:eshell (setq demo-it--shell-or-eshell :eshell)) 189 | (:shell (setq demo-it--shell-or-eshell :shell)) 190 | 191 | (:windows-on-side (setq demo-it--open-windows :right)) 192 | (:windows-on-right (setq demo-it--open-windows :right)) 193 | (:windows-on-left (setq demo-it--open-windows :left)) 194 | (:windows-below (setq demo-it--open-windows :below)) 195 | (:windows-above (setq demo-it--open-windows :above)) 196 | (:windows-replace (setq demo-it--open-windows :none)) 197 | 198 | (:fullscreen (setq demo-it--start-fullscreen t)) 199 | (:full-screen (setq demo-it--start-fullscreen t)) 200 | (:single-window (setq demo-it--start-single-window t)) 201 | 202 | (:text-small (setq demo-it--text-scale -1)) 203 | (:text-normal (setq demo-it--text-scale 0)) 204 | (:text-medium (setq demo-it--text-scale 1)) 205 | (:text-large (setq demo-it--text-scale 2)) 206 | (:text-x-large (setq demo-it--text-scale 3)) 207 | (:text-xx-large (setq demo-it--text-scale 4)) 208 | (:text-huge (setq demo-it--text-scale 5)) 209 | 210 | (:insert-quickly (setq demo-it--insert-text-speed :instant)) 211 | (:insert-faster (setq demo-it--insert-text-speed :faster)) 212 | (:insert-fast (setq demo-it--insert-text-speed :fast)) 213 | (:insert-medium (setq demo-it--insert-text-speed :medium)) 214 | (:insert-slow (setq demo-it--insert-text-speed :slow)) 215 | 216 | (:show-mode-line (setq demo-it--presentation-hide-mode-line nil)) 217 | (:hide-mode-line (setq demo-it--presentation-hide-mode-line t)) 218 | (:show-org-markers (setq demo-it--presentation-hide-org-markers nil)) 219 | (:hide-org-markers (setq demo-it--presentation-hide-org-markers t)) 220 | (:variable-width (setq demo-it--presentation-variable-width t)) 221 | (:fixed-width (setq demo-it--presentation-variable-width nil)) 222 | (:show-block-headers (setq demo-it--presentation-hide-org-blocks nil)) 223 | (:hide-block-headers (setq demo-it--presentation-hide-org-blocks t)))) 224 | 225 | (provide 'demo-it-custom) 226 | 227 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 228 | ;;; demo-it-custom.el ends here 229 | -------------------------------------------------------------------------------- /demo-it-extras.el: -------------------------------------------------------------------------------- 1 | ;;; DEMO-IT-EXTRAS --- Demo Functions that depend on other packages 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright © 2016, Howard Abrams, all rights reserved. 5 | ;; Created: 23 September 2016 6 | ;; 7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 | ;; 9 | ;;; Commentary: 10 | ;; 11 | ;; A collection of functions that depend on other packages available 12 | ;; from MELPA. While the functions check to see if the package is 13 | ;; available and loaded, it does not actually do the loading (or the 14 | ;; installing of the package). 15 | ;; 16 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 17 | ;; 18 | ;; This program is free software; you can redistribute it and/or 19 | ;; modify it under the terms of the GNU General Public License as 20 | ;; published by the Free Software Foundation; either version 3, or 21 | ;; (at your option) any later version. 22 | ;; 23 | ;; This program is distributed in the hope that it will be useful, 24 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 | ;; General Public License for more details. 27 | ;; 28 | ;; You should have received a copy of the GNU General Public License 29 | ;; along with this program; see the file COPYING. If not, write to 30 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 31 | ;; Floor, Boston, MA 02110-1301, USA. 32 | ;; 33 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 34 | ;; 35 | ;;; Code: 36 | 37 | (require 'cl) 38 | 39 | (declare-function demo-it--get-section "demo-it") 40 | (declare-function demo-it-load-file "demo-it") 41 | 42 | (declare-function fancy-narrow-to-region "ext:fancy-narrow") 43 | (declare-function fancy-narrow-to-defun "ext:fancy-narrow") 44 | 45 | ;; ---------------------------------------------------------------------- 46 | ;; FANCY HIGHLIGHTING 47 | ;; 48 | ;; A function useful for interactive work or as part of a 49 | ;; demonstration script, can use the tres cool highlighting feature 50 | ;; of `fancy-narrow' (see https://github.com/Malabarba/fancy-narrow) 51 | 52 | (defun demo-it-highlight-dwim (&optional type-or-fn start end) 53 | "Highlights or narrows to a particular 'section'. 54 | 55 | If TYPE-OR-FN is a string, it specifies the name of a function to 56 | highlight. If it is :line, then START and END specifies the 57 | beginning or ending lines. If TYPE-OR-FN is :char, then START and 58 | END are buffer positions. Finally, if TYPE-OR-FN is :regex, then 59 | START and END are regular expressions that refers to a match in 60 | the buffer. 61 | 62 | If TYPE-OR-FN is `nil', (or running interactively), then if a 63 | section is currently highlighted/narrowed, it is 64 | unhighlighted/widened. If the region is active, use, the region, 65 | otherwise, select the function the point is currently in. 66 | 67 | If the `fancy-narrow' package is installed, we'll call 68 | `fancy-narrow-to-region' or `fancy-narrow-to-defun', otherwise, 69 | we narrow to it." 70 | (interactive) 71 | 72 | (cl-flet ((hi-defun () ;; Highlight the current function 73 | (if (fboundp 'fancy-narrow-to-defun) 74 | (fancy-narrow-to-defun) 75 | (narrow-to-defun))) 76 | 77 | (hi-region (start end) 78 | (if (fboundp 'fancy-narrow-to-region) 79 | (fancy-narrow-to-region start end) 80 | (narrow-to-region start end)) 81 | (if (region-active-p) 82 | (deactivate-mark))) 83 | (active-p () 84 | (if (fboundp 'fancy-narrow-active-p) 85 | (fancy-narrow-active-p) 86 | (buffer-narrowed-p))) 87 | (unhighlight () 88 | (if (fboundp 'fancy-narrow-to-region) 89 | (ignore-errors 90 | (fancy-widen)) 91 | (widen)))) 92 | (let ((should-highlight (not (active-p)))) 93 | (unhighlight) 94 | (cond 95 | ;; Type is null, we assume we are interactive: 96 | ((null type-or-fn) (when should-highlight 97 | (if (region-active-p) 98 | (hi-region (region-beginning) (region-end)) 99 | (hi-defun)))) 100 | 101 | ;; With a specified type, we aren't interactive, and if we got a 102 | ;; symbol, then we can use `demo-it--get-section' for our bounds. 103 | ((symbolp type-or-fn) 104 | (let ((positions (demo-it--get-section type-or-fn start end))) 105 | (goto-char (car positions)) 106 | (hi-region (car positions) (cdr positions)) 107 | (recenter))) 108 | 109 | ;; With string, use `imenu' for matching: 110 | ((stringp type-or-fn) (imenu type-or-fn) 111 | (hi-defun)))))) 112 | 113 | (defun demo-it-load-fancy-file (file type &optional start end side size) 114 | "Splits window and loads FILE in another window, and use fancy 115 | narrow to highlight part of the buffer. 116 | 117 | If TYPE is a string that specifies a function name (available via 118 | the `imenu' call), then it highlights that function. 119 | 120 | If TYPE is :char or 'char, START and END refers to specific 121 | character positions, but if TYPE is :line or 'line, this selects 122 | the point positions as if START and END are line numbers. 123 | 124 | If `fancy-narrow' is not installed, then simply narrows to the area." 125 | (demo-it-load-file file side size) 126 | (demo-it-highlight-dwim type start end)) 127 | 128 | 129 | (provide 'demo-it-extras) 130 | 131 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 132 | ;;; demo-it-extras.el ends here 133 | -------------------------------------------------------------------------------- /demo-it-present.el: -------------------------------------------------------------------------------- 1 | ;;; DEMO-IT-PRESENT --- Summary 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright © 2016, Howard Abrams, all rights reserved. 5 | ;; Created: 23 September 2016 6 | ;; 7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 | ;; 9 | ;;; Commentary: 10 | ;; 11 | ;; Since I often have an org-mode file on the side of the screen to 12 | ;; demonstrate an outline of what I will be demoing, I made it a 13 | ;; function. 14 | ;; 15 | ;; The file contains functions for displaying an org-mode file as a 16 | ;; presentation using the `org-tree-slide' project (see 17 | ;; https://github.com/takaxp/org-tree-slide). 18 | ;; 19 | ;; If `org-tree-slide' is not available, it simply shows the 20 | ;; org-mode file. We really need to look at a way to make the 21 | ;; display configurable. 22 | ;; 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 24 | ;; 25 | ;; This program is free software; you can redistribute it and/or 26 | ;; modify it under the terms of the GNU General Public License as 27 | ;; published by the Free Software Foundation; either version 3, or 28 | ;; (at your option) any later version. 29 | ;; 30 | ;; This program is distributed in the hope that it will be useful, 31 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33 | ;; General Public License for more details. 34 | ;; 35 | ;; You should have received a copy of the GNU General Public License 36 | ;; along with this program; see the file COPYING. If not, write to 37 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 38 | ;; Floor, Boston, MA 02110-1301, USA. 39 | ;; 40 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 41 | ;; 42 | ;;; Code: 43 | 44 | (require 'cl) 45 | 46 | (declare-function org-tree-slide-content "ext:org-tree-slide") 47 | (declare-function org-tree-slide-move-next-tree "ext:org-tree-slide") 48 | (declare-function face-remap-add-relative "face-remap.el") 49 | (declare-function face-remap-remove-relative "face-remap.el") 50 | 51 | (defvar org-image-actual-width) 52 | (defvar org-tree-slide-heading-emphasis) 53 | (defvar org-hide-emphasis-markers) 54 | 55 | (defvar demo-it--text-scale) 56 | (defvar demo-it--presentation-hide-mode-line) 57 | (defvar demo-it--presentation-hide-org-markers) 58 | (defvar demo-it--presentation-variable-width) 59 | (defvar demo-it--presentation-hide-org-blocks) 60 | 61 | (declare-function demo-it--get-text-scale "demo-it-custom.el") 62 | (declare-function demo-it--presentation-variable-width-p "demo-it-custom.el") 63 | (declare-function demo-it--presentation-hide-blocks-p "demo-it-custom.el") 64 | (declare-function demo-it-hide-mode-line "demo-it.el") 65 | (declare-function demo-it-show-mode-line "demo-it.el") 66 | (declare-function demo-it-disable-mode "demo-it.el") 67 | 68 | (declare-function demo-it-create "demo-it.el") 69 | (declare-function demo-it-start "demo-it.el") 70 | (declare-function demo-it--setq-restore "demo-it.el") 71 | 72 | ;; ---------------------------------------------------------------------- 73 | 74 | (defvar demo-it--presentation-file "") 75 | (defvar demo-it--presentation-buffer nil) 76 | (defvar demo-it--presentation-prev-settings (make-hash-table)) 77 | 78 | 79 | (defun demo-it-presentation (file &optional size style section) 80 | "Load FILE (org-mode?) as presentation. Start `org-tree-slide' 81 | if available. SIZE specifies the text scale, and defaults to the 82 | value set in `demo-it--text-scale'. 83 | 84 | STYLE can either be `:variable' for variable font pitch, 85 | `:blocks' for diminished headers on org-blocks, or `:both' for 86 | both features. If nil, defaults to the customize variables, 87 | `demo-it--presentation-variable-width' and 88 | `demo-it--presentation-hide-org-blocks'. 89 | 90 | The SECTION is the name of an org-mode header to specify as the 91 | first section to display." 92 | (find-file file) 93 | (setq demo-it--presentation-file file) 94 | (setq demo-it--presentation-buffer (buffer-name)) 95 | 96 | (when (fboundp 'org-tree-slide-mode) 97 | (setq org-tree-slide-heading-emphasis t) 98 | (org-tree-slide-mode)) 99 | 100 | (when section 101 | (demo-it--presentation-section section)) 102 | 103 | ;; Style things up correctly... 104 | (make-local-variable 'demo-it--presentation-prev-settings) 105 | (puthash :emphasis-markers org-hide-emphasis-markers demo-it--presentation-prev-settings) 106 | (setq org-hide-emphasis-markers demo-it--presentation-hide-org-markers) 107 | 108 | ;; Make the display of the org-mode file more presentable 109 | (when (demo-it--presentation-hide-blocks-p style) 110 | (demo-it--presentation-display-set)) 111 | (when (demo-it--presentation-variable-width-p style) 112 | (variable-pitch-mode 1)) 113 | (when demo-it--presentation-hide-mode-line 114 | (demo-it-hide-mode-line)) 115 | (text-scale-set (demo-it--get-text-scale size)) 116 | 117 | (when (fboundp 'org-bullets-mode) 118 | (org-bullets-mode 1)) 119 | (when (fboundp 'flyspell-mode) 120 | (flyspell-mode -1)) 121 | (setq cursor-type nil)) 122 | 123 | (defun demo-it--presentation-display-set () 124 | "Change some typical `org-mode' display values to make more 125 | presentation-friendly. Store the changed values in a hashtable. 126 | See `demo-it--presentation-display-restore'." 127 | ;; Save everything that is interesting into a hash table: 128 | (puthash :restore t demo-it--presentation-prev-settings) 129 | ;; Allow us to resize our images: 130 | (setq org-image-actual-width nil) 131 | (let* ((backgd (face-attribute 'default :background)) 132 | (border (list (list :foreground backgd :background backgd :height 1)))) 133 | (cl-flet ((set-attr (attr values) 134 | (puthash attr 135 | (face-remap-add-relative attr values) 136 | demo-it--presentation-prev-settings))) 137 | (set-attr 'org-block-begin-line border) 138 | (set-attr 'org-block-end-line border) 139 | (set-attr 'org-meta-line border) 140 | (set-attr 'org-special-keyword border) 141 | (set-attr 'org-block '((:family "monospace"))) 142 | (set-attr 'org-verbatim '((:family "monospace"))) 143 | (set-attr 'org-code '((:family "monospace"))) 144 | (set-attr 'org-table '((:family "monospace"))) 145 | (set-attr 'org-special-keyword '((:family "monospace")))))) 146 | 147 | (defun demo-it--presentation-display-restore () 148 | "After `demo-it--presentation-display-set', call to restore previous settings." 149 | (setq org-hide-emphasis-markers 150 | (gethash :emphasis-markers demo-it--presentation-prev-settings)) 151 | (when (gethash :restore demo-it--presentation-prev-settings) 152 | (remhash :restore demo-it--presentation-prev-settings) 153 | (cl-flet ((rest-attr (attr) (face-remap-remove-relative 154 | (gethash attr demo-it--presentation-prev-settings)))) 155 | (mapcar #'rest-attr (list 'org-block-begin-line 'org-block-end-line 'org-block 'org-meta-line 156 | 'org-verbatim 'org-code 'org-table 'org-special-keyword))))) 157 | 158 | ;; Specify a section in the presentation 159 | 160 | (defun demo-it--presentation-section (section) 161 | "Moves the displayed presentation to a SECTION header." 162 | (interactive "s") 163 | (when demo-it--presentation-buffer 164 | (switch-to-buffer demo-it--presentation-buffer) 165 | 166 | (when (fboundp 'org-tree-slide-mode) 167 | (org-tree-slide-content)) 168 | 169 | (goto-char (point-min)) 170 | (re-search-forward (format "^\*+ +%s" section)) 171 | 172 | (when (fboundp 'org-tree-slide-mode) 173 | (org-tree-slide-move-next-tree)))) 174 | 175 | ;; Jumping Back to the Presentation 176 | ;; 177 | ;; In this case, we've been doing some steps, and the screen is 178 | ;; "messed up", calling this function returns back to the 179 | ;; presentation. 180 | 181 | (defun demo-it-presentation-return-noadvance () 182 | "Return to the presentation buffer and delete other windows." 183 | (when demo-it--presentation-buffer 184 | (switch-to-buffer demo-it--presentation-buffer)) 185 | (delete-other-windows)) 186 | 187 | (defun demo-it-presentation-return () 188 | "Return to the presentation buffer, delete other windows, and 189 | advance to the next 'org-mode' section." 190 | (when demo-it--presentation-buffer 191 | (demo-it-presentation-return-noadvance) 192 | (when (fboundp 'org-tree-slide-move-next-tree) 193 | (org-tree-slide-move-next-tree)))) 194 | 195 | ;; Advance Presentation without Changing Focus 196 | ;; 197 | ;; Advances the org-mode presentation, but after popping into that 198 | ;; presentation buffer, returns to the window where our focus was 199 | ;; initially. 200 | 201 | (defun demo-it-presentation-advance () 202 | "Advance the presentation to the next frame (if the buffer is 203 | an `org-mode' and `org-tree-slide' is available), but doesn't 204 | change focus to the window." 205 | (interactive) 206 | (when demo-it--presentation-buffer 207 | (let ((orig-window (current-buffer))) 208 | (switch-to-buffer demo-it--presentation-buffer) 209 | (when (fboundp 'org-tree-slide-move-next-tree) 210 | (org-tree-slide-move-next-tree)) 211 | (switch-to-buffer orig-window)))) 212 | 213 | (defun demo-it-presentation-highlight-phrase (phrase &optional color) 214 | "Highlight a PHRASE (based on a regular expression) in the 215 | presentation buffer. This is useful to highlight bullet point 216 | items while executing appropriate code." 217 | (when demo-it--presentation-buffer 218 | (let ((orig-window (current-buffer)) 219 | (hilite-color (if (null color) 'hi-green-b color))) 220 | (switch-to-buffer demo-it--presentation-buffer) 221 | (hi-lock-unface-buffer t) 222 | (hi-lock-face-phrase-buffer phrase hilite-color) 223 | (switch-to-buffer orig-window)))) 224 | 225 | (define-obsolete-function-alias 'demo-it--presentation-highlight-phrase 226 | 'demo-it-presentation-highlight-phrase "2016-Oct") 227 | 228 | (defun demo-it-presentation-unhighlight-all () 229 | "Remove all highlighted values in a presentation previously set 230 | by a call to `demo-it-presentation-highlight-phrase'." 231 | (when demo-it--presentation-buffer 232 | (let ((orig-window (current-buffer))) 233 | (switch-to-buffer demo-it--presentation-buffer) 234 | (hi-lock-unface-buffer t) 235 | (switch-to-buffer orig-window)))) 236 | 237 | (define-obsolete-function-alias 'demo-it--presentation-unhighlight-all 238 | 'demo-it-presentation-unhighlight-all "2016-Oct") 239 | 240 | ;; Clean up the Presentation 241 | ;; 242 | ;; The org-presentation-start function alters the way an org-mode file 243 | ;; is displayed. This function returns it back to a normal, editable 244 | ;; state. 245 | 246 | (defun demo-it-presentation-quit () 247 | "Undo display settings made to the presentation buffer." 248 | (interactive) 249 | (demo-it--setq-restore) 250 | (when demo-it--presentation-buffer 251 | (switch-to-buffer demo-it--presentation-buffer) 252 | (when (fboundp 'org-tree-slide-mode) 253 | (org-tree-slide-mode -1)) 254 | (when (fboundp 'flyspell-mode) 255 | (flyspell-mode t)) 256 | (setq cursor-type t) 257 | (demo-it--presentation-display-restore) ; Restore previous changes 258 | (variable-pitch-mode 0) 259 | (demo-it-show-mode-line) 260 | (text-scale-set 0))) 261 | 262 | ;; ---------------------------------------------------------------------- 263 | 264 | ;;;###autoload 265 | (defun demo-it-single-presentation (file &optional size style section) 266 | "Demonstration that presents an `org-mode' FILE as a 267 | full-screen presentation. SIZE is the text scaling size, and STYLE is the presentation " 268 | (interactive "fPresentation File: ") 269 | (demo-it-create (demo-it-presentation file size style section)) 270 | (demo-it-start) 271 | 272 | ;; Now that the presentation is going, let's change the mode: 273 | (demo-it-disable-mode) 274 | (demo-it-mode-pres t)) 275 | 276 | (define-minor-mode demo-it-mode-pres "Pressing 'space' advances demo." 277 | :lighter " demo-p" 278 | :require 'demo-it 279 | :global t 280 | :keymap '((" " . demo-it-presentation-advance) 281 | (" " . demo-it-presentation-advance) 282 | ("q" . demo-it-disable-mode) 283 | ("Q" . demo-it-end))) 284 | 285 | (provide 'demo-it-present) 286 | 287 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 288 | ;;; demo-it-present.el ends here 289 | -------------------------------------------------------------------------------- /demo-it-tests.el: -------------------------------------------------------------------------------- 1 | ;;; DEMO-IT-TESTS --- Basic tests to help verify demo-it functions 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright © 2016, Howard Abrams, all rights reserved. 5 | ;; Created: 22 September 2016 6 | ;; 7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 | ;; 9 | ;;; Commentary: 10 | ;; 11 | ;; Obviously testing specific functions is easy with ERT, but 12 | ;; attempting to verify a _visual demonstration_ is a lot more 13 | ;; complicated. 14 | ;; 15 | ;; However, we'll do what we can. 16 | ;; 17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 18 | ;; 19 | ;; This program is free software; you can redistribute it and/or 20 | ;; modify it under the terms of the GNU General Public License as 21 | ;; published by the Free Software Foundation; either version 3, or 22 | ;; (at your option) any later version. 23 | ;; 24 | ;; This program is distributed in the hope that it will be useful, 25 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 | ;; General Public License for more details. 28 | ;; 29 | ;; You should have received a copy of the GNU General Public License 30 | ;; along with this program; see the file COPYING. If not, write to 31 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 32 | ;; Floor, Boston, MA 02110-1301, USA. 33 | ;; 34 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 35 | ;; 36 | ;;; Code: 37 | 38 | (require 'ert) 39 | 40 | (load-file "demo-it.el") 41 | (defvar demo-it--shell-or-eshell) 42 | (defvar demo-it--keymap-mode-style) 43 | (defvar demo-it--insert-text-speed) 44 | (defvar demo-it--start-fullscreen) 45 | (defvar demo-it--start-single-window) 46 | (defvar demo-it--text-scale) 47 | (defvar demo-it--open-windows) 48 | 49 | (declare-function demo-it-create "demo-it") 50 | (declare-function demo-it-start "demo-it") 51 | (declare-function demo-it-end "demo-it") 52 | (declare-function demo-it--set-property "demo-it-custom") 53 | (declare-function demo-it--get-section "demo-it-custom") 54 | (declare-function demo-it--get-insert-text-speed "demo-it-custom") 55 | (declare-function demo-it--get-text-scale "demo-it-custom") 56 | 57 | 58 | (defvar demo-it-tests--state 0) 59 | (defun demo-it-tests--step-1 (&optional state) 60 | "Just an initial step in a demonstration" 61 | (setq demo-it-tests--state (if state state 1))) 62 | (defun demo-it-tests--step-2 () 63 | "Another step in a demonstration" 64 | (setq demo-it-tests--state 2)) 65 | 66 | ;; ---------------------------------------------------------------------- 67 | 68 | (ert-deftest basic-validation () 69 | "Validate first step executes, but not the second." 70 | (setq demo-it-tests--state 0) 71 | (demo-it-create demo-it-tests--step-1 72 | demo-it-tests--step-2) 73 | (demo-it-start) 74 | (demo-it-end) 75 | (should (= 1 demo-it-tests--state))) 76 | 77 | (ert-deftest basic-form-validation () 78 | "Validate first form executes, but not the second." 79 | (demo-it-create (demo-it-tests--step-1 5) 80 | demo-it-tests--step-2) 81 | (setq demo-it-tests--state 0) 82 | (demo-it-start) 83 | (demo-it-end) 84 | (should (= 5 demo-it-tests--state))) 85 | 86 | ;; ---------------------------------------------------------------------- 87 | ;; Let's test some of the property values 88 | 89 | (ert-deftest test-demo-it--get-insert-text-speed () 90 | (demo-it--set-property :insert-fast) 91 | (should (and (= 10 (car (demo-it--get-insert-text-speed))) 92 | (= 100 (cdr (demo-it--get-insert-text-speed))))) 93 | 94 | (demo-it--set-property :insert-medium) 95 | (should (and (= 30 (car (demo-it--get-insert-text-speed))) 96 | (= 500 (cdr (demo-it--get-insert-text-speed))))) 97 | 98 | (demo-it--set-property :insert-slow) 99 | (should (and (= 200 (car (demo-it--get-insert-text-speed))) 100 | (= 1000 (cdr (demo-it--get-insert-text-speed)))))) 101 | 102 | (ert-deftest test-demo-it--get-text-scale () 103 | (demo-it--set-property :text-small) 104 | (should (= -1 (demo-it--get-text-scale))) 105 | (demo-it--set-property :text-normal) 106 | (should (= 0 (demo-it--get-text-scale))) 107 | (demo-it--set-property :text-medium) 108 | (should (= 1 (demo-it--get-text-scale))) 109 | (demo-it--set-property :text-large) 110 | (should (= 2 (demo-it--get-text-scale))) 111 | (demo-it--set-property :text-x-large) 112 | (should (= 3 (demo-it--get-text-scale))) 113 | (demo-it--set-property :text-xx-large) 114 | (should (= 4 (demo-it--get-text-scale))) 115 | (demo-it--set-property :text-huge) 116 | (should (= 5 (demo-it--get-text-scale)))) 117 | 118 | (ert-deftest test-demo-it--get-text-scale-unset () 119 | (should (= -1 (demo-it--get-text-scale :small))) 120 | (should (= -1 (demo-it--get-text-scale :text-small))) 121 | (should (= 0 (demo-it--get-text-scale :normal))) 122 | (should (= 0 (demo-it--get-text-scale :text-normal))) 123 | (should (= 1 (demo-it--get-text-scale :medium))) 124 | (should (= 1 (demo-it--get-text-scale :text-medium))) 125 | (should (= 2 (demo-it--get-text-scale :large))) 126 | (should (= 2 (demo-it--get-text-scale :text-large))) 127 | (should (= 3 (demo-it--get-text-scale :x-large))) 128 | (should (= 3 (demo-it--get-text-scale :text-x-large))) 129 | (should (= 4 (demo-it--get-text-scale :xx-large))) 130 | (should (= 4 (demo-it--get-text-scale :text-xx-large))) 131 | (should (= 5 (demo-it--get-text-scale :huge))) 132 | (should (= 5 (demo-it--get-text-scale :text-huge))) 133 | (should (= 13 (demo-it--get-text-scale 13)))) 134 | 135 | (ert-deftest test-demo-it--set-property () 136 | (demo-it--set-property :simple-mode) 137 | (should (eq :simple-mode demo-it--keymap-mode-style)) 138 | (demo-it--set-property :advance-mode) 139 | (should (eq :advanced-mode demo-it--keymap-mode-style)) 140 | (demo-it--set-property :advanced-mode) 141 | (should (eq :advanced-mode demo-it--keymap-mode-style)) 142 | 143 | (demo-it--set-property :use-shell) 144 | (should (eq :shell demo-it--shell-or-eshell)) 145 | (demo-it--set-property :use-eshell) 146 | (should (eq :eshell demo-it--shell-or-eshell)) 147 | 148 | (demo-it--set-property :windows-below) 149 | (should (eq :below demo-it--open-windows)) 150 | (demo-it--set-property :windows-above) 151 | (should (eq :above demo-it--open-windows)) 152 | (demo-it--set-property :windows-on-side) 153 | (should (eq :right demo-it--open-windows)) 154 | (demo-it--set-property :windows-on-left) 155 | (should (eq :left demo-it--open-windows)) 156 | (demo-it--set-property :windows-on-right) 157 | (should (eq :right demo-it--open-windows)) 158 | 159 | (demo-it--set-property :fullscreen) 160 | (should demo-it--start-fullscreen) 161 | (demo-it--set-property :single-window) 162 | (should demo-it--start-single-window) 163 | 164 | (demo-it--set-property :text-small) 165 | (should (eq -1 demo-it--text-scale)) 166 | (demo-it--set-property :text-normal) 167 | (should (eq 0 demo-it--text-scale)) 168 | (demo-it--set-property :text-medium) 169 | (should (eq 1 demo-it--text-scale)) 170 | (demo-it--set-property :text-large) 171 | (should (eq 2 demo-it--text-scale)) 172 | (demo-it--set-property :text-x-large) 173 | (should (eq 3 demo-it--text-scale)) 174 | (demo-it--set-property :text-xx-large) 175 | (should (eq 4 demo-it--text-scale)) 176 | (demo-it--set-property :text-huge) 177 | (should (eq 5 demo-it--text-scale)) 178 | 179 | (demo-it--set-property :insert-quickly) 180 | (should (eq :instant demo-it--insert-text-speed)) 181 | (demo-it--set-property :insert-fast) 182 | (should (eq :fast demo-it--insert-text-speed)) 183 | (demo-it--set-property :insert-medium) 184 | (should (eq :medium demo-it--insert-text-speed)) 185 | (demo-it--set-property :insert-slow) 186 | (should (eq :slow demo-it--insert-text-speed))) 187 | 188 | (ert-deftest test-demo-it--get-section () 189 | ;; The :char type should return the values given: 190 | (switch-to-buffer "demo-it-tests.el") 191 | (let* ((start 71) 192 | (end 212) 193 | (tuple (demo-it--get-section :char start end))) 194 | (should (and (= (car tuple) start) 195 | (= (cdr tuple) end)))) 196 | 197 | ;; The :line type should return the points of the starting and 198 | ;; ending lines... don't change the comment section at the top of 199 | ;; this file without resetting the magic values: 200 | (let* ((line-1 3) 201 | (line-2 6) 202 | (tuple (demo-it--get-section :line line-1 line-2))) 203 | (should (and (= (car tuple) 71) 204 | (= (cdr tuple) 212))))) 205 | 206 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 207 | ;;; demo-it-tests.el ends here 208 | -------------------------------------------------------------------------------- /demo-it.el: -------------------------------------------------------------------------------- 1 | ;;; demo-it.el --- Create demonstrations 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright (C) 2014 Howard Abrams 5 | ;; Keywords: demonstration presentation test 6 | ;; Version: 2.0.0 7 | ;; 8 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 9 | ;; 10 | ;; This program is free software; you can redistribute it and/or modify 11 | ;; it under the terms of the GNU General Public License as published by 12 | ;; the Free Software Foundation, either version 3 of the License, or 13 | ;; (at your option) any later version. 14 | ;; 15 | ;; This program is distributed in the hope that it will be useful, 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | ;; GNU General Public License for more details. 19 | ;; 20 | ;; You should have received a copy of the GNU General Public License 21 | ;; along with this program. If not, see . 22 | ;; 23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 24 | ;; 25 | ;;; Commentary: 26 | ;; 27 | ;; When making demonstrations of new products, technologies and other 28 | ;; geekery, I love the versatility of using Emacs to demonstrate the 29 | ;; trifecta of sprint reviews, including: 30 | ;; 31 | ;; - Presentations explaining the technologies 32 | ;; - Source code ... correctly highlighted 33 | ;; - Executing the code in Eshell ... or similar demonstration 34 | ;; - Test a new feature 35 | ;; 36 | ;; However, I don't want to fat-finger, mentally burp, or even delay 37 | ;; the gratification while I type, so I predefine each "step" as an 38 | ;; Elisp function or keyboard macro, and then have =demo-it= execute 39 | ;; each function when I hit either the SPACE key or the F12 key 40 | ;; (advanced minor mode). 41 | ;; 42 | ;; Using the library is a four step process: 43 | ;; 44 | ;; 1. Load the library in your own Elisp source code file 45 | ;; 2. Create a collection of functions that "do things". 46 | ;; 3. Create the ordered list of functions/steps with `demo-it-create' 47 | ;; 4. Start the demonstration with `demo-it-start' 48 | ;; 49 | ;; For instance: 50 | ;; 51 | ;; (require 'demo-it) ;; Load this library of functions 52 | ;; 53 | ;; (defun dit-load-source-code () 54 | ;; "Load some source code in a side window." 55 | ;; (demo-it-presentation-advance) 56 | ;; (demo-it-load-fancy-file "example.py" :line 5 12 :side)) 57 | ;; 58 | ;; (defun dit-run-code () 59 | ;; "Execute our source code in an Eshell buffer." 60 | ;; ;; Close other windows and advance the presentation: 61 | ;; (demo-it-presentation-return) 62 | ;; (demo-it-start-shell) 63 | ;; (demo-it-run-in-shell "python example.py Snoopy")) 64 | ;; 65 | ;; (demo-it-create :single-window :insert-slow :full-screen 66 | ;; (demo-it-title-screen "example-title.org") 67 | ;; (demo-it-presentation "example.org") 68 | ;; dit-load-source-code 69 | ;; dit-run-code 70 | ;; (demo-it-run-in-shell "exit" nil :instant)) 71 | ;; 72 | ;; (demo-it-start) 73 | ;; 74 | ;; Each "step" is a series of Elisp functions that "do things". 75 | ;; While this package has a collection of helping functions, the steps 76 | ;; can use any Elisp command to show off a feature. 77 | ;; 78 | ;; I recommend installing these other Emacs packages: 79 | ;; 80 | ;; - https://github.com/takaxp/org-tree-slide 81 | ;; - https://github.com/sabof/org-bullets 82 | ;; - https://github.com/magnars/expand-region.el 83 | ;; - https://github.com/Bruce-Connor/fancy-narrow 84 | ;; 85 | ;; See http://github.com/howardabrams/demo-it for more details and 86 | ;; better examples. You will want to walk through the source code 87 | ;; for all the utility functions. 88 | ;; 89 | ;;; Code: 90 | 91 | (require 'cl-lib) 92 | 93 | ;; Predefined necessary external functions: 94 | (defvar org-image-actual-width) 95 | 96 | ;; And functions from other projects I like to use... 97 | (declare-function eshell-send-input "ext:eshell") 98 | (declare-function show-all "ext:eshell.c") 99 | 100 | ;; Load our 'modules' from other files: 101 | (require 'demo-it-custom) 102 | 103 | ;; And specify the customization variables set in that module: 104 | (defvar demo-it--shell-or-eshell) 105 | (defvar demo-it--keymap-mode-style) 106 | (defvar demo-it--insert-text-speed) 107 | (defvar demo-it--open-windows) 108 | (defvar demo-it--open-windows-size) 109 | (defvar demo-it--text-scale) 110 | (defvar demo-it--start-fullscreen) 111 | (defvar demo-it--start-single-window) 112 | (declare-function demo-it--get-insert-text-speed "demo-it-custom.el") 113 | (declare-function demo-it--get-text-scale "demo-it-custom.el") 114 | (declare-function demo-it--set-property "demo-it-custom.el") 115 | 116 | 117 | ;; ---------------------------------------------------------------------- 118 | ;; MINOR MODES 119 | ;; 120 | ;; We define two styles of minor modes for dealing with special keys 121 | ;; to advance the demonstration along ... a simple uses space and 122 | ;; return, and an 'advanced' mode that requires a special function 123 | ;; key... 124 | 125 | (define-minor-mode demo-it-mode "Pressing 'space' advances demo." 126 | :lighter " demo" 127 | :require 'demo-it 128 | :global t 129 | :keymap '((" " . demo-it-step) 130 | (" " . demo-it-step) 131 | ("[down]" . demo-it-step) 132 | ("[mouse-1]" . demo-it-set-mouse-or-advance) 133 | ([nil mouse-1] . demo-it-step) 134 | ([nil wheel-up] . demo-it-ignore-event) 135 | ([nil wheel-down] . demo-it-ignore-event) 136 | ([nil wheel-left] . demo-it-ignore-event) 137 | ([nil wheel-right] . demo-it-ignore-event) 138 | ("q" . demo-it-disable-mode) 139 | ("Q" . demo-it-end))) 140 | 141 | (define-minor-mode demo-it-mode-adv "Pressing '' advances demo." 142 | :lighter " demo-adv" 143 | :require 'demo-it 144 | :global t 145 | :keymap (let ((map (make-sparse-keymap))) 146 | (define-key map (kbd "") 'demo-it-step) 147 | (define-key map (kbd "s-") 'demo-it-insert-text) 148 | (define-key map (kbd "A-") 'demo-it-insert-text) 149 | (define-key map (kbd "C-") 'demo-it-highlight-dwim) 150 | (define-key map (kbd "M-") 'demo-it-end) 151 | map)) 152 | 153 | ;; Demo Mode 154 | ;; 155 | ;; Allows us to advance to the next step by pressing the 156 | ;; space bar or return. Press the 'q' key to stop the mode. 157 | 158 | (defun demo-it-disable-mode () 159 | "Called when 'q' (or similar key) pressed to disable either the 160 | simple or advanced version of `demo-it-mode'." 161 | (interactive) 162 | (demo-it-mode -1) 163 | (demo-it-mode-adv -1)) 164 | 165 | ;; ---------------------------------------------------------------------- 166 | ;; DEMONSTRATION MAKER 167 | ;; 168 | ;; When we start a demonstration, we would pass in a list of functions 169 | ;; to call for each step, and then call =demo-step= to execute the 170 | ;; first one on the list. 171 | 172 | ;; A "global" variable (shudder) to track state of the demonstration: 173 | (defvar demo-it--step 0 "Stores the current demo 'step' function.") 174 | (defvar demo-it--steps '() "List of functions to be executed in order.") 175 | (defvar demo-it-start-winconf nil 176 | "Window configuration when starting demo. Used to restore 177 | buffer positions after demonstration is complete.") 178 | 179 | ;;;###autoload 180 | (defun demo-it-start (&optional steps advanced-mode) 181 | "Start the current demonstration and kick off the first step. 182 | STEPS is a list of functions or keystrokes to execute. 183 | If nil, the STEPS must be specified by a call to `demo-it-create'. 184 | 185 | The optional ADVANCED-MODE turns on keybindings where 186 | advances the steps instead of Space. This mode is better for 187 | more interactive demonstrations." 188 | (interactive) 189 | (when (or demo-it-mode demo-it-mode-adv) 190 | (error "Do not start new demonstrations DURING demonstration")) 191 | 192 | (setq demo-it-start-winconf (current-window-configuration)) 193 | (setq demo-it--step 0) ;; Reset the step to the beginning 194 | (when steps 195 | (setq demo-it--steps steps)) ;; Store the steps. 196 | 197 | (if (or advanced-mode (eq demo-it--keymap-mode-style :advanced-mode)) 198 | (demo-it-mode-adv t) 199 | (demo-it-mode t)) 200 | 201 | (if demo-it--start-fullscreen 202 | (demo-it-frame-fullscreen)) 203 | (if demo-it--start-single-window 204 | (delete-other-windows)) 205 | 206 | (demo-it-step)) 207 | 208 | ;;;###autoload 209 | (defmacro demo-it-create (&rest forms) 210 | "Create and store an ordered list of steps and configuration 211 | values. The FORMS can be either function names, expressions or 212 | keywords, like `:advanced-mode' and `:variable-width'." 213 | `(progn 214 | (demo-it--set-properties (cl-remove-if-not 'keywordp '(,@forms))) 215 | (setq demo-it--steps (cl-remove-if 'keywordp '(,@forms))))) 216 | 217 | 218 | 219 | (defun demo-it-end () 220 | "End the current demonstration by resetting the values 221 | inflicted on the presentation buffer as well as closing other 222 | windows." 223 | (interactive) 224 | (demo-it-disable-mode) 225 | (demo-it-presentation-quit) 226 | (set-window-configuration demo-it-start-winconf)) 227 | 228 | ;; Next Step 229 | ;; 230 | ;; Hitting the key should be bound to triggering the next step in 231 | ;; the demonstration. 232 | 233 | (defun demo-it-step (&optional step) 234 | "Execute the next step in the current demonstration. Jump to a 235 | particular STEP if the optional parameter is given, i.e. C-6 236 | to run the 6th step." 237 | (interactive "P") 238 | (if step 239 | (setq demo-it--step step) ;; Changing Global state, yay! 240 | (setq demo-it--step (1+ demo-it--step))) 241 | (let 242 | ;; At this point, step is 1-based, and I need it 0-based 243 | ;; and f-step is the function to call for this step... 244 | ((f-step (nth (1- demo-it--step) demo-it--steps))) 245 | (if f-step 246 | (demo-it--execute-step f-step) 247 | (read-event "Demonstration finished. Hit any key to return.") 248 | (demo-it-end)))) 249 | 250 | (defun demo-it-restep () 251 | "Execute the previous step in the current demonstration. 252 | 253 | Useful when the previous step failed, and you want to redo it." 254 | (interactive) 255 | (let 256 | ;; At this point, step is 1-based, and I need it 0-based 257 | ;; and f-step is the function to call for this step... 258 | ((f-step (nth (1- demo-it--step) demo-it--steps))) 259 | (if f-step 260 | (demo-it--execute-step f-step) 261 | (message "Finished the entire demonstration.")))) 262 | 263 | (defun demo-it--execute-step (f-step) 264 | "Executes F-STEP depending on its type, e.g. expression, function, etc." 265 | (condition-case err 266 | (cond ((functionp f-step) (funcall f-step)) 267 | ((listp f-step) (eval f-step)) ; An expression 268 | ((stringp f-step) (execute-kbd-macro (kbd f-step))) 269 | ((keywordp f-step) (demo-it--set-property f-step)) 270 | (t (error "invaid step: %s" f-step))) 271 | (error (read-event (format "Abort the demonstration because of error. Hit any key to return.\n%S" err)) 272 | (demo-it-end)))) 273 | 274 | ;; Position or advance the slide? Depends... 275 | 276 | (defun demo-it-set-mouse-or-advance (evt) 277 | "Advances to the next step if clicked on the right side of any 278 | window, otherwise, it position the point as expected. With EVT, 279 | function can be bound to the mouse click." 280 | (interactive "e") 281 | (if (posn-area (event-start evt)) ;; Clicked in special area? 282 | (demo-it-step) 283 | (let ((col (car (posn-col-row (event-start evt)))) 284 | (wid (window-width (posn-window (event-start evt))))) 285 | (if (> col (- wid 4)) 286 | (demo-it-step) 287 | (mouse-set-point evt))))) 288 | 289 | (defun demo-it-show-step () 290 | "Display the expected function to be run during the next step." 291 | (interactive) 292 | (let ((func (nth demo-it--step demo-it--steps))) 293 | (message "Step: %d - Going to run: %s" demo-it--step func))) 294 | 295 | (defun demo-it-ignore-event (evt) 296 | "Empty function that absorbs the EVT parameter to keep 297 | demonstration from flipping out." 298 | (interactive "P") 299 | (message "")) 300 | 301 | 302 | ;; ---------------------------------------------------------------------- 303 | ;; HIDE MODELINE 304 | ;; 305 | ;; Call the `demo-it-hide-mode-line' when displaying images and 306 | ;; org-mode files displayed as "presentations", so that we aren't 307 | ;; bothered by the sight of the mode. 308 | 309 | (defvar demo-it--old-mode-line nil) 310 | (make-variable-buffer-local 'demo-it--old-mode-line) 311 | 312 | (defun demo-it-hide-mode-line () 313 | "Hide mode line for a particular buffer." 314 | (interactive) 315 | (when mode-line-format 316 | (setq demo-it--old-mode-line mode-line-format) 317 | (setq mode-line-format nil))) 318 | 319 | (defun demo-it-show-mode-line () 320 | "Show mode line for a particular buffer, if it was previously hidden with 'demo-it--hide-mode-line." 321 | (interactive) 322 | (if demo-it--old-mode-line 323 | (setq mode-line-format demo-it--old-mode-line))) 324 | 325 | 326 | ;; ---------------------------------------------------------------------- 327 | ;; SIDE WINDOWS and HELPER FILES 328 | ;; 329 | ;; Typically, we make a side window that is large enough to have some 330 | ;; fun in, as the main window would serve as little more than an 331 | ;; outline or displaying a presentation. 332 | ;; 333 | ;; The `demo-it--make-side-window' function is a helper and 334 | ;; probably won't be called directly, but instead is called by 335 | ;; functions that load a file, image or start a shell... 336 | 337 | (defun demo-it--make-side-window (&optional side size) 338 | "Opens window on the side of the current frame and selects that window. 339 | 340 | SIDE is either `:above', `:below', `:left', `:right', `:side' (a 341 | synonym for `:right') or `:none' (for a window that occupies 342 | the entire frame). Defaults to the value of `demo-it--open-windows' 343 | (A value of `:none' acts as a no-op and doesn't open a window). 344 | 345 | SIZE specifies the width of the window if new window is on the 346 | side, or the height if the window is either `:above' or 347 | `:below'." 348 | ;; Since many functions call this, we need a way to actually /not/ 349 | ;; split the screen, so passing in a `:none' overrides the default. 350 | (when (not (or (eq side 'none) (eq side :none))) 351 | 352 | (select-window (demo-it--new-root-window 353 | (or side demo-it--open-windows) 354 | (or size demo-it--open-windows-size))))) 355 | 356 | ;; Since the `make-side-window' shouldn't be called, it has two 357 | ;; dashes, but to maintain backward compatibility, we make an alias: 358 | (define-obsolete-function-alias 'demo-it-make-side-window 359 | 'demo-it--make-side-window "2016-Oct") 360 | 361 | (defun demo-it--new-root-window (direction size) 362 | "Split the main window in the DIRECTION where DIRECTION is a 363 | symbol with possible values of 'right, 'left, 'above or 'below 364 | and SIZE is the final size of the windows, if the window is split 365 | horizontally (i.e. DIRECTION 'below or 'above) SIZE is assumed to 366 | be the target height otherwise SIZE is assumed to be target 367 | width." 368 | (let* ((dir (pcase direction ;; Create synonyms!? 369 | (:left 'left) 370 | (:right 'right) 371 | (:side 'right) 372 | (:below 'below) 373 | (:above 'above) 374 | (_ direction))) 375 | (new-window (split-window (frame-root-window) nil dir)) 376 | (horizontal (member dir '(right left)))) 377 | (save-excursion 378 | (select-window new-window) 379 | (enlarge-window (- size (if horizontal 380 | (window-width) 381 | (window-height))) 382 | horizontal)) 383 | new-window)) 384 | 385 | (defun demo-it-load-file (file &optional side size width) 386 | "Splits root frame into a window and load FILE into it. 387 | 388 | SIDE can be `:above' or `:below' (for vertical split) or `:left' 389 | or `:right' (`:side' is a synomym for `:right'), or `:none' for 390 | load the file in the current buffer. This defaults to the 391 | customized value of `demo-it--open-windows'. 392 | 393 | SIZE can specify the text font scale, and if `nil', it uses the 394 | value of `demo-it--text-scale'. The WIDTH specifies the size of 395 | this new window, which is either the width of a side window, or 396 | the height if the window is `:above' or `:below'." 397 | (demo-it--make-side-window side width) 398 | (find-file file) 399 | (text-scale-set (demo-it--get-text-scale size))) 400 | 401 | (defun demo-it--get-section (type &optional start end) 402 | "Return tuple of beginning and end of a section of buffer. 403 | 404 | If TYPE is :char or 'char, START and END refers to specific 405 | character positions, but if TYPE is :line or 'line, this returns 406 | the point positions as if START and END are line numbers." 407 | 408 | (cond 409 | ;; LINE ... resets the START and END positions to be character 410 | ;; positions based on the line numbers given. 411 | ((or (eq type :line) (eq type 'line)) 412 | (save-excursion 413 | ;; Re-implementing `goto-line' for the win! 414 | (goto-char (point-min)) (forward-line (1- start)) 415 | (setq start (point)) 416 | (goto-char (point-min)) (end-of-line end) 417 | (setq end (point)))) 418 | 419 | ;; CHAR ... start and end should already be the positions. Unless 420 | ;; START or END are null, in which case, we can assume we are 421 | ;; looking at the end of the buffer. 422 | ((or (eq type :char) (eq type 'char)) 423 | (when (null start) 424 | (setq start (point-min))) 425 | (when (null end) 426 | (setq end (point-max)))) 427 | 428 | ;; REGEXP 429 | ((or (eq type :regex) (eq type :regexp)) 430 | (save-excursion 431 | (goto-char (point-min)) 432 | (re-search-forward start) 433 | (setq start (match-beginning 0)) 434 | (re-search-forward end) 435 | (setq end (match-end 0)))) 436 | 437 | ;; STRING 438 | ((or (eq type :str) (eq type :string)) 439 | (save-excursion 440 | (goto-char (point-min)) 441 | (search-forward start) 442 | (setq start (match-beginning 0)) 443 | (search-forward end) 444 | (setq end (match-end 0))))) 445 | 446 | (cons start end)) 447 | 448 | (defun demo-it-load-part-file (file type start end &optional side size width) 449 | "Splits window and loads FILE, but narrow to particular region. 450 | 451 | If TYPE is set to :line, then START and END refers to the first 452 | and last lines to narrow. If TYPE is set to :char, then START and 453 | END refer to specific character positions. 454 | 455 | See `demo-it-load-file' for an explanation of SIDE and SIZE. 456 | Also see `demo-it-load-fancy-file' for an alternative version." 457 | (demo-it-load-file file side size width) 458 | (let ((positions (demo-it--get-section type start end))) 459 | (narrow-to-region (car positions) (cdr positions)))) 460 | 461 | (defun demo-it-show-image (file &optional side size width) 462 | "Load FILE as image (or any other special file) in another 463 | window without a mode line or fringe. SIDE can be either :side 464 | or :below, and if `nil', the default is to use the value of 465 | `demo-it--open-windows'." 466 | (demo-it-load-file file side size width) 467 | (fringe-mode '(0 . 0)) 468 | (demo-it-hide-mode-line)) 469 | 470 | ;; Compare and Contrast Files 471 | ;; 472 | ;; Places two files next to each other so that you can diff 473 | ;; or at least visually compare them. I suppose that after 474 | ;; they are loaded, you can switch to them with something like: 475 | ;; (pop-to-buffer "example.py") 476 | ;; To further manipulate them. 477 | 478 | (defun demo-it-compare-files (file1 file2 &optional side size) 479 | "Load FILE1 and FILE2 as either two windows on top of each 480 | other on the side of the screen, or two windows below (depending 481 | on the value of SIDE). The SIZE specifies the text scaling of 482 | both buffers." 483 | (if (null side) 484 | (setq side demo-it--open-windows)) 485 | (if (null size) 486 | (setq size demo-it--text-scale)) 487 | 488 | (cl-flet ((open-other-window (file side size) 489 | (if (or (eq side 'below) (eq side :below)) 490 | (split-window-horizontally) 491 | (split-window-below)) 492 | (find-file file) 493 | (text-scale-set (demo-it--get-text-scale size)))) 494 | (demo-it-load-file file2 side size) 495 | (open-other-window file1 side size))) 496 | 497 | ;; ---------------------------------------------------------------------- 498 | ;; SHELL WORK 499 | ;; 500 | ;; Kick off a shell in another window, change to a particular 501 | ;; directory, and automatically run something. 502 | 503 | (defun demo-it--erase-shell-buffer () 504 | "Uses comint-clear-buffer in Emacs >=25, otherwise erase buffer. Better 505 | compatibility with read-only shell-mode prompts" 506 | (let ((inhibit-read-only t)) 507 | (if (and (fboundp 'comint-clear-buffer) 508 | (derived-mode-p 'comint-mode)) 509 | (progn 510 | (comint-clear-buffer) 511 | t) 512 | (erase-buffer)))) 513 | 514 | (defun demo-it-start-shell (&optional directory command name 515 | side size width) 516 | "Start a shell or eshell instance, and change to DIRECTORY to 517 | execute COMMAND. NAME optionally labels the buffer, and defaults 518 | to `Shell'. 519 | 520 | SIDE can be `:above' or `:below' (for vertical split) or `:left' 521 | or `:right' (`:side' is a synomym for `:right'), or `:none' for 522 | load the file in the current buffer. This defaults to the 523 | customized value of `demo-it--open-windows'. 524 | 525 | SIZE can specify the text font scale, and if `nil', it uses the 526 | value of `demo-it--text-scale'. The WIDTH specifies the size of 527 | this new window, which is either the width of a side window, or 528 | the height if the window is `:above' or `:below'." 529 | (let* ((title (demo-it--shell-buffer-name name)) 530 | (des-buf (get-buffer title))) 531 | 532 | (demo-it--make-side-window side width) 533 | (if des-buf 534 | (demo-it--start-shell-reuse title directory) 535 | 536 | ;; Otherwise, create a new shell buffer... 537 | (demo-it--start-shell-new title directory size)) 538 | 539 | (when command 540 | (demo-it-insert-shell command)))) 541 | 542 | (define-obsolete-function-alias 'demo-it-start-eshell 'demo-it-start-shell "2016-Oct") 543 | 544 | (defun demo-it--start-shell-new (title directory size) 545 | "Attempt to create a new shell/eshell with a buffer named TITLE 546 | in a particular DIRECTORY." 547 | (let ((default-directory (or directory 548 | (file-name-directory (buffer-file-name))))) 549 | (cond 550 | ((not (keywordp demo-it--shell-or-eshell)) 551 | (funcall-interactively demo-it--shell-or-eshell title)) 552 | 553 | ((eq demo-it--shell-or-eshell :shell) (shell title)) 554 | (t (progn 555 | (eshell "new-shell") 556 | (rename-buffer title)))) 557 | 558 | (read-only-mode -1) 559 | (text-scale-set (demo-it--get-text-scale size)) 560 | 561 | (unless (demo-it--erase-shell-buffer) 562 | (demo-it-insert-shell "" :instant)))) 563 | 564 | (defun demo-it--start-shell-reuse (title directory) 565 | "Attempt to re-use existing shell/eshell with a buffer named 566 | TITLE in a particular DIRECTORY." 567 | (switch-to-buffer title) 568 | (when directory 569 | (goto-char (point-max)) 570 | (demo-it-insert-shell (format "cd %s" directory) :instant) 571 | (unless (demo-it--erase-shell-buffer) 572 | (demo-it-insert-shell "" :instant)))) 573 | 574 | (defun demo-it--shell-buffer-name (&optional name) 575 | "Return the buffer NAME for the shell or eshell window." 576 | (if name 577 | (concat "Shell: " name) 578 | "Shell")) 579 | 580 | (defun demo-it-insert-shell (command &optional speed) 581 | "Inserts some text in the given shell or eshell. The optional 582 | SPEED overrides the custom, `demo-it--insert-text-speed'." 583 | (demo-it-insert command speed) 584 | (if (eq demo-it--shell-or-eshell :eshell) 585 | (eshell-send-input) 586 | (comint-send-input))) 587 | 588 | (defun demo-it-insert (str &optional speed) 589 | "Insert STR into the current buffer as if you were typing it by hand. 590 | The SPEED (if non-nil) overrides the default value settings of the 591 | `demo-it--insert-text-speed' custom variable." 592 | (let ((timings (demo-it--get-insert-text-speed speed))) 593 | 594 | (if (eq timings :instant) 595 | (insert str) 596 | 597 | (let ((entries (if (stringp str) 598 | (string-to-list str) 599 | str)) 600 | (bottom-limit (car timings)) 601 | (top-limit (cdr timings))) 602 | ;; If we are not inserting instantaneously, then loop over each 603 | ;; character in the string with a random delay based on this range: 604 | (dolist (ch entries) 605 | (insert ch) 606 | (let ((tm (+ (/ bottom-limit 1000.0) 607 | (/ (random top-limit) 1000.0)))) 608 | (sit-for tm))))))) 609 | 610 | (defun demo-it-run-in-shell (command &optional name speed) 611 | "Run shell command COMMAND in a previously initialized Eshell. 612 | If NAME is not specified, it defaults to `Shell'." 613 | (pop-to-buffer (demo-it--shell-buffer-name name)) 614 | (goto-char (point-max)) 615 | (demo-it-insert-shell command speed)) 616 | 617 | (define-obsolete-function-alias 'demo-it-run-in-eshell 'demo-it-run-in-shell "2016-Oct") 618 | (define-obsolete-function-alias 'demo-it-type-in-eshell 'demo-it-run-in-shell "2016-Oct") 619 | 620 | (defun demo-it-show-shell (&optional name side width) 621 | "Show the shell buffer of a given NAME whose buffer may have 622 | been buried and not in visible. Optionally specify the 623 | SIDE (either 'below or 'side) of the screen where the shell 624 | should be shown." 625 | (demo-it--make-side-window side width) 626 | (switch-to-buffer (demo-it--shell-buffer-name name))) 627 | 628 | (define-obsolete-function-alias 'demo-it-show-eshell 'demo-it-show-shell "2016-Oct") 629 | 630 | 631 | ;; TITLE DISPLAY 632 | ;; 633 | ;; Create a file to serve as a "title" as it will be displayed with a 634 | ;; larger-than-life font and make Emacs not look like Emacs. 635 | 636 | (defun demo-it-title-screen (file &optional size) 637 | "Display FILE to serve as the demonstration's title, as it will 638 | be displayed with a larger-than-life font without a mode line, 639 | etc. SIZE specifies the text scale, which ignores the 640 | `demo-it--text-scale' customization setting and defaults to 5x." 641 | (fringe-mode '(0 . 0)) 642 | 643 | (find-file file) 644 | (show-all) 645 | (demo-it-hide-mode-line) 646 | (setq cursor-type nil) 647 | (if (fboundp 'flyspell-mode) 648 | (flyspell-mode -1)) 649 | (variable-pitch-mode 1) 650 | (text-scale-set (or size (demo-it--get-text-scale :huge))) 651 | 652 | ;; Time to brag a wee bit... 653 | (message "† This presentation is running within Emacs.")) 654 | 655 | 656 | ;; ---------------------------------------------------------------------- 657 | ;; DEALING WITH FRAME 658 | ;; 659 | ;; During a demonstration, it might be nice to toggle between 660 | ;; full screen and "regular window" in a programmatic way: 661 | 662 | (defun demo-it-toggle-fullscreen () 663 | "Toggle the frame between full screen and normal size. Only 664 | useful for old versions of Emacs, but this code probably won't 665 | work on them anyway." 666 | (declare (obsolete toggle-frame-fullscreen "2016-Oct")) 667 | (interactive) 668 | (set-frame-parameter 669 | nil 'fullscreen 670 | (when (not (frame-parameter nil 'fullscreen)) 'fullboth))) 671 | 672 | ;; We can force the window to be full screen: 673 | 674 | (defun demo-it-frame-fullscreen () 675 | "Set the frame window to cover the full screen." 676 | (interactive) 677 | (set-frame-parameter nil 'fullscreen 'fullboth)) 678 | 679 | ;; Let's make a right-side frame window: 680 | 681 | (defun demo-it-frame-leftside () 682 | "Set the window frame to be exactly half the physical display 683 | screen, and place it on the left side of the screen. This can be 684 | helpful when showing off some other application." 685 | (declare (obsolete "Really!? You think this is useful?" "2016-Oct")) 686 | (interactive) 687 | (let* ((full-pixels (- (x-display-pixel-width) 16)) 688 | (full-width (/ full-pixels (frame-char-width))) 689 | (dest-width (/ full-width 2))) 690 | (set-frame-parameter nil 'fullscreen nil) 691 | (set-frame-parameter nil 'width dest-width) 692 | (set-frame-parameter nil 'left 0))) 693 | 694 | ;; Temporary variables 695 | ;; 696 | ;; Set variables during a demonstration. 697 | ;; They are restored after the demonstration. 698 | 699 | (defvar demo-it--setq-tempvars (make-hash-table)) 700 | (defvar demo-it--setq-voidvars nil) 701 | (defvar demo-it--setq-nilvars nil) 702 | 703 | (defun demo-it--setq (l) 704 | (cl-case (length l) 705 | (0) 706 | (1 707 | (error "Argument length is odd")) 708 | (t 709 | (let ((name (car l)) 710 | (var (eval (cadr l)))) 711 | (cond ((and (boundp name) (symbol-value name)) 712 | (puthash name (symbol-value name) demo-it--setq-tempvars)) 713 | ((boundp name) 714 | (push name demo-it--setq-nilvars)) 715 | (t 716 | (push name demo-it--setq-voidvars))) 717 | (set name var) 718 | (demo-it--setq (nthcdr 2 l)))))) 719 | 720 | (defmacro demo-it-setq (&rest list) 721 | "Like `setq', but the values are restored to original after the demo. 722 | Actually restored by `demo-it--setq-restore'." 723 | `(demo-it--setq '(,@list))) 724 | 725 | (defmacro demo-it-setq-save (&rest list) 726 | "Saves the original value of a LIST of variables. 727 | 728 | Call `demo-it--setq-restore' to restore the original values of 729 | the variables." 730 | `(mapcar ,(lambda (v) (puthash v (eval v) demo-it--setq-tempvars)) 731 | '(,@list))) 732 | 733 | (defun demo-it--setq-restore () 734 | "Restore values of setting by `demo-it-setq'." 735 | (cl-loop for name being the hash-keys in demo-it--setq-tempvars using (hash-values value) 736 | do (set name value)) 737 | (dolist (name demo-it--setq-nilvars) (set name nil)) 738 | (mapc 'makunbound demo-it--setq-voidvars) 739 | (clrhash demo-it--setq-tempvars) 740 | (setq demo-it--setq-nilvars nil 741 | demo-it--setq-voidvars nil)) 742 | 743 | (defun demo-it--set-properties (l) 744 | "Sets a series of single property values from list, L." 745 | ;; First, save all the customization properties... 746 | (demo-it-setq-save demo-it--keymap-mode-style 747 | demo-it--shell-or-eshell 748 | demo-it--open-windows 749 | demo-it--text-scale 750 | demo-it--start-fullscreen 751 | demo-it--start-single-window 752 | demo-it--insert-text-speed) 753 | ;; Second, set all the new customization properties: 754 | (mapc 'demo-it--set-property l)) 755 | ;; Helper Functions 756 | 757 | (defun demo-it-message-keybinding (key command) 758 | "Display message showing the KEY keybinding and its COMMAND." 759 | (interactive) 760 | (message "Typed: '%s' Command: '%s'" key command)) 761 | 762 | ;; ---------------------------------------------------------------------- 763 | 764 | (require 'demo-it-present) 765 | (require 'demo-it-extras) 766 | 767 | ;; As a final harrah, we need to let other files know how to include 768 | ;; this bad child. 769 | 770 | (provide 'demo-it) 771 | 772 | ;;; demo-it.el ends here 773 | -------------------------------------------------------------------------------- /demo-it.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Demo It 2 | #+AUTHOR: Howard Abrams 3 | #+EMAIL: howard.abrams@gmail.com 4 | #+DATE: 2016 Oct 06 5 | #+DESCRIPTION: This file is used as the basis for the Info documentation 6 | #+OPTIONS: ':t toc:t author:t email:t 7 | #+LANGUAGE: en 8 | #+MACRO: version 2.0 9 | #+MACRO: updated last updated 24 October 2016 10 | 11 | #+TEXINFO_FILENAME: demo-it.info 12 | #+TEXINFO_HEADER: @syncodeindex pg cp 13 | #+TEXINFO_HEADER: @syncodeindex vr cp 14 | 15 | * Basics 16 | 17 | At the end of each sprint, each of us demonstrate our accomplishments. 18 | These reviews often incorporate the following trifecta: 19 | 20 | * Presentations explaining the technology and whatnot 21 | * Source code reviews...correctly highlighted and interactive 22 | * Executing the code in a shell 23 | 24 | During my sprint reviews, I noticed I used my org-mode-formatted 25 | files, eshell and source code buffers... In other words, I was 26 | always in Emacs. However, fat-fingering or mentally burping delayed 27 | the gratification for my audience while I laboriously typed. I 28 | originally solved this problem by predefining each "step" as an 29 | Emacs Lisp function, and then had another function execute each 30 | function when I hit an /advance/ key (=F12=). 31 | 32 | After I had amassed a small army of /helper functions/, I packaged it as 33 | =demo-it=, because I lack the imagination to come up with anything more 34 | clever. 35 | 36 | See the following videos as examples of what can be done: 37 | 38 | * [[http://www.youtube.com/watch?v=B6jfrrwR10k][Emacs: An Introduction for the Curious]] 39 | * [[https://www.youtube.com/watch?v=dljNabciEGg][Literate DevOps Programming]] 40 | * [[http://www.youtube.com/watch?v=3T00X_sNg4Q][Learn You Some Lisp for Great Good]] 41 | 42 | ** Simple Example 43 | #+CINDEX: Basic exmaple 44 | 45 | Using this project is a four step process: 46 | 47 | 1. Load the library in your own Elisp source code file 48 | 2. Create zero or more helper functions that "do things", or use the 49 | functions provided by this project. 50 | 3. Order the functions by calling =(demo-it-create)= 51 | 4. Call =demo-it-start= to begin the fun. 52 | 53 | Press the space for each step, or call =demo-it-end= to end early. 54 | 55 | For instance: 56 | 57 | #+BEGIN_SRC elisp 58 | (require 'demo-it) 59 | 60 | (defun my-demo-step/show-code () 61 | "Helper demo function that displays some source code and 62 | advances the presentation at the same time." 63 | (demo-it-load-file "example/example.py") 64 | (demo-it-presentation-advance)) 65 | 66 | ;; Order the functions and forms for this presentation: 67 | (demo-it-create (demo-it-presentation "example/example.org") 68 | my-demo-step/show-code 69 | demo-it-presentation-return ; close file and advance 70 | (demo-it-run-in-eshell "python example/example.py")) 71 | 72 | (demo-it-start) 73 | #+END_SRC 74 | 75 | ** Step Types 76 | #+PINDEX: demo-it-create 77 | #+CINDEX: Parameters for demo-it-create 78 | 79 | The `demo-it-create' is a macro that stores a single demonstration. 80 | Calling it a second time replaces any previously created demonstrations. 81 | 82 | Each "step" given to the =demo-it-create= macro can be one of the 83 | following: 84 | 85 | - Expression typically calling a helper function, for instance: 86 | #+BEGIN_SRC elisp 87 | (demo-it-presentation "example/example.org") 88 | #+END_SRC 89 | 90 | - Name of a function to call that does multiple actions, for instance: 91 | #+BEGIN_SRC elisp 92 | demo-it-presentation-return 93 | #+END_SRC 94 | 95 | - a string referring to a key-binding to run, for instance: 96 | #+BEGIN_SRC elisp 97 | "C-x C-f example.el " 98 | #+END_SRC 99 | 100 | - a property that affects demonstration behavior, see the 101 | [[Demonstration Options]] or [[Customization]] 102 | 103 | Note: Any Emacs function can be called, either by name or as part 104 | of an expression. These functions can be standard functions, 105 | supplied by this =demo-it= package, or even ones you write. ;-) 106 | 107 | ** Demonstration Options 108 | #+CINDEX: Demonstration Behavior options 109 | 110 | The following list of keywords can be passed to =demo-it-create= to 111 | override various [[Customization]] settings: 112 | 113 | - =:simple-mode= uses mode where space advances demonstration. 114 | - =:advance-mode= uses mode where ~F12~ advances demonstration. 115 | - =:use-shell= chooses a standard =shell= command line interface when 116 | running the [[demo-it-start-shell]] command. 117 | - =:use-shell= chooses to use the built-in Emacs shell, which Emacs 118 | uses find more comfortable when subjected to Windows systems. 119 | - =:eshell= is an alias for =:use-eshell.= 120 | - =:shell= is an alias for =:user-shell=. 121 | - =:windows-on-right= defaults to opening auxiliary windows on the 122 | right side of the frame (see [[Showing Files][demo-it-load-file]] and other helper 123 | functions for examples). 124 | - =:windows-on-side= is an alias for =:windows-on-right=. 125 | - =:windows-on-left= like the above, but defaults to the /left/ side of 126 | the frame. 127 | - =:windows-below= opens other windows at the bottom of the current frame. 128 | - =:windows-above= opens other windows at the top of the current frame. 129 | - =:fullscreen= starts the demonstration with the current frame in fullscreen mode. 130 | - =:single-window= deletes other windows when started, and restores 131 | those windows when the demonstration completes. 132 | - =:text-small= starts presentations and other files in a slightly 133 | smaller font that the current default. Yeah, it seems like a nice 134 | idea to offer it, but I wonder if that is really helpful as a 135 | default for a demonstration. 136 | - =:text-normal= starts presentations and other loaded files in the 137 | default font and size. 138 | - =:text-medium= starts presentations and other loaded files in a 139 | slight larger font size (technically scaled at 1). 140 | - =:text-large= scales presentations and other loaded files at 2. 141 | - =:text-x-large= scales loaded files at 3. 142 | - =:text-xx-large= scales loaded files at 4 ... go figure. 143 | - =:text-huge= scales newly loaded files at 5. Got a big monitor or 144 | very few words, I see. 145 | - =:insert-slow= shell commands (and other calls to [[Inserting Text][demo-it-insert]] 146 | function) are inserted character by character as if a hacker who 147 | never took a typing class in middle school was typing the text. 148 | - =:insert-medium= shell commands and other text are inserted as if a 149 | medium-grade nerd with sufficient typing skills entered them. 150 | - =:insert-fast= shell commands are entered like a typist, but to an 151 | audience with the attention span of a gerbil. 152 | - =:insert-quickly= shell commands are instantly entered, and the 153 | audience is spared the gimmickry of yet-another Emacs feature. 154 | - =:show-mode-line= leaves the mode-line alone for presentations and 155 | files loaded by the demonstration package. 156 | - =:hide-mode-line= hides the mode line so neckbeards pay attention 157 | to your demonstration and quit straining to see what minor modes 158 | you prefer. Still using paredit, I see. 159 | - =:hide-org-markers= hides the asterisks, slashes, and other markup 160 | characters that format text, but still shows the text in bold and 161 | italics. 162 | - =:show-org-markers= displays org-mode presentations as you wrote it. 163 | - =:variable-width= uses a variable width font for presentations 164 | because we want to make the vi users cry. 165 | - =:fixed-width= displays org-mode presentations with your default 166 | monospaced font for ultra nerd cred. You may need this feature if 167 | source code in your presentation. 168 | - =:show-block-headers= Should the =#+begin= and =#+end= markers be 169 | shown? If you are trying to talk about /literate devops/ then, the 170 | answer is yes, show them the way you see them. 171 | - =:hide-block-headers= Hides the =#+begin= and =#+end= markers, but 172 | shows the glorious source code inside. Currently, also shows the 173 | surrounding =#+HEADER= entries, so beware. 174 | 175 | ** Running the Demo 176 | #+PINDEX: demo-it-start 177 | #+CINDEX: Starting Demonstration 178 | 179 | Once the demonstration has been created using ~demo-it-create~, 180 | start it by calling =demo-it-start=, as this will invoke the 181 | first step. 182 | 183 | Typically, pressing the =SPACE= or =RETURN= key will advance to the 184 | next step, but this depends on which of the [[Demo Modes]] was chosen. 185 | 186 | A deprecated version of =demo-it-start= allows you to pass in a list 187 | of the steps, but creating this list can be problematic, so you'll 188 | get more mileage from the =demo-it-create= macro. 189 | 190 | ** Demo Modes 191 | #+CINDEX: Minor modes 192 | 193 | Some demonstrations are so complete that pressing the space bar to 194 | advance to each step is sufficient. However, this project can be 195 | used as a /helper/ where each step merely sets up an environment 196 | where some Emacs feature or source code can be elaborated with 197 | personal prestidigitation. In this case, using the space and return 198 | to advance the demonstration would limit what can be demonstrated manually. 199 | 200 | So =demo-it= contains two minor modes, and starting a 201 | demonstration, one of the following minor mode is chosen. 202 | 203 | The choice is either made by setting the global customization 204 | value, , or by passing the following keyword to =demo-it-create=. 205 | - =:simple-mode= 206 | - =:advance-mode= 207 | 208 | *** demo-it-mode 209 | #+PINDEX: demo-it-mode 210 | 211 | The standard minor mode for demonstrations, has the following key 212 | features: 213 | - ~Space~ or ~Return~ advances to the next demonstration step 214 | - ~q~ turns off this mode, allowing you to type normally. 215 | Call =demo-it-mode= to resume this mode 216 | - ~Q~ ends the demonstration 217 | 218 | Note: In this mode, clicking the mouse on the right-side of the 219 | screen will advance the demonstration, while clicking elsewhere, 220 | repositions the cursor. 221 | 222 | *** demo-it-mode-adv 223 | #+PINDEX: demo-it-mode-adv 224 | 225 | The advanced mode is used when the =demo-it= project simply sets 226 | up an environment, where you want most keys available to enter 227 | commands manually. This mode has the following key features: 228 | 229 | - ~F12~ advances to the next step in the demonstration 230 | - ~M-F12~ ends the demonstration 231 | 232 | Why yes, while called /advanced/ is certainly has limited features. 233 | 234 | * Showing Presentations 235 | #+CINDEX: org-mode Presentations 236 | 237 | This project relies on other projects to do most of the heavy 238 | lifting for using ~org-mode~ files as the basis of a presentation, 239 | especially the [[https://github.com/takaxp/org-tree-slide][org-tree-slide]] project, which displays each section 240 | under a header as the sole contents of a buffer. 241 | 242 | The following functions can be added to your demonstration to 243 | control the display of the presentation. 244 | 245 | ** demo-it-presentation 246 | #+PINDEX: demo-it-presentation 247 | #+CINDEX: Presentations 248 | 249 | (file &optional size style section) 250 | 251 | Loads the given ~org-mode~ file as a presentation. This 252 | automatically calls [[https://github.com/takaxp/org-tree-slide][org-tree-slide]] if available. 253 | 254 | This function takes an optional ~size~ parameter to specifies the 255 | text scale. If ~nil~, this defaults to the value set in 256 | [[demo-it--text-scale]] customization variable. 257 | 258 | The optional ~style~ parameter can be set to either :variable for 259 | variable font pitch, :blocks for diminished headers on org-blocks, 260 | or :both to enable both features. This is a deprecated, legacy 261 | feature, since it is easier and clearer to either use the 262 | customization variables: 263 | - [[demo-it--presentation-variable-width]] 264 | - [[demo-it--presentation-hide-org-blocks]] 265 | 266 | The final parameter, ~section~, is a string containing the name of 267 | an ~org-mode~ header to specify as the first section to display. 268 | 269 | ** demo-it-presentation-quit 270 | #+PINDEX: demo-it-presentation-quit 271 | 272 | Undoes the display settings made to the presentation buffer. 273 | 274 | ** demo-it-presentation-return 275 | #+PINDEX: demo-it-presentation-return 276 | 277 | Makes the last running presentation the current buffer, deletes 278 | other windows, and advances to the next ~org-mode~ section. 279 | 280 | ** demo-it-presentation-return-noadvance 281 | #+PINDEX: demo-it-presentation-return-noadvance 282 | 283 | Similar to calling [[demo-it-presentation-return]] in that the latest 284 | specified presentation becomes the current buffer and all other 285 | windows are deleted. 286 | 287 | However, the presentation is not advanced to the next section. 288 | 289 | ** demo-it-presentation-advance 290 | #+PINDEX: demo-it-presentation-advance 291 | 292 | Advances the currently running presentation to the next section, 293 | but doesn't change focus to the window. Any further commands happen 294 | in the current window. 295 | 296 | This function is useful if a presentation discusses multiple 297 | commands, then you can advance through them while other commands 298 | actually perform the action (like executing commands in a shell). 299 | 300 | As an example, the following demonstration will /live-code/ while the 301 | presentation discusses each part: 302 | 303 | #+BEGIN_SRC elisp 304 | (demo-it-create (demo-it-presentation "elisp-cookbook.org") 305 | (demo-it-load-file "elisp-example.el") 306 | 307 | ; Advance to next section that talks about defun: 308 | demo-it-presentation-advance 309 | 310 | ; Start coding an Emacs Lisp function: 311 | (demo-it-insert "def") ; Begin yasnippet template 312 | "TAB" ; Trigger yasnippet 313 | (demo-it-insert "some-func") ; The function name 314 | "TAB" ; Advance to parameters 315 | (demo-it-insert "x y") ; parameters 316 | "TAB" ; Advance to parameters 317 | (demo-it-insert "Example function.") 318 | "TAB" ; Advance to interactive 319 | (demo-it-insert " ") ; No need for this section 320 | "TAB" ; Advance to function body 321 | 322 | ; Advance to next section to talk about if statements 323 | demo-it-presentation-advance 324 | 325 | (demo-it-insert "if") ; Begin next template 326 | "TAB" ; Trigger yasnippet 327 | (demo-it-insert "(eq x y)") ; predicate expression 328 | "TAB" ; Advance to if body 329 | 330 | ) ;; etc. 331 | #+END_SRC 332 | 333 | ** demo-it-presentation-highlight-phrase 334 | #+PINDEX: demo-it-presentation-highlight-phrase 335 | 336 | Given a string parameter, ~phrase~, as a regular expression, this 337 | function highlights a /phrase/ in the presentation buffer without 338 | changing the current buffer. This is 339 | useful to highlight bullet point items while executing appropriate 340 | code. 341 | 342 | The ~color~ parameter is a face from the ~hi-lock~ project, 343 | e.g. :hi-yellow. 344 | 345 | Note: This unhighlights previous highlighted phrases. 346 | Call ~demo-it-presentation-unhighlight-all~ if you just want to 347 | remove the highlighting. 348 | 349 | ** demo-it-single-presentation 350 | #+PINDEX: demo-it-single-presentation 351 | #+CINDEX: Demonstration with Only Presentation 352 | 353 | Demonstration similar to calling [[demo-it-presentation]], in that it 354 | presents an ~org-mode~ file as a full-screen presentation. In this 355 | form, the demonstration doesn't do anything more than advance 356 | through the presentation, and calling either ~demo-it-create~ or 357 | ~demo-it-start~ is not needed. 358 | 359 | This function begins a minor-mode where the space or return key 360 | advances the presentation to the next section. In this mode, the 361 | ~q~ disables this mode, and ~Q~ quits the demonstration and 362 | presentation. 363 | 364 | While the standard customization variables configure the 365 | presentation display style, this function accepts a ~size~ 366 | parameter to set the text scaling size. 367 | 368 | The optional ~style~ parameter can be set to either :variable for 369 | variable font pitch, :blocks for diminished headers on org-blocks, 370 | or :both to enable both features. 371 | 372 | * Showing Files 373 | #+CINDEX: Showing Side Files 374 | #+CINDEX: Options for side files 375 | 376 | While a simple call to =find-file= is often sufficient to display a 377 | file in Emacs, the following functions can be helpful for showing 378 | files and source code during a demonstration. 379 | 380 | These functions often take the following optional parameters, and in 381 | the spirit of DRY, we will specify them here: 382 | 383 | The optional ~side~ parameter specifies the side of the frame to 384 | display the new window. Acceptable values can one of the following 385 | keywords: 386 | - =:above= 387 | - =:below= 388 | - =:left= 389 | - =:right= 390 | - =:side= is a synomym for =:right= 391 | - =:none= loads the file in the current buffer. 392 | 393 | If ~nil~, defaults is to use the customized value of 394 | [[demo-it--open-windows]]. 395 | 396 | The optional ~size~ parameter takes an integer and specifies the 397 | text scale. If ~nil~, this defaults to the value set in 398 | [[demo-it--text-scale]] customization variable. 399 | 400 | The ~width~ parameter specifies the size of 401 | the new window, which is either the width of a side window, or 402 | the height if the window is =:above= or =:below=. 403 | 404 | ** demo-it-load-file 405 | #+PINDEX: demo-it-load-file 406 | #+CINDEX: Loading side files 407 | Calling this function with a file, first splits the root frame into 408 | a side window and loads the file into that window. 409 | 410 | Keep in mind, that calling it a second time will result in further 411 | splitting of the root window. Call =delete-window= or 412 | [[demo-it-presentation-return-noadvance]], or close the window 413 | while also updating the presentation with [[demo-it-presentation-return]]. 414 | 415 | The optional parameters this function takes are [[Showing Files][described above]]. 416 | 417 | ** demo-it-load-part-file 418 | #+PINDEX: demo-it-load-part-file 419 | #+CINDEX: Show part of a file 420 | 421 | Splits window and loads a file, but also narrows to particular region. 422 | 423 | If the ~type~ parameter is set to =:line=, then the ~start~ and 424 | ~end~ parameters specify the first and last lines of the region to 425 | narrow. If ~type~ is set to =:char=, then ~start~ and ~end~ refer 426 | to specific character positions. 427 | 428 | The other optional parameters this function takes are [[Showing Files][described above]]. 429 | 430 | See [[demo-it-load-fancy-file]] for an alternative version. 431 | 432 | ** demo-it-load-fancy-file 433 | #+CINDEX: demo-it-load-fancy-file 434 | #+PINDEX: Highlighting while showing side file 435 | 436 | Splits the root frame and loads a ~file~ specified by the first 437 | parameter in that window (see [[demo-it-load-file]]), however, this 438 | function can use the 439 | [[https://github.com/Malabarba/fancy-narrow][fancy narrow]] to 440 | highlight part of the buffer (if it has been loaded), otherwise, it 441 | behaves like [[demo-it-load-part-file]] and narrows to the area specified. 442 | 443 | If the second parameter, ~type~ is a string that specifies a 444 | function name (available via ~imenu~), then it highlights 445 | that function. 446 | 447 | If ~type~ is a =:line=, then the next two parameters, ~start~ and ~end~ 448 | specifies the beginning or ending lines. 449 | 450 | If ~type~ is =:char=, then ~start~ and ~end~ are exact buffer 451 | positions, which you can determine by evaluating (~M-;~) the 452 | following expression: 453 | #+BEGIN_SRC elisp 454 | (kill-new (int-to-string (point))) 455 | #+END_SRC 456 | 457 | The optional parameters ~side~ and ~size~ are 458 | [[Showing Files][described above]]. 459 | 460 | Note: This function simply detects if the ~fancy-narrow~ package 461 | has been loaded. The demonstration will need to issue a ~require~. 462 | 463 | ** demo-it-show-image 464 | #+PINDEX: demo-it-show-image 465 | 466 | Loads a file as an image (or any other special file) in another 467 | window without a mode line or fringe. 468 | 469 | The optional parameters this function takes are [[Showing Files][described above]]. 470 | 471 | ** demo-it-compare-files 472 | #+PINDEX: demo-it-compare-files 473 | #+CINDEX: Showing Two Files 474 | 475 | Loads two files in either two windows on top of each other on the 476 | right side of the screen, or two windows below (depending on the 477 | value of the ~side~, which should either be =:below= or =:side=. 478 | 479 | The other optional parameter, ~size~ is [[Showing Files][described above]]. 480 | 481 | * Running Commands 482 | #+CINDEX: Shell Commands 483 | 484 | What Emacs-sponsored demonstration would be complete without being 485 | able to run the application you created. While your demonstration 486 | could easily call ~shell-command~, starting a shell, and having 487 | Emacs /type/ the commands makes a demonstration appear more real and 488 | interactive. 489 | 490 | The /typing/ abilities when inserting text are not very realistic, 491 | as it simply picks a random delay between each letter. What is 492 | lacking, however, it clacking should of the switches going off while 493 | the letter appears (PRs are acceptable). 494 | 495 | The following functions can be added to your demonstration to enter 496 | commands in a shell (both your default shell, as well as the Eshell 497 | is supported by setting the [[demo-it--shell-or-eshell]] variable or 498 | giving =demo-it-create= one of the following keyword configurations: 499 | 500 | - =:use-shell= 501 | - =:use-eshell= 502 | 503 | ** demo-it-start-shell 504 | #+PINDEX: demo-it-start-shell 505 | 506 | Starts a shell or eshell instance, in a particular directory and 507 | executes the given command. The command can be entered into the 508 | shell with a slight random delay intended to mimic a person typing. 509 | This speed of this is specified by [[demo-it--insert-text-speed]]. 510 | 511 | The optional ~name~ parameter labels the buffer, and defaults to 512 | ~Shell~. 513 | 514 | The other optional parameters this function takes are 515 | [[Showing Files][described above]]. 516 | 517 | ** demo-it-run-in-shell 518 | #+PINDEX: demo-it-run-in-shell 519 | #+CINDEX: Typing in Shell 520 | 521 | Run shell command in a shell previously started with 522 | [[demo-it-start-shell]]. If a ~name~ is not specified, it defaults to 523 | name, ~Shell~. 524 | 525 | The optional ~speed~ parameter overrides the customization value 526 | set by [[demo-it--insert-text-speed]], or the text-speed related 527 | keyword given to =demo-it-create=. 528 | 529 | ** demo-it-show-shell 530 | #+PINDEX: demo-it-show-shell 531 | 532 | Call to display the shell buffer if the shell window of a given 533 | ~name~ has been hidden. If ~name~ is not specified, it defaults to 534 | ~Shell~. 535 | 536 | The other optional parameters this function takes are 537 | [[Showing Files][described above]]. 538 | 539 | * Inserting Text 540 | #+PINDEX: demo-it-insert 541 | #+CINDEX: Typing Text into Buffer 542 | 543 | Perhaps you want to regale your audience with your programmatic 544 | prowess, but don't dare attempt to do live-coding in front of live 545 | individuals? Yes, even creating a series of yasnippets can result in 546 | some serious embarrassment (and compiler errors) if you fat-finger 547 | any of the fields. 548 | 549 | Have no fear, just create a series of entries that contains calls to 550 | ~demo-it-insert~, as this function inserts a string into the current 551 | buffer as if you were typing it by hand (this is called by 552 | [[demo-it-run-in-shell]]). 553 | 554 | The following =demo-it= example uses this function as well as 555 | the =def= yasnippet for Ruby and particular keystrokes to move from 556 | field to field: 557 | 558 | #+BEGIN_SRC elisp :results silent 559 | (demo-it-create (find-file "foobar.rb") 560 | (demo-it-insert "def") 561 | (yas-expand) 562 | (demo-it-insert "hello") 563 | "TAB TAB" 564 | (demo-it-insert "name") 565 | "TAB" 566 | (demo-it-insert "\"Hello, #{name}\"" :fast)) 567 | #+END_SRC 568 | 569 | The optional ~speed~ parameter is [[Showing Files][described above]]. 570 | 571 | Note: The previous version of =demo-it= offered specialized 572 | feature for inserting text where each string to entered was put in 573 | a hashmap, ~demo-it-text-entries~, and the entries were inserted 574 | with calls to a dedicated function, ~demo-it-insert-text~. However, 575 | the above seems to work just as well without a special function, so 576 | it has been deprecated and removed. 577 | 578 | * Extra Functions 579 | 580 | The following are useful functions that don't fit in the previous 581 | sections, so consider this the /miscellaeous/ section. 582 | 583 | ** demo-it-end 584 | #+PINDEX: demo-it-end 585 | #+CINDEX: Ending Demonstration 586 | 587 | Calling this command ends the current demonstration by disabling 588 | the mode (see [[Demo Modes]]), resetting the values inflicted on the presentation buffer 589 | as well as restoring the window arrangement to their original glory 590 | before =demo-it-start= was called. 591 | 592 | ** demo-it-step 593 | #+PINDEX: demo-it-step 594 | 595 | This function is typically called by one of the [[Demo Modes]] 596 | to execute the next step in the current demonstration. 597 | 598 | However, this function can be called to jump to a particular STEP 599 | by specifying a step number to the optional parameter, ~step~. This 600 | can also be done with a prefix, e.g. C-6 to run the 6th step. 601 | 602 | Keep in mind that normally step functions expect a particular state 603 | to be established, so calling this function to jump to a particular 604 | step may not work as intended. 605 | 606 | Why yes, we do want to figure out a good mechanism for establishing 607 | a state for each called step, but that be a wee-bit challenging. 608 | 609 | ** demo-it-restep 610 | #+PINDEX: demo-it-restep 611 | #+CINDEX: Redoing Demo Step 612 | 613 | Re-executes the previous step in the current demonstration. 614 | 615 | Note, this doesn't handle the concept of the state of the Emacs 616 | system, so calling this function interactively does not rewind and 617 | re-executes, it just re-executes given the current Emacs state. 618 | 619 | ** demo-it-show-step 620 | #+PINDEX: demo-it-show-step 621 | #+CINDEX: What step am I on? 622 | 623 | Displays a message about the expected function (that is, the 624 | function that /will be run/) during the next step. This can be 625 | useful when you've lost your way, and ask yourself, How did I 626 | get here? 627 | 628 | Of course, you may ask yourself, How do I work this? \\ 629 | And you may ask yourself, Where is that large automobile? \\ 630 | And you may tell yourself, This is not my beautiful house! \\ 631 | And you may tell yourself, This is not my beautiful wife! 632 | 633 | ** demo-it-hide-mode-line 634 | #+PINDEX: demo-it-hide-mode-line 635 | 636 | Hides the mode line for a current buffer. This is done by setting 637 | the ~mode-line-format~ to ~nil~, but also saves off the value so 638 | that it can be restored by calling [[demo-it-show-mode-line]]. 639 | 640 | ** demo-it-show-mode-line 641 | #+PINDEX: demo-it-how-mode-line 642 | 643 | Shows the mode line of the current buffer, if it was previously 644 | hidden with a call to [[demo-it-hide-mode-line]]. 645 | 646 | ** demo-it-title-screen 647 | #+PINDEX: demo-it-title-screen 648 | #+CINDEX: Demonstration Begins 649 | 650 | Displays a file as the demonstration's title, e.g. 651 | displayed with a larger-than-life font without a mode line, 652 | etc. Typically, a specially-formatted org-mode file would do the 653 | job, but any file, including an image will work. 654 | 655 | The ~size~ parameter specifies the text scale, which ignores the 656 | [[demo-it--text-scale]] customization setting and defaults to :huge 657 | (or 5x your normal text font size). 658 | 659 | ** demo-it-message-keybinding 660 | #+PINDEX: demo-it-message-keybinding 661 | #+CINDEX: Showing what you type 662 | 663 | When demonstrating Emacs features, you may want to display the 664 | keystroke you type. Yes, you could (and probably should) use a 665 | package like [[http://www.foldr.org/~michaelw/emacs/mwe-log-commands.el][mwe-log-commands]] by Michael Weber, but you can't 666 | really use that sort of feature with =demo-it=, as you'd just log a 667 | bunch of spacebars bound to [[demo-it-step]]. 668 | 669 | What you really want is to display the key you /wanted/ to type. 670 | For that, you'll want to end your /step function/ with a call to 671 | ~demo-it-message-keybinding~, as it will take two strings, where 672 | the first one is the "key" and the other is a function or command 673 | that it normally calls. 674 | 675 | For instance: 676 | #+BEGIN_SRC elisp 677 | (defun my-demo/dired-a-directory () 678 | "Opens a `dired' buffer on a particular directory. 679 | This is a step function that I add to demo-it-create." 680 | (dired (expand-file-name "~/work")) 681 | (demo-it-message-keybinding "C-x d" "dired")) 682 | #+END_SRC 683 | 684 | This sort of /step function/ would be added to =demo-it-create= as 685 | a simple symbol, like: 686 | #+BEGIN_SRC elisp 687 | (demo-it-create ;; :keybindings 688 | ;; other functions and expressions 689 | my-demo/dired-a-directory 690 | ;; other functions and expressions 691 | ) 692 | #+END_SRC 693 | 694 | ** demo-it-highlight-dwim 695 | #+CINDEX: demo-it-highlight-dwim 696 | #+PINDEX: Text highlighting 697 | 698 | Can use the [[https://github.com/Malabarba/fancy-narrow][fancy-narrow]] package to highlight a particular 699 | /section/. If the package is not available, it simply /narrows/ to that 700 | area. If called interactively, this highlights the region (if 701 | active) or the current function. 702 | 703 | If the first parameter, ~type-or-fn~ is a string, this specifies 704 | the name of a function to highlight. 705 | 706 | If it is a =:line=, then the next two parameters, ~start~ and ~end~ 707 | specifies the beginning or ending lines. 708 | 709 | If it is =:char=, then ~start~ and ~end~ are exact buffer 710 | positions, which you can determine by evaluating (~M-;~) the 711 | following expression: 712 | #+BEGIN_SRC elisp 713 | (kill-new (int-to-string (point))) 714 | #+END_SRC 715 | 716 | If ~type-or-fn~ is ~nil~ and the region is active, highlight the 717 | region. 718 | 719 | If none of the following match, simply select the function the 720 | point is currently in. 721 | 722 | Note: While this function checks to see if the package is 723 | available and loaded, it does not actually do the loading (or the 724 | installing of the package), for that, you will need to do something 725 | like: 726 | 727 | #+BEGIN_SRC elisp 728 | (require 'fancy-narrow) 729 | #+END_SRC 730 | 731 | * Customization 732 | :PROPERTIES: 733 | :APPENDIX: t 734 | :END: 735 | #+CINDEX: Demonstration Customizations 736 | 737 | The following is a list of custom variables that can be set through 738 | the standard Emacs customization feature (under the =demo-it= group). 739 | Note, each custom value may be overridden with a magic symbol to the 740 | [[Step Types][demo-it-create]] macro or with a parameter to many functions. 741 | 742 | ** demo-it--keymap-mode-style 743 | #+PINDEX: demo-it--keymap-mode-style 744 | #+CINDEX: Defaults for advancing demo 745 | 746 | The keymap-specific minor mode to use when a demonstration 747 | starts. Should either be set to the symbol, =:simple-mode= for using 748 | the space to advance to next step and ~q~ to exit the demonstration, 749 | or =:advanced-mode=, where ~F12~ advances. 750 | 751 | Defaults to =:simple-mode= 752 | 753 | This setting can be overridden by a keyword to =demo-it-create=: 754 | - =:simple-mode= 755 | - =:advanced-mode= 756 | 757 | ** demo-it--shell-or-eshell 758 | #+PINDEX: demo-it--shell-or-eshell 759 | 760 | When opening up a shell, this customization value specifies whether 761 | it should run the =shell= or =eshell= command. 762 | 763 | Should be set to one of the following keywords: 764 | - =:shell= 765 | - =:eshell= 766 | 767 | Defaults to =:eshell= 768 | 769 | This setting can be overridden by the following keywords to 770 | =demo-it-create= macro: 771 | - =:use-eshell= 772 | - =:use-shell= 773 | 774 | ** demo-it--open-windows 775 | #+PINDEX: demo-it--open-windows 776 | #+CINDEX: Side Windows 777 | 778 | When opening side windows, split the frame on a particular side. 779 | Should be set to one of the following keywords: 780 | 781 | - =:above= 782 | - =:below= 783 | - =:left= 784 | - =:right= 785 | 786 | The keyword, =:side= is a synonym for =:right=. 787 | 788 | Defaults to =:right= 789 | 790 | This setting can be overridden by one of the following keywords 791 | passed to =demo-it-create=: 792 | - =:windows-on-side= 793 | - =:windows-on-right= 794 | - =:windows-on-left= 795 | - =:windows-below= 796 | - =:windows-above= 797 | 798 | ** demo-it--open-windows-size 799 | #+PINDEX: demo-it--open-windows-size 800 | #+CINDEX: Side Windows Size 801 | 802 | The size of side windows to open. This is the width if the window 803 | is opened on one of the sides (=:left= or =:right=), or the height 804 | if the window is opened =:above= or =:below=. 805 | 806 | Defaults to =80= 807 | 808 | ** demo-it--text-scale 809 | #+PINDEX: demo-it--text-scale 810 | #+CINDEX: Side Windows Font Size 811 | 812 | Sets the default text scale when opening files in side windows (see 813 | [[demo-it--open-windows]]). While this can be set to an integer, it 814 | can also be set to one of the following keywords: 815 | - =:small=, set to a text scale of -1 816 | - =:normal=, set to a text scale of 0 817 | - =:medium=, set to a text scale of 1 818 | - =:large=, set to a text scale of 2 819 | - =:x-large=, set to a text scale of 3 820 | - =:xx-large=, set to a text scale of 4 821 | - =:huge=, set to a text scale of 5 822 | 823 | It defaults to =:large= (a =text-scale-set= value of =2=). 824 | 825 | This customization value can be overridden with one of the 826 | following keywords passed to =demo-it-create=: 827 | - =:text-small= 828 | - =:text-normal= 829 | - =:text-medium= 830 | - =:text-large= 831 | - =:text-x-large= 832 | - =:text-xx-large= 833 | - =:text-huge= 834 | 835 | ** demo-it--start-fullscreen 836 | #+PINDEX: demo-it--start-fullscreen 837 | 838 | A boolean setting that if set to a non-nil value, demonstrations 839 | start with the current frame in fullscreen mode. Defaults to 840 | =false=. 841 | 842 | This customization value can be overridden with =:fullscreen= 843 | keyword passed to =demo-it-create=. 844 | 845 | ** demo-it--start-single-window 846 | #+PINDEX: demo-it--start-single-window 847 | 848 | A boolean setting that if non-nil, deletes other windows to start 849 | the demonstration with a current buffer window being the only 850 | displayed window. Defaults to =t=. 851 | 852 | This customization value can be overridden with =:single-window= 853 | keyword passed to =demo-it-create=. 854 | 855 | ** demo-it--presentation-hide-mode-line 856 | #+PINDEX: demo-it--presentation-hide-mode-line 857 | 858 | If set to a nil value (/false/), the mode-line is hidden for any 859 | presentation files (this doesn't affect other files opened with the 860 | [[demo-it-load-file]]). Defaults to =t=. 861 | 862 | This customization value can be overridden with either of the 863 | following keywords passed to =demo-it-create=: 864 | - =:show-mode-line= 865 | - =:hide-mode-line= 866 | 867 | ** demo-it--presentation-hide-org-markers 868 | #+PINDEX: demo-it--presentation-hide-org-markers 869 | 870 | If set to a non-nil value, surrounding asterisks, underlines and 871 | slashes that define an ~org-mode~ textual formats in a presentation 872 | are displayed. Otherwise those characters hidden, even though the 873 | effects of bolding and italics are still shown. Defaults to =t=. 874 | 875 | This customization value can be overridden with either of the 876 | following keywords passed to =demo-it-create=: 877 | - =:show-org-markers= 878 | - =:hide-org-markers= 879 | 880 | ** demo-it--presentation-variable-width 881 | #+PINDEX: demo-it--presentation-variable-width 882 | 883 | If set to a non-nil value, a /variable-width/ font is used when 884 | displaying ~org-mode~ presentation files, otherwise the standard 885 | fixed-width font is used. Defaults to =nil=. 886 | 887 | This customization value can be overridden with either of the 888 | following keywords passed to =demo-it-create=: 889 | - =:variable-width= 890 | - =:fixed-width= 891 | 892 | ** demo-it--presentation-hide-org-blocks 893 | #+PINDEX: demo-it--presentation-hide-org-blocks 894 | 895 | If set to a non-nil value, the start and ending lines of ~org-mode~ 896 | blocks are shown during a presentation, otherwise these lines are 897 | hidden, but the contents within the blocks are still shown. 898 | 899 | This currently only hides these lines: 900 | #+BEGIN_EXAMPLE 901 | ,#+BEGIN_SRC 902 | ... 903 | ,#+END_SRC 904 | #+END_EXAMPLE 905 | 906 | Other surrounding header values, like =#+HEADERS:= may still be seen. 907 | 908 | This defaults to =t=, however, this customization value can be 909 | overridden with either of the following keywords passed to 910 | =demo-it-create=: 911 | - =:show-block-headers= 912 | - =:hide-block-headers= 913 | 914 | ** demo-it--insert-text-speed 915 | #+PINDEX: demo-it--insert-text-speed 916 | 917 | The functions, [[demo-it-run-in-shell]], [[demo-it-start-shell]], 918 | and [[Inserting Text][demo-it-insert]], enters the text into the shell as if a human 919 | were typing it. This value specifies the speed at which that text 920 | is inserted into the shell. 921 | 922 | This can set to one of the following keywords: 923 | - =:instant= to insert text with no delay 924 | - =:slow= 925 | - =:medium= 926 | - =:fast= 927 | 928 | Defaults to =:medium=. 929 | 930 | This can also specify a tuple of two integer values for the random 931 | number of milliseconds between those two values to delay before 932 | inserting each character, for instance, the =:medium= delay has a 933 | lower value of 30 milliseconds, and an upper delay of 500. 934 | 935 | * Copying 936 | :PROPERTIES: 937 | :COPYING: t 938 | :END: 939 | #+CINDEX: Open Source License 940 | 941 | This manual is for =demo-it= (version {{{version}}}, 942 | {{{updated}}}), a project for running demonstrations within Emacs. 943 | 944 | Copyright @@texinfo:@copyright{}@@ 2016, Howard Abrams 945 | 946 | #+BEGIN_QUOTE 947 | Permission is granted to copy, distribute and/or modify this 948 | document under the terms of the GNU Free Documentation License, 949 | Version 1.3 or any later version published by the Free Software 950 | Foundation; with no Invariant Sections, with no Front-Cover Texts, 951 | and with no Back-Cover Texts. A copy of the license is included in 952 | the section entitled "GNU Free Documentation License". 953 | #+END_QUOTE 954 | 955 | #+TEXINFO_DIR_CATEGORY: Emacs 956 | #+TEXINFO_DIR_TITLE: Demo It: (demo-it) 957 | #+TEXINFO_DIR_DESC: Demonstrations made and shown in Emacs 958 | 959 | * Index 960 | :PROPERTIES: 961 | :INDEX: cp 962 | :END: 963 | 964 | For those of you trying to read this online, this index is generated 965 | and only available within Emacs. If you are reading this from within 966 | Emacs, well-done. 967 | -------------------------------------------------------------------------------- /demo-it.texi: -------------------------------------------------------------------------------- 1 | \input texinfo @c -*- texinfo -*- 2 | @c %**start of header 3 | @setfilename demo-it.info 4 | @settitle Demo It 5 | @documentencoding UTF-8 6 | @documentlanguage en 7 | @syncodeindex pg cp 8 | @syncodeindex vr cp 9 | @c %**end of header 10 | 11 | @copying 12 | @cindex Open Source License 13 | 14 | This manual is for @verb{~demo-it~} (version 2.0, 15 | last updated 24 October 2016), a project for running demonstrations within Emacs. 16 | 17 | Copyright @copyright{} 2016, Howard Abrams 18 | 19 | @quotation 20 | Permission is granted to copy, distribute and/or modify this 21 | document under the terms of the GNU Free Documentation License, 22 | Version 1.3 or any later version published by the Free Software 23 | Foundation; with no Invariant Sections, with no Front-Cover Texts, 24 | and with no Back-Cover Texts. A copy of the license is included in 25 | the section entitled ``GNU Free Documentation License''. 26 | @end quotation 27 | @end copying 28 | 29 | @dircategory Emacs 30 | @direntry 31 | * Demo It: (demo-it). Demonstrations made and shown in Emacs. 32 | @end direntry 33 | 34 | @finalout 35 | @titlepage 36 | @title Demo It 37 | @author Howard Abrams (@email{howard.abrams@@gmail.com}) 38 | @page 39 | @vskip 0pt plus 1filll 40 | @insertcopying 41 | @end titlepage 42 | 43 | @contents 44 | 45 | @ifnottex 46 | @node Top 47 | @top Demo It 48 | @insertcopying 49 | @end ifnottex 50 | 51 | @menu 52 | * Basics:: 53 | * Showing Presentations:: 54 | * Showing Files:: 55 | * Running Commands:: 56 | * Inserting Text:: 57 | * Extra Functions:: 58 | * Customization:: 59 | * Index:: 60 | 61 | @detailmenu 62 | --- The Detailed Node Listing --- 63 | 64 | Basics 65 | 66 | * Simple Example:: 67 | * Step Types:: 68 | * Demonstration Options:: 69 | * Running the Demo:: 70 | * Demo Modes:: 71 | 72 | 73 | 74 | 75 | 76 | Demo Modes 77 | 78 | * demo-it-mode:: 79 | * demo-it-mode-adv:: 80 | 81 | Showing Presentations 82 | 83 | * demo-it-presentation:: 84 | * demo-it-presentation-quit:: 85 | * demo-it-presentation-return:: 86 | * demo-it-presentation-return-noadvance:: 87 | * demo-it-presentation-advance:: 88 | * demo-it-presentation-highlight-phrase:: 89 | * demo-it-single-presentation:: 90 | 91 | 92 | 93 | Showing Files 94 | 95 | * demo-it-load-file:: 96 | * demo-it-load-part-file:: 97 | * demo-it-load-fancy-file:: 98 | * demo-it-show-image:: 99 | * demo-it-compare-files:: 100 | 101 | 102 | 103 | Running Commands 104 | 105 | * demo-it-start-shell:: 106 | * demo-it-run-in-shell:: 107 | * demo-it-show-shell:: 108 | 109 | 110 | 111 | 112 | Extra Functions 113 | 114 | * demo-it-end:: 115 | * demo-it-step:: 116 | * demo-it-restep:: 117 | * demo-it-show-step:: 118 | * demo-it-hide-mode-line:: 119 | * demo-it-show-mode-line:: 120 | * demo-it-title-screen:: 121 | * demo-it-message-keybinding:: 122 | * demo-it-highlight-dwim:: 123 | 124 | 125 | 126 | Customization 127 | 128 | * demo-it--keymap-mode-style:: 129 | * demo-it--shell-or-eshell:: 130 | * demo-it--open-windows:: 131 | * demo-it--open-windows-size:: 132 | * demo-it--text-scale:: 133 | * demo-it--start-fullscreen:: 134 | * demo-it--start-single-window:: 135 | * demo-it--presentation-hide-mode-line:: 136 | * demo-it--presentation-hide-org-markers:: 137 | * demo-it--presentation-variable-width:: 138 | * demo-it--presentation-hide-org-blocks:: 139 | * demo-it--insert-text-speed:: 140 | @end detailmenu 141 | @end menu 142 | 143 | 144 | 145 | @node Basics 146 | @unnumbered Basics 147 | 148 | At the end of each sprint, each of us demonstrate our accomplishments. 149 | These reviews often incorporate the following trifecta: 150 | 151 | @itemize 152 | @item 153 | Presentations explaining the technology and whatnot 154 | @item 155 | Source code reviews@dots{}correctly highlighted and interactive 156 | @item 157 | Executing the code in a shell 158 | @end itemize 159 | 160 | During my sprint reviews, I noticed I used my org-mode-formatted 161 | files, eshell and source code buffers@dots{} In other words, I was 162 | always in Emacs. However, fat-fingering or mentally burping delayed 163 | the gratification for my audience while I laboriously typed. I 164 | originally solved this problem by predefining each ``step'' as an 165 | Emacs Lisp function, and then had another function execute each 166 | function when I hit an @emph{advance} key (@verb{~F12~}). 167 | 168 | After I had amassed a small army of @emph{helper functions}, I packaged it as 169 | @verb{~demo-it~}, because I lack the imagination to come up with anything more 170 | clever. 171 | 172 | See the following videos as examples of what can be done: 173 | 174 | @itemize 175 | @item 176 | @uref{http://www.youtube.com/watch?v=B6jfrrwR10k,Emacs: An Introduction for the Curious} 177 | @item 178 | @uref{https://www.youtube.com/watch?v=dljNabciEGg,Literate DevOps Programming} 179 | @item 180 | @uref{http://www.youtube.com/watch?v=3T00X_sNg4Q,Learn You Some Lisp for Great Good} 181 | @end itemize 182 | 183 | @menu 184 | * Simple Example:: 185 | * Step Types:: 186 | * Demonstration Options:: 187 | * Running the Demo:: 188 | * Demo Modes:: 189 | @end menu 190 | 191 | @node Simple Example 192 | @unnumberedsec Simple Example 193 | 194 | @cindex Basic exmaple 195 | 196 | Using this project is a four step process: 197 | 198 | @enumerate 199 | @item 200 | Load the library in your own Elisp source code file 201 | @item 202 | Create zero or more helper functions that ``do things'', or use the 203 | functions provided by this project. 204 | @item 205 | Order the functions by calling @verb{~(demo-it-create)~} 206 | @item 207 | Call @verb{~demo-it-start~} to begin the fun. 208 | @end enumerate 209 | 210 | Press the space for each step, or call @verb{~demo-it-end~} to end early. 211 | 212 | For instance: 213 | 214 | @lisp 215 | (require 'demo-it) 216 | 217 | (defun my-demo-step/show-code () 218 | "Helper demo function that displays some source code and 219 | advances the presentation at the same time." 220 | (demo-it-load-side-window "example/example.py") 221 | (demo-it-presentation-advance)) 222 | 223 | ;; Order the functions and forms for this presentation: 224 | (demo-it-create (demo-it-presentation "example/example.org") 225 | my-demo-step/show-code 226 | demo-it-presentation-return ; close file and advance 227 | (demo-it-run-in-eshell "python example/example.py")) 228 | 229 | (demo-it-start) 230 | @end lisp 231 | 232 | @node Step Types 233 | @unnumberedsec Step Types 234 | 235 | @pindex demo-it-create 236 | @cindex Parameters for demo-it-create 237 | 238 | The `demo-it-create' is a macro that stores a single demonstration. 239 | Calling it a second time replaces any previously created demonstrations. 240 | 241 | Each ``step'' given to the @verb{~demo-it-create~} macro can be one of the 242 | following: 243 | 244 | @itemize 245 | @item 246 | Expression typically calling a helper function, for instance: 247 | @lisp 248 | (demo-it-presentation "example/example.org") 249 | @end lisp 250 | 251 | @item 252 | Name of a function to call that does multiple actions, for instance: 253 | @lisp 254 | demo-it-presentation-return 255 | @end lisp 256 | 257 | @item 258 | a string referring to a key-binding to run, for instance: 259 | @lisp 260 | "C-x C-f example.el " 261 | @end lisp 262 | 263 | @item 264 | a property that affects demonstration behavior, see the 265 | @ref{Demonstration Options,Demonstration Options} or @ref{Customization,Customization} 266 | @end itemize 267 | 268 | Note: Any Emacs function can be called, either by name or as part 269 | of an expression. These functions can be standard functions, 270 | supplied by this @verb{~demo-it~} package, or even ones you write. ;-) 271 | 272 | @node Demonstration Options 273 | @unnumberedsec Demonstration Options 274 | 275 | @cindex Demonstration Behavior options 276 | 277 | The following list of keywords can be passed to @verb{~demo-it-create~} to 278 | override various @ref{Customization,Customization} settings: 279 | 280 | @itemize 281 | @item 282 | @verb{~:simple-mode~} uses mode where space advances demonstration. 283 | @item 284 | @verb{~:advance-mode~} uses mode where @code{F12} advances demonstration. 285 | @item 286 | @verb{~:use-shell~} chooses a standard @verb{~shell~} command line interface when 287 | running the @ref{demo-it-start-shell,demo-it-start-shell} command. 288 | @item 289 | @verb{~:use-shell~} chooses to use the built-in Emacs shell, which Emacs 290 | uses find more comfortable when subjected to Windows systems. 291 | @item 292 | @verb{~:eshell~} is an alias for @verb{~:use-eshell.~} 293 | @item 294 | @verb{~:shell~} is an alias for @verb{~:user-shell~}. 295 | @item 296 | @verb{~:windows-on-right~} defaults to opening auxiliary windows on the 297 | right side of the frame (see @ref{Showing Files,demo-it-load-file} and other helper 298 | functions for examples). 299 | @item 300 | @verb{~:windows-on-side~} is an alias for @verb{~:windows-on-right~}. 301 | @item 302 | @verb{~:windows-on-left~} like the above, but defaults to the @emph{left} side of 303 | the frame. 304 | @item 305 | @verb{~:windows-below~} opens other windows at the bottom of the current frame. 306 | @item 307 | @verb{~:windows-above~} opens other windows at the top of the current frame. 308 | @item 309 | @verb{~:fullscreen~} starts the demonstration with the current frame in fullscreen mode. 310 | @item 311 | @verb{~:single-window~} deletes other windows when started, and restores 312 | those windows when the demonstration completes. 313 | @item 314 | @verb{~:text-small~} starts presentations and other files in a slightly 315 | smaller font that the current default. Yeah, it seems like a nice 316 | idea to offer it, but I wonder if that is really helpful as a 317 | default for a demonstration. 318 | @item 319 | @verb{~:text-normal~} starts presentations and other loaded files in the 320 | default font and size. 321 | @item 322 | @verb{~:text-medium~} starts presentations and other loaded files in a 323 | slight larger font size (technically scaled at 1). 324 | @item 325 | @verb{~:text-large~} scales presentations and other loaded files at 2. 326 | @item 327 | @verb{~:text-x-large~} scales loaded files at 3. 328 | @item 329 | @verb{~:text-xx-large~} scales loaded files at 4 @dots{} go figure. 330 | @item 331 | @verb{~:text-huge~} scales newly loaded files at 5. Got a big monitor or 332 | very few words, I see. 333 | @item 334 | @verb{~:insert-slow~} shell commands (and other calls to @ref{Inserting Text,demo-it-insert} 335 | function) are inserted character by character as if a hacker who 336 | never took a typing class in middle school was typing the text. 337 | @item 338 | @verb{~:insert-medium~} shell commands and other text are inserted as if a 339 | medium-grade nerd with sufficient typing skills entered them. 340 | @item 341 | @verb{~:insert-fast~} shell commands are entered like a typist, but to an 342 | audience with the attention span of a gerbil. 343 | @item 344 | @verb{~:insert-quickly~} shell commands are instantly entered, and the 345 | audience is spared the gimmickry of yet-another Emacs feature. 346 | @item 347 | @verb{~:show-mode-line~} leaves the mode-line alone for presentations and 348 | files loaded by the demonstration package. 349 | @item 350 | @verb{~:hide-mode-line~} hides the mode line so neckbeards pay attention 351 | to your demonstration and quit straining to see what minor modes 352 | you prefer. Still using paredit, I see. 353 | @item 354 | @verb{~:hide-org-markers~} hides the asterisks, slashes, and other markup 355 | characters that format text, but still shows the text in bold and 356 | italics. 357 | @item 358 | @verb{~:show-org-markers~} displays org-mode presentations as you wrote it. 359 | @item 360 | @verb{~:variable-width~} uses a variable width font for presentations 361 | because we want to make the vi users cry. 362 | @item 363 | @verb{~:fixed-width~} displays org-mode presentations with your default 364 | monospaced font for ultra nerd cred. You may need this feature if 365 | source code in your presentation. 366 | @item 367 | @verb{~:show-block-headers~} Should the @verb{~#+begin~} and @verb{~#+end~} markers be 368 | shown? If you are trying to talk about @emph{literate devops} then, the 369 | answer is yes, show them the way you see them. 370 | @item 371 | @verb{~:hide-block-headers~} Hides the @verb{~#+begin~} and @verb{~#+end~} markers, but 372 | shows the glorious source code inside. Currently, also shows the 373 | surrounding @verb{~#+HEADER~} entries, so beware. 374 | @end itemize 375 | 376 | @node Running the Demo 377 | @unnumberedsec Running the Demo 378 | 379 | @pindex demo-it-start 380 | @cindex Starting Demonstration 381 | 382 | Once the demonstration has been created using @code{demo-it-create}, 383 | start it by calling @verb{~demo-it-start~}, as this will invoke the 384 | first step. 385 | 386 | Typically, pressing the @verb{~SPACE~} or @verb{~RETURN~} key will advance to the 387 | next step, but this depends on which of the @ref{Demo Modes,Demo Modes} was chosen. 388 | 389 | A deprecated version of @verb{~demo-it-start~} allows you to pass in a list 390 | of the steps, but creating this list can be problematic, so you'll 391 | get more mileage from the @verb{~demo-it-create~} macro. 392 | 393 | @node Demo Modes 394 | @unnumberedsec Demo Modes 395 | 396 | @cindex Minor modes 397 | 398 | Some demonstrations are so complete that pressing the space bar to 399 | advance to each step is sufficient. However, this project can be 400 | used as a @emph{helper} where each step merely sets up an environment 401 | where some Emacs feature or source code can be elaborated with 402 | personal prestidigitation. In this case, using the space and return 403 | to advance the demonstration would limit what can be demonstrated manually. 404 | 405 | So @verb{~demo-it~} contains two minor modes, and starting a 406 | demonstration, one of the following minor mode is chosen. 407 | 408 | The choice is either made by setting the global customization 409 | value, , or by passing the following keyword to @verb{~demo-it-create~}. 410 | @itemize 411 | @item 412 | @verb{~:simple-mode~} 413 | @item 414 | @verb{~:advance-mode~} 415 | @end itemize 416 | 417 | @menu 418 | * demo-it-mode:: 419 | * demo-it-mode-adv:: 420 | @end menu 421 | 422 | @node demo-it-mode 423 | @unnumberedsubsec demo-it-mode 424 | 425 | @pindex demo-it-mode 426 | 427 | The standard minor mode for demonstrations, has the following key 428 | features: 429 | @itemize 430 | @item 431 | @code{Space} or @code{Return} advances to the next demonstration step 432 | @item 433 | @code{q} turns off this mode, allowing you to type normally. 434 | Call @verb{~demo-it-mode~} to resume this mode 435 | @item 436 | @code{Q} ends the demonstration 437 | @end itemize 438 | 439 | Note: In this mode, clicking the mouse on the right-side of the 440 | screen will advance the demonstration, while clicking elsewhere, 441 | repositions the cursor. 442 | 443 | @node demo-it-mode-adv 444 | @unnumberedsubsec demo-it-mode-adv 445 | 446 | @pindex demo-it-mode-adv 447 | 448 | The advanced mode is used when the @verb{~demo-it~} project simply sets 449 | up an environment, where you want most keys available to enter 450 | commands manually. This mode has the following key features: 451 | 452 | @itemize 453 | @item 454 | @code{F12} advances to the next step in the demonstration 455 | @item 456 | @code{M-F12} ends the demonstration 457 | @end itemize 458 | 459 | Why yes, while called @emph{advanced} is certainly has limited features. 460 | 461 | @node Showing Presentations 462 | @unnumbered Showing Presentations 463 | 464 | @cindex org-mode Presentations 465 | 466 | This project relies on other projects to do most of the heavy 467 | lifting for using @code{org-mode} files as the basis of a presentation, 468 | especially the @uref{https://github.com/takaxp/org-tree-slide,org-tree-slide} project, which displays each section 469 | under a header as the sole contents of a buffer. 470 | 471 | The following functions can be added to your demonstration to 472 | control the display of the presentation. 473 | 474 | @menu 475 | * demo-it-presentation:: 476 | * demo-it-presentation-quit:: 477 | * demo-it-presentation-return:: 478 | * demo-it-presentation-return-noadvance:: 479 | * demo-it-presentation-advance:: 480 | * demo-it-presentation-highlight-phrase:: 481 | * demo-it-single-presentation:: 482 | @end menu 483 | 484 | @node demo-it-presentation 485 | @unnumberedsec demo-it-presentation 486 | 487 | @pindex demo-it-presentation 488 | @cindex Presentations 489 | 490 | (file &optional size style section) 491 | 492 | Loads the given @code{org-mode} file as a presentation. This 493 | automatically calls @uref{https://github.com/takaxp/org-tree-slide,org-tree-slide} if available. 494 | 495 | This function takes an optional @code{size} parameter to specifies the 496 | text scale. If @code{nil}, this defaults to the value set in 497 | @ref{demo-it--text-scale,demo-it--text-scale} customization variable. 498 | 499 | The optional @code{style} parameter can be set to either :variable for 500 | variable font pitch, :blocks for diminished headers on org-blocks, 501 | or :both to enable both features. This is a deprecated, legacy 502 | feature, since it is easier and clearer to either use the 503 | customization variables: 504 | @itemize 505 | @item 506 | @ref{demo-it--presentation-variable-width,demo-it--presentation-variable-width} 507 | @item 508 | @ref{demo-it--presentation-hide-org-blocks,demo-it--presentation-hide-org-blocks} 509 | @end itemize 510 | 511 | The final parameter, @code{section}, is a string containing the name of 512 | an @code{org-mode} header to specify as the first section to display. 513 | 514 | @node demo-it-presentation-quit 515 | @unnumberedsec demo-it-presentation-quit 516 | 517 | @pindex demo-it-presentation-quit 518 | 519 | Undoes the display settings made to the presentation buffer. 520 | 521 | @node demo-it-presentation-return 522 | @unnumberedsec demo-it-presentation-return 523 | 524 | @pindex demo-it-presentation-return 525 | 526 | Makes the last running presentation the current buffer, deletes 527 | other windows, and advances to the next @code{org-mode} section. 528 | 529 | @node demo-it-presentation-return-noadvance 530 | @unnumberedsec demo-it-presentation-return-noadvance 531 | 532 | @pindex demo-it-presentation-return-noadvance 533 | 534 | Similar to calling @ref{demo-it-presentation-return,demo-it-presentation-return} in that the latest 535 | specified presentation becomes the current buffer and all other 536 | windows are deleted. 537 | 538 | However, the presentation is not advanced to the next section. 539 | 540 | @node demo-it-presentation-advance 541 | @unnumberedsec demo-it-presentation-advance 542 | 543 | @pindex demo-it-presentation-advance 544 | 545 | Advances the currently running presentation to the next section, 546 | but doesn't change focus to the window. Any further commands happen 547 | in the current window. 548 | 549 | This function is useful if a presentation discusses multiple 550 | commands, then you can advance through them while other commands 551 | actually perform the action (like executing commands in a shell). 552 | 553 | As an example, the following demonstration will @emph{live-code} while the 554 | presentation discusses each part: 555 | 556 | @lisp 557 | (demo-it-create (demo-it-presentation "elisp-cookbook.org") 558 | (demo-it-load-file "elisp-example.el") 559 | 560 | ; Advance to next section that talks about defun: 561 | demo-it-presentation-advance 562 | 563 | ; Start coding an Emacs Lisp function: 564 | (demo-it-insert "def") ; Begin yasnippet template 565 | "TAB" ; Trigger yasnippet 566 | (demo-it-insert "some-func") ; The function name 567 | "TAB" ; Advance to parameters 568 | (demo-it-insert "x y") ; parameters 569 | "TAB" ; Advance to parameters 570 | (demo-it-insert "Example function.") 571 | "TAB" ; Advance to interactive 572 | (demo-it-insert " ") ; No need for this section 573 | "TAB" ; Advance to function body 574 | 575 | ; Advance to next section to talk about if statements 576 | demo-it-presentation-advance 577 | 578 | (demo-it-insert "if") ; Begin next template 579 | "TAB" ; Trigger yasnippet 580 | (demo-it-insert "(eq x y)") ; predicate expression 581 | "TAB" ; Advance to if body 582 | 583 | ) ;; etc. 584 | @end lisp 585 | 586 | @node demo-it-presentation-highlight-phrase 587 | @unnumberedsec demo-it-presentation-highlight-phrase 588 | 589 | @pindex demo-it-presentation-highlight-phrase 590 | 591 | Given a string parameter, @code{phrase}, as a regular expression, this 592 | function highlights a @emph{phrase} in the presentation buffer without 593 | changing the current buffer. This is 594 | useful to highlight bullet point items while executing appropriate 595 | code. 596 | 597 | The @code{color} parameter is a face from the @code{hi-lock} project, 598 | e.g. :hi-yellow. 599 | 600 | Note: This unhighlights previous highlighted phrases. 601 | Call @code{demo-it-presentation-unhighlight-all} if you just want to 602 | remove the highlighting. 603 | 604 | @node demo-it-single-presentation 605 | @unnumberedsec demo-it-single-presentation 606 | 607 | @pindex demo-it-single-presentation 608 | @cindex Demonstration with Only Presentation 609 | 610 | Demonstration similar to calling @ref{demo-it-presentation,demo-it-presentation}, in that it 611 | presents an @code{org-mode} file as a full-screen presentation. In this 612 | form, the demonstration doesn't do anything more than advance 613 | through the presentation, and calling either @code{demo-it-create} or 614 | @code{demo-it-start} is not needed. 615 | 616 | This function begins a minor-mode where the space or return key 617 | advances the presentation to the next section. In this mode, the 618 | @code{q} disables this mode, and @code{Q} quits the demonstration and 619 | presentation. 620 | 621 | While the standard customization variables configure the 622 | presentation display style, this function accepts a @code{size} 623 | parameter to set the text scaling size. 624 | 625 | The optional @code{style} parameter can be set to either :variable for 626 | variable font pitch, :blocks for diminished headers on org-blocks, 627 | or :both to enable both features. 628 | 629 | @node Showing Files 630 | @unnumbered Showing Files 631 | 632 | @cindex Showing Side Files 633 | @cindex Options for side files 634 | 635 | While a simple call to @verb{~find-file~} is often sufficient to display a 636 | file in Emacs, the following functions can be helpful for showing 637 | files and source code during a demonstration. 638 | 639 | These functions often take the following optional parameters, and in 640 | the spirit of DRY, we will specify them here: 641 | 642 | The optional @code{side} parameter specifies the side of the frame to 643 | display the new window. Acceptable values can one of the following 644 | keywords: 645 | @itemize 646 | @item 647 | @verb{~:above~} 648 | @item 649 | @verb{~:below~} 650 | @item 651 | @verb{~:left~} 652 | @item 653 | @verb{~:right~} 654 | @item 655 | @verb{~:side~} is a synomym for @verb{~:right~} 656 | @item 657 | @verb{~:none~} loads the file in the current buffer. 658 | @end itemize 659 | 660 | If @code{nil}, defaults is to use the customized value of 661 | @ref{demo-it--open-windows,demo-it--open-windows}. 662 | 663 | The optional @code{size} parameter takes an integer and specifies the 664 | text scale. If @code{nil}, this defaults to the value set in 665 | @ref{demo-it--text-scale,demo-it--text-scale} customization variable. 666 | 667 | The @code{width} parameter specifies the size of 668 | the new window, which is either the width of a side window, or 669 | the height if the window is @verb{~:above~} or @verb{~:below~}. 670 | 671 | @menu 672 | * demo-it-load-file:: 673 | * demo-it-load-part-file:: 674 | * demo-it-load-fancy-file:: 675 | * demo-it-show-image:: 676 | * demo-it-compare-files:: 677 | @end menu 678 | 679 | @node demo-it-load-file 680 | @unnumberedsec demo-it-load-file 681 | 682 | @pindex demo-it-load-file 683 | @cindex Loading side files 684 | Calling this function with a file, first splits the root frame into 685 | a side window and loads the file into that window. 686 | 687 | Keep in mind, that calling it a second time will result in further 688 | splitting of the root window. Call @verb{~delete-window~} or 689 | @ref{demo-it-presentation-return-noadvance,demo-it-presentation-return-noadvance}, or close the window 690 | while also updating the presentation with @ref{demo-it-presentation-return,demo-it-presentation-return}. 691 | 692 | The optional parameters this function takes are @ref{Showing Files,described above}. 693 | 694 | @node demo-it-load-part-file 695 | @unnumberedsec demo-it-load-part-file 696 | 697 | @pindex demo-it-load-part-file 698 | @cindex Show part of a file 699 | 700 | Splits window and loads a file, but also narrows to particular region. 701 | 702 | If the @code{type} parameter is set to @verb{~:line~}, then the @code{start} and 703 | @code{end} parameters specify the first and last lines of the region to 704 | narrow. If @code{type} is set to @verb{~:char~}, then @code{start} and @code{end} refer 705 | to specific character positions. 706 | 707 | The other optional parameters this function takes are @ref{Showing Files,described above}. 708 | 709 | See @ref{demo-it-load-fancy-file,demo-it-load-fancy-file} for an alternative version. 710 | 711 | @node demo-it-load-fancy-file 712 | @unnumberedsec demo-it-load-fancy-file 713 | 714 | @cindex demo-it-load-fancy-file 715 | @pindex Highlighting while showing side file 716 | 717 | Splits the root frame and loads a @code{file} specified by the first 718 | parameter in that window (see @ref{demo-it-load-file,demo-it-load-file}), however, this 719 | function can use the 720 | @uref{https://github.com/Malabarba/fancy-narrow,fancy narrow} to 721 | highlight part of the buffer (if it has been loaded), otherwise, it 722 | behaves like @ref{demo-it-load-part-file,demo-it-load-part-file} and narrows to the area specified. 723 | 724 | If the second parameter, @code{type} is a string that specifies a 725 | function name (available via @code{imenu}), then it highlights 726 | that function. 727 | 728 | If @code{type} is a @verb{~:line~}, then the next two parameters, @code{start} and @code{end} 729 | specifies the beginning or ending lines. 730 | 731 | If @code{type} is @verb{~:char~}, then @code{start} and @code{end} are exact buffer 732 | positions, which you can determine by evaluating (@code{M-;}) the 733 | following expression: 734 | @lisp 735 | (kill-new (int-to-string (point))) 736 | @end lisp 737 | 738 | The optional parameters @code{side} and @code{size} are 739 | @ref{Showing Files,described above}. 740 | 741 | Note: This function simply detects if the @code{fancy-narrow} package 742 | has been loaded. The demonstration will need to issue a @code{require}. 743 | 744 | @node demo-it-show-image 745 | @unnumberedsec demo-it-show-image 746 | 747 | @pindex demo-it-show-image 748 | 749 | Loads a file as an image (or any other special file) in another 750 | window without a mode line or fringe. 751 | 752 | The optional parameters this function takes are @ref{Showing Files,described above}. 753 | 754 | @node demo-it-compare-files 755 | @unnumberedsec demo-it-compare-files 756 | 757 | @pindex demo-it-compare-files 758 | @cindex Showing Two Files 759 | 760 | Loads two files in either two windows on top of each other on the 761 | right side of the screen, or two windows below (depending on the 762 | value of the @code{side}, which should either be @verb{~:below~} or @verb{~:side~}. 763 | 764 | The other optional parameter, @code{size} is @ref{Showing Files,described above}. 765 | 766 | @node Running Commands 767 | @unnumbered Running Commands 768 | 769 | @cindex Shell Commands 770 | 771 | What Emacs-sponsored demonstration would be complete without being 772 | able to run the application you created. While your demonstration 773 | could easily call @code{shell-command}, starting a shell, and having 774 | Emacs @emph{type} the commands makes a demonstration appear more real and 775 | interactive. 776 | 777 | The @emph{typing} abilities when inserting text are not very realistic, 778 | as it simply picks a random delay between each letter. What is 779 | lacking, however, it clacking should of the switches going off while 780 | the letter appears (PRs are acceptable). 781 | 782 | The following functions can be added to your demonstration to enter 783 | commands in a shell (both your default shell, as well as the Eshell 784 | is supported by setting the @ref{demo-it--shell-or-eshell,demo-it--shell-or-eshell} variable or 785 | giving @verb{~demo-it-create~} one of the following keyword configurations: 786 | 787 | @itemize 788 | @item 789 | @verb{~:use-shell~} 790 | @item 791 | @verb{~:use-eshell~} 792 | @end itemize 793 | 794 | @menu 795 | * demo-it-start-shell:: 796 | * demo-it-run-in-shell:: 797 | * demo-it-show-shell:: 798 | @end menu 799 | 800 | @node demo-it-start-shell 801 | @unnumberedsec demo-it-start-shell 802 | 803 | @pindex demo-it-start-shell 804 | 805 | Starts a shell or eshell instance, in a particular directory and 806 | executes the given command. The command can be entered into the 807 | shell with a slight random delay intended to mimic a person typing. 808 | This speed of this is specified by @ref{demo-it--insert-text-speed,demo-it--insert-text-speed}. 809 | 810 | The optional @code{name} parameter labels the buffer, and defaults to 811 | @code{Shell}. 812 | 813 | The other optional parameters this function takes are 814 | @ref{Showing Files,described above}. 815 | 816 | @node demo-it-run-in-shell 817 | @unnumberedsec demo-it-run-in-shell 818 | 819 | @pindex demo-it-run-in-shell 820 | @cindex Typing in Shell 821 | 822 | Run shell command in a shell previously started with 823 | @ref{demo-it-start-shell,demo-it-start-shell}. If a @code{name} is not specified, it defaults to 824 | name, @code{Shell}. 825 | 826 | The optional @code{speed} parameter overrides the customization value 827 | set by @ref{demo-it--insert-text-speed,demo-it--insert-text-speed}, or the text-speed related 828 | keyword given to @verb{~demo-it-create~}. 829 | 830 | @node demo-it-show-shell 831 | @unnumberedsec demo-it-show-shell 832 | 833 | @pindex demo-it-show-shell 834 | 835 | Call to display the shell buffer if the shell window of a given 836 | @code{name} has been hidden. If @code{name} is not specified, it defaults to 837 | @code{Shell}. 838 | 839 | The other optional parameters this function takes are 840 | @ref{Showing Files,described above}. 841 | 842 | @node Inserting Text 843 | @unnumbered Inserting Text 844 | 845 | @pindex demo-it-insert 846 | @cindex Typing Text into Buffer 847 | 848 | Perhaps you want to regale your audience with your programmatic 849 | prowess, but don't dare attempt to do live-coding in front of live 850 | individuals? Yes, even creating a series of yasnippets can result in 851 | some serious embarrassment (and compiler errors) if you fat-finger 852 | any of the fields. 853 | 854 | Have no fear, just create a series of entries that contains calls to 855 | @code{demo-it-insert}, as this function inserts a string into the current 856 | buffer as if you were typing it by hand (this is called by 857 | @ref{demo-it-run-in-shell,demo-it-run-in-shell}). 858 | 859 | The following @verb{~demo-it~} example uses this function as well as 860 | the @verb{~def~} yasnippet for Ruby and particular keystrokes to move from 861 | field to field: 862 | 863 | @lisp 864 | (demo-it-create (find-file "foobar.rb") 865 | (demo-it-insert "def") 866 | (yas-expand) 867 | (demo-it-insert "hello") 868 | "TAB TAB" 869 | (demo-it-insert "name") 870 | "TAB" 871 | (demo-it-insert "\"Hello, #@{name@}\"" :fast)) 872 | @end lisp 873 | 874 | The optional @code{speed} parameter is @ref{Showing Files,described above}. 875 | 876 | Note: The previous version of @verb{~demo-it~} offered specialized 877 | feature for inserting text where each string to entered was put in 878 | a hashmap, @code{demo-it-text-entries}, and the entries were inserted 879 | with calls to a dedicated function, @code{demo-it-insert-text}. However, 880 | the above seems to work just as well without a special function, so 881 | it has been deprecated and removed. 882 | 883 | @node Extra Functions 884 | @unnumbered Extra Functions 885 | 886 | The following are useful functions that don't fit in the previous 887 | sections, so consider this the @emph{miscellaeous} section. 888 | 889 | @menu 890 | * demo-it-end:: 891 | * demo-it-step:: 892 | * demo-it-restep:: 893 | * demo-it-show-step:: 894 | * demo-it-hide-mode-line:: 895 | * demo-it-show-mode-line:: 896 | * demo-it-title-screen:: 897 | * demo-it-message-keybinding:: 898 | * demo-it-highlight-dwim:: 899 | @end menu 900 | 901 | @node demo-it-end 902 | @unnumberedsec demo-it-end 903 | 904 | @pindex demo-it-end 905 | @cindex Ending Demonstration 906 | 907 | Calling this command ends the current demonstration by disabling 908 | the mode (see @ref{Demo Modes,Demo Modes}), resetting the values inflicted on the presentation buffer 909 | as well as restoring the window arrangement to their original glory 910 | before @verb{~demo-it-start~} was called. 911 | 912 | @node demo-it-step 913 | @unnumberedsec demo-it-step 914 | 915 | @pindex demo-it-step 916 | 917 | This function is typically called by one of the @ref{Demo Modes,Demo Modes} 918 | to execute the next step in the current demonstration. 919 | 920 | However, this function can be called to jump to a particular STEP 921 | by specifying a step number to the optional parameter, @code{step}. This 922 | can also be done with a prefix, e.g. C-6 to run the 6th step. 923 | 924 | Keep in mind that normally step functions expect a particular state 925 | to be established, so calling this function to jump to a particular 926 | step may not work as intended. 927 | 928 | Why yes, we do want to figure out a good mechanism for establishing 929 | a state for each called step, but that be a wee-bit challenging. 930 | 931 | @node demo-it-restep 932 | @unnumberedsec demo-it-restep 933 | 934 | @pindex demo-it-restep 935 | @cindex Redoing Demo Step 936 | 937 | Re-executes the previous step in the current demonstration. 938 | 939 | Note, this doesn't handle the concept of the state of the Emacs 940 | system, so calling this function interactively does not rewind and 941 | re-executes, it just re-executes given the current Emacs state. 942 | 943 | @node demo-it-show-step 944 | @unnumberedsec demo-it-show-step 945 | 946 | @pindex demo-it-show-step 947 | @cindex What step am I on? 948 | 949 | Displays a message about the expected function (that is, the 950 | function that @emph{will be run}) during the next step. This can be 951 | useful when you've lost your way, and ask yourself, How did I 952 | get here? 953 | 954 | Of course, you may ask yourself, How do I work this? @* 955 | And you may ask yourself, Where is that large automobile? @* 956 | And you may tell yourself, This is not my beautiful house! @* 957 | And you may tell yourself, This is not my beautiful wife! 958 | 959 | @node demo-it-hide-mode-line 960 | @unnumberedsec demo-it-hide-mode-line 961 | 962 | @pindex demo-it-hide-mode-line 963 | 964 | Hides the mode line for a current buffer. This is done by setting 965 | the @code{mode-line-format} to @code{nil}, but also saves off the value so 966 | that it can be restored by calling @ref{demo-it-show-mode-line,demo-it-show-mode-line}. 967 | 968 | @node demo-it-show-mode-line 969 | @unnumberedsec demo-it-show-mode-line 970 | 971 | @pindex demo-it-how-mode-line 972 | 973 | Shows the mode line of the current buffer, if it was previously 974 | hidden with a call to @ref{demo-it-hide-mode-line,demo-it-hide-mode-line}. 975 | 976 | @node demo-it-title-screen 977 | @unnumberedsec demo-it-title-screen 978 | 979 | @pindex demo-it-title-screen 980 | @cindex Demonstration Begins 981 | 982 | Displays a file as the demonstration's title, e.g. 983 | displayed with a larger-than-life font without a mode line, 984 | etc. Typically, a specially-formatted org-mode file would do the 985 | job, but any file, including an image will work. 986 | 987 | The @code{size} parameter specifies the text scale, which ignores the 988 | @ref{demo-it--text-scale,demo-it--text-scale} customization setting and defaults to :huge 989 | (or 5x your normal text font size). 990 | 991 | @node demo-it-message-keybinding 992 | @unnumberedsec demo-it-message-keybinding 993 | 994 | @pindex demo-it-message-keybinding 995 | @cindex Showing what you type 996 | 997 | When demonstrating Emacs features, you may want to display the 998 | keystroke you type. Yes, you could (and probably should) use a 999 | package like @uref{http://www.foldr.org/~michaelw/emacs/mwe-log-commands.el,mwe-log-commands} by Michael Weber, but you can't 1000 | really use that sort of feature with @verb{~demo-it~}, as you'd just log a 1001 | bunch of spacebars bound to @ref{demo-it-step,demo-it-step}. 1002 | 1003 | What you really want is to display the key you @emph{wanted} to type. 1004 | For that, you'll want to end your @emph{step function} with a call to 1005 | @code{demo-it-message-keybinding}, as it will take two strings, where 1006 | the first one is the ``key'' and the other is a function or command 1007 | that it normally calls. 1008 | 1009 | For instance: 1010 | @lisp 1011 | (defun my-demo/dired-a-directory () 1012 | "Opens a `dired' buffer on a particular directory. 1013 | This is a step function that I add to demo-it-create." 1014 | (dired (expand-file-name "~/work")) 1015 | (demo-it-message-keybinding "C-x d" "dired")) 1016 | @end lisp 1017 | 1018 | This sort of @emph{step function} would be added to @verb{~demo-it-create~} as 1019 | a simple symbol, like: 1020 | @lisp 1021 | (demo-it-create ;; :keybindings 1022 | ;; other functions and expressions 1023 | my-demo/dired-a-directory 1024 | ;; other functions and expressions 1025 | ) 1026 | @end lisp 1027 | 1028 | @node demo-it-highlight-dwim 1029 | @unnumberedsec demo-it-highlight-dwim 1030 | 1031 | @cindex demo-it-highlight-dwim 1032 | @pindex Text highlighting 1033 | 1034 | Can use the @uref{https://github.com/Malabarba/fancy-narrow,fancy-narrow} package to highlight a particular 1035 | @emph{section}. If the package is not available, it simply @emph{narrows} to that 1036 | area. If called interactively, this highlights the region (if 1037 | active) or the current function. 1038 | 1039 | If the first parameter, @code{type-or-fn} is a string, this specifies 1040 | the name of a function to highlight. 1041 | 1042 | If it is a @verb{~:line~}, then the next two parameters, @code{start} and @code{end} 1043 | specifies the beginning or ending lines. 1044 | 1045 | If it is @verb{~:char~}, then @code{start} and @code{end} are exact buffer 1046 | positions, which you can determine by evaluating (@code{M-;}) the 1047 | following expression: 1048 | @lisp 1049 | (kill-new (int-to-string (point))) 1050 | @end lisp 1051 | 1052 | If @code{type-or-fn} is @code{nil} and the region is active, highlight the 1053 | region. 1054 | 1055 | If none of the following match, simply select the function the 1056 | point is currently in. 1057 | 1058 | Note: While this function checks to see if the package is 1059 | available and loaded, it does not actually do the loading (or the 1060 | installing of the package), for that, you will need to do something 1061 | like: 1062 | 1063 | @lisp 1064 | (require 'fancy-narrow) 1065 | @end lisp 1066 | 1067 | @node Customization 1068 | @appendix Customization 1069 | 1070 | @cindex Demonstration Customizations 1071 | 1072 | The following is a list of custom variables that can be set through 1073 | the standard Emacs customization feature (under the @verb{~demo-it~} group). 1074 | Note, each custom value may be overridden with a magic symbol to the 1075 | @ref{Step Types,demo-it-create} macro or with a parameter to many functions. 1076 | 1077 | @menu 1078 | * demo-it--keymap-mode-style:: 1079 | * demo-it--shell-or-eshell:: 1080 | * demo-it--open-windows:: 1081 | * demo-it--open-windows-size:: 1082 | * demo-it--text-scale:: 1083 | * demo-it--start-fullscreen:: 1084 | * demo-it--start-single-window:: 1085 | * demo-it--presentation-hide-mode-line:: 1086 | * demo-it--presentation-hide-org-markers:: 1087 | * demo-it--presentation-variable-width:: 1088 | * demo-it--presentation-hide-org-blocks:: 1089 | * demo-it--insert-text-speed:: 1090 | @end menu 1091 | 1092 | @node demo-it--keymap-mode-style 1093 | @unnumberedsec demo-it--keymap-mode-style 1094 | 1095 | @pindex demo-it--keymap-mode-style 1096 | @cindex Defaults for advancing demo 1097 | 1098 | The keymap-specific minor mode to use when a demonstration 1099 | starts. Should either be set to the symbol, @verb{~:simple-mode~} for using 1100 | the space to advance to next step and @code{q} to exit the demonstration, 1101 | or @verb{~:advanced-mode~}, where @code{F12} advances. 1102 | 1103 | Defaults to @verb{~:simple-mode~} 1104 | 1105 | This setting can be overridden by a keyword to @verb{~demo-it-create~}: 1106 | @itemize 1107 | @item 1108 | @verb{~:simple-mode~} 1109 | @item 1110 | @verb{~:advanced-mode~} 1111 | @end itemize 1112 | 1113 | @node demo-it--shell-or-eshell 1114 | @unnumberedsec demo-it--shell-or-eshell 1115 | 1116 | @pindex demo-it--shell-or-eshell 1117 | 1118 | When opening up a shell, this customization value specifies whether 1119 | it should run the @verb{~shell~} or @verb{~eshell~} command. 1120 | 1121 | Should be set to one of the following keywords: 1122 | @itemize 1123 | @item 1124 | @verb{~:shell~} 1125 | @item 1126 | @verb{~:eshell~} 1127 | @end itemize 1128 | 1129 | Defaults to @verb{~:eshell~} 1130 | 1131 | This setting can be overridden by the following keywords to 1132 | @verb{~demo-it-create~} macro: 1133 | @itemize 1134 | @item 1135 | @verb{~:use-eshell~} 1136 | @item 1137 | @verb{~:use-shell~} 1138 | @end itemize 1139 | 1140 | @node demo-it--open-windows 1141 | @unnumberedsec demo-it--open-windows 1142 | 1143 | @pindex demo-it--open-windows 1144 | @cindex Side Windows 1145 | 1146 | When opening side windows, split the frame on a particular side. 1147 | Should be set to one of the following keywords: 1148 | 1149 | @itemize 1150 | @item 1151 | @verb{~:above~} 1152 | @item 1153 | @verb{~:below~} 1154 | @item 1155 | @verb{~:left~} 1156 | @item 1157 | @verb{~:right~} 1158 | @end itemize 1159 | 1160 | The keyword, @verb{~:side~} is a synonym for @verb{~:right~}. 1161 | 1162 | Defaults to @verb{~:right~} 1163 | 1164 | This setting can be overridden by one of the following keywords 1165 | passed to @verb{~demo-it-create~}: 1166 | @itemize 1167 | @item 1168 | @verb{~:windows-on-side~} 1169 | @item 1170 | @verb{~:windows-on-right~} 1171 | @item 1172 | @verb{~:windows-on-left~} 1173 | @item 1174 | @verb{~:windows-below~} 1175 | @item 1176 | @verb{~:windows-above~} 1177 | @end itemize 1178 | 1179 | @node demo-it--open-windows-size 1180 | @unnumberedsec demo-it--open-windows-size 1181 | 1182 | @pindex demo-it--open-windows-size 1183 | @cindex Side Windows Size 1184 | 1185 | The size of side windows to open. This is the width if the window 1186 | is opened on one of the sides (@verb{~:left~} or @verb{~:right~}), or the height 1187 | if the window is opened @verb{~:above~} or @verb{~:below~}. 1188 | 1189 | Defaults to @verb{~80~} 1190 | 1191 | @node demo-it--text-scale 1192 | @unnumberedsec demo-it--text-scale 1193 | 1194 | @pindex demo-it--text-scale 1195 | @cindex Side Windows Font Size 1196 | 1197 | Sets the default text scale when opening files in side windows (see 1198 | @ref{demo-it--open-windows,demo-it--open-windows}). While this can be set to an integer, it 1199 | can also be set to one of the following keywords: 1200 | @itemize 1201 | @item 1202 | @verb{~:small~}, set to a text scale of -1 1203 | @item 1204 | @verb{~:normal~}, set to a text scale of 0 1205 | @item 1206 | @verb{~:medium~}, set to a text scale of 1 1207 | @item 1208 | @verb{~:large~}, set to a text scale of 2 1209 | @item 1210 | @verb{~:x-large~}, set to a text scale of 3 1211 | @item 1212 | @verb{~:xx-large~}, set to a text scale of 4 1213 | @item 1214 | @verb{~:huge~}, set to a text scale of 5 1215 | @end itemize 1216 | 1217 | It defaults to @verb{~:large~} (a @verb{~text-scale-set~} value of @verb{~2~}). 1218 | 1219 | This customization value can be overridden with one of the 1220 | following keywords passed to @verb{~demo-it-create~}: 1221 | @itemize 1222 | @item 1223 | @verb{~:text-small~} 1224 | @item 1225 | @verb{~:text-normal~} 1226 | @item 1227 | @verb{~:text-medium~} 1228 | @item 1229 | @verb{~:text-large~} 1230 | @item 1231 | @verb{~:text-x-large~} 1232 | @item 1233 | @verb{~:text-xx-large~} 1234 | @item 1235 | @verb{~:text-huge~} 1236 | @end itemize 1237 | 1238 | @node demo-it--start-fullscreen 1239 | @unnumberedsec demo-it--start-fullscreen 1240 | 1241 | @pindex demo-it--start-fullscreen 1242 | 1243 | A boolean setting that if set to a non-nil value, demonstrations 1244 | start with the current frame in fullscreen mode. Defaults to 1245 | @verb{~false~}. 1246 | 1247 | This customization value can be overridden with @verb{~:fullscreen~} 1248 | keyword passed to @verb{~demo-it-create~}. 1249 | 1250 | @node demo-it--start-single-window 1251 | @unnumberedsec demo-it--start-single-window 1252 | 1253 | @pindex demo-it--start-single-window 1254 | 1255 | A boolean setting that if non-nil, deletes other windows to start 1256 | the demonstration with a current buffer window being the only 1257 | displayed window. Defaults to @verb{~t~}. 1258 | 1259 | This customization value can be overridden with @verb{~:single-window~} 1260 | keyword passed to @verb{~demo-it-create~}. 1261 | 1262 | @node demo-it--presentation-hide-mode-line 1263 | @unnumberedsec demo-it--presentation-hide-mode-line 1264 | 1265 | @pindex demo-it--presentation-hide-mode-line 1266 | 1267 | If set to a nil value (@emph{false}), the mode-line is hidden for any 1268 | presentation files (this doesn't affect other files opened with the 1269 | @ref{demo-it-load-file,demo-it-load-file}). Defaults to @verb{~t~}. 1270 | 1271 | This customization value can be overridden with either of the 1272 | following keywords passed to @verb{~demo-it-create~}: 1273 | @itemize 1274 | @item 1275 | @verb{~:show-mode-line~} 1276 | @item 1277 | @verb{~:hide-mode-line~} 1278 | @end itemize 1279 | 1280 | @node demo-it--presentation-hide-org-markers 1281 | @unnumberedsec demo-it--presentation-hide-org-markers 1282 | 1283 | @pindex demo-it--presentation-hide-org-markers 1284 | 1285 | If set to a non-nil value, surrounding asterisks, underlines and 1286 | slashes that define an @code{org-mode} textual formats in a presentation 1287 | are displayed. Otherwise those characters hidden, even though the 1288 | effects of bolding and italics are still shown. Defaults to @verb{~t~}. 1289 | 1290 | This customization value can be overridden with either of the 1291 | following keywords passed to @verb{~demo-it-create~}: 1292 | @itemize 1293 | @item 1294 | @verb{~:show-org-markers~} 1295 | @item 1296 | @verb{~:hide-org-markers~} 1297 | @end itemize 1298 | 1299 | @node demo-it--presentation-variable-width 1300 | @unnumberedsec demo-it--presentation-variable-width 1301 | 1302 | @pindex demo-it--presentation-variable-width 1303 | 1304 | If set to a non-nil value, a @emph{variable-width} font is used when 1305 | displaying @code{org-mode} presentation files, otherwise the standard 1306 | fixed-width font is used. Defaults to @verb{~nil~}. 1307 | 1308 | This customization value can be overridden with either of the 1309 | following keywords passed to @verb{~demo-it-create~}: 1310 | @itemize 1311 | @item 1312 | @verb{~:variable-width~} 1313 | @item 1314 | @verb{~:fixed-width~} 1315 | @end itemize 1316 | 1317 | @node demo-it--presentation-hide-org-blocks 1318 | @unnumberedsec demo-it--presentation-hide-org-blocks 1319 | 1320 | @pindex demo-it--presentation-hide-org-blocks 1321 | 1322 | If set to a non-nil value, the start and ending lines of @code{org-mode} 1323 | blocks are shown during a presentation, otherwise these lines are 1324 | hidden, but the contents within the blocks are still shown. 1325 | 1326 | This currently only hides these lines: 1327 | @verbatim 1328 | #+BEGIN_SRC 1329 | ... 1330 | #+END_SRC 1331 | @end verbatim 1332 | 1333 | Other surrounding header values, like @verb{~#+HEADERS:~} may still be seen. 1334 | 1335 | This defaults to @verb{~t~}, however, this customization value can be 1336 | overridden with either of the following keywords passed to 1337 | @verb{~demo-it-create~}: 1338 | @itemize 1339 | @item 1340 | @verb{~:show-block-headers~} 1341 | @item 1342 | @verb{~:hide-block-headers~} 1343 | @end itemize 1344 | 1345 | @node demo-it--insert-text-speed 1346 | @unnumberedsec demo-it--insert-text-speed 1347 | 1348 | @pindex demo-it--insert-text-speed 1349 | 1350 | The functions, @ref{demo-it-run-in-shell,demo-it-run-in-shell}, @ref{demo-it-start-shell,demo-it-start-shell}, 1351 | and @ref{Inserting Text,demo-it-insert}, enters the text into the shell as if a human 1352 | were typing it. This value specifies the speed at which that text 1353 | is inserted into the shell. 1354 | 1355 | This can set to one of the following keywords: 1356 | @itemize 1357 | @item 1358 | @verb{~:instant~} to insert text with no delay 1359 | @item 1360 | @verb{~:slow~} 1361 | @item 1362 | @verb{~:medium~} 1363 | @item 1364 | @verb{~:fast~} 1365 | @end itemize 1366 | 1367 | Defaults to @verb{~:medium~}. 1368 | 1369 | This can also specify a tuple of two integer values for the random 1370 | number of milliseconds between those two values to delay before 1371 | inserting each character, for instance, the @verb{~:medium~} delay has a 1372 | lower value of 30 milliseconds, and an upper delay of 500. 1373 | 1374 | @node Index 1375 | @unnumbered Index 1376 | 1377 | For those of you trying to read this online, this index is generated 1378 | and only available within Emacs. If you are reading this from within 1379 | Emacs, well-done. 1380 | 1381 | @printindex cp 1382 | 1383 | @bye -------------------------------------------------------------------------------- /demonstration/a-demo.el: -------------------------------------------------------------------------------- 1 | ;;; A-DEMO --- Demonstration of demo-it 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright © 2016, Howard Abrams, all rights reserved. 5 | ;; Created: 27 October 2016 6 | ;; 7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 | ;; 9 | ;;; Commentary: 10 | ;; 11 | ;; A demonstration and a bit of a live tutorial of the demo-it 12 | ;; project... yeah, seriously meta. 13 | ;; 14 | ;; Keep in mind, this is a bit of an 'advanced demonstration' where 15 | ;; many of the steps are actually functions that perform multiple 16 | ;; actions. Tis also a little more fun to craft. 17 | ;; 18 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 19 | ;; 20 | ;;; Code: 21 | 22 | (require 'demo-it) 23 | 24 | ;; Let's pretend our demonstration is really code, and define a few 25 | ;; variables that we'll use when referring to the source code files in 26 | ;; the 'examples' directory: 27 | 28 | (setq a-demo/example-dir (expand-file-name "../example")) 29 | (setq a-demo/python-buffer "example.py") 30 | (setq a-demo/python-source 31 | (format "%s/%s" a-demo/example-dir a-demo/python-buffer)) 32 | (setq a-demo/ruby-buffer "example.rb") 33 | (setq a-demo/ruby-source 34 | (format "%s/%s" a-demo/example-dir a-demo/ruby-buffer)) 35 | 36 | 37 | ;; The following is the steps to this demonstration, keep in mind that 38 | ;; many of the 'steps' are calls to functions defined below. 39 | ;; 40 | ;; Note: The keywords may override some of your default settings of 41 | ;; our customized variables. 42 | 43 | (demo-it-create :fullscreen :single-window :advanced-mode 44 | :use-shell :variable-width 45 | 46 | (demo-it-presentation "a-demo.org") 47 | demo-it-presentation-advance 48 | demo-it-presentation-advance 49 | 50 | ;; Mini demonstration ... 51 | (find-file a-demo/ruby-source) 52 | (demo-it-start-shell a-demo/example-dir) 53 | (demo-it-run-in-shell "ruby ./example.rb") 54 | "M-p" 55 | (demo-it-run-in-shell " Everyone") 56 | 57 | ;; And the rest of the demonstration 58 | demo-it-presentation-return ; Demo It Functions 59 | demo-it-presentation-advance 60 | a-demo/show-file 61 | a-demo/show-part-file 62 | a-demo/show-fancy-file 63 | a-demo/show-compare-files 64 | demo-it-presentation-return ; Running Code 65 | demo-it-presentation-advance ; Presenting 66 | 67 | demo-it-presentation-advance ; Misc 68 | (demo-it-show-image 69 | (format "%s/pdx-emacs.png" a-demo/example-dir) 70 | :below 0 18) 71 | demo-it-presentation-return-noadvance 72 | 73 | demo-it-presentation-advance ; Getting Started 74 | a-demo/show-customizations 75 | a-demo/show-info-mode 76 | demo-it-presentation-return-noadvance) 77 | 78 | ;; The following functions are a collection of multi-action steps 79 | 80 | (defun a-demo/show-file () 81 | "An example of a multi-function 'step' where we write a number 82 | of sommands that will be executed with a single action. In this 83 | case, we first highlight a presentation phrase and then display 84 | the source code. 85 | 86 | We also make sure we have killed the source code to display, so 87 | that any settings we may have added to it go away." 88 | (demo-it-presentation-highlight-phrase "demo-it-load-file") 89 | (ignore-errors ; Make sure we load a fresh copy 90 | (kill-buffer a-demo/python-buffer)) 91 | (demo-it-load-file a-demo/python-source)) 92 | 93 | (defun a-demo/show-part-file () 94 | (demo-it-presentation-return-noadvance) 95 | (ignore-errors ; File shouldn't be loaded, but just in case: 96 | (kill-buffer a-demo/python-buffer)) 97 | (demo-it-presentation-highlight-phrase "demo-it-load-part-file") 98 | (demo-it-load-part-file a-demo/python-source :line 5 12)) 99 | 100 | (defun a-demo/show-fancy-file () 101 | (demo-it-presentation-return-noadvance) ; (kill-buffer-and-window) 102 | (kill-buffer a-demo/python-buffer) 103 | (demo-it-presentation-highlight-phrase "demo-it-load-fancy-file") 104 | (demo-it-load-fancy-file a-demo/python-source :line 5 12)) 105 | 106 | (defun a-demo/show-compare-files () 107 | (demo-it-presentation-return-noadvance) ; (kill-buffer-and-window) 108 | (kill-buffer a-demo/python-buffer) 109 | (demo-it-presentation-highlight-phrase "demo-it-compare-files") 110 | (demo-it-compare-files a-demo/python-source a-demo/ruby-source)) 111 | 112 | (defun a-demo/show-customizations () 113 | "Simply opens up the customize-group in side window" 114 | (demo-it-presentation-highlight-phrase "Customize the package") 115 | (split-window-horizontally) 116 | (customize-group-other-window "demo-it")) 117 | 118 | (defun a-demo/show-info-mode () 119 | "Opens side window with the Info to demo-it" 120 | (demo-it-presentation-highlight-phrase "Read the.*$") 121 | (info "demo-it")) 122 | 123 | (defun a-demo/clean-up () 124 | "Cleans up the files it has loaded, et. al." 125 | (interactive) 126 | (ignore-errors 127 | (kill-bufer "Shell")) 128 | (ignore-errors 129 | (kill-buffer a-demo/python-buffer)) 130 | (ignore-errors 131 | (kill-buffer a-demo/ruby-buffer))) 132 | 133 | (a-demo/clean-up) 134 | 135 | (demo-it-start) 136 | 137 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 138 | ;;; a-demo.el ends here 139 | -------------------------------------------------------------------------------- /demonstration/a-demo.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Demo-It 2 | #+AUTHOR: Howard Abrams 3 | #+EMAIL: howard.abrams@gmail.com 4 | #+DATE: 2016 Oct 26 5 | #+TAGS: presentation demo-it 6 | 7 | * What and Why? 8 | 9 | We all communicate in a /demonstrable way/. 10 | 11 | End of Sprint demonstration/retrospectives often involve 12 | /showing/ what you did... 13 | 14 | - Source code viewing 15 | - Source code running 16 | - High-level explanations... 17 | 18 | * Once upon a time... 19 | 20 | A demonstration is just a /number of steps/ 21 | 22 | I do everything in Emacs, so... 23 | 24 | I created some helper functions: [[http://github.com/howardabrams/demo-it][demo-it]] 25 | 26 | I now /program/ my demonstrations 27 | 28 | * Example of a Demo 29 | 30 | Each /step/ in the demo can be: 31 | 1. a function to call 32 | 2. an expression to evaluate 33 | 3. a key to press 34 | 35 | #+BEGIN_EXAMPLE 36 | (demo-it-create (find-file "example.rb") ; expression 37 | demo-it-start-shell ; function 38 | (demo-it-run-in-shell "ruby example.rb") 39 | "M-p" ; keystroke 40 | (demo-it-insert " Everyone") 41 | "RET") 42 | #+END_EXAMPLE 43 | 44 | Start with =M-x demo-it-start= 45 | 46 | * Demo It Functions 47 | 48 | Creating Emacs demonstrations is that simple. 49 | 50 | Demo-It also provides many /helper functions/: 51 | 52 | ** Showing Code 53 | 54 | Usually want to show files /next/ to the presentation: 55 | 56 | - =demo-it-load-file= :: Shows code in side window 57 | 58 | - =demo-it-load-part-file= :: Narrows to a section 59 | 60 | - =demo-it-load-fancy-file= :: Highlights part 61 | 62 | - =demo-it-compare-files= :: Shows two files 63 | 64 | ** Running Code 65 | 66 | Begin a shell (or eshell) to /psuedo-interactive/ enter commands. 67 | 68 | - =demo-it-start-shell= :: Begin a shell, optional parameters: 69 | - =directory= 70 | - =command= to run 71 | - =name= (defaults to "Shell") 72 | - =side= can be =:right= or =:below=, etc. 73 | - =size= is the font size 74 | - =width= is the size of window either, /width/ or /length/ 75 | 76 | - =demo-it-run-in-shell= :: Run a command 77 | 78 | - =demo-it-show-shell= :: Switches to shell buffer 79 | 80 | ** Presenting 81 | 82 | Uses =org-tree-slide= to display an =org-mode= as a /presentation/. 83 | (Each /section/ is a /screen/) 84 | 85 | - =demo-it-presentation= :: loads a presentation and optionally goes 86 | to a particular section 87 | 88 | - =demo-it-presentation-quit= :: stops presentation but not demo 89 | 90 | - =demo-it-presentation-return= :: closes other windows and advances 91 | to next section 92 | 93 | - =demo-it-presentation-return-noadvance= :: closes other windows, 94 | but /does not/ advance to the next section 95 | 96 | - =demo-it-presentation-advance= :: goes to next section 97 | 98 | - =demo-it-presentation-highlight-phrase= :: regular expression 99 | highlights some part of the presentation 100 | 101 | ** Misc Functions 102 | 103 | - =demo-it-insert= :: /types/ into a buffer 104 | 105 | - =demo-it-highlight-dwim= :: highlights region or function 106 | (actually can be interactive) 107 | 108 | - =demo-it-show-image= :: loads file without mode-line 109 | 110 | - =demo-it-single-presentation= :: complete demo of only 111 | a presentation 112 | 113 | * Getting Started 114 | 115 | Use =package-install= from MELPA: =demo-it= 116 | 117 | - Customize the package 118 | 119 | - Read the [[info:demo-it][Info File]] 120 | 121 | - Use a [[file:~/Work/demo-it/snippets/demo-it][yasnippet template]] 122 | 123 | - Keep it simple 124 | 125 | ** Questions? 126 | -------------------------------------------------------------------------------- /dir: -------------------------------------------------------------------------------- 1 | This is the file .../info/dir, which contains the 2 | topmost node of the Info hierarchy, called (dir)Top. 3 | The first time you invoke Info you start off looking at this node. 4 |  5 | File: dir, Node: Top This is the top of the INFO tree 6 | 7 | This (the Directory node) gives a menu of major topics. 8 | Typing "q" exits, "?" lists all Info commands, "d" returns here, 9 | "h" gives a primer for first-timers, 10 | "mEmacs" visits the Emacs manual, etc. 11 | 12 | In Emacs, you can click mouse button 2 on a menu item or cross reference 13 | to select it. 14 | 15 | * Menu: 16 | 17 | Emacs 18 | * Demo It: (demo-it). Demonstrations made and shown in Emacs. 19 | -------------------------------------------------------------------------------- /example/error-example.el: -------------------------------------------------------------------------------- 1 | ;;; error-example.el --- Demo error example -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | 5 | ;; This is a simple demonstration that shows off an error handling of 6 | ;; the demo-it system. Evaluating this buffer starts off the 7 | ;; presentation, and hitting SPC steps through the demonstration. 8 | 9 | ;;; Code: 10 | 11 | (setq a 0) 12 | (demo-it-start 13 | '((lambda () 14 | (demo-it-setq a 2)) 15 | (lambda () 16 | (run-with-timer 3 nil (lambda () (message "a=%s (after the error demo)" a))) 17 | (message "a=%s" a)) 18 | (lambda () 19 | (error "an error")) 20 | (lambda () 21 | (message "not reached")))) 22 | 23 | (provide 'error-example) 24 | ;;; error-example.el ends here 25 | -------------------------------------------------------------------------------- /example/example-code.el: -------------------------------------------------------------------------------- 1 | ;;; difference-of-squares.el --- Difference of Squares (exercism) 2 | 3 | ;;; Commentary: 4 | 5 | ;; Interesting exercise that is quite simple to solve if you can 6 | ;; use standard mapcar with a generated list of numbers. Obviously, 7 | ;; the `number-sequence' call won't work with extremely large 8 | ;; numbers. 9 | ;; 10 | ;; But my goal, I think, was to make something parallel and 11 | ;; readable. 12 | 13 | ;;; Code: 14 | 15 | (defun square (n) 16 | "Returns the square of a number." 17 | (* n n)) 18 | 19 | (defun sum (list-of-nums) 20 | "Like the + function, but takes a list." 21 | (apply '+ list-of-nums)) 22 | 23 | (defun squares (list-of-nums) 24 | "Returns LIST-OF-NUMS where each element is squared." 25 | (mapcar 'square list-of-nums)) 26 | 27 | (defun square-of-sums (n) 28 | "Returns the square of all sums of n with all natural numbers 29 | lower than n." 30 | (square (sum (number-sequence 1 n)))) 31 | 32 | (defun sum-of-squares (n) 33 | "Sums the square of n with the square of all natural number 34 | lower than n." 35 | (sum (squares (number-sequence 1 n)))) 36 | 37 | (defun difference (n) 38 | "Difference between the square of sums and the sums of squares." 39 | (- (square-of-sums n) (sum-of-squares n))) 40 | (provide 'difference-of-squares) 41 | ;;; difference-of-squares.el ends here 42 | -------------------------------------------------------------------------------- /example/example-code.py: -------------------------------------------------------------------------------- 1 | def even_cubes(values): 2 | """Given a list of integer values, this 3 | returns the cube (power of 3) for each even 4 | number in the list of values.""" 5 | return [x*x*x for x in values if x % 2 == 0] 6 | -------------------------------------------------------------------------------- /example/example-code.rb: -------------------------------------------------------------------------------- 1 | # Given a list of integer values, this 2 | # returns the cube (power of 3) for each even 3 | # number in the list of values. 4 | 5 | def cube(x) 6 | x * x * x 7 | end 8 | 9 | def even_cubes(values) 10 | values.select(&:even?).map(&:cube) 11 | end 12 | -------------------------------------------------------------------------------- /example/example-files.el: -------------------------------------------------------------------------------- 1 | ;;; EXAMPLE-FILES --- Demo of `demo-it' showing files 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright © 2016, Howard Abrams, all rights reserved. 5 | ;; Created: 3 October 2016 6 | ;; 7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 | ;; 9 | ;;; Commentary: 10 | ;; 11 | ;; This demonstration shows some of the ways we can load and show 12 | ;; files, like images and source code. 13 | ;; 14 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 15 | ;; 16 | ;; This program is free software; you can redistribute it and/or 17 | ;; modify it under the terms of the GNU General Public License as 18 | ;; published by the Free Software Foundation; either version 3, or 19 | ;; (at your option) any later version. 20 | ;; 21 | ;; This program is distributed in the hope that it will be useful, 22 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | ;; General Public License for more details. 25 | ;; 26 | ;; You should have received a copy of the GNU General Public License 27 | ;; along with this program; see the file COPYING. If not, write to 28 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 29 | ;; Floor, Boston, MA 02110-1301, USA. 30 | ;; 31 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 32 | ;; 33 | ;;; Code: 34 | 35 | (require 'demo-it) 36 | 37 | (ignore-errors 38 | (kill-buffer "example.py")) 39 | 40 | (defun dit-switch-and-load-two () 41 | (demo-it-presentation-return) 42 | (demo-it-compare-files "example-code.py" "example-code.rb")) 43 | 44 | (demo-it-create :full-screen :single-window :hide-block-headers 45 | (demo-it-presentation "example-files.org") 46 | demo-it-presentation-return 47 | (demo-it-load-fancy-file "example-code.el" :line 27 36) 48 | dit-switch-and-load-two 49 | demo-it-presentation-return 50 | (demo-it-show-image "pdx-emacs.png" :below nil 16) 51 | demo-it-presentation-return) 52 | 53 | (demo-it-start) 54 | 55 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 56 | ;;; example-files.el ends here 57 | -------------------------------------------------------------------------------- /example/example-files.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Example Demonstration of Showing Files 2 | #+AUTHOR: Howard Abrams 3 | #+EMAIL: howard.abrams@gmail.com 4 | #+DATE: 2016 Oct 03 5 | 6 | * Display Source Code Inline 7 | 8 | In this demonstration, we show how to display files. 9 | 10 | You can display in-line with =org-mode= code blocks: 11 | 12 | #+BEGIN_SRC emacs-lisp 13 | (defun response-for (msg) 14 | "Return message based on the input string, MSG. 15 | The responses are based on `Bob' Exercism project." 16 | (let ((case-fold-search nil) ;; Case matters! 17 | ;; Let's operate on a simpler string: 18 | (ops-msg (string-trim (replace-regexp-in-string 19 | "[0-9,.%^@#$*()]" "" msg)))) 20 | (cond 21 | ((string-match "^$" msg) "Fine. Be that way!") 22 | ((string-match "^[A-Z][A-Z' ?!]+$" ops-msg) "Whoa, chill out!") 23 | ((string-match "\\?$" ops-msg) "Sure.") 24 | (t "Whatever.")))) 25 | #+END_SRC 26 | 27 | * Display Source in Separate Window 28 | 29 | You can display source in its own buffer window. 30 | 31 | This shows the complete source code file, 32 | but with a sub-section highlighted. 33 | 34 | If you have [[https://github.com/Malabarba/fancy-narrow][fancy-narrow]] package installed, 35 | the highlighted code is colored, and the 36 | rest of the file is gray. 37 | 38 | If not, we simply narrow to the region. 39 | 40 | * Showing Code Comparisons 41 | 42 | To demonstrate the difference between two files, 43 | use =demo-it-compare-files= where each file 44 | is placed next to each other. 45 | 46 | This function allows the code to be show on 47 | the =:side= or =:below=. 48 | 49 | * Loading Images 50 | 51 | Since presentations like this one remove 52 | Emacs decorations, images can be displayed 53 | the same way. 54 | 55 | * Better Control 56 | 57 | When creating a demonstration where you 58 | plan to show code, choose =:advanced-mode= 59 | 60 | While this means you use =F12= to advance, 61 | you can use any other keys to show off 62 | your source code. 63 | -------------------------------------------------------------------------------- /example/example-shell.el: -------------------------------------------------------------------------------- 1 | ;;; EXAMPLE-SHELL --- Demonstrates Shell Features 2 | ;; 3 | ;; Author: Howard Abrams 4 | ;; Copyright © 2016, Howard Abrams, all rights reserved. 5 | ;; Created: 1 October 2016 6 | ;; 7 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 | ;; 9 | ;;; Commentary: 10 | ;; 11 | ;; Demonstrates the features of running commands in a shell. 12 | ;; 13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 14 | ;; 15 | ;; This program is free software; you can redistribute it and/or 16 | ;; modify it under the terms of the GNU General Public License as 17 | ;; published by the Free Software Foundation; either version 3, or 18 | ;; (at your option) any later version. 19 | ;; 20 | ;; This program is distributed in the hope that it will be useful, 21 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | ;; General Public License for more details. 24 | ;; 25 | ;; You should have received a copy of the GNU General Public License 26 | ;; along with this program; see the file COPYING. If not, write to 27 | ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth 28 | ;; Floor, Boston, MA 02110-1301, USA. 29 | ;; 30 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 31 | ;; 32 | ;;; Code: 33 | 34 | (require 'demo-it) 35 | 36 | (demo-it-create :use-eshell ;; Change this to :use-shell 37 | :single-window 38 | :windows-on-right 39 | :insert-fast 40 | :text-large 41 | 42 | (demo-it-presentation "example-shell.org") 43 | 44 | ;; This step opens up a shell window: 45 | (demo-it-start-shell) 46 | 47 | ;; Press 'Space' to run each of these commands: 48 | (demo-it-run-in-shell "pwd") 49 | (demo-it-run-in-shell "hostname" nil :slow) 50 | 51 | ;; Closes the window and goes to next presentation section 52 | (demo-it-presentation-return) 53 | 54 | ;; Passing nil for first parameter uses current dir 55 | ;; Connect to default shell if third param is nil 56 | (demo-it-start-shell nil "ls" nil :below :large 10)) 57 | 58 | (demo-it-start) 59 | 60 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 61 | ;;; example-shell.el ends here 62 | -------------------------------------------------------------------------------- /example/example-shell.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Shell Demonstration Example 2 | #+AUTHOR: Howard Abrams 3 | #+EMAIL: howard.abrams@gmail.com 4 | #+DATE: 2016 Oct 01 5 | 6 | * Shell Demonstration Example 7 | 8 | Opening up a shell window (or =eshell=) and running commands is easy: 9 | 10 | #+BEGIN_SRC elisp 11 | (demo-it-start-shell) 12 | #+END_SRC 13 | 14 | Press the ~Space~ to advance to each step which runs various commands 15 | at different /speeds/ specified to =demo-it-create=: 16 | 17 | - :insert-quickly 18 | - :insert-fast 19 | - :insert-medium 20 | - :insert-slow 21 | 22 | All demonstrations can behave the same with customization. 23 | 24 | * Window Positions 25 | 26 | Depending on your monitor, you can start your shell in other 27 | configurations... like :below 28 | -------------------------------------------------------------------------------- /example/example-title.org: -------------------------------------------------------------------------------- 1 | 2 | 3 | * Demo-It 4 | 5 | A simple demonstration of making demonstrations 6 | ...within Emacs 7 | -------------------------------------------------------------------------------- /example/example.el: -------------------------------------------------------------------------------- 1 | ;;; EXAMPLE --- Demonstrate a demo-it demonstration 2 | 3 | ;;; Commentary: 4 | 5 | ;; This is a simple demonstration that shows off a few of the 6 | ;; functions and options of the demo-it system. Evaluating this 7 | ;; buffer starts off the presentation, and hitting SPC steps through 8 | ;; the demonstration. 9 | 10 | ;;; Code: 11 | 12 | (require 'demo-it) 13 | 14 | ;; ---------------------------------------------------------------------- 15 | ;; Create some demonstration helper functions... 16 | 17 | (defun dit-load-source-code () 18 | "Load some source code in a side window." 19 | (demo-it-presentation-advance) 20 | (demo-it-load-fancy-file "example.py" :line 5 12 :side)) 21 | 22 | (defun dit-run-code () 23 | "Execute our source code in an Eshell buffer." 24 | ;; Close other windows and advance the presentation: 25 | (demo-it-presentation-return) 26 | (demo-it-start-shell) 27 | (demo-it-run-in-shell "python example.py Snoopy")) 28 | 29 | ;; ---------------------------------------------------------------------- 30 | ;; Demonstration creation and the ordering of steps... 31 | 32 | (demo-it-create :single-window :insert-fast 33 | (demo-it-title-screen "example-title.org") 34 | (demo-it-presentation "example.org") 35 | dit-load-source-code ;; Step 3 36 | dit-run-code) ;; Step 4 37 | 38 | ;; ---------------------------------------------------------------------- 39 | ;; Start the presentation whenever this script is evaluated. Good idea? 40 | 41 | (demo-it-start) 42 | 43 | ;;; example.el ends here 44 | -------------------------------------------------------------------------------- /example/example.org: -------------------------------------------------------------------------------- 1 | #+TITLE: An Example of Demo-It 2 | #+AUTHOR: Howard Abrams 3 | #+DATE: 2014 Jul 29 4 | 5 | This document is a simple presentation that can show off the 6 | many...well, the few features of the =demo-it= project. 7 | 8 | * Introduction 9 | 10 | Demo-It is a very simple project that allows you to execute 11 | pre-defined steps within Emacs. 12 | 13 | I use it along with org-tree-slide in order to begin with a 14 | nifty-swell presentation explaining the source code I've written. 15 | 16 | * Source Code Highlighting 17 | 18 | We can show source code using Emacs' 19 | built in capabilities, including connecting 20 | to a REPL. 21 | 22 | Of course, this depends on what source 23 | code and how well you have integrated 24 | that language with Emacs. ;-) 25 | 26 | * Code Demonstration 27 | 28 | At this point, we can assume that we 29 | have some sort of script that would be 30 | great to actually run in a shell... 31 | -------------------------------------------------------------------------------- /example/example.py: -------------------------------------------------------------------------------- 1 | # This Python program is a simple example. 2 | import sys 3 | 4 | 5 | def greeting(name): 6 | """Prints a greeting when given the 7 | optional name variable.""" 8 | if name: 9 | print "Hello, %s" % name 10 | else: 11 | print "Hello World" 12 | 13 | 14 | if __name__ == "__main__": 15 | if len(sys.argv) > 0: 16 | name = sys.argv[1] 17 | else: 18 | name = None 19 | 20 | greeting(name) 21 | -------------------------------------------------------------------------------- /example/example.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Simplistic example of a Ruby function demonstrating that 4 | # quintessential program, the hello world: 5 | 6 | def greeting(name) 7 | if name 8 | print "Hello, #{name}!\n" 9 | else 10 | print "Hello World.\n" 11 | end 12 | end 13 | 14 | greeting(ARGV.first) 15 | -------------------------------------------------------------------------------- /example/kbd-example.el: -------------------------------------------------------------------------------- 1 | ;;; kbd-example.el --- Demonstration of step by keyboard macro -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | 5 | ;; This is a simple demonstration that shows off keyboard macro 6 | ;; of the demo-it system. Evaluating this buffer starts off the 7 | ;; presentation, and hitting SPC steps through the demonstration. 8 | 9 | ;;; Code: 10 | 11 | (demo-it-start 12 | '((lambda () (message "Show example.el")) 13 | "C-x C-f example.el " 14 | "M-<" 15 | "M->")) 16 | 17 | (provide 'kbd-example) 18 | ;;; kbd-example.el ends here 19 | -------------------------------------------------------------------------------- /example/pdx-emacs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/howardabrams/demo-it/e399fd7ceb73caeae7cb50b247359bafcaee2a3f/example/pdx-emacs.png -------------------------------------------------------------------------------- /example/setq-example.el: -------------------------------------------------------------------------------- 1 | ;;; setq-example.el --- Demonstration of demo-it-setq -*- lexical-binding: t; -*- 2 | 3 | ;;; Commentary: 4 | 5 | ;; This is a simple demonstration that shows off temporary variables 6 | ;; of the demo-it system. Evaluating this buffer starts off the 7 | ;; presentation, and hitting SPC steps through the demonstration. 8 | 9 | ;;; Code: 10 | 11 | (demo-it-start 12 | '((lambda () 13 | (setq a 1) 14 | (makunbound 'v) 15 | (message "a=%d v=%s boundp=%s" a (bound-and-true-p v) (boundp 'v))) 16 | (lambda () 17 | (demo-it-setq a 10 v 0) 18 | (message "a=%d v=%s boundp=%s" a (bound-and-true-p v) (boundp 'v)) 19 | (run-at-time 2 nil (lambda () (message "After demo: a=%d v=%s boundp=%s" a (bound-and-true-p v) (boundp 'v))))))) 20 | 21 | (provide 'setq-example) 22 | ;;; setq-example.el ends here 23 | -------------------------------------------------------------------------------- /snippets/demo-it: -------------------------------------------------------------------------------- 1 | # -*- mode: snippet; require-final-newline: nil -*- 2 | # key: Sample Functions for demo-it 3 | # name: demoit 4 | # contributor: Howard Abrams 5 | # -- 6 | ;;; ${1:`(file-name-sans-extension (file-name-base (buffer-file-name)))`} --- ${2:Simple Summary} 7 | 8 | ;;; Commentary: 9 | 10 | ;; $3 11 | 12 | ;;; Code: 13 | 14 | (load-library "demo-it") 15 | 16 | ;; ---------------------------------------------------------------------- 17 | ;; Create functions for complicated, but individual steps 18 | 19 | (defun ${4:my-demo}-step-function () 20 | "Display $1.org (an 'org-mode' file) as a presentation." 21 | (demo-it-presentation "$1.org") 22 | (demo-it-presentation-highlight-phrase "Step 1")) 23 | 24 | ;; ---------------------------------------------------------------------- 25 | ;; Demonstration Order and configuration 26 | 27 | (demo-it-create :fullscreen :single-window 28 | $0 29 | (demo-it-title-screen "$1-title.org") 30 | $4-step-function) 31 | 32 | ;; ---------------------------------------------------------------------- 33 | ;; Start the presentation whenever this script is evaluated. Good idea? 34 | 35 | (demo-it-start) 36 | 37 | ;;; $1.el ends here 38 | --------------------------------------------------------------------------------