Emacs 08 - Configurazione per sviluppo Rust


Come prima cosa dobbiamo installare la rust toolchain tramite rustup, che può essere ottenuto tramite curl

curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf > rustup.sh
chmod +x rustup.sh
./rustup.sh

Se ad esempio stiamo su arch linux possiamo direttamente fare

pacman -S rustup

A questo punto possiamo installare la toolchain stable con

rustup install stable
rustup default stable

Questo installa varie cose tra cargo, il package manager dell'ecosistema Rust, e rustc, il compilatore di Rust.


Arrivati a questo punto possiamo compilare il nostro primo programma rust.

fn main() {
    println!("Hello World!");
}
rustc main.rs
./main 

Oppure possiamo utilizzare cargo per inizializzare un nuovo progetto.

cargo init new-rust-project

Per iniziare ad utilizzare rust con utilizzare il pacchetto rust-mode. Questo pacchetto però è molto limitato in quello che può fare. Per avere più feature dobbiamo utilizzare il protocollo LSP.

Il protocollo LSP (language Server Protocol) è utilizzato per aggiungere una serie di features tra cui:

  • auto-complete

  • go-to-definitions

  • documentation

  • type inference annotation

agli strumenti che utilizziamo per scrivere codice.

Per utilizzare questo protocollo abbiamo bisogno di un server e di un client. Ogni linguaggio di programmazione può avere diversi server, ciascuno dei quali può scegliere di implementare determinate features del protocollo LSP.

Per il linguaggio rust in particolare ci sono due servers:

Al momento della scrittura di questo articolo mi sto trovando meglio con rust analyzer, e dunque il tutorial mostrerà come installarlo e farlo funzionare su emacs.


In termine di software esterno, abbiamo bisogno di installare rust-analyzer, che può essere fatto nel seguente modo

https://github.com/rust-analyzer/rust-analyzer/releases/tag/2022-02-14

git clone https://github.com/rust-analyzer/rust-analyzer.git
cd rust-analyzer
cargo xtask install --server # will install rust-analyzer into $HOME/.cargo/bin

In ubuntu possiamo

sudo apt install snapd
sudo snap install rust-analyzer --beta

NOTA: nel codice emacs-lisp a seguire si assume di avere già installato il pacchetto use-package. Per maggiori informazioni rimando alle seguenti risorse:

Una volta installato rust analyzer dobbiamo configurare i seguenti pacchetti di emacs:

  • lsp: client emacs per interagire con il protocollo LSP

    (use-package lsp-mode
      :ensure
      :commands lsp
      :custom
      
      (lsp-eldoc-render-all t)
      (lsp-idle-delay 0.6)
      
      ;; what to use when checking on-save. "check" is default, I prefer clippy
      (lsp-rust-analyzer-cargo-watch-command "check")
      (lsp-rust-analyzer-server-display-inlay-hints t)
      
      :config
      (add-hook 'lsp-mode-hook 'lsp-ui-mode))
    
  • lsp-ui: gestione elementi grafici dei dati ottenuti interagendo con il server LSP

    (use-package lsp-ui
      :ensure
      :commands lsp-ui-mode
      :custom
      (lsp-signature-render-documentation nil)  
      (lsp-ui-peek-always-show nil)
      (lsp-ui-sideline-enable nil)
      (lsp-ui-sideline-show-hover nil)
      (lsp-ui-doc-enable nil)
    )
    
  • rustic: major-mode costruita sopra rustic-mode che si interfaccia con il protocollo lsp nel contesto dello sviluppo rust.

    (use-package rustic
      :ensure
      :bind (:map rustic-mode-map
                  ("M-j" . lsp-ui-imenu)
                  ("M-?" . lsp-find-references)
                  ("C-c C-c l" . flycheck-list-errors)
                  ("C-c C-c a" . lsp-execute-code-action)
                  ("C-c C-c r" . lsp-rename)
                  ("C-c C-c q" . lsp-workspace-restart)
                  ("C-c C-c Q" . lsp-workspace-shutdown)
                  ("C-c C-c s" . lsp-rust-analyzer-status)
                  ("C-c C-c e" . lsp-rust-analyzer-expand-macro)
                  ("C-c C-c d" . dap-hydra)
                  ("C-c C-c h" . lsp-ui-doc-glance))
      :config
      ;; uncomment for less flashiness
      (setq lsp-eldoc-hook nil)
      (setq lsp-enable-symbol-highlighting nil)
      (setq lsp-signature-auto-activate nil)
    
      ;; ;; comment to disable rustfmt on save
      ;; (setq rustic-format-on-save t)
      
      ;; (add-hook 'rustic-mode-hook 'rk/rustic-mode-hook)
      )
    
    (defun my/rustic-save-mode-hook ()
      (when (equal major-mode 'rustic-mode)
        (rustic-cargo-check)))
    
  • flycheck: utilizzato per mostrare gli errori

    (use-package flycheck
      :ensure t
      :config
      (setq flycheck-display-errors-function nil)  
      ;; (add-hook 'java-mode-hook 'flycheck-mode)
      )
    

    per fixare determinati errori ed aggiornare il pacchetto all'ultima versione dobbiamo fare le seguenti cose

    # update to current version
    cd /tmp
    git clone https://github.com/flycheck/flycheck
    cd /tmp/flycheck
    cp flycheck-ert.el flycheck.el ~/.emacs.d/elpa/flycheck-31/
    
    # remove previously byte-compiled elispc ode
    rm ~/.emacs.d/elpa/flycheck-31/flycheck.elc ~/.emacs.d/elpa/flycheck-31/flycheck-ert.elc