Category Archives: geek

On this page:

Learning to design Help and Support communities: Apple deep dive

I’m looking at how people design help/Q&A communities to support a wide range of users. After looking at Adobe’s examples, I’d like to focus on another company well-known for design savvy: Apple.

2014-07-02 14_10_47-Official Apple SupportApple uses a two-screen automatically advancing carousel on its front page. I find that curious because the carousel doesn’t pause when you hover over it, although I guess that with only two slides, you can always wait until the icon you want slides back into place. If Apple did that in order to keep the Apple Support Communities and Contact Us links above the fold, I wonder why they didn’t move those links up higher and then keep a static list of icons underneath it instead. Anyway…

2014-07-02 14_15_15-Welcome _ Apple Support Communities

The main overview page has a big, simple Ask a Question widget that dynamically searches as you type. Underneath it, there are icons to the featured communities.

2014-07-02 14_16_48-Welcome _ Apple Support Communities

Clicking on an icon shows icons for subcommunities.

2014-07-02 14_17_21-Community_ Using iPad _ Apple Support Communities

All the communities I’ve checked out seem to follow these lines. Big group icon, group title, ask a question box right underneath the group title. There’s a manual slider with a custom category filter that loads the discussion list using AJAX, avoiding a page refresh.

2014-07-02 14_20_04-Community_ Boot Camp _ Apple Support Communities

Some of the communities have a Top Participants widget along the bottom.

The Apple communities focus exclusively on Q&A – they don’t link to tutorials or other resources to help people get better at using things. IF you click on the Content link, you can find tips, but they’re hidden and tend to fall off the recent content list. The Content link lists content for all the communities, not the particular community you’re interested in – the Apple discussions theme doesn’t include a link to the content for your particular community.

The discussion-focused approach is interesting, but probably a little too severe. Providing links to tutorials and frequently asked questions can help people who are getting started and don’t know what they don’t know. This information is available elsewhere (ex: http://www.apple.com/support/mac/), so that could explain why it’s not duplicated in the support site. Anyway, Apple’s support communities are clean and stripped down to the essentials.

 

Made my first laser cut thing!

I have access to a laser cutter and a 3D printer through Hacklab.to, but I had never actually tried to use either. I’d been mostly treating Hacklab as a way to hang out with interesting people. Still, since the tools are there, why not learn how to use them?

I looked through the supply closet to get a sense of what other people had been doing with the laser cutter, and what materials would be easy to work with. Acrylic and wood were popular. There were lots of whimsical cut-outs (hearts, scalloped edges, etc.), but I’d also heard stories about how useful the laser cutter was in creating boxes, cases, and other parts.

I browsed through photos of all sorts of laser-cut objects online (boxes? stencils? earrings?), but nothing jumped out as something I wanted to copy. I decided to start from scratch by drawing something in Inkscape. We’d been talking about some ways to make it easier for newcomers to figure out what they can do during open houses. They can start with a brief tour of the projects at Hacklab, and then settle in to work on a project or chat with other people. I figured a welcome sign might be handy. I found a stencil-type font that cut the shapes so that the inner spaces would stay attached. I also learned that Inkscape has a Lindenmayer system (L-system) evaluator, which is useful for making certain kinds of fractals. For fun, I decided to make a Koch snowflake as the frame. Eric Boyd helped me convert the design to G-code and run the machine. It was fascinating watching the paper burn in these intricate shapes.

We cut the welcome sign out of paper as a prototype. (We can always cut it out of cardboard or something fancier if we need to.) Here’s what it looked like:

2014-07-04 15.30.07

I’d like to get the hang of designing things for the laser cutter. It’s a little interesting pairing that with our general slant towards decluttering and minimizing stuff. Maybe as I learn more about the possibilities, I’ll find things that make me go “Ooh, that would be nice,” or even come across gaps that nudge me to make stuff up.

What’s next? Maybe a name tag that I can add a magnet to? A scarf buckle? Bookmarks? I don’t really wear earrings or necklaces any more, but a conversation piece might be handy when meeting people – so maybe a brooch. Various containers for things around the house? Hmm… I drew this, and I might be able to turn it into a bookmark after some tweaking:

cat

Learning from things I like: Smashing Magazine’s responsiveness

I’m teaching myself design by looking at things I like and trying to figure out why I like them. Smashing Magazine is not only a good blog for design inspiration, but it’s also (naturally!) a great example of techniques.

One of the things I like about Smashing Magazine is how the site adapts to different screen sizes. For example, if you view it on a mobile device or in a small window, you’ll see a simple header and the story.

2014-07-07 12_45_42-Smashing Magazine — For Professional Web Designers and Developers

The menu icon links to the footer menu, which is used only with narrow screens:

2014-07-07 13_08_53-Coding Archives _ Smashing Magazine

If you have a little more space, the header will include the top-leel site sections (books, e-books, workshops, job board) and the left sidebar will include categories. The search also moves from being hidden behind an icon to having its own space.

2014-07-07 12_45_26-Smashing Magazine — For Professional Web Designers and Developers

Even more space? The left sidebar gets collapsed into a small horizontal menu, and a right sidebar appears with an e-mail subscription form and some highlights from other sections. I wonder why the left sidebar is collapsed into the menu, but I guess it would be weird to have the category list jump from the left sidebar to the right sidebar and then back again, and they probably wanted the e-mail subscription form to be above the fold (so it wouldn’t make sense to add it to the left sidebar). The search box is moved to the top of the right sidebar, too, so it looks more like a background element.

2014-07-07 12_45_09-Smashing Magazine — For Professional Web Designers and Developers

Incidentally, here’s a little thing that happens when the window is just a little bit narrower – the WordPress menu item gets abbreviated to WP.

2014-07-07 13_05_24-Coding Archives _ Smashing Magazine

 

 

And here’s what the site looks like when I maximize the window. There’s the header, the left sidebar, and the right sidebar.

2014-07-07 12_44_45-

I also like Smashing Magazine’s use of colours – the cool blue matches well with the warm red, for some reason that I can’t quite explain at the moment. I also like how they use different grays to make things recede into the background.

When I redesigned my site, I wanted to do something like the responsiveness of Smashing Magazine, so I learned more about using media queries. Here’s how my site behaves at different sizes. (Or at least, how it should!) On a small screen, the key links are just hand-drawn icons, and there’s no sidebar:

2014-07-07 12_50_57-sacha chua __ living an awesome life - learn - share - scale

Slightly wider? I can add some text to the links, and I can add a couple of optional links like Random.

2014-07-07 12_51_17-sacha chua __ living an awesome life - learn - share - scale

On a normal-sized screen, I add a sidebar on the right side.

2014-07-07 12_51_32-

On a wide screen, I move the post meta information to the left margin.

2014-07-07 12_51_54-sacha chua __ living an awesome life - learn - share - scale

Learning to design Help and Support communities: Adobe deep dive

Design seems like magic, but it’s probably a skill that I can develop. If I just focus on coding, the things I build can end up looking like an accumulation of little ideas designed by committee. If I learn more about design and develop my own opinions, I can make recommendations that simplify the experience and make it more coherent. For example, on one of my consulting engagements, I could probably take the initiative in redesigning the help and support community for a better user experience. I have to work with the technical limitations of the platform, but as a coder, I have a little more latitude than most people do. By looking at how other people have structured their support experiences, maybe I can pick up ideas that I can try.

It’s interesting to see how much variety there is even within one company. Adobe uses the Jive platform for its support communities, and the different products have slightly different configurations. Here’s the overall product page that leads to the community page:

Adobe

Adobe

http://helpx.adobe.com/photoshop.html

Adobe starts with graphical icons for tutorials that have time estimates clearly indicated.

2014-07-02 13_37_08-Community_ Photoshop General Discussion _ Adobe Community

https://forums.adobe.com/community/photoshop

The “Ask the Community” page leads to a page with a lot of things going on, but there’s an “Ask a Question” widget in the top left with a quick way for people to ask questions. With the emphasis on points and the leaderboard of top participants, it seems that this community focuses on user-to-user support. That’s probably why the Unanswered Questions and Trending Questions widgets are so prominent. Still, the page feels a little cluttered to me. I’d probably prefer to set it up with fewer calls to action. Ask a Question would still be in the top left, but I would probably organize the resources by skill level. I like the way some of the frequently asked questions are highlighted, but they feel somewhat random and not well-formatted.

Different products have different community pages. The Illustrator one is slightly more neatly organized:

2014-07-02 13_43_51-Community_ Illustrator _ Adobe Community

https://forums.adobe.com/community/illustrator

I like the announcement box for Illustrator CC 2014 and the Getting Started box in a prominent place. This page feels more oriented towards new users. It still has trending and unanswered questions, but they’re below the fold.

2014-07-02 13_46_28-Community_ Premiere Pro _ Adobe Community

https://forums.adobe.com/community/premiere

The Premier Pro community focuses on sub-forums. Based on the forum activity, it looks like the Forums widget does a decent job of directing people to the appropriate place to ask, although the main community still gets many questions. This community is less newbie-focused (no tutorial link). The Recent Discussions widget seems to be a better choice than having both Unanswered Questions and Trending Questions, since the other widgets are visually similar and often have duplicate content.

2014-07-02 13_50_10-Community_ After Effects _ Adobe Community

https://forums.adobe.com/community/aftereffects_general_discussion

The After Effects community has a welcome message and a Getting Started box, which I think are good ideas. They’ve decided to highlight some discussions as Sticky Threads, too. Unlike the other communities, this community doesn’t include messages about translating pages or earning points. I wonder how de-emphasizing points affects user-to-user support…

2014-07-02 13_54_57-Community_ Lightroom for Beginners _ Adobe Community

https://forums.adobe.com/community/lightroom/lightroom_for_beginners

The Lightroom for Beginners community uses graphics (that responsively resize, even!) to make frequently-asked questions more visually interesting.

2014-07-02 13_57_21-Community_ Acrobat _ Adobe Community

https://forums.adobe.com/community/acrobat

The Acrobat community directs people to the appropriate sub-forum.

2014-07-02 13_59_54-Welcome _ Adobe Community

https://forums.adobe.com/welcome

The overall welcome page for the site is static and graphical.

I think the key points I’ll pick up from Adobe’s support communities are:

  • A Welcome box makes a support community less intimidating.
  • Although having separate widgets for unanswered questions or trending content makes it easier for community managers and volunteers to find questions to respond to, that can lead to visual clutter. Recent discussions or recent content will do the job well enough.
  • Consistent formatting helps resource lists look more professional. Some of the resource lists had different font sizes or bullet types within the same box.
  • Images go a long way towards making a site look more polished.

Know any well-designed community support sites that offer both tutorials and Q&A? I’d love to take a closer look at them! Up next: Probably Apple, who use Jive as well.

 

 

 

Read Lisp, Tweak Emacs (Beginner 4/4): “How can I add more features? How do I deal with errors?”

This entry is part 4 of 4 in the series Read Lisp, Tweak Emacs

Previous module: “How can I make things more convenient?”

Some conventions we’ll use:

  • Inline code will be boxed and monospace in the HTML version and generally surrounded by equal signs in plain text.
  • Code samples will be monospace and in boxes in the HTML version, and enclosed in #+begin_src#+end_src in plain text. Example:
    (message "Hello world")
    

After this module, you’ll be able to:

  • load libraries so that you can add new features or set configuration variables
  • install and configure packages in order to add more features to your Emacs
  • understand and fix common errors
  • learn more! =)

