This is my Emacs configuration.
- Notes
- Inspiration
- Installation
- Packages
- Configuration Helpers
- Tweaking Defaults
- Additional Functionality
- Programming
- Keybindings
- User Interface
Some functions I should use more often:
- Use
evil-window
commands (e.g.C-w j
) - Use
C-c u
more often (counsel-imenu
). - Use
C-c p 5 f
to open a file in a new frame with projectile. - Use
``
to jump back and forth. - Use
m <letter>
to create markers` <letter>
to go to marker. - Use
C-i
(jump-forward
) andC-o
(jump-backward
). - The font-size can be adjusted buffer-locally with
C-x C-+
andC-x C--
.
Packages to check out:
- straight.el - Next-generation, purely functional package manager for the Emacs hacker.
- diff-hl or emacs-git-gutter - Highlighting uncommitted changes.
- company-tabnine - A company-mode backend for TabNine, the all-language autocompleter.
- magit forge - Work with Git forges from the comfort of Magit.
- aggressive-indent-mode - Emacs minor mode that keeps your code always indented. More reliable than electric-indent-mode.
- use-package - A use-package declaration for simplifying your .emacs.
Other things to check out and problems to deal with:
- Use project-specific exec-path. For example to use
eslint
from the project’s./node_modules/
and not from globally installed modules. - Check out this company-yasnippet setup
- Alain’s configuration
- Awesome-Emacs: A list of awesome Emacs packages
- Emacs.dz: A collection of Emacs configurations
- Yay-Evil distro by Ian Y.E. Pan
$ cd ~/git
$ git clone http://github.com/sirpscl/emacs.d
$ ln -s ~/git/emacs.d ~/.emacs.d
Some important and noteworthy dependencies:
After the first start, run the following commands.
(jedi:install-server)
Use the gnu
(official) and melpa
(unofficial) archives.
(require 'package)
(setq package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")))
(package-initialize)
Install packages on demand. This is cleaner and easier to keep tidy than defining a huge list of packages at the beginning of the configuration.
(defun ph/install-package (package)
"Install PACKAGE if not yet installed."
(unless (package-installed-p package)
(progn
(package-refresh-contents)
(package-install package))))
Update all packages with M-x auto-package-update-now
.
(ph/install-package 'auto-package-update)
(require 'auto-package-update)
(setq auto-package-update-interval 7)
To calculate the number of available updates, package-refresh-contents
needs
to be executed. Doing this periodically is annoying since it will block emacs. I
therefore use the following function to query the number of
auto-package-update-interval
since the last update for my status bar so that I
remember to update my packages regularly.
(defun ph/update-intervals-since-last-update ()
"Return the number of auto-update-package-intervals since the
last update."
(when (file-exists-p auto-package-update-last-update-day-path)
(/ (- (apu--today-day) (apu--read-last-update-day))
auto-package-update-interval)))
General provides a more convenient method for binding keys in emacs (for both evil and non-evil users).
(ph/install-package 'general)
Other Helpers:
(defun ph/call-rotate (fn lst)
"Call FN with first element of the LST.
Returns the rotated list."
(let ((args (car lst)))
(funcall fn args)
(append (cdr lst) (cons args ()))))
This section contains customizations of Emacs’ default settings and built-in packages configuration and extensions.
Enable all disabled commands.
(setq disabled-command-function nil)
For reasons of simplicity.
(defalias 'yes-or-no-p 'y-or-n-p)
Always Follow Symlinks, no questions asked.
(setq vc-follow-symlinks t)
Show line numbers in all text and programming buffers.
(add-hook 'text-mode-hook 'display-line-numbers-mode)
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
Count the number of lines to use for line number width.
(setq display-line-numbers-width-start t)
Automatically add a newline at the end of a file.
(setq require-final-newline t)
No backups, commit frequently!
(setq make-backup-files nil)
Store auto-saves in /tmp
(setq auto-save-file-name-transforms
`((".*" ,temporary-file-directory t)))
Show my keystrokes almost immediately in the echo-area.
(setq echo-keystrokes 0.1)
When scrolling, keep the cursor at the same position.
(setq scroll-preserve-screen-position 'keep)
When something changes a file, automatically refresh the buffer containing that file so they can’t get out of sync.
(global-auto-revert-mode t)
Update vc-info when reverting (e.g. after changing branch). Note that this may cause performance issues when many buffers are present.
(setq auto-revert-check-vc-info t)
Collect garbage after 20MB. Some packages which cache a lot (e.g. flx-ido
)
will profit.
(setq gc-cons-threshold (* 20 1000 1000))
Use Firefox to browse URLs.
(setq browse-url-browser-function 'browse-url-generic
browse-url-generic-program "firefox"
browse-url-generic-args '("--private-window")
browse-url-new-window-flag t)
Use a line width of 80 columns.
(setq-default fill-column 80)
To reorganize a paragraph to fit the 80 columns, use M-q
(M-x
fill-paragraph
) and/or enable auto-fill-mode
.
Don’t do double-spaces between sentences.
(setq-default sentence-end-double-space nil)
To undo paragraph and region reorganization. Stolen from here.
(defun ph/unfill-paragraph (&optional region)
"Takes a multi-line paragraph and makes it into a single line
of text."
(interactive (progn (barf-if-buffer-read-only) '(t)))
(let ((fill-column (point-max))
;; This would override `fill-column' if it's an integer.
(emacs-lisp-docstring-fill-column t))
(fill-paragraph nil region)))
Delete trailing whitespaces when saving.
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
Split functions which open the previous buffer in the new window instead of showing the current buffer twice. Stolen shamelessly from here
(defun ph/vsplit-last-buffer ()
(interactive)
(split-window-vertically)
(other-window 1 nil)
(switch-to-next-buffer))
(defun ph/hsplit-last-buffer ()
(interactive)
(split-window-horizontally)
(other-window 1 nil)
(switch-to-next-buffer))
A function to open the previous buffer in a new frame.
(defun ph/open-last-buffer ()
(interactive)
(switch-to-buffer-other-frame (other-buffer)))
Ido (“interactively do things”) supercharges Emacs’ completion system. I use
ido
everywhere ivy
is not set up.
(ido-mode 1)
(ido-everywhere 1)
Enable the built-in fuzzy-matching
(setq ido-enable-flex-matching t)
ido-vertical-mode makes ido-mode display vertically.
(ph/install-package 'ido-vertical-mode)
(ido-vertical-mode 1)
(setq ido-vertical-define-keys 'C-n-and-C-p-only)
(setq ido-vertical-show-count t)
If the current buffer is not writable, ask if it should be saved with sudo.
(defun ph/sudo-file-name (filename)
"Prepend '/sudo:root@`system-name`:' to FILENAME if appropriate.
If the file already has a tramp prefix, return nil."
(when (and filename
(not (file-remote-p filename)))
(format "/sudo:root@%s:%s" (system-name) filename)))
(defun ph/sudo-save-buffer ()
"Save buffer as root if the user approves."
(let ((filename (ph/sudo-file-name (buffer-file-name))))
(when (and filename
(yes-or-no-p (format "Save file as %s ? " filename)))
(write-file filename))))
(advice-add 'save-buffer :around
'(lambda (fn &rest args)
(when (or (not (buffer-file-name))
(not (buffer-modified-p))
(file-writable-p (buffer-file-name))
(not (ph/sudo-save-buffer)))
(call-interactively fn args))))
Flyspell enables on-the-fly spell checking in Emacs by the means of a minor mode. Flyspell highlights incorrect words as soon as they are completed or as soon as the TextCursor hits a new word.
Flyspell-Correct offers distraction-free words correction with flyspell via selected interface.
(ph/install-package 'flyspell-correct-ivy)
(setq flyspell-correct-interface #'flyspell-correct-ivy)
Use Hunspell instead of Aspell.
(setq ispell-program-name "hunspell")
Rotate through Ispell languages
(setq ph/ispell-dictionaries-list '("en_US" "de_CH"))
(defun ph/ispell-next-dictionary ()
"Load next Ispell dictionary."
(interactive)
(setq ph/ispell-dictionaries-list
(ph/call-rotate 'ispell-change-dictionary
ph/ispell-dictionaries-list)))
(add-hook 'after-init-hook 'ph/ispell-next-dictionary)
Occur-Mode is a search minor-mode that shows a buffer with all matching results in a popup buffer. Use the occur-dwim (do what I mean) function from (or emacs irrelevant)
(defun ph/occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(let ((sym (thing-at-point 'symbol)))
(when (stringp sym)
(regexp-quote sym))))
regexp-history)
(call-interactively 'occur))
Usage:
a
to open a file or directory in the current bufferRET
to open a file or directory in a new buffero
to open a file or directory in a vertical split bufferC-o
to open a file or directory in a vertical split buffer but keep the focus in the current buffer.C-c C-o
to open a file or directory in a new frame.
Reuse buffer
(put 'dired-find-alternate-file 'disabled nil)
Show all files, in long listing format and human readable units.
(setq-default dired-listing-switches "-lh")
Open in new frame
(defun ph/dired-find-file-other-frame ()
"In Dired, visit this file or directory in another window."
(interactive)
(find-file-other-frame (dired-get-file-for-visit)))
(eval-after-load "dired"
'(define-key dired-mode-map (kbd "C-c C-o") 'ph/dired-find-file-other-frame))
Org-Mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.
(require 'org)
Automatically fill lines
(add-hook 'org-mode-hook 'auto-fill-mode)
Don’t ask every time when executing a code block.
(setq org-confirm-babel-evaluate nil)
Don’t indent code blocks
(setq org-edit-src-content-indentation 0)
No empty lines between items
(setq org-blank-before-new-entry
'((heading . nil)
(plain-list-item . nil)))
Every time you’ll be saving an org file, the first headline with a :TOC:
tag
will be updated with the current table of contents.
:TOC_2:
- sets the max depth of the headlines in the table of contents to 2 (the default):TOC_2_gh:
- sets the max depth as in above and also uses the GitHub-style hrefs in the table of contents (this style is default). The other supported href style is ‘org’, which is the default org style.
(ph/install-package 'toc-org)
(add-hook 'org-mode-hook 'toc-org-enable)
Kill all but the current buffer. Stolen shamelessly from here.
(defun ph/kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer (delq (current-buffer) (buffer-list))))
This section contains some third party packages and additional functionality.
Ace-window aims to take the speed and predictability of windmove
and pack it
into a single key binding, similar to other-window
.
(ph/install-package 'ace-window)
Use the following characters/keys to switch to the windows
(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
Set the ace-window-scope to frame
because I often have multiple frames opened
on other workspaces and only want to jump to other windows in the current frame.
(setq aw-scope 'frame)
Smex is a M-x enhancement for Emacs. Built on top of Ido, it provides a convenient interface to your recently and most frequently used commands. And to all the other commands, too.
(ph/install-package 'smex)
(ph/install-package 'browse-kill-ring)
(setq browse-kill-ring-highlight-inserted-item t
browse-kill-ring-highlight-current-entry nil
browse-kill-ring-show-preview t)
(general-def browse-kill-ring-mode-map
"k" 'browse-kill-ring-previous
"j" 'browse-kill-ring-forward)
A Collection of Ridiculously Useful eXtensions for Emacs. crux bundles a few useful interactive commands to enhance your overall Emacs experience.
(ph/install-package 'crux)
(ph/install-package 'dockerfile-mode)
Ag allows you to search using ag from inside Emacs. You can filter by file type, edit results inline, or find files.
(ph/install-package 'ag)
Ripgrep (rg) is a replacement for both grep like (search one file) and ag like (search many files) tools. It’s fast and versatile and written in Rust.
(ph/install-package 'rg)
Evil is an extensible vi layer for Emacs. It emulates the main features of Vim, and provides facilities for writing custom extensions.
(ph/install-package 'evil)
(require 'evil)
(evil-mode 1)
Set initial state by major mode.
(dolist (mode-map '((ag-mode . emacs)
(calendar-mode . emacs)
(elfeed-show-mode . emacs)
(elfeed-search-mode . emacs)
(eshell-mode . emacs)
(flycheck-error-list-mode . emacs)
(git-commit-mode . insert)
(git-rebase-mode . emacs)
(haskell-error-mode . emacs)
(haskell-interactive-mode . emacs)
(help-mode . emacs)
(inferior-ess-mode . emacs)
(inf-ruby-mode . emacs)
(intero-repl-mode . emacs)
(pdf-occur-buffer-mode . emacs)
(rspec-compilation-mode . emacs)
(shell-mode . emacs)
(term-mode . emacs)))
(evil-set-initial-state `,(car mode-map) `,(cdr mode-map)))
- Add surrounding
'
withS'
from visual-state (useviw
to mark current word) - Change surrounding
'
to*
withcs'*
- Remove surrounding
*
withds*
(ph/install-package 'evil-surround)
(global-evil-surround-mode 1)
Free M-.
and M-,
since they are popular keybindings for “jump to definition”
and “back”. Also I don’t use evil-complete
.
(general-def 'normal
"M-." nil
"M-," nil)
(general-def 'insert
"C-p" nil
"C-n" nil)
Evil Goddess makes it possible for evil users to conveniently access Emacs keybindings without touching the control and meta key - similar to god-mode.
In order not to loose (hard-coded) which-key support, it is called god-mode
and thus conflicts with the original god-mode
.
See evil-goddess/README.md for more details.
(add-to-list 'load-path "~/.emacs.d/evil-goddess/")
(require 'god-mode)
Which-Key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup.
(ph/install-package 'which-key)
(which-key-mode)
;; (use-package which-key
;; :bind (("C-' k" . which-key-mode)
;; ("C-' C-k" . which-key-mode))
;; :init
;; (which-key-setup-side-window-bottom)
;; (which-key-enable-god-mode-support)
;; ;; ...
;; (which-key-mode t))
Also use which-key evil and god-mode shortcuts.
(setq which-key-allow-evil-operators t)
(setq which-key-show-operator-state-maps t)
Show command names up to 40 columns before cutting them.
(setq which-key-max-description-length 25)
Show which-key after .4 seconds inactivity
(setq which-key-idle-delay 0.4)
(which-key-setup-side-window-bottom)
(which-key-enable-god-mode-support)
(which-key-enable-god-mode-support)
Projectile is a project interaction library for Emacs. Its goal is to provide a nice set of features operating on a project level without introducing external dependencies (when feasible).
(ph/install-package 'projectile)
(projectile-mode +1)
(general-def projectile-mode-map
"C-c p" 'projectile-command-map)
(setq projectile-completion-system 'ivy)
Ivy, Counsel (and Swiper), a collection of Ivy-enhanced versions of common Emacs commands.
- Ivy is a generic completion mechanism for Emacs.
- Counsel is a collection of Ivy-enhanced versions of common Emacs commands.
- Swiper is an Ivy-enhanced alternative to isearch.
Installing counsel
will also install the other two as dependencies.
(ph/install-package 'counsel)
(require 'swiper)
Use ivy
for completion instead of ido
.
(ivy-mode 1)
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t)
Some packages need special attention.
(setq magit-completing-read-function 'ivy-completing-read)
(setq projectile-completion-system 'ivy)
(setq mu4e-completing-read-function 'ivy-completing-read)
Show current entry number.
(setq ivy-count-format " %d/%d ")
Prevent swiper from swiping itself.
(defun ph/swiper-from-isearch ()
(interactive)
(unless (string= (symbol-name major-mode) "minibuffer-inactive-mode")
(swiper-from-isearch)))
Pdf-Tools is, among other things, a replacement of DocView for PDF files. The key difference is that pages are not pre-rendered by e.g. ghostscript and stored in the file-system, but rather created on-demand and stored in memory.
(ph/install-package 'pdf-tools)
(require 'pdf-tools)
(pdf-tools-install-noverify)
When highlighting, automatically add an annotation.
(setq pdf-annot-activate-created-annotations t)
Zoom by 10%.
(setq pdf-view-resize-factor 1.1)
Keybindings:
C-c C-a h
to highlight textC-c C-a o
to strike though textC-c C-a t
to add a noteC-c C-a D
to delete one of the aboveC-c C-a l
to list all annotations. UseSPACE
to jump to the annotation.- and more
Open File in External App. Stolen shamelessly from here.
(defun ph/xdg-open (&optional @fname)
"Open the current file or dired marked files in external app.
The app is chosen from your OS's preference.
When called in emacs lisp, if @fname is given, open that.
URL `http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html'
Version 2019-01-18"
(interactive)
(let* (
($file-list
(if @fname
(progn (list @fname))
(if (string-equal major-mode "dired-mode")
(dired-get-marked-files)
(list (buffer-file-name)))))
($do-it-p (if (<= (length $file-list) 5)
t
(y-or-n-p "Open more than 5 files? "))))
(when $do-it-p
(cond
((string-equal system-type "windows-nt")
(mapc
(lambda ($fpath)
(w32-shell-execute "open" (replace-regexp-in-string "/" "\\" $fpath t t))) $file-list))
((string-equal system-type "darwin")
(mapc
(lambda ($fpath)
(shell-command
(concat "open " (shell-quote-argument $fpath)))) $file-list))
((string-equal system-type "gnu/linux")
(mapc
(lambda ($fpath) (let ((process-connection-type nil))
(start-process "" nil "xdg-open" $fpath))) $file-list))))))
Mu4e is an emacs-based e-mail client. It’s based on the mu e-mail indexer/searcher. It attempts to be a super-efficient tool to withstand the daily e-mail tsunami.
(require 'mu4e)
(require 'mu4e-contrib)
(ph/install-package 'smtpmail)
Mail directory
(setq mu4e-maildir "~/.mail")
Save attachments in ~/Downloads/
.
(setq mu4e-attachment-dir "~/Downloads")
Close mu4e without asking.
(setq mu4e-confirm-quit nil)
Open mu4e in the current frame or switch to an already existing mu4e-buffer.
(defun ph/mu4e ()
"Open or switch to mu4e."
(interactive)
(unless (string-prefix-p "mu4e" (symbol-name major-mode))
(let ((buffer (get-buffer "*mu4e-headers*")))
(if buffer (switch-to-buffer buffer) (mu4e)))))
Hide addresses on main view
(setq mu4e-main-buffer-hide-personal-addresses t)
Hide the annoying indexing message.
(setq mu4e-hide-index-messages t)
Update every 10 minutes
(setq mu4e-get-mail-command "offlineimap")
(setq mu4e-update-interval (* 10 60))
For some reason the first two cited faces are equal by default. Let’s fix this.
(set-face-attribute 'mu4e-cited-2-face nil
:foreground "#5fafd7")
Custom date and time format.
(setq mu4e-headers-time-format "today %H:%M")
(setq mu4e-headers-date-format "%d.%m.%y %H:%M")
Do not show related messages by default (toggle with W
)
(setq mu4e-headers-include-related nil)
Don’t show duplicate messages.
(setq mu4e-headers-skip-duplicates t)
Add default search values for mu4e-headers-search
unless arguments are given
to mu4e-headers-search
or the search is not called from within a mu4e-buffer.
The values are set in the context definition (ph/mu4e-default-search-expr
).
(advice-add 'mu4e-headers-search :around
(lambda (fn &rest args)
(if (and (= 0 (length args))
(string-prefix-p "mu4e" (symbol-name major-mode))
(< 0 (length ph/mu4e-default-search-expr)))
(apply fn (list (concat ph/mu4e-default-search-expr " ")
"Search for: " t))
(apply fn args))))
Some functions to get some additional information about emails. Stolen shamelessly from here
(defun ph/mu4e-get-user-agent (msg)
(let ((path (or (mu4e-message-field msg :path) "")))
(if (or (string= path "")
(not (file-readable-p path)))
"no path found"
(let ((xmailer (ph/mu4e-get-mail-header "x-mailer" path))
(useragent (ph/mu4e-get-mail-header "user-agent" path)))
(if (string= xmailer useragent)
xmailer
(cond
((string= xmailer "") useragent)
((string= useragent "") xmailer)
(t (concat xmailer " (xmailer)\n" useragent " (user-agent)"))))))))
(defun ph/mu4e-get-mail-header (header-name path)
(replace-regexp-in-string
"[ \t\n]*$"
""
(shell-command-to-string
(concat "/usr/bin/sed -n '/^" header-name
":/I{:loop t;h;n;/^ /{H;x;s/\\n//;t loop};x;p}' '" path
"' | sed -n 's/^" header-name
": \\(.*\\)$/\\1/Ip'"))))
(add-to-list 'mu4e-header-info-custom
'(:useragent . (:name "User-Agent"
:shortname "UserAgt."
:help "Mail client used by correspondant"
:function ph/mu4e-get-user-agent)))
Set the fields displayed in mu4e-headers-mode
and mu4e-view-mode
.
(setq mu4e-headers-fields
'((:flags . 4)
(:human-date . 15)
(:from . 25)
(:subject)))
Ask before I delete something permanently or set the trash flag. I just move messages to the trash folder to “delete” them.
(defun ph/do-or-dont-execute (fn &rest args)
"Execute FN (with ARGS) iff I confirm."
(when (y-or-n-p "Are you sure? ")
(apply fn args)))
(advice-add 'mu4e-headers-mark-for-delete
:around 'ph/do-or-dont-execute)
(advice-add 'mu4e-view-mark-for-delete
:around 'ph/do-or-dont-execute)
(advice-add 'mu4e-headers-mark-for-trash
:around 'ph/do-or-dont-execute)
(advice-add 'mu4e-view-mark-for-trash
:around 'ph/do-or-dont-execute)
Show the useragent
and bcc
.
(setq mu4e-view-fields
'(:from
:to
:cc
:bcc
:subject
:flags
:date
:maildir
:mailing-list
:tags
:signature
:decryption
:useragent
:attachments))
Show me the addresses, not only names.
(setq mu4e-view-show-addresses t)
View html-mail in browser with aV
.
(add-to-list 'mu4e-view-actions
'("ViewInBrowser" . mu4e-action-view-in-browser) t)
Custom Bookmarks
(add-to-list 'mu4e-bookmarks
(make-mu4e-bookmark
:name "Big ones"
:query "size:5M..50000M"
:key ?b))
(add-to-list 'mu4e-bookmarks
(make-mu4e-bookmark
:name "Bullshit"
:query "maildir:/.*/.*\\(spam\\|junk\\).*/"
:key ?s))
Enabling receiving clients that support this feature to reflow my paragraphs.
Plain text emails with Content-Type: text/plain; format=flowed
can be reflowed
(i.e. line endings removed, paragraphs refilled) by receiving clients that
support this standard. Clients that don’t support this, show them as is, which
means this feature is truly non-invasive.
(setq mu4e-compose-format-flowed t)
Dont reply to myself.
(setq mu4e-compose-dont-reply-to-self t)
Kill message-buffer when finished.
(setq message-kill-buffer-on-exit t)
Add formatted citation line.
(setq message-citation-line-function
'message-insert-formatted-citation-line)
Use smtpmail
with gnutls
to sending mails.
(setq message-send-mail-function 'smtpmail-send-it)
(setq starttls-use-gnutls t)
(setq smtpmail-debug-info t)
Before sending a message, check if it contains any words that indicate that there should be an attachement. If it does, ask if all attachments were added before sending the mail.
(defvar ph/message-attachment-regexp
(concat "\\("
"[Ww]e send\\|"
"[Ii] send\\|"
"attach\\|"
"[aA]nhang\\|"
"[aA]ngehängt\\|"
"[sS]chicke\\|"
"haenge\\|"
"hänge\\)"))
(defun ph/message-check-attachment nil
"Check for forgotten attachments"
(save-excursion
(message-goto-body)
(when (search-forward-regexp ph/message-attachment-regexp nil t nil)
(message-goto-body)
(unless (message-y-or-n-p
"Did you attach all documents?" nil nil)
(error "No message sent, add some attachments!")))))
(add-hook 'message-send-hook 'ph/message-check-attachment)
Pick first Context as default.
(setq mu4e-context-policy 'pick-first)
(setq mu4e-compose-context-policy 'ask-if-none)
(setq mu4e-contexts
`(,(make-mu4e-context
:name "Private"
:match-func (lambda (msg)
(when msg
(or
(mu4e-message-contact-field-matches
msg
:to "[email protected]")
(mu4e-message-contact-field-matches
msg
:to "[email protected]"))))
:vars '((user-full-name . "Pascal Huber" )
(user-mail-address . "[email protected]")
(mu4e-get-mail-command . "offlineimap")
(mu4e-drafts-folder . "/r/Drafts")
(mu4e-sent-folder . "/r/Sent")
(mu4e-trash-folder . "/r/Trash")
(mu4e-maildir-shortcuts
.( ("/r/INBOX" . ?i)
("/r/Sent" . ?s)
("/r/Spam" . ?x)
("/r/keep" . ?k)
("/r/tempKeep" . ?t)
("/r/Trash" . ?b)))
(mu4e-compose-crypto-reply-plain-policy . sign)
(ph/mu4e-default-search-expr . "maildir:/r/.*[^Trash]/")
(mu4e-sent-messages-behavior . sent)
(smtpmail-stream-type . starttls)
(smtpmail-default-smtp-server . "mail.infomaniak.com")
(smtpmail-smtp-server . "mail.infomaniak.com")
(smtpmail-smtp-service . 587)
(smtpmail-smtp-user . "[email protected]")
(smtpmail-starttls-credentials . "/home/pascal/.authinfo.gpg")
(smtpmail-auth-credentials . '(("mail.resolved.ch" 587 nil nil)))))
,(make-mu4e-context
:name "QuickShift"
:match-func (lambda (msg)
(when msg
(mu4e-message-contact-field-matches
msg
:to "[email protected]")))
:vars '((user-full-name . "Pascal Huber" )
(user-mail-address . "[email protected]")
(mu4e-get-mail-command . "offlineimap")
(mu4e-drafts-folder . "/q/INBOX.Drafts")
(mu4e-sent-folder . "/q/INBOX.Sent")
(mu4e-trash-folder . "/q/INBOX.Trash")
(mu4e-maildir-shortcuts
.( ("/q/INBOX" . ?i)
("/q/INBOX.Sent" . ?s)
("/q/INBOX.spambucket" . ?x)
("/q/INBOX.keep" . ?k)
("/q/INBOX.live" . ?l)
("/q/INBOX.customers" . ?c)
("/q/INBOX.tempKeep" . ?k)
("/q/INBOX.bugsnag" . ?e)
("/q/INBOX.Trash" . ?b)))
(mu4e-compose-crypto-reply-plain-policy . sign)
(ph/mu4e-default-search-expr . "maildir:/q/.*[^Trash]/")
(mu4e-sent-messages-behavior . sent)
(smtpmail-stream-type . starttls)
(smtpmail-default-smtp-server . "mail.quickshift.ch")
(smtpmail-smtp-server . "mail.quickshift.ch")
(smtpmail-smtp-service . 587)
(smtpmail-smtp-user . "[email protected]")
(smtpmail-starttls-credentials . "/home/pascal/.authinfo.gpg")
(smtpmail-auth-credentials . '(("mail.quickshift.ch" 587 nil nil)))))
,(make-mu4e-context
:name "ETH"
:match-func (lambda (msg)
(when msg
(mu4e-message-contact-field-matches
msg
:to "[email protected]")))
:vars '((user-full-name . "Pascal Huber" )
(user-mail-address . "[email protected]")
(mu4e-get-mail-command . "offlineimap")
(mu4e-drafts-folder . "/e/Drafts")
(mu4e-sent-folder . "/e/Sent Items")
(mu4e-trash-folder . "/e/Deleted Items")
(mu4e-maildir-shortcuts
.( ("/e/INBOX" . ?i)
("/e/Junk E-Mail" . ?x)
("/e/INBOX.keep" . ?k)
("/e/INBOX.asl" . ?a)
("/e/INBOX.iml" . ?m)
("/e/INBOX.negotiation" . ?n)
("/e/INBOX.podc" . ?p)
("/e/Sent Items" . ?s)
("/e/INBOX.tmp" . ?t)
("/e/Deleted Items" . ?b)))
(mu4e-compose-crypto-reply-plain-policy . sign)
(ph/mu4e-default-search-expr . "maildir:/e/.*[^Deleted\\ Items]/")
(mu4e-sent-messages-behavior . sent)
(smtpmail-stream-type . starttls)
(smtpmail-default-smtp-server . "mail.ethz.ch")
(smtpmail-smtp-server . "mail.ethz.ch")
(smtpmail-smtp-service . 587)
(smtpmail-smtp-user . "pahuber")
(smtpmail-starttls-credentials . "/home/pascal/.authinfo.gpg")
(smtpmail-auth-credentials . '(("mail.ethz.ch" 587 nil nil)))))))
This section contains programming packages and settings.
Company is a text completion framework for Emacs. The name stands for “complete anything”. It uses pluggable back-ends and front-ends to retrieve and display completion candidates.
(ph/install-package 'company)
(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
Automatically show completion after 1 character.
(setq company-minimum-prefix-length 1)
Don’t require a match to continue typing.
(setq company-require-match nil)
Switch between suggestions with C-n
and C-p
.
(general-def company-active-map
"C-n" 'company-select-next
"C-p" 'company-select-previous)
(general-def company-search-map
"C-n" 'company-select-next
"C-p" 'company-select-previous)
Rainbow-Delimiters makes brackets colorful.
(ph/install-package 'rainbow-delimiters)
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
Highlight matching brackets.
(setq show-paren-style 'mixed)
(add-hook 'prog-mode-hook 'show-paren-mode)
Dumb-Jump is an Emacs “jump to definition” package with support for multiple programming languages that favors “just working”. This means minimal – and ideally zero – configuration with absolutely no stored indexes (TAGS) or persistent background processes
(ph/install-package 'dumb-jump)
(dumb-jump-mode)
(setq dumb-jump-selector 'ivy)
(setq dumb-jump-use-visible-window nil)
Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs. The
most important commands have keybindings with prefix C-c !
.
(ph/install-package 'flycheck)
(require 'flycheck)
Enable Flycheck
globally (prog-mode-hook
may not cover all modes).
(add-hook 'after-init-hook 'global-flycheck-mode)
(define-fringe-bitmap 'flycheck-fringe-bitmap-ball
(vector #b00000000
#b00000000
#b00000000
#b00000000
#b00000000
#b00111000
#b01111100
#b11111110
#b11111110
#b11111110
#b01111100
#b00111000
#b00000000
#b00000000
#b00000000
#b00000000
#b00000000))
(flycheck-define-error-level 'error
:severity 100
:compilation-level 2
:overlay-category 'flycheck-error-overlay
:fringe-bitmap 'flycheck-fringe-bitmap-ball
:fringe-face 'flycheck-fringe-error
:error-list-face 'flycheck-error-list-error)
Magit is an interface to the version control system Git.
(ph/install-package 'magit)
Magit-Todos shows all TODO
items of the projct in the main magit-buffer.
(ph/install-package 'magit-todos)
(magit-todos-mode t)
Some major-modes to configure git repositories.
(ph/install-package 'gitattributes-mode)
(ph/install-package 'gitconfig-mode)
(ph/install-package 'gitignore-mode)
diff-hl-mode highlights uncommitted changes on the left side of the window, allows you to jump between and revert them selectively.
(ph/install-package 'diff-hl)
(setq-default indent-tabs-mode nil
tab-width 2)
Rainbow-Mode sets background color to strings that match color names, e.g. #0000ff is displayed in white with a blue background
(ph/install-package 'rainbow-mode)
(add-hook 'prog-mode-hook 'rainbow-mode)
YASnippet is a template system for Emacs.
(ph/install-package 'yasnippet)
(ph/install-package 'yasnippet-snippets)
(require 'yasnippet)
(yas-global-mode 1)
Irony-mode is an Emacs minor-mode that aims at improving the editing experience for the C, C++ and Objective-C languages. I
(ph/install-package 'irony)
(add-hook 'c++-mode-hook 'irony-mode)
(add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)
Add flycheck linting.
(ph/install-package 'flycheck-irony)
(add-hook 'flycheck-mode-hook #'flycheck-irony-setup)
(ph/install-package 'flycheck-clang-tidy)
(eval-after-load 'flycheck
'(add-hook 'flycheck-mode-hook #'flycheck-clang-tidy-setup))
Realgud - An extensible, modular GNU Emacs front-end for interacting with external debuggers (e.g. gdb).
(ph/install-package 'realgud)
(require 'realgud)
Notes:
- Run
irony-install-server
the first time (and install OS dependencies). - Compile with
M-x compile
. - For debugging, use
M-x gdb
andM-x gdb-many-windows
and the GUD keybindings (C-x C-a ...
). - Use
M-x realgud:gdb
for debugging.
(setq css-indent-offset 2)
Install on system.
$ go get -u github.com/rogpeppe/godef
$ go get -u github.com/mdempsky/gocode
(ph/install-package 'go-mode)
Autocompletion
(ph/install-package 'company-go)
(ph/install-package 'haml-mode)
OS setup
curl -sSL https://get.haskellstack.org/ | sh
Create a new project
stack new myproject # to create a new project
# see stack --help
Intero is a complete interactive development program for Haskell. It offers many useful functions (see here) and an (automatically loaded) company-backend.
(ph/install-package 'intero)
(with-eval-after-load 'haskell-mode (intero-global-mode))
Don’t jump to the repl everytime it does something.
(defun ph/intero-repl-switch-back (&rest _)
(intero-repl-switch-back))
(advice-add 'intero-repl-eval-region :after 'ph/intero-repl-switch-back)
(advice-add 'intero-repl-load :after 'ph/intero-repl-switch-back)
Some more convenient keybindings
(general-def 'haskell-mode-map
"C-c C-d" 'haskell-hoogle)
(general-def 'intero-mode-map
"C-c C-b" 'intero-repl)
(general-def 'intero-repl-mode-map
"C-c C-b" 'intero-repl-switch-back)
Syntax checker
(ph/install-package 'flycheck-haskell)
(add-hook 'haskell-mode-hook #'flycheck-haskell-setup)
Indentation
(setq js-indent-level 2)
TODO: company-tern is not on melpa anymore, find a solution
;(ph/install-package 'company-tern)
;(require 'company-tern)
;(add-to-list 'company-backends 'company-tern)
jquery-doc
provides completion source for auto-complete and company-mode as
well as a jquery-doc
command to lookup documentation.
(ph/install-package 'jquery-doc)
(ph/install-package 'js2-mode)
(ph/install-package 'js2-refactor)
This is Tern. Tern is a stand-alone, editor-independent JavaScript analyzer that can be used to improve the JavaScript integration of existing editors.
(ph/install-package 'tern)
Put a file .tern-project
in the root of the project. Additionally, a file
~/.tern-config
.
A Ruby on Rails .tern-project
may look like this:
{
"libs": [
"browser",
"jquery"
],
"loadEagerly": [
"app/assets/javascripts/**/*.js",
"lib/assets/javascript/**/*.js",
"vendor/assets/javascript/**/*.js"
],
"plugins": {
"es_modules": {},
"node": {}
}
}
And my ~/.tern-config
{
"libs": [
"browser",
"jquery"
],
"plugins": {
"es_modules": {},
"node": {}
}
}
Use eslint
instead of jshint
.
(setq-default flycheck-disabled-checkers (append flycheck-disabled-checkers
'(javascript-jshint)))
(flycheck-add-mode 'javascript-eslint 'web-mode)
(ph/install-package 'json-mode)
(ph/install-package 'lua-mode)
(ph/install-package 'markdown-mode)
(setq markdown-command "pandoc")
(ph/install-package 'php-mode)
(ph/install-package 'elpy)
(elpy-enable)
Indentation
(setq python-indent 2)
Some useful commands:
M-x run-python
to start a shellC-c C-z
to switch to shellC-c C-y b
to send buffer to shell- many more send to shell functions
Jedi is a Python auto-completion package for Emacs.
(ph/install-package 'jedi)
(add-hook 'python-mode-hook 'jedi:setup)
(setq jedi:complete-on-dot t)
There are several tools and helpers to handle virtual environments, dependencies, etc. (virtualenv, pyenv, pyenv-virtualenv, virtualenvwrapper, pyenv-virtualenvwrapper, pipenv, venv, pip-tools, …).
Pipenv is the newest and combines Pipfile
, pip
and virtualenv
and plays
well with projectile
.
(ph/install-package 'pipenv)
(add-hook 'python-mode 'pipenv-mode)
To run a shell, use M-x pipenv-shell
. Some example commands are:
pipenv --python 3.7 # create project with python 3.7
pipenv run python main.py # run application
pipenv install numpy # with Pipfile
pipenv install -r path/to/requirements.txt # with requirements.txt
Emacs Speaks Statistics (ess) is designed to support editing of scripts and interaction with various statistical analysis programs such as R, S-Plus, SAS, Stata and OpenBUGS/JAGS.
(ph/install-package 'ess)
Function:
C-c C-b
to eval bufferC-c C-j
to eval lineC-c C-r
to eval regionC-c C-f
to eval function- And more
Inf-Ruby provides a REPL buffer connected to a Ruby subprocess.
(ph/install-package 'inf-ruby)
Use the built-in ruby-mode
for all common ruby-files.
No magic comments
(setq ruby-insert-encoding-magic-comment nil)
Robe is a code assistance tool that uses a Ruby REPL subprocess with your application or gem code loaded, to provide information about loaded classes and modules, and where each method is defined.
(ph/install-package 'robe)
Add the following gems to the Gemfile
(if existent) and install them.
group :development do
gem 'pry'
gem 'pry-doc'
gem 'method_source'
end
Generally, you’ll want to start with M-x inf-ruby-console-auto
. If there’s no
Ruby console running, most interactive commands provided by Robe will offer to
launch it automatically.
The exceptions are code completion and eldoc, which only work if the server is
already running. To launch it, type M-x robe-start
.
As you change the code in your project, you’ll want to update the running
process. To load the current file, type C-c C-l
(ruby-load-file
), see
inf-ruby for more commands. When you’re working on a Rails project, you can type
C-c C-k
instead to reload the whole environment at once.
(add-hook 'ruby-mode-hook 'robe-mode)
Some useful Commands/Keybindings
C-c C-d
Lookup documentationM-.
/M-,
Jump to defintion and back
Use company mode for code completion.
(eval-after-load 'company
'(push 'company-robe company-backends))
Rspec-Mode provides some convenience functions for dealing with RSpec.
(ph/install-package 'rspec-mode)
When you’ve hit the breakpoint, hit C-x C-q
to enable inf-ruby.
(add-hook 'after-init-hook 'inf-ruby-switch-setup)
Usage:
C-c , s
Verify the example or method defined at pointC-c , m
Run all specs related to the current bufferC-c , a
Run spec for entire project- and more
Put the following in the Gemfile
of the projects.
group :development do
gem 'spring-commands-rspec'
end
Projectile Rails is a minor mode for working with Ruby on Rails applications and engines in GNU Emacs. Internally it is based on Projectile.
(setq projectile-rails-keymap-prefix (kbd "C-c p n"))
(ph/install-package 'projectile-rails)
(projectile-rails-global-mode)
(ph/install-package 'company-inf-ruby)
(add-to-list 'company-backends 'company-inf-ruby)
Indentation
(setq sh-basic-offset 2)
(setq sh-indentation 2)
Autocompletion
(ph/install-package 'company-shell)
(add-to-list 'company-backends 'company-shell)
AUCTeX is an extensible package for writing and formatting TeX files in GNU Emacs.
(ph/install-package 'auctex)
Parse on load and save. This increases performance, especially for large multifile projects. The information is stored in an “auto” subdirectory.
(setq TeX-parse-self t)
(setq TeX-auto-save t)
Query to find out which is the master file.
(setq-default TeX-master nil)
Auctex by default adds comment sections to all the .tex files to save the
TeX-master
variable. In order not to confuse my colleagues with such
auctex-specific lines I use per-directory local variables. For that I put the
following list in a .dir-locals.el
file in the project root if the main latex
file is report.tex
.
((latex-mode . ((TeX-master . "report"))))
I use Evince to view my PDFs.
(setq TeX-PDF-mode t)
(setq TeX-view-program-selection '((output-pdf "Evince")))
Sync with evince. Use Control + Left Click
for backward search.
(add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode)
(setq TeX-source-correlate-start-server t)
Autocompletion
(ph/install-package 'company-bibtex)
(add-to-list 'company-backends 'company-bibtex)
(ph/install-package 'company-auctex)
(company-auctex-init)
Auto-fill
(add-hook 'LaTeX-mode-hook 'turn-on-auto-fill)
Web-Mode is an autonomous emacs major-mode for editing web templates. HTML documents can embed parts (CSS / JavaScript) and blocks (client / server side).
(ph/install-package 'web-mode)
Use web-mode
for the following file-types.
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.tag?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.vue?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.erb?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.js[x]?\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.json?\\'" . web-mode))
Some web-mode settings.
(setq web-mode-markup-indent-offset 2
web-mode-css-indent-offset 2
web-mode-code-indent-offset 2
web-mode-script-padding 2
web-mode-style-padding 2
web-mode-script-padding 2
web-mode-block-padding 0
web-mode-enable-current-element-highlight t
web-mode-enable-current-column-highlight t)
(ph/install-package 'company-web)
(require 'company-web-html)
(add-to-list 'company-backends 'company-web-html)
Use company backends for tern
, html
and css
.
(add-hook 'web-mode-hook
'(lambda ()
(set (make-local-variable 'company-backends)
'(company-tern
company-web-html
company-css
company-files))))
Enable tern
when the current language is JavaScript.
(advice-add 'company-tern :before
'(lambda (&rest _)
(if (equal major-mode 'web-mode)
(let ((web-mode-cur-language
(web-mode-language-at-pos)))
(if (or (string= web-mode-cur-language "javascript")
(string= web-mode-cur-language "jsx"))
(unless tern-mode (tern-mode))
(if tern-mode (tern-mode -1)))))))
(ph/install-package 'yaml-mode)
My global keybindings are defined here. In order to get a better overview, they are neatly packed inside a minor-mode with its own keymap.
(defvar ph/global-keys-keymap (make-sparse-keymap))
(define-minor-mode ph/global-keys-mode
"A minor mode with personalized keybindings."
t ;; init-value
nil ;; lighter
ph/global-keys-keymap)
Overwriting sequences (and defining new ones) for non-user-reserved sequences.
(general-def ph/global-keys-keymap
"M-x" 'counsel-M-x
"C-s" 'ph/swiper-from-isearch
"C-h f" 'counsel-describe-function
"C-h v" 'counsel-describe-variable)
(general-def ph/global-keys-keymap
:prefix "C-x"
"2" 'ph/vsplit-last-buffer
"3" 'ph/hsplit-last-buffer
"7" 'ph/open-last-buffer
"b" 'ivy-switch-buffer
"f" 'counsel-find-file
"m" 'counsel-M-x
"o" 'ace-window
"C-b" 'ivy-switch-buffer
"C-f" 'set-fill-column)
User-reserved sequences (C-c
followed by a letter and <F5>
through <F9>
without modifiers) should (theoretically -.-) not be used by any major modes and
are intended for user-defined keybindings.
(general-def ph/global-keys-keymap
:prefix "C-c"
"d" 'crux-kill-line-backwards
"f d" 'rg-dwim
"f f" 'counsel-rg
"f p" 'rg-project
"f r" 'rg
"h b" 'dumb-jump-back
"h f" 'dumb-jump-go
"h p" 'dumb-jump-go-prompt
"l g" 'diff-hl-mode
"l k" 'ph/kill-other-buffers
"l m" 'magit-diff-buffer-file
"l o" 'ph/xdg-open
"l q" 'ph/qs-notes
"l r" 'browse-kill-ring
"l u" 'ph/unfill-paragraph
"l v" 'visual-line-mode
"i" 'indent-region
"j" 'switch-to-next-buffer
"k" 'switch-to-prev-buffer
"m" 'magit
"o" 'ph/occur-dwim
"r" 'ph/mu4e
"s b" 'flyspell-buffer
"s c" 'flyspell-correct-at-point
"s e" 'flyspell-mode
"s n" 'flyspell-goto-next-error
"s l" 'ph/ispell-next-dictionary
"u" 'counsel-imenu
"w m" 'which-key-show-major-mode
"w t" 'which-key-show-top-level)
(general-def ph/global-keys-keymap
"<f5>" 'ph/next-theme
"<f6>" 'ivy-resume)
Some state specific bindings.
(general-def 'normal ph/global-keys-keymap
"SPC" 'god-local-mode)
(general-def 'visual ph/global-keys-keymap
"SPC" 'god-local-mode)
(general-def 'motion ph/global-keys-keymap
"j" 'evil-next-visual-line
"k" 'evil-previous-visual-line)
(general-def 'insert ph/global-keys-keymap
"<C-tab>" 'company-yasnippet
"C-SPC" 'company-complete)
(set-face-attribute 'default nil
:family "DejaVu Sans Mono"
;; some similar characters: 0OD yprw VU Ss |iIl
:weight 'normal
:height 120
:width 'normal)
Diminish implements hiding or abbreviation of the mode line displays (lighters) of minor-modes.
(ph/install-package 'diminish)
(diminish 'counsel-mode)
(diminish 'god-local-mode)
(diminish 'ivy-mode)
(diminish 'projectile-mode)
(diminish 'undo-tree-mode)
(diminish 'visual-line-mode "VL")
(diminish 'which-key-mode)
Doom Modeline is a fancy and fast mode-line with minimalism design.
(ph/install-package 'doom-modeline)
(require 'doom-modeline)
Show both line and column numbers but not a percentage.
(setq line-number-mode t)
(setq column-number-mode t)
(setq doom-modeline-percent-position nil)
Make modeline as high as its content.
(setq doom-modeline-height 30)
(setq doom-modeline-bar-width 1)
No icons in my mode-line.
(setq doom-modeline-icon (display-graphic-p))
(setq all-the-icons-scale-factor 1.0)
Make the mode-line segment show the minions-menu AND the minor-modes.
(setq doom-modeline-minor-modes t)
Show flycheck info/warning/error instead of only one number for them all.
(setq doom-modeline-checker-simple-format nil)
Show long branch names.
(setq doom-modeline-vcs-max-length 24)
Show buffer-name instead of path.
(setq doom-modeline-buffer-file-name-style 'buffer-name)
A Segment to indicate the active ispell dictionary in flyspell.
(doom-modeline-def-segment ph/flyspell-dictionary
(when (and flyspell-mode
ispell-local-dictionary)
(concat
(doom-modeline-spc)
(propertize ispell-local-dictionary
'face 'doom-modeline-buffer-minor-mode))))
Show the tramp method.
(doom-modeline-def-segment tramp-method
(let ((method (file-remote-p default-directory 'method)))
(if method
(concat
(doom-modeline-spc)
(propertize method 'face 'doom-modeline-urgent)))))
Show the projectile project name.
(doom-modeline-def-segment ph/projectile-project-name
(when (projectile-project-p)
(concat
(doom-modeline-spc)
(propertize (projectile-project-name) 'face
(if (doom-modeline--active)
'doom-modeline-buffer-path
'mode-line-inactive))
(doom-modeline-spc))))
Show the buffer name.
(doom-modeline-def-segment ph/buffer-info
(concat
(doom-modeline-spc)
(propertize (buffer-name) 'face 'doom-modeline-buffer-file)))
Handle evil-state faces in a more extendable way. I also want them to be always
active/colorful to have a better overview of where my windows start and end.
Also the modals
segment adds a second indicator for god-mode which I don’t
want.
(setq doom-modeline-evil-state-faces-alist
'((normal . doom-modeline-evil-normal-state)
(emacs . doom-modeline-evil-emacs-state)
(insert . doom-modeline-evil-insert-state)
(motion . doom-modeline-evil-motion-state)
(visual . doom-modeline-evil-visual-state)
(operator . doom-modeline-evil-operator-state)
(replace . doom-modeline-evil-replace-state)))
(doom-modeline-def-segment ph/evil-state
"The current evil state. Requires `evil-mode' to be enabled."
(when (bound-and-true-p evil-local-mode)
(let ((tag (evil-state-property evil-state :tag t)))
(propertize (if (stringp tag) tag (funcall tag)) 'face
(if (doom-modeline--active)
(cdr (assoc evil-state
doom-modeline-evil-state-faces-alist))
'doom-modeline-bar-inactive)))))
(set-face-attribute 'doom-modeline-evil-emacs-state nil
:foreground "#111"
:background "SkyBlue")
(set-face-attribute 'doom-modeline-evil-insert-state nil
:foreground "#111"
:background "LimeGreen")
(set-face-attribute 'doom-modeline-evil-motion-state nil
:foreground "#111"
:background "#9c91e4")
(set-face-attribute 'doom-modeline-evil-normal-state nil
:foreground "#111"
:background "#ffdd30")
(set-face-attribute 'doom-modeline-evil-operator-state nil
:foreground "#111"
:background "NavajoWhite")
(set-face-attribute 'doom-modeline-evil-visual-state nil
:foreground "#111"
:background "#aaaaaa")
(set-face-attribute 'doom-modeline-evil-replace-state nil
:foreground "#111"
:background "#fd971f")
Setup the mode-line.
(doom-modeline-def-modeline 'main
'(bar
window-number
ph/evil-state
matches ; e.g. evil-substitute
selection-info
tramp-method
ph/buffer-info
remote-host
buffer-position
ph/flyspell-dictionary
checker)
'(minor-modes
media-info
misc-info
vcs
ph/projectile-project-name
major-mode)
)
Last but not least, enable it.
(doom-modeline-mode 1)
When I open my first frame, the mode-line has a rather large empty space on the
right side. The width is set incorrectly although
doom-modeline-refresh-font-width-cache
is in after-make-frame-functions
.
Adding the function to buffer-list-update-hook
seems to resolve this issue.
(add-hook 'buffer-list-update-hook 'doom-modeline-refresh-font-width-cache)
Function to rotate through ph/theme-list
. The entries may be functions or
themes.
(ph/install-package 'doom-themes)
(setq ph/theme-list
'(doom-peacock
doom-tomorrow-day))
(defun ph/next-theme ()
"Load next theme."
(interactive)
(setq ph/theme-list
(ph/call-rotate 'ph/load-theme ph/theme-list)))
(add-hook 'emacs-startup-hook 'ph/next-theme)
Functions to load and customize themes.
(defun ph/load-theme (theme)
"Like load-theme but first disable all custom-enabled themes ,
then load THEME and finally do some customizations."
(interactive
(list
(intern (completing-read
"Load custom theme: "
(mapcar 'symbol-name (custom-available-themes))))))
(mapcar 'disable-theme custom-enabled-themes)
(load-theme theme t)
(ph/customize-theme theme)
(ph/any-theme-customize))
(defun ph/customize-theme (theme)
"Call ph/THEME-customize if existent."
(let ((fn (intern (concat "ph/" (symbol-name theme) "-customize"))))
(message (concat "ph/" (symbol-name theme) "-customize"))
(if (functionp fn)
(funcall fn))))
(defun ph/doom-peacock-customize ()
;; highlight current line number
(set-face-attribute 'line-number-current-line nil
:foreground "#BCD42A"
:weight 'bold))
(defun ph/any-theme-customize ()
"This function sets some default values for all themes."
;; Never ever scale org and markdown headings
(set-face-attribute 'org-level-1 nil
:height 1.0 :background nil)
(set-face-attribute 'org-level-2 nil
:height 1.0 :background nil)
(set-face-attribute 'org-level-3 nil
:height 1.0 :background nil)
(set-face-attribute 'org-level-4 nil
:height 1.0 :background nil)
(set-face-attribute 'org-level-5 nil
:height 1.0 :background nil)
(set-face-attribute 'org-level-6 nil
:height 1.0 :background nil)
(set-face-attribute 'org-level-7 nil
:height 1.0 :background nil)
(set-face-attribute 'org-level-8 nil
:height 1.0 :background nil)
(set-face-attribute 'doom-modeline-bar nil
:foreground nil
:background nil)
;; Use a smaller font for the mode-line
(set-face-attribute 'mode-line nil
:height 90)
(set-face-attribute 'mode-line-inactive nil
:height 90)
)
Disable fancy GUI stuff
(setq inhibit-splash-screen t)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(menu-bar-mode -1)
Show the buffer-name in the frame title and use the same title for unfocused frames.
(setq ph/frame-title-format '("%b"))
(setq frame-title-format ph/frame-title-format)
(setq icon-title-format ph/frame-title-format)
Don’t use ugly GTK tooltips.
(setq x-gtk-use-system-tooltips nil)