Hacker News new | past | comments | ask | show | jobs | submit login
Emacs Rocks (emacsrocks.com)
361 points by pmoriarty on Nov 16, 2014 | hide | past | favorite | 112 comments



I ran across this site the other day when I was looking at overhauling my .emacs file since I'm only an occasional emacs user these days. This guy has a great starter repo of his customized .emacs.d directory that takes care of a lot of the setup work to use all the customizations and modes he's using: https://github.com/magnars/.emacs.d

One note, if you do clone the repo, make sure to use the --recursive option (as the readme instructs) since there are a bunch of other git repositories imported in the repo.


Bozhidar Batsov's Emacs Prelude is also worthy of study:

https://github.com/bbatsov/prelude

That is, even if you didn't want to use it outright for your config, prelude's init.el and modules are a good resource for learning how to wire things together with Emacs Lisp.


> One note, if you do clone the repo, make sure to use the --recursive option (as the readme instructs) since there are a bunch of other git repositories imported in the repo.

Doing this, you can tell that this guy really doesn't care for the Emacs package-repositories :)


There's also http://emacs.sexy/


The "How to Learn Emacs" infographic that's linked a little ways down on that page includes a bit of attitude that drives me nuts:

NOTE: The Emacs tutorial has lots of weird terms: "Meta key", "frame", "buffer". This is because Emacs started a LONG time ago. Don't worry, you'll get the hang of it with practice.

I have no idea why we make people jump through the hoops of learning archaic terminology, rather than evolving the software to use the terms people actually use today.

The Meta key is called the "Meta key" because that's the label that was on the keyboards of the Lisp machines in the MIT AI lab when Emacs was first developed. It's been thirty-plus years since that key was found on anything close to a significant fraction of keyboards in use in the world. There's no evidence that it's ever going to make a roaring comeback, either.

In other words, the Meta key, as a key, is dead and gone. It is literally as dead as disco! And yet the name persists, even though the way people have interacted with the "Meta key" for decades has been to press a key labeled something other than "Meta."

So: why hang on to a dead word? It serves no practical purpose, and does active harm by confusing people new to the editor.

But no, rather than update our terminology so it bears some resemblance to the world we actually live in, we hang on to it and tell newcomers that to learn Emacs they're just going to have to get used to pretending they're working on a space-cadet keyboard, because that's The Way It Has Always Been Done. Sigh.


> The Meta key is called the "Meta key" because that's the label that was on the keyboards of the Lisp machines in the MIT AI lab when Emacs was first developed.

You have your cause and effect backwards. TL;DR: The Lispm's bucky keyboard simply extended existing practice.

Emacs predates the Lisp machines (CADRs in this case), and was originally written in TECO. Originally escape escape would open and close a minibuffer in which you could simply enter raw TECO. The Knight TV system had a custom keyboard used by us at MIT AI (and at Stanford AI for their own, slightly different TV system) had a Meta key which was used to invoke the minubuffer with a single keystroke (meta-altmode, mapped to escape when using ASCII) which later turned into direct "long" commands (M-X commands) and a wider keyspace.

In those days most programs on the PDP-6 & PDP-10 used six or seven bit bytes (though byte pointers could stride by 1-18 bit bytes) but the KTV was built on a PDP-11 which had 8 bit bytes, so meta was trivially available. FWIW the PDP-11 was memory mapped into the 36-bit PDP-6 through an arcane process I have thankfully forgotten.


Because the terminology is tied into the code in ways that would cause incompatibility with past code if changed. For example, emacs uses "frame" to mean what we now call a "window" and vice versa, and all the functions for interacting with windows and frames reflect this usage. If one just did a blanket search-and-replace swap of window and frame throughout the entire Emacs codebase and documentation, you would probably have a working Emacs, but all external packages and customization code that interact with windows or frames in any way would now be broken. You can't just update the documentation but leave the code as is, because then you have to start telling people ridiculous things like "switch windows with 'other-frame' and switch frames with 'other-window'", which isn't going to be any less confusing that what you started with. Elisp is a dynamic language, so you can't set up some sort of name-translation layer and use it for backward-compatibility with old code (that code could have a reference to an old name inside a quoted form, or even a string).

And the window/frame term swap is only one of many such examples. So basically, you could make your own Emacs that uses modern terminology and is completely incompatible with all existing 3rd-party elisp code, and then you could try to convince people to switch to it. But would having two equivalent but fundamentally incompatible Emacs/elisp variants be beneficial to Emacs as a whole? I doubt it.


This might sound a bit harsh - so basically condemning Emacs to obsolescence.

Emacs has a lot of hurdles in front of it: niche extension language, huge volume of customization before it becomes usable for your average Notepad++/Sublime user, etc., why add confusing documentation and naming on top of it?

The cost is huge, but IMO it is worth paying. It is a one time cost (refactoring, updating the documentation and many/most extensions) which could open Emacs to a much larger audience.


What I'd like to "condemn to obsolesence" is this tired narrative that insists that emacs needs to change to "get with the times." People were saying this when I starting using emacs in 2000, back when vi vs. emacs could still erupt into flame wars.

I left text editors for a few years (buried in Eclipse) but came back recently for Haskell and Go, and the community is ON FIRE. So much good stuff now: Melpa, flycheck, magit.

PS: "Meta" is fine. There's no standard "Alt" key anyway. On Mac, meta is often the "option" key but not always. It helps that Emacs has it's own term when switching between Windows, Mac, VNC of either, terminal, etc.


+1, fascinating to see emacs remain front page news 20+ years after I first started using it, and even more shocking, I'm still finding new features.

Multiple-cursors looks amazing.


"why hang on to a dead word?"

Because it doesn't refer to a key. It's more of a identifier. It would be considerably more confusing to substitute whatever key you think it should be. Cmd? Alt? Opt? Esc?

When I see "M-" in the literature, I know what that means and translate it to the relevant keystrokes. For instance, M-x for me is actually "C-[ x". I've customized it that way. However, we have a lingua franca for communicating commands despite the personalizations.