Adding more features to Emacs

Most Emacs libraries are not loaded automatically. This saves memory and keeps things simpler. Some of the customizations you may want to make require that other parts of Emacs are loaded first. For example, if you want to define a key for the c-mode-map (used for editing C code) or add a function to org-mode-hook (called when a buffer is set up with Org Mode), those libraries need to be loaded first. You can load libraries by using require, like this:

(require 'org)

This loads the org library. require looks for a file named after the name provided to it, loads it, and double-checks that the library includes (provide 'feature-name-goes-here). It signals a Cannot open load file error if the library is not found. If the library exists but does not provide that symbol, you’ll get a Required feature FEATURE was not provided error instead.

Note that the symbol you give to require might not be the same as the function you call. For example, c-mode is actually defined in the cc-mode library, while org-mode is defined in org. To find out what file a function is defined in, use C-h f (describe-function) followed by the name of the function. The first line will tell you what file the function is defined in, if any. For example, c-mode‘s definition starts with:

c-mode is an interactive autoloaded compiled Lisp function in
`cc-mode.el'.

The first part of the filename (before the .el or .elc) is usually what you would use with require. If you have the source installed (the .el file), you can look for the (provide ...) expression to find the actual symbol to use.

Installing packages

Emacs comes with a lot of code, but there are even more packages out there. When you read other people’s Emacs configurations, you might come across other interesting packages to try out.

Sometimes people don’t indicate which packages they use, so you have to guess the package name based on the function. For example, (global-auto-complete-mode) turns on a completion mode called auto-complete-mode in all buffers. Before you can use this, you will need to install the auto-complete package. In general, you can find package names by looking at functions that include mode in their name, removing global, turn-on, and other prefixes as needed.

The default package repository in Emacs 24 has a limited number of packages. For more choices, you may want to add another repository such as MELPA or Marmalade Here’s the code that you would run in order to add these repositories to your Emacs:

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"))
(add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/"))

Note that MELPA includes many packages under active development. If you prefer to install only the packages marked as stable, replace the MELPA line with this:

(add-to-list 'package-archives '("melpa-stable" . "http://hiddencameras.milkbox.net/packages/"))

If you’re connected to the Internet, use M-x package-refresh-contents to update the list of packages. Use M-x package-list-packages to list the available packages. RET displays the package’s description. i marks the current package for installation, and x actually performs the operations. If you know the name of the package you want to install, you can skip the list and use M-x package-install instead.

A lightweight list of the key functions defined by packages is loaded after your init.el is run. You can start that initialization earlier by adding (package-initialize), which is useful if you want to call functions that are defined in packages.

Sometimes people want to install some packages on one computer but not on another. Here’s some code that runs some configuration if the miniedit package can be loaded, but silently continues if the package has not been installed.

(when (require 'miniedit nil t)
   (miniedit-install)
   (define-key minibuffer-local-map (kbd "C-c e") 'miniedit))

If you use C-h f (describe-function) on require, you’ll see that it has one required argument (feature) and two optional arguments (filename, noerror). require returns non-nil (or true) if the library was loaded, so if the library exists, then the rest of the code inside the when expression gets called.

Along those lines, you may come across code that looks like this:

(eval-after-load "dash" 
  '(dash-enable-font-lock))

This runs (dash-enable-font-lock) only after dash is loaded. It does not automatically load dash. You’ll see this when people have configuration that they want to run only if something is loaded, which can make sense for performance reasons. When you’re starting out, you may want to use require instead of eval-after-load, since the argument to eval-after-load has to be quoted.

Other Emacs Lisp files

Some files are not yet available as packages. If you search for the function, you’ll probably find a webpage with an .el file. You can save those to your computer and load them with:

(load "/path/to/file")

You can also use this technique to split up your Emacs configuration file into smaller files. For example, you might have an org-config.el file, a programming-config.el file, and so forth. If you would like to load a host-specific file only if it exists, you can take advantage of the optional NOERROR argument for load like this:

(load (concat "~/.emacs.d/" (system-name) ".el") t)

Want to find out what that filename is? Position your cursor after the ​".el") and use C-x C-e (eval-last-sexp) to see the value in the buffer.

Use C-h f (describe-function) to learn more about the load function, including other arguments you can pass to it.

If you would like to use the require syntax to load files only if they haven’t already been loaded, you can do that as long as they include the (provide ...) expression somewhere. First, you’ll need to add your downloaded Emacs Lisp file to the load-path with something like this.

(add-to-list 'load-path "/path/to/dir/with/el/files")

Then you can use require to load the Emacs Lisp code if it exists.

(require 'feature-name)

“Oh no! I have an error!”

Part of learning Emacs is having the confidence to experiment, which you can develop by learning how to recognize and deal with different errors.

If you’ve already added the code to your ~/.emacs.d/init.el, you can start Emacs with emacs --debug-init to display debugging messages, or you can start Emacs with emacs -q to skip your personal configuration. Before reporting a bug with Emacs or with a package, use emacs -q (or emacs -Q, which skips site-wide configuration as well) to see if it works as intended without your personal configuration.

To make it easier to find errors while Emacs is running, use M-x toggle-debug-on-error, then do whatever you did to trigger the error. You will probably see a detailed list of functions called in the *Messages* buffer. If you find this useful, you can enable this by default in your ~/.emacs.d/init.el. Add:

(setq debug-on-error t)

If you have code that takes a while, you might find the debug-on-quit variable or the M-x toggle-debug-on-quit function useful as well. You can quit a long-running operation by using C-g (keyboard-quit).

You can narrow down the source of the problem by progressively commenting out more and more of the code. Make sure you comment out balanced sets of parentheses. To comment a region, select it and use M-x comment-region. You can use M-x uncomment-region to uncomment it. M-x comment-dwim (do what I mean) guesses whether you want to comment or uncomment something, and has the handy keyboard shortcut M-;.

Here are some common error messages and how you can try fixing them. If you don’t see the error you’re struggling with here, ask the relevant mailing list, help-gnu-emacs, the #emacs channel on irc.freenode.net, or StackOverflow for help. Good luck!

Scan error: “Unbalanced parentheses” or “Containing expression ends prematurely”

You may have pasted in something that has a “(” but no matching “)“, which results in unbalanced parentheses. Alternatively, you may have pasted in something that has “)” but no “(“, which results in a premature end. You can use M-x check-parens to quickly check for mismatched parentheses, or try reading the code carefully in order to find the mismatched pair. You can also use C-M-f (forward-sexp) and C-M-b (backward-sexp) to navigate by complete expressions until you find the specific one that causes the error.

Cannot open load file: …

The code is trying to require or load a file that Emacs can’t find.

  • Have you installed the appropriate package? Use M-x list-packages to see if it has been packaged into a form that’s easy to install. You may need to add other sources to your package-archives to see a wider range of packages.
  • Have you downloaded it manually and added it to your load-path? See the notes on load-path for more details.
  • If you’re using load, does the file exist?

Lisp error: (void-function …)

The code calls a function that has not been defined.

  • Have you installed the appropriate package? Look at the function name and try to guess the name of the package. People usually start the function name with the package name in order to make the function names unique. Use M-x list-packages to see the available packages. You may need to add other sources to your package-archives to see a wider range of packages.
  • If you downloaded the library manually, load or require it.
  • If you’re copying some code that isn’t packaged in a library, check if there are any defun (define function) expressions that you forgot to copy. Make sure to include and evaluate those.

Symbol’s value as variable is void: _

The code is trying to get the value of a variable that has not yet been set. See if there’s other code that you need to evaluate first in order to set up those variables. If the expression involves add-to-list or add-hook, you may need to use require to load the library that defines that list or hook first.

You might also get this if you’re using C-x C-e (eval-last-sexp) to evaluate an expression that’s inside let or other things that create variables. When you’re starting out, make sure you use C-x C-e (eval-last-sexp) after the outermost set of parentheses.

I’m using C-x C-e (eval-last-sexp) and I don’t get the results I expected

Make sure you call C-x C-e after the outermost ) for the expression you want to evaluate.

(ido-mode 1)
            ^
            |
            +---- Your cursor should be here

If the code you’re looking at has multiple expressions, you’ll need to call C-x C-e after each of them. It might be easier to select the region and use M-x eval-region, or evaluate the entire buffer with M-x eval-buffer. Alternatively, use M-x ielm to evaluate the code instead.

Again, if you don’t see the error you’re struggling with here, ask the relevant mailing list, help-gnu-emacs, the #emacs channel on irc.freenode.net, or StackOverflow for help. Good luck!

Wrapping up the beginner course

I hope that this course has helped you become more comfortable with reading and tweaking Emacs Lisp configuration code from blog posts, wiki pages, and other resources. There’s much more to learn, of course. With describe-function, describe-variable, and the ability to quickly experiment with Emacs Lisp code without restarting Emacs all the time, I’m sure you’ll get the hang of it! If you’d like to review or refer to this course, you can get it as one page at http://emacslife.com/how-to-read-emacs-lisp.html .

Check out An Introduction to Programming in Emacs Lisp, and delve into the Emacs Lisp Reference Manual for more details. Both are available within Emacs as Info manuals, which you can read with C-h i (info). Look for the Emacs Lisp Intro and Elisp entries, and browse through those manuals for more details. To search the current info manuals, type s (Info-search). To search all info manuals, use M-x info-apropos.

If you liked this or you have other questions, please get in touch – [email protected]. I’d love to hear from you, and I’m happy to help with other Emacs questions you may have. Good luck and have fun!

More links:

Series Navigation« Read Lisp Tweak Emacs (Beginner 3/4): How can I make things more convenient?

Read Lisp Tweak Emacs (Beginner 3/4): How can I make things more convenient?

This entry is part 3 of 4 in the series Read Lisp, Tweak Emacs

“How can I customize Emacs to make things more convenient?”

After this module, you’ll be able to:

  • define your own keyboard shortcuts so that you can call functions more easily
  • work with custom functions that other people have defined in their configurations
  • copy and use anonymous functions

Keyboard shortcuts

The default keyboard shortcuts (or “keybindings”) can be difficult to remember, and many useful functions don’t have any keyboard shortcuts at all. People often set up their own keyboard shortcuts to make other commands easier to use. There are different ways to assign keys depending on where you want the keybinding to be available.

Setting keybindings in all buffers

You can assign a key to a function globally, which means that it will be available in buffers of any type if there are no mode maps or local keybindings that override it. (Mode maps are set by major modes like emacs-lisp-mode or minor modes like auto-fill-mode.) Setting a global keybinding is usually done with global-set-key, although sometimes you’ll see it done with define-key and global-map.

You can use global-set-key interactively by calling it with M-x global-set-key. Type the keyboard shortcut you would like to set, then specify the name of the function you would like Emacs to call. Note that the function must be interactive – that is, it must be something you can call with M-x and it should include (interactive ...) in its definition. For example, try M-x global-set-key, then press <f10>, and assign it to save-buffer. After you do that, you should be able to press <f10> to save the current buffer.

If you like a keybinding that you’ve interactively set, use C-x ESC ESC (repeat-complex-command) to see the Emacs Lisp code for it. You can copy and paste that into your configuration. For example, setting the keybinding above will result in:

(global-set-key [f10] (quote save-buffer))

You can also write keybindings from scratch. For example, the code below redefines the Return key (or the Enter key) so that it calls the newline-and-indent function by default.

(global-set-key (kbd "RET") 'newline-and-indent)

Remember, ​'newline-and-indent and (quote newline-and-indent) are the same thing – they both refer to the name of a thing (a function, in this case) instead of its value.

(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)

These set C-+ (Ctrl and <plus>) and C-- (Ctrl and <minus>) to increase and decrease the font size when you’re running Emacs in a graphical environment.

If you want to set a keyboard shortcut only in particular modes or types of files, jump ahead to Setting keybindings in a particular mode.

What does kbd do? How can I figure out which key it sets?

If you’ve gone through the Emacs Tutorial (Help – Emacs Tutorial or C-h t), you’ll be familiar with many of the conventions used for writing keyboard shortcuts. C- stands for the Ctrl key, M- stands for the Meta key (which is probably Alt or Option on your keyboard). There are other prefixes as well. S- is for Shift, H- is for Hyper, and s- is for Super. Some people use operating system tools (such as setxkbmap for Linux) to change keys on their keyboard to Super or Hyper in order to enable even more keyboard shortcuts.

Uppercase or lowercase depends on the character in the shortcut. C-x means Control + x, while C-X is actually Control + Shift + X. You can also specify shift by adding S-, so C-X and C-S-x are the same.

In addition, there are some special characters: RET, SPC, TAB, and ESC must be written in uppercase to mean the special keys they refer to. (There’s also LFD and NUL, but you’re probably not going to encounter those as often.) You can use angle brackets to refer to some other keys, like <return>, <up>, <down>, <left>, <right>. Function keys are written like this: <f1>.

There are different ways to specify the key. Many people use (kbd ...) because it makes bindings easy to read.

(global-set-key (kbd "M-/") 'hippie-expand)

This is the same as

(global-set-key "\M-/" 'hippie-expand)

or

(global-set-key [?\M-/] 'hippie-expand)

You can use ^ to mean Control, so

(global-set-key (kbd "C-s") 'isearch-forward-regexp)

is the same as either of these lines:

(global-set-key "\C-s" 'isearch-forward-regexp)
(global-set-key (kbd "^s") 'isearch-forward-regexp)

but C- is probably easier to read.

When you use kbd, whitespace doesn’t usually matter, but it’s easier to read if you use space to separate the keys to type. For more information about the syntax used by kbd, see C-h f (describe-function) for kbd, then follow the link to the documentation for edmacro-mode.

In general, you can use C-h k (describe-key) followed by a keyboard shortcut to see if it’s already bound, and if so, what function it calls. If you type C-h k and the key you’re interested in, and Emacs is still waiting for another key, then you’re probably looking at a prefix key. For example, C-x is a prefix key that’s used in keyboard shortcuts like C-x C-e (eval-last-sexp).

Multi-key shortcuts

You can set up keybindings that use more than one key combination. This is a popular technique since you can only have so many short keybindings. For example, the following code changes C-x C-b to call ibuffer, which lists your buffers and makes it easy to jump to another buffer.

(global-set-key (kbd "C-x C-b") 'ibuffer)

You don’t have to start with C-c or C-x. Consider using one of your function keys like <f9> as the start of your keyboard shortcuts. Then you can create shortcuts that don’t involve using Ctrl, Alt, or other modifier keys. For example:

(global-set-key (kbd "<f9> b") 'ibuffer)

Read other people’s configurations to get a sense of useful commands and handy keyboard shortcuts. By convention, shortcuts like C-c followed by a lowercase or uppercase letter are reserved for your use, as are the function keys <f5> to <f9>. Other keyboard shortcuts are likely to already be defined by modes. You can override them if you want.

Some people like using a function key followed by letters in order to minimize the need to press Control or Meta. For example, you might use:

(global-set-key (kbd "C-c r") 'query-replace)

or

(global-set-key (kbd "<f9> r") 'query-replace)

to make it easier to replace strings. You can even bind it to both shortcuts.

Binding keys to other keys

In addition to setting keyboard shortcuts for functions, you can also define keys to expand to a longer sequence of keystrokes. You can use this for inserting strings or calling keyboard macros. For example:

(global-set-key (kbd "<f7> e") "[email protected]")
(global-set-key (kbd "<f7> w") "http://example.com")
(global-set-key (kbd "<f7> u") (kbd "C-x C-s"))

These might be handy for quickly inserting your e-mail address or website.

Dealing with errors: “Key sequence __ starts with non-prefix key _

If you want to create a multi-key shortcut, the preceding keys must not already be assigned to functions. For example, if you want M-t l to call transpose-lines, you’ll need to get rid of M-t‘s default binding to transpose-words first. To unset a key, bind it to nil or use global-unset-key. Here’s a group of shortcuts you can try.

(global-set-key (kbd "M-t") nil) ;; Remove the old keybinding
(global-set-key (kbd "M-t c") 'transpose-chars)
(global-set-key (kbd "M-t w") 'transpose-words)
(global-set-key (kbd "M-t t") 'transpose-words)
(global-set-key (kbd "M-t M-t") 'transpose-words)
(global-set-key (kbd "M-t l") 'transpose-lines)
(global-set-key (kbd "M-t e") 'transpose-sexps)
(global-set-key (kbd "M-t s") 'transpose-sentences)
(global-set-key (kbd "M-t p") 'transpose-paragraphs)

The example above has three bindings for transpose-words. M-t w uses the mnemonic of t-ranspose w-ords. M-t t is similar to the original binding for transpose-words, which was M-t. M-t M-t may seem like overkill, but sometimes you’ll find it easier to hold the Meta key down and hit t twice quickly instead of typing M-t, releasing Meta, and then typing t. As you read other people’s keybindings, you’ll get a sense of how people have configured their keyboard shortcuts to speed up typing and minimize thinking.

Setting keybindings in a particular mode

Sometimes you want keys to do different things in different types of files. Modes are how Emacs changes behaviour based on context. For example, Java files use java-mode, Org files use org-mode, and so forth. In addition to the major mode for a buffer, you may have several minor modes that modify the behaviour. Each mode has a keybinding map (or a “keymap”). You can assign a key in a mode map, which means it will override global keybindings in buffers with that mode. You can do this with define-key if you know the name of the keymap you want to change, which is generally the name of the mode + -map. For example:

(define-key emacs-lisp-mode-map (kbd "C-c f") 'find-function)

changes the C-c f keyboard shortcut to find-function (which jumps to the definition of a function), but only in Emacs Lisp buffers.

Note that if you use define-key with a mode map, the mode must already be loaded by the time this code is run. That’s why you’ll often see this after a require (which loads the code) or inside an eval-after-load (which postpones the code until after the mode is loaded). See Adding more features to Emacs for information on loading packages and adding new functions to Emacs.

Other ways people bind keys

The bind-key package provides a function that makes it easier to see your personal keybindings, but bind-key is not part of Emacs by default. I use bind-key a lot in my configuration. The syntax is similar to global-set-key, except it automatically wraps the keyboard shortcut string in kbd. It also keeps track of which keyboard shortcuts you’ve overridden so that you can use M-x describe-personal-keybindings to review them.

(bind-key "C-+" 'text-scale-increase)
(bind-key "C--" 'text-scale-decrease)

You’ll need to install and use the bind-key package before you can use that code.

Because keybinding is something that lots of people do to customize their Emacs, you may find other ways that people have simplified writing keybindings for themselves. When in doubt, use C-h f (describe-function) to explore how something works. If the function can’t be found, see if it’s in a package somewhere, or search the Web for more information.

For more about keybindings, see the Emacs manual and this Mastering Emacs post on keybindings.

Defuns – function definitions

In addition to the functions built into Emacs or available in packages, many people define their own with the defun function.

People often distinguish custom functions by starting them with my/ or their initials. This makes it easier to tell which functions they’ve customized and which ones are part of a package. It also minimizes the risk of accidentally overriding a function defined elsewhere. You can change the name of a function as long as you make sure you change the name wherever it’s called, such as in keyboard shortcuts, hooks, or other functions.

For example, here’s a custom function from Jorgan Schaefer’s config:

(defun fc/kill-to-beginning-of-line ()
  "Kill from the beginning of the line to point."
  (interactive)
  (kill-region (point-at-bol) (point)))

This creates a function called fc/kill-to-beginning-of-line. () is the argument list. Since it doesn’t contain anything, that means this function does not take arguments. ​"Kill from the beginning of the line to point."​ is a documentation string (or docstring) that describes what the function does. Docstrings are optional, but highly recommended. (interactive) means that this can be called with M-x (execute-extended-command) or bound to a keyboard shortcut.

If a function does not have the (interactive) keyword, you won’t be able to call it with M-x or assign it to a keyboard shortcut, but you will still be able to write Emacs Lisp code that calls the function. This means M-x (execute-extended-command) lists only the commands that people will probably find useful while working directly with Emacs, skipping internal functions used by code.

Once you’ve defined a custom function, you can bind it to a keyboard shortcut if you want. The code below binds the fc/kill-to-beginning-of-line function to C-c C-u:

(global-set-key (kbd "C-c C-u") 'fc/kill-to-beginning-of-line)

You will often see custom functions added to hooks. A hook is a list of functions that’s called by some other code. Modes usually define a hook that’s called after the mode is initialized so that you can further customize its behaviours. For example, emacs-lisp-mode has an associated emacs-lisp-mode-hook which is run when a buffer is set up in Emacs Lisp Mode. You can add built-in functions or custom functions to hooks, and they’ll be run when that hook is called.

People sometimes use hook functions to set up keybindings instead of using define-key. For example, this code:

(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
(define-key emacs-lisp-mode-map (kbd "C-c f") 'find-function)

can also be written as:

(defun my/set-up-emacs-lisp-shortcuts ()
  "Set up some conveniences for Emacs Lisp."
  (turn-on-eldoc-mode)
  (local-set-key (kbd "C-c f") 'find-function))
(add-hook 'emacs-lisp-mode-hook 'my/set-up-emacs-lisp-shortcuts)

Lambdas – anonymous functions

Sometimes people just want to create a keyboard binding or process some data without defining a new function. lambda creates an anonymous function, which is a function that doesn’t have a name. Here’s an example:

(global-set-key (kbd "C-c e") (lambda () (interactive) (find-file "~/.emacs.d/init.el")))

This binds C-c e to an anonymous function. The () means it doesn’t take any arguments. (interactive) means it can be called through a keyboard shortcut, although since it’s anonymous, it can’t be called with M-x. The function opens the ~/.emacs.d/init.el file, which is a handy way to edit your configuration.

  1. Look for an Emacs configuration file that defines keybindings that you’re curious about. Install any packages or copy any custom functions needed. Experiment with using those keybindings. Do you like them? Do you want to tweak them further?
  2. Think about how you use Emacs. What kinds of keyboard shortcuts would make your work easier? How can you adapt some of the functions you’ve read into things that would make them even more convenient for you?
You can find the draft of the complete course at emacslife.com/how-to-read-emacs-lisp.html. Enjoy!
Series Navigation« Read Lisp Tweak Emacs [Beginner 2/4]: How to understand what Emacs Lisp code doesRead Lisp, Tweak Emacs (Beginner 4/4): “How can I add more features? How do I deal with errors?” »