This is a set of display-buffer records to make window management easier in Emacs.
674 lines
26 KiB
Org Mode
674 lines
26 KiB
Org Mode
#+TITLE: Emacs configuration
|
|
#+AUTHOR: Oreodave
|
|
#+DESCRIPTION: My new Emacs configuration
|
|
|
|
* Initial
|
|
** Setup straight
|
|
Bootstrap of straight (from github)
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar bootstrap-version)
|
|
(let ((bootstrap-file
|
|
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
|
|
(bootstrap-version 5))
|
|
(unless (file-exists-p bootstrap-file)
|
|
(with-current-buffer
|
|
(url-retrieve-synchronously
|
|
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
|
|
'silent 'inhibit-cookies)
|
|
(goto-char (point-max))
|
|
(eval-print-last-sexp)))
|
|
(load bootstrap-file nil 'nomessage))
|
|
#+END_SRC
|
|
** Setup use package
|
|
Straight clone use-package and state that all use-package statements implicity use straight.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(straight-use-package 'use-package)
|
|
(setq straight-use-package-by-default t)
|
|
#+END_SRC
|
|
** Setup alpha and yes-or-no-p
|
|
This just sets the alpha to 85% and all yes or no questions to single letter responses.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'default-frame-alist '(alpha . 85))
|
|
(fset 'yes-or-no-p 'y-or-n-p)
|
|
#+END_SRC
|
|
** Hs Minor mode
|
|
Turn on hs minor mode for all prog-mode.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'prog-mode-hook #'hs-minor-mode)
|
|
#+END_SRC
|
|
** Set backup directory
|
|
Set the backup directory to =user-emacs-directory=/saves so I don't get those annoying '~' files.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq backup-directory-alist `(("." . "~/.config/emacs/saves")))
|
|
#+END_SRC
|
|
** Turn off the bars
|
|
Turn off all the bars, don't need them anymore!
|
|
#+BEGIN_SRC emacs-lisp
|
|
(tool-bar-mode -1)
|
|
(scroll-bar-mode -1)
|
|
(menu-bar-mode -1)
|
|
#+END_SRC
|
|
** Themes
|
|
Load my custom "Grayscale" theme (look at [[file:Grayscale-theme.el][this file]]).
|
|
#+BEGIN_SRC emacs-lisp
|
|
(load-theme 'Grayscale t)
|
|
#+END_SRC
|
|
** Turn off startup buffer
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq inhibit-startup-screen t)
|
|
#+END_SRC
|
|
* Emacs Mode-line
|
|
Firstly, declare a variable for the number of spaces between each module in the modeline.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defconst +modeline/sep-spaces 4 "Number of spaces separating modules.")
|
|
#+END_SRC
|
|
|
|
Then, declare a list of reserved characters for which the previously declared seperator won't be applied when placed at the end of a module string.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defconst +modeline/reserved-chars (list "[" "(")
|
|
"Characters that, when at the end of a module string, won't have the separator applied to them.")
|
|
#+END_SRC
|
|
|
|
Now declare a function that applies the separator with respect to the reserved characters to any one string.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun +modeline/handle-string (STR)
|
|
(condition-case nil
|
|
(progn
|
|
(string-blank-p STR)
|
|
(cond ((cl-member (car (last (split-string STR "" t))) +modeline/reserved-chars :test #'string=) STR)
|
|
(t (concat STR (cl-reduce #'concat (cl-loop for i from 1 to +modeline/sep-spaces collect " "))))))
|
|
(error STR)))
|
|
#+END_SRC
|
|
|
|
Finally, set the mode-line-format.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default
|
|
mode-line-format
|
|
(mapcar #'+modeline/handle-string
|
|
(list "%l:%c"
|
|
"%p["
|
|
'(:eval (upcase
|
|
(substring
|
|
(format "%s" (if (bound-and-true-p evil-state) evil-state ""))
|
|
0 1)))
|
|
"]"
|
|
"%+%b("
|
|
'(:eval (format "%s" major-mode))
|
|
")"
|
|
"%I"
|
|
vc-mode
|
|
mode-line-end-spaces)))
|
|
#+END_SRC
|
|
* Custom Functions
|
|
These are custom functions I have defined
|
|
** New line function
|
|
Vim bindings don't have a nice way of adding new lines before or after the current line while staying in normal mode.
|
|
You can use =o/O= to enter insert mode at a new line, but this isn't the same as being able to stay in normal mode, and only adds extra keypresses if your only purpose was to open up some lines.
|
|
As this is Emacs I can extend it as I wish, so I decided to define a new line function that won't remove me from normal state.
|
|
|
|
The logic is pretty simple:
|
|
- Use the predefined vim functions for opening new lines above and below with insert mode
|
|
- Given the argument =BACKWARD= to assess whether to open lines above or below
|
|
- Return to previous location
|
|
- Enter normal state
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load "evil"
|
|
(defun dx:newline (&optional BACKWARD)
|
|
(interactive)
|
|
(let ((old (point)))
|
|
(cond ((and BACKWARD (= BACKWARD 1)) (evil-open-below 1))
|
|
(t (evil-open-above 1)))
|
|
(goto-char (+ old 1))
|
|
(evil-normal-state))))
|
|
#+END_SRC
|
|
** Generate tags
|
|
For some reason, I can't seem to rely on the =projectile-regenerate-tags= function, so define my own.
|
|
|
|
Steps are as follows:
|
|
- Consider the =root= to be either =default-directory= or the =projectile-project-root= depending on if it's loaded and set.
|
|
- Start a process (shell command) by changing to =root= and executing =ctags -Re=
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun dx:generate-tags ()
|
|
(interactive)
|
|
(let ((root (if (bound-and-true-p projectile-project-root)
|
|
projectile-project-root
|
|
default-directory)))
|
|
(start-process-shell-command "" nil (format "cd %s; ctags -Re ." root))))
|
|
#+END_SRC
|
|
* Keybindings
|
|
** Global map
|
|
Any functions that are already loaded, set them to the global map.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(bind-keys
|
|
:map global-map
|
|
("<menu>" . nil)
|
|
("M-v" . (lambda () (interactive) (dx:newline 1)))
|
|
("M-V" . (lambda () (interactive) (dx:newline)))
|
|
("M-z" . mark-whole-buffer)
|
|
("C-x h" . next-buffer)
|
|
("C-x l" . previous-buffer)
|
|
("C-c !" . async-shell-command)
|
|
("C-c c" . compile)
|
|
("C-c t" . eshell)
|
|
("M-s i" . imenu)
|
|
("M-n f" . narrow-to-defun)
|
|
("M-n w" . widen)
|
|
("M-n r" . narrow-to-region))
|
|
#+END_SRC
|
|
** Menu map
|
|
Any keys I want to map to <menu>, the weird little menu interaction button on some keyboards.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(bind-keys
|
|
:prefix "<menu>"
|
|
:prefix-map dx:menu-map
|
|
("<menu>" . execute-extended-command)
|
|
("p" . (lambda () (interactive) (find-file (concat user-emacs-directory "config.org"))))
|
|
("#" . (lambda () (interactive) (projectile-find-file)))
|
|
("." . imenu))
|
|
#+END_SRC
|
|
* Evil
|
|
** Evil default
|
|
Setup the evil package, with some basic keybinds.
|
|
Also declare a leader-map at "SPC".
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package evil
|
|
:init
|
|
(setq evil-want-keybinding nil)
|
|
:config
|
|
(evil-mode +1)
|
|
(evil-define-key 'normal global-map
|
|
"TAB" #'evil-jump-item
|
|
"SPC" nil)
|
|
(evil-define-key 'visual 'emacs-lisp-mode-map "gr" #'eval-region)
|
|
(bind-keys
|
|
:map evil-normal-state-map
|
|
:prefix "SPC"
|
|
:prefix-map +evil/leader-map
|
|
("f" . find-file)
|
|
("s" . save-buffer)
|
|
("q" . save-buffers-kill-terminal)
|
|
("i" . imenu)
|
|
("b" . switch-to-buffer)))
|
|
#+END_SRC
|
|
** Evil surround
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package evil-surround
|
|
:after evil
|
|
:config
|
|
(global-evil-surround-mode))
|
|
#+END_SRC
|
|
** Evil commentary
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package evil-commentary
|
|
:after evil
|
|
:config
|
|
(evil-commentary-mode))
|
|
#+END_SRC
|
|
** Evil mc
|
|
Setup for multicursors in Evil mode.
|
|
Don't let evil-mc setup it's own keymap because it uses 'gr' as its prefix, which I don't like.
|
|
Instead, bind some useful functions to my personal =dx:evil-mc-map= which is bound to 'gz'.
|
|
Furthermore, define a function =dx:evil-mc-cursor-here= which pauses cursors upon placing a cursor at the current position.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package evil-mc
|
|
:after evil
|
|
:bind (("M-p" . evil-mc-skip-and-goto-prev-cursor)
|
|
:map dx:evil-mc-map
|
|
("q" . evil-mc-undo-all-cursors)
|
|
("d" . evil-mc-make-and-goto-next-match)
|
|
("j" . evil-mc-make-cursor-move-next-line)
|
|
("k" . evil-mc-make-cursor-move-prev-line)
|
|
("j" . evil-mc-make-cursor-move-next-line)
|
|
("m" . evil-mc-make-all-cursors)
|
|
("z" . dx:evil-mc-cursor-here)
|
|
("r" . evil-mc-resume-cursors)
|
|
("s" . evil-mc-pause-cursors))
|
|
:init
|
|
(defvar evil-mc-key-map (make-sparse-keymap))
|
|
(define-prefix-command 'dx:evil-mc-map)
|
|
(bind-key "gz" dx:evil-mc-map evil-normal-state-map)
|
|
(bind-key "gz" dx:evil-mc-map evil-visual-state-map)
|
|
:config
|
|
(global-evil-mc-mode +1)
|
|
(defun dx:evil-mc-cursor-here ()
|
|
(interactive)
|
|
(evil-mc-make-cursor-here)
|
|
(evil-mc-pause-cursors)))
|
|
#+END_SRC
|
|
** Evil collection
|
|
Setup evil collection, but don't turn on the mode.
|
|
Instead, I'll turn on setups for specific modes I think benefit from it.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package evil-collection
|
|
:after evil)
|
|
#+END_SRC
|
|
* IBuffer
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package ibuffer
|
|
:bind ("<menu> ," . ibuffer)
|
|
:after evil-collection
|
|
:config
|
|
(evil-collection-ibuffer-setup))
|
|
#+END_SRC
|
|
* Dired
|
|
Setup for dired.
|
|
Firstly, as it's an inbuilt package don't let straight try and download it.
|
|
Make dired-hide-details-mode the default mode when dired-mode, as it removes the clutter.
|
|
Create a keymap =dx:dired-map= which is bound to the prefix "C-c d", binding useful dired functions.
|
|
Setup evil collection for dired (even though dired doesn't really conflict with evil, there are some black corners I'd like to adjust)
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package dired
|
|
:straight nil
|
|
:hook (dired-mode . dired-hide-details-mode)
|
|
:bind (:map +evil/leader-map
|
|
("d" . dired-jump))
|
|
:bind-keymap* ("C-c d" . dx:dired-map)
|
|
:after evil-collection
|
|
:init
|
|
(defvar dx:dired-map (make-sparse-keymap) "dx:dired-map")
|
|
:config
|
|
(bind-keys
|
|
:map dx:dired-map
|
|
("f" . find-dired)
|
|
("D" . dired-other-window)
|
|
("d" . dired-jump))
|
|
(evil-collection-dired-setup))
|
|
#+END_SRC
|
|
* Helpful
|
|
Basic setup, will be fully integrated in counsel.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package helpful
|
|
:commands (helpful-callable helpful-variable))
|
|
#+END_SRC
|
|
* Which-key
|
|
Pretty simple, just activate after init.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package which-key
|
|
:hook (after-init . which-key-mode))
|
|
#+END_SRC
|
|
* Avy
|
|
Avy is an incredibly useful package that I have just started to understand.
|
|
For now, I have two bindings for =avy-goto-line= and =avy-goto-char-2= as I use them often.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package avy
|
|
:bind (("M-g" . #'avy-goto-char-2)
|
|
("M-l" . #'avy-goto-line)))
|
|
#+END_SRC
|
|
* Hydra
|
|
I haven't found a use for it yet, so don't tangle this.
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
(use-package hydra)
|
|
#+END_SRC
|
|
* Yasnippet
|
|
Yasnippet is a great package for snippets, which I use heavily in programming and org-mode.
|
|
I setup here the global mode for yasnippet and a collection of snippets for ease of use.
|
|
** Yasnippet default
|
|
Setup global mode after evil mode has been loaded
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package yasnippet
|
|
:after evil
|
|
:hook (after-init . yas-global-mode)
|
|
:bind ("C-c i" . yas-insert-snippet))
|
|
#+END_SRC
|
|
** Yasnippet snippets
|
|
Collection of snippets, activate after yasnippet has been loaded.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package yasnippet-snippets
|
|
:after yasnippet)
|
|
#+END_SRC
|
|
* Keychord
|
|
Keychord is only really here for this one chord I wish to define: "jk" for exiting insert state.
|
|
Otherwise, I don't really need it.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package key-chord
|
|
:after evil
|
|
:config
|
|
(key-chord-define evil-insert-state-map "jk" #'evil-normal-state)
|
|
(key-chord-mode +1))
|
|
#+END_SRC
|
|
* Ivy
|
|
Ivy is a completion framework for Emacs, and my preferred (sometimes second favourite) one.
|
|
It has a great set of features with little to no pain with setting up.
|
|
** Ivy
|
|
Setup for ivy, in preparation for counsel.
|
|
Turn on ivy-mode just after init.
|
|
Setup vim-like bindings for the minibuffer ("C-(j|k)" for down|up the selection list)
|
|
Also setup evil-collection for ivy.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package ivy
|
|
:after evil-collection
|
|
:hook (after-init . ivy-mode)
|
|
:bind (:map ivy-minibuffer-map
|
|
("C-j" . ivy-next-line-or-history)
|
|
("C-k" . ivy-previous-line-or-history)
|
|
:map ivy-switch-buffer-map
|
|
("C-j" . ivy-next-line-or-history)
|
|
("C-k" . ivy-previous-line-or-history))
|
|
:config
|
|
(evil-collection-ivy-setup))
|
|
|
|
|
|
#+END_SRC
|
|
** Counsel
|
|
Setup for counsel.
|
|
Load after ivy and helpful.
|
|
|
|
Bind:
|
|
- Swiper to "C-s"
|
|
- Switch buffer to "C-x b"
|
|
- Counsel ripgrep to "M-s r" (search namespace)
|
|
|
|
Along with that, set the help function and variable functions to their helpful counterparts.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package counsel
|
|
:after (ivy helpful)
|
|
:bind (("C-s" . counsel-grep-or-swiper)
|
|
("C-x b" . counsel-switch-buffer))
|
|
:config
|
|
(setq ivy-initial-inputs-alist nil
|
|
counsel-describe-function-function #'helpful-callable
|
|
counsel-describe-variable-function #'helpful-variable))
|
|
#+END_SRC
|
|
** Counsel etags
|
|
Counsel etags allows me to search generated tag files for tags.
|
|
I already have a function defined [[*Generate tags][here]] to generate the tags, so it's just searching them which I find to be a bit of a hassle, and where this package comes in.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package counsel-etags
|
|
:after counsel
|
|
:bind ("M-s t" . counsel-etags-find-tag))
|
|
#+END_SRC
|
|
* Ripgrep
|
|
The ripgrep package provides utilities to grep projects and files for strings via the rg tool.
|
|
Though [[*Ivy][ivy]] comes with =counsel-rg= using it makes me dependent on the ivy framework, and this configuration is intentionally built to be modular and switchable.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package rg
|
|
:after evil
|
|
:bind (("M-s r" . rg)
|
|
:map +evil/leader-map
|
|
("r" . rg)
|
|
:map rg-mode-map
|
|
("]]" . rg-next-file)
|
|
("[[" . rg-prev-file))
|
|
:init
|
|
(setq rg-group-result t
|
|
rg-hide-command t
|
|
rg-show-columns nil
|
|
rg-show-header t
|
|
rg-custom-type-aliases nil
|
|
rg-default-alias-fallback "all"))
|
|
#+END_SRC
|
|
* Projectile
|
|
** Projectile default
|
|
Setup projectile, along with the tags command.
|
|
Also bind "C-c C-p" to the projectile command map for quick access.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package projectile
|
|
:after evil
|
|
:hook (prog-mode . projectile-mode)
|
|
:bind (:map +evil/leader-map
|
|
("p" . projectile-switch-buffer))
|
|
:bind-keymap* ("C-c C-p" . projectile-command-map)
|
|
:init
|
|
(setq projectile-tags-command "ctags -Re -f \"%s\" %s \"%s\"")
|
|
:config
|
|
(projectile-global-mode))
|
|
#+END_SRC
|
|
** Counsel projectile
|
|
Counsel projectile provides the ivy interface to projectile commands, which is really useful.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package counsel-projectile
|
|
:after (projectile counsel)
|
|
:config
|
|
(counsel-projectile-mode +1))
|
|
#+END_SRC
|
|
* Magit
|
|
Magit is *the* git porcelain for Emacs, which perfectly encapsulates the git cli.
|
|
In this case, I just need to setup the bindings for it.
|
|
As magit will definitely load after evil (as it must be run by a binding, and evil will load after init), I can use evil-collection freely.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package magit
|
|
:bind (("C-x g g" . magit-status)
|
|
("C-x g c" . magit-clone)
|
|
("C-x g l" . magit-log)
|
|
:map +evil/leader-map
|
|
("g" . magit-status)))
|
|
|
|
(use-package evil-magit
|
|
:after magit)
|
|
#+END_SRC
|
|
* Company
|
|
Company is the auto complete system I use.
|
|
I don't like having heavy setups for company, as it only makes it worse to use.
|
|
In this case, just setup some evil binds for company
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package company
|
|
:hook (prog-mode . company-mode)
|
|
:bind (("C-SPC" . company-complete)
|
|
:map company-active-map
|
|
("C-j" . company-select-next)
|
|
("C-k" . company-select-previous)))
|
|
#+END_SRC
|
|
* Elfeed
|
|
Elfeed is the perfect RSS feed reader, integrated into Emacs perfectly.
|
|
I've got a set of feeds that I use for a large variety of stuff, mostly media and entertainment.
|
|
I've also bound "C-c r" to elfeed for loading the system.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package elfeed
|
|
:bind ("C-c r" . elfeed)
|
|
:init
|
|
(setq +rss/feed-urls
|
|
'(("Arch Linux" "https://www.archlinux.org/feeds/news/" Linux)
|
|
("LEMMiNO" "https://www.youtube.com/feeds/videos.xml?channel_id=UCRcgy6GzDeccI7dkbbBna3Q" YouTube Stories)
|
|
("Dark Sominium" "https://www.youtube.com/feeds/videos.xml?channel_id=UC_e39rWdkQqo5-LbiLiU10g" YouTube Stories)
|
|
("Dark Sominium Music" "https://www.youtube.com/feeds/videos.xml?channel_id=UCkLiZ_zLynyNd5fd62hg1Kw" YouTube Music)
|
|
("Nexpo" "https://www.youtube.com/feeds/videos.xml?channel_id=UCpFFItkfZz1qz5PpHpqzYBw" YouTube)
|
|
("Techquickie" "https://www.youtube.com/feeds/videos.xml?channel_id=UC0vBXGSyV14uvJ4hECDOl0Q" YouTube)
|
|
("Captain Sinbad" "https://www.youtube.com/feeds/videos.xml?channel_id=UC8XKyvQ5Ne_bvYbgv8LaIeg" YouTube)
|
|
("3B1B" "https://www.youtube.com/feeds/videos.xml?channel_id=UCYO_jab_esuFRV4b17AJtAw" YouTube)
|
|
("Fredrik Knusden" "https://www.youtube.com/feeds/videos.xml?channel_id=UCbWcXB0PoqOsAvAdfzWMf0w" YouTube Stories)
|
|
("Barely Sociable" "https://www.youtube.com/feeds/videos.xml?channel_id=UC9PIn6-XuRKZ5HmYeu46AIw" YouTube Stories)
|
|
("Atrocity Guide" "https://www.youtube.com/feeds/videos.xml?channel_id=UCn8OYopT9e8tng-CGEWzfmw" YouTube Stories)
|
|
("Phillip Defranco" "https://www.youtube.com/feeds/videos.xml?channel_id=UClFSU9_bUb4Rc6OYfTt5SPw" YouTube News)
|
|
("Hacker News" "http://morss.aryadevchavali.com/news.ycombinator.com/rss" Social)
|
|
("Hacker Factor" "https://www.hackerfactor.com/blog/index.php?/feeds/index.rss2" Social)
|
|
("BBC Top News" "http://morss.aryadevchavali.com/feeds.bbci.co.uk/news/rss.xml" News)
|
|
("BBC Tech News" "http://morss.aryadevchavali.com/feeds.bbci.co.uk/news/technology/rss.xml" News)))
|
|
(setq elfeed-db-directory (concat user-emacs-directory "elfeed"))
|
|
:config
|
|
(evil-collection-elfeed-setup)
|
|
(evil-define-key 'normal elfeed-search-mode-map "gr" #'elfeed-update)
|
|
(evil-define-key 'normal elfeed-search-mode-map "s" #'elfeed-search-live-filter)
|
|
(evil-define-key 'normal elfeed-search-mode-map "<return>" #'elfeed-search-show-entry)
|
|
(setq elfeed-feeds (mapc #'(lambda (item) (append (list (nth 1 item)) (cdr (cdr item)))) +rss/feed-urls)))
|
|
#+END_SRC
|
|
* Org mode
|
|
** Org default with evil
|
|
Setup for org mode, currently basically nothing.
|
|
Has evil-org for evil bindings.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package org
|
|
:hook (org-mode . yas-minor-mode)
|
|
:bind (:map org-mode-map
|
|
([remap imenu] . counsel-org-goto))
|
|
:custom
|
|
(org-src-window-setup 'current-window))
|
|
|
|
(use-package evil-org
|
|
:hook (org-mode . evil-org-mode))
|
|
#+END_SRC
|
|
** Org superstar
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package org-superstar
|
|
:hook (org-mode . org-superstar-mode))
|
|
#+END_SRC
|
|
** Flyspell
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package flyspell
|
|
:hook (org-mode . flyspell-mode))
|
|
|
|
(use-package flyspell-correct-ivy
|
|
:after flyspell
|
|
:bind (:map org-mode-map
|
|
("C-c C-a" . flyspell-correct-at-point)))
|
|
#+END_SRC
|
|
* Window management
|
|
Window management is really important.
|
|
I find the default window handling of Emacs incredibly annoying: sometimes consuming my windows, sometimes creating new ones.
|
|
So, as Emacs is the ultimate editor, I want to configure and fine tune the window management of Emacs.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq display-buffer-alist
|
|
'(("\\*e?shell\\*"
|
|
(display-buffer-in-side-window)
|
|
(window-height . 0.25)
|
|
(side . bottom)
|
|
(slot . 0))
|
|
("\\*[Hh]elp.*"
|
|
(display-buffer-in-side-window)
|
|
(window-height . 0.25)
|
|
(side . bottom)
|
|
(slot . 1))
|
|
("magit:.*"
|
|
(display-buffer-in-side-window)
|
|
(side . right)
|
|
(slot . -1)
|
|
(window-width . 0.5))
|
|
("magit-diff:.*"
|
|
(display-buffer-in-side-window)
|
|
(side . right)
|
|
(slot . -2)
|
|
(window-width . 0.5))
|
|
("\\*compilation\\*"
|
|
(display-buffer-in-side-window)
|
|
(side . bottom)
|
|
(slot . -1)
|
|
(window-height . 0.25))
|
|
("\\*Flycheck.*"
|
|
(display-buffer-in-side-window)
|
|
(side . bottom)
|
|
(window-height . 0.25)
|
|
(slot . 0))
|
|
("\\*rg.*"
|
|
(display-buffer-in-side-window)
|
|
(side . bottom)
|
|
(window-height . 0.25)
|
|
(slot . 1))
|
|
))
|
|
#+END_SRC
|
|
* Major modes and Programming
|
|
Setups for common major modes and languages
|
|
Here are some basic packages for programming first
|
|
** Smartparens
|
|
Smartparens is a smarter electric-parens, it's much more aware of stuff and easier to use.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package smartparens
|
|
:after evil
|
|
:config
|
|
(setq sp-highlight-pair-overlay nil
|
|
sp-highlight-wrap-overlay t
|
|
sp-highlight-wrap-tag-overlay t)
|
|
(smartparens-global-mode))
|
|
#+END_SRC
|
|
** Show-paren-mode
|
|
Show parenthesis for Emacs
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'prog-mode-hook #'show-paren-mode)
|
|
#+END_SRC
|
|
** Eldoc
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package eldoc
|
|
:hook (prog-mode . eldoc-mode))
|
|
|
|
(use-package eldoc-box
|
|
:hook (eglot--managed-mode . eldoc-box-hover-mode)
|
|
:custom
|
|
((eldoc-box-max-pixel-height 15)
|
|
(eldoc-box-max-pixel-width 15)))
|
|
#+END_SRC
|
|
|
|
** Eglot
|
|
Eglot is a library of packages to communicate with LSP servers for better programming capabilities.
|
|
Interactions with a server provide results to the client, done through JSON.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package eglot
|
|
:hook (c++-mode . eglot-ensure)
|
|
:hook (c-mode . eglot-ensure)
|
|
:bind (:map eglot-mode-map
|
|
("<f2>" . eglot-rename)
|
|
("C-c C-A" . eglot-code-actions)
|
|
("C-c C-f" . eglot-format))
|
|
:config
|
|
(add-to-list 'eglot-server-programs '((c-mode c++-mode) "clangd")))
|
|
#+END_SRC
|
|
** Flycheck
|
|
Flycheck is the checking system for Emacs.
|
|
I don't necessarily like having all my code checked all the time, so I haven't added a hook to prog-mode as it would be better for me to decide when I want checking and when I don't.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package flycheck
|
|
:commands flycheck-mode
|
|
:bind ("C-c x" . +flycheck/list-errors-load-flycheck)
|
|
:config
|
|
(defun +flycheck/list-errors-load-flycheck ()
|
|
"Load flycheck if not available, then list errors."
|
|
(interactive)
|
|
(when (not (or flycheck-mode global-flycheck-mode))
|
|
(flycheck-mode))
|
|
(flycheck-list-errors)))
|
|
#+END_SRC
|
|
** Activate tabs
|
|
Set tabs to nil by default, with normal tab size set to 2.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default indent-tabs-mode nil
|
|
tab-width 2)
|
|
#+END_SRC
|
|
|
|
Add a function to activate tabs mode.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun dx:activate-tabs ()
|
|
(interactive)
|
|
(setq indent-tabs-mode t))
|
|
#+END_SRC
|
|
** C/C++
|
|
Setup for C and C++ modes via the cc-mode package.
|
|
Firstly hook the C and C++ modes to activate tabs.
|
|
Then set the offset to 2, and the general style to user.
|
|
Finally, add a user style that mimics the Microsoft guidelines for C# (open braces everywhere).
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package cc-mode
|
|
:hook (c-mode . +dx:activate-tabs)
|
|
:hook (c++-mode . +dx:activate-tabs)
|
|
:init
|
|
(setq-default c-basic-offset 2)
|
|
(setq c-default-style '((java-mode . "java")
|
|
(awk-mode . "awk")
|
|
(other . "user")))
|
|
:config
|
|
(c-add-style
|
|
"user"
|
|
'((c-basic-offset . 2)
|
|
(c-comment-only-line-offset . 0)
|
|
(c-hanging-braces-alist (brace-list-open)
|
|
(brace-entry-open)
|
|
(substatement-open after)
|
|
(block-close . c-snug-do-while)
|
|
(arglist-cont-nonempty))
|
|
(c-cleanup-list brace-else-brace)
|
|
(c-offsets-alist
|
|
(statement-block-intro . +)
|
|
(knr-argdecl-intro . 0)
|
|
(substatement-open . 0)
|
|
(substatement-label . 0)
|
|
(access-label . 0)
|
|
(label . 0)
|
|
(statement-cont . +)))))
|
|
#+END_SRC
|
|
*** Clang format
|
|
use-package clang-format for ease of use formatting, binding to "C-c '" for both C and C++ mode maps.
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package clang-format
|
|
:after cc-mode
|
|
:config
|
|
(bind-key "C-c '" #'clang-format-region c-mode-map)
|
|
(bind-key "C-c '" #'clang-format-region c++-mode-map))
|
|
#+END_SRC
|