Posted on :: Tags: , , , ,

Emacs for Rust with rustic and lsp

Learning Rust is my personal goal for this year. It is very strict in type checking and memory ownership. So, I needed some help until I could fully grasp its key concepts and syntax. I use Emacs for almost everything, including coding. After an hour of searching, I think I found a pretty good setup (a part of .emacs.d/init.el):

;; Ensure that rust-mode is installed
(use-package rust-mode
  :ensure t
  :config
  ;; Set the key binding for rust-format-buffer
  (define-key rust-mode-map (kbd "C-c C-f") #'rust-format-buffer))

(use-package lsp-mode
  :init
  (add-hook 'rust-mode-hook #'lsp)
  :custom
  (lsp-rust-server 'rust-analyzer))

(use-package rustic
  :ensure
  :bind (:map rustic-mode-map
              ("M-j" . lsp-ui-imenu)
              ("M-?" . lsp-find-references)
              ("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))
  :config
  (add-hook 'rustic-mode-hook (lambda () (flyspell-mode -1)))
  )

;; Stop reformatting every time on save
(rust-disable-format-on-save)

We can peek into documentation and fn and struct definitions.

(setq lsp-inlay-hint-enable t)
(setq lsp-ui-peek-enable t)
(setq lsp-format-on-save nil)
(setq rustic-format-on-save nil)
(setq rust-format-on-save nil)

(setq special-display-buffer-names
      '("*rustic-compilation*"))

(setq special-display-function
      (lambda (buffer &optional args)
        (split-window)
        (switch-to-buffer buffer)
        (get-buffer-window buffer 0)))

(use-package company
  :ensure
  :custom
  (company-idle-delay 0.25) ;; how long to wait until popup
  ;; (company-begin-commands nil) ;; uncomment to disable popup
  :bind
  (:map company-active-map
	("C-n". company-select-next)
	("C-p". company-select-previous)
	("M-<". company-select-first)
	("M->". company-select-last)))

(use-package yasnippet
  :ensure
  :config
  (yas-reload-all)
  (add-hook 'prog-mode-hook 'yas-minor-mode)
  (add-hook 'text-mode-hook 'yas-minor-mode))

When we deal with multiple projects, unused and leftover workspace caused performance drawback. So, the following wrapper is pretty handy.

(defun cleanup-lsp ()
  "Remove all the workspace folders from LSP"
  (interactive)
  (let ((folders (lsp-session-folders (lsp-session))))
    (while folders
      (lsp-workspace-folders-remove (car folders))
      (setq folders (cdr folders)))))

Overall, coding Rust is pretty fun, and working with lsp, company, yasnippet can certainly teach me my mistakes interactively. They are quite resource-heavy, but I will need "a tutor" for a while.

Fix unstable Internet

Working from home for a couple of weeks, I learned that my network is very unstable, especially with the ethernet connection! The problem was my internet service provider is not top-notch, so the download and upload speed shouldn't exceed 100mb/s, but my ethernet device kept on trying to find better speed but couldn't do it. I found a nice solution that the network speed can be simply capped by disabling autoneg:

sudo lshw -C network
sudo ethtool --change ${eth} speed 100 autoneg off

Fix display issues

Amazon Prime Day got me a new monitor, which is spacious and bulky enough to force me to fold up my laptop screen on my small desk. But I found Ubuntu keeps on activating my laptop screen. I can exclusively switch on my HDMI screen with this command:

xrandr --output eDP-1 --off --output HDMI-1 --primary --auto