More people would be confused if you dispelled the term "meta" than are confused by its use today.

Similarly: there is no particularly good reason to use the term "lambda" for anonymous function constructs --- its use traces back to a typesetting quirk of Alonzo Church's. But here we are today, typing "lambda" like a bunch of chumps. :)


Disco is most definitely not dead. In fact, if you were to look at relative usage as "dead", and compared Emacs and disco, I'd put money that Emacs is deader than disco.

Disco lives on as house music, which has influenced current pop music so much it's scary. Disco didn't die, it just went underground. Like every other cultural phenomenon, it has its subcultures and offshoots. I could play you music released in the last year that you would probably think was released in the late sixties.


Disco is not dead, it's called "House" now.


Because Escape Meta Alt Control Shift of course :-)


This feels strangely relevant: https://rms.sexy/



I personally like the emacs.sexy icon better than the current one (Emacs 24.4 on OSX). I actually liked the older icon better than the current one too.


Ooh, and http://vim.sexy!



I've been using emacs for years and I didn't know a few of these tricks!

I've been meaning to dig deeper, and things like this site are a great way to whet my appetite.


I've never used emacs- currently using XCode to do C++ development. While I find the demonstrations interesting, what would emacs buy me as a C++ developer?


Emacs is not only an editor, but a "computing environment" that can be readily customized and extended using the Emacs Lisp (elisp) language. In fact, much of Emacs itself is built with elisp. Some developers find that kind of flexibility in their tooling to be highly compelling, others not so much.

I'm not a C++ programmer, but I turned up the following guide with a Google search, which might you might find interesting:

C/C++ Development Environment for Emacs

http://tuhdo.github.io/c-ide.html


Maybe not much. When working with C++ - at least in my experience - you get more use out of code navigation and code completion (two things that emacs supports rather averagely, even after customization) than you do out of text editing functionality (for which emacs is excellent).


I don't know that I agree with this. I'm rewriting for the fourth time a blog post I wrote on auditing C/C++ code using Emacs. The combination of Helm, cscope/ascope, hi-lock, ectags, Projectile, and incremental recursive grep is pretty hard to beat.

I use unobtrusive dabbrev-style completion --- I don't want popup menus with completion possibilities drawn from documentation, because Dash.app does a better job of that and is shared by all applications.

I think Emacs does an at least adequate job at all the core functions of Xcode, but does some things Xcode can't do at all.

(It's been a few years since I've written more than a couple thousands lines in Xcode, though.)


Don't worry, I'm not saying Xcode isn't awful. I've just found that code navigation saves me more time than having a fancy text editor does. And even after putting some effort in, the results with emacs just aren't as good (particularly compared to effort expended) as what you get from Xcode and Visual Studio.

Which is a shame, because Xcode's text editor is awful (or did I mention that already??), and Visual Studio's is crashingly average. I'd much rather use emacs.

(I use company-mode, with the clang backend, and it's OK. For code navigation, currently nothing, but rtags (https://github.com/Andersbakken/rtags) is on my todo list. The README is worth a skim - it has a cute way of grabbing the list of files you're using.)


Link to the post please? It should make for interesting reading.


It's still sitting in Draftin.com, waiting for me to like it enough.


Instead of cscope/ctages, have you tried GNU GLOBAL? I've taken my first steps with it and the ggtags mode. So far, I am finding it to be drastically better than ctags.

Have I just never configured ctags correctly?


I didn't even know about it. This looks awesome. Highly recommend: wrap GNU GLOBAL in a web app (scrape its output, stick it in a database). We did that at Matasano (with dumber tools than GLOBAL) and not only was it incredibly useful, but shockingly, shockingly easy.


I'm not sure what you are referring to for the web app. Are you just wanting to skin what it puts as a hypertext file already?[1]

[1] http://www.tamacom.com/tour/kernel/linux/


I didn't know GLOBAL had a web interface, but we generally want search, highlight, bookmarks, and notes, in addition to clickable cross-reference popups. We used ectags and Pygments.


Makes sense, I think. As I said earlier, I am new to GLOBAL entirely. Something I found as I was building up my new emacs setup at work. So far, I've been impressed. Not sure I'll ever care for the web interface, but the ggtags mode has been a dream. And I've really only used find-references and find-definition.


I've been using GLOBAL with a slightly tweaked gtags.el for almost 5 years now. It's definitely served me well.


Do you run into any practical size limitations?


It works well for project like Linux kernel. Jump/listing references happens instantly.


Not really. With Emacs, it makes navigating a project like Linux kernel seems a small project. You can see the demos in my other answer here: https://news.ycombinator.com/item?id=8616737

Emacs allows you to jump to anything instantly, even with source tree like Clang or Linux.



Possibly not much. I've never used XCode for C++ development but I imagine it has pretty nifty Clang integration, given Apple's investment in Clang. Anyone who suggests using ctags, GNU Global, gtags, CEDET's own parser (implemented in elisp!), etc. for C++ navigation is basically saying "use a C parser to parse C++ code", which works well enough if you're writing 1990s style C++, I suppose. There are projects out there to integrate with Clang (such as rtags mentioned by another poster) but it will require hours/days of setup & frustration, and the result won't be as good as a dedicated C++ ide.

BTW I say this as an emacs fan and the author of http://david.rothlis.net/emacs/howtolearn.html and https://github.com/drothlis/clang-ctags/

Where emacs shines (for me, at least) is when you spend a lot of time in different languages. Maybe you spend 50% of the time in C++, but the other 50% in shell, makefiles, python, etc. -- and the benefit of better C++ code navigation begins to seem like a micro-optimisation that isn't worth the tradeoff compared to Emacs's support for navigation, version control, compilation, linting, grepping, etc etc, all of which are consistent across all languages. Not to mention Emacs's great support for text manipulation in general.

Also Emacs seems to me the best bet for the "one true editor" you'll still be using in 20 years (by which time hopefully few of us will still be using C++).

I'll also point out that on OS X, Emacs has a lower learning curve than any other OS, at least as far as the basic keystrokes: OS X's Command key still works for the usual shortcuts (cut, copy, paste, save, open, quit, undo) while the quirky emacs bindings are on the Control and Option keys. This doesn't make it any easier to set up a C++ navigation solution, of course.


I agree with everything you said about other aspects of Emacs.

You are right that supports for C++ is not as rich, since it is such a complicated language. But for small C++ projects and large C projects, it is pretty much usable, especially just for code navigation. At least it's better than using Grep and better than nothing at all. The currently available tools are perfectly usable for those who only write C.

For code completion, there's no pretty solution, but at least simple solution like company-clang which uses clang to get completion candidates from system include paths is pretty usable.


On the good side, once you are used to the keys, the text editing part is pretty efficient. Also, you have access to a lot of the other modes once you want to step out of the C++ tasks, to look at other files (makefiles, log files), keeping notes with org-mode, opening ftp windows, pretty-printing,.... Plus there's less behind the scene magic than in IDEs and you have access to everything to see where something breaks. It's not a black box the same way an IDE is.

On the bad side, you'll have to spend time tweaking packages and so on to get IDE-similar goodies like autocomplete. I can't remember if there's a similar thing as a background compilation that highlight errors as you type. But the thing with emacs is that if you wonder about a plugin, there'a good chance it exists already.


I can't remember if there's a similar thing as a background compilation that highlight errors as you type.

Check out Flycheck: http://flycheck.readthedocs.org/en/latest/


Doh! Thx.


XCode is amazing for C/C++ development, but Emacs is just better as a text editor. The rtags project [1] is under active development right now to have more IDE-like features in Emacs for C/C++ developers. There are some other projects, for example clang-complete-async [2]

[1] https://github.com/Andersbakken/rtags

[2] https://github.com/Golevka/emacs-clang-complete-async


Here are some nice features that Emacs provide:

- Powerful automatic indentation: https://raw.githubusercontent.com/Bruce-Connor/aggressive-in.... It does not only indent the current line, but the whole Semantic context around your cursor.

- Live grep: http://tuhdo.github.io/static/live_grep.gif

- Access to a list of project with a few key strokes: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Quickly access any file in your project, as large as Linux kernel, instantly, regardless of where you are in the project, and within a few keystrokes: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Jump to any file depends on context, even if the file path is in a plain ASCII text file: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Copy files from anywhere to anywhere: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Delete files anywhere; files are always at your finger tip to do whatever with them: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Switch between other files with same names but different extensions: http://tuhdo.github.io/static/helm-projectile/helm-projectil.... Work not only for C/C++ but other languages, and is customizable. You don't have to configure anything, like adding include paths for the command to search. Everything is automatic. Just use it as it is.

- Jump to tag definition, from Emacs's own parser or external parser like GNU Global: http://tuhdo.github.io/static/c-ide/helm-gtags-jump-dwim.gif

- Jump to any definition from a list of definitions in source tree, even for Linux kernel: http://tuhdo.github.io/static/c-ide/helm-gtags-select.gif

- Jump up to parent: http://tuhdo.github.io/static/c-ide/senator-go-to-up-referen....

- Do you like outline tree?: http://tuhdo.github.io/static/c-ide/sr-speedbar.gif

- Interactive outline tree: http://tuhdo.github.io/static/c-ide/helm-semantic-or-imenu-w....

- Easily move back and forth using the interactive outline tree: http://tuhdo.github.io/static/part3/helm-semantic-or-imenu-2....

- References retrieved from its Emacs internal parser: http://tuhdo.github.io/static/c-ide/semantic-symref.gif.

- Beautiful compile output: http://tuhdo.github.io/static/c-ide/compilation-compile.gif

- Frontend support for GDB: http://tuhdo.github.io/static/c-ide/gdb-many-windows.gif

- Code completion: http://tuhdo.github.io/static/c-ide/semantic-boost-demo.gif.

- Open man page for symbol at cursor: http://tuhdo.github.io/static/part3/helm-man-woman.gif.

- Emacs open 39MB C file: http://tuhdo.github.io/static/performance.gif

- Emac opens multi-gigabtye file: http://www.emacswiki.org/VLF

- Emacs is a bit torrent client: https://bitbucket.org/ukaszg/aria2-mode/

You can see more demos in:

+ Emacs Mini Manual: http://tuhdo.github.io/emacs-tutor.html + C/C++ Development Environment for Emacs: http://tuhdo.github.io/c-ide.html + A Package in a league of its own: Helm: http://tuhdo.github.io/helm-intro.html + Exploring large projects with Projectile and Helm Projectile: http://tuhdo.github.io/helm-projectile.html

Note that in the demos you may see me type in the commands. You can think of it like the start menu in Windows, but actually those commands can be executed quickly with a shortcut. I type in the commands for demonstration purpose to Emacs users.

Those demos are just tip of the iceberg.


