daedreth / UncleDavesEmacs

My personal ~/.emacs.d
GNU General Public License v3.0
247 stars 54 forks source link
emacs emacs-configuration emacs-customizations emacs-initialization emacs-lisp emacs-packages

+STARTUP: overview

+TITLE: Uncle Dave's Emacs

+CREATOR: Dawid 'daedreth' Eckert

+LANGUAGE: en

+OPTIONS: num:nil

+ATTR_HTML: :style margin-left: auto; margin-right: auto;

[[./img/screen.png]]

Keep in mind that you should remove your own ~/.emacs and your ~/.emacs.d prior to cloning this configuration. The next time you launch Emacs (and I recommend launching emacs in the tty for the first time) it's going to download a good amount of packages and configure them for you, you might see warnings and errors being displayed as well, those are safe to ignore as long as you relaunch emacs and see none.

The configuration, much like emacs is self documented, I highly recommend reading through my ramblings in their entirety.

** Less Quick Installation You are free to pick out bits and pieces of this and apply them. So long as you have a working =use-package= configuration (take a peek at my init.el), there should be absolutely no issues. I highly encourage you to read up on the prose around the packages you are interested in, I do my absolute best to describe the configuration as well as I only can, this might help you on your emacs journey! Have some fun with it, add your own keybindings, change parameters, it's your editor in the end.

**** Optional

** TRAMP *** From the package manager:

** EMMS *** From the package manager:

** Programming *** Package manager

*** pip

** On the format of the configuration As you may have noticed, as you scroll down my bit of prose, this is the configuration file itself. This configuration is written in =org-mode=, which is a great emacs package and a great markup language. On launch, this file is being sourced into =~/.emacs.d/init.el=, the prose is being automatically stripped (as to not affect performance) and the remaining =config.el= file is parsed.

This is also the reason why your org-mode configuration file is never called =init.org=.

** On the use case of this configuration This entire config is meant to be used as a full on desktop environment, it is tailored to sit on top of xorg and be awesome. It is perfectly possible to use it without exwm and emms, as a regular emacs config, just make sure to delete the unwanted sections, ex.g EXWM, Audio Control, EMMS and all the launchers. There is barely any learning curve to using =exwm=, since it makes x-windows act as regular buffers as much as possible, so chances are, as long as you know your way around emacs itself, you will instinctively know how to make use of its features.

** On the keybindings I do my best to not pollute keymaps with my own keybindings. Most of the bindings I defined myself utilize the Super key (noted as =s-=). This is the least used modifier key together with Shift (noted as =S-=), thus using those, chances are all the bindings you already know and love are going to work flawlessly. For all the others, just keep on reading.

** Some customization The theme is great, really, but some of the concepts just suck with powerline.

+BEGIN_SRC emacs-lisp

(let ((class '((class color) (min-colors 89))) (default (if (true-color-p) "#abb2bf" "#afafaf")) (light (if (true-color-p) "#ccd4e3" "#d7d7d7")) (background (if (true-color-p) "#282c34" "#333333")) (background-dark (if (true-color-p) "#24282f" "#222222")) (background-darker (if (true-color-p) "#22252c" "#222222")) (mode-line-inactive (if "#1c2129" "#222222")) (mode-line-active (if (true-color-p) "#6f337e" "#875f87")) (background-lighter (if (true-color-p) "#3a3f4b" "#5f5f5f")) (background-red (if (true-color-p) "#4c3840" "#5f5f5f")) (bright-background-red (if (true-color-p) "#744a5b" "#744a5b")) (background-purple (if (true-color-p) "#48384c" "#5f5f5f")) (background-blue (if (true-color-p) "#38394c" "#444444")) (bright-background-blue (if (true-color-p) "#4e5079" "#4e5079")) (background-green (if (true-color-p) "#3d4a41" "#5f5f5f")) (bright-background-green (if (true-color-p) "#3f6d54" "#3f6d54")) (background-orange (if (true-color-p) "#4a473d" "#5f5f5f")) (hl-line (if (true-color-p) "#2c323b" "#333333")) (grey (if (true-color-p) "#cccccc" "#cccccc")) (grey-dark (if (true-color-p) "#666666" "#666666")) (highlight (if (true-color-p) "#3e4451" "#5f5f5f")) (comment (if (true-color-p) "#687080" "#707070")) (orange (if (true-color-p) "#da8548" "#d7875f")) (orange-light (if (true-color-p) "#ddbd78" "#d7af87")) (red (if (true-color-p) "#ff6c6b" "#ff5f5f")) (purple (if (true-color-p) "#c678dd" "#d787d7")) (purple-dark (if (true-color-p) "#64446d" "#5f5f5f")) (blue (if (true-color-p) "#61afef" "#5fafff")) (blue-dark (if (true-color-p) "#1f5582" "#005f87")) (green (if (true-color-p) "#98be65" "#87af5f")) (green-light (if (true-color-p) "#9eac8c" "#afaf87")) (peach "PeachPuff3") (diff-added-background (if (true-color-p) "#284437" "#284437")) (diff-added-refined-background (if (true-color-p) "#1e8967" "#1e8967")) (diff-removed-background (if (true-color-p) "#583333" "#580000")) (diff-removed-refined-background (if (true-color-p) "#b33c49" "#b33c49")) (diff-current-background (if (true-color-p) "#29457b" "#29457b")) (diff-current-refined-background (if (true-color-p) "#4174ae" "#4174ae")))

(custom-theme-set-faces
 'zerodark

 `(fancy-battery-charging ((,class (:background ,background-blue :height 1.0 :bold t))))
 `(fancy-battery-discharging ((,class (:background ,background-blue :height 1.0))))
 `(fancy-battery-critical ((,class (:background ,background-blue :height 1.0))))

 ;; mode line stuff
 `(mode-line ((,class (:background ,background-blue :height 1.0 :foreground ,blue
                                   :distant-foreground ,background-blue
                                   :box ,(when zerodark-use-paddings-in-mode-line
                                           (list :line-width 6 :color background-blue))))))

 `(mode-line-inactive ((,class (:background ,background-blue :height 1.0 :foreground ,default
                                            :distant-foreground ,background-blue
                                            :box ,(when zerodark-use-paddings-in-mode-line
                                                    (list :line-width 6 :color background-blue))))))

 `(header-line ((,class (:inherit mode-line-inactive))))

 `(powerline-active0 ((,class (:height 1.0 :foreground ,blue :background ,background-blue
                                       :distant-foreground ,background-blue))))
 `(powerline-active1 ((,class (:height 1.0 :foreground ,blue :background ,background-blue
                                       :distant-foreground ,background-blue))))
 `(powerline-active2 ((,class (:height 1.0 :foreground ,blue :background ,background-blue
                                       :distant-foreground ,background-blue))))
 `(powerline-inactive0 ((,class (:height 1.0 :foreground ,blue :background ,background-blue
                                         :distant-foreground ,background-blue))))
 `(powerline-inactive1 ((,class (:height 1.0 :foreground ,blue :background ,background-blue
                                         distant-foreground ,background-blue))))
 `(powerline-inactive2 ((,class (:height 1.0 :foreground ,blue :background ,background-blue
                                         :distant-foreground ,background-blue))))

 `(dashboard-heading-face ((,class (:background ,background :foreground ,blue
                                                :bold t :height 1.2))))
 `(dashboard-banner-logo-title-face ((,class (:background ,background :foreground ,blue
                                                          :bold t :height 1.2))))
 `(widget-button ((,class (:background ,background :foreground ,default :bold nil
                                       :underline t :height 0.9))))

 ;; erc stuff
 `(erc-nick-default-face ((,class :foreground ,blue :background ,background :weight bold)))

 ;; org stuff
 `(outline-1 ((,class (:foreground ,blue :weight bold :height 1.8 :bold nil))))
 `(outline-2 ((,class (:foreground ,purple :weight bold :height 1.7 :bold nil))))
 `(outline-3 ((,class (:foreground ,peach :weight bold :height 1.6 :bold nil))))
 `(outline-4 ((,class (:foreground ,green-light :weight bold :height 1.5 :bold nil))))
 `(outline-5 ((,class (:foreground ,blue :weight bold :height 1.4 :bold nil))))
 `(outline-6 ((,class (:foreground ,purple :weight bold :height 1.3 :bold nil))))
 `(outline-7 ((,class (:foreground ,peach :weight bold :height 1.2 :bold nil))))
 `(outline-8 ((,class (:foreground ,green-light :weight bold :height 1.1 :bold nil))))

 `(org-block-begin-line ((,class (:background ,background-blue :foreground ,blue
                                              :bold t :height 1.0))))
 `(org-block-end-line ((,class (:background ,background-blue :foreground ,blue
                                            :bold t :height 1.0))))))

+END_SRC

** Looks *** Remove lame startup screen We use an actual replacement for it, keep reading or head directly to =dashboard=.

+BEGIN_SRC emacs-lisp

(setq inhibit-startup-message t)

+END_SRC

*** Disable menus and scrollbars If you like using any of those, change =-1= to =1=.

+BEGIN_SRC emacs-lisp

(tool-bar-mode -1) (menu-bar-mode -1) (scroll-bar-mode -1)

+END_SRC

*** Disable bell This is annoying, remove this line if you like being visually reminded of events.

+BEGIN_SRC emacs-lisp

(setq ring-bell-function 'ignore)

+END_SRC

*** Set UTF-8 encoding

+BEGIN_SRC emacs-lisp

(setq locale-coding-system 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-selection-coding-system 'utf-8) (prefer-coding-system 'utf-8)

+END_SRC

*** Highligh current line =hl-line= is awesome! It's not very awesome in the terminal version of emacs though, so we don't use that. Besides, it's only used for programming.

+BEGIN_SRC emacs-lisp

(when window-system (add-hook 'prog-mode-hook 'hl-line-mode))

+END_SRC

*** Pretty symbols Changes =lambda= to an actual symbol and a few others as well, only in the GUI version though.

+BEGIN_SRC emacs-lisp

(when window-system (use-package pretty-mode :ensure t :config (global-pretty-mode t)))

+END_SRC

** Functionality *** Disable backups and auto-saves I don't use either, you might want to turn those from =nil= to =t= if you do.

+BEGIN_SRC emacs-lisp

(setq make-backup-files nil) (setq auto-save-default nil)

+END_SRC

*** Change yes-or-no questions into y-or-n questions

+BEGIN_SRC emacs-lisp

(defalias 'yes-or-no-p 'y-or-n-p)

+END_SRC

*** Async Lets us use asynchronous processes wherever possible, pretty useful.

+BEGIN_SRC emacs-lisp

(use-package async :ensure t :init (dired-async-mode 1))

+END_SRC

** exwm The only time I actually had to use comments, this is for ease of removal if you happen to not like exwm. *** Installation

+BEGIN_SRC emacs-lisp

(use-package exwm :ensure t :config

  ;; necessary to configure exwm manually
  (require 'exwm-config)

  ;; fringe size, most people prefer 1 
  (fringe-mode 3)

  ;; emacs as a daemon, use "emacsclient <filename>" to seamlessly edit files from the terminal directly in the exwm instance
  (server-start)

  ;; this fixes issues with ido mode, if you use helm, get rid of it
  (exwm-config-ido)

  ;; a number between 1 and 9, exwm creates workspaces dynamically so I like starting out with 1
  (setq exwm-workspace-number 1)

  ;; this is a way to declare truly global/always working keybindings
  ;; this is a nifty way to go back from char mode to line mode without using the mouse
  (exwm-input-set-key (kbd "s-r") #'exwm-reset)
  (exwm-input-set-key (kbd "s-k") #'exwm-workspace-delete)
  (exwm-input-set-key (kbd "s-w") #'exwm-workspace-swap)

  ;; the next loop will bind s-<number> to switch to the corresponding workspace
  (dotimes (i 10)
    (exwm-input-set-key (kbd (format "s-%d" i))
                        `(lambda ()
                           (interactive)
                           (exwm-workspace-switch-create ,i))))

  ;; the simplest launcher, I keep it in only if dmenu eventually stopped working or something
  (exwm-input-set-key (kbd "s-&")
                      (lambda (command)
                        (interactive (list (read-shell-command "$ ")))
                        (start-process-shell-command command nil command)))

  ;; an easy way to make keybindings work *only* in line mode
  (push ?\C-q exwm-input-prefix-keys)
  (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)

  ;; simulation keys are keys that exwm will send to the exwm buffer upon inputting a key combination
  (exwm-input-set-simulation-keys
   '(
     ;; movement
     ([?\C-b] . left)
     ([?\M-b] . C-left)
     ([?\C-f] . right)
     ([?\M-f] . C-right)
     ([?\C-p] . up)
     ([?\C-n] . down)
     ([?\C-a] . home)
     ([?\C-e] . end)
     ([?\M-v] . prior)
     ([?\C-v] . next)
     ([?\C-d] . delete)
     ([?\C-k] . (S-end delete))
     ;; cut/paste
     ([?\C-w] . ?\C-x)
     ([?\M-w] . ?\C-c)
     ([?\C-y] . ?\C-v)
     ;; search
     ([?\C-s] . ?\C-f)))

  ;; this little bit will make sure that XF86 keys work in exwm buffers as well
  (dolist (k '(XF86AudioLowerVolume
             XF86AudioRaiseVolume
             XF86PowerOff
             XF86AudioMute
             XF86AudioPlay
             XF86AudioStop
             XF86AudioPrev
             XF86AudioNext
             XF86ScreenSaver
             XF68Back
             XF86Forward
             Scroll_Lock
             print))
  (cl-pushnew k exwm-input-prefix-keys))

  ;; this just enables exwm, it started automatically once everything is ready
  (exwm-enable))

+END_SRC

** Launchers Since I do not use a GUI launcher and do not have an external one like dmenu or rofi, I figured the best way to launch my most used applications would be direct emacsy keybindings.

*** dmenu for emacs Who would've thought this was available, together with ido-vertical it's a nice large menu with its own cache for most launched applications.

+BEGIN_SRC emacs-lisp

(use-package dmenu :ensure t :bind ("s-SPC" . 'dmenu))

+END_SRC

*** Functions to start processes I guess this goes without saying but you absolutely have to change the arguments to suit the software that you are using. What good is a launcher for discord if you don't use it at all.

+BEGIN_SRC emacs-lisp

(defun exwm-async-run (name) (interactive) (start-process name nil name))

(defun daedreth/launch-discord () (interactive) (exwm-async-run "discord"))

(defun daedreth/launch-browser () (interactive) (exwm-async-run "qutebrowser"))

(defun daedreth/lock-screen () (interactive) (exwm-async-run "slock"))

(defun daedreth/shutdown () (interactive) (start-process "halt" nil "sudo" "halt"))

+END_SRC

*** Keybindings to start processes These can be modified as well, suit yourself.

+BEGIN_SRC emacs-lisp

(global-set-key (kbd "s-d") 'daedreth/launch-discord) (global-set-key (kbd "") 'daedreth/launch-browser) (global-set-key (kbd "") 'daedreth/lock-screen) (global-set-key (kbd "") 'daedreth/shutdown)

+END_SRC

** Audio controls This is a set of bindings to my XF86 keys that invokes pulsemixer with the correct parameters

*** Volume modifier It goes without saying that you are free to modify the modifier as you see fit, 4 is good enough for me though.

+BEGIN_SRC emacs-lisp

(defconst volumeModifier "4")

+END_SRC

*** Functions to start processes

+BEGIN_SRC emacs-lisp

(defun audio/mute () (interactive) (start-process "audio-mute" nil "pulsemixer" "--toggle-mute"))

(defun audio/raise-volume () (interactive) (start-process "raise-volume" nil "pulsemixer" "--change-volume" (concat "+" volumeModifier)))

(defun audio/lower-volume () (interactive) (start-process "lower-volume" nil "pulsemixer" "--change-volume" (concat "-" volumeModifier)))

+END_SRC

*** Keybindings to start processes You can also change those if you'd like, but I highly recommend keeping 'em the same, chances are, they will just work.

+BEGIN_SRC emacs-lisp

(global-set-key (kbd "") 'audio/mute) (global-set-key (kbd "") 'audio/raise-volume) (global-set-key (kbd "") 'audio/lower-volume)

+END_SRC

** Screenshots I don't need scrot to take screenshots, or shutter or whatever tools you might have. This is enough. These won't work in the terminal version or the virtual console, obvious reasons.

*** Screenshotting the entire screen

+BEGIN_SRC emacs-lisp

(defun daedreth/take-screenshot () "Takes a fullscreen screenshot of the current workspace" (interactive) (when window-system (loop for i downfrom 3 to 1 do (progn (message (concat (number-to-string i) "...")) (sit-for 1))) (message "Cheese!") (sit-for 1) (start-process "screenshot" nil "import" "-window" "root" (concat (getenv "HOME") "/" (subseq (number-to-string (float-time)) 0 10) ".png")) (message "Screenshot taken!"))) (global-set-key (kbd "") 'daedreth/take-screenshot)

+END_SRC

*** Screenshotting a region

+BEGIN_SRC emacs-lisp

(defun daedreth/take-screenshot-region () "Takes a screenshot of a region selected by the user." (interactive) (when window-system (call-process "import" nil nil nil ".newScreen.png") (call-process "convert" nil nil nil ".newScreen.png" "-shave" "1x1" (concat (getenv "HOME") "/" (subseq (number-to-string (float-time)) 0 10) ".png")) (call-process "rm" nil nil nil ".newScreen.png"))) (global-set-key (kbd "") 'daedreth/take-screenshot-region)

+END_SRC

** Default browser I use qutebrowser, so that's what I'll set up.

+BEGIN_SRC emacs-lisp

(setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "qutebrowser")

+END_SRC

** Enable projectile globally This makes sure that everything can be a project.

+BEGIN_SRC emacs-lisp

(use-package projectile :ensure t :init (projectile-mode 1))

+END_SRC

** Let projectile call make

+BEGIN_SRC emacs-lisp

(global-set-key (kbd "") 'projectile-compile-project)

+END_SRC

Due to the fact that we attempt to use emacs as a desktop environment replacement, and external bar showing the time, the battery percentage and more system info would be great to have. I have however abandoned polybar in favor of a heavily modified modeline, this offers me more space on the screen and better integration.

One modeline-related setting that is missing and is instead placed at the bottom is =diminish=. ** Spaceline! I may not use spacemacs, since I do not like evil-mode and find spacemacs incredibly bloated and slow, however it would be stupid not to acknowledge the best parts about it, the theme and their modified powerline setup.

This enables spaceline, it looks better and works very well with my theme of choice.

+BEGIN_SRC emacs-lisp

(use-package spaceline :ensure t :config (require 'spaceline-config) (setq spaceline-buffer-encoding-abbrev-p nil) (setq spaceline-line-column-p nil) (setq spaceline-line-p nil) (setq powerline-default-separator (quote arrow)) (spaceline-spacemacs-theme))

+END_SRC

** No separator!

+BEGIN_SRC emacs-lisp

(setq powerline-default-separator nil)

+END_SRC

** Cursor position Show the current line and column for your cursor. We are not going to have =relative-linum-mode= in every major mode, so this is useful.

+BEGIN_SRC emacs-lisp

(setq line-number-mode t) (setq column-number-mode t)

+END_SRC

** Clock If you prefer the 12hr-format, change the variable to =nil= instead of =t=.

*** Time format

+BEGIN_SRC emacs-lisp

(setq display-time-24hr-format t) (setq display-time-format "%H:%M - %d %B %Y")

+END_SRC

*** Enabling the mode This turns on the clock globally.

+BEGIN_SRC emacs-lisp

(display-time-mode 1)

+END_SRC

** Battery indicator A package called =fancy-battery= will be used if we are in GUI emacs, otherwise the built in battery-mode will be used. Fancy battery has very odd colors if used in the tty, hence us disabling it.

+BEGIN_SRC emacs-lisp

(use-package fancy-battery :ensure t :config (setq fancy-battery-show-percentage t) (setq battery-update-interval 15) (if window-system (fancy-battery-mode) (display-battery-mode)))

+END_SRC

** System monitor A teeny-tiny system monitor that can be enabled or disabled at runtime, useful for checking performance with power-hungry processes in ansi-term

symon can be toggled on and off with =Super + h=.

+BEGIN_SRC emacs-lisp

(use-package symon :ensure t :bind ("s-h" . symon-mode))

+END_SRC

** Default shell should be bash I don't know why this is a thing, but asking me what shell to launch every single time I open a terminal makes me want to slap babies, this gets rid of it. This goes without saying but you can replace bash with your shell of choice.

+BEGIN_SRC emacs-lisp

(defvar my-term-shell "/bin/bash") (defadvice ansi-term (before force-bash) (interactive (list my-term-shell))) (ad-activate 'ansi-term)

+END_SRC

** Easy to remember keybinding In loving memory of bspwm, Super + Enter opens a new terminal, old habits die hard.

+BEGIN_SRC emacs-lisp

(global-set-key (kbd "") 'ansi-term)

+END_SRC

As a great emacs user once said:

+BEGIN_QUOTE

Do me the favor, do me the biggest favor, matter of fact do yourself the biggest favor and integrate those into your workflow.

+END_QUOTE

** a prerequisite for others packages

+BEGIN_SRC emacs-lisp

(use-package ivy :ensure t)

+END_SRC

** scrolling and why does the screen move I don't know to be honest, but this little bit of code makes scrolling with emacs a lot nicer.

+BEGIN_SRC emacs-lisp

(setq scroll-conservatively 100)

+END_SRC

** which-key and why I love emacs In order to use emacs, you don't need to know how to use emacs. It's self documenting, and coupled with this insanely useful package, it's even easier. In short, after you start the input of a command and stop, pondering what key must follow, it will automatically open a non-intrusive buffer at the bottom of the screen offering you suggestions for completing the command, that's it, nothing else.

It's beautiful

+BEGIN_SRC emacs-lisp

(use-package which-key :ensure t :config (which-key-mode))

+END_SRC

** windows,panes and why I hate other-window Some of us have large displays, others have tiny netbook screens, but regardless of your hardware you probably use more than 2 panes/windows at times, cycling through all of them with =C-c o= is annoying to say the least, it's a lot of keystrokes and takes time, time you could spend doing something more productive.

*** switch-window This magnificent package takes care of this issue. It's unnoticeable if you have <3 panes open, but with 3 or more, upon pressing =C-x o= you will notice how your buffers turn a solid color and each buffer is asigned a letter (the list below shows the letters, you can modify them to suit your liking), upon pressing a letter asigned to a window, your will be taken to said window, easy to remember, quick to use and most importantly, it annihilates a big issue I had with emacs. An alternative is =ace-window=, however by default it also changes the behaviour of =C-x o= even if only 2 windows are open, this is bad, it also works less well with =exwm= for some reason.

+BEGIN_SRC emacs-lisp

(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" "i" "o")) :bind ([remap other-window] . switch-window))

+END_SRC

*** Following window splits After you split a window, your focus remains in the previous one. This annoyed me so much I wrote these two, they take care of it.

+BEGIN_SRC emacs-lisp

(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)

+END_SRC

** swiper and why is the default search so lame I like me some searching, the default search is very meh. In emacs, you mostly use search to get around your buffer, much like with avy, but sometimes it doesn't hurt to search for entire words or mode, swiper makes sure this is more efficient.

+BEGIN_SRC emacs-lisp

(use-package swiper :ensure t :bind ("C-s" . 'swiper))

+END_SRC

** buffers and why I hate list-buffers Another big thing is, buffers. If you use emacs, you use buffers, everyone loves them. Having many buffers is useful, but can be tedious to work with, let us see how we can improve it.

*** Always murder current buffer Doing =C-x k= should kill the current buffer at all times, we have =ibuffer= for more sophisticated thing.

+BEGIN_SRC emacs-lisp

(defun kill-current-buffer () "Kills the current buffer." (interactive) (kill-buffer (current-buffer))) (global-set-key (kbd "C-x k") 'kill-current-buffer)

+END_SRC

*** Kill buffers without asking for confirmation Unless you have the muscle memory, I recommend omitting this bit, as you may lose progress for no reason when working.

+BEGIN_SRC emacs-lisp

(setq kill-buffer-query-functions (delq 'process-kill-buffer-query-function kill-buffer-query-functions))

+END_SRC

*** Turn switch-to-buffer into ibuffer I don't understand how ibuffer isn't the default option by now. It's vastly superior in terms of ergonomics and functionality, you can delete buffers, rename buffer, move buffers, organize buffers etc.

+BEGIN_SRC emacs-lisp

(global-set-key (kbd "C-x b") 'ibuffer)

+END_SRC

**** expert-mode If you feel like you know how ibuffer works and need not to be asked for confirmation after every serious command, enable this as follows.

+BEGIN_SRC emacs-lisp

(setq ibuffer-expert t)

+END_SRC

*** close-all-buffers It's one of those things where I genuinely have to wonder why there is no built in functionality for it. Once in a blue moon I need to kill all buffers, and having ~150 of them open would mean I'd need to spend a few too many seconds doing this than I'd like, here's a solution.

This can be invoked using =C-M-s-k=. This keybinding makes sure you don't hit it unless you really want to.

+BEGIN_SRC emacs-lisp

(defun close-all-buffers () "Kill all buffers without regard for their origin." (interactive) (mapc 'kill-buffer (buffer-list))) (global-set-key (kbd "C-M-s-k") 'close-all-buffers)

+END_SRC

** line numbers and programming Every now and then all of us feel the urge to be productive and write some code. In the event that this happens, the following bit of configuration makes sure that we have access to relative line numbering in programming-related modes. I highly recommend not enabling =linum-relative-mode= globally, as it messed up something like =ansi-term= for instance.

+BEGIN_SRC emacs-lisp

(use-package linum-relative :ensure t :config (setq linum-relative-current-symbol "") (add-hook 'prog-mode-hook 'linum-relative-mode))

+END_SRC

** ido and why I started using helm Sometimes, you don't realize how good something is until you try it extensively. I give in, helm is awesome. I'll end up customizing it more eventually, it's rather similar to ido-vertical though. *** helm

+BEGIN_SRC emacs-lisp

(use-package helm :ensure t :bind ("C-x C-f" . 'helm-find-files) ("C-x C-b" . 'helm-buffers-list) ("M-x" . 'helm-M-x) :config (defun daedreth/helm-hide-minibuffer () (when (with-helm-buffer helm-echo-input-in-header-line) (let ((ov (make-overlay (point-min) (point-max) nil nil t))) (overlay-put ov 'window (selected-window)) (overlay-put ov 'face (let ((bg-color (face-background 'default nil))) `(:background ,bg-color :foreground ,bg-color))) (setq-local cursor-type nil)))) (add-hook 'helm-minibuffer-set-up-hook 'daedreth/helm-hide-minibuffer) (setq helm-autoresize-max-height 0 helm-autoresize-min-height 40 helm-M-x-fuzzy-match t helm-buffers-fuzzy-matching t helm-recentf-fuzzy-match t helm-semantic-fuzzy-match t helm-imenu-fuzzy-match t helm-split-window-in-side-p nil helm-move-to-line-cycle-in-source nil helm-ff-search-library-in-sexp t helm-scroll-amount 8 helm-echo-input-in-header-line t) :init (helm-mode 1))

(require 'helm-config)
(helm-autoresize-mode 1) (define-key helm-find-files-map (kbd "C-b") 'helm-find-files-up-one-level) (define-key helm-find-files-map (kbd "C-f") 'helm-execute-persistent-action)

+END_SRC

** avy and why it's the best thing in existence Many times have I pondered how I can move around buffers even quicker. I'm glad to say, that avy is precisely what I needed, and it's precisely what you need as well. In short, as you invoke one of avy's functions, you will be prompted for a character that you'd like to jump to in the /visible portion of the current buffer/. Afterwards you will notice how all instances of said character have additional letter on top of them. Pressing those letters, that are next to your desired character will move your cursor over there. Admittedly, this sounds overly complicated and complex, but in reality takes a split second and improves your life tremendously.

I like =M-s= for it, same as =C-s= is for moving by searching string, now =M-s= is moving by searching characters.

+BEGIN_SRC emacs-lisp

(use-package avy :ensure t :bind ("M-s" . avy-goto-char))

+END_SRC

** Mark-Multiple I can barely contain my joy. This extension allows you to quickly mark the next occurence of a region and edit them all at once. Wow!

+BEGIN_SRC emacs-lisp

(use-package mark-multiple :ensure t :bind ("C-c q" . 'mark-next-like-this))

+END_SRC

** Improved kill-word Why on earth does a function called =kill-word= not .. kill a word. It instead deletes characters from your cursors position to the end of the word, let's make a quick fix and bind it properly.

+BEGIN_SRC emacs-lisp

(defun daedreth/kill-inner-word () "Kills the entire word your cursor is in. Equivalent to 'ciw' in vim." (interactive) (forward-char 1) (backward-word) (kill-word 1)) (global-set-key (kbd "C-c w k") 'daedreth/kill-inner-word)

+END_SRC

** Improved copy-word And again, the same as above but we make sure to not delete the source word.

+BEGIN_SRC emacs-lisp

(defun daedreth/copy-whole-word () (interactive) (save-excursion (forward-char 1) (backward-word) (kill-word 1) (yank))) (global-set-key (kbd "C-c w c") 'daedreth/copy-whole-word)

+END_SRC

** Copy a line Regardless of where your cursor is, this quickly copies a line.

+BEGIN_SRC emacs-lisp

(defun daedreth/copy-whole-line () "Copies a line without regard for cursor position." (interactive) (save-excursion (kill-new (buffer-substring (point-at-bol) (point-at-eol))))) (global-set-key (kbd "C-c l c") 'daedreth/copy-whole-line)

+END_SRC

** Kill a line And this quickly deletes a line.

+BEGIN_SRC emacs-lisp

(global-set-key (kbd "C-c l k") 'kill-whole-line)

+END_SRC

** Visiting the configuration Quickly edit =~/.emacs.d/config.org=

+BEGIN_SRC emacs-lisp

(defun config-visit () (interactive) (find-file "~/.emacs.d/config.org")) (global-set-key (kbd "C-c e") 'config-visit)

+END_SRC

** Reloading the configuration

Simply pressing =Control-c r= will reload this file, very handy. You can also manually invoke =config-reload=.

+BEGIN_SRC emacs-lisp

(defun config-reload () "Reloads ~/.emacs.d/config.org at runtime" (interactive) (org-babel-load-file (expand-file-name "~/.emacs.d/config.org"))) (global-set-key (kbd "C-c r") 'config-reload)

+END_SRC

** Subwords Emacs treats camelCase strings as a single word by default, this changes said behaviour.

+BEGIN_SRC emacs-lisp

(global-subword-mode 1)

+END_SRC

** Electric If you write any code, you may enjoy this. Typing the first character in a set of 2, completes the second one after your cursor. Opening a bracket? It's closed for you already. Quoting something? It's closed for you already.

You can easily add and remove pairs yourself, have a look.

+BEGIN_SRC emacs-lisp

(setq electric-pair-pairs '( (?{ . ?}) (?( . ?)) (?[ . ?]) (?\" . ?\") ))

+END_SRC

And now to enable it

+BEGIN_SRC emacs-lisp

(electric-pair-mode t)

+END_SRC

** Beacon While changing buffers or workspaces, the first thing you do is look for your cursor. Unless you know its position, you can not move it efficiently. Every time you change buffers, the current position of your cursor will be briefly highlighted now.

+BEGIN_SRC emacs-lisp

(use-package beacon :ensure t :config (beacon-mode 1))

+END_SRC

** Rainbow Mostly useful if you are into web development or game development. Every time emacs encounters a hexadecimal code that resembles a color, it will automatically highlight it in the appropriate color. This is a lot cooler than you may think.

+BEGIN_SRC emacs-lisp

(use-package rainbow-mode :ensure t :init (add-hook 'prog-mode-hook 'rainbow-mode))

+END_SRC

** Show parens I forgot about that initially, it highlights matching parens when the cursor is just behind one of them.

+BEGIN_SRC emacs-lisp

(show-paren-mode 1)

+END_SRC

** Rainbow delimiters Colors parentheses and other delimiters depending on their depth, useful for any language using them, especially lisp.

+BEGIN_SRC emacs-lisp

(use-package rainbow-delimiters :ensure t :init (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))

+END_SRC

** Expand region A pretty simple package, takes your cursor and semantically expands the region, so words, sentences, maybe the contents of some parentheses, it's awesome, try it out.

+BEGIN_SRC emacs-lisp

(use-package expand-region :ensure t :bind ("C-q" . er/expand-region))

+END_SRC

** Hungry deletion On the list of things I like doing, deleting big whitespaces is pretty close to the bottom. Backspace or Delete will get rid of all whitespace until the next non-whitespace character is encountered. You may not like it, thus disable it if you must, but it's pretty decent.

+BEGIN_SRC emacs-lisp

(use-package hungry-delete :ensure t :config (global-hungry-delete-mode))

+END_SRC

** Zapping to char A nifty little package that kills all text between your cursor and a selected character. A lot more useful than you might think. If you wish to include the selected character in the killed region, change =zzz-up-to-char= into =zzz-to-char=.

+BEGIN_SRC emacs-lisp

(use-package zzz-to-char :ensure t :bind ("M-z" . zzz-up-to-char))

+END_SRC

** popup-kill-ring Out of all the packages I tried out, this one, being the simplest, appealed to me most. With a simple M-y you can now browse your kill-ring like browsing autocompletion items. C-n and C-p totally work for this.

+BEGIN_SRC emacs-lisp

(use-package popup-kill-ring :ensure t :bind ("M-y" . popup-kill-ring))

+END_SRC

** yasnippet

+BEGIN_SRC emacs-lisp

(use-package yasnippet
  :ensure t
  :config
    (use-package yasnippet-snippets
      :ensure t)
    (yas-reload-all))

+END_SRC

** flycheck

+BEGIN_SRC emacs-lisp

(use-package flycheck :ensure t)

+END_SRC

** company mode I set the delay for company mode to kick in to half a second, I also make sure that it starts doing its magic after typing in only 2 characters.

I prefer =C-n= and =C-p= to move around the items, so I remap those accordingly.

+BEGIN_SRC emacs-lisp

(use-package company :ensure t :config (setq company-idle-delay 0) (setq company-minimum-prefix-length 3))

(with-eval-after-load 'company (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))

+END_SRC

** specific languages Be it for code or prose, completion is a must. After messing around with =auto-completion= and =company= for a while I decided to .. use both? AC is for Lua/LÖVE and Company for the rest.

Each category also has additional settings.

*** c/c++

+BEGIN_SRC emacs-lisp

(add-hook 'c++-mode-hook 'yas-minor-mode) (add-hook 'c-mode-hook 'yas-minor-mode)

(use-package flycheck-clang-analyzer :ensure t :config (with-eval-after-load 'flycheck (require 'flycheck-clang-analyzer) (flycheck-clang-analyzer-setup)))

(with-eval-after-load 'company (add-hook 'c++-mode-hook 'company-mode) (add-hook 'c-mode-hook 'company-mode))

(use-package company-c-headers :ensure t)

(use-package company-irony :ensure t :config (setq company-backends '((company-c-headers company-dabbrev-code company-irony))))

(use-package irony :ensure t :config (add-hook 'c++-mode-hook 'irony-mode) (add-hook 'c-mode-hook 'irony-mode) (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options))

+END_SRC

*** python

+BEGIN_SRC emacs-lisp

(add-hook 'python-mode-hook 'yas-minor-mode) (add-hook 'python-mode-hook 'flycheck-mode)

(with-eval-after-load 'company (add-hook 'python-mode-hook 'company-mode))

(use-package company-jedi :ensure t :config (require 'company) (add-to-list 'company-backends 'company-jedi))

(defun python-mode-company-init () (setq-local company-backends '((company-jedi company-etags company-dabbrev-code))))

(use-package company-jedi :ensure t :config (require 'company) (add-hook 'python-mode-hook 'python-mode-company-init))

+END_SRC

*** emacs-lisp

+BEGIN_SRC emacs-lisp

(add-hook 'emacs-lisp-mode-hook 'eldoc-mode) (add-hook 'emacs-lisp-mode-hook 'yas-minor-mode) (add-hook 'emacs-lisp-mode-hook 'company-mode)

(use-package slime :ensure t :config (setq inferior-lisp-program "/usr/bin/sbcl") (setq slime-contribs '(slime-fancy)))

(use-package slime-company :ensure t :init (require 'company) (slime-setup '(slime-fancy slime-company)))

+END_SRC

*** bash

+BEGIN_SRC emacs-lisp

(add-hook 'shell-mode-hook 'yas-minor-mode) (add-hook 'shell-mode-hook 'flycheck-mode) (add-hook 'shell-mode-hook 'company-mode)

(defun shell-mode-company-init () (setq-local company-backends '((company-shell company-shell-env company-etags company-dabbrev-code))))

(use-package company-shell :ensure t :config (require 'company) (add-hook 'shell-mode-hook 'shell-mode-company-init))

+END_SRC

*** lua/löve I must regrettably admit that =company= sucks with Lua/LÖVE. Which is also why I have =AC= now. I needed to do some shenanigans to get great auto-completion but here goes.

+BEGIN_SRC emacs-lisp

(add-hook 'lua-mode-hook 'yas-minor-mode) (add-hook 'lua-mode-hook 'flycheck-mode)

;;; this will download the necessary modules from git (let (value) (dolist (element '("love" "lua") value) (unless (file-directory-p (concatenate 'string (getenv "HOME") "/.emacs.d/auto-complete-" element)) (shell-command (format "git clone %s %s" (concatenate 'string "https://github.com/rolpereira/auto-complete-" element ".el") (concatenate 'string (getenv "HOME") "/.emacs.d/auto-complete-" element) nil))) (add-to-list 'load-path (expand-file-name (concatenate 'string "~/.emacs.d/auto-complete-" element)))))

(require 'auto-complete-love) (require 'auto-complete-lua)

;;; repl! (add-hook 'lua-mode-hook '(lambda () (local-set-key (kbd "C-c C-s") 'lua-show-process-buffer) (local-set-key (kbd "C-c C-h") 'lua-hide-process-buffer)))

;;; ac > company (use-package auto-complete :ensure t :config (setq ac-use-menu-map t) (setq ac-ignore-case nil) (define-key ac-menu-map "\C-n" 'ac-next) (define-key ac-menu-map "\C-p" 'ac-previous))

;;; this will be changed, it's good enough for now (add-hook 'lua-mode-hook '(lambda () (setq ac-sources '(ac-source-love ac-source-lua ac-source-abbrev ac-source-words-in-same-mode-buffers)) (auto-complete-mode)))

(add-hook 'lua-mode-hook 'auto-complete-mode)

;;; I don't even know all the functionality (use-package love-minor-mode :ensure t :config (add-hook 'lua-mode-hook 'love-minor-mode))

;;; behold, perfection :°) (global-set-key (kbd "") '(lambda () (interactive) (start-process "love-play-game" nil "love" default-directory)))

+END_SRC

** Editing with sudo Pretty self-explanatory, useful as hell if you use exwm.

+BEGIN_SRC emacs-lisp

(use-package sudo-edit :ensure t :bind ("s-e" . sudo-edit))

+END_SRC

Those are all rather self-explanatory.

** Common settings

+BEGIN_SRC emacs-lisp

(setq org-ellipsis " ") (setq org-src-fontify-natively t) (setq org-src-tab-acts-natively t) (setq org-confirm-babel-evaluate nil) (setq org-export-with-smart-quotes t) (setq org-src-window-setup 'current-window) (add-hook 'org-mode-hook 'org-indent-mode)

+END_SRC

** Syntax highlighting for documents exported to HTML

+BEGIN_SRC emacs-lisp

(use-package htmlize :ensure t)

+END_SRC

** Line wrapping

+BEGIN_SRC emacs-lisp

(add-hook 'org-mode-hook '(lambda () (visual-line-mode 1)))

+END_SRC

** Keybindings

+BEGIN_SRC emacs-lisp

(global-set-key (kbd "C-c '") 'org-edit-src-code)

+END_SRC

** Org Bullets Makes it all look a bit nicer, I hate looking at asterisks.

+BEGIN_SRC emacs-lisp

(use-package org-bullets :ensure t :config (add-hook 'org-mode-hook (lambda () (org-bullets-mode))))

+END_SRC

** Easy-to-add emacs-lisp template Hitting tab after an "<el" in an org-mode file will create a template for elisp insertion.

+BEGIN_SRC emacs-lisp

(add-to-list 'org-structure-template-alist '("el" "#+BEGIN_SRC emacs-lisp\n?\n#+END_SRC"))

+END_SRC

** Exporting options One of the best things about org is the ability to export your file to many formats. Here is how we add more of them!

*** latex

+BEGIN_SRC emacs-lisp

(when (file-directory-p "/usr/share/emacs/site-lisp/tex-utils") (add-to-list 'load-path "/usr/share/emacs/site-lisp/tex-utils") (require 'xdvi-search))

+END_SRC

*** Twitter Bootstrap

+BEGIN_SRC emacs-lisp

(use-package ox-twbs :ensure t)

+END_SRC

THIS WILL BE REMOVED SOON AS USE-PACKAGE HAS THE FUNCTIONALITY BUILT IN

Edit this list as you see fit!

+BEGIN_SRC emacs-lisp

(use-package diminish :ensure t :init (diminish 'which-key-mode) (diminish 'linum-relative-mode) (diminish 'hungry-delete-mode) (diminish 'visual-line-mode) (diminish 'subword-mode) (diminish 'beacon-mode) (diminish 'irony-mode) (diminish 'page-break-lines-mode) (diminish 'auto-revert-mode) (diminish 'rainbow-delimiters-mode) (diminish 'rainbow-mode) (diminish 'yas-minor-mode) (diminish 'flycheck-mode) (diminish 'helm-mode))

+END_SRC

** erc, also known as "a way to ask for help on #emacs" You might want to edit the default nick, it's password protected anyway so don't bother.

*** Some common settings This also hides some of the channel messages to avoid cluttering the buffer. The other line changes the prompt for each channel buffer to match the channel name, this way you always know who you are typing to.

+BEGIN_SRC emacs-lisp

(setq erc-nick "daedreth") (setq erc-prompt (lambda () (concat "[" (buffer-name) "]"))) (setq erc-hide-list '("JOIN" "PART" "QUIT"))

+END_SRC

*** Poor mans selectable server list What it says on the tin, this changes the =erc= history to include the server I connect to often.

+BEGIN_SRC emacs-lisp

(setq erc-server-history-list '("irc.freenode.net" "localhost"))

+END_SRC

*** Nick highlighting You can even highlight nicks to make the buffers a bit more visually pleasing and easier to look at.

+BEGIN_SRC emacs-lisp

(use-package erc-hl-nicks :ensure t :config (erc-update-modules))

+END_SRC

** rich presence for discord Memes, but it's fun and tiny.

+BEGIN_SRC emacs-lisp

(use-package elcord :ensure t)

+END_SRC

** EMMS with mpd There is many backends, many players and codecs for EMMS, we use mpd now.

*** Basic setup for mpd The non XF86 keys are made to be somewhat logical to follow and easy to remember. At the bottom part of the configuration, you will notice how XF86 keys are used by default, so unless you keyboard is broken it should work out of the box. Obviously you might have to adjust /server-name/ and /server-port/ to fit your configuration.

+BEGIN_SRC emacs-lisp

(use-package emms :ensure t :config (require 'emms-setup) (require 'emms-player-mpd) (emms-all) ; don't change this to values you see on stackoverflow questions if you expect emms to work (setq emms-seek-seconds 5) (setq emms-player-list '(emms-player-mpd)) (setq emms-info-functions '(emms-info-mpd)) (setq emms-player-mpd-server-name "localhost") (setq emms-player-mpd-server-port "6601") :bind ("s-m p" . emms) ("s-m b" . emms-smart-browse) ("s-m r" . emms-player-mpd-update-all-reset-cache) ("" . emms-previous) ("" . emms-next) ("" . emms-pause) ("" . emms-stop))

+END_SRC

* MPC Setup ** Setting the default port We use non-default settings for the socket, to use the built in =mpc= functionality we need to set up a variable. Adjust according to your setup.

+BEGIN_SRC emacs-lisp

(setq mpc-host "localhost:6601")

+END_SRC

* Some more fun stuff ** Starting the daemon from within emacs If you have an absolutely massive music library, it might be a good idea to get rid of =mpc-update= and only invoke it manually when needed.

+BEGIN_SRC emacs-lisp

(defun mpd/start-music-daemon () "Start MPD, connects to it and syncs the metadata cache." (interactive) (shell-command "mpd") (mpd/update-database) (emms-player-mpd-connect) (emms-cache-set-from-mpd-all) (message "MPD Started!")) (global-set-key (kbd "s-m c") 'mpd/start-music-daemon)

+END_SRC

**** Killing the daemon from within emacs

+BEGIN_SRC emacs-lisp

(defun mpd/kill-music-daemon () "Stops playback and kill the music daemon." (interactive) (emms-stop) (call-process "killall" nil nil nil "mpd") (message "MPD Killed!")) (global-set-key (kbd "s-m k") 'mpd/kill-music-daemon)

+END_SRC

**** Updating the database easily.

+BEGIN_SRC emacs-lisp

(defun mpd/update-database () "Updates the MPD database synchronously." (interactive) (call-process "mpc" nil nil nil "update") (message "MPD Database Updated!")) (global-set-key (kbd "s-m u") 'mpd/update-database)

+END_SRC