Skip to content

tampix/.emacs.d

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Emacs configuration file

About

Foreword

2018-10-12, I declare .emacs.d bankruptcy.

My current configuration used to rely on Cask and Pallet but it didn’t work anymore after upgrading to Emacs 26. I lived with a broken config for some months but it started becoming a real problem once I had to go through some config overhaul to accomodate sudden needs.

Another point of pain was how I handled my bindings, especially for Evil where I had some custom text-object and thus corresponding motions. It’s been almost a year that I want to try out general alongside which-key to have a nice experience ala Magit, Spacemacs, Doom… etc.

So, why not use Spacemacs or Doom directly? Well first, this is the occasion for me to learn more of org-mode (which I only scratched the surface of) and improves my emacs-lisp.

After seeing so many people using org-mode to write their configuration with great success, why not do it myself?

Anyway, I hope this attempt at a clean config won’t end in bankruptcy this time…

Aim

  • Keep it fast (at first, aim for less than 0.5s at startup)
  • Don’t let it rot
  • Have a little bit of documentation so that I understand some of my choices afterwards

License

This configuration is licensed under the MIT license. See provided LICENSE.

Early init

Take advantage on Emacs 27+ early-init file.

Configure GC so it doesn’t run during the init. This will be handled later in the init by GCMH.

(setq gc-cons-threshold most-positive-fixnum)

Disable menus and stuff. Calls to tool-bar-mode and scroll-bar-mode takes roughtly 100ms each, so disable those in early-init.el.

(push '(tool-bar-lines . 0) default-frame-alist)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)

Backport stuff from emacs 28.1 if needed.

;; backport features of emacs 28.1
(when (and (<= emacs-major-version 28)
           (< emacs-minor-version 1))
  (defmacro with-environment-variables (variables &rest body)
    (declare (indent 1))
    `(let (process-environment (copy-sequence process-environment))
       ,@(mapcar (lambda (e)
                   `(setenv ,(car e) ,(cadr e)))
                 variables)
       ,@body))

  (defun string-replace (from-string to-string in-string)
    (replace-regexp-in-string
     (regexp-quote from-string) to-string in-string t t))

  (defun string-search (needle haystack &optional start-pos)
    (string-match-p (regexp-quote needle) haystack start-pos))

  (defun length= (sequence len)
    (and (>= len 0)
         (= (length sequence) len)))

  (defun length> (sequence len)
    (> (length sequence) len))

  (defun length< (sequence len)
    (< (length sequence) len)))

Bootstrapping

First, let’s ensure generated init.el has proper scoping and encoding.

;;; -*- lexical-binding: t -*-
;;; -*- coding: utf-8 -*-

Original init.el defines the way to reload the configuration.