Most of your links are truncated :(


Opps sorry about the link. I reposted with proper links here:

If you write C++, did you check my C/C++ guide: http://tuhdo.github.io/c-ide.html. Aside from refactoring, you have mostly everything like:

- code navigation: jump to anywhere instantly. DEMO: http://tuhdo.github.io/static/c-ide/helm-gtags-jump-dwim.gif.

- code completion: context-sensitve completion. DEMO: http://tuhdo.github.io/static/c-ide/semantic-boost-demo.gif.

- code compilation: you can click on the error and it gets you to where you want; work with any build system, while other IDE only supports a specific build system, i.e. for Makefile project, you only get plain text error message. DEMO: http://tuhdo.github.io/static/c-ide/compilation-mode.gif.

- code debugging: provides a frontend for GDB; DEMO: http://tuhdo.github.io/static/c-ide/gdb-many-windows.gif.

- Powerful automatic indentation: https://github.com/Bruce-Connor/aggressive-indent-mode. It does not only indent the current line, but the whole Semantic context around your cursor. Demos inside the homepage.

- Live grep: http://tuhdo.github.io/static/live_grep.gif.

- Access to a list of project with a few key strokes: http://tuhdo.github.io/static/helm-projectile/helm-projectil...

- Quickly access any file in your project, as large as Linux kernel, instantly, regardless of where you are in the project, and within a few keystrokes: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Jump to any file depends on context, even if the file path is in a plain ASCII text file: http://tuhdo.github.io/static/helm-projectile/helm-projectil...

- Copy files from anywhere to anywhere: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Delete files anywhere; files are always at your finger tip to do whatever with them: http://tuhdo.github.io/static/helm-projectile/helm-projectil....

- Switch between other files with same names but different extensions: http://tuhdo.github.io/static/helm-projectile/helm-projectil.... Work not only for C/C++ but other languages, and is customizable. You don't have to configure anything, like adding include paths. Everything is automatically done for you.

- Jump to tag definition, from its own parser or external parser like GNu Global: http://tuhdo.github.io/static/c-ide/helm-gtags-jump-dwim.gif

- Jump up to parent: http://tuhdo.github.io/static/c-ide/senator-go-to-up-referen....

- Do you like outline tree?: http://tuhdo.github.io/static/c-ide/sr-speedbar.gif

- Interactive outline tree: http://tuhdo.github.io/static/c-ide/helm-semantic-or-imenu-w...

- Easily move back and forth using the interactive outline tree: http://tuhdo.github.io/static/part3/helm-semantic-or-imenu-2...

- References retrieved from its Emacs internal parser: http://tuhdo.github.io/static/c-ide/semantic-symref.gif.

- Beautiful compile output: http://tuhdo.github.io/static/c-ide/compilation-compile.gif

- Frontend support for GDB: http://tuhdo.github.io/static/c-ide/gdb-many-windows.gif

- Open man page for symbol at cursor: http://tuhdo.github.io/static/part3/helm-man-woman.gif.

- Emacs open 39MB C file: http://tuhdo.github.io/static/performance.gif

- Emac opens multi-gigabtye file: http://www.emacswiki.org/VLF


And if a parenthesis is missing in any of those 2300 elisp files: MWAHAHAHAH

;)


Emacs will tell you the exact location where you missed instantly when the files are loaded. No worry! Anyway, to try out Emacs these days everything is already done for you:

- Prelude (for those who want to learn Emacs): https://github.com/bbatsov/prelude

- Spacemacs (for long time Vim users): https://github.com/syl20bnr/spacemacs


That isn't my experience...


Just opened Emacs 24.4 for a test:

    Warning (initialization): An error occurred while loading `c:/Users/swah/.emacs':

    Wrong type argument: listp, 769

    To ensure normal operation, you should investigate and remove the
    cause of the error in your initialization file.  Start Emacs with
    the `--debug-init' option to view a complete error backtrace.
That .emacs file contains only has two lines:

    (defvar emacs-root (expand-file-name "~/Dropbox/dotfiles/emacs/"))
    (load-file "~/Dropbox/dotfiles/emacs/init.el")
