Last active
February 28, 2026 09:42
-
-
Save nimeshneema/69ff55ecc50c7727e1b1a0cb0a88fd4b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;; 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