setup emacs IDE for Rust

Objectives:

  1. generate a simple hello world in Rust.
  2. format on save
  3. auto completion
  4. code navigation
  5. cargo integration

use 100ms_dot_emacs

If you are not so patient, you can install 100ms_dot_emacs, it works out of box.

generate a new project

https://doc.rust-lang.org/cargo/guide/creating-a-new-project.html

% cargo new hello_world --bin
     Created binary (application) `hello_world` package
% tree .
.
└── hello_world
    ├── Cargo.toml
    └── src
        └── main.rs

2 directories, 2 files
chunywan@localhost:rust% cd hello_world/
chunywan@localhost:hello_world% cargo build
   Compiling hello_world v0.1.0 (/Users/chunywan/d/working/learn/rust/hello_world)
    Finished dev [unoptimized + debuginfo] target(s) in 1.80s
chunywan@localhost:hello_world% cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/hello_world`
Hello, world!

install emacs rust-mode

https://github.com/rust-lang/rust-mode

format on save

install rustfmt

https://github.com/rust-lang/rustfmt

rustup component add rustfmt
M-x rust-format-buffer

you might need exec-path-from-shell if you are using mac os.

https://github.com/purcell/exec-path-from-shell

M-x package-install RET exec-path-from-shell RET.
(use-package exec-path-from-shell
  :ensure t
  :config
  (when (or (memq window-system '(mac ns x))
            (memq system-type '(darwin)))
    (exec-path-from-shell-initialize)))
(use-package rust-mode
  :ensure t
  :config
  (setq rust-format-on-save t))

auto completion

install racer

https://github.com/racer-rust/racer#installation

% cargo install racer
% rustup toolchain add nightly
% cargo +nightly install racer
% rustup component add rust-src

https://github.com/racer-rust/emacs-racer

(use-package rust-mode
  :mode "\\.rs\\'"
  :ensure t
  :config
  (setq rust-format-on-save t)
  (add-hook 'rust-mode-hook #'cargo-minor-mode))
(use-package racer
  :ensure t
  :config
  :after (rust-mode)
  :config
  (add-hook 'rust-mode-hook #'racer-mode)
  (add-hook 'racer-mode-hook #'eldoc-mode)
  (add-hook 'racer-mode-hook #'company-mode)
  (define-key rust-mode-map (kbd "TAB") #'company-indent-or-complete-common)
  (setq company-tooltip-align-annotations t)
  (setq racer-loaded 1))

You can input std::io::B<TAB> , to test whether it works or not.

To test go to definition: Place your cursor over a symbol and press M-. to jump to its definition.

Press C-x 4 . to jump to its definition in another window.

Press C-x 5 . to jump to its definition in another frame.

Press M-, to jump back to the previous cursor location.

If it doesn't work, try M-x racer-debug to see what command was run and what output was returned.

In this way, we can navigate in source code.

cargo integration

(add-hook 'rust-mode-hook #'cargo-minor-mode)

cargo-minor-mode is enabled in rust mode, now we can use the following cargo commands.

C-c C-c C-a     cargo-process-add
C-c C-c C-b     cargo-process-build
C-c C-c C-c     cargo-process-repeat
C-c C-c C-d     cargo-process-doc
C-c C-c C-e     cargo-process-bench
C-c C-c C-f     cargo-process-current-test
C-c C-c TAB     cargo-process-init
C-c C-c C-k     cargo-process-check
C-c C-c C-l     cargo-process-clean
C-c C-c RET     cargo-process-fmt
C-c C-c C-n     cargo-process-new
C-c C-c C-o     cargo-process-current-file-tests
C-c C-c C-r     cargo-process-run
C-c C-c C-s     cargo-process-search
C-c C-c C-t     cargo-process-test
C-c C-c C-u     cargo-process-update
C-c C-c C-v     cargo-process-doc-open
C-c C-c C-x     cargo-process-run-example
C-c C-c C-S-a   cargo-process-audit
C-c C-c C-S-d   cargo-process-rm
C-c C-c C-S-k   cargo-process-clippy
C-c C-c C-S-o   cargo-process-outdated
C-c C-c C-S-u   cargo-process-upgrade

language server support

% rustup component add rls rust-analysis rust-src
(use-package lsp-mode
  :defines (lsp-keymap-prefix)
  :commands (lsp lsp-deferred)
  :init (setq lsp-keymap-prefix "C-l")
  :hook (((rust-mode)
          . lsp-deferred)
         (lsp-mode . lsp-enable-which-key-integration)))