Emacs configuration for Rust

Related tags

IDEs rust-mode
Overview

MELPA

Table of Contents

Introduction

rust-mode makes editing Rust code with Emacs enjoyable. It requires Emacs 25 or later, and is included in both Emacs Prelude and Spacemacs by default.

This mode provides:

  • Syntax highlighting (for Font Lock Mode)
  • Indentation
  • Integration with Cargo, clippy and rustfmt

This mode does not provide autocompletion, or jumping to function / trait definitions. See Auto-completion / code navigation below for tips on how to enable this.

Installation

Melpa

The package is available on MELPA. Add this to your init.el.

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(package-refresh-contents)

Now you can install rust-mode with:

M-x package-install rust-mode

And put this in your config to load rust-mode automatically:

(require 'rust-mode)

Manual installation

Clone this repository locally, and add this to your init.el:

(add-to-list 'load-path "/path/to/rust-mode/")
(autoload 'rust-mode "rust-mode" nil t)

Feature guide

Indentation

Commands like TAB should indent correctly.

The Rust style guide recommends spaces rather than tabs for indentation; to follow the recommendation add this to your init.el, which forces indentation to always use spaces.

(add-hook 'rust-mode-hook
          (lambda () (setq indent-tabs-mode nil)))

Code formatting

The rust-format-buffer function will format your code with rustfmt if installed. By default, this is bound to C-c C-f.

The variable rust-format-on-save enables automatic formatting on save. For example, add the following in your init.el to enable format on save:

(setq rust-format-on-save t)

Running / testing / compiling code

The rust-run, rust-test, rust-compile and rust-check functions shell out to Cargo to run, test, build and check your code. Under the hood, these use the standard Emacs compile function.

These are not bound by default. To bind these to keyboard shortcuts, you can use the following in your init.el:

(define-key rust-mode-map (kbd "C-c C-c") 'rust-run)

Clippy

rust-run-clippy runs Clippy, a linter.

Easy insertion of !dbg

rust-dbg-wrap-or-unwrap either wraps or unwraps the current region in dbg!. This can be useful for easily adding debug lines to your program.

This is bound to C-c C-d by default.

Other recommended packages

Auto-completion / code navigation

This package does not provide integration with RLS, which provides auto-completion and code navigation. To use this you need an Emacs package that supports LSP.

Two examples are:

A lighter package that uses racer is emacs-racer.

flycheck

flycheck allows highlighting compile errors and Clippy lints inline.

cargo.el

cargo.el provides a minor mode for integration with Cargo, Rust's package manager.

Rustic

rustic is a fork of rust-mode, extending it with other features such as integration with LSP and with flycheck.

For package maintainers

Tests

The file rust-mode-tests.el contains tests that can be run via ERT. You can use run_rust_emacs_tests.sh to run them in batch mode, if you set the environment variable EMACS to a program that runs emacs.

Comments
  • Re-implement rust-in-macro faster

    Re-implement rust-in-macro faster

    This function is called repeatedly by syntax-ppss and so needs to be fast. We adopt a simpler mechanism for determining whether we are in a macro.

    Fixes #208

    opened by phillord 37
  • Package maintainer

    Package maintainer

    Since nobody seems to have time for maintaining the package, I would propose that I take care of this. Rustic now has some users and maybe we should suggest to use it instead of rust-mode for emacs26+. However it would be nice to get some help with this(rust-mode + rustic).

    What do you think ?

    opened by brotzeit 32
  • crippy bug: stdin buffer if

    crippy bug: stdin buffer if "Rust Format On Save" is on

    It is random, I have no idea how to reproduce it.

    Time to time when I save current buffer with rust-mode, let's call it a.rs, emacs does not save it, and instead it open buffer stdin, in other words I press C-x s and current buffer change to "stdin" buffer. This buffer is empty, and a.rs still in modified state. I switch back to a.rs, try to save it and again empty stdin instead of a.rs.

    So actually I can not save my rust buffer, I have to set "Rust Format On Save" to off to make possible save, or change mode from rust-mode to text-mode.

    This bug appear only recently, so I suppose it is related to last "rustfmt" changes in master.

    GNU Emacs 26.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.10) of 2019-08-29 rust-mode 20200229.1547

    bug 
    opened by Dushistov 29
  • Significant slowdown with rust-match-angle-brackets non nil

    Significant slowdown with rust-match-angle-brackets non nil

    I'm experiencing serious slowdowns when entering insert mode & navigating in general all of a sudden. Not sure what the cause is but figured I'd create an issue as it doesn't happen with rust-mode turned off.

    Here's the output from the profiler-report:

    
    Function                            Cpu samples   %
    
    timer-event-handler                       13844  92%
    command-execute                             782   5%
     ...                                        187   1%
    redisplay_internal (C function)             169   1%
    eldoc-pre-command-refresh-echo-area           5   0%
    sp--save-pre-command-state                    3   0%
    
    

    If I expand timer-event-handler, most of the CPU is being hogged on rust-in-macro within the up-list function. Also backward-up-list hogs a good chunk of CPU.

     - apply                                                         2171  77%
      - hl-paren-highlight                                           2090  74%
       - scan-sexps                                                  2077  74%
        - internal--syntax-propertize                                2077  74%
         - syntax-propertize                                         2077  74%
          - rust-syntax-propertize                                   2073  74%
           - rust-ordinary-lt-gt-p                                   2073  74%
            - rust-in-macro                                          1955  69%
             + rust-in-macro                                         1615  57%
             + backward-up-list                                       241   8%
             + rust-rewind-irrelevant                                  95   3%
             + rust-looking-back-ident                                  4   0%
            + rust-in-str-or-cmnt                                     118   4%
    

    Anyone experienced anything similar?

    Same issue on current nightly & stable (1.17) I've tried with a clean .spacemacs file and without any additional packages. It's only when rust-mode is enabled I run into this slowdown.

    The file I'm working on is less than 1k lines.

    Also as an aside, I've tried Emacs24, Ubuntu 15.04, 16.04 and now upgraded to 16.10. This is on a Virtual machine.

    Description:	Ubuntu 16.10
    Release:	16.10
    Codename:	yakkety
    
    bug 
    opened by stianeklund 28
  • Fix window scrolling after rustfmt is run

    Fix window scrolling after rustfmt is run

    Hello,

    I tried investigating the window scrolling after rustfmt is run (this issue has been referenced in various forms in issues #268 #231 #251) as I am still experiencing it and imo it's pretty annoying.

    I'm not an elisp expert, but I think a quick fix/workaround could be to simply nail the window start position and restore it after rustfmt has finished.

    I think there may be still cases where the code reformatting can be a bit confusing (f.e. rustfmt'ing a big messed up file), but at least I'm not getting mad every time I compulsively save a buffer :-)

    Can you let me know what you think of this little patch? I tested it a bit and it has greatly improved my coding experience with rustfmt.

    Thanks for your time!

    EDIT: I did some checks, but I'm not sure how to fix those warning that make the CI fail EDIT2: maybe fixed (not sure if fix is correct though)

    opened by apiraino 21
  • Add doctest editing command

    Add doctest editing command

    Adds a command rust-edit-doctest (bound to C-c C-e by default) that opens the doctest around point in an indirect buffer and pre– as well as postprocesses it to ease editing. The indirect buffer is placed in a new rust-doctest-mode that recognizes a leading hash as a comment character. After editing, the code is replaced in the original file and the region is re-indented. Here’s a screenshot:

    snap2

    This is all accomplished using edit-indirect. If that package is not loaded, the keybinding is not added. I initially placed the definition of the rust-edit-doctest command itself under a conditional, but then I thought it would be more useful to have the command show an explanatory error in case it’s missing.

    rust-doctest-mode doesn’t account for escaped hashes. I’m not sure how to implement that. Any suggestions would be welcome!

    opened by Aankhen 19
  • rust-enable-format-on-save + compile = annoying jump to end of buffer

    rust-enable-format-on-save + compile = annoying jump to end of buffer

    This is bug is similar to #231, but instead of begin of buffer, at now it jumps to the end of buffer with rust code. I have applied fix from #251

    Steps to reproduce:

    1. Split window by two and run compile command in the second one: C-x 2 C-x O M-x compile choose and run compilation command
    2. Return back to code window and choose code at the middle of buffer and change it's formating in so way that rustfmt should modify it (Do not save buffer)
    3. Jump to compilation window C-x O and press g

    as result the position of cursor in buffer with rust code will change to the end of buffer.

    /cc @brotzeit

    rustfmt 
    opened by Dushistov 14
  • Simplify and correct angle bracket propertizing and macro argument detection.

    Simplify and correct angle bracket propertizing and macro argument detection.

    Fixes #465.

    When rust-syntax-propertize uses rust-macro-scopes to find ranges of text that are macro arguments, it ends up inadvertently poisoning the syntax-ppss cache by applying it to text that doesn't have the necessary syntax-table properties applied yet - the very job that rust-syntax-propertize is trying to do.

    However, rust-macro-scopes does much more work than necessary. Rather than producing a list of ranges of macro arguments, we can just use the list of enclosing opening parens provided by syntax-ppss, checking each paren to see if it seems to be a macro or macro_rules call.

    We have to keep syntax-ppss's cache accurate for other reasons anyway, so we might as well just use its data, rather than introducing another cache of our own - especially a problematic one (see #465).

    • rust-mode.el (rust-in-macro): Consult syntax-ppss's list of enclosing parens, rather than using rust-macro-scope. Remove optional arguments, which were only used by tests. (rust-macro-scopes, rust-macro-scope): Delete. Now we just use syntax-ppss's internal cache. (rust-syntax-propertize): Don't bind rust-macro-scopes. (rust-looking-back-macro-rules): New function. (rust-looking-back-macro): Support a space between macro name and !, by consulting rust-expression-introducers. (rust-expression-introducers): New constant. Use in rust-looking-back-macro and rust-is-in-expression-context. (rust-is-in-expression-context): Use rust-expression-introducers. (rust-looking-back-ident): Don't use looking-back. We've already moved to the correct spot for looking-at, within a save-excursion.
    • rust-mode-tests.el: Update tests.
    opened by jimblandy 13
  • Looking for feedback

    Looking for feedback

    I've been trying to improve some stuff. Let me know what you think about it. I can rebase if you want to merge it.

    Try these commands: rust-compile rust-recompile rust-format-call rust-run-clippy

    opened by brotzeit 13
  • rust-mode.el: check for possible space between variable name and type

    rust-mode.el: check for possible space between variable name and type

    Fixes the following problem: consider code

    fn foo(a: u32, b : u32) {}
    

    Here, b was not highlighted as a variable, because the regex didn't take into account possible space before the colon.

    Signed-off-by: Konstantin Kharlamov [email protected]

    opened by Hi-Angel 12
  • Large numbers of <>'s in a file cause massive slowdown

    Large numbers of <>'s in a file cause massive slowdown

    E.g. it takes several seconds for a keypress to appear at the bottom of a file with 400 copies of fn foo<T>() {}. Editing the same file after s/<T>/_T_/ (to preserve the size) is fine.

    opened by huonw 12
  • no library targets found in package `current_project`

    no library targets found in package `current_project`

    I am very new to emacs and are trying to set it up for rust development. When I am in a *.rs file and M-x rust-mode this error pops up:

    Suspicious state from syntax checker rust-cargo: Flycheck checker rust-cargo returned 101, but its output contained no errors: error: no library targets found in package `learn_async`
    
    Try installing a more recent version of rust-cargo, and please open a bug report if the issue persists in the latest release.  Thanks!
    
    

    I updated cargo rust with: rustup update and updated all my packages with paradox. Emacs: Doom OS: Fedora config.el:

    [...]
    (after! rustic
      (setq lsp-rust-server 'rust-analyzer))
    
    (use-package lsp-mode
      :ensure
      :commands lsp
      :custom
      ;; what to use when checking on-save. "check" is default, I prefer clippy
      (lsp-rust-analyzer-cargo-watch-command "clippy")
      (lsp-eldoc-render-all t)
      (lsp-idle-delay 0.6)
      ;; enable / disable the hints as you prefer:
      (lsp-rust-analyzer-server-display-inlay-hints t)
      (lsp-rust-analyzer-display-lifetime-elision-hints-enable "skip_trivial")
      (lsp-rust-analyzer-display-chaining-hints t)
      (lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names nil)
      (lsp-rust-analyzer-display-closure-return-type-hints t)
      (lsp-rust-analyzer-display-parameter-hints nil)
      (lsp-rust-analyzer-display-reborrow-hints nil)
      :config
      (add-hook 'lsp-mode-hook 'lsp-ui-mode))
    
    (use-package lsp-ui
      :ensure
      :commands lsp-ui-mode
      :custom
      (lsp-ui-peek-always-show t)
      (lsp-ui-sideline-show-hover t)
      (lsp-ui-doc-enable nil))
    

    (rustic and lsp mode both don't work either but I am starting with rust-mode, because it told me to open a new issue)

    opened by Bkeinn 6
  • Abilty to customize the enabling of URL shortener for playpen

    Abilty to customize the enabling of URL shortener for playpen

    This makes me share the Playpen URL directly. And this is kind of necessary for me since the region I'm out of currently, the URL shortener domain itself is blocked. Snapshot here: https://imgur.com/a/ugLLVwP

    opened by psibi 0
  • Support multiple binary targets in `rust-run`

    Support multiple binary targets in `rust-run`

    rust-run fails if cargo run needs a --bin argument, which is the case if:

    1. The workspace has multiple binary targets.
    2. No target is listed as the package's default-run

    It is probably reasonably easy to support this. A possible interface update to rust-run could simply prompt for a target name iff both conditions above hold (multiple binary target, no default) OR it's called with an argument. The chosen target's name could be saved somewhere so further invocations of rust-run can just reuse it (unless called with an arg)

    This is a quick and dirty way to get all binary targets from the current workspace, and the default target:

    (let* ((json (with-temp-buffer
                   (call-process "cargo" nil (current-buffer) nil
                                 "metadata" "--format-version" "1")
                   (goto-char (point-min))
                   (json-parse-buffer)))
           ;; !! this is a bit dirty. !!
           (members (seq-map (lambda (wm)
                               (car (split-string wm " ")))
                             (gethash "workspace_members" json)))
           (targets
            (-flatten ; from dash.el, but not strictly required.
             (seq-map (lambda (v)
                        (seq-keep
                         (lambda (target)
                           (when (seq-contains-p
                                  (gethash "kind" target) "bin" 'string=)
                             (gethash "name" target))) v))
                      (seq-map (lambda (package) (gethash "targets" package))
                               (seq-filter
                                (lambda (pkg) (seq-contains-p members (gethash "name" pkg)))
                                (gethash "packages" json))))))
           (default-run (gethash "default_run"
                                 (car
                                  (seq-filter
                                   (lambda (item) (string= "raoc2021" (gethash "name" item)))
                                   (gethash "packages" json))))))
      (message "Workspace members: %s" members)
      (message "Binary targets: %s" targets)
      (message "Default run target is: %s" default-run))
    

    What do you think?

    opened by thblt 5
  • `rust-beginning-of-defun` skips async functions

    `rust-beginning-of-defun` skips async functions

    rust-beginning-of-defun skips async functions.

    The problem starts at rust-mode.el:1228

    (defvar rust-top-item-beg-re
      (concat "^\\s-*\\(?:priv\\|pub\\)?\\s-*"
              (regexp-opt
               '("enum" "struct" "type" "mod" "use" "fn" "static" "impl"
                 "extern" "trait"))))
    
    (defun rust-beginning-of-defun (&optional arg)
      "Move backward to the beginning of the current defun.
    
    With ARG, move backward multiple defuns.  Negative ARG means
    move forward.
    
    This is written mainly to be used as `beginning-of-defun-function' for Rust.
    Don't move to the beginning of the line. `beginning-of-defun',
    which calls this, does that afterwards."
      (interactive "p")
      (re-search-backward (concat "^\\(" rust-top-item-beg-re "\\)\\_>")
                          nil 'move (or arg 1)))
    

    rust-top-item-beg-re does not include the async keyword anywhere and therefore does not match a function with the async keyword.

    opened by cowile 2
  • cargo check and cargo metadata not respecting CARGO_HOME env variable.

    cargo check and cargo metadata not respecting CARGO_HOME env variable.

    I have my CARGO_HOME and RUSTUP_HOME set to ~/.loca/share/cargo and ~/.local/share/rustup respectively, all commands do find the correct binary and run the correct command, but each time I make a change to my rust source file or Cargo.toml file cargo check or cargo metadata fires up automatically using the default cargo directory which is ~/.cargo and keeps re-compiling my program which takes some time and as it is needed to get linting and all I can't skip it.

    I tried editing several variables to fix the issue but nothing seems to help,

      (use-package rust-mode
        :straight t
        :hook (rust-mode . lsp-deferred)
        :config
        (with-eval-after-load "lsp-mode"
          (add-to-list 'lsp-enabled-clients 'rust-analyzer))
        :custom
        (rust-format-on-save t)
        (rust-cargo-bin "~/.local/share/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo")
        (rust-rustfmt-bin "~/.local/share/rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rustfmt")
        (lsp-rust-library-directories '("~/.local/share/cargo/registry/src" "~/.local/share/rustup/toolchains"))
        (lsp-rust-analyzer-library-directories '("~/.local/share/cargo/registry/src" "~/.local/share/rustup/toolchains")))
    

    I added all those variables under the custom section, but nothing helps.

    I had the problem with other commands not finding the binary path correctly at first, but I fixed that by installing,

      (use-package exec-path-from-shell
        :straight t)
    
      (when (memq window-system '(mac ns x))
        (exec-path-from-shell-initialize))
    

    If I delete the ~/.cargo directory I get error,

    LSP :: Error from the Language Server: waiting for cargo metadata or cargo check (Unknown error)
    

    and after few seconds it starts again, creating the ~/.cargo directory and re-compiling my program.

    opened by apoorv569 0
Releases(1.0.5)
Owner
The Rust Programming Language
The Rust Programming Language
crispmacs is a WIP implementation of Emacs from scratch in Rust.

crispmacs is a WIP implementation of Emacs from scratch in Rust.

rust 3 Jul 31, 2022
Racer support for Emacs

Racer for Emacs This is the official Emacs package for Racer. Table of Contents Racer for Emacs Completion Find Definitions Describe Functions and Typ

null 398 Nov 30, 2022
Auto-Complete is an intelligent auto-completion extension for Emacs.

Auto-Complete is an intelligent auto-completion extension for Emacs. It extends the standard Emacs completion interface and provides an environment that allows users to concentrate more on their own work.

Emacs Auto-Complete 1.7k Dec 28, 2022
On the fly syntax checking for GNU Emacs

https://www.flycheck.org Modern on-the-fly syntax checking extension for GNU Emacs. Try it! For a more gentle introduction read the Installation instr

Flycheck 2.3k Dec 30, 2022
Vim configuration for Rust.

rust.vim Description This is a Vim plugin that provides Rust file detection, syntax highlighting, formatting, Syntastic integration, and more. It requ

The Rust Programming Language 3.4k Jan 8, 2023
Rust IDE support for Atom, powered by the Rust Language Server (RLS)

IDE-Rust Rust language support for Atom-IDE, powered by rust-analyzer. Features Auto-completion Diagnostics (errors and warnings from rustc) Document

The Rust Programming Language 239 Dec 14, 2022
rust-analyzer is a modular compiler frontend for the Rust language

rust-analyzer is a modular compiler frontend for the Rust language. It is a part of a larger rls-2.0 effort to create excellent IDE support for Rust.

null 11.2k Jan 8, 2023
Rust language support in Atom - LOOKING FOR MAINTAINER, see #144

Rust language support in Atom Adds syntax highlighting and snippets to Rust files in Atom. Install Install the package language-rust in Atom (Preferen

Andreas Neuhaus 118 Oct 11, 2022
Eclipse Corrosion - Rust edition in Eclipse IDE

Eclipse Corrosion Rust edition and debug in Eclipse IDE Corrosion is a Rust development plugin for the Eclipse IDE, providing a rich edition experienc

Eclipse Foundation 194 Dec 23, 2022
RustDT is an Eclipse based IDE for the Rust programming language:

Project website: http://rustdt.github.io/ As of 2017, RustDT is no longer actively maintained, see this blog post for more information. If you are int

null 351 Aug 20, 2022
Better Rust/Cargo support for Flycheck

flycheck-rust — Flycheck for Rust This Flycheck extension configures Flycheck automatically for the current Cargo project. Setup Install from MELPA or

Flycheck 112 Sep 21, 2022
NetBeans Rust plugin

Rust NetBeans Plugin A NetBeans plugin for Rust. Linux / OSX Windows Requirements NetBeans 8.2.x Java 8+ Rust Cargo Rustup Features So far, it include

drrb 52 Oct 10, 2022
Rust plugin for the IntelliJ Platform

Rust plugin for the IntelliJ Platform Build Status Check Stable Beta Nightly Installation & Usage Available installation options and features are desc

IntelliJ Rust 4.2k Jan 2, 2023
Rust IDE

This branch contains the development of a "new ride" that maintain a small impact on the ui library. This is for a few reasons. Can customize the colo

Gustav Jansson 171 Dec 24, 2022
An IDE for Rust

Introduction SolidOak is a simple IDE for Rust. See the website for binary releases. It has the following features: An embedded copy of Neovim as its

Zach Oakes 907 Dec 29, 2022
The official Sublime Text 3 package for the Rust Programming Language

Rust Enhanced About This is a Sublime Text 3 package which supports Rust starting with version 1.0, it makes no attempt at supporting earlier incompat

The Rust Programming Language 704 Jan 7, 2023
Rust Cargo command bindings

Vim Cargo Simple vim command bindings to quickly run cargo stuff from vim. Commands Available, mapping with their Cargo equivalant: CargoBench CargoBu

Timon Vonk 52 Dec 24, 2022
Visual Studio extension for Rust

Visual Studio extension for Rust Currently in development, and not feature complete. Stable versions are available on the Visual Studio extension gall

PistonDevelopers 697 Dec 18, 2022
Rust extension for Visual Studio 2017 with RLS support

Rust support for Visual Studio 2017 Preview Adds language support for Rust to Visual Studio 2017. Supports: code completion goto definition find all r

Zoey Riordan 111 Aug 4, 2022