Skip to content

Instantly share code, notes, and snippets.

@nimeshneema
Last active February 28, 2026 09:42
Show Gist options
  • Select an option

  • Save nimeshneema/69ff55ecc50c7727e1b1a0cb0a88fd4b to your computer and use it in GitHub Desktop.

Select an option

Save nimeshneema/69ff55ecc50c7727e1b1a0cb0a88fd4b to your computer and use it in GitHub Desktop.
;;; init.el --- Scala IDE configuration for Emacs 30.2
;;; -*- lexical-binding: t -*-
;; ============================================================
;; SECTION 1: Package Manager Bootstrap
;; ============================================================
(require 'package)
;; Package archives: MELPA (latest) + GNU + NonGNU
(setq package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/packages/")
("melpa" . "https://melpa.org/packages/")))
(package-initialize)
;; Refresh package list on first run
(unless package-archive-contents
(package-refresh-contents))
;; Bootstrap use-package (built into Emacs 29+, but ensure it's loaded)
(require 'use-package)
(setq use-package-always-ensure t
use-package-verbose t) ; log what's being loaded (helpful for debugging)
;; ============================================================
;; SECTION 2: Core Editor Behaviour
;; ============================================================
;; UTF-8 everywhere
(set-language-environment "UTF-8")
(prefer-coding-system 'utf-8)
;; UI cleanup
(setq inhibit-startup-screen t
ring-bell-function 'ignore)
(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)
;; Line numbers in programming modes
(add-hook 'prog-mode-hook #'display-line-numbers-mode)
;; Show matching parens
(show-paren-mode 1)
;; Tabs → spaces, 2-wide (Scala convention)
(setq-default indent-tabs-mode nil
tab-width 2)
;; Remember recent files
(recentf-mode 1)
;; Better buffer names when files share a name
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)
;; Auto-refresh buffers when file changes on disk
(global-auto-revert-mode 1)
;; Save backup files to a dedicated dir (not cluttering your project)
(setq backup-directory-alist `(("." . ,(expand-file-name "backups" user-emacs-directory)))
auto-save-file-name-transforms `((".*" ,(expand-file-name "auto-saves/" user-emacs-directory) t)))
;; ============================================================
;; SECTION 3: which-key — shows available keybindings
;; ============================================================
(use-package which-key
:config
(which-key-mode)
(setq which-key-idle-delay 0.5))
;; ============================================================
;; SECTION 4: Tree-sitter (Emacs 29+ built-in, enhanced syntax)
;; ============================================================
;; tree-sitter gives much richer syntax highlighting than regex modes.
;; scala-ts-mode uses it. We install the grammar if not present.
(use-package treesit-auto
:config
(setq treesit-auto-install 'prompt) ; will ask before downloading grammars
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
;; ============================================================
;; SECTION 5: Scala Mode (syntax + indentation)
;; ============================================================
;; scala-mode is the traditional mode; scala-ts-mode is the tree-sitter version.
;; We install both. lsp-metals works with either.
(use-package scala-mode
:mode (("\\.scala\\'" . scala-mode)
("\\.sc\\'" . scala-mode)) ; .sc = Scala script / Ammonite
:interpreter ("scala" . scala-mode)
:config
(setq scala-indent:use-javadoc-style t))
;; ============================================================
;; SECTION 6: sbt-mode (build tool integration)
;; ============================================================
(use-package sbt-mode
:commands (sbt-start sbt-command sbt-run-previous-command)
:config
(setq sbt:program-options '("-Dsbt.supershell=false")))
;; ============================================================
;; SECTION 7: Company (completion UI)
;; ============================================================
(use-package company
:hook (prog-mode . company-mode)
:config
(setq company-minimum-prefix-length 1
company-idle-delay 0.2 ; slight delay avoids flickering
company-tooltip-align-annotations t
company-show-quick-access t))
;; ============================================================
;; SECTION 8: Flycheck (error/warning display)
;; ============================================================
(use-package flycheck
:hook (prog-mode . flycheck-mode))
;; ============================================================
;; SECTION 9: LSP Mode
;; ============================================================
(use-package lsp-mode
:hook
((scala-mode . lsp-deferred) ; lsp-deferred starts LSP lazily (better startup)
(lsp-mode . lsp-lens-mode)) ; show code lens (references count, run/test actions)
:init
;; lsp-mode prefix key — all LSP commands under C-c l
(setq lsp-keymap-prefix "C-c l")
:config
;; --- Performance tuning (important for Scala which has large responses) ---
(setq lsp-idle-delay 0.5 ; how long to wait before asking server
lsp-response-timeout 30 ; metals can be slow on cold start
read-process-output-max (* 4 1024 1024) ; 4MB - critical for metals
gc-cons-threshold 100000000) ; reduce GC pressure
;; --- UI preferences ---
(setq lsp-headerline-breadcrumb-enable t ; shows class/method path in header
lsp-headerline-breadcrumb-segments '(project file symbols)
lsp-enable-snippet t ; enables snippet completions
lsp-completion-enable t
lsp-signature-auto-activate t ; show signature help as you type args
lsp-signature-render-documentation t
;; --- Diagnostics ---
lsp-diagnostics-provider :flycheck ; use flycheck (not flymake)
;; --- File watching (disable for large projects if slow) ---
lsp-enable-file-watchers t
lsp-file-watch-threshold 5000)
;; Enable which-key integration for the C-c l prefix
(lsp-enable-which-key-integration t))
;; ============================================================
;; SECTION 10: LSP UI (hover docs, sideline diagnostics, peek)
;; ============================================================
(use-package lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:config
;; Sideline: shows errors/warnings inline at end of line
(setq lsp-ui-sideline-enable t
lsp-ui-sideline-show-diagnostics t
lsp-ui-sideline-show-hover nil ; can be noisy; toggle with C-c l T s
lsp-ui-sideline-show-code-actions t
lsp-ui-sideline-delay 0.2)
;; Doc popup on hover (eldoc-style but richer)
(setq lsp-ui-doc-enable t
lsp-ui-doc-position 'at-point ; alternatives: 'top 'bottom
lsp-ui-doc-delay 0.5
lsp-ui-doc-show-with-cursor nil ; show on cursor idle
lsp-ui-doc-show-with-mouse t ; show on mouse hover
lsp-ui-doc-include-signature t
lsp-ui-doc-max-width 80
lsp-ui-doc-max-height 20)
;; Peek: show definitions/references in an inline overlay (very useful)
(setq lsp-ui-peek-enable t
lsp-ui-peek-show-directory t)
;; Imenu integration (M-x imenu lists all symbols in file)
(setq lsp-ui-imenu-enable t
lsp-ui-imenu-auto-refresh t))
;; ============================================================
;; SECTION 11: lsp-metals (Scala-specific Metals server config)
;; ============================================================
(use-package lsp-metals
:after lsp-mode
:custom
(lsp-metals-server-args '("-J-Xss4m" "-J-Xms512m" "-J-Xmx2g" "-J-XX:+UseG1GC"
"-J-Dmetals.allow-multiline-string-formatting=off"))
(lsp-metals-enable-indent-on-paste t)
(lsp-metals-enable-semantic-highlighting t)
(lsp-metals-treeview-show-when-views-received t))
;; ============================================================
;; SECTION 12: DAP Mode (Debugging)
;; ============================================================
;; dap-mode provides the Debug Adapter Protocol client.
;; Metals also acts as a DAP server for Scala.
(use-package dap-mode
:hook
((lsp-mode . dap-mode)
(dap-mode . dap-ui-mode)
(dap-mode . dap-tooltip-mode)
(dap-mode . dap-ui-controls-mode))
:config
(setq dap-auto-configure-features '(sessions locals breakpoints expressions tooltip))
;; dap-scala is loaded conditionally — only if present
(with-eval-after-load 'scala-mode
(when (require 'dap-scala nil 'noerror)
(message "dap-scala loaded successfully")))
:bind
(:map dap-mode-map
("<f5>" . dap-debug)
("<f6>" . dap-next)
("<f7>" . dap-step-in)
("<f8>" . dap-step-out)
("C-<f5>" . dap-continue)
("C-<f9>" . dap-breakpoint-toggle)))
;; ============================================================
;; SECTION 13: Treemacs (Project file tree, used by lsp-metals tree view)
;; ============================================================
(use-package treemacs
:bind
(("C-x t t" . treemacs)
("C-x t 1" . treemacs-select-window))
:config
(setq treemacs-width 30
treemacs-show-hidden-files t))
;; lsp-treemacs: integration between lsp-mode and treemacs
;; (used by lsp-metals for the build targets tree)
(use-package lsp-treemacs
:after (lsp-mode treemacs)
:config
(lsp-treemacs-sync-mode 1))
;; ============================================================
;; SECTION 14: Projectile (project management)
;; ============================================================
(use-package projectile
:bind-keymap
("C-c p" . projectile-command-map)
:config
(projectile-mode 1)
(setq projectile-completion-system 'default))
;; ============================================================
;; SECTION 15: Magit (Git integration — too useful to omit)
;; ============================================================
(use-package magit
:bind ("C-c g" . magit-status))
;; ============================================================
;; SECTION 16: Consult + Vertico (modern minibuffer completion)
;; Optional but transforms M-x, C-x b, C-x f experience
;; ============================================================
(use-package vertico
:init (vertico-mode))
(use-package orderless
:config
(setq completion-styles '(orderless basic)
completion-category-overrides '((file (styles basic partial-completion)))))
(use-package consult
:bind
(("C-x b" . consult-buffer)
("C-x r b" . consult-bookmark)
("M-y" . consult-yank-pop)
("M-g g" . consult-goto-line)
("M-s r" . consult-ripgrep) ; needs ripgrep installed: sudo apt install ripgrep
("M-s f" . consult-find)))
(use-package marginalia
:init (marginalia-mode))
;; ============================================================
;; END OF CONFIGURATION
;;; init.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment