[[./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
=pip install jedi flake8 autopep8=, here, a one line install.
Some notes ** On use-package some more We utilize use-package to handle downloading and configuring other packages painlessly. With =init.el= written the way it is, emacs checks for the presence of =use-package= on launch and downloads it and installs if necessary. =el-Get= is too old and not configurable enough.
** 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.
(use-package zerodark-theme :ensure t :init (load-theme 'zerodark t))
** Some customization The theme is great, really, but some of the concepts just suck with powerline.
(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))))))
** Looks *** Remove lame startup screen We use an actual replacement for it, keep reading or head directly to =dashboard=.
(setq inhibit-startup-message t)
*** Disable menus and scrollbars If you like using any of those, change =-1= to =1=.
(tool-bar-mode -1) (menu-bar-mode -1) (scroll-bar-mode -1)
*** Disable bell This is annoying, remove this line if you like being visually reminded of events.
(setq ring-bell-function 'ignore)
*** Set UTF-8 encoding
(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)
*** 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.
(when window-system (add-hook 'prog-mode-hook 'hl-line-mode))
*** Pretty symbols Changes =lambda= to an actual symbol and a few others as well, only in the GUI version though.
(when window-system (use-package pretty-mode :ensure t :config (global-pretty-mode t)))
** Functionality *** Disable backups and auto-saves I don't use either, you might want to turn those from =nil= to =t= if you do.
(setq make-backup-files nil) (setq auto-save-default nil)
*** Change yes-or-no questions into y-or-n questions
(defalias 'yes-or-no-p 'y-or-n-p)
*** Async Lets us use asynchronous processes wherever possible, pretty useful.
(use-package async :ensure t :init (dired-async-mode 1))
** exwm The only time I actually had to use comments, this is for ease of removal if you happen to not like exwm. *** Installation
(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))
** 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.
(use-package dmenu :ensure t :bind ("s-SPC" . 'dmenu))
*** 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.
(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"))
*** Keybindings to start processes These can be modified as well, suit yourself.
(global-set-key (kbd "s-d") 'daedreth/launch-discord)
(global-set-key (kbd "
** 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.
(defconst volumeModifier "4")
*** Functions to start processes
(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)))
*** 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.
(global-set-key (kbd "
** 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
(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 "
*** Screenshotting a region
(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 "
** Default browser I use qutebrowser, so that's what I'll set up.
(setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "qutebrowser")
** Enable projectile globally This makes sure that everything can be a project.
(use-package projectile :ensure t :init (projectile-mode 1))
** Let projectile call make
(global-set-key (kbd "
Dashboard This is your new startup screen, together with projectile it works in unison and provides you with a quick look into your latest projects and files. Change the welcome message to whatever string you want and change the numbers to suit your liking, I find 5 to be enough.
(use-package dashboard :ensure t :config (dashboard-setup-startup-hook) (setq dashboard-startup-banner "~/.emacs.d/img/dashLogo.png") (setq dashboard-items '((recents . 5) (projects . 5))) (setq dashboard-banner-logo-title ""))
Modeline The modeline is the heart of emacs, it offers information at all times, it's persistent and verbose enough to gain a full understanding of modes and states you are in.
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.
(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))
** No separator!
(setq powerline-default-separator nil)
** 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.
(setq line-number-mode t) (setq column-number-mode t)
** Clock If you prefer the 12hr-format, change the variable to =nil= instead of =t=.
*** Time format
(setq display-time-24hr-format t) (setq display-time-format "%H:%M - %d %B %Y")
*** Enabling the mode This turns on the clock globally.
(display-time-mode 1)
** 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.
(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)))
** 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=.
(use-package symon :ensure t :bind ("s-h" . symon-mode))
File manager Abandoning sunrise-commander. The repos are dead and I'm looking for something better anyway.
The terminal I have used urxvt for years, and I miss it sometimes, but ansi-term is enough for most of my tasks.
** 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.
(defvar my-term-shell "/bin/bash") (defadvice ansi-term (before force-bash) (interactive (list my-term-shell))) (ad-activate 'ansi-term)
** Easy to remember keybinding In loving memory of bspwm, Super + Enter opens a new terminal, old habits die hard.
(global-set-key (kbd "
As a great emacs user once said:
Do me the favor, do me the biggest favor, matter of fact do yourself the biggest favor and integrate those into your workflow.
** a prerequisite for others packages
(use-package ivy :ensure t)
** 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.
(setq scroll-conservatively 100)
** 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
(use-package which-key :ensure t :config (which-key-mode))
** 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.
(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))
*** 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.
(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)
** 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.
(use-package swiper :ensure t :bind ("C-s" . 'swiper))
** 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.
(defun kill-current-buffer () "Kills the current buffer." (interactive) (kill-buffer (current-buffer))) (global-set-key (kbd "C-x k") 'kill-current-buffer)
*** 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.
(setq kill-buffer-query-functions (delq 'process-kill-buffer-query-function kill-buffer-query-functions))
*** 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.
(global-set-key (kbd "C-x b") 'ibuffer)
**** 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.
(setq ibuffer-expert t)
*** 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.
(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)
** 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.
(use-package linum-relative :ensure t :config (setq linum-relative-current-symbol "") (add-hook 'prog-mode-hook 'linum-relative-mode))
** 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
(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)
** 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.
(use-package avy :ensure t :bind ("M-s" . avy-goto-char))
** 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!
(use-package mark-multiple :ensure t :bind ("C-c q" . 'mark-next-like-this))
** 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.
(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)
** Improved copy-word And again, the same as above but we make sure to not delete the source word.
(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)
** Copy a line Regardless of where your cursor is, this quickly copies a line.
(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)
** Kill a line And this quickly deletes a line.
(global-set-key (kbd "C-c l k") 'kill-whole-line)
** Visiting the configuration Quickly edit =~/.emacs.d/config.org=
(defun config-visit () (interactive) (find-file "~/.emacs.d/config.org")) (global-set-key (kbd "C-c e") 'config-visit)
** Reloading the configuration
Simply pressing =Control-c r= will reload this file, very handy. You can also manually invoke =config-reload=.
(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)
** Subwords Emacs treats camelCase strings as a single word by default, this changes said behaviour.
(global-subword-mode 1)
** 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.
(setq electric-pair-pairs '( (?{ . ?}) (?( . ?)) (?[ . ?]) (?\" . ?\") ))
And now to enable it
(electric-pair-mode t)
** 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.
(use-package beacon :ensure t :config (beacon-mode 1))
** 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.
(use-package rainbow-mode :ensure t :init (add-hook 'prog-mode-hook 'rainbow-mode))
** Show parens I forgot about that initially, it highlights matching parens when the cursor is just behind one of them.
(show-paren-mode 1)
** Rainbow delimiters Colors parentheses and other delimiters depending on their depth, useful for any language using them, especially lisp.
(use-package rainbow-delimiters :ensure t :init (add-hook 'prog-mode-hook #'rainbow-delimiters-mode))
** 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.
(use-package expand-region :ensure t :bind ("C-q" . er/expand-region))
** 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.
(use-package hungry-delete :ensure t :config (global-hungry-delete-mode))
** 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=.
(use-package zzz-to-char :ensure t :bind ("M-z" . zzz-up-to-char))
(setq kill-ring-max 100)
** 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.
(use-package popup-kill-ring :ensure t :bind ("M-y" . popup-kill-ring))
** yasnippet
(use-package yasnippet
:ensure t
:config
(use-package yasnippet-snippets
:ensure t)
(yas-reload-all))
** flycheck
(use-package flycheck :ensure t)
** 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.
(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))
** 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++
(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))
*** python
(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))
*** 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)))
*** bash
(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))
*** 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.
(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 "
Git integration Countless are the times where I opened ansi-term to use =git= on something. These times are also something that I'd prefer stay in the past, since =magit= is great. It's easy and intuitive to use, shows its options at a keypress and much more. ** magit
(use-package magit :ensure t :config (setq magit-push-always-verify nil) (setq git-commit-summary-max-length 50) :bind ("M-g" . magit-status))
Remote editing I have no need to directly edit files over SSH, but what I do need is a way to edit files as root. Opening up nano in a terminal as root to play around with grubs default settings is a no-no, this solves that.
** Editing with sudo Pretty self-explanatory, useful as hell if you use exwm.
(use-package sudo-edit :ensure t :bind ("s-e" . sudo-edit))
Those are all rather self-explanatory.
** Common settings
(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)
** Syntax highlighting for documents exported to HTML
(use-package htmlize :ensure t)
** Line wrapping
(add-hook 'org-mode-hook '(lambda () (visual-line-mode 1)))
** Keybindings
(global-set-key (kbd "C-c '") 'org-edit-src-code)
** Org Bullets Makes it all look a bit nicer, I hate looking at asterisks.
(use-package org-bullets :ensure t :config (add-hook 'org-mode-hook (lambda () (org-bullets-mode))))
** Easy-to-add emacs-lisp template Hitting tab after an "<el" in an org-mode file will create a template for elisp insertion.
(add-to-list 'org-structure-template-alist '("el" "#+BEGIN_SRC emacs-lisp\n?\n#+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
(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))
*** Twitter Bootstrap
(use-package ox-twbs :ensure t)
THIS WILL BE REMOVED SOON AS USE-PACKAGE HAS THE FUNCTIONALITY BUILT IN
Edit this list as you see fit!
(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))
** 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.
(setq erc-nick "daedreth") (setq erc-prompt (lambda () (concat "[" (buffer-name) "]"))) (setq erc-hide-list '("JOIN" "PART" "QUIT"))
*** Poor mans selectable server list What it says on the tin, this changes the =erc= history to include the server I connect to often.
(setq erc-server-history-list '("irc.freenode.net" "localhost"))
*** Nick highlighting You can even highlight nicks to make the buffers a bit more visually pleasing and easier to look at.
(use-package erc-hl-nicks :ensure t :config (erc-update-modules))
** rich presence for discord Memes, but it's fun and tiny.
(use-package elcord :ensure t)
** 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.
(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)
("
* 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.
(setq mpc-host "localhost:6601")
* 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.
(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)
**** Killing the daemon from within emacs
(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)
**** Updating the database easily.
(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)