"People talk about getting used to a new editor, but over time, it is precisely the opposite that should happen - the editor should get used to us." - Vivek Haldar

Now that Emacs has moved to git, maybe it's time to start contributing directly? Here's how you build Emacs from source on OS X: git clone git://git.savannah.gnu.org/emacs.git cd emacs ./autogen.sh ./configure --with-ns make install cd nextstep open Emacs.app For more info and instructions for other distros, see Lars' post.

I mess up a lot, and often want to do a quick amend to the last commit. ( defun magit-just-amend () (interactive) ( save-window-excursion (magit-with-refresh (shell-command "git --no-pager commit --amend --reuse-message=HEAD" )))) ( eval-after-load "magit" '(define-key magit-status-mode-map (kbd "C-c C-a" ) 'magit-just-amend)) This code will let me just press C-c C-a and it amends with no fuss at all. Thanks to this post for the inspiration. Update! As noted by Kyle Meyer in the comments below, this no longer works in the newest magit. Instead you should be using the built in Extend Commit command: c e .

Ever been annoyed at the lack of reindentation after using sgml-delete-tag? ( defadvice sgml-delete-tag (after reindent activate) (indent-region (point-min) (point-max))) Be annoyed no more! This blogpost brought to you live from WebRebels 2013.

I already covered the awesomely commented diminish.el. Here's another trick to reduce the cruft in your modeline: ( defmacro rename-modeline (package-name mode new-name) `( eval-after-load ,package-name '( defadvice ,mode (after rename-modeline activate) (setq mode-name ,new-name)))) (rename-modeline "js2-mode" js2-mode "JS2" ) (rename-modeline "clojure-mode" clojure-mode "Clj" ) With this, I reduce the js2-mode modeline lighter from "JavaScript IDE" to just "JS2". I stole it from Bodil's .emacs.d and macroified it a little. The first argument is the package name, the second is the mode in question, and the third is the new lighter for the mode.

Undo in region is one of those mind-blowing things about emacs. However, the region keeps jumping about when I use it. So I added this: ( defadvice undo-tree-undo (around keep-region activate) ( if (use-region-p) ( let ((m (set-marker (make-marker) (mark))) (p (set-marker (make-marker) (point)))) ad-do-it (goto-char p) (set-mark m) (set-marker p nil) (set-marker m nil)) ad-do-it)) Now the region stays in place while I'm undoing. Since I use undo-tree, that's what it advises, but I would guess it works the same for regular old undo too.