(require 'subr-x)

(defun in-emacs-dir (file)
  "Return the absolute path to FILE in `user-emacs-directory'."
  (file-truename (expand-file-name file user-emacs-directory)))

(defvar tangle-init-org-file--first-time
  (not (file-exists-p (in-emacs-dir "init.elc")))
  "t if no init.elc exists.")

(defun tangle-init-org-file (&optional no-compile)
  "Tangle, `byte-compile' and load the init file from README.org.

With a prefix-argument, or a not-nil NO-COMPILE argument if
called non-interactively, don't compile the tangled file.

Return the absolute path to the tangle file if either NO-COMPILE
is nil or `debug-on-error' is not-nil, else return nil."
  (interactive "P")
  (unless (boundp 'org-babel-tangle-file)
    (require 'ob-tangle))
  ;; For some reason, I can't make `org-babel-load-file' create the
  ;; .elc file during the first init, so for now, stick to manual
  ;; tangle -> compile -> load.
  (let ((tangled (thread-last
                   ;; car isn't always default tangled file when there
                   ;; are multiple tangled files
                   (org-babel-tangle-file (in-emacs-dir "README.org")
                                          nil
                                          "emacs-lisp")
                   (member (in-emacs-dir "README.el"))
                   car)))
    ;; When first loading the config, load the tangled file anyway to
    ;; ensure that packages are setup.
    (when tangle-init-org-file--first-time
      (load-file tangled))
    (if no-compile
        tangled
      (byte-compile-file tangled)
      (rename-file (byte-compile-dest-file tangled)
                   (in-emacs-dir "init.elc")
                   :ok-if-already-exists)
      (setq tangle-init-org-file--first-time nil)
      ;; Keep the init file for debug purposes.
      (if debug-on-error
          tangled
        (delete-file tangled)
        nil))))

(defun tangle-init-org-file-after-save ()
  (add-hook 'after-save-hook #'tangle-init-org-file nil t))
;; It's a bit ugly but it does the job
(setq safe-local-variable-values '((eval tangle-init-org-file-after-save)))

It should only be run once, at the first startup, as the real config will get generated, byte-compiled and loaded.

To ensure modifications in this file update the configuration, tangle-init-org-file is added to the after-save-hook as a local variable of this file so that changes apply immediatly.

<<init>>

(when (and (not after-init-time) ; avoid recursive tangle
           tangle-init-org-file--first-time)
  (tangle-init-org-file))

General configuration

cl-lib

Import cl-lib at compile time.

(eval-when-compile
  (require 'cl-lib))

Garbage collector

Add a macro to inhibit GC.

(defmacro inhibit-gc (&rest body)
  "Inhibit gc around BODY by setting `gc-cons-threshold' to
`most-positive-fixnum'.

\(fn BODY...)"
  (declare (indent 0)
           (debug t))
  `(let ((gc-cons-threshold most-positive-fixnum))
     ,@body))

Setup defaults

Setup some default values.

(setq echo-keystrokes 0.1
      bidi-display-reordering nil
      require-final-newline t
      ring-bell-function #'ignore
      require-final-newline t
      truncate-lines t
      scroll-step 1
      scroll-conservatively 10000
      auto-window-vscroll nil
      inhibit-default-init t
      inhibit-startup-screen t
      fill-column 80
      confirm-nonexistent-file-or-buffer nil)

Make custom file temporary.

(setq custom-file (make-temp-file "custom" nil ".el"))

Put all auto saves in the same location.

(setq backup-directory-alist `((".*" . ,temporary-file-directory))
      auto-save-file-name-transforms `((".*" ,temporary-file-directory t)))

Change yes/no to y/n.

(fset #'yes-or-no-p #'y-or-n-p)

Disable VC as i use Git through Magit exclusively.

(setq vc-handled-backends nil)

Stuff I should move to different files

(defun disable-tabs ()
  "Disable tabs for indentation."
  (setq indent-tabs-mode nil))

Setup use-package

Automatically install use-package if it’s not installed.

(require 'package)

(add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/") t)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(require 'use-package)

(use-package use-package
  :ensure nil ; useless, just here to be consistent
  :custom (use-package-always-ensure t))

GCMH

(use-package gcmh
  :hook
  (after-init . gcmh-mode))

esup

Esup is a great package for profiling the init. Setup Esup to profile the byte-compiled version of the init.

(use-package esup
  :init
  (defun esup-tangled ()
    "Profile ~/.emacs.d/init.elc.
See `esup'"
    (interactive)
    (esup (tangle-init-org-file :no-compile))))

Theme and modeline

Some themes have trouble when Emacs was run as a daemon. Create a one-time hook called after-first-make-frame-hook that is ran only once during the after-make-frame-functions hook.

(defvar after-first-make-frame-hook nil
  "Functions to run after the first frame is created.
If Emacs was started as a daemon, uses `after-make-frame-functions',
else uses `after-init-hook'.")

(defun run-after-first-make-frame-hooks ()
  "Run hooks in `after-first-make-frame-hook'."
  (if (daemonp)
      (cl-labels ((my--run-once (&optional frame)
                    (with-selected-frame (or frame (selected-frame))
                      (run-hooks 'after-first-make-frame-hook))
                    (remove-hook 'after-make-frame-functions #'my--run-once)))
        (add-hook 'after-make-frame-functions #'my--run-once))
    ;; not a daemon, run hooks in the `after-init-hook'
    (run-hooks 'after-first-make-frame-hook)))

(add-hook 'after-init-hook #'run-after-first-make-frame-hooks)

Inspired by Doom Emacs, introduce a variable my–theme that is used to determine the default theme at startup.

(defvar my--theme nil
  "Theme selected in the configuration.")

(defun my--load-theme (&optional frame)
  "Load theme configured in `my--theme'.in FRAME."
  (if my--theme
      ;; don't load `my--theme' if it's already loaded
      (when (not (memq my--theme custom-enabled-themes))
        (with-selected-frame (or frame (selected-frame))
          (load-theme my--theme :no-confirm)))
    (error "`my-theme' shouldn't be nil")))

(add-hook 'after-first-make-frame-hook #'my--load-theme)

(defun my--reload-theme ()
  "Reload `my--theme'."
  (interactive)
  (my--load-theme))

Also inspired by Doom Emacs, add a hook on load-theme and ensure themes are loaded without any cluttering from previous themes.

(defvar my--load-theme-hook nil
  "Hooks to run after `load-theme'.")

(defun load-theme--after (theme &optional _ no-enable)
  "When `load-theme' is called, disable previous themes and run
`my-load-theme-hook'."
  (unless no-enable
    (setq my--theme theme)
    (mapc #'disable-theme (remq theme custom-enabled-themes))
    (run-hooks 'my--load-theme-hook)))

(advice-add 'load-theme :after #'load-theme--after)

Setup theme.

(use-package doom-themes
  :init
  (setq my--theme 'doom-challenger-deep))

Setup modeline.

(use-package doom-modeline
  :config
  (defun enable-doom-modeline-icons ()
    (setq doom-modeline-icon t))
  (defun set-doom-modeline-height ()
    (setq doom-modeline-height (* 2 (doom-modeline--font-height))))
  :hook ((after-first-make-frame . doom-modeline-mode)
         (after-first-make-frame . enable-doom-modeline-icons)
         (after-first-make-frame . set-doom-modeline-height)
         (after-first-make-frame . column-number-mode)))

Setup solaire-mode.

(use-package solaire-mode
  :when (or (daemonp) (display-graphic-p))
  :hook (after-first-make-frame . solaire-global-mode))

Setup Evil

I’ve been a Vim enthusiast for about 10 years before I switched to Emacs back in 2013. I discovered Evil in 2012 and tried it out, but I wasn’t ready to make the switch back then, even if I found the experience pretty impressive (especially since, at the time, Evil was very young).

I was using ctrlp.vim and fugitive.vim then, and was happy about it, but i knew that Magit was a level above Fugitive (I tried it out too). What really got me interested in Emacs was that I started using more and more of Shougo’s Vim plugins, and one of them was unite.vim, which seemed brilliant to me. The deeper I got into using Unite and the more I got interested into Emacs as it was an anything.el clone (which became known as helm along the way).

Anyway, import Evil and setup a very basic configuration for now.

(use-package evil
  :commands evil-mode
  :init
  (setq evil-want-C-u-scroll t
        evil-want-C-i-jump t
        evil-want-C-w-in-emacs-state t
        evil-search-module 'evil-search
        evil-undo-system 'undo-fu
        evil-default-cursor t)
  :config
  (evil-define-text-object defun-text-object (count &optional beg end type)
    (save-excursion
      (mark-defun)
      (evil-range (region-beginning)
                  (region-end)
                  type
                  :expanded t)))
  :hook (after-init . evil-mode))

Undo configuration

Try out Vundo

(use-package undo-fu
  :after evil
  :config
  ;; values taken from Doom
  (setq undo-limit 400000
        undo-strong-limit 3000000
        undo-outer-limit 3000000))

(use-package undo-fu-session
  :after undo-fu
  :hook (prog-mode . undo-fu-session-mode))

which-key

(use-package which-key
  :init
  (which-key-mode)
  :config
  (setq which-key-sort-order 'which-key-key-order-alpha
        which-key-idle-delay 0.1))

general

Setup general with Vim like functions and some equivalents with a default global prefix.

As SPC is already bound to evil-forward-char in the motion state, unbind it beforehand so it can be used as a global prefix.

(use-package general
  :config
  (general-evil-setup t)

  (defconst my--prefix "SPC")
  (general-def
    :prefix my--prefix
    :states '(motion normal visual)
    ""
    '(nil :which-key "Main prefix"))
  (general-create-definer prefix-map
      :prefix my--prefix
      :prefix-command 'my--prefix-command
      :prefix-map 'my--prefix-map)
  (general-create-definer prefix-mmap
      :prefix my--prefix
      :prefix-command 'my--prefix-command
      :prefix-map 'my--prefix-map
      :states 'motion)
  (general-create-definer prefix-nmap
      :prefix my--prefix
      :prefix-command 'my--prefix-command
      :prefix-map 'my--prefix-map
      :states 'normal)
  (general-create-definer prefix-vmap
      :prefix my--prefix
      :prefix-command 'my--prefix-command
      :prefix-map 'my--prefix-map
      :states 'visual)
  (general-create-definer prefix-nvmap
      :prefix my--prefix
      :prefix-command 'my--prefix-command
      :prefix-map 'my--prefix-map
      :states '(normal visual))

  (tomap "m" #'defun-text-object))

Winner

Use winner, mostly for winner-undo.

(use-package winner
  :ensure nil
  :init
  (winner-mode 1)
  :config
  (general-define-key
   :states '(normal emacs)
   :prefix "C-w"
   "u" 'winner-undo))

hide-mode-line

A package from Doom, which helps hiding modeline when it isn’t pertinent.

(use-package hide-mode-line
  :commands hide-mode-line-mode)

savehist

Enabled savehist-mode to keep minibuffer history.

(use-package savehist
  :ensure nil
  :init
  (setq history-length 100)
  :hook (after-init . savehist-mode))

Magit

Magit was what, along with Evil, sold me Emacs at first. I tried it out back in 2012 and even then, I was amazed by it’s ease of use and power (mind that I was using Fugitive at the time, which was powerful in it’s own right).

It’s become even more awesome as time went by, and really thank it’s contributors, and especially tarsius, who deserves all the praise he got, without any shadow of a doubt, for what is the best Git porcelain out there.

Surprisingly, I don’t have much configuration going on for it… Guess that means the defaults are sane and well thought of.

(use-package magit
  :commands magit-status
  :general
  (:keymaps 'magit-status-mode-map my--prefix nil)
  (prefix-map :keymaps 'magit-status-mode-map "SPC" 'magit-diff-show-or-scroll-up)
  :config
  ;; Ensure `magit-status' is fullframe. Previous window configuration
  ;; is restored by default.
  (setq magit-display-buffer-function
        #'magit-display-buffer-fullframe-status-v1)
  (add-hook 'magit-mode-hook #'hide-mode-line-mode)
  (add-hook 'magit-popup-mode-hook #'hide-mode-line-mode)
  (add-hook 'with-editor-mode-hook #'evil-insert-state))

Forge

Forge is a new package so config is going to be minimal. Mostly used for github-review.

(use-package forge
  :after (magit)
  :config
  (setq forge-toggle-closed-visibility t)
  (setcdr forge-topic-list-limit -5))

code-review

Do GitHub Pull Request reviews from Emacs.

(use-package code-review
  :after forge)

git-timemachine

(use-package git-timemachine
  :commands (git-timemachine
             git-timemachine-toggle))

fix binding conflicts with evil

Vertico

(use-package vertico
  :custom
  (vertico-cycle t "Enable cycling for `vertico-next' and `vertico-previous'")
  (vertico-resize t "Grow and shrink the Vertico minibuffer")
  (vertico-count 20 "More candidates")
  (vertico-scroll-margin 0)
  :hook (after-init . vertico-mode))

;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
  :ensure nil
  :after (vertico)
  :init
  (savehist-mode))

(use-package emacs
  :ensure nil
  :init
  ;; Add prompt indicator to `completing-read-multiple'.
  ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
  (defun crm-indicator (args)
    (cons (format "[CRM%s] %s"
                  (replace-regexp-in-string
                   "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
                   crm-separator)
                  (car args))
          (cdr args)))
  (advice-add #'completing-read-multiple :filter-args #'crm-indicator)

  ;; Do not allow the cursor in the minibuffer prompt
  (setq minibuffer-prompt-properties
        '(read-only t cursor-intangible t face minibuffer-prompt))
  (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

  ;; Emacs 28: Hide commands in M-x which do not work in the current mode.
  ;; Vertico commands are hidden in normal buffers.
  (setq read-extended-command-predicate
        #'command-completion-default-include-p)

  ;; Enable recursive minibuffers
  (setq enable-recursive-minibuffers t))

(use-package orderless
  :after (vertico)
  :custom
  (completion-styles '(orderless basic))
  (completion-category-defaults nil)
  (completion-category-overrides '((file (styles partial-completion))))
  ;; Configure a custom style dispatcher (see the Consult wiki)
  ;; (orderless-style-dispatchers '(+orderless-dispatch))
  ;; (orderless-component-separator #'orderless-escapable-split-on-space)
  )

(use-package consult
  :after (vertico))

(use-package marginalia
  ;; TODO bind marginalia-cycle
  :after (vertico)
  :init
  (marginalia-mode))

Projectile

(use-package projectile
  :diminish (projectile-mode)
  :commands (projectile-mode
             projectile-find-file
             projectile-switch-project
             projectile-switch-to-buffer)
  :general
  (prefix-nmap
      "p" '(:keymap projectile-command-map :which-key "Projectile"))
  :config
  (projectile-mode t)
  (recentf-mode t)
  :custom
  (projectile-enable-caching t)
  (projectile-sort-order 'recentf)
  (projectile-completion-system 'default)
  (projectile-switch-project-action 'projectile-vc))

ag

(use-package ag)

flycheck

(use-package flycheck
  :hook (prog-mode . flycheck-mode))

yasnippet

(use-package yasnippet
  :pin melpa
  :hook (prog-mode . yas-minor-mode))
(use-package yasnippet-snippets
  :hook (yasnipppet . yasnippet-snippets-initialize))

all-the-icons

(use-package all-the-icons
  :config
  (defun my--all-the-icons-setup ()
    (if (display-graphic-p)
        (when (not (member "all-the-icons" (font-family-list)))
          (all-the-icons-install-fonts t))))
  :hook (before-make-frame . my--all-the-icons-setup))

(use-package all-the-icons-dired
  :hook (dired-mode . all-the-icons-dired-mode))

company

(use-package company
  :general
  (imap "C-SPC" 'company-complete)
  (general-def :keymaps 'company-active-map
    "C-n" 'company-select-next
    "C-p" 'company-select-previous)
  :config
  (setq company-tooltip-align-annotations t
        company-show-quick-access t)
  :hook (after-init . global-company-mode))
(use-package company-quickhelp
  :hook (company-mode . company-quickhelp-local-mode))
(use-package company-box
  :after (all-the-icons company)
  :config
  (setq company-box-icons-alist 'company-box-icons-all-the-icons)
  :hook (company-mode . company-box-mode))

tree-sitter

(use-package tree-sitter
  :hook (after-init . global-tree-sitter-mode))

(use-package tree-sitter-langs
  :after tree-sitter)

(use-package evil-textobj-tree-sitter
  :after (evil tree-sitter)
  :general
  (:keymaps 'evil-outer-text-objects-map
            "f" (evil-textobj-tree-sitter-get-textobj "function.outer")
            "a" (evil-textobj-tree-sitter-get-textobj ("conditional.outer" "loop.outer")))
  (:keymaps 'evil-inner-text-objects-map
            "f" (evil-textobj-tree-sitter-get-textobj "function.inner")
            "a" (evil-textobj-tree-sitter-get-textobj ("conditional.inner" "loop.inner"))))

lsp

Setup lsp-mode. Don’t setup lsp-ui for now as it’s very cumbersome (disable sideline, doc, company-quickhelp override…)

(use-package lsp-mode
  :commands lsp
  :general
  (prefix-nmap
      "l" '(:prefix-command my--lsp-command :prefix-map my--lsp-map :which-key "LSP"))
  (general-def :keymaps 'my--lsp-map
    "" '(nil :which-key "LSP")
    "f" '(:prefix-command my--lsp-find-command :prefix-map my--lsp-find-map :which-key "Find")
    "e" '(lsp-execute-code-action :which-key "Execute code action")
    "=" '(lsp-format-dwim :which-key "Format dwim")
    "h" '(lsp-document-highlight :which-key "Highlight symbol")
    "r" '(lsp-rename :which-key "Rename symbol under point")
    "?" '(lsp-describe-thing-at-point :which-key "Describe thing at point"))
  (general-def :keymaps 'my--lsp-find-map
    "" '(nil :which-key "LSP Find")
    "d" '(lsp-find-definition :which-key "Definition")
    "D" '(lsp-find-declaration :which-key "Declaration")
    "i" '(lsp-find-implementation :which-key "Implementation")
    "t" '(lsp-find-type-definition :which-key "Type definition")
    "r" '(lsp-find-references :which-key "References"))
  :init
  (defun lsp-format-dwim ()
    "Format using `lsp-format-region' is `region-active-p', or
else use `lsp-format-buffer'."
    (interactive)
    (if (region-active-p)
        (lsp-format-region (region-beginning) (region-end))
      (lsp-format-buffer)))
  :config
  (setq lsp-prefer-flymake nil
        lsp-enable-xref t
        lsp-enable-snippets t
        lsp-eldoc-render-all t
        lsp-enable-on-type-formatting t))

Restclient

(use-package restclient)

Rainbow delimiters

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

rainbow-mode

(use-package rainbow-mode
  :hook ((config-mode . rainbow-mode)
         (css-mode . rainbow-mode)
         (emacs-lisp-mode . rainbow-mode)
         (org-mode . rainbow-mode)))

highlight-defined

(use-package highlight-defined)

align

(use-package align
  :ensure nil
  :custom (align-to-tab-stop nil))

Per language configuration

Here goes every language specific configuration.

Org

(use-package org
  ;; TODO Fix config for org-version greater than 9.6
  :ensure nil
  ;; :preface
  ;; ;; See `package-installed-p' implementation
  ;; (assq-delete-all 'org package--builtins)
  ;; (assq-delete-all 'org package--builtin-versions)
  :hook ((org-mode . disable-tabs)
         (org-mode . yas-minor-mode)))

(use-package htmlize
  :after org
  :config
  (setq htmlize-output-type 'inline-css))

(use-package org-re-reveal
  :after org
  :config
  (setq org-re-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js"
        org-re-reveal-revealjs-version "4"
        org-re-reveal-theme "solarized"))

Emacs Lisp configuration

Because the indentation of cl-flet and such is still broken as of [2018-10-14 Sun], fix their indentation.

(use-package lisp-mode
  :ensure nil
  :commands emacs-lisp-mode
  :config
  (setq lisp-indent-function 'common-lisp-indent-function)
  :hook ((lisp-mode . disable-tabs)
         (emacs-lisp-mode . disable-tabs)
         (eamcs-lisp-mode . highlight-defined)))

(use-package cl-indent
  :ensure nil
  :commands common-lisp-indent-function
  :config
  (defun fix-elisp-indent (func indent)
    "Fix the indendation of elisp forms that
`common-lisp-indent-function' might have broken."
    (unless (and (symbolp func)
                 (fboundp func))
      (error "%s: is not a function" func))
    (put func 'common-lisp-indent-function-for-elisp indent))

  (fix-elisp-indent 'defalias 1)
  (fix-elisp-indent 'define-clojure-indent 0)
  (fix-elisp-indent 'use-package 1))

Java

(use-package lsp-java
  :after lsp-mode
  :config
  (setq lsp-java-java-path "/usr/lib/jvm/java-11-openjdk/bin/java"
        lsp-java-vmargs '("-server"
                          "-noverify"
                          "-Xms2G"
                          "-Xmx2G"
                          "-XX:+UseG1GC"
                          "-XX:+UseStringDeduplication"
                          "-XX:MaxGCPauseMillis=150"
                          "-XX:+AlwaysPreTouch"
                          "-XX:TargetSurvivorRatio=80")
        lsp-java-format-on-type-enabled t
        lsp-java-code-generation-hash-code-equals-use-java7objects t
        lsp-java-code-generation-use-blocks t)
  :hook (java-mode . lsp))

Clojure

(use-package clojure-mode
  :config
  (define-clojure-indent
    (defroutes 'defun)
    (GET 2)
    (POST 2)
    (PUT 2)
    (DELETE 2)
    (HEAD 2)
    (ANY 2)
    (OPTIONS 2)
    (PATCH 2)
    (rfn 2)
    (let-routes 1)
    (context 2)))

(use-package cider
  :after clojure
  :hook (cider-mode . cider-enlighten-mode))

(use-package clj-refactor
  :after cider
  :general
  (prefix-nmap
      "c" '(hydra-cljr-help-menu/body :which-key "Clojure Refactor"))
  :hook (clojure-mode . clj-refactor-mode))

Terraform

(use-package terraform-mode)

(use-package company-terraform)

(use-package terraform-doc)

YAML

(use-package yaml-mode)

nXML

(use-package nxml-mode
  :ensure nil
  :config
  (defun my--nxml-indent-tabs-mode ()
    (setq indent-tabs-mode t
          nxml-child-indent tab-width
          nxml-attribute-indent tab-width
          nxml-slash-auto-complete-flag t))
  :hook (nxml-mode . my--nxml-indent-tabs-mode))

Haskell

(use-package haskell-mode)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published