So I did M-x toggle-debug-on-error and reloaded init.el manually.. Then I took a look at the Messages buffer:

  Debugger entered--Lisp error: (wrong-type-argument listp 769)
    memq(&rest 769)
    (if (memq (quote &rest) arglist) most-positive-fixnum (length (remq (quote &optional) arglist)))
    (let ((arglist (if (byte-code-function-p function) (aref function 0) (second function)))) (if (memq (quote &rest) arglist) most-positive-fixnum (length (remq (quote &optional) arglist))))
    (if (subrp function) (let ((max (cdr (subr-arity function)))) (if (eq (quote many) max) most-positive-fixnum max)) (if (eq (quote macro) (car-safe function)) (setq function (cdr function))) (let ((arglist (if (byte-code-function-p function) (aref function 0) (second function)))) (if (memq (quote &rest) arglist) most-positive-fixnum (length (remq (quote &optional) arglist)))))
    magit-max-args-internal(delete-directory)
    (>= (magit-max-args-internal (quote delete-directory)) 2)
    (if (>= (magit-max-args-internal (quote delete-directory)) 2) (defalias (quote magit-delete-directory) (quote delete-directory)) (defun magit-delete-directory (directory &optional recursive) "Deletes a directory named DIRECTORY.  If RECURSIVE is non-nil,\nrecursively delete all of DIRECTORY's contents as well.\n\nDoes not follow symlinks." (if (or (file-symlink-p directory) (not (file-directory-p directory))) (delete-file directory) (if recursive (dolist (file (directory-files directory (quote full) "\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) (magit-delete-directory file recursive))) (delete-directory directory))))
    (progn (defun magit-max-args-internal (function) "Returns the maximum number of arguments accepted by FUNCTION." (if (symbolp function) (setq function (symbol-function function))) (if (subrp function) (let ((max (cdr (subr-arity function)))) (if (eq (quote many) max) most-positive-fixnum max)) (if (eq (quote macro) (car-safe function)) (setq function (cdr function))) (let ((arglist (if (byte-code-function-p function) (aref function 0) (second function)))) (if (memq (quote &rest) arglist) most-positive-fixnum (length (remq (quote &optional) arglist)))))) (if (functionp (quote start-file-process)) (defalias (quote magit-start-process) (quote start-file-process)) (defalias (quote magit-start-process) (quote start-process))) (unless (fboundp (quote string-match-p)) (defun string-match-p (regexp string &optional start) "Same as `string-match' except this function does not\nchange the match data." (let ((inhibit-changing-match-data t)) (string-match regexp string start)))) (if (fboundp (quote with-silent-modifications)) (defalias (quote magit-with-silent-modifications) (quote with-silent-modifications)) (defmacro magit-with-silent-modifications (&rest body) "Execute body without changing `buffer-modified-p'. Also, do not\nrecord undo information." (\` (set-buffer-modified-p (prog1 (buffer-modified-p) (let (... before-change-functions after-change-functions) (\,@ body))))))) (if (>= (magit-max-args-internal (quote delete-directory)) 2) (defalias (quote magit-delete-directory) (quote delete-directory)) (defun magit-delete-directory (directory &optional recursive) "Deletes a directory named DIRECTORY.  If RECURSIVE is non-nil,\nrecursively delete all of DIRECTORY's contents as well.\n\nDoes not follow symlinks." (if (or (file-symlink-p directory) (not (file-directory-p directory))) (delete-file directory) (if recursive (dolist (file (directory-files directory ... "\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) (magit-delete-directory file recursive))) (delete-directory directory)))))
    eval((progn (defun magit-max-args-internal (function) "Returns the maximum number of arguments accepted by FUNCTION." (if (symbolp function) (setq function (symbol-function function))) (if (subrp function) (let ((max (cdr (subr-arity function)))) (if (eq (quote many) max) most-positive-fixnum max)) (if (eq (quote macro) (car-safe function)) (setq function (cdr function))) (let ((arglist (if (byte-code-function-p function) (aref function 0) (second function)))) (if (memq (quote &rest) arglist) most-positive-fixnum (length (remq (quote &optional) arglist)))))) (if (functionp (quote start-file-process)) (defalias (quote magit-start-process) (quote start-file-process)) (defalias (quote magit-start-process) (quote start-process))) (unless (fboundp (quote string-match-p)) (defun string-match-p (regexp string &optional start) "Same as `string-match' except this function does not\nchange the match data." (let ((inhibit-changing-match-data t)) (string-match regexp string start)))) (if (fboundp (quote with-silent-modifications)) (defalias (quote magit-with-silent-modifications) (quote with-silent-modifications)) (defmacro magit-with-silent-modifications (&rest body) "Execute body without changing `buffer-modified-p'. Also, do not\nrecord undo information." (\` (set-buffer-modified-p (prog1 (buffer-modified-p) (let (... before-change-functions after-change-functions) (\,@ body))))))) (if (>= (magit-max-args-internal (quote delete-directory)) 2) (defalias (quote magit-delete-directory) (quote delete-directory)) (defun magit-delete-directory (directory &optional recursive) "Deletes a directory named DIRECTORY.  If RECURSIVE is non-nil,\nrecursively delete all of DIRECTORY's contents as well.\n\nDoes not follow symlinks." (if (or (file-symlink-p directory) (not (file-directory-p directory))) (delete-file directory) (if recursive (dolist (file (directory-files directory ... "\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) (magit-delete-directory file recursive))) (delete-directory directory))))) nil)
    #[128 "\301\302\303B\"D\207" [lexical-binding quote eval progn] 5 1631664]((defun magit-max-args-internal (function) "Returns the maximum number of arguments accepted by FUNCTION." (if (symbolp function) (setq function (symbol-function function))) (if (subrp function) (let ((max (cdr (subr-arity function)))) (if (eq (quote many) max) most-positive-fixnum max)) (if (eq (quote macro) (car-safe function)) (setq function (cdr function))) (let ((arglist (if (byte-code-function-p function) (aref function 0) (second function)))) (if (memq (quote &rest) arglist) most-positive-fixnum (length (remq (quote &optional) arglist)))))) (if (functionp (quote start-file-process)) (defalias (quote magit-start-process) (quote start-file-process)) (defalias (quote magit-start-process) (quote start-process))) (unless (fboundp (quote string-match-p)) (defun string-match-p (regexp string &optional start) "Same as `string-match' except this function does not\nchange the match data." (let ((inhibit-changing-match-data t)) (string-match regexp string start)))) (if (fboundp (quote with-silent-modifications)) (defalias (quote magit-with-silent-modifications) (quote with-silent-modifications)) (defmacro magit-with-silent-modifications (&rest body) "Execute body without changing `buffer-modified-p'. Also, do not\nrecord undo information." (\` (set-buffer-modified-p (prog1 (buffer-modified-p) (let ((buffer-undo-list t) before-change-functions after-change-functions) (\,@ body))))))) (if (>= (magit-max-args-internal (quote delete-directory)) 2) (defalias (quote magit-delete-directory) (quote delete-directory)) (defun magit-delete-directory (directory &optional recursive) "Deletes a directory named DIRECTORY.  If RECURSIVE is non-nil,\nrecursively delete all of DIRECTORY's contents as well.\n\nDoes not follow symlinks." (if (or (file-symlink-p directory) (not (file-directory-p directory))) (delete-file directory) (if recursive (dolist (file (directory-files directory (quote full) "\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) (magit-delete-directory file recursive))) (delete-directory directory)))))
    (eval-and-compile (defun magit-max-args-internal (function) "Returns the maximum number of arguments accepted by FUNCTION." (if (symbolp function) (setq function (symbol-function function))) (if (subrp function) (let ((max (cdr (subr-arity function)))) (if (eq (quote many) max) most-positive-fixnum max)) (if (eq (quote macro) (car-safe function)) (setq function (cdr function))) (let ((arglist (if (byte-code-function-p function) (aref function 0) (second function)))) (if (memq (quote &rest) arglist) most-positive-fixnum (length (remq (quote &optional) arglist)))))) (if (functionp (quote start-file-process)) (defalias (quote magit-start-process) (quote start-file-process)) (defalias (quote magit-start-process) (quote start-process))) (unless (fboundp (quote string-match-p)) (defun string-match-p (regexp string &optional start) "Same as `string-match' except this function does not\nchange the match data." (let ((inhibit-changing-match-data t)) (string-match regexp string start)))) (if (fboundp (quote with-silent-modifications)) (defalias (quote magit-with-silent-modifications) (quote with-silent-modifications)) (defmacro magit-with-silent-modifications (&rest body) "Execute body without changing `buffer-modified-p'. Also, do not\nrecord undo information." (\` (set-buffer-modified-p (prog1 (buffer-modified-p) (let (... before-change-functions after-change-functions) (\,@ body))))))) (if (>= (magit-max-args-internal (quote delete-directory)) 2) (defalias (quote magit-delete-directory) (quote delete-directory)) (defun magit-delete-directory (directory &optional recursive) "Deletes a directory named DIRECTORY.  If RECURSIVE is non-nil,\nrecursively delete all of DIRECTORY's contents as well.\n\nDoes not follow symlinks." (if (or (file-symlink-p directory) (not (file-directory-p directory))) (delete-file directory) (if recursive (dolist (file (directory-files directory ... "\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")) (magit-delete-directory file recursive))) (delete-directory directory)))))
    eval-buffer(#<buffer  *load*> nil "c:/Users/swah/Dropbox/dotfiles/emacs_new/packages/magit/magit.el" nil t)  ; Reading at buffer position 28726
    load-with-code-conversion("c:/Users/swah/Dropbox/dotfiles/emacs_new/packages/magit/magit.el" "c:/Users/swah/Dropbox/dotfiles/emacs_new/packages/magit/magit.el" nil t)
    require(magit)
    eval-buffer()  ; Reading at buffer position 3564
    #<subr call-interactively>(eval-buffer record nil)
    funcall(#<subr call-interactively> eval-buffer record nil)
    (with-no-warnings (funcall ad--addoit-function function record-flag keys))
    (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys)))
    (let ((ido-ubiquitous-next-override (ido-ubiquitous-get-command-override function))) (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys))))
    (ido-ubiquitous-with-override (ido-ubiquitous-get-command-override function) (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys))))
    (let (ad-return-value) (ido-ubiquitous-with-override (ido-ubiquitous-get-command-override function) (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys)))) ad-return-value)
    ad-Advice-call-interactively(#<subr call-interactively> eval-buffer record nil)
    apply(ad-Advice-call-interactively #<subr call-interactively> (eval-buffer record nil))
    call-interactively(eval-buffer record nil)
    command-execute(eval-buffer record)
    execute-extended-command(nil "eval-buffer")
    #<subr call-interactively>(execute-extended-command nil nil)
    funcall(#<subr call-interactively> execute-extended-command nil nil)
    (with-no-warnings (funcall ad--addoit-function function record-flag keys))
    (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys)))
    (let ((ido-ubiquitous-next-override (ido-ubiquitous-get-command-override function))) (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys))))
    (ido-ubiquitous-with-override (ido-ubiquitous-get-command-override function) (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys))))
    (let (ad-return-value) (ido-ubiquitous-with-override (ido-ubiquitous-get-command-override function) (setq ad-return-value (with-no-warnings (funcall ad--addoit-function function record-flag keys)))) ad-return-value)
    ad-Advice-call-interactively(#<subr call-interactively> execute-extended-command nil nil)
    apply(ad-Advice-call-interactively #<subr call-interactively> (execute-extended-command nil nil))
    call-interactively(execute-extended-command nil nil)
    command-execute(execute-extended-command)
I decide to try updating magit. After a bit of googling, I find out how to update packages installed with package.el: http://stackoverflow.com/questions/14836958/updating-package....

15 packages are updated. I close Emacs and open again, and it still seems to break on the same place - something related to Magit. Fault of my customizations? Maybe. I don't know. Consider going back to Sublime? Yep.

So... no, tracking the source of errors ain't that trivial. What options do I have now? Throw away my customizations and start over?


It gives you hints like "buffer position 28726". You can press "M-g c" and enter that number to jump to that location, which is a character location of the error.

I wrote a guide on how to use package.el to install your package and how to customize and extend your Emacs here: http://tuhdo.github.io/emacs-tutor3.html, if you want control of your configuration from scratch.

Probably if you do not have proper Elisp learning, you should use Prelude: https://github.com/bbatsov/prelude. Everything is configured for you and packages are downloaded automatically. This is the easy way. Put your personal configuration code in ~/.emacs.d/personal/. You can also enable additional modules based on your need in ~/.emacs.d/sample/prelude-modules.el by toggling off comments: https://github.com/bbatsov/prelude/blob/master/sample/prelud....

I haven't tried loading from a different location, but you should try in your ~/.emacs.d first. Are you sure your packages are installed in Dropbox folder? I think it is installed in ~/.emacs.d. You should use a VCS like Git to store your configuration in the same .emacs.d directory.

Finally, to make sure it is because Magit, you should uninstall it to see if your Emacs loads properly. In my Windows machine, it loads perfectly fine with more than 130 packages.


Actually I've used emacs since 2003 or so... but still. Removing magit from ~/.emacs.d/elpa and reinstalling seems to have solved it. I'll check prelude.

I still think we need more text editors.


The annoying thing about customising Emacs is that when following along with tutorials, I keep tripping up against shortcuts that I have reconfigured to work in a different way. Luckily emacs lets you type out the command in full to bypass the short cut key. I can then determine if it is useful enough to remap the command to a different key.


Thank you very much for a great link! I am using emacs for almost everything I do, and I've naturally learned a lot about it, and I was planning for a long time to start seriously learning some in-depth things.

I've just recently learned the basics of lisp, this will be the perfect time to find out more about emacs. It is fantastic, and every time I discover some new feature it blows my mind how great and useful it is.


I've been using Magnar's and Christian's excellent collection of emacs settings and packages for some years now, and haven't bothered to adjust the settings in emacs myself evet since.

It's like turning your trusty old emacs into a monster hacker tool. Watching the screencasts is much more entertaining than reading boring documentation.


Another good emacs site is http://www.masteringemacs.org


Nice! Is there something similar for vim? For newbies looking to get into one, it'll be nice to see a comparison.


There is very high quality series: http://vimcasts.org/


There's also http://vim-adventures.com/. Costs a bit, unfortunately, but it's an amazing way to learn vim.


Costs too much, I think, in that I think they're probably losing too much business. I know that I clicked the button happy to pay $10, they probably could have squeezed $20 out of me, I balked at the "$50/yr".

I think it might very well be worth paying that to someone just learning vim. I'm skeptical enough of that population understand that, though.


Maybe if there was a way to use it without modifier keys. Even using shift for caps is painful for me.


There's evil-mode,[1][2] which is a fantastic vim-emulation mode for emacs. Using it, you'll get all the modal editing you're used to in vim.

One user's transition from vim to emacs+evil was recently discussed here.[3][4]

[1] - http://www.emacswiki.org/emacs/Evil

[2] - https://gitorious.org/evil/pages/Home

[3] - http://juanjoalvarez.net.nyud.net/es/detail/2014/sep/19/vim-...

[4] - https://news.ycombinator.com/item?id=8581530


Evil-mode, god-mode and key-chord are a few that address the modifier issue.

Re-mapping caps lock to ctrl is also immensely helpful.



in OS X system preferences you can set sticky modifiers. I used it for a while with emacs, but finally abandoned it because, while easy on fingers, it tends to cause strange things if you start typing a combination and halfway you change your mind (you can just release a modifier key usually, but if you just typed it there is nothing you can do to undo it, except C-G).


When you wrote that, did you know that if the sticky-keys setting is set and you accidentally hit a modifier key, then you can undo that by hitting the key 2 more times?

(I've been using OS X's sticky-keys setting with Emacs for years, BTW.)


Yes, I recall having noticed that, but still didn't feel very natural, probably because I use different systems (not all of them OS X even) and this complicates habit making.


M-u - uppercase current string starting at point

M-l - lowercase current string starting at point

M-c - capitalize from current point to next word delimiter


On a kinesis keyboard all the emacs modifier keys are by your thumbs. It makes emacs so much more awesome


There's also optional foot petals.


Is this actually serious? I would actually really love that. Would save so much strain on my fingers and it would probably even give my legs a bit of a workout.


It's serious. Unfortunately I find it very difficult to use. The foot just isn't as flexible as the fingers. It's slow and cumbersome. Also, using it limits how much I can move around in/with my chair.

I tried to get used to it, but my foot pedal is just collecting dust under the desk now.


It's a shame the modifiers (shift included) like to get stuck on the Kinesis. Expensive pile of crap...

If I had the money, I'd try out the Maltron 3D keyboard. I haven't heard about such problems with it. It also comes with a numpad in the middle, which I kinda miss in the Kinesis. It would be great for nethack, and something else.




Can't you just create an alias for

`emacs -nw -Q` or `emacsclient -nw`

when you want to open an instance in a terminal?


I could, of course, but I like it less bloated - 70 shared libraries less.)


I just found my new emacs logo ;-)


Nice concept. Id like to see this for vim, the one "true" text editor.


You'll never need it for ed, the standard text editor, because it is the standard. It is eternal. It is infinite. It is the standard, and any change would make it not standard. Puny mortals fail to see the immanent perfection of ed. There is no configuration because a Platonic Form has no time, no space, no change. It Is, It Was, It Will Be.

?


It's a great OS.

I mean, Emacs is an OS, right? They've certainly crammed enough things into it to make it an OS.


I didn't downvote you, but I wish people would stop saying that.

There's no scheduler inside Emacs. In contrast, there is something very much like a scheduler inside Firefox and inside Google Chrome so that more than one browser tab can make computational progress "simultaneously".

What Emacs does have (at least when it is running on a Unix-like OS rather than on Windows) is a way to use the underlying OS to create and manage child processes. I.e., a way to add processes to the OS's scheduler. But a terminal-emulation app that lets the user create and manage multiple terminal-emulation windows or tabs has the same capability, and no one calls it an OS with an OS.

Moreover, the programs `screen` and `tmux` also have that capability, and no one call them OSes within OSes.

People who like Emacs sometimes treat it like a generalized interface to information. But the combination of a Unix shell and a terminal-emulation app ("the Unix commandline") is often treated the same way, and no one calls it an OS within an OS. Ditto a simple web browser like Lynx.

EDIT: replaced "OS" with "OS within an OS" to try to make my argument less vulnerable to jacquesm's reply.


There was no scheduler in DOS either but it definitely was an OS.


> There was no scheduler in DOS either but it definitely was an OS.

Meh. If you have to call it an OS, it isn't one.


> I wish people would stop saying that.

Really? I thought I had an original thought there for a second. So, someone, somewhere, agrees with me out there.


"Well, the nice thing about an operating system is that you can write a text editor for it; that text editor is called evil-mode." https://bling.github.io/blog/2013/10/27/emacs-as-my-leader-v...


"Mind Exploded" basically does what vi/vim natively does in an inferior way... (2x key strokes!)


Vim is a modal editor, which means one keystroke doesn’t have the same meaning in one mode and in another. Emacs, on the other hand, doesn’t have all these modes, which is why you have to use modifier keys like ctrl/shift/alt to tell it what to do. That’s two paradigms, I’m not sure one is better than the other (note: I’m a Vim user).


I'm currently in the middle of attempting to gain proficiency in Emacs. I have to admit that it's difficult being someone that's spent 10+ years using Vim. I'm used to being able to just hit HJKL as a nervous habit, which doesn't go over so well in Emacs. I feel like there are many things in Vim that seem superior at first glance.

For example, if I want to do a regexp search/replace in Vim, I can do this from Normal Mode (which will replace throughout the whole file):

  :%s/regxp/replacement/g<enter>
Emacs (by default) has `replace-regexp`:

  M-x replace-regexp<enter>regexp<enter>replacement<enter>
My only problem? This only replaces from the cursor to the end of the file/buffer, so to replace over the whole file I would need to do:

  M-< M-x replace-regexp<enter>regexp<enter>replacement<enter>
It just seems that much more complicated, and now I've lost my place, so I'm at the top of the buffer rather than wherever I was in the file.

On the other hand, I find Emacs Lisp to be much easier to deal with then VimScript/VimL even as someone that has written my own Vim plugins, and created plugins to patch issues with files in the standard Vim dist (too lazy to submit a patch and wait for the next Vim release).


This obviously isn't a solution to your valid complaint, but you can use C-u C-SPC to navigate to your previous cursor position. It can band-aid your issue, but it's also quite useful in general.

https://www.gnu.org/software/emacs/manual/html_node/emacs/Ma...


I find that you need to be willing to write your own little elisp routines to get the best out of Emacs. If whole-file replacements is how you like your search and replace, then write a routine for that. My bugbear with regex replace - apart from rebinding it to M-r - was that, when applied to a region, it didn't keep the region. So I wrote a macro that "advised" the function (and any other function I choose) with code that restored the region after the command was finished.

Be aware, however, of iedit-mode. Select a region of text and enable iedit-mode, and any change to the selected region will be propagated to every other instance of the region's text throughout the document.

Using iedit-mode in combination with rgrep (recursive grep) and wgrep (editable grep buffer that propagates changes to the underlying documents) is a decent way of doing project-wide refactorings.

And of course, neither iedit nor wgrep are part of the base emacs install. Using the package manager is essential.


You can check https://github.com/syl20bnr/spacemacs if you want to use Evil mode not just for editing but for everything else in Emacs. Just clone to your ~/.emacs.d and start Emacs then everything will be automatically installed for you. Most key bindings outside of editing are Vim-like, created by Vim users. You already stick with Vim for 10 years and learned many things about, so I suggest you to keep that knowledge. But then, aside of editing text, if some Emacs utility does not have Evil key bindings, you should also learn the default, because most of the utilities are always in normal mode, so you only need to press a single key to execute most commands.

spacemacs also has extensive documentation, so you can learn key bindings easily and be productive with Emacs immediately without any extra configuration.


Here's some elisp I use to do this (assuming I understand your issue correctly and it's the same as mine):

  (defun replace-regexp-g ()
    (interactive)
    (save-excursion
      (goto-char 0)
      (call-interactively 'replace-regexp)))


Are you aware of evil-mode? One of the many things it implements is the :%s/stuff/otherstuff/g syntax.


I'm aware of evil-mode. I'm attempting to try 'the Emacs way' first. I'm not attempting to just throw myself in. When I need to be proficient I'll fallback to Vim, but I want to gain access to things like org-mode, for instance.


"The Emacs way" is very much "learn some elisp and write whatever you want".

I switched from Vim to Emacs and in the beginning there were some things I really missed. One that I remember was "*", which in Vim/my config highlights current word in whole buffer and let's you n/N between matches. In Emacs, doing the same with M-left C-s C-w felt just wrong.

Fixing this was a matter of 2-3 lines of very straightforward elisp. I since started relying more on Occur mode and IEdit mode for this, but the experience of lacking a feature and adding it absolutely painlessly remained with me.

Writing simple elisp and simple editing-related features is a joy under Emacs. It's much easier than in Vim, for a number of different reasons. This makes me think that "the Emacs way" is about scripting and programming it to do whatever you need it to do.


You may also be interested in https://github.com/nschum/highlight-symbol.el which provides highlighting of the current symbol, and provides highlight-symbol-{next,prev} commands to move between occurrences of a symbol.


Have you taken a look at NeoVim (https://github.com/neovim/neovim)? They plan on replacing VimScript with Lua.


I'm watching NeoVim, but I'm skeptical about their ambitious goals (i.e. refactoring internal Vim code). I do wish them luck though.


M-< C-M-% regexp RET replacement RET C-u C-space

If you are just replacing plain text (no regexps) then take a look at iedit. Then C-; will edit all occurrences of the word at cursor.


Iedit mode works beautifully with wgrep + rgrep/ack/ag results.


Emacs does have modes (even if we set aside vi/vim emulation modes like evil, which is discussed elsewhere in this thread).

When you use certain major or minor modes in emacs, you get to use a whole new set of keystrokes, by which you're effectively doing modal editing.

One well-known example is magit.[1] When you activate magit, you can type all sorts of new one- or two-key commands. This is comparable to modes in vim.

[1] - http://www.emacswiki.org/emacs/Magit


Exactly right! All input in Emacs is just a key-bind. In a buffer focused on text-editing, letter keys (e.g. "a") are actually bound to a function called self-insert-command which inserts the last character typed. Modes like magit just re-bind keys to different functions (e.g. "s" gets bound to magit-stage-item).


Thanks. As a Vim-only user I don’t know all these Emacs things (but am willing to learn).


I switched from Vim to Emacs 15+ years ago because I did not like modal editing. Now I am using evil-mode in Emacs :-|

I'm not sure which one is better either.


No because keystrokes happen at the same time. They are cords. Is typing 'A' 2x the keystrokes that typing 'a'. Sure but it doesn't matter, it happens at the same time -- 'Shift+a'.

So it is actaully Vim that takes 2x the time to do anything because you have multiple modes to track and switch from.

If you look at how stenographers type, they don't use modes, they use cords. They also minimize moving the hands away from the homerow (or equivalent of), and by "minimize" I think that movement might be 0 actually.


Counterpoint: many of the world's fastest typists avoid using modifier keys (and prefer caps lock over shift for typing uppercase letters), because using them requires careful timing: press the modifier after any other keys, press the key you need modified, lift the modifier. If you press the modifier too early or raise it too late, you screw up. In normal typing with no modifiers, it doesn't really matter when you lift the finger. You can afford to go much faster.


But programming is not equivalent to stenography. Stenography works on a stream of input speech converting it into text, whereas programming is separated into the 2 modes of browsing&thinking and actually editing.

But I think it comes down to preference of whether you want the universality of commands, or conceptual separation of modes.


I'll leave this comment here for those of us who still prefer vi. :)


Emacs is pretty decent, yep. It remains my editor of choice. From what I've read over the years it's a paradigm of poor design under the hood however.


It's pretty neat for a paradigm of poor design to last so long...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: