The least sane Emacs distribution
Lainmacs is a very simple and basic configuration file for Emacs. From here you can edit, remove, or add many aspects of Emacs you want. I encourage you to do so, because Emacs works best when it’s customized to your own liking!
What’s the difference between a villain and a super villain? Presentation!
Currently, the appeal of Lainmacs is seeing a schizo Lain picture everytime you start up Emacs. Also, it is a very basic config which means you can easily add, edit or remove things as you like. You can use this as a building block when making your OWN Emacs config!
Ogres are like onions
They smell?
Yes - No! layers! onions have layers! ogres have layers!
As opposed to many other Emacs distributions, Lainmacs has ZERO customization layers which means you can just jump in, look at the config file and start editing away! After all, Emacs works best when it’s customized to your own liking!
git clone https://github.com/shampee/Lainmacs ~/.emacs.d
After running this command, the first time you run Emacs will download all of the specified packages in the config.org file, so please be patient!
Also, to get autocompletion on C, C++ and Java files, you’ll need to install the corresponding company backend servers first (you’ll be automatically prompted to do so the first time you open a relevant file)
clang
as backend for C and C++ autocompletion
llvm
to install irony server
(optional) mvn
maven for java project handling through meghanada
- Add and configure some extra packages
- Configure Lisp
- Configure Scheme
Make dashboard cooler- Make dashboard EVEN cooler!
- Maybe add rotating dashboard pictures
Make custom Lainmacs theme- (Maybe) Make a random Lain pop up on the dashboard every time you launch.
Clean up/organize init.el- Clean up/organize config.org
- Optimize startup time
Minor quality-of-life modifications for a more pleasant Emacs experience
Emacs breaks certain modes when it has line-numbers-mode enabled, (like docview or ansi-term) so I utilize the approach of only enabling it on some major modes rather than globally
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'text-mode-hook 'display-line-numbers-mode)
(show-paren-mode 1)
(setq inhibit-startup-message t)
(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)
(setq x-select-enable-clipboard t)
(setq make-backup-files nil)
(setq auto-save-default nil)
(setq scroll-conservatively 100)
(setq ring-bell-function 'ignore)
(setq-default tab-width 4)
(setq-default standard-indent 4)
(setq c-basic-offset tab-width)
(setq-default electric-indent-inhibit t)
(setq-default indent-tabs-mode t)
(setq backward-delete-char-untabify-method 'nil)
(global-prettify-symbols-mode t)
(setq electric-pair-pairs '(
(?\{ . ?\})
(?\( . ?\))
(?\[ . ?\])
(?\" . ?\")))
;(electric-pair-mode t)
(defun split-and-follow-horizontally ()
(interactive)
(split-window-below)
(balance-windows)
(other-window 1))
(global-set-key (kbd "C-x 2") 'split-and-follow-horizontally)
(defun split-and-follow-vertically ()
(interactive)
(split-window-right)
(balance-windows)
(other-window 1))
(global-set-key (kbd "C-x 3") 'split-and-follow-vertically)
(defalias 'yes-or-no-p 'y-or-n-p)
Super - Control - <arrow>
(global-set-key (kbd "s-C-<left>") 'shrink-window-horizontally)
(global-set-key (kbd "s-C-<right>") 'enlarge-window-horizontally)
(global-set-key (kbd "s-C-<down>") 'shrink-window)
(global-set-key (kbd "s-C-<up>") 'enlarge-window)
(global-hl-line-mode t)
(setq use-package-always-defer t)
(setq package-check-signature nil)
(setq browse-url-browser-function #'eww-browse-url)
One of the main selling points of Emacs! no Emacs distribution is complete without sensible and well-defined org-mode defaults
(use-package org
:config
(add-hook 'org-mode-hook 'org-indent-mode)
(add-hook 'org-mode-hook
#'(lambda ()
(visual-line-mode 1))))
(use-package org-indent
:diminish org-indent-mode)
(use-package htmlize
:ensure t)
(use-package org-ref
:ensure t)
(use-package org-roam
:ensure t
:custom
(org-roam-directory (file-truename "~/src/org/"))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
;; Dailies
("C-c n j" . org-roam-dailies-capture-today))
:config
;; If you're using a vertical completion framework, you might want a more informative completion interface
(setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
(org-roam-db-autosync-mode)
;; If using org-roam-protocol
(require 'org-roam-protocol))
(use-package org-roam-bibtex
:after org-roam
:load-path "~/opt/org-roam-bibtex/" ; Modify with your own path where you cloned the repositorya<
:config
(require 'org-ref)) ; optional: if using Org-ref v2 or v3 citation links
(use-package org-noter
:ensure t)
(use-package org-remark
:ensure t
:config
(define-key global-map (kbd "C-c n m") #'org-remark-mark)
(with-eval-after-load 'org-remark
(define-key org-remark-mode-map (kbd "C-c n o") #'org-remark-open)
(define-key org-remark-mode-map (kbd "C-c n ]") #'org-remark-view-next)
(define-key org-remark-mode-map (kbd "C-c n [") #'org-remark-view-prev)
(define-key org-remark-mode-map (kbd "C-c n r") #'org-remark-remove))
:config (org-remark-global-tracking-mode +1))
We are using Emacs, so we might as well implement as many tools from our workflow into it as possible
Eshell cannot handle ncurses programs and in certain interpreters (Python, GHCi) selecting previous commands does not work (for now). I recommend using eshell for light cli work, and using your external terminal emulator of choice for heavier tasks
(setq eshell-prompt-regexp "^[^αλ\n]*[αλ] ")
(setq eshell-prompt-function
(lambda nil
(concat
(if (string= (eshell/pwd) (getenv "HOME"))
(propertize "~" 'face `(:foreground "#99CCFF"))
(replace-regexp-in-string
(getenv "HOME")
(propertize "~" 'face `(:foreground "#99CCFF"))
(propertize (eshell/pwd) 'face `(:foreground "#99CCFF"))))
(if (= (user-uid) 0)
(propertize " α " 'face `(:foreground "#FF6666"))
(propertize " λ " 'face `(:foreground "#A6E22E"))))))
(setq eshell-highlight-prompt nil)
(defun eshell/sudo-open (filename)
"Open a file as root in Eshell."
(let ((qual-filename (if (string-match "^/" filename)
filename
(concat (expand-file-name (eshell/pwd)) "/" filename))))
(switch-to-buffer
(find-file-noselect
(concat "/sudo::" qual-filename)))))
(defun eshell-other-window ()
"Create or visit an eshell buffer."
(interactive)
(if (not (get-buffer "*eshell*"))
(progn
(split-window-sensibly (selected-window))
(other-window 1)
(eshell))
(switch-to-buffer-other-window "*eshell*")))
(global-set-key (kbd "<s-C-return>") 'eshell-other-window)
(unless (package-installed-p 'quelpa)
(with-temp-buffer
(url-insert-file-contents "https://raw.githubusercontent.com/quelpa/quelpa/master/quelpa.el")
(eval-buffer)
(quelpa-self-upgrade)))
(quelpa
'(quelpa-use-package
:fetcher git
:url "https://github.com/quelpa/quelpa-use-package.git"))
(require 'quelpa-use-package)
Auto-package-update automatically updates and removes old packages
(use-package auto-package-update
:defer nil
:ensure t
:config
(setq auto-package-update-delete-old-versions t)
(setq auto-package-update-hide-results t)
(auto-package-update-maybe))
Diminish hides minor modes to prevent cluttering your mode line
(use-package diminish
:ensure t)
22/04/2019: This macro was provided by user ld43 after I couldn’t figure out how to make diminish work by being at the top of the config file.
;(defmacro diminish-built-in (&rest modes)
; "Accepts a list MODES of built-in emacs modes and generates `with-eval-after-load` diminish forms based on the file implementing the mode functionality for each mode."
; (declare (indent defun))
; (let* ((get-file-names (lambda (pkg) (file-name-base (symbol-file pkg))))
; (diminish-files (mapcar get-file-names modes))
; (zip-diminish (-zip modes diminish-files)))
; `(progn
; ,@(cl-loop for (mode . file) in zip-diminish
; collect `(with-eval-after-load ,file
; (diminish (quote ,mode)))))))
; This bit goes in init.el
;(diminish-built-in
; beacon-mode
; which-key-mode
; page-break-lines-mode
; undo-tree-mode
; eldoc-mode
; abbrev-mode
; irony-mode
; company-mode
; meghanada-mode)
27/05/2019: Since the diminish functionality was always built-in in use-package, there was never a point in using a diminish config. lol silly me
I tried spaceline and didn’t like it. What I did like was its theme
(use-package spaceline
:ensure t)
I prefer powerline over spaceline, but the default powerline themes don’t work for me for whatever reason, so I use the spaceline theme
(use-package powerline
:ensure t
:init
(spaceline-spacemacs-theme)
:hook
('after-init-hook) . 'powerline-reset)
(spaceline-toggle-treesit-inspect-off) ;; broken for some reason and needs to be off
The frontend of Lainmacs; without this there’d be no Lain in your Emacs startup screen
(use-package dashboard
:ensure t
:defer nil
:preface
(defun update-config ()
"Update Lainmacs to the latest version."
(interactive)
(let ((dir (expand-file-name user-emacs-directory)))
(if (file-exists-p dir)
(progn
(message "Lainmacs is updating!")
(cd dir)
(shell-command "git pull")
(message "Update finished. Switch to the messages buffer to see changes and then restart Emacs"))
(message "\"%s\" doesn't exist." dir))))
(defun create-scratch-buffer ()
"Create a scratch buffer"
(interactive)
(switch-to-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode))
:config
(dashboard-setup-startup-hook)
(setq dashboard-items '((recents . 5)))
(setq dashboard-banner-logo-title "L A I N M A C S - The schizoid Emacs distribution!")
(setq dashboard-startup-banner "~/.emacs.d/lainvector.png")
(setq dashboard-center-content t)
(setq dashboard-show-shortcuts nil)
(setq dashboard-set-init-info t)
(setq dashboard-init-info (format "%d packages loaded in %s"
(length package-activated-list) (emacs-init-time)))
(setq dashboard-set-footer nil)
(setq dashboard-set-navigator t)
(setq dashboard-navigator-buttons
`(;; line1
((,nil
"Lainmacs on github"
"Open Lainmacs github page on your browser"
(lambda (&rest _) (browse-url "https://github.com/shampee/Lainmacs"))
'default)
(nil
"Lainmacs crash course"
"Open Lainmacs (Witchmacs) introduction to Emacs"
(lambda (&rest _) (find-file "~/.emacs.d/Witcheat.org"))
'default)
(nil
"Update Lainmacs"
"Get the latest Lainmacs update. Check out the github commits for changes!"
(lambda (&rest _) (update-config))
'default))
;; line 2
((,nil
"Open scratch buffer"
"Switch to the scratch buffer"
(lambda (&rest _) (create-scratch-buffer))
'default)
(nil
"Open config.org"
"Open Lainmacs configuration file for easy editing"
(lambda (&rest _) (find-file "~/.emacs.d/config.org"))
'default)))))
If you pay close attention to the code in dashboard, you’ll notice that it uses custom functions defined under the :preface use-package block. I wrote all of those functions by looking at other people’s Emacs distributions (Mainly Centaur Emacs) and then experimenting and adapting them to Lainmacs. If you dig around, you’ll find the same things I did - maybe even more!
22/05/19: On this day, the main maintainers of the dashboard package have added built-in fuinctionality to display init and package load time, thing that I already had implemented much earlier on my own. I have left here my implementation for historical purposes
;(insert (concat
; (propertize (format "%d packages loaded in %s"
; (length package-activated-list) (emacs-init-time))
; 'face 'font-lock-comment-face)))
;
;(dashboard-center-line)
Incredibly useful package; if you are in the middle of a command and don’t know what to type next, just wait a second and you’ll get a nice buffer with all possible completions
(use-package which-key
:ensure t
:diminish which-key-mode
:init
(which-key-mode))
When doing C-s to search, you get this very nice and neat mini-buffer that you can traverse with the arrow keys (or C-n and C-p) and then press <RET> to select where you want to go
;(use-package swiper ;:ensure t ;:bind ("C-s" . 'swiper))
(use-package goggles
:ensure t
:defer nil
:hook ((prog-mode text-mode) . goggles-mode)
:config
(setq-default goggles-pulse t)) ;; set to nil to disable pulsing
Vim keybindings in Emacs. Please note that Lainmacs has NO other evil-mode compatibility packages because I like to KISS. This might change in the future
(use-package evil
:ensure t
:defer nil
:init
(setq evil-want-keybinding nil)
(setq evil-want-C-u-scroll t)
:config
(evil-mode 1))
(use-package evil-collection
:after evil
:ensure t
:config
(evil-collection-init))
You might find beacon an unnecesary package but I find it very neat. It briefly highlights the cursor position when switching to a new window or buffer
;(use-package beacon
; :ensure t
; :diminish beacon-mode
; :init
; (beacon-mode 1))
Avy is a very useful package; instead of having to move your cursor to a line that is very far away, just do M - s and type the character that you want to move to
(use-package avy
:ensure t)
;; :bind
;; ("M-s" . avy-goto-char))
Switch window is a neat package because instead of having to painstakingly do C - x o until you’re in the window you want to edit, you can just do C - x o and pick the one you want to move to according to the letter it is assigned to
(use-package switch-window
:ensure t
:config
(setq switch-window-input-style 'minibuffer)
(setq switch-window-increase 4)
(setq switch-window-threshold 2)
(setq switch-window-shortcut-style 'qwerty)
(setq switch-window-qwerty-shortcuts
'("a" "s" "d" "f" "j" "k" "l"))
:bind
([remap other-window] . switch-window))
For the longest time I used the default way of switching and killing buffers in Emacs. Same for finding files. Ido-mode made these three tasks IMMENSELY easier and more intuitive. Please not that I still use the default way M - x works because I believe all you really need for it is which-key
(use-package ido
:ensure t
:defer nil
:init
(ido-mode 1)
:config
(setq ido-enable-flex-matching nil)
(setq ido-create-new-buffer 'always)
(setq ido-everywhere t))
(use-package ido-vertical-mode
:ensure t
:init
(ido-vertical-mode 1))
; This enables arrow keys to select while in ido mode. If you want to
; instead use the default Emacs keybindings, change it to
; "'C-n-and-C-p-only"
(setq ido-vertical-define-keys 'C-n-C-p-up-and-down)
Utilize asynchronous processes whenever possible
(use-package async
:ensure t
:init
(dired-async-mode 1))
(use-package page-break-lines
:ensure t
:diminish (page-break-lines-mode visual-line-mode))
(use-package undo-tree
:ensure t
:diminish undo-tree-mode)
Neat side-bar file and project explorer
(use-package treemacs
:ensure t
:defer t
:init
(with-eval-after-load 'winum
(define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
:config
(progn
(setq treemacs-collapse-dirs (if (executable-find "python3") 3 0)
treemacs-deferred-git-apply-delay 0.5
treemacs-display-in-side-window t
treemacs-eldoc-display t
treemacs-file-event-delay 5000
treemacs-file-follow-delay 0.2
treemacs-follow-after-init t
treemacs-git-command-pipe ""
treemacs-goto-tag-strategy 'refetch-index
treemacs-indentation 2
treemacs-indentation-string " "
treemacs-is-never-other-window nil
treemacs-max-git-entries 5000
treemacs-missing-project-action 'ask
treemacs-no-png-images nil
treemacs-no-delete-other-windows t
treemacs-project-follow-cleanup nil
treemacs-persist-file (expand-file-name ".cache/treemacs-persist" user-emacs-directory)
treemacs-recenter-distance 0.1
treemacs-recenter-after-file-follow nil
treemacs-recenter-after-tag-follow nil
treemacs-recenter-after-project-jump 'always
treemacs-recenter-after-project-expand 'on-distance
treemacs-show-cursor nil
treemacs-show-hidden-files t
treemacs-silent-filewatch nil
treemacs-silent-refresh nil
treemacs-sorting 'alphabetic-desc
treemacs-space-between-root-nodes t
treemacs-tag-follow-cleanup t
treemacs-tag-follow-delay 1.5
treemacs-width 30)
(treemacs-resize-icons 11)
(treemacs-follow-mode t)
(treemacs-filewatch-mode t)
(treemacs-fringe-indicator-mode t)
(pcase (cons (not (null (executable-find "git")))
(not (null (executable-find "python3"))))
(`(t . t)
(treemacs-git-mode 'deferred))
(`(t . _)
(treemacs-git-mode 'simple))))
:bind
(:map global-map
("M-0" . treemacs-select-window)
("C-x t 1" . treemacs-delete-other-windows)
("C-x t t" . treemacs)
("C-x t B" . treemacs-bookmark)
("C-x t C-t" . treemacs-find-file)
("C-x t M-t" . treemacs-find-tag)))
(use-package treemacs-evil
:after treemacs evil
:ensure t)
(use-package treemacs-icons-dired
:after treemacs dired
:ensure t
:config (treemacs-icons-dired-mode))
Git porcelain for Emacs
(use-package magit
:ensure t)
Vertico provides a performant and minimalistic vertical completion UI based on the default completion system.
;; Enable vertico
(use-package vertico
:defer t
:ensure t
:init
(vertico-mode))
;; Different scroll margin
;; (setq vertico-scroll-margin 0)
;; Show more candidates
;; (setq vertico-count 20)
;; Grow and shrink the Vertico minibuffer
;; (setq vertico-resize t)
;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
;; (setq vertico-cycle t)
(use-package vertico-posframe
:defer t
:ensure t
:init
(vertico-posframe-mode 1))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init
(savehist-mode))
;; A few more useful configurations...
(use-package emacs
: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))
;; Optionally use the `orderless' completion style.
(use-package orderless
:ensure t
:init
;; Configure a custom style dispatcher (see the Consult wiki)
;; (setq orderless-style-dispatchers '(+orderless-dispatch)
;; orderless-component-separator #'orderless-escapable-split-on-space)
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))
(define-key vertico-map "?" #'minibuffer-completion-help)
(define-key vertico-map (kbd "M-RET") #'minibuffer-force-complete-and-exit)
(define-key vertico-map (kbd "TAB") #'minibuffer-complete)
;; Example configuration for Consult
(use-package consult
;; Replace bindings. Lazily loaded due by `use-package'.
:bind (;; C-c bindings (mode-specific-map)
("C-c M-x" . consult-mode-command)
("C-c h" . consult-history)
("C-c k" . consult-kmacro)
("C-c m" . consult-man)
("C-c i" . consult-info)
([remap Info-search] . consult-info)
;; C-x bindings (ctl-x-map)
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
;; Custom M-# bindings for fast register access
("M-#" . consult-register-load)
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
("C-M-#" . consult-register)
;; Other custom bindings
("M-y" . consult-yank-pop) ;; orig. yank-pop
;; M-g bindings (goto-map)
("M-g e" . consult-compile-error)
("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-g o" . consult-outline) ;; Alternative: consult-org-heading
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-g i" . consult-imenu)
("M-g I" . consult-imenu-multi)
;; M-s bindings (search-map)
("M-s d" . consult-find)
("M-s D" . consult-locate)
("M-s g" . consult-grep)
("M-s G" . consult-git-grep)
("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-s k" . consult-keep-lines)
("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map isearch-mode-map
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
;; Minibuffer history
:map minibuffer-local-map
("M-s" . consult-history) ;; orig. next-matching-history-element
("M-r" . consult-history)) ;; orig. previous-matching-history-element
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI.
:hook (completion-list-mode . consult-preview-at-point-mode)
;; The :init configuration is always executed (Not lazy)
:init
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
(setq register-preview-delay 0.5
register-preview-function #'consult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
;; Configure other variables and modes in the :config section,
;; after lazily loading the package.
:config
;; Optionally configure preview. The default value
;; is 'any, such that any key triggers the preview.
;; (setq consult-preview-key 'any)
;; (setq consult-preview-key "M-.")
;; (setq consult-preview-key '("S-<down>" "S-<up>"))
;; For some commands and buffer sources it is useful to configure the
;; :preview-key on a per-command basis using the `consult-customize' macro.
(consult-customize
consult-theme :preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-file-register
consult--source-recent-file consult--source-project-recent-file
;; :preview-key "M-."
:preview-key '(:debounce 0.4 any))
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
(setq consult-narrow-key "<") ;; "C-+"
;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
;; By default `consult-project-function' uses `project-root' from project.el.
;; Optionally configure a different project root function.
;;;; 1. project.el (the default)
;; (setq consult-project-function #'consult--default-project--function)
;;;; 2. vc.el (vc-root-dir)
;; (setq consult-project-function (lambda (_) (vc-root-dir)))
;;;; 3. locate-dominating-file
;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")))
;;;; 4. projectile.el (projectile-project-root)
;; (autoload 'projectile-project-root "projectile")
;; (setq consult-project-function (lambda (_) (projectile-project-root)))
;;;; 5. No project support
;; (setq consult-project-function nil)
)
;; Enable rich annotations using the Marginalia package
(use-package marginalia
:ensure t
;; Either bind `marginalia-cycle' globally or only in the minibuffer
:bind (("M-A" . marginalia-cycle)
:map minibuffer-local-map
("M-A" . marginalia-cycle))
;; The :init configuration is always executed (Not lazy!)
:init
;; Must be in the :init section of use-package such that the mode gets
;; enabled right away. Note that this forces loading the package.
(marginalia-mode))
(use-package embark
:ensure t
:bind
(("C-." . embark-act) ;; pick some comfortable binding
("C-;" . embark-dwim) ;; good alternative: M-.
("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
:init
;; Optionally replace the key help with a completing-read interface
(setq prefix-help-command #'embark-prefix-help-command)
;; Show the Embark target at point via Eldoc. You may adjust the Eldoc
;; strategy, if you want to see the documentation from multiple providers.
;; (add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target)
(setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)
:config
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none)))))
;; Consult users will also want the embark-consult package.
(use-package embark-consult
:ensure t ; only need to install it, embark loads it after consult if found
:hook
(embark-collect-mode . consult-preview-at-point-mode))
(use-package corfu
:ensure t
:defer nil
;; Optional customizations
;; (corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
;; (corfu-auto t) ;; Enable auto completion
;; (corfu-separator ?\s) ;; Orderless field separator
;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary
;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match
;; (corfu-preview-current nil) ;; Disable current candidate preview
;; (corfu-preselect-first nil) ;; Disable candidate preselection
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
;; (corfu-scroll-margin 5) ;; Use scroll margin
;; Enable corfu only for certain modes.
;; :hook ((prog-mode . corfu-mode)
;; (shell-mode . corfu-mode)
;; (eshell-mode . corfu-mode))
;; Recommended: Enable Corfu globally.
;; This is recommended since Dabbrev can be used globally (M-/).
;; See also `corfu-excluded-modes'.
:init
(global-corfu-mode)
(corfu-popupinfo-mode)
(setq corfu-auto t
corfu-popupinfo-delay (cons 0.5 0.5)
corfu-quit-no-match 'separator)
:config
(define-key corfu-map (kbd "C-n") #'corfu-next)
(define-key corfu-map (kbd "C-p") #'corfu-previous))
;; A few more useful configurations...
(use-package emacs
:init
;; TAB cycle if there are only few candidates
(setq completion-cycle-threshold 3)
;; Emacs 28: Hide commands in M-x which do not apply to the current mode.
;; Corfu commands are hidden, since they are not supposed to be used via M-x.
;; (setq read-extended-command-predicate
;; #'command-completion-default-include-p)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
(setq tab-always-indent 'complete))
(use-package affe
:defer t :ensure t
:config
;; Manual preview key for `affe-grep'
(consult-customize affe-grep :preview-key "M-."))
(use-package reformatter
:defer t :ensure t :diminish ormolu)
Company is the autocompletion frontend that takes all the backends and gives you possible autocompletions when writing programs
(use-package company
:ensure t
:diminish (meghanada-mode company-mode irony-mode)
:config
(setq company-idle-delay 0)
(setq company-minimum-prefix-length 3)
(define-key company-active-map (kbd "M-n") nil)
(define-key company-active-map (kbd "M-p") nil)
(define-key company-active-map (kbd "C-n") #'company-select-next)
(define-key company-active-map (kbd "C-p") #'company-select-previous)
(define-key company-active-map (kbd "SPC") #'company-abort)
(defun company-abort-and-insert-space ()
(interactive)
(company-abort)
(insert " "))
(define-key company-active-map (kbd "SPC") #'company-abort-and-insert-space))
;:hook
;((java-mode c-mode c++-mode) . company-mode))
Yasnippet provides useful snippets, nothing to do with Company but still useful when used in conjuction with it
(use-package yasnippet
:ensure t
:diminish yas-minor-mode
:hook
((c-mode c++-mode) . yas-minor-mode)
:config
(yas-reload-all))
(use-package yasnippet-snippets
:ensure t)
(use-package lsp-mode
:defer t :ensure t
:init
;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
(setq lsp-keymap-prefix "C-c l")
:hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode)
;(clojure-mode . lsp)
((haskell-mode c-mode) . lsp)
;; if you want which-key integration
(lsp-mode . lsp-enable-which-key-integration))
:commands lsp)
(use-package consult-lsp
:defer t :ensure t
:config
(define-key lsp-mode-map [remap xref-find-apropos] #'consult-lsp-symbols))
(use-package lsp-ui :ensure t :commands lsp-ui-mode)
(use-package lsp-treemacs :ensure t :commands lsp-treemacs-errors-list)
(use-package lsp-ivy :commands lsp-ivy-workspace-symbol)
;; optionally if you want to use debugger
(use-package dap-mode)
Irony is the company backend for C and C++
(use-package company-c-headers
:defer nil
:ensure t)
(use-package company-irony
:defer nil
:ensure t
:config
(setq company-backends '((company-c-headers
company-dabbrev-code
company-irony))))
(use-package irony
:defer nil
:ensure t
:config
:hook
;((c++-mode c-mode) . irony-mode)
('irony-mode-hook) . 'irony-cdb-autosetup-compile-options)
I use meghanada to provide very neat autocompletion when editing Java files. I use it mainly for autocompletion but there’s a ton of other things it can do, automatic imports, for example.
(use-package meghanada
:ensure t
:defer nil
:config
(add-hook 'java-mode-hook
(lambda ()
(meghanada-mode t)))
(setq meghanada-java-path "java")
(setq meghanada-maven-path "mvn"))
(defvar electrify-return-match
"[\]}\)\"]"
"If this regexp matches the text after the cursor, do an \"electric\"
return.")
(defun electrify-return-if-match (arg)
"If the text after the cursor matches `electrify-return-match' then
open and indent an empty line between the cursor and the text. Move the
cursor to the new line."
(interactive "P")
(let ((case-fold-search nil))
(if (looking-at electrify-return-match)
(save-excursion (newline-and-indent)))
(newline arg)
(indent-according-to-mode)))
;; Using local-set-key in a mode-hook is a better idea.
;;;;(global-set-key (kbd "RET") 'electrify-return-if-match)
(defun setup-lisp-stuff ()
(paredit-mode t)
(turn-on-eldoc-mode)
(eldoc-add-command 'paredit-backward-delete 'paredit-close-round)
(local-set-key (kbd "RET") 'electrify-return-if-match)
(eldoc-add-command 'electrify-return-if-match)
(show-paren-mode t))
; Paredit
(use-package paredit
:defer nil
:ensure t
:config
(add-hook 'lisp-mode-hook 'setup-lisp-stuff)
(add-hook 'scheme-mode-hook 'setup-lisp-stuff)
(add-hook 'clojure-mode-hook 'setup-lisp-stuff)
(add-hook 'clojurec-mode-hook 'setup-lisp-stuff)
:hook
((lisp-mode scheme-mode emacs-lisp-mode clojure-mode clojurec-mode) . paredit-mode))
; Parinfer
(use-package parinfer-rust-mode
:init
(setq parinfer-rust-auto-download t)
:config
;:hook
;((lisp-mode scheme-mode emacs-lisp-mode) . parinfer-rust-mode)
)
; Lispy
(use-package lispy
:defer nil
:ensure t
:config
(defun conditionally-enable-lispy ()
(when (eq this-command 'eval-expression)
(lispy-mode 1)))
(add-hook 'minibuffer-setup-hook 'conditionally-enable-lispy)
:hook
((lisp-mode scheme-mode emacs-lisp-mode clojure-mode) . lispy-mode))
; Slime
(use-package sly
:defer nil
:ensure t
:config
(setq inferior-lisp-program "ros -Q run"))
; Guile
(use-package geiser
:defer nil
:ensure t
:config
(setq geiser-guile-load-init-file t))
(use-package geiser-guile
:defer nil
:ensure t)
(use-package geiser-chicken
:defer nil
:ensure t)
; Clojure
(use-package cider
:ensure t :defer t
:config
(setq
cider-repl-history-file ".cider-repl-history" ;; not squiggly-related, but I like it
nrepl-log-messages t) ;; not necessary, but useful for trouble-shooting
(flycheck-clojure-setup)) ;; run setup *after* cider load
(use-package flycheck-clojure
:ensure t
:defer t
:commands (flycheck-clojure-setup) ;; autoload
:config
(eval-after-load 'flycheck
'(setq flycheck-display-errors-function #'flycheck-pos-tip-error-messages))
(add-hook 'after-init-hook #'global-flycheck-mode))
(use-package go-mode
:defer t :ensure t)