├── .gitignore ├── LICENSE ├── README.org ├── absolute-beginners-guide.org ├── icing-on-the-cake.org ├── images ├── esup.png ├── modeline.png └── windowframebuffers.png ├── introduction.org ├── managing-the-workspace.org ├── misc-goodies.org ├── modern-emacs.org ├── modern-emacs.pdf ├── preface.org ├── preface.pdf ├── project-management.org ├── taming-the-beast.org ├── thoughtspeed-editing.org └── thoughtspeed-motion.org /.gitignore: -------------------------------------------------------------------------------- 1 | *.tex 2 | /_minted-hacking-emacs 3 | *.mintedcmd 4 | *.pyg 5 | *.log 6 | _minted* 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jethro Kuan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | * Modern Emacs 2 | ** Introduction 3 | This is an attempt at producing course material for Emacs. 4 | 5 | The material is highly opinionated. For example, I handpick certain MELPA packages like /use-package/ to introduce. 6 | 7 | The pdf file can be found [[./modern-emacs.pdf][here]]. 8 | 9 | [[file:modern-emacs.org][Start Here]] 10 | -------------------------------------------------------------------------------- /absolute-beginners-guide.org: -------------------------------------------------------------------------------- 1 | * The Absolute Beginners Guide 2 | ** A Mindful Approach 3 | It is important that I be careful to impart Emacs knowledge objectively. Each individual has differing personal development practices, and Emacs is to be customized to suit one's needs. Hence, it is paramount that you absorb this material with a questioning mindset. 4 | 5 | Before we begin, I'd like you to create a blank text file. Fill this file with questions that arise while going through the material. For example: you may be used to the multiple-cursors feature in Sublime Text, how do I do the same (or better) in Emacs? Or maybe you work with C++ intimately, and would like to know how to compile my C++ files from within Emacs. 6 | 7 | There many different paths to Emacs mastery, but most include the following steps: 8 | 9 | 1. Muscle memory. Removing the conscious effort in figuring out which key combinations to press, allows clarity of thought. Emacs will empower you to code/write at unimaginable speeds. 10 | 2. Aggressive Optimization. Be on the constant lookout for things you perform often in your daily work, and ensure these are easily accessible with key combinations. If functions are yet available for your purposes, write one. 11 | 12 | The keybindings that you'll come across in this material are either the defaults or personal preference, and are only for your reference. Take note of keybindings that you dislike, and note them down to be replaced later. 13 | 14 | ** Baby Steps 15 | I often hear complaints that Emacs is huge in terms of file size, compared to other editors like Vim. This is no longer a cause for concern, with hard disk space becoming larger and cheaper by the day. One reason why Emacs is so large, is because it hosts a great many things, and this includes a manual and a tutorial. 16 | 17 | The tutorial is great for newcomers, and I would like you to go through it before we begin. You can access the tutorial via =C-h t=. 18 | 19 | ** And that's it! 20 | Now, you should be minimally competent with Emacs. One thing I found to be extra useful when I first started out was to print out a cheatsheet, and put it up somewhere accessible near my computer. Making your own is fun (especially if you do so in Emacs), but there are plenty available that are a quick search away. [[https://www.google.com.sg/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=0ahUKEwjvwoiX0PDQAhWGuo8KHTJ2Af0QFggjMAE&url=https%253A%252F%252Fwww.gnu.org%252Fsoftware%252Femacs%252Frefcards%252Fps%252Frefcard.ps.gz&usg=AFQjCNHxeH0-ZtB7F-95ByLTDRfVB0JZCA][Here's]] one by GNU themselves. 21 | 22 | You may be unimpressed by Emacs thus far, but I encourage you to stick on a little longer; things are just starting to get interesting. We are now armed with sufficient knowledge to begin making modifications to Emacs. 23 | 24 | *** [[file:taming-the-beast.org][Taming the Beast]] :noexport: 25 | -------------------------------------------------------------------------------- /icing-on-the-cake.org: -------------------------------------------------------------------------------- 1 | * Icing on the Cake 2 | Here I introduce packages I've installed that are not a must, but are definitely nice to have. 3 | 4 | ** [[https://github.com/roman/golden-ratio.el][golden-ratio]] 5 | #+NAME: golden-ratio 6 | Give the window you're working in more screen estate. 7 | 8 | #+BEGIN_SRC emacs-lisp 9 | (use-package golden-ratio 10 | :diminish golden-ratio-mode 11 | :config (progn 12 | ;;(add-to-list 'golden-ratio-extra-commands 'ace-window) 13 | (golden-ratio-mode 1))) 14 | #+END_SRC 15 | 16 | If you're using [[Ace-window][ace-window]], uncomment the line for golden-ratio to function properly. 17 | 18 | ** [[https://github.com/Malabarba/aggressive-indent-mode][aggressive-indent]] 19 | Keep your code nicely aligned while you hack away at more important stuff. Remember to disable this for languages that depend on indentation for syntax, like Python. 20 | 21 | #+BEGIN_SRC emacs-lisp 22 | (use-package aggressive-indent 23 | :diminish aggressive-indent-mode 24 | :config (add-hook 'prog-mode-hook 'aggressive-indent-mode)) 25 | #+END_SRC 26 | 27 | ** [[https://github.com/justbur/emacs-which-key][which-key]] 28 | Which-key is a godsend when you're first starting out using Emacs. I still refer to the list of keybindings it shows from time to time. 29 | 30 | #+BEGIN_SRC emacs-lisp 31 | (use-package which-key 32 | :diminish which-key-mode 33 | :config (add-hook 'after-init-hook 'which-key-mode)) 34 | #+END_SRC 35 | 36 | ** [[https://github.com/k-talo/volatile-highlights.el][volatile-highlights]] 37 | Volatile-highlights provides visual feedback for operations such as yanking by highlighting the relevant regions. 38 | 39 | #+BEGIN_SRC emacs-lisp 40 | (use-package volatile-highlights 41 | :diminish volatile-highlights-mode 42 | :config (volatile-highlights-mode t)) 43 | #+END_SRC 44 | 45 | ** [[https://github.com/wasamasa/firestarter][firestarter]] 46 | firestarter lets you execute commands (including shell commands) on save. Example use cases include compiling SASS files, and compiling a program. 47 | 48 | #+BEGIN_SRC emacs-lisp 49 | (use-package firestarter 50 | :bind ("C-c m s" . firestarter-mode) 51 | :init (put 'firestarter 'safe-local-variable 'identity)) 52 | #+END_SRC 53 | 54 | ** [[https://github.com/nonsequitur/git-gutter-plus][git-gutter+]] 55 | I use git-gutter+ primarily for showing on the left side what parts of my files have changed. It also has additional features like staging hunks for commits, but I use [[Magit][Magit]] for that. You can take a look at the Github page for more details. 56 | 57 | #+BEGIN_SRC emacs-lisp 58 | (use-package git-gutter+ 59 | :init (global-git-gutter+-mode) 60 | :diminish git-gutter+-mode 61 | :defer 5 62 | :config (progn 63 | (setq git-gutter+-modified-sign "==") 64 | (setq git-gutter+-added-sign "++") 65 | (setq git-gutter+-deleted-sign "--"))) 66 | #+END_SRC 67 | ** Honourable Mentions 68 | 1. [[https://github.com/abo-abo/hydra][hydra]] 69 | 2. [[https://github.com/zk-phi/electric-align][electric-align]] 70 | *** [[file:misc-goodies.org][Miscellaneous Goodies]] :noexport: 71 | -------------------------------------------------------------------------------- /images/esup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jethrokuan/emacs-workshop/dbc41e1e790198332036b91bf76f23c63dd6ebe2/images/esup.png -------------------------------------------------------------------------------- /images/modeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jethrokuan/emacs-workshop/dbc41e1e790198332036b91bf76f23c63dd6ebe2/images/modeline.png -------------------------------------------------------------------------------- /images/windowframebuffers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jethrokuan/emacs-workshop/dbc41e1e790198332036b91bf76f23c63dd6ebe2/images/windowframebuffers.png -------------------------------------------------------------------------------- /introduction.org: -------------------------------------------------------------------------------- 1 | * Introduction 2 | ** Installing Emacs 3 | If you're on a Linux distribution, Emacs should be available through your respective package managers. 4 | 5 | For OSX users, I recommend [[https://emacsformacosx.com/][Emacs for OSX]]. 6 | 7 | Refer [[http://stackoverflow.com/documentation/emacs/986/introduction-to-emacs#t=201607230658416845243][here]] if you have further doubts. 8 | 9 | This text assumes a recent Emacs version (of version >24.0). You can check your Emacs version with =M-x emacs-version=. 10 | 11 | ** Terminology 12 | Emacs is aged piece of software, so a lot of the terms it uses often confound first-timers. It is important to speak a common language, hence we begin by introducing the necessary terminology. 13 | 14 | *** Windows, Frames and Buffers 15 | The text you are editing in Emacs resides in an object called the *buffer*. It is important to note that a buffer is not a file. Buffers can contain more than just file contents: it could be an email draft, the compile error message, the list goes on. When you open a file, the file contents get loaded into a new buffer. When a buffer is saved, the buffer contents are written into the corresponding file. 16 | 17 | A *window* is a container for a buffer. A window can contain one and only one buffer. 18 | 19 | A *frame* is a container for windows. One can think of it as the window configuration for Emacs. 20 | 21 | #+CAPTION: A pictorial representation of windows, frames and buffers. In this picture, there are 1 frame, 3 windows and 3 buffers. 22 | [[./images/windowframebuffers.png]] 23 | 24 | *** Killing, Yanking and the CUA 25 | The table below shows analogous terminologies between Emacs clipboard system and modern standards: 26 | 27 | | Modern | Emacs | 28 | |--------+-------------------| 29 | | Cut | Kill | 30 | | Paste | Yank | 31 | | Copy | Save To Kill Ring | 32 | 33 | The Emacs terminology had been set in stone decades ago, long before the terms 'cut', 'copy' and 'paste' (derived from the CUA, or Common User Access) were formed. 34 | 35 | I will demonstrate in a later chapter why the Emacs way is better for text-editing. 36 | 37 | ** Modes, Major Modes and Minor Modes 38 | *Major modes* control how buffers behave. Each buffer will have /one and only one/ major mode. Most major modes tend to be language-specific. For example, when opening a Python file =foo.py=, the central Emacs register will figure out that this file is a Python file and load the Python major mode. 39 | 40 | Major modes often offer the following functionality: 41 | 42 | 1. Font locking (aka syntax highlighting) 43 | 2. Indentation 44 | 3. Language-specific keybindings (for refactoring etc.) 45 | 46 | In the scenario where the Emacs central registry for file extensions should fail to associate the file with a major mode, Emacs will scan the first portion of the file and infer one. 47 | 48 | *Minor modes* can be thought of as extensions, adding functionality to a buffer. These are optional, and can be added locally on a per buffer basis, or globally affecting all buffers. 49 | 50 | An example of a popular minor mode is the /aggressive-indent mode/, which keeps text in a buffer properly indented at all times. 51 | 52 | ** Modeline 53 | The bottom bar in Emacs is called the *modeline*. Each window has a modeline, which presents useful information about the buffer it displays. The first item in brackets is the major mode, and the others are all minor modes. 54 | 55 | Note that some minor modes can be configured to not appear on the modeline (a.k.a diminished). To see the full list of modes activated, run =M-x describe-mode=, or =C-h m=. 56 | 57 | #+CAPTION: A typical modeline for Emacs 58 | [[./images/modeline.png]] 59 | 60 | ** Emacs Lisp 61 | Keybindings are combinations of keys that invoke functions when pressed. The origins of these functions can be one of three: 62 | 63 | 1. It could come out-of-the-box 64 | 2. It could be provided by an installed package 65 | 3. It could be self-written 66 | 67 | These functions are defined in a language called *Emacs Lisp*, abbreviated as *Elisp*. Emacs Lisp files typically have the file extension =.el=. 68 | 69 | The full list of functions are browsable and invokable with =M-x=. 70 | 71 | ** Keybindings 72 | What is =M-x=, you may ask? This is how keybindings are discussed in Emacs. In =M-x=, =M= stands for the Meta key. This key is mapped to =alt= in most systems and keyboards, but this could vary. The next important key is =Ctrl=, abbreviated as =C=. For example =C-w= on a highlighted region kills the region of text. That would be pressing =Ctrl-w=. 73 | 74 | Because of the sheer number of functions Emacs has and could have, Many functions are invoked via more complex key combinations. Emacs does try to keep things mnemonic. For example, =C-h= is not a keybinding in itself, but opens a gateway to all the help functions. =C-h k= invokes =describe-key=, which brings up documentation for the function invoked by the next key combination. With =C-h k=, you press =Ctrl= and =h=, let go of =Ctrl= and press =k.= On the other hand, =C-h C-a= invokes =about-emacs=, which brings up the first screen that greets you on your new Emacs install. To invoke =C-h C-a=, hold =Ctrl= throughout, and press =h= then =a=. 75 | 76 | ** Summary 77 | - Emacs has it's own terminology, some of which we have covered in detail: windows, frames, buffers, killing and cutting. 78 | - Most functions in Emacs are written in Emacs Lisp, or Elisp. These functions are invokable with =M-x=. 79 | - Key combinations in Emacs are bound to invokable functions, and their complexities may vary. 80 | 81 | Armed with this new knowledge, you can begin exploring Emacs. 82 | 83 | *** [[file:absolute-beginners-guide.org][The Absolute Beginners Guide]] :noexport: 84 | In the next chapter, we make our first modifications to Emacs, to make it a saner environment to play around with. 85 | -------------------------------------------------------------------------------- /managing-the-workspace.org: -------------------------------------------------------------------------------- 1 | * Managing the Workspace 2 | It's common to want to create new windows in your Emacs frame to maximize screen estate and make editing easier. 3 | 4 | | Key | Window | 5 | |-------+-----------------------------------| 6 | | =C-x 0= | Delete current window | 7 | | =C-x 1= | Maximize current window | 8 | | =C-x 2= | Split current window /horizontally/ | 9 | | =C-x 3= | Split current window /vertically/ | 10 | 11 | ** Winner-mode 12 | /Winner-mode/ is a global minor mode. When activated, it allows you to "undo" and "redo" changes in the window configuration. 13 | 14 | | Key | Action | 15 | |-----------+-------------| 16 | | C-c left | =winner-undo= | 17 | | C-c right | =winner-redo= | 18 | 19 | The keybinding for switching between windows is =C-x o=, which I find overly complex for such an essential key. 20 | 21 | ** WindMove 22 | /WindMove/ is a library included in Emacs starting with version 21. It lets you switch between windows using Shift + arrow keys. To activate it on startup, add the following piece of code in your =init.el=. 23 | 24 | #+BEGIN_SRC emacs-lisp 25 | (when (fboundp 'windmove-default-keybindings) 26 | (windmove-default-keybindings)) 27 | #+END_SRC 28 | 29 | ** Ace-window 30 | [[https://github.com/abo-abo/ace-window][ace-window]] lets you quickly switch between windows. It's the one I'm currently using, and I'm very happy with it. 31 | 32 | #+BEGIN_SRC emacs-lisp 33 | (use-package ace-window 34 | :bind (("M-q" . ace-window))) 35 | #+END_SRC 36 | 37 | I'd bind it to =M-q=, or anything else you find convenient. 38 | 39 | *** [[file:thoughtspeed-motion.org][Thought-speed Motion]] :noexport: 40 | -------------------------------------------------------------------------------- /misc-goodies.org: -------------------------------------------------------------------------------- 1 | * Miscellaneous Goodies 2 | ** Minimizing Startup Time 3 | *** Emacs Daemon 4 | One way to avoid all perceived boot time, is to start emacs during the system boot as a daemon. This is the option I have gone with. 5 | 6 | All you need to do add the Emacs daemon to auto-start: 7 | 8 | #+BEGIN_SRC bash 9 | emacs --daemon 10 | #+END_SRC 11 | 12 | I use /systemd/ instead. For this option, create a user /systemd/ service file with the following content: 13 | 14 | #+BEGIN_SRC txt 15 | [Unit] 16 | Description=Emacs: the extensible, self-documenting text editor 17 | Documentation=man:emacs(1) info:Emacs 18 | 19 | [Service] 20 | Type=forking 21 | ExecStart=/usr/bin/emacs --daemon 22 | ExecStop=/usr/bin/emacsclient --eval "(progn (setq kill-emacs-hook nil) (kill emacs))" 23 | Environment=DISPLAY=:%i 24 | TimeoutStartSec=0 25 | Restart=on-failure 26 | 27 | [Install] 28 | WantedBy=default.target 29 | #+END_SRC 30 | 31 | To enable the service on startup, just do =systemd enable --user emacsd.service=. 32 | 33 | *** Profiling with esup 34 | Esup can perform a profile of your current configuration. Esup is obtainable over MELPA, so go ahead and use =use-package= like we normally do: 35 | 36 | #+BEGIN_SRC emacs-lisp 37 | (use-package esup 38 | :defer t) 39 | #+END_SRC 40 | 41 | Next, just execute esup with =M-x esup=. A separate emacs process will start, and the profiling results will be returned in a separate window, which would look like this: 42 | 43 | #+CAPTION: esup profiling results 44 | [[./images/esup.png]] 45 | 46 | You can take note of the packages that take the longest amount of time to initialize, and weigh their alternatives. For example, I might contemplate removing git-gutter+ or replacing it with a more lightweight alternative. 47 | 48 | ** Micro-optimizations with keyfreq 49 | Once you've determined your Emacs style, you begin to use the same keybindings again and again. Understanding which functions are invoked most often, allows you to optimize your workflow by binding them to shorter, more accessible key combinations. 50 | 51 | [[https://github.com/dacap/keyfreq][keyfreq]] monitors your keypresses during daily Emacs usage. 52 | 53 | #+BEGIN_SRC emacs-lisp 54 | (use-package keyfreq 55 | :config 56 | (keyfreq-mode 1) 57 | (keyfreq-autosave-mode 1)) 58 | #+END_SRC 59 | 60 | After a period of Emacs usage, run =M-x keyfreq-show=. Perform micro-optimizations based on the results. After which, =M-x keyfreq-reset= to rinse and repeat. 61 | 62 | ** Remapping Capslock 63 | Without doubt, the capslock key is one of the most underused keys (that is if you're normal). Do yourself a favour and remap it to something more useful -- I recommend the elusive Ctrl key. On the Mac, you can remap it in the keyboard preferences pane. 64 | 65 | ** Ergonomic Keybindings 66 | Anyone who spends enough time at the keyboard is at risk of repetitive strain injury, or RSI. Spend some time reflecting on how often you stretch out your pinky or move your thumb into awkward positions to press a key. 67 | 68 | *** M-x 69 | Let's face it. =M-x= is actually pretty damn hard to hit. /x/ is highly inaccessible, not even on alternative keyboard layouts like Dvorak. 70 | 71 | In [[https://github.com/bbatsov/prelude][prelude]], =M-x= is bound to =C-x C-m=. I bind =M-x= to =M-a=, which is originally bound to =backward-sentence=, which I don't use much at all. Both are viable options. 72 | 73 | *** ergoemacs 74 | [[https://ergoemacs.github.io/][ergoemacs]] was developed to bring familiar keys to Emacs, as well as to reduce risk of RSI. While you could follow the instructions on the webpage to have it installed, I recommend studying their keybindings and adopting the ones you think you'll like. 75 | -------------------------------------------------------------------------------- /modern-emacs.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Modern Emacs 2 | #+AUTHOR: Jethro Kuan 3 | #+LATEX_CLASS: books 4 | 5 | #+INCLUDE: "./preface.org" 6 | #+INCLUDE: "./introduction.org" 7 | #+INCLUDE: "./absolute-beginners-guide.org" 8 | #+INCLUDE: "./taming-the-beast.org" 9 | #+INCLUDE: "./managing-the-workspace.org" 10 | #+INCLUDE: "./thoughtspeed-motion.org" 11 | #+INCLUDE: "./thoughtspeed-editing.org" 12 | #+INCLUDE: "./project-management.org" 13 | #+INCLUDE: "./icing-on-the-cake.org" 14 | #+INCLUDE: "./misc-goodies.org" 15 | 16 | ** Table of Contents :noexport: 17 | 1. [[file:preface.org][Preface]] 18 | 2. [[file:introduction.org][Introduction]] 19 | 3. [[file:absolute-beginners-guide.org][The Absolute Beginners Guide]] 20 | 4. [[file:taming-the-beast.org][Taming the Beast]] 21 | 5. [[file:managing-the-workspace.org][Managing the Workspace]] 22 | 6. [[file:thoughtspeed-motion.org][Thought-speed Motion]] 23 | 7. [[file:thoughtspeed-editing.org][Thought-speed Editing]] 24 | 8. [[file:project-management.org][Project Management]] 25 | 9. [[file:icing-on-the-cake.org][Icing on the Cake]] 26 | 10. [[file:misc-goodies.org][Miscellaneous Goodies]] 27 | -------------------------------------------------------------------------------- /modern-emacs.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jethrokuan/emacs-workshop/dbc41e1e790198332036b91bf76f23c63dd6ebe2/modern-emacs.pdf -------------------------------------------------------------------------------- /preface.org: -------------------------------------------------------------------------------- 1 | * Preface 2 | #+BEGIN_LaTeX 3 | \openepigraph{Emacs is a nice operating system, but what it lacks, in order to compete with Linux, is a good text editor.}{Thomer M. Gil} 4 | #+END_LaTeX 5 | 6 | Today, you begin your journey with Emacs, /the extensible, customizable, self-documenting real-time display editor/. 7 | 8 | Emacs is complex, and will seem difficult to grok. It takes a certain amount of courage, or an equal amount of frustration, to turn to Emacs. 9 | 10 | This material was originally titled /Hacking Emacs/, because a great deal of customization can and will be made. The tinkerer will marvel at the masterpiece which is Emacs. We hack on it because we can; every facet of Emacs is extensible and customizable. 11 | 12 | I have since renamed this piece to "Modern Emacs". Emacs has evolved over several decades, and it is important that our tools are kept up to date. I have handpicked several packages to introduce. These will greatly boost your productivity with the least amount of learning time. 13 | 14 | For the novice, this will provide you with a sane environment for you to play around and do some self-exploration. For the first time you'll own your editor: Emacs should designed specifically for your own needs. 15 | 16 | For the intermediate, this presents itself as a literate org-mode configuration. I hope you find something useful in here you could copy. 17 | 18 | Atom users, go grab yourselves another cup of coffee while you wait for it to load up :P. 19 | #+BEGIN_LaTeX 20 | \begin{flushright} 21 | #+END_LaTeX 22 | -- Jethro Kuan 23 | #+BEGIN_LaTeX 24 | \end{flushright} 25 | #+END_LaTeX 26 | 27 | *** 🢒 [[file:introduction.org][Introduction]] :noexport: 28 | We begin by introducing Emacs, how to get it, and familiarize ourselves with terminology that will appear again and again in later chapters. 29 | -------------------------------------------------------------------------------- /preface.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jethrokuan/emacs-workshop/dbc41e1e790198332036b91bf76f23c63dd6ebe2/preface.pdf -------------------------------------------------------------------------------- /project-management.org: -------------------------------------------------------------------------------- 1 | * Project Management 2 | In most cases, your work is not limited to a single file. Instead, it's comprised of multiple files residing in a parent directory, or perhaps even version-controlled with Git or the likes. 3 | 4 | While Emacs does not ship with project management tooling, there are a few quality libraries that help you with that. 5 | 6 | ** FFIP 7 | [[https://github.com/technomancy/find-file-in-project][find-file-in-project]], or /ffip/ in short, provides quick access to files in a directory managed by version-control (git/svn/mercurial). It's intentionally kept simple. It uses GNU find under the hood, which makes it suitable even for large codebases. The default interface has been recently changed to /ivy/ (introduced [[Ivy, Counsel and Swiper][earlier]]). Look no further than ffip for a simple project-management tool. 8 | 9 | #+BEGIN_SRC emacs-lisp 10 | (use-package find-file-in-project 11 | :bind (("s-f" . find-file-in-project) 12 | ("s-F". find-file-in-current-directory) 13 | ("M-s-f" . find-file-in-project-by-selected))) 14 | #+END_SRC 15 | 16 | The functions are so useful they deserve a short keybinding: =s-f= is what I'd go with. 17 | 18 | ** Projectile 19 | [[https://github.com/bbatsov/projectile][Projectile]] is a different beast, leveraging a variety of tools to be a performant project interaction library. While ffip aims to be a minimalistic and fast file-switcher for projects, projectile aims to be the all-encompassing project-management tool. It has certainly proved to be the only one you'll need. 20 | 21 | Here are some handpicked features Projectile has to offer, as seen on the Github page: 22 | 23 | - jump to a file in project 24 | - jump to files at point in project 25 | - jump to a project buffer 26 | - jump to a test in project 27 | - toggle between files with same names but different extensions (e.g. .h <-> .c/.cpp, Gemfile <-> Gemfile.lock) 28 | - toggle between code and its test (e.g. main.service.js <-> main.service.spec.js) 29 | - switch between projects you have worked on 30 | - replace in project 31 | - regenerate project etags or gtags (requires ggtags). 32 | - run =make= in a project with a single key chord 33 | 34 | I bind the projectile keymap to =C-x p=. If you use =ivy=, set the =projectile-completion-system= to =ivy=, and install [[https://github.com/ericdanan/counsel-projectile][counsel-projectile]], which adds more ivy-friendly functions for projectile. 35 | 36 | #+BEGIN_SRC emacs-lisp 37 | (use-package projectile 38 | :demand t 39 | :init (projectile-global-mode 1) 40 | :bind-keymap* ("C-x p" . projectile-command-map) 41 | :config 42 | (require 'projectile) 43 | (use-package counsel-projectile 44 | :bind (("s-p" . counsel-projectile) 45 | ("s-f" . counsel-projectile-find-file) 46 | ("s-b" . counsel-projectile-switch-to-buffer))) 47 | (setq projectile-use-git-grep t) 48 | (setq projectile-completion-system 'ivy)) 49 | #+END_SRC 50 | 51 | Projectile also has a little known feature: =projectile-commander=. The default action upon switching projects is =find-file=, and that might not be desirable. Give yourself a choice between doing a =find-file=, a git-fetch, or even language specific things like starting a REPL. 52 | 53 | First, set the projectile to utilize =projectile-commander=: 54 | 55 | #+BEGIN_SRC emacs-lisp 56 | (setq projectile-switch-project-action #'projectile-commander) 57 | #+END_SRC 58 | 59 | Next, define the methods you want: 60 | #+BEGIN_SRC emacs-lisp 61 | (def-projectile-commander-method ?s 62 | "Open a *eshell* buffer for the project." 63 | (projectile-run-eshell)) 64 | (def-projectile-commander-method ?c 65 | "Run `compile' in the project." 66 | (projectile-compile-project nil)) 67 | (def-projectile-commander-method ?\C-? 68 | "Go back to project selection." 69 | (projectile-switch-project)) 70 | (def-projectile-commander-method ?d 71 | "Open project root in dired." 72 | (projectile-dired)) 73 | (def-projectile-commander-method ?F 74 | "Git fetch." 75 | (magit-status) 76 | (call-interactively #'magit-fetch-current)) 77 | (def-projectile-commander-method ?j 78 | "Jack-in." 79 | (let* ((opts (projectile-current-project-files)) 80 | (file (ido-completing-read 81 | "Find file: " 82 | opts 83 | nil nil nil nil 84 | (car (cl-member-if 85 | (lambda (f) 86 | (string-match "core\\.clj\\'" f)) 87 | opts))))) 88 | (find-file (expand-file-name 89 | file (projectile-project-root))) 90 | (run-hooks 'projectile-find-file-hook) 91 | (cider-jack-in)))) 92 | #+END_SRC 93 | 94 | Append all these code into =:config= for the =projectile= package. 95 | 96 | ** Using Ag or Grep 97 | Projectile ships with functions that make use of grep and ag. Grep and Ag are both command-line tools used for searching code. You use =projectile-ag= (=C-x p s s)= or =projectile-grep= (=C-x p s g=) to perform a project-scoped search, and use the search results to navigate to the relevant locations. Ag is more performant, but does not come installed with most systems. In most cases, grep is sufficiently fast. 98 | 99 | Alternatively, if you had installed counsel by following the instructions [[Ivy, Counsel and Swiper][here]], you'd have access to the function, =counsel-ag=, =counsel-git=, and =counsel-git-grep=. =counsel-git-grep= (=C-c j=) is especially great for projects, because it prunes out files captured by =.gitignore=. 100 | 101 | ** Magit 102 | [[https://github.com/magit/magit][Magit]] is an interface for Git. It is an absolute joy to use, and is one of the main reasons I stuck with Emacs after a period with Vim. 103 | 104 | #+BEGIN_SRC emacs-lisp 105 | (use-package magit 106 | :bind (("C-x g" . magit-status) 107 | ("C-x M-g" . magit-blame)) 108 | :init (setq magit-auto-revert-mode nil) 109 | :config (add-hook 'magit-mode-hook 'hl-line-mode)) 110 | #+END_SRC 111 | 112 | Surely you can figure out the basics like adding remotes, fetching, and committing with such a simplified interface. [[https://www.youtube.com/watch?v=mtliRYQd0j4][Here's]] a great tutorial on how to perform rebases, squashes and the like easily with Magit. 113 | 114 | *** [[file:icing-on-the-cake.org][Icing on the Cake]] :noexport: 115 | -------------------------------------------------------------------------------- /taming-the-beast.org: -------------------------------------------------------------------------------- 1 | * Taming the Beast 2 | Vanilla Emacs works in a variety of unfortunate ways. These defaults have grown a resistance to change over the decades. 3 | 4 | We perform tweaking on Emacs minutiae, and simultaneously learn how Emacs is customized. 5 | 6 | ** Customizing Emacs 7 | During initialization, Emacs attempts to load an /init/ file. This /init/ file is an Emacs Lisp file, and is processed top-down. 8 | 9 | #+BEGIN_QUOTE 10 | TIP: To load Emacs without a configuration file, run =emacs= with the command-line switch =-q=. This is useful when your configuration file breaks. 11 | #+END_QUOTE 12 | 13 | Emacs searches for /init/ files in several locations: 14 | 15 | 1. =~/.emacs= 16 | 2. =~/.emacs.el= 17 | 3. =~/.emacs.d/init.el= 18 | 19 | I recommend the third option, =~/.emacs.d/init.el=. Having a dedicated =.emacs.d= folder for all Emacs-related config simplifies versioning. 20 | 21 | If you haven't done so, create a blank file =init.el= in =~/.emacs.d=. 22 | 23 | Next, I'll introduce your first few tweaks. To enable them, copy them into the =init.el= file. 24 | 25 | *** Enabling Package Archives 26 | [[https://melpa.org/#/][MELPA]] is the de-facto community package archive for Emacs. Because it does not ship with Emacs, we add it to =package-archives=. Similarly, we enable the Org-mode repository, which contains the most up-to-date version of =org-with-contrib=. 27 | 28 | #+BEGIN_SRC emacs-lisp 29 | (when (>= emacs-major-version 24) 30 | (require 'package) 31 | (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t) 32 | (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t) 33 | (package-initialize)) 34 | #+END_SRC 35 | 36 | The more security conscious will note that packages are fetched using HTTP, instead of HTTPS. HTTPS, however, did not work for me. Refer [[https://glyph.twistedmatrix.com/2015/11/editor-malware.html][here]] for the reasons why you might want to do so, and how to do it. 37 | 38 | *** Setting User Details 39 | These variables are used in several parts of Emacs, including email. 40 | 41 | #+BEGIN_SRC emacs-lisp 42 | (setq user-full-name "John Appleseed" 43 | user-mail-address "john@me.com") 44 | #+END_SRC 45 | 46 | *** UI Cruft 47 | All these UI cruft take up precious screen estate, and should be removed. 48 | 49 | #+BEGIN_SRC emacs-lisp 50 | (tooltip-mode -1) 51 | (tool-bar-mode -1) 52 | (menu-bar-mode -1) 53 | (scroll-bar-mode -1) 54 | (setq inhibit-splash-screen t) 55 | (setq inhibit-startup-message t) 56 | #+END_SRC 57 | 58 | *** Use-package 59 | [[https://github.com/jwiegley/use-package][use-package]] is a macro which allows you to isolate package configuration in an organized and performant fashion. It is written by John Wiegley, the current Emacs maintainer. Before you move on, I recommend briefly browsing through the [[https://github.com/jwiegley/use-package][REAME]], to familiarize yourself with the macro syntax. 60 | 61 | #+BEGIN_SRC emacs-lisp 62 | (unless (package-installed-p 'use-package) 63 | (package-refresh-contents) 64 | (package-install 'use-package)) 65 | 66 | (eval-and-compile 67 | (defvar use-package-verbose t) 68 | (require 'cl) 69 | (require 'use-package) 70 | (require 'bind-key) 71 | (require 'diminish) 72 | (setq use-package-always-ensure t)) 73 | #+END_SRC 74 | 75 | Here, we set =use-package-always-ensure= to =true=, so missing packages will be installed automatically. 76 | 77 | *** y/n 78 | This is mostly personal preference, but I find y/n easier to type than yes/no. 79 | 80 | #+BEGIN_SRC emacs-lisp 81 | (defalias 'yes-or-no-p 'y-or-n-p) 82 | #+END_SRC 83 | 84 | *** Custom Files 85 | Emacs comes with a built-in interface to customize all parts of Emacs. 86 | 87 | To persist the changes you've made, Emacs saves them (by default) into your =init.el= file, which can cause it to grow out of control. 88 | 89 | I like to keep such customizations saved in a separate file. 90 | 91 | #+BEGIN_SRC emacs-lisp 92 | (setq custom-file "~/.emacs.d/custom.el") 93 | (load custom-file) 94 | #+END_SRC 95 | 96 | *** Backup Files 97 | Backup files are important, but they litter your work directories with temporary files. Instead, with the following configuration temp files are created in the system temp directory. 98 | 99 | #+BEGIN_SRC emacs-lisp 100 | (setq backup-directory-alist 101 | `((".*" . ,temporary-file-directory))) 102 | (setq auto-save-file-name-transforms 103 | `((".*" ,temporary-file-directory t))) 104 | #+END_SRC 105 | 106 | *** Overwriting Text 107 | I'm used to having text being overwritten when highlighted. This usually saves me a keystroke. 108 | 109 | #+BEGIN_SRC emacs-lisp 110 | (delete-selection-mode +1) 111 | #+END_SRC 112 | 113 | *** Default Font 114 | Emacs looks for fonts installed in your file system. There are several ways to go about this, but I find the following the simplest and most reliable. 115 | 116 | #+BEGIN_SRC emacs-lisp 117 | (add-to-list 'default-frame-alist 118 | '(font . "Fira Code-12")) 119 | #+END_SRC 120 | 121 | *** Tabs vs Spaces 122 | I choose to set my tabs to 2 spaces, an increasingly common trend. 123 | 124 | #+BEGIN_SRC emacs-lisp 125 | (setq-default tab-width 2) 126 | (setq-default indent-tabs-mode nil) 127 | #+END_SRC 128 | 129 | ** Theming 130 | There are a [[https://emacsthemes.com/][myriad]] of themes available for your picking. Here I list the better ones: 131 | 132 | 1. Zenburn 133 | 2. Solarized 134 | 3. Leuven (has an impressive org-mode theme) 135 | 4. Monokai 136 | 5. Tomorrow by Sanityinc 137 | 6. Ample 138 | 139 | Usually, themes are named =foo-theme= in MELPA. 140 | 141 | #+BEGIN_SRC emacs-lisp 142 | (use-package ample-theme 143 | :init 144 | (load-theme 'ample-flat t)) 145 | #+END_SRC 146 | 147 | At this point you should have quite a hefty amount of modification done. Remember to save your configuration directory into version control. 148 | 149 | *** [[file:managing-the-workspace.org][Managing The Workspace]] :noexport: 150 | -------------------------------------------------------------------------------- /thoughtspeed-editing.org: -------------------------------------------------------------------------------- 1 | * Thought-speed Editing 2 | ** Moving Text Around 3 | [[Killing, Yanking and the CUA][Earlier]], I introduced the terminology Emacs uses for its clipboard system. I missed one vital piece, because I felt it was more appropriate to introduce here to keep things fresh. 4 | 5 | Text that gets killed is erased, and then stored inside the *kill ring*. This stored text is then retrievable by *yanking*. There is only one kill ring, global to Emacs. 6 | 7 | A clear distinction has to be made between killing and deleting. Deleting text removes it from the buffer, but does not store it in the kill ring. Therefore extra caution has to be made when performing deletions. 8 | 9 | *** Deleting Text 10 | Here are the more useful text deletion commands: 11 | 12 | #+ATTR_LATEX: :align lp{6cm}l 13 | | Key | Action | Function | 14 | |---------+------------------------------------------------------------------------+---------------------------| 15 | | =M-\= | Delete spaces and tabs around point | =(delete-horizontal-space)= | 16 | | =M-SPC= | Delete spaces and tabs around point, leaving one space | =(just-one-space)= | 17 | | =C-x C-o= | Delete blank lines around current line | =(delete-blank-lines)= | 18 | | =M-^= | Join two lines by deleting intervening newline, along with indentation | =(delete-indentation)= | 19 | 20 | *** Killing Text 21 | Here are the more useful text killing commands: 22 | 23 | | Key | Action | Function | 24 | |---------+------------------------------------+--------------------------| 25 | | =C-k= | Kill line | =(kill-line)= | 26 | | =C-w= | Kill region | =(kill-region)= | 27 | | =C-x DEL= | Kill back to beginning of sentence | =(backward-kill-sentence)= | 28 | | =M-k= | Kill to end of sentence | =(kill-sentence)= | 29 | 30 | #+BEGIN_QUOTE 31 | NOTE: By default, a sentence is delimited by a period, followed by *two* spaces. This is so that Emacs can differentiate between abbrieviations (M. J. for example), and actual sentences. It is recommended that you follow the two space convention, but if you insist, =(setq sentence-end-double-space nil)= should do the trick. 32 | #+END_QUOTE 33 | 34 | *** Yanking Text 35 | Here are the more useful text killing commands: 36 | 37 | | Key | Action | Function | 38 | |-------+---------------------------------------------------------------+--------------------| 39 | | =C-y= | Yank last killed text | =(yank)= | 40 | | =M-y= | Replace last killed text with an earlier batch of killed text | =(yank-pop)= | 41 | | =M-w= | Save region as last killed text without performing the kill | =(kill-ring-save)= | 42 | | =C-M-w= | Append next kill to last batch of killed text | =(append-next-kill)= | 43 | 44 | You can think of the kill ring as a stack, so you could continuously pop the kill ring to obtain earlier batches of killed text. 45 | 46 | *** browse-kill-ring 47 | I often defer to [[https://github.com/browse-kill-ring/browse-kill-ring][browse-kill-ring]] to access my kill-ring history. I bind it to =M-y=, replacing =(yank-pop)=. Try it out, and see if it suits your workflow. 48 | 49 | #+BEGIN_SRC emacs-lisp 50 | (use-package browse-kill-ring 51 | :bind ("M-y" . browse-kill-ring)) 52 | #+END_SRC 53 | 54 | ** Selecting Regions 55 | *** The Mark, the Point and the Region 56 | Many Emacs commands operate on an arbituary, contiguous part of the buffer, also known as the /region/. A region is delimited by two objects: the /mark/ and the /point/. 57 | 58 | The point is where your cursor (keyboard) is currently placed. =C-SPC= creates a mark at the current position of point, activating it, as well as activating the region. The region is the text between the point and the mark, regardless of which direction. To deactivate the mark, simply quit with =C-g=. 59 | 60 | Some common region commands include =kill-region=. 61 | 62 | *** Rectangular Region 63 | Rectangle commands operate on retangular areas of text. This may seem rather esoteric, but it occasionally presents itself as the correct tool. 64 | 65 | =C-x SPC= creates a rectangular mark. The following presents commonly used rectangular commands, all prefixed with =C-x r=, operate on rectangular regions: 66 | 67 | (Region-rectangle is short-formed as RR) 68 | 69 | #+ATTR_LATEX: :align lp{7cm}l 70 | | Key | Action | Function | 71 | |--------------------+-----------------------------------------------------------------+--------------------------| 72 | | =C-x r k= | Kill text in RR, saving its contents into last-killed rectangle | =(kill-rectangle)= | 73 | | =C-x r M-w= | Save text in RR into kill-ring | =(copy-rectangle-as-kill)= | 74 | | =C-x r d= | Delete text in RR | =(delete-rectangle)= | 75 | | =C-x r y= | Yank last killed rectangle | =(yank-rectangle)= | 76 | | =C-x r c= | Clear RR, replacing all text with spaces | =(clear-rectangle)= | 77 | | =C-x r t string RET= | Replace rectangle contents with string on each line | =(string-rectangle)= | 78 | 79 | *** Expand Region 80 | [[https://github.com/magnars/expand-region.el][expand-region]] is one of those packages that you can live without, but as you use it more often, you find yourself repeatedly going back to it. [[http://emacsrocks.com/e09.html][Here's]] a great overview of expand-region. 81 | 82 | #+BEGIN_SRC emacs-lisp 83 | (use-package expand-region 84 | :bind (("C-=" . er/expand-region))) 85 | #+END_SRC 86 | 87 | ** Zap-to-char 88 | As an ex-vim user, I miss the =ct= and =dt= key dearly. Fret not, for what vim can do, emacs can do better. 89 | 90 | =zap-up-to-char= does exactly what it says it does: it kills up to, but not including the ARGth occurrence of CHAR. 91 | 92 | #+BEGIN_SRC emacs-lisp 93 | (autoload 'zap-up-to-char "misc" 94 | "Kill up to, but not including ARGth occurrence of CHAR." 95 | 'interactive) 96 | 97 | (bind-key* "M-z" 'zap-up-to-char) 98 | #+END_SRC 99 | 100 | Let's play with some examples: 101 | 102 | #+BEGIN_VERSE 103 | I think I love to eat pancakes and bananas. 104 | #+END_VERSE 105 | 106 | We begin from the start of the sentence. Now let's say we want to kill up to "think", I'd do =M-z t RET=. If I wanted to kill up to "to", then I provide an argument value of 2 to =zap-up-to-char= by pressing =M-2 M-z t RET=. 107 | 108 | Remember that the text is /killed/, which means it gets saved into the kill ring and can be retrieved at a later point in time through yanking. 109 | 110 | If you use [[Moving Within Visible Text][avy]], perhaps you'll find [[https://github.com/mrkkrp/zzz-to-char][zzz-to-char]] to your liking. It uses the avy interface to select which letter to zap up till. 111 | 112 | #+BEGIN_SRC emacs-lisp 113 | (use-package zzz-to-char 114 | :bind (("M-z" . zzz-up-to-char))) 115 | #+END_SRC 116 | 117 | ** Multiple-cursors 118 | Multiple cursors would be familiar functionality to Sublime Text users. It's the perfect tool for many things, including editing variable names with visual feedback. 119 | 120 | #+BEGIN_SRC emacs-lisp 121 | (use-package multiple-cursors 122 | :bind (("C->" . mc/mark-next-like-this) 123 | ("C-<" . mc/mark-previous-like-this) 124 | ("C-c C-<" . mc/mark-all-like-this))) 125 | #+END_SRC 126 | 127 | I use it in conjunction with =expand-region=: =expand-region= to select the keyword (variable names, for example), and use =C-c C-<= to select all instances of the variable, and simply type over it. 128 | 129 | ** Templating 130 | [[https://github.com/joaotavora/yasnippet][yasnippet]] is a templating system, allowing you to type an abbrieviation and automatically expand it into function templates with ==. This feature is similar to the one offered by Textmate; in fact, the templating language is inherited from it. 131 | 132 | #+BEGIN_SRC emacs-lisp 133 | (use-package yasnippet 134 | :diminish yas-global-mode yas-minor-mode 135 | :defer 5 136 | :init (add-hook 'after-init-hook 'yas-global-mode) 137 | :config (setq yas-snippet-dirs '("~/.emacs.d/snippets/"))) 138 | #+END_SRC 139 | 140 | Andrea Crotti maintains an [[https://github.com/AndreaCrotti/yasnippet-snippets][official repo]] for yasnippet templates. It supports many languages and major-modes. I recommend forking the repository -- as I did -- and cloning it as a git submodule under =~/.emacs.d=: this way you can add your own templates and version control them. I had set the =yas-snippet-dirs= to =~/.emacs.d/snippets=, so following that configuration: 141 | 142 | #+BEGIN_SRC bash 143 | git submodule add git@github.com:foobar/snippets.git ~/.emacs.d/snippets 144 | #+END_SRC 145 | 146 | ** Autocompletion 147 | Text completion in Emacs has Emacs users split between two major factions: autocomplete and company-mode. Both have similar feature sets, but it is generally argued that company-mode is more feature-rich. 148 | 149 | The following snippet installs [[http://company-mode.github.io/][company-mode]]. 150 | 151 | #+BEGIN_SRC emacs-lisp 152 | (use-package company 153 | :defer 5 154 | :diminish company-mode 155 | :init (progn 156 | (add-hook 'after-init-hook 'global-company-mode) 157 | (setq company-dabbrev-ignore-case nil 158 | company-dabbrev-code-ignore-case nil 159 | company-dabbrev-downcase nil 160 | company-idle-delay 0 161 | company-begin-commands '(self-insert-command) 162 | company-transformers '(company-sort-by-occurrence)) 163 | (use-package company-quickhelp 164 | :config (company-quickhelp-mode 1)))) 165 | #+END_SRC 166 | 167 | One thing that people miss from autocomplete is documentation popups. We add that functionality with [[https://github.com/expez/company-quickhelp][company-quickhelp]]. Another notable setting made was to set the delay for autocomplete to =0=. Play around with the numbers and see what you're comfortable with. 168 | 169 | Note that company-mode is merely a framework for autocompletion. To enable autocompletion for various languages, you'd need to install various company backends. 170 | 171 | *** [[file:project-management.org][Project Management]] :noexport: 172 | -------------------------------------------------------------------------------- /thoughtspeed-motion.org: -------------------------------------------------------------------------------- 1 | * Thought-speed Motion 2 | With a more usable Emacs configuration, we'll begin navigating around Emacs, installing helper libraries where relevant. 3 | 4 | I recommend printing [[https://www.gnu.org/software/emacs/refcards/pdf/refcard.pdf][this refcard]], and refer to it when necessary. 5 | 6 | The first rule to moving around quickly is to *never leave the keyboard*. This concept is pervalent across all efficient text editors, be it Vim or Emacs. In Emacs, key combinations are the gateway to text-editing nirvana. 7 | 8 | ** Moving Across Lines 9 | The most common line-movement operations are listed below. 10 | 11 | | Key | Movement | Emacs Function | 12 | |-----+------------------------------+-----------------------| 13 | | =C-e= | End of line | =(end-of-line)= | 14 | | =C-a= | Start of line | =(beginning-of-line)= | 15 | | =M-m= | first non-whitespace of line | =(back-to-indentation)= | 16 | 17 | #+BEGIN_QUOTE 18 | PROTIP: To check what a key combination is bound to, press =C-h k kbd=. Alternatively, =M-x describe-keybindings= lists all defined keys and their definitions in order of precedence. 19 | #+END_QUOTE 20 | 21 | ** Moving Within Visible Text 22 | [[https://github.com/abo-abo/avy][avy]] is a package for jumping to visible text using a char-based decision tree. Within three keystrokes, you're able to get to any visible point in the buffer. 23 | 24 | #+BEGIN_SRC emacs-lisp 25 | (use-package avy 26 | :bind* (("C-'" . avy-goto-char) 27 | ("C-," . avy-goto-char-2))) 28 | #+END_SRC 29 | 30 | #+BEGIN_QUOTE 31 | PROTIP: To jump back to your previous location, use =C-u C-space=. 32 | #+END_QUOTE 33 | 34 | ** Moving Within the Buffer 35 | *** isearch 36 | /isearch/ is short for incremental search. On several occasions you find yourself wanting to move to a different location of the document, knowing the textual content in the area. You can move to the location using the /isearch/, bound to =C-s=. To move to the next matching search result, press =C-s= again. The search can also be performed in the reverse direction, and this is bound to =C-r=. 37 | 38 | *** moccur 39 | /moccur/ is short for multi-occur. Some find this useful, but I personally feel like Swiper (introduced below) is sufficient for my day to day operations. The key benefit of /moccur/ is that a buffer for search result matches is created, and this can be used to move to the matched locations again. 40 | 41 | *** imenu 42 | imenu is short for interactive menu. Imenu offers a way to find the major definitions in a file by name. For example, in an Emacs Lisp (=.el=) file, you can navigate around with imenu to variables, and function definitions. In org-mode, you can navigate to title headers with imenu. Because of its utility, I bind it to =M-i=. 43 | 44 | #+BEGIN_SRC emacs-lisp 45 | (bind-key* "M-i" imenu) 46 | #+END_SRC 47 | 48 | To use =bind-key=, you need =use-package= installed. Skip this step if you intend to install counsel, described below. 49 | 50 | ** Registers 51 | #+BEGIN_QUOTE 52 | NOTE: Before I begin, note that while I introduce registers here, registers are not just for moving around the buffer. 53 | #+END_QUOTE 54 | 55 | Registers are compartments where text, rectangles, positions, window configurations and many more can be stored. Think of it as a temporal bookmarking system; these registers get wiped at the end of the Emacs process. Each register is denoted by a single character (eg. =?r= or =?1=). The register =?a= is different from the register =?A=. 56 | 57 | Whatever you store inside a register persists until it is overwritten by something else, or until the Emacs process is killed. 58 | 59 | Store a file in a register is simple: 60 | 61 | #+BEGIN_SRC emacs-lisp 62 | (set-register r '(file . name)) 63 | #+END_SRC 64 | 65 | Do this for all your bookmarks, and you can quickly jump to them with =C-x r reg=. 66 | 67 | To make things simpler, bind =jump-to-register= to a more accessible key: 68 | 69 | #+BEGIN_SRC emacs-lisp 70 | (bind-key* "C-o" 'jump-to-register) 71 | #+END_SRC 72 | 73 | Putting these in your =init.el= file ensures that they will always be available. I encourage you to play around with the other forms of registers. 74 | 75 | ** Bookmarks 76 | Bookmarks are similar to registers, but they are persisted in a file. 77 | 78 | To create a bookmark, type =C-x r m bookmark-name=. Similarly, bind =bookmark-jump= to a more accessible key: 79 | 80 | #+BEGIN_SRC emacs-lisp 81 | (bind-key* "C-o" 'bookmark-jump) 82 | #+END_SRC 83 | 84 | To change the file in which you store your bookmarks, invoke =M-x customize-variable bookmark-default-file=. 85 | 86 | ** Ivy, Counsel and Swiper 87 | Ivy is a generic completion mechanism for Emacs. It aims to be smaller, simpler and more highly customizable. 88 | 89 | Counsel provides a collection of Ivy-enhanced versions of command Emacs commands, including =find-file=, =describe-function= and =M-x=. 90 | 91 | [[https://github.com/abo-abo/swiper][Swiper]], the ivy-enhanced version of isearch. 92 | #+BEGIN_SRC emacs-lisp 93 | (use-package counsel) 94 | (use-package swiper 95 | :bind* 96 | (("C-s" . swiper) 97 | ("C-c C-r" . ivy-resume) 98 | ("M-a" . counsel-M-x) 99 | ("C-x C-f" . counsel-find-file) 100 | ("C-c h f" . counsel-describe-function) 101 | ("C-c h v" . counsel-describe-variable) 102 | ("C-c i u" . counsel-unicode-char) 103 | ("M-i" . counsel-imenu) 104 | ("C-c g" . counsel-git) 105 | ("C-c j" . counsel-git-grep) 106 | ("C-c k" . counsel-ag) 107 | ("C-c l" . counsel-locate)) 108 | :config 109 | (progn 110 | (ivy-mode 1) 111 | (setq ivy-use-virtual-buffers t) 112 | (define-key read-expression-map (kbd "C-r") #'counsel-expression-history) 113 | (ivy-set-actions 114 | 'counsel-find-file 115 | '(("d" (lambda (x) (delete-file (expand-file-name x))) 116 | "delete" 117 | ))) 118 | (ivy-set-actions 119 | 'ivy-switch-buffer 120 | '(("k" 121 | (lambda (x) 122 | (kill-buffer x) 123 | (ivy--reset-state ivy-last)) 124 | "kill") 125 | ("j" 126 | ivy--switch-buffer-other-window-action 127 | "other window"))))) 128 | #+END_SRC 129 | 130 | For a powerful preconfigured alternative, consider [[https://github.com/emacs-helm/helm][helm]] and its companion tutorial [[http://tuhdo.github.io/helm-intro.html][here]]. For something like Swiper, look at [[https://github.com/ShingoFukuyama/helm-swoop][helm-swoop]]. 131 | 132 | For a simpler in-built alternative, look at =ido-mode=, Mickey Petersen has a great write-up about it [[https://www.masteringemacs.org/article/introduction-to-ido-mode][here]]. 133 | 134 | *** [[file:thoughtspeed-editing.org][Thoughtspeed Editing]] :noexport: 135 | --------------------------------------------------------------------------------