Where do you put your project specific settings? ( defmacro project-specifics (name &rest body) ( declare (indent 1)) `( progn (add-hook 'find-file-hook ( lambda () ( when (string-match-p ,name (buffer-file-name)) ,@body))) (add-hook 'dired-after-readin-hook ( lambda () ( when (string-match-p ,name (dired-current-directory)) ,@body))))) (project-specifics "projects/zombietdd" (set (make-local-variable 'slime-js-target-url) "http://localhost:3000/" ) (ffip-local-patterns "*.js" "*.jade" "*.css" "*.json" "*.md" )) I created this macro to help me set up local vars. So in the example, any files in projects/zombietdd will see these slime-js-target-url and the find-file-in-projects patterns. I keep these in a projects-folder to keep track of all the different settings for my projects.

I mainly use org-mode for a collection of TODO-lists. ( defun myorg-update-parent-cookie () ( when (equal major-mode 'org-mode) ( save-excursion ( ignore-errors (org-back-to-heading) (org-update-parent-todo-statistics))))) ( defadvice org-kill-line (after fix-cookies activate) (myorg-update-parent-cookie)) ( defadvice kill-whole-line (after fix-cookies activate) (myorg-update-parent-cookie)) So I get a little annoyed when the [17/23] cookies at the parent level aren't updated when I remove an item. This code fixes that.

In html-mode, forward/backward-paragraph is infuriatingly slow. ( defun skip-to-next-blank-line () (interactive) ( let ((inhibit-changing-match-data t)) (skip-syntax-forward " >" ) ( unless (search-forward-regexp "^\\s *$" nil t) (goto-char (point-max))))) ( defun skip-to-previous-blank-line () (interactive) ( let ((inhibit-changing-match-data t)) (skip-syntax-backward " >" ) ( unless (search-backward-regexp "^\\s *$" nil t) (goto-char (point-min))))) ( eval-after-load "sgml-mode" '( progn (define-key html-mode-map [remap forward-paragraph] 'skip-to-next-blank-line) (define-key html-mode-map [remap backward-paragraph] 'skip-to-previous-blank-line))) I use them a lot for quick navigation. In html-mode, they are anything but quick. Defining paragraphs in Emacs is black magic, and I'm not sure it's a good idea to change that in case something else relies on its erratic behavior. Instead I just remap the commands to my home brewed skip-to-next/previous-blank-line. Ahh, speedy and predictable navigation once more.

Okay, this is a bad idea if your files are prefixed with ~ . (add-hook 'ido-setup-hook ( lambda () (define-key ido-file-completion-map (kbd "~" ) ( lambda () (interactive) ( if (looking-back "/" ) (insert "~/" ) (call-interactively 'self-insert-command)))))) But if they're not, this keybinding lets you even more quickly reach your home folder when in ido-find-file. It doesn't matter if you're a million directories in, just press ~ to go home.

In dired, M-> and M- never take me where I want to go. ( defun dired-back-to-top () (interactive) (beginning-of-buffer) (dired-next-line 4)) (define-key dired-mode-map (vector 'remap 'beginning-of-buffer) 'dired-back-to-top) ( defun dired-jump-to-bottom () (interactive) (end-of-buffer) (dired-next-line -1)) (define-key dired-mode-map (vector 'remap 'end-of-buffer) 'dired-jump-to-bottom) That is, now they do. Instead of taking me to the very beginning or very end, they now take me to the first or last file.

I use Phil Hagelbergs' find-file-in-project, but fuzzy matching with LOTS of files can be suboptimal. ( defun ffip-create-pattern-file-finder ( &rest patterns) ( lexical-let ((patterns patterns)) ( lambda () (interactive) ( let ((ffip-patterns patterns)) (find-file-in-project))))) (global-unset-key (kbd "C-x C-o" )) (global-set-key (kbd "C-x C-o ja" ) (ffip-create-pattern-file-finder "*.java" )) (global-set-key (kbd "C-x C-o js" ) (ffip-create-pattern-file-finder "*.js" )) (global-set-key (kbd "C-x C-o jp" ) (ffip-create-pattern-file-finder "*.jsp" )) This function limits the search to files of a specific file type. I've got loads more of these keybindings, all of them with the two-letter mnemonic shortcut. It really speeds up finding files. Both because ido-completing-read has less matches to worry about, because there are fewer similarly named files, and especially when the .java, the .js and the .jsp share a name.

Here's one keybinding I could not live without. (global-set-key (kbd "M-j" ) ( lambda () (interactive) (join-line -1))) It joins the following line onto this one. Let's say I want to collapse this paragraph-tag to one line: < p class = "example" > Some text over multiple lines. </ p > With point anywhere on the first line, I simply press M-j multiple times to pull the lines up.

There are lots of neat ways of moving around quickly in a buffer. (global-set-key (kbd "C-S-n" ) ( lambda () (interactive) ( ignore-errors (next-line 5)))) (global-set-key (kbd "C-S-p" ) ( lambda () (interactive) ( ignore-errors (previous-line 5)))) (global-set-key (kbd "C-S-f" ) ( lambda () (interactive) ( ignore-errors (forward-char 5)))) (global-set-key (kbd "C-S-b" ) ( lambda () (interactive) ( ignore-errors (backward-char 5)))) For instance, check out Emacs Rocks e10: Jumping Around. But sometimes I just want to browse a little. Or move a few lines down. These keybindings let me do that more quickly than C-n C-n C-n C-n C-n C-n ... In fact, with these I can navigate to any line within a distance of 11 in 3 keystrokes or less. Or close enough to count. Two of them require 4 keystrokes. Can you figure out which ones?

Everybody knows about moving Control to Caps Lock. These are my extra neat tricks for my MacBook Pro: (setq mac-command-modifier 'meta) (setq mac-option-modifier 'super) (setq ns-function-modifier 'hyper) First of all, Meta M- needs to be really easy to hit. On a Mac keyboard, that means Command - and not the default Option - since we want the key that is right next to Space. The good news is that now Option is available for Super s- . And even more amazing, you can also bind the Function-key to Hyper H- - without losing the ability to change the volume or pause/play. So now I can use crazy keybindings like H-SPC hyperspace. I haven't entirely decided what I should be using this newfound superpower for, but one thing I've done is reserve all the C-s- prefixed letters for refactorings with js2-refactor, as you can see here.

I love the symbiosis between expand-region and delete-selection-mode. (put 'paredit-forward-delete 'delete-selection 'supersede) (put 'paredit-backward-delete 'delete-selection 'supersede) (put 'paredit-open-round 'delete-selection t) (put 'paredit-open-square 'delete-selection t) (put 'paredit-doublequote 'delete-selection t) (put 'paredit-newline 'delete-selection t) This makes paredit-mode work with delete-selection-mode, replacing its wrapping behavior. If I want to wrap, I'll do it with the paredit-wrap-* commands explicitly.

Yesterday Kototama commented about another neat paredit addition: duplicating sexps. This is my take on that: ( defun paredit--is-at-start-of-sexp () (and (looking-at "( \\ | \\[" ) (not (nth 3 (syntax-ppss))) (not (nth 4 (syntax-ppss))))) ( defun paredit-duplicate-closest-sexp () (interactive) ( while (not (paredit--is-at-start-of-sexp)) (paredit-backward)) (set-mark-command nil) ( while (and (bounds-of-thing-at-point 'sexp) (<= (point) (car (bounds-of-thing-at-point 'sexp))) (not (= (point) (line-end-position)))) (forward-sexp) ( while (looking-at " " ) (forward-char))) (kill-ring-save (mark) (point)) (paredit-newline) (yank) (exchange-point-and-mark)) Like Kototama says in his blogpost, duplicating a line is very useful, but sometimes it leads to invalid sexps. In the blogpost he shows a snippet that will duplicate the sexp after point. I immediately realized I had really been wanting this. The version listed here is a little modified: It will duplicate the sexp you are currently inside, or looking at, or looking behind at. So basically, point can be in any of these positions: |(my sexp) (my| sexp) (my sexp)| Insta-useful!

Programming any lisp? Then this paredit-inspired snippet may be for you. ( defun paredit-wrap-round-from-behind () (interactive) (forward-sexp -1) (paredit-wrap-round) (insert " " ) (forward-char -1)) (define-key paredit-mode-map (kbd "M-)" ) 'paredit-wrap-round-from-behind) With point in front of a sexp, paredit-wrap-round (bound to M-( ), will open a paren in front the the sexp, and place the closing paren at the end of it. That's pretty handy. This snippet does the same, but from the other end. It saves me a C-M-b ever so often. I like it.

Annoyed when Emacs opens the window below instead at the side? ( defun toggle-window-split () (interactive) ( if (= (count-windows) 2) ( let* ((this-win-buffer (window-buffer)) (next-win-buffer (window-buffer (next-window))) (this-win-edges (window-edges (selected-window))) (next-win-edges (window-edges (next-window))) (this-win-2nd (not (and (<= (car this-win-edges) (car next-win-edges)) (<= (cadr this-win-edges) (cadr next-win-edges))))) (splitter ( if (= (car this-win-edges) (car (window-edges (next-window)))) 'split-window-horizontally 'split-window-vertically))) (delete-other-windows) ( let ((first-win (selected-window))) (funcall splitter) ( if this-win-2nd (other-window 1)) (set-window-buffer (selected-window) this-win-buffer) (set-window-buffer (next-window) next-win-buffer) (select-window first-win) ( if this-win-2nd (other-window 1)))))) This snippet toggles between horizontal and vertical layout of two windows. Neat.

Ever open a file in the wrong window? ( defun rotate-windows () "Rotate your windows" (interactive) ( cond ((not (> (count-windows)1)) (message "You can't rotate a single window!" )) (t (setq i 1) (setq numWindows (count-windows)) ( while (< i numWindows) ( let* ( (w1 (elt (window-list) i)) (w2 (elt (window-list) (+ (% i numWindows) 1))) (b1 (window-buffer w1)) (b2 (window-buffer w2)) (s1 (window-start w1)) (s2 (window-start w2)) ) (set-window-buffer w1 b2) (set-window-buffer w2 b1) (set-window-start w1 s2) (set-window-start w2 s1) (setq i (1+ i))))))) This snippet flips a two-window frame, so that left is right, or up is down. It's sanity preserving if you've got a sliver of OCD.

Ido gives fuzzy matching in my completing-read. I want that everywhere. ( require ' ido-ubiquitous ) (ido-ubiquitous-mode 1) ( defmacro ido-ubiquitous-use-new-completing-read (cmd package) `( eval-after-load ,package '( defadvice ,cmd (around ido-ubiquitous-new activate) ( let ((ido-ubiquitous-enable-compatibility nil)) ad-do-it)))) (ido-ubiquitous-use-new-completing-read webjump 'webjump) (ido-ubiquitous-use-new-completing-read yas/expand 'yasnippet) (ido-ubiquitous-use-new-completing-read yas/visit-snippet-file 'yasnippet) ido-ubiquitous delivers on that promise. However, there is some discrepancies in the completing-read API between newer and older versions regarding the case where you just press enter to choose the first item. To fix these, some of the newer usages of completing read need a slightly different implementation. These tweaks fix that problem.

Uneven application of white-space is bad, m'kay? ( defun cleanup-buffer-safe () "Perform a bunch of safe operations on the whitespace content of a buffer. Does not indent buffer, because it is used for a before-save-hook, and that might be bad." (interactive) (untabify (point-min) (point-max)) (delete-trailing-whitespace) (set-buffer-file-coding-system 'utf-8)) (add-hook 'before-save-hook 'cleanup-buffer-safe) ( defun cleanup-buffer () "Perform a bunch of operations on the whitespace content of a buffer. Including indent-buffer, which should not be called automatically on save." (interactive) (cleanup-buffer-safe) (indent-region (point-min) (point-max))) (global-set-key (kbd "C-c n" ) 'cleanup-buffer) I use these two literally all the time. The first one removes trailing whitespace and replaces all tabs with spaces before save. The last one I've got on a key - it also indents the entire buffer. These might not be for everybody. Sometimes you do want tabs (I'm looking at you Makefile grrrrr). Then this isn't optimal. The same can be said for when Emacs doesn't indent correctly. But that is a horrid, unacceptable situation in any case. I always fix those as soon as I can.

I find the default dired look a bit spammy, especially in narrow windows. ( require ' dired-details ) (setq-default dired-details-hidden-string "--- " ) (dired-details-install) By installing M-x package-install dired-details and using this snippet, we hide all the unnecessary ls -details. That rare occasion where you actually need that information, you can show it with ) and hide again with ( .

Like rename yesterday, I think delete deserves a designated keybinding. ( defun delete-current-buffer-file () "Removes file connected to current buffer and kills buffer." (interactive) ( let ((filename (buffer-file-name)) (buffer (current-buffer)) (name (buffer-name))) ( if (not (and filename (file-exists-p filename))) (ido-kill-buffer) ( when (yes-or-no-p "Are you sure you want to remove this file? " ) (delete-file filename) (kill-buffer buffer) (message "File '%s' successfully removed" filename))))) (global-set-key (kbd "C-x C-k" ) 'delete-current-buffer-file) This is it. C-x C-k : file begone! I like the feel between C-x k to kill the buffer and C-x C-k to kill the file. Release ctrl to kill it a little, hold to kill it a lot.

For some reason, renaming the current buffer file is a multi-step process in Emacs. ( defun rename-current-buffer-file () "Renames current buffer and file it is visiting." (interactive) ( let ((name (buffer-name)) (filename (buffer-file-name))) ( if (not (and filename (file-exists-p filename))) ( error "Buffer '%s' is not visiting a file!" name) ( let ((new-name (read-file-name "New name: " filename))) ( if (get-buffer new-name) ( error "A buffer named '%s' already exists!" new-name) (rename-file filename new-name 1) (rename-buffer new-name) (set-visited-file-name new-name) (set-buffer-modified-p nil) (message "File '%s' successfully renamed to '%s'" name (file-name-nondirectory new-name))))))) (global-set-key (kbd "C-x C-r" ) 'rename-current-buffer-file) This defun fixes that. And unlike some other alternatives to perform this common task, you don't have to type the name out from scratch - but get the current name to modify. Like it should be.

When programming I tend to shuffle lines around a lot. ( defun move-line-down () (interactive) ( let ((col (current-column))) ( save-excursion (forward-line) (transpose-lines 1)) (forward-line) (move-to-column col))) ( defun move-line-up () (interactive) ( let ((col (current-column))) ( save-excursion (forward-line) (transpose-lines -1)) (move-to-column col))) (global-set-key (kbd "<C-S-down>" ) 'move-line-down) (global-set-key (kbd "<C-S-up>" ) 'move-line-up) Maybe not when I program elisp, since that's sexp-based, but for other programming languages these two come in very handy. They simply move the current line one step up or down.

Opening new lines can be finicky. ( defun open-line-below () (interactive) (end-of-line) (newline) (indent-for-tab-command)) ( defun open-line-above () (interactive) (beginning-of-line) (newline) (forward-line -1) (indent-for-tab-command)) (global-set-key (kbd "<C-return>" ) 'open-line-below) (global-set-key (kbd "<C-S-return>" ) 'open-line-above) With these shortcuts you can open a new line above or below the current one, even if the cursor is midsentence. Try it out, it's a nice convenience.

C-d on an empty line in the shell terminates the process. ( defun comint-delchar-or-eof-or-kill-buffer (arg) (interactive "p" ) ( if (null (get-buffer-process (current-buffer))) (kill-buffer) (comint-delchar-or-maybe-eof arg))) (add-hook 'shell-mode-hook ( lambda () (define-key shell-mode-map (kbd "C-d" ) 'comint-delchar-or-eof-or-kill-buffer))) With this snippet, another press of C-d will kill the buffer. It's pretty nice, since you then just tap C-d twice to get rid of the shell and go on about your merry way.

Actual changes lost in a sea of whitespace diffs? ( defun magit-toggle-whitespace () (interactive) ( if (member "-w" magit-diff-options) (magit-dont-ignore-whitespace) (magit-ignore-whitespace))) ( defun magit-ignore-whitespace () (interactive) (add-to-list 'magit-diff-options "-w" ) (magit-refresh)) ( defun magit-dont-ignore-whitespace () (interactive) (setq magit-diff-options (remove "-w" magit-diff-options)) (magit-refresh)) (define-key magit-status-mode-map (kbd "W" ) 'magit-toggle-whitespace) This adds W to toggle ignoring whitespace in magit. It has some weird interactions with the changed files list, in that files with nothing but whitespace changes go missing. Toggle back to find them again.

Tired of seeing stale dired buffers? (global-auto-revert-mode 1) (setq global-auto-revert-non-file-buffers t) (setq auto-revert-verbose nil) Auto revert mode looks for changes to files, and updates them for you. With these settings, dired buffers are also updated. The last setting makes sure that you're not alerted every time this happens. Which is every time you save something.

You are using magit with your git, right? ( defadvice magit-status (around magit-fullscreen activate) (window-configuration-to-register :magit-fullscreen ) ad-do-it (delete-other-windows)) ( defun magit-quit-session () "Restores the previous window configuration and kills the magit buffer" (interactive) (kill-buffer) (jump-to-register :magit-fullscreen )) (define-key magit-status-mode-map (kbd "q" ) 'magit-quit-session) This code makes magit-status run alone in the frame, and then restores the old window configuration when you quit out of magit. No more juggling windows after commiting. It's magit bliss.

What are those line numbers for anyway? (global-set-key [remap goto-line] 'goto-line-with-feedback) ( defun goto-line-with-feedback () "Show line numbers temporarily, while prompting for the line number input" (interactive) ( unwind-protect ( progn (linum-mode 1) (goto-line (read-number "Goto line: " ))) (linum-mode -1))) I don't have line numbers visible in the fringe of my Emacs. If I want to go to a line number, that is usually because it is referenced in an error message somewhere. Showing them all the time is just noise. Still, many people want line numbers visible. I guess that is because they use them for navigation. This snippet shows line numbers temporarily just when you're going to a line number with goto-line . Notice the nice remap -trick in the key binding. It will remap all key bindings from goto-line to goto-line-with-feedback . Neat!

Searching the web can also be improved with Emacs. (global-set-key (kbd "C-x g" ) 'webjump) ( eval-after-load "webjump" '(add-to-list 'webjump-sites '( "Urban Dictionary" . [simple-query "www.urbandictionary.com" "http://www.urbandictionary.com/define.php?term=" "" ]))) Webjump let's you quickly search Google, Wikipedia, Emacs Wiki and other pages. I've got it bound to C-x g . This snippet adds Urban Dictionary to the list of pages, so the next time you wonder what those dastardly kids mean when they write faceroll or sassafrassa or Technotard or kthxbye or whatever else is hip these days, well, then you can find out. With webjump .

Need different settings for different machines? (setq user-settings-dir (concat user-emacs-directory "users/" user-login-name)) ( when (file-exists-p user-settings-dir) (mapc 'load (directory-files user-settings-dir nil "^[ ^ #].*el$" ))) These are the last lines of my init.el. They will load any *.el files in the ~/.emacs.d/users/ user-login-name / folder. Anything specific for that machine goes there.

Do you program any elisp, at all, ever? (autoload 'elisp-slime-nav-mode "elisp-slime-nav" ) (add-hook 'emacs-lisp-mode-hook ( lambda () (elisp-slime-nav-mode t))) ( eval-after-load 'elisp-slime-nav '(diminish 'elisp-slime-nav-mode)) Then you need to M-x package-install elisp-slime-nav-mode . It lets you jump to the definition of a function with M-. , and back again afterwards with M-, . That last line says that we want elisp-slime-nav-mode to continue doing its work for us, but we no longer want to be reminded of it.

Is your modeline chock full of minor-mode abbreviations and cruft? ( require ' diminish ) (diminish 'wrap-region-mode) (diminish 'yas/minor-mode) After a quick M-x package-install diminish , you too can have the pleasure of using a lot of minor modes, without those minor modes making a mess of the modeline. Mmm. As for diminish.el itself, it contains the most beautifully poetic code commentary of all time. Here's an excerpt: "When we diminish a mode, we are saying we want it to continue doing its work for us, but we no longer want to be reminded of it. It becomes a night worker, like a janitor; it becomes an invisible man; it remains a component, perhaps an important one, sometimes an indispensable one, of the mechanism that maintains the day-people's world, but its place in their thoughts is diminished, usually to nothing. As we grow old we diminish more and more such thoughts, such people, usually to nothing." - Will Mengarini in diminish.el

Tired of navigating back to where you were last in a file? ( require ' saveplace ) (setq-default save-place t) (setq save-place-file (expand-file-name ".places" user-emacs-directory)) The saveplace package is part of Emacs, and remembers the position of point - even between emacs sessions. The last line sets the path to where saveplace stores your position data. Change it at your peril! * * Ahem, there really is no peril. That was just melodrama.

Annoyed by those pesky ~ files? (setq backup-directory-alist `(( "." . ,(expand-file-name (concat user-emacs-directory "backups" ))))) (setq vc-make-backup-files t) Backup files are so very annoying, until the day they save your hide. That's when you don't want to look back and say "Man, I really shouldn't have disabled those stupid backups." These settings move all backup files to a central location. Bam! No longer annoying. As an added bonus, that last line makes sure your files are backed up even when the files are in version control. Do it.