Skip to content

Instantly share code, notes, and snippets.

@nimeshneema
Last active March 26, 2026 07:24
Show Gist options
  • Select an option

  • Save nimeshneema/9060117c2d94c8912176a5b74a127383 to your computer and use it in GitHub Desktop.

Select an option

Save nimeshneema/9060117c2d94c8912176a5b74a127383 to your computer and use it in GitHub Desktop.
;; ============================================================
;; Emacs 30.2 — Scala IDE Configuration (Clean Test Config)
;; Approach: lsp-mode + Metals (official recommendation)
;; ============================================================
;; ---- Package Management Setup ----
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(package-initialize)
;; Refresh package list on first run
(unless package-archive-contents
(package-refresh-contents))
;; Install use-package if not already installed
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)
(setq use-package-always-defer t)
;; ---- General Settings ----
;; Keep auto-save/backup files out of project directories
;; (Metals is sensitive to stray files in the project tree)
(setq backup-directory-alist `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(column-number-mode 1)
(show-paren-mode 1)
(setq inhibit-startup-screen t)
(setq-default indent-tabs-mode nil)
(setq-default tab-width 2)
;; which-key is built into Emacs 30 — shows available keybindings after a prefix
(which-key-mode 1)
;; ---- Performance Tuning for LSP ----
;; These are critical for Metals. Without them, large projects will lag.
;; Increase GC threshold to 100MB (default 800KB causes constant GC pauses)
(setq gc-cons-threshold 100000000)
;; Increase process read size to 1MB (default 4KB too small for LSP JSON)
(setq read-process-output-max (* 1024 1024))
;; ---- scala-mode — Syntax Highlighting & Indentation ----
(use-package scala-mode
:interpreter ("scala" . scala-mode)
:mode "\\.s\\(cala\\|bt\\)$")
;; ---- sbt-mode — Run sbt Commands from Emacs ----
(use-package sbt-mode
:commands sbt-start sbt-command
:config
;; Allow SPACE in minibuffer (without this, space triggers completion)
(substitute-key-definition
'minibuffer-complete-word
'self-insert-command
minibuffer-local-completion-map)
;; Disable sbt supershell (breaks sbt-mode output parsing)
(setq sbt:program-options '("-Dsbt.supershell=false")))
;; ---- flycheck — Real-time Error Highlighting ----
(use-package flycheck
:init (global-flycheck-mode))
;; ---- company — Auto-completion Framework ----
(use-package company
:hook (scala-mode . company-mode)
:config
(setq company-idle-delay 0.2)
(setq company-minimum-prefix-length 1)
(setq lsp-completion-provider :capf))
;; ---- yasnippet — Code Snippets ----
(use-package yasnippet
:hook (scala-mode . yas-minor-mode))
;; ---- posframe — Pop-up Framework (needed by dap-mode) ----
(use-package posframe)
;; ---- lsp-mode — The Core LSP Client ----
(use-package lsp-mode
:hook
(scala-mode . lsp)
(lsp-mode . lsp-lens-mode)
:config
(setq lsp-prefer-flymake nil)
(setq lsp-keep-workspace-alive nil)
(setq lsp-headerline-breadcrumb-enable t)
(setq lsp-semantic-tokens-enable t)
(setq lsp-log-io nil))
;; ---- lsp-metals — Scala-specific LSP Features ----
(use-package lsp-metals
:ensure t
:custom
(lsp-metals-server-args '(
"-J-Dmetals.allow-multiline-string-formatting=off"
"-J-Dmetals.icons=unicode"))
(lsp-metals-enable-semantic-highlighting t)
:hook (scala-mode . lsp))
;; ---- lsp-ui — Enhanced UI ----
(use-package lsp-ui
:after lsp-mode
:config
(setq lsp-ui-doc-enable t)
(setq lsp-ui-doc-position 'at-point)
(setq lsp-ui-sideline-enable t)
(setq lsp-ui-sideline-show-code-actions t)
(setq lsp-ui-sideline-show-hover nil)
(setq lsp-ui-peek-enable t))
;; ---- dap-mode — Debugging ----
(use-package dap-mode
:hook
(lsp-mode . dap-mode)
(lsp-mode . dap-ui-mode))
;; ---- Scala Keybindings ----
;; Russ will have his own — these are for verification in the test VM
(with-eval-after-load 'scala-mode
(define-key scala-mode-map (kbd "C-c C-t") 'lsp-describe-thing-at-point)
(define-key scala-mode-map (kbd "C-c C-d") 'lsp-ui-doc-show)
(define-key scala-mode-map (kbd "C-c C-r") 'lsp-rename)
(define-key scala-mode-map (kbd "C-c C-a") 'lsp-execute-code-action)
(define-key scala-mode-map (kbd "C-c C-f") 'lsp-format-buffer)
(define-key scala-mode-map (kbd "C-c C-o") 'lsp-organize-imports)
(define-key scala-mode-map (kbd "C-c C-b") 'lsp-metals-build-import))
(provide 'init)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment