Don't let the default bare configuration of Emacs scare you away: It's highly customizable outside (see e.g. better-defaults for what aims to be improvements over default settings), cross-platform, and there are a large number of great packages such as Magit and org-mode. In my opinion, just Magit alone makes your initial investment into learning Emacs worth it. As a plus, when stuck working on a Windows machine, you can still pop open Emacs and make the best of the situation. But Emacs by itself is just a text editor and not a full-blown IDE. But with a little configuration and installing packages, it can be made to act like one.

Initially when I moved the switch to Emacs as my default text editor back in ~2009, I was almost exclusively working with C++. I spent consider about of time setting up the "perfect" configuration for code-completion and jumping to definitions with cedet and semantic combo, which on larger code bases resulted in a pain-stakingly slow code-completion and error- prone jump-to-definition with no support for c++11 standards onward.

These days the three class of languages I frequently use are c++, python, js/nodejs, and the the out-of-the-box code completion with emacs for these languages are minimal or non-existent. But with minimal effort and using existing toolset, you can get a uniform-ish and decent IDE-like behavior in Emacs.

C and C++ : RTags

Any decent code completion for Emacs seems to require a daemon running in the background. By far the best solution I have used for C and C++ is RTags. As a plus, with an initial configuration in place, it will "just work" if the project uses cmake as its build tool.

Installation

I use rtags with company as opposed to auto-complete as the text completion framework. This made the initial build, installation, and setup for getting rtags working was a pretty frustrating experience. Specifically, what I learned was that the code completion for some reason wasn't working if working under /tmp. My final setup documetation was as follows:

  1. Install prerequisites. For this installation I'm using OpenSUSE
    zypper in gcc-c++ clang clang-devel llvm llvm-devel cmake
    
  2. Build rtags
    > git clone --recursive https://github.com/Andersbakken/rtags.git
    > cd rtags && mkdir build && cd build
    > cmake ..
    > cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .
    > make -j 4
    
  3. Copy bin files
    > cp ./bin/* ~/bin/
    
  4. Install emacs prerequisites from melpa: company, rtags, company-rtags
  5. Update emacs init scripts
    ;; use and initalize package if haven't already done so
    (require 'cl)
    (require 'rtags)
    (require 'company)
    
    (define-key c-mode-base-map (kbd "M-.")
      (function rtags-find-symbol-at-point))
    (define-key c-mode-base-map (kbd "M-,")
      (function rtags-find-references-at-point))
    (rtags-enable-standard-keybindings)
    
    (setq rtags-autostart-diagnostics t)
    (rtags-diagnostics)
    (setq rtags-completions-enabled t)
    (push 'company-rtags company-backends)
    (global-company-mode)
    (define-key c-mode-base-map (kbd "<C-tab>") (function company-complete))
    
  6. Check if everything's working fine.
    > rdm &
    > cd </path/to/rtags/build/directory>
    > rc -J ../
    
    If no errors, then pop open a new emacs session, and navigate to /path/to/rtags/src/rdm.cpp and verify that symbol combinations work.
Video of using rtags inside its own codebase:

Troubleshooting

Python

I use jedi and company mode for python. To get started, read the official documentation, or:

  1. Install prerequisites
    su -c "zypper in python3-virtualenv"
    
  2. Start a project
    > mkdir my-project-name
    > cd my-project-name
    > virtualenv-3.7 env # replace with appropriate virtualenv version
    
  3. Activate the virtual environment and install jedi
    > . ./env/bin/activate
    > pip install jedi
    
  4. Move contents to ~/bin/jedi-env for convenience
  5. Install elpy in emacs. I generally install packages from melpa. Pop open emacs and do M-x package-list-packages and install elpy
  6. Update ~/.emacs.d/ config files
    ;...
    (elpy-enable)
    (add-hook 'python-mode '(lambda()
    (set (make-local-variable 'company-backends '(elpy-company-backend)))
    (company-mode)))
    
    (defun hf/python-mode-hook ()
      (add-to-list 'company-backends 'company-jedi)
      (require 'pyvenv)
      (pyvenv-activate "~/bin/jedi-env/")
      (setq jedi:setup-keys t)
      (setq jedi:complete-on-dot t)
      (setq jedi:use-shortcuts t)
      (jedi:setup)
      )
    
    (add-hook 'python-mode-hook 'hf/python-mode-hook)
    ;...
    
  7. If for some reason pyvenv is not enabled, try explicitely enabling jedi virtual environment
    M-x pyvenv-activate <enter>
    
    and direct to parent directory containing the virtual environment.
  8. Everything should work now, e.g.
    1. M-. should jump to definition
    2. C-M i should force call elpy-company-backend and autocomplete at point
    3. C-c ? show docstring of object at given point

Below shows a demo of how it works. Consider playing the video in fullscreen mode and look at messages in the minibuffer especially when there is a small pause.

Javascript and Node.js

Reference

  1. Install tern globally
    su -c "npm install -g tern"
    
  2. Install company-tern in Emacs
  3. Add following to ~/.emacs.d/init.el
    (require 'company-tern)
    (eval-after-load 'company
       '(add-to-list 'company-backends 'company-tern))
    (add-hook 'js2-mode-hook (lambda () (tern-mode t)))
    
  4. Create .tern-project in your root project directory with following contents
    {
        "plugins": {
            "node": {
        },
            "libs": [
        ]
      }
    }
    
  5. Demo of how it works: