My emacs configuration

Copyright (C) 2017-2019 Laurent Hoeltgen <contact@laurenthoeltgen.name>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

General information

This project is hosted on gitlab. A corresponding html version is available here.

Setup

This emacs config file uses use-package and org. To get started, follow the instructions below and place this file under ~/.emacs.d/config.org.

First Line

Set to read-only to make edits harder. Recall that the tangled file is not supposed to be edited.

;; -*- lexical-binding: t ; eval: (read-only-mode 1)-*-
;; config.el --- personal config file

init.el

The following code is the content of the file init.el inside the folder ~/.emacs.d. If starting from scratch copy that code there. Note that this source code block overwrites init.el at every startup to keep its content in sync. This also implies that all changes done here are only active after a restart.

;; -*- lexical-binding: t ; eval: (read-only-mode 1)-*-
;; init.el --- personal config file

;; I need this on my Windows System, otherwise emacs complains about
;; some chinese characters somewhere
(prefer-coding-system 'utf-8)

(require 'cl) ;; Needed for case in replace-matching-parens.
(require 'package)
(setq package-enable-at-startup nil)
;; Customizations set using Emacs’ customization system go here.
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))

(unless (assoc-default "melpa" package-archives)
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t))
(unless (assoc-default "gnu" package-archives)
  (add-to-list 'package-archives '("gnu" . "https://elpa.gnu.org/packages/") t))
(unless (assoc-default "org" package-archives)
  (add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t))
(package-initialize)

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'diminish)
  (package-install 'bind-key)
  (package-install 'use-package)
  (setq use-package-always-ensure t)
  (use-package diminish :ensure t))

(eval-when-compile
  (require 'use-package))
(require 'diminish)
(require 'bind-key)

(setq use-package-verbose t)
(setq use-package-check-before-init t)
(setq use-package-minimum-reported-time 0.01)

(org-babel-load-file
 (expand-file-name "config.org" user-emacs-directory))

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(default ((t (:family "Office Code Pro" :foundry "outline" :slant normal :weight normal :height 120 :width normal))))
 '(package-selected-packages (quote (use-package))))

Important functions

Here I store functions that I have gathered over the years and which I found useful. A package with more such stuff is crux.

Add \left and \right to matching pairs of ( ), [ ] and { } in LaTeX

Source

Put the point immediately after a closing paren. replace-matching-parens will replace the closing ) with \right) and the matching start paren ( with \left(.

(defun replace-matching-parens (char)
  (interactive (list (char-before)))
  (unless (memq char '(?\) ?\] ?\}))
    (error "Cursor is not after `)', `]', or `}'"))
  (save-excursion
    (let ((syntable   (copy-syntax-table (syntax-table)))
          (end-point  (point)))
      (modify-syntax-entry ?\[ "(" syntable)
      (modify-syntax-entry ?\] ")" syntable)
      (modify-syntax-entry ?\{ "(" syntable)
      (modify-syntax-entry ?\} ")" syntable)
      (with-syntax-table syntable
        (backward-list)
        (let ((start-point  (point)))
          (goto-char end-point)
          (search-backward (format "%c" char) nil t)
          (replace-match (format " \\\\right%c" char) nil nil)
          (goto-char start-point)
          (search-forward (format "%c" (setq newchar  (case char
                                                        (?\) ?\( )
                                                        (?\] ?\[ )
                                                        (?\} ?\{ ))))
                          nil t)
          (replace-match (format "\\\\left%c " newchar) nil nil))))))

Get LaTeX indentation to suit my taste

I write a lot of LaTeX and want my texts to be formatted in a special way.

(defun LaTeX-indent-item ()
  "Provide proper indentation for LaTeX \"itemize\",\"enumerate\", and
\"description\" environments.

  \"\\item\" is indented `LaTeX-indent-level' spaces relative to
  the the beginning of the environment.

  Continuation lines are indented either twice
  `LaTeX-indent-level', or `LaTeX-indent-level-item-continuation'
  if the latter is bound."
  (save-match-data
    (let* ((offset LaTeX-indent-level)
           (contin (or (and (boundp 'LaTeX-indent-level-item-continuation)
                            LaTeX-indent-level-item-continuation)
                       (* 2 LaTeX-indent-level)))
           (re-beg "\\\\begin{")
           (re-end "\\\\end{")
           (re-env "\\(itemize\\|\\enumerate\\|description\\)")
           (indent (save-excursion
                     (when (looking-at (concat re-beg re-env "}"))
                       (end-of-line))
                     (LaTeX-find-matching-begin)
                     (current-column))))
      (cond ((looking-at (concat re-beg re-env "}"))
             (or (save-excursion
                   (beginning-of-line)
                   (ignore-errors
                     (LaTeX-find-matching-begin)
                     (+ (current-column)
                        (if (looking-at (concat re-beg re-env "}"))
                            contin
                          offset))))
                 indent))
            ((looking-at (concat re-end re-env "}"))
             indent)
            ((looking-at "\\\\item")
             (+ offset indent))
            (t
             (+ contin indent))))))

fill-or-unfill a paragraph

Source

With this, M-q will act as a toggle. Hitting it once will fill a paragraph (even if the paragraph is already filled), but hitting it twice will completely unwrap the current paragraph into a single line. The keybinding is set below.

(defun endless/fill-or-unfill ()
  "Like `fill-paragraph', but unfill if used twice."
  (interactive)
  (let ((fill-column
         (if (eq last-command 'endless/fill-or-unfill)
             (progn (setq this-command nil)
                    (point-max))
           fill-column)))
    (call-interactively #'fill-paragraph)))

goto-line-with-feedback

Source Alternatives Sources

Show line numbers temporarily, while prompting for the line number input

(use-package goto-line-preview :ensure t)

(defun my-goto-line-numbers-advice (fun)
  (interactive)
  (unwind-protect
     (progn (display-line-numbers-mode 1)
            (call-interactively fun))
  (display-line-numbers-mode -1)))
(advice-add #'goto-line-preview :around #'my-goto-line-numbers-advice)

goto-column

move-to-column (bound to M-g TAB) cannot jump past the end of the line. This version does.

Source

(defun goto-column (number)
  "Untabify, and go to a column NUMBER within the current line (0
is beginning of the line)."
  (interactive "nColumn number: ")
  (move-to-column number t))

Theming

(use-package all-the-icons
  :ensure t
  )

(use-package all-the-icons-dired
  :ensure t
  :init
  (add-hook 'dired-mode-hook 'all-the-icons-dired-mode)
  )

(use-package doom-modeline
  :if window-system
  :ensure t
  :hook
  (after-init . doom-modeline-mode)
  :config
  (setq doom-modeline-height 25)
  (setq doom-modeline-bar-width 3)
  (setq doom-modeline-buffer-file-name-style 'buffer-name)
  (setq doom-modeline-icon t)
  (setq doom-modeline-major-mode-icon t)
  (setq doom-modeline-major-mode-color-icon nil)
  (setq doom-modeline-minor-modes nil)
  (setq doom-modeline-enable-word-count nil)
  (setq doom-modeline-checker-simple-format nil)
  (setq doom-modeline-persp-name nil)
  (setq doom-modeline-lsp t)
  (setq doom-modeline-github nil)
  (setq doom-modeline-env-version nil)
  (setq doom-modeline-env-enable-python nil)
  (setq doom-modeline-env-enable-ruby nil)
  (setq doom-modeline-env-enable-perl nil)
  (setq doom-modeline-env-enable-go nil)
  (setq doom-modeline-env-enable-elixir nil)
  (setq doom-modeline-env-enable-rust nil)
  (setq doom-modeline-mu4e nil)
  (setq doom-modeline-irc nil)
  (setq doom-modeline-irc-stylize 'identity)
  )

(use-package doom-themes
  :if window-system
  :ensure t
  :after (doom-modeline)
  :init
  (setq doom-themes-enable-bold t
        doom-themes-enable-italic t)
  (setq doom-nord-brighter-modeline t)
  (setq doom-nord-brighter-comments t)
  (setq doom-nord-comment-bg t)
  (setq doom-nord-padded-modeline t)
  (setq doom-nord-light-brighter-modeline t)
  (setq doom-nord-light-brighter-comments t)
  (setq doom-nord-light-comment-bg t)
  (setq doom-nord-light-padded-modeline t)
  (setq doom-nord-light-region-highlight t)
  (load-theme 'doom-nord t)
  (doom-themes-visual-bell-config)
  (doom-themes-neotree-config)
  (doom-themes-treemacs-config)
  (doom-themes-org-config)
)

(use-package centaur-tabs
  :demand
  :ensure t
  :config
  (setq centaur-tabs-style "wave")
  (setq centaur-tabs-height 32)
  ;; (setq centaur-tabs-set-icons t)
  (setq centaur-tabs-gray-out-icons 'buffer)
  ;; (setq centaur-tabs-set-bar 'over)
  ;; (setq centaur-tabs-set-modified-marker t)
  ;; (centaur-tabs-inherit-tabbar-faces)
  (setq centaur-tabs-set-close-button nil)
  (centaur-tabs-headline-match)
  (centaur-tabs-mode t)
  :bind
  ("C-<prior>" . centaur-tabs-backward)
  ("C-<next>" . centaur-tabs-forward)
  ("C-c t" . centaur-tabs-counsel-switch-group)
)

(set-face-attribute 'default nil
                    :family "Office Code Pro"
                    :height 120
                    :weight 'normal
                    :width 'normal)

Various packages that improve emacs user experience

no-littering

Keeping your .emacs.d clean. Load this as soon as possible to avoid problems. Source

(use-package no-littering
  :ensure t
  :config
  (require 'recentf)
  (add-to-list 'recentf-exclude no-littering-etc-directory)
  (add-to-list 'recentf-exclude no-littering-var-directory))

Garbage Collection Magic Hack

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

use-package-hydra

(use-package use-package-hydra
  :ensure t
  :after hydra)

load-relative

(use-package load-relative
  :ensure t)

saveplace

Automatically save place in files, so that visiting them later (even during a different Emacs session) automatically moves point to the saved position, when the file is first found. Uses the value of buffer-local variable save-place to determine whether to save position or not.

Source

(use-package saveplace
  :ensure t
  :init
  (save-place-mode)
  (setq-default save-place t))

mode line settings

I’m pretty happy with the default mode line settings. Just a few tweaks to how time and date are displayed.

(use-package time
  :ensure t
  :custom
  (display-time-24hr-format t)
  (display-time-day-and-date t)
  (display-time-mail-file (quote none))
  (display-time-mail-function (quote ignore))
  (display-time-default-load-average nil)
  :config
  (display-time-mode))

golden-ratio-scroll-screen

Scroll screen down or up, and highlight current line before or after scrolling.

the lines it scrolling is 0.618 times screen height

(use-package golden-ratio-scroll-screen
  :ensure t
  :config
  (global-set-key [remap scroll-down-command] 'golden-ratio-scroll-screen-down)
  (global-set-key [remap scroll-up-command]   'golden-ratio-scroll-screen-up))

visual-regexp

Live visual feedback for regexps.

(use-package visual-regexp
  :ensure t
  :bind
  (
   ("C-%" . vr/replace)
   ("M-%" . vr/query-replace)
   ))

volatile-highlights

This library provides minor mode volatile-highlights-mode, which brings visual feedback to some operations by highlighting portions relating to the operations.

(use-package volatile-highlights
  :ensure t
  :diminish volatile-highlights-mode
  :init
  (volatile-highlights-mode t))

hydra

Helps memorising keybindings.

(use-package hydra
  :ensure t
  :config
  (defhydra hydra-ibuffer-main (:color pink :hint nil)
    "
    ^Mark^         ^Actions^         ^View^          ^Select^              ^Navigation^
    _m_: mark      _D_: delete       _g_: refresh    _q_: quit             _k_:   ↑    _h_
    _u_: unmark    _s_: save marked  _S_: sort       _TAB_: toggle         _RET_: visit
    _*_: specific  _a_: all actions  _/_: filter     _o_: other window     _j_:   ↓    _l_
    _t_: toggle    _._: toggle hydra _H_: help       C-o other win no-select
    "
    ("m" ibuffer-mark-forward)
    ("u" ibuffer-unmark-forward)
    ("*" hydra-ibuffer-mark/body :color blue)
    ("t" ibuffer-toggle-marks)

    ("D" ibuffer-do-delete)
    ("s" ibuffer-do-save)
    ("a" hydra-ibuffer-action/body :color blue)

    ("g" ibuffer-update)
    ("S" hydra-ibuffer-sort/body :color blue)
    ("/" hydra-ibuffer-filter/body :color blue)
    ("H" describe-mode :color blue)

    ("h" ibuffer-backward-filter-group)
    ("k" ibuffer-backward-line)
    ("l" ibuffer-forward-filter-group)
    ("j" ibuffer-forward-line)
    ("RET" ibuffer-visit-buffer :color blue)

    ("TAB" ibuffer-toggle-filter-group)

    ("o" ibuffer-visit-buffer-other-window :color blue)
    ("q" quit-window :color blue)
    ("." nil :color blue)
    )
  (defhydra hydra-ibuffer-mark (:color teal :columns 5
                                       :after-exit (hydra-ibuffer-main/body))
    "Mark"
    ("*" ibuffer-unmark-all "unmark all")
    ("M" ibuffer-mark-by-mode "mode")
    ("m" ibuffer-mark-modified-buffers "modified")
    ("u" ibuffer-mark-unsaved-buffers "unsaved")
    ("s" ibuffer-mark-special-buffers "special")
    ("r" ibuffer-mark-read-only-buffers "read-only")
    ("/" ibuffer-mark-dired-buffers "dired")
    ("e" ibuffer-mark-dissociated-buffers "dissociated")
    ("h" ibuffer-mark-help-buffers "help")
    ("z" ibuffer-mark-compressed-file-buffers "compressed")
    ("b" hydra-ibuffer-main/body "back" :color blue)
    )
  (defhydra hydra-ibuffer-action (:color teal :columns 4
                                         :after-exit
                                         (if (eq major-mode 'ibuffer-mode)
                                             (hydra-ibuffer-main/body)))
    "Action"
    ("A" ibuffer-do-view "view")
    ("E" ibuffer-do-eval "eval")
    ("F" ibuffer-do-shell-command-file "shell-command-file")
    ("I" ibuffer-do-query-replace-regexp "query-replace-regexp")
    ("H" ibuffer-do-view-other-frame "view-other-frame")
    ("N" ibuffer-do-shell-command-pipe-replace "shell-cmd-pipe-replace")
    ("M" ibuffer-do-toggle-modified "toggle-modified")
    ("O" ibuffer-do-occur "occur")
    ("P" ibuffer-do-print "print")
    ("Q" ibuffer-do-query-replace "query-replace")
    ("R" ibuffer-do-rename-uniquely "rename-uniquely")
    ("T" ibuffer-do-toggle-read-only "toggle-read-only")
    ("U" ibuffer-do-replace-regexp "replace-regexp")
    ("V" ibuffer-do-revert "revert")
    ("W" ibuffer-do-view-and-eval "view-and-eval")
    ("X" ibuffer-do-shell-command-pipe "shell-command-pipe")
    ("b" nil "back")
    )
  (defhydra hydra-ibuffer-sort (:color amaranth :columns 3)
    "Sort"
    ("i" ibuffer-invert-sorting "invert")
    ("a" ibuffer-do-sort-by-alphabetic "alphabetic")
    ("v" ibuffer-do-sort-by-recency "recently used")
    ("s" ibuffer-do-sort-by-size "size")
    ("f" ibuffer-do-sort-by-filename/process "filename")
    ("m" ibuffer-do-sort-by-major-mode "mode")
    ("b" hydra-ibuffer-main/body "back" :color blue)
    )
  (defhydra hydra-ibuffer-filter (:color amaranth :columns 4)
    "Filter"
    ("m" ibuffer-filter-by-used-mode "mode")
    ("M" ibuffer-filter-by-derived-mode "derived mode")
    ("n" ibuffer-filter-by-name "name")
    ("c" ibuffer-filter-by-content "content")
    ("e" ibuffer-filter-by-predicate "predicate")
    ("f" ibuffer-filter-by-filename "filename")
    (">" ibuffer-filter-by-size-gt "size")
    ("<" ibuffer-filter-by-size-lt "size")
    ("/" ibuffer-filter-disable "disable")
    ("b" hydra-ibuffer-main/body "back" :color blue)
    )
  (defhydra hydra-outline (:color pink :hint nil)
    "
^Hide^             ^Show^           ^Move
^^^^^^------------------------------------------------------
_q_: sublevels     _a_: all         _u_: up
_t_: body          _e_: entry       _n_: next visible
_o_: other         _i_: children    _p_: previous visible
_c_: entry         _k_: branches    _f_: forward same level
_l_: leaves        _s_: subtree     _b_: backward same level
_d_: subtree

"
    ;; Hide
    ("q" hide-sublevels)    ; Hide everything but the top-level headings
    ("t" hide-body)         ; Hide everything but headings (all body lines)
    ("o" hide-other)        ; Hide other branches
    ("c" hide-entry)        ; Hide this entry's body
    ("l" hide-leaves)       ; Hide body lines in this entry and sub-entries
    ("d" hide-subtree)      ; Hide everything in this entry and sub-entries
    ;; Show
    ("a" show-all)          ; Show (expand) everything
    ("e" show-entry)        ; Show this heading's body
    ("i" show-children)     ; Show this heading's immediate child sub-headings
    ("k" show-branches)     ; Show all sub-headings under this heading
    ("s" show-subtree)      ; Show (expand) everything in this heading & below
    ;; Move
    ("u" outline-up-heading)                ; Up
    ("n" outline-next-visible-heading)      ; Next
    ("p" outline-previous-visible-heading)  ; Previous
    ("f" outline-forward-same-level)        ; Forward - same level
    ("b" outline-backward-same-level)       ; Backward - same level
    ("z" nil "leave"))
  )

  (defhydra hydra-move ()
    "move"
    ("n" next-line)
    ("p" previous-line)
    ("f" forward-char)
    ("b" backward-char)
    ("a" beginning-of-line)
    ("e" move-end-of-line)
    ("v" scroll-up-command)
    ("c" scroll-down-command)
    ("l" recenter-top-bottom))

hercules

(use-package hercules
  :ensure t
  :after (hydra which-key)
)

whole-line-or-region

The primary use for this is to kill (cut) the current line if no region is defined, and kill-region is invoked.

(use-package whole-line-or-region
  :ensure t
  :diminish whole-line-or-region-global-mode
  :config
  (whole-line-or-region-global-mode)
  (diminish 'whole-line-or-region-local-mode)
  )

ivy, swiper and counsel

A perfect description of these packages. Source, also good: Source

ivy is a generic narrowing framework, like helm, that both swiper and counsel use. So, instead of tabbing your way through options in the default completing-read, you will type to narrow search results, like ido. The difference is that it displays results in a vertical list in the minibuffer and lets you do more actions than ido does. It uses a regexp based search by default but can be made fuzzy if you want it to. It also has a nice API by which you can build your completion commands.

counsel is a bunch of commands like counsel-grep, counsel-M-x, etc. which use ivy as the narrowing framework to select matches. For example, instead of using ido to replace execute-extended-command, you can use counsel-M-x which will use ivy instead of ido. So, ivy is a dependency for counsel.

swiper is a “replacement” for isearch and displays the search results with a nice highlight as a list so you can narrow it down further or traverse the list. Some people, including myself, find it easier than the default isearch option. This also depends on ivy.

The reason you’re seeing C-r triggering a different command in swiper is because ivy has its own set of maps in the minibuffer. Some are the same as normal ones (C-a, C-b, etc.), some are adapted to move through ivy’s list (C-v, M-v, etc.), and some are mapped to convenient functions (C-c C-o for ivy-occur, C-M-j for ivy-immediate-done, etc.). So, if IIRC C-r triggers the command for previous swiper searches. You can change any of it if you want, of course.

The reason it is popular is because of its simpler API and nice interface. The counsel-* commands also have a lot of functionality in them and it is easy to extend. The reason people typically use all three is to have a consistency across the board. Any operation that requires me to narrow something will use ivy. Hope this helped.

Smex improves the suggestions in counsel-M-x. The package just needs to be there. No config needed.

(use-package smex :ensure t)
(use-package ivy
  :ensure t
  :diminish ivy-mode
  :custom
  (enable-recursive-minibuffers t)
  (ivy-display-style 'fancy)
  (ivy-use-virtual-buffers t)
  (ivy-use-selectable-prompt t)
  :bind
  (
   ("C-c C-r" . ivy-resume)
   :map ivy-minibuffer-map
   ("M-y" . ivy-next-line)
   ("C-M-y" . ivy-previous-line)
   )
  :config
  (ivy-mode 1))
(use-package ivy-posframe
  :ensure t
  :after ivy
  :config
  (setq ivy-posframe-display-functions-alist '((t . ivy-posframe-display-at-window-bottom-left)))
  (ivy-posframe-mode 1)
)
(use-package swiper
  :ensure t
  :bind
  ("\C-s" . swiper))
(use-package counsel
  :ensure t
  :diminish counsel-mode
  :bind
  (
   ("M-x"     . counsel-M-x)
   ("C-x C-f" . counsel-find-file)
   ("C-h v"   . counsel-describe-variable)
   ("C-h f"   . counsel-describe-function)
   ("C-c 8"   . counsel-unicode-char)
   ("C-."     . counsel-imenu)
   ("M-y"     . counsel-yank-pop)
   :map read-expression-map
   ("C-r"     . counsel-expression-history)
  )
  :custom
  (counsel-find-file-at-point t)
  :config
  (counsel-mode))
(use-package all-the-icons-ivy
  :ensure t
  :config
  (all-the-icons-ivy-setup))

mwim

(use-package mwim
  :ensure t
  :bind
  (
   ("C-a" . mwim-beginning-of-line-or-code)
   ("C-e" . mwim-end-of-code-or-line)
   ("<home>" . mwim-beginning-of-line-or-code)
   ("<end>" . mwim-end-of-line-or-code)
  )
)

comment-dwim-2

(use-package comment-dwim-2
  :ensure t
  :bind
  ("M-;" . comment-dwim-2))

ws-butler

I have grown a certain obsession when it comes to trailing whitespaces. I want to see them and I want to get rid of them.

(use-package ws-butler
  :ensure t
  :diminish ws-butler-global-mode
  :config
  (diminish 'ws-butler-mode)
  (ws-butler-global-mode t))

beginend

Intelligent movement to begin and end of buffer.

(use-package beginend
  :ensure t
  :diminish beginend-global-mode
  :config
  (diminish 'beginend-prog-mode)
  (diminish 'beginend-magit-status-mode)
  (diminish 'beginend-prodigy-mode)
  (diminish 'beginend-elfeed-search-mode)
  (diminish 'beginend-notmuch-search-mode)
  (diminish 'beginend-compilation-mode)
  (diminish 'beginend-org-agenda-mode)
  (diminish 'beginend-recentf-dialog-mode)
  (beginend-global-mode))

paren

show-paren-mode allows one to see matching pairs of parentheses and other characters. When point is on one of the paired characters, the other is highlighted.

(use-package paren
  :ensure t
  :custom
  (show-paren-style (quote expression))
  :config
  (show-paren-mode))

winner

Undo changes in the window configuration.

(use-package winner
  :ensure t
  :diminish winner-mode
  :config
  (winner-mode))

whitespace

highlight trailing whitespace

(use-package whitespace
  :ensure t
  :custom
  (whitespace-style (quote (face trailing empty)))
  :custom-face
  (whitespace-big-indent       ((t (:background "#dc322f" :foreground "#fdf6e3"))))
  (whitespace-empty            ((t (:background "#dc322f" :foreground "#fdf6e3"))))
  (whitespace-hspace           ((t (:background "#dc322f" :foreground "#fdf6e3"))))
  (whitespace-indentation      ((t (:background "#dc322f" :foreground "#fdf6e3"))))
  (whitespace-line             ((t (:background "#eee8d5" :foreground "#d33682"))))
  (whitespace-space-after-tab  ((t (:background "#dc322f" :foreground "#fdf6e3"))))
  (whitespace-space-before-tab ((t (:background "#dc322f" :foreground "#fdf6e3"))))
  (whitespace-trailing         ((t (:background "#dc322f" :foreground "#fdf6e3"))))
  :config
  (global-whitespace-mode)
  (global-whitespace-newline-mode)
  :diminish global-whitespace-mode)

column-enforce-mode

Highlight text that extends beyond a certain column.

(use-package column-enforce-mode
  :ensure t
  :custom
  (column-enforce-comments nil)
  :diminish column-enforce-mode)

recentf

List of recently used files.

Source

(use-package recentf
  :ensure t
  :custom
  (recentf-auto-cleanup 'never)
  (recentf-exclude (list "/\\.git/.*\\'" "/elpa/.*\\'"))
  (recentf-max-menu-items 25)
  (recentf-max-saved-items 200)
  :config
  (recentf-mode))

autorevert

Automatically update buffers when changed on harddisk.

(use-package autorevert
  :ensure t
  :custom
  (auto-revert-verbose nil)
  (global-auto-revert-non-file-buffers t)
  :init
  (when (eq system-type 'darwin) (setq auto-revert-use-notify nil))
  :diminish auto-revert-mode
  :config
  (global-auto-revert-mode))

ibuffer

(use-package ibuffer
  :ensure t
  :bind
  (
   ("C-x C-b" . ibuffer)
   :map ibuffer-mode-map
   ("." . hydra-ibuffer-main/body)
   )
  :config
  (autoload 'ibuffer "ibuffer" "List buffers." t)
  (add-hook 'ibuffer-hook #'hydra-ibuffer-main/body))

goto-chg

Goto the point of the most recent edit in the buffer. When repeated, goto the second most recent edit, etc.

(use-package goto-chg
  :ensure t
  :bind (("C-?" . goto-last-change)))

helpful

(use-package helpful
  :ensure t
  :defer t
  :bind (("C-h f" . helpful-callable)
         ("C-h v" . helpful-variable)
         ("C-h k" . helpful-key)
         ("C-h F" . helpful-function)
         ("C-h C" . helpful-command)
         ))

neotree

(use-package neotree
  :ensure t
  :defer t
  :bind (("<f8>" . neotree-toggle)))

flycheck

Flycheck Website

(use-package flycheck
  :ensure t
  :defer t
  :custom
  (flycheck-gfortran-language-standard "f2008")
  (flycheck-gfortran-layout (quote free))
  :config
  (add-hook 'f90-mode-hook 'flycheck-mode)
)

dumb-jump

(use-package dumb-jump
  :ensure t
  :defer t
  :after hydra
  :bind (("M-g o" . dumb-jump-go-other-window)
         ("M-g j" . dumb-jump-go)
         ("M-g i" . dumb-jump-go-prompt)
         ("M-g x" . dumb-jump-go-prefer-external)
         ("M-g z" . dumb-jump-go-prefer-external-other-window))
  :hydra (hydra-dumb-jump (:color blue :columns 3)
           "Dumb Jump"
           ("j" dumb-jump-go "Go")
           ("o" dumb-jump-go-other-window "Other window")
           ("e" dumb-jump-go-prefer-external "Go external")
           ("x" dumb-jump-go-prefer-external-other-window "Go external other window")
           ("i" dumb-jump-go-prompt "Prompt")
           ("l" dumb-jump-quick-look "Quick look")
           ("b" dumb-jump-back "Back"))
  :config
  (setq dumb-jump-selector 'ivy)
)

region-occurrences-highlighter

(use-package region-occurrences-highlighter
  :ensure t
  :defer t
  :config
  (define-key region-occurrences-highlighter-nav-mode-map "\M-n" 'region-occurrences-highlighter-next)
  (define-key region-occurrences-highlighter-nav-mode-map "\M-p" 'region-occurrences-highlighter-prev))

Miscellaneous settings

The following settings don’t belong to any package.

(add-hook 'window-setup-hook 'toggle-frame-maximized t)

(defalias 'yes-or-no-p #'y-or-n-p)
(setq calendar-week-start-day 1)
(setq confirm-kill-emacs (quote y-or-n-p))
(setq-default cursor-in-non-selected-windows t)
(setq delete-by-moving-to-trash t)
(setq delete-old-versions -1)
(setq dired-auto-revert-buffer t)
(setq dired-listing-switches "-alhF")
(setq dired-ls-F-marks-symlinks t)
(setq echo-keystrokes 0.1)
(setq indicate-empty-lines t)
(setq inhibit-startup-screen t)
(setq initial-buffer-choice #'recentf-open-files)
(setq initial-scratch-message nil)
(setq kill-whole-line t)
(setq read-buffer-completion-ignore-case t)
(setq require-final-newline t)
(setq ring-bell-function #'ignore)
(setq safe-local-variable-values (quote ((org-tags-column . 148) (TeX-master . t))))
(setq save-interprogram-paste-before-kill t)
(setq uniquify-buffer-name-style 'post-forward-angle-brackets)
(setq vc-make-backup-files t)
(setq version-control t)
(setq sentence-end-double-space nil)
(setq x-stretch-cursor t)
(setq inhibit-compacting-font-caches t)
;; https://emacs.stackexchange.com/questions/33510/unicode-txt-slowness
(column-number-mode)
(blink-cursor-mode 0)
(pixel-scroll-mode)
(size-indication-mode)

;; distraction free mode
(menu-bar-mode -1)
(set-scroll-bar-mode nil)
(tool-bar-mode -1)
(diminish 'eldoc-mode)

;; UTF-8 handling
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-language-environment 'utf-8)
(set-terminal-coding-system 'utf-8)
(setq locale-coding-system 'utf-8)
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
(setq-default buffer-file-coding-system 'utf-8)
(unless (eq system-type 'windows-nt) (set-selection-coding-system 'utf-8))

Source as well as Source and Source

OS specific settings

(cond
 ((string-equal system-type "windows-nt") ; Microsoft Windows
  (progn
    (message "Microsoft Windows")
    ))
 ((string-equal system-type "darwin") ; Mac OS X
  (progn
    ;; (message "Mac OS X")
    (setenv "PATH" (concat "/Library/TeX/texbin" ":" (getenv "PATH")))
    (setq exec-path (append exec-path '("/Library/TeX/texbin")))
    (setenv "PATH" (concat "/Users/laurent/bin" ":" (getenv "PATH")))
    (setq exec-path (append exec-path '("/Users/laurent/bin")))
    (setenv "PATH" (concat "/opt/local/bin/" ":" (getenv "PATH")))
    (setq exec-path (append exec-path '("/opt/local/bin/")))
    (setenv "PATH" (concat "/usr/local/bin/" ":" (getenv "PATH")))
    (setq exec-path (append exec-path '("/usr/local/bin/")))
    ))
 ((string-equal system-type "gnu/linux") ; linux
  (progn
    (message "Linux")
    ))
 )

Keybindings

A great resource on keybindings: The Emacs Guru Guide to Key Bindings.

Some times I really hate the keyboard on MacBooks. The keybindings below make it somewhat bearable.

(cond
 ((string-equal system-type "windows-nt") ; Microsoft Windows
  (progn
    (message "Microsoft Windows")
    ))
 ((string-equal system-type "darwin") ; Mac OS X
  (progn
    (setq ns-command-modifier (quote meta))
    (setq ns-function-modifier (quote control))
    (setq ns-right-alternate-modifier (quote none))
    (setq ns-right-command-modifier (quote none))
    (global-set-key (kbd "C-ö") (lambda () (interactive) (insert "[")))
    (global-set-key (kbd "C-ä") (lambda () (interactive) (insert "]")))
    (global-set-key (kbd "C-ü") (lambda () (interactive) (insert "\\")))
    (global-set-key (kbd "M-ö") (lambda () (interactive) (insert "{")))
    (global-set-key (kbd "M-ä") (lambda () (interactive) (insert "}")))
    (global-set-key (kbd "M-ü") (lambda () (interactive) (insert "\\")))
    ))
 ((string-equal system-type "gnu/linux") ; linux
  (progn
    (message "Linux")
    ))
)

Generic keybindings

(define-key global-map (kbd "C-+") #'text-scale-increase)
(define-key global-map (kbd "C--") #'text-scale-decrease)
(global-set-key [remap goto-line] #'goto-line-with-feedback)
(global-set-key [remap fill-paragraph] #'endless/fill-or-unfill)
(global-set-key (kbd "C-<backspace>") (lambda () (interactive) (kill-line 0)))
(global-set-key (kbd "C-x C-r") #'counsel-recentf)
(global-set-key [remap goto-line] 'goto-line-preview)
(global-set-key (kbd "M-p") #'goto-column)

org mode configuration   org

I’ve started taking notes on my computer somewhere around 2009. Since then I’ve tried pretty much every note taking software that I could find. None of them were as fast and flexible as org mode. In addition, emacs runs on pretty much any OS, which is an absolute must for me.

I use org mode extensively for various tasks. When I attend a conference I usually have a list of all available presentations and I mark them with ATTEND or SKIP keyword depending on whether I think they are interesting enough. In addition I use priorities (A-B) to mark the most important ones. Priorities are also used in other contexts to mark importance.

Tasks are marked eith with TODO, HOLD or DONE depending on their state.

I have a file which serves as a small bugtracker for my various little projects. Since I am the sole developer on most of these, it doesn’t make sense to use anything fancier than a simple file. The bugs are labelled either with OPEN, BUG, IMPROVEMENT, RESOLVED. OPEN means I haven’t decided yet whether it’s a bug or desired behaviour. Finally, anything that I have given up on is labelled with CANCELED.

Tags are used in a hierarchical manner to further categorise my notes. The hierarchy looks as follows:

  • config
    • core
    • latex
    • org
    • fortran
  • work
    • conference
      • keynote
      • talk
      • poster
    • research
      • programming
      • mathematics
    • teaching
  • noexport
  • sort

noexport is used if I don’t want that something gets exported and sort is used for captured stuff that needs to be sorted into the right place. The variable org-todo-state-tags-triggers could be used to correlate certain keywords with certain tags, but currently I have no use case for it.

Colorising agenda view was copied from here.

TODO regex tag hierarchies

https://orgmode.org/manual/Tag-hierarchy.html#Tag-hierarchy

Fontify done checkbox items in org-mode (https://fuco1.github.io/2017-05-25-Fontify-done-checkbox-items-in-org-mode.html)

(font-lock-add-keywords
 'org-mode
 `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)" 1 'org-headline-done prepend))
 'append)
(defun diary-last-day-of-month (date)
"Return `t` if DATE is the last day of the month."
  (let* ((day (calendar-extract-day date))
         (month (calendar-extract-month date))
         (year (calendar-extract-year date))
         (last-day-of-month
            (calendar-last-day-of-month month year)))
    (= day last-day-of-month)))

   (use-package org
     :ensure org-plus-contrib
     :defer 7
     :mode ("\\.org$" . org-mode)
     :custom
     (org-agenda-show-future-repeats 'next)
     (org-agenda-skip-deadline-if-done t)
     (org-agenda-skip-scheduled-if-done t)
     (org-agenda-skip-timestamp-if-done t)
     (org-agenda-skip-unavailable-files t)
     (org-agenda-span 14)
     (org-agenda-start-on-weekday nil)
     (org-agenda-todo-ignore-deadlines t)
     (org-agenda-todo-ignore-scheduled t)
     (org-agenda-todo-ignore-timestamp t)
     (org-agenda-todo-ignore-with-date t)
     (org-confirm-babel-evaluate nil)
     (org-deadline-warning-days 0)
     (org-default-priority 65)
     (org-ellipsis " ⤵")
     (org-enforce-todo-checkbox-dependencies t)
     (org-enforce-todo-dependencies t)
     (org-fontify-done-headline t)
     (org-fontify-whole-heading-line t)
     (org-log-done (quote note))
     (org-log-into-drawer t)
     (org-log-refile (quote time))
     (org-pretty-entities t)
     (org-src-fontify-natively t)
     (org-src-tab-acts-natively t)
     (org-startup-with-inline-images t)
     (org-startup-with-latex-preview t)
     (org-tags-column -100)
     (org-tags-sort-function (quote string<))
     :init
     (setq org-agenda-files (list (getenv "ORGAGENDAPATH")))
     (setq org-directory (getenv "ORGAGENDAPATH"))
     (setq org-default-notes-file (getenv "ORGINBOXPATH"))
     (setq org-todo-keywords
           '(
             (sequence "TODO(t)" "INPROGRESS(i)" "DELEGATED(e)" "ONHOLD(h@/!)" "|" "DONE(d!)")
             (sequence                                                         "|" "CANCELED(c@)")))
     (setq org-todo-keyword-faces
           '(
             ("TODO" .        (:foreground "#dc322f" :weight bold))
             ("INPROGRESS" .  (:foreground "#dc322f" :weight bold))
             ("DELEGATED" .   (:foreground "#dc322f" :weight bold))
             ("ONHOLD" .      (:foreground "#b58900" :weight bold))
             ("DONE" .        (:foreground "#859900" :weight bold))
             ("CANCELED" .    (:foreground "#d33682" :weight bold))
             ))
     (setq org-tag-alist
           '(
             (:startgroup . nil)
             ("Job" . ?j) ("Exclusive" . ?e)
             (:endgrouptag . nil)
             (:startgroup . nil)
             ("julia" . ?j) ("latex" . ?l)
             (:endgrouptag . nil)
             ))
     (setq org-tag-faces
           '(
             ("Job" .       (:foreground "#268bd2" :weight bold))
             ("Exclusive" . (:foreground "#d33682" :weight bold))
             ("julia" .     (:foreground "#dc322f" :weight bold))
             ("latex" .     (:foreground "#dc322f" :weight bold))
             ))
     (setq org-priority-faces
           '(
             (?A . (:foreground "#dc322f"))
             (?B . (:foreground "#b58900"))
             (?C . (:foreground "#859900"))
             ))
     (setq org-capture-templates
           '(
             ("t" "ToDo" plain (file "")
              "* TODO %?\n %^T\n %i\n"
              :empty-lines 1)
             ("b" "Bug Tracker Entry" entry
              (file+olp (getenv "ORGBUGTRACKERPATH") "Open Issues")
              "* TODO %?\n %^{PROJECT}p %^{CREATED}p %^{IMPORTANCE}p")
             ))
     (setq org-agenda-custom-commands
           '(
             ("1" "Todays Agenda"
                  ((agenda "" ((org-agenda-span 'day)))))
             ("2" "Agenda and all TODOs"
                  ((agenda "") (alltodo "")))
             ("3" "Daily Overview"
                  ((agenda ""
                      ((org-agenda-overriding-header "Todays Appointments")
                       (org-agenda-span (quote day))
                       (org-agenda-remove-tags t)
                       (org-agenda-prefix-format " %i %?-12t% s")
                       (org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline 'scheduled))
                      ))
                   (agenda ""
                      ((org-agenda-overriding-header "Deadline Today")
                       (org-agenda-span (quote day))
                       (org-agenda-time-grid nil)
                       (org-agenda-prefix-format " %i %?-12t% s")
                       (org-agenda-remove-tags t)
                       (org-deadline-warning-days 1)
                       (org-agenda-entry-types '(:deadline))
                      ))
                   (agenda ""
                      ((org-agenda-overriding-header "Scheduled Today")
                       (org-agenda-span (quote day))
                       (org-agenda-time-grid nil)
                       (org-agenda-prefix-format " %i %?-12t% s")
                       (org-agenda-remove-tags t)
                       (org-agenda-skip-function '(org-agenda-skip-entry-if 'notscheduled))
                       (org-agenda-todo-ignore-scheduled 'future)
                      ))
                   (agenda "+CATEGORY=\"Meeting\""
                      ((org-agenda-span 2)
                       (org-agenda-time-grid nil)
                       (org-agenda-prefix-format " %i %?-12t% s")
                       (org-agenda-remove-tags t)
                       (org-agenda-overriding-header "Meetings Today")
                       (org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline 'scheduled))
                      ))
                   (tags-todo "+PRIORITY=\"A\""
                      ((org-agenda-overriding-header "High Priority")
                       (org-agenda-prefix-format " %i ")
                       (org-agenda-remove-tags t)
                      ))
                   (tags-todo "+PRIORITY=\"B\""
                      ((org-agenda-overriding-header "Medium Priority")
                       (org-agenda-prefix-format " %i ")
                       (org-agenda-remove-tags t)
                      ))
                   )
                nil nil)
             ("4" "Job"   tags-todo "job")
             ("5" "Open Bugs in my bugtracker" alltodo ""
               ((org-agenda-overriding-columns-format "%75ITEM(Title) %TODO(State) %PRIORITY(Importance) %ALLTAGS(Tag)")
                (org-agenda-view-columns-initially t)
                (org-agenda-files (getenv "ORGBUGTRACKERPATH"))
             ))
             ))
     :bind (("C-c l" . org-store-link)
            ("C-c a" . org-agenda)
            ("C-c c" . org-capture)
            ("C-c b" . org-iswitchb)))

(use-package calfw
  :ensure t
  ;; :init
  ;; (setq cfw:fchar-junction ?╋
  ;;     cfw:fchar-vertical-line ?┃
  ;;     cfw:fchar-horizontal-line ?━
  ;;     cfw:fchar-left-junction ?┣
  ;;     cfw:fchar-right-junction ?┫
  ;;     cfw:fchar-top-junction ?┯
  ;;     cfw:fchar-top-left-corner ?┏
  ;;    cfw:fchar-top-right-corner ?┓)
)

(use-package calfw-org
  :ensure t
)

LaTeX configuration   latex

I work with LaTeX on a daily basis. I need it to be as optimised to my workflow as possible. Concerning completion and automatic customisation, I should probably read Section 5.5 of the auctex manual again.

  (use-package langtool
     :ensure t
     :defer t
     :init
     (setq langtool-java-bin (getenv "JAVAPATH"))
     (setq langtool-language-tool-jar (getenv "LANGUAGETOOLJAR"))
)
(use-package tex-site :ensure auctex)
(use-package tex
  :ensure auctex
  :defer t
  :custom
  (TeX-auto-local "auto")
  (TeX-auto-save t)
  (TeX-clean-confirm t)
  (TeX-debug-bad-boxes t)
  (TeX-debug-warnings t)
  (TeX-electric-math (quote ("$" . "$")))
  (TeX-electric-sub-and-superscript t)
  (TeX-parse-self t)
  (TeX-source-correlate-mode t)
  :config
  (setq-default TeX-engine 'luatex)
  (setq-default TeX-master nil)
  (unless (assoc "PDF Tools" TeX-view-program-list-builtin)
    (push '("PDF Tools" TeX-pdf-tools-sync-view) TeX-view-program-list))
  (setq TeX-view-program-selection '((output-pdf "PDF Tools"))
        TeX-source-correlate-start-server t))
(use-package tex-buf
  :ensure auctex
  :defer t
  :custom
  (TeX-error-overview-open-after-TeX-run t)
  (TeX-error-overview-setup (quote separate-frame))
  (TeX-save-query t))
(use-package tex-mode :ensure auctex :defer t)
(use-package tex-style
  :ensure auctex
  :defer t
  :custom
  (LaTeX-includegraphics-read-file (quote LaTeX-includegraphics-read-file-relative)))
(use-package latex
    :ensure auctex
    :defer t
    :init
    (defcustom LaTeX-indent-level-item-continuation 4
    "*Indentation of continuation lines for items in itemize-like environments."
    :group 'LaTeX-indentation
    :type 'integer)
    (setq LaTeX-default-author "Laurent Hoeltgen")
    (setq LaTeX-default-environment "equation")
    (setq LaTeX-default-options (quote ("a4paper, 12pt")))
    (setq LaTeX-default-style "scrartcl")
    (setq LaTeX-electric-left-right-brace t)
    (setq LaTeX-indent-level 6)
    (setq LaTeX-indent-level-item-continuation 8)
    (setq LaTeX-item-indent -6)
    (setq LaTeX-math-menu-unicode t)
    (setq LaTeX-top-caption-list (quote ("table" "algorithm")))
    (cond
      ((string-equal system-type "windows-nt") ; Microsoft Windows
        (progn
          (setq LaTeX-math-abbrev-prefix "§")
        ))
      ((string-equal system-type "darwin") ; Mac OS X
        (progn
          (setq LaTeX-math-abbrev-prefix "#")
        ))
      ((string-equal system-type "gnu/linux") ; linux
        (progn
          (setq LaTeX-math-abbrev-prefix "§")
        ))
    )
    (setq font-latex-match-type-command-keywords
      (quote
        (("linkgraphics" "[{"))))
    (setq font-latex-match-slide-title-keywords
      (quote
        (("framesubtitle" "{")
         ("frametitle" "{")
         ("multisubtitle" "{"))))
    (setq font-latex-match-reference-keywords
      (quote
        (("cref" "{") ("eidx" "*{"))))
    (setq LaTeX-math-list (quote
      (("C-v" "vec" ("private") nil)
       ("C-a" "abs*" ("private") nil))))
    (add-hook 'LaTeX-mode-hook 'turn-on-reftex)
    (add-hook 'latex-mode-hook 'turn-on-reftex)
    (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
    (add-hook 'LaTeX-mode-hook 'outline-minor-mode)
; Moved to MyMathEnvironments.el
;    (add-hook 'LaTeX-mode-hook
;       (lambda ()
;           (LaTeX-add-environments
;               '("definition" LaTeX-env-label)
;               '("theorem" LaTeX-env-label)
;               '("proposition" LaTeX-env-label)
;               '("lemma" LaTeX-env-label)
;               )))
    :config
    (add-to-list 'LaTeX-font-list '(?\C-x "\\eidx*{" "}"))
;    (add-to-list 'LaTeX-label-alist
;       '(("theorem" . "thm:")
;         ("corollary" . "thm:")
;         ("proposition" . "thm:")
;         ("lemma" . "thm:")
;         ("definition" . "thm:")
;         ))
    (add-hook 'LaTeX-mode-hook
          (lambda ()
            (local-set-key (kbd "C-$") 'replace-matching-parens)
            (local-set-key [f9] 'TeX-error-overview)
            ))
  )

Reftex website. Useful for managing cross references, bibliographies, indices, and document navigation.

Source

(use-package reftex-vars
  :ensure reftex
  :defer t
  :commands turn-on-reftex
  :diminish reftex-mode
  :init
  (setq reftex-plug-into-AUCTeX t)
  :config
  (setq reftex-auto-recenter-toc t)
  (setq reftex-default-bibliography (getenv "LIBRARYPATH"))
  (setq reftex-enable-partial-scans nil)
  (setq reftex-index-follow-mode t)
  (setq reftex-keep-temporary-buffers t)
  (setq reftex-save-parse-info nil)
  (setq reftex-toc-follow-mode t)
  (setq reftex-toc-include-context t)
  (setq reftex-toc-include-file-boundaries t)
  ;; Unsure if this is working
  (setq reftex-label-alist
      '(
        ("theorem" ?A "thm:" "~\\ref{%s}" t ("Theorem" "theorem") -3)
        ("proposition" ?B "thm:" "~\\ref{%s}" t ("Proposition" "proposition") -3)
        ("lemma" ?C "thm:" "~\\ref{%s}" t ("Lemma" "lemma") -3)
        ("definition" ?D "thm:" "~\\ref{%s}" t ("Definition" "definition") -3)
        ("remark" ?E "rem:" "~\\ref{%s}" t ("Remark" "remark") -3)
        ("corollary" ?F "thm:" "~\\ref{%s}" t ("Corollary" "corollary") -3)
  ))
  (setq reftex-trust-label-prefix '("tab:" "fig:" "eq:"))
  (add-to-list 'reftex-section-levels '("frametitle" . 4) t)
  (add-to-list 'reftex-section-levels '("framesubtitle" . 5) t)
  ;; Provide basic RefTeX support for biblatex
  (add-to-list 'reftex-cite-format-builtin
               '(biblatex "biblatex"
                          ((?\C-m . "\\cite[]{%l}")
                           (?t . "\\textcite{%l}")
                           (?a . "\\autocite[]{%l}")
                           (?p . "\\parencite{%l}")
                           (?f . "\\footcite[][]{%l}")
                           (?F . "\\fullcite[]{%l}")
                           (?x . "[]{%l}")
                           (?X . "{%l}"))))
  (setq reftex-cite-format 'biblatex)
)

PDF-tools

Source

(use-package pdf-tools
  :ensure t
  :magic ("%PDF" . pdf-view-mode)
  :config
  ;; open pdfs scaled to fit page
  (setq-default pdf-view-display-size 'fit-page)
  ;; use normal isearch
  (define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward)
  ;; keyboard shortcuts
  (define-key pdf-view-mode-map (kbd "h") 'pdf-annot-add-highlight-markup-annotation)
  (define-key pdf-view-mode-map (kbd "t") 'pdf-annot-add-text-annotation)
  (define-key pdf-view-mode-map (kbd "D") 'pdf-annot-delete)
  (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer)
  (pdf-tools-install)
  :custom
  (pdf-view-resize-factor 1.1)
  (pdf-annot-activate-created-annotations t)
  )

BibTeX

I manage most of my literature with JabRef, having some support in emacs is useful sometimes, though.

(use-package bibtex
  :ensure t
  :config
  (bibtex-set-dialect 'biblatex)
)

Company and LSP

(use-package company
  :ensure t
  :defer 5
  :diminish
  )

(use-package company-posframe
  :ensure t
  :after company
  :diminish
  :config
  (company-posframe-mode 1)
)

(use-package lsp-mode
  :ensure t
  :commands lsp
  :diminish
  )

(use-package lsp-ui
  :ensure t
  :commands lsp-ui-mode
  :diminish
  :config
  (define-key lsp-ui-mode-map [remap xref-find-definitions] #'lsp-ui-peek-find-definitions)
  (define-key lsp-ui-mode-map [remap xref-find-references] #'lsp-ui-peek-find-references)
  )

(use-package company-lsp
  :ensure t
  :commands company-lsp
  :diminish
  :config
  (push 'company-lsp company-backends)
  )

Fortran configuration   fortran

Fortran file extensions are a mess. I use .F08 since much of my code relies on features either introduced in the 2003 or 2008 standard. Nevertheless, I encounter the other extensions from time to time, too. Also, Consider fypp files (fortran templates to be pre-processed) to be fortran code.

(use-package f90
  :ensure t
  :mode (("\\.f\\'" . f90-mode)
         ("\\.F\\'" . f90-mode)
         ("\\.f90\\'" . f90-mode)
         ("\\.F90\\'" . f90-mode)
         ("\\.f95\\'" . f90-mode)
         ("\\.F95\\'" . f90-mode)
         ("\\.f03\\'" . f90-mode)
         ("\\.F03\\'" . f90-mode)
         ("\\.f08\\'" . f90-mode)
         ("\\.F08\\'" . f90-mode)
         ("\\.fypp\\'" . f90-mode))
  :custom
  (f90-auto-keyword-case (quote downcase-word))
  (f90-continuation-indent 8)
  (f90-do-indent 4)
  (f90-if-indent 4)
  (f90-program-indent 4)
  (f90-type-indent 4)
  :hook (f90-add-imenu-menu abbrev-mode)
  )

(use-package eglot
  :ensure t
  :defer 5
  :config
  (add-to-list 'eglot-server-programs '(f90-mode . ("fortls")))
  :hook (f90-mode-hook . eglot-ensure)
  )

Set the fill column at 128 and highlight code that extends this column but not comments. Also show me the ruler at the top

(add-hook 'f90-mode-hook (lambda () (set-fill-column 128)))
(add-hook 'f90-mode-hook (lambda () (setq column-enforce-comments nil)))
(add-hook 'f90-mode-hook (lambda () (setq column-enforce-column 128)))
(add-hook 'f90-mode-hook 'column-enforce-mode)

Magit

(use-package magit
  :ensure t
  :defer t
  :after hydra
  :hydra (hydra-magit (:color blue :columns 8)
    "Magit"
    ("c" magit-status "status")
    ("C" magit-checkout "checkout")
    ("v" magit-branch-manager "branch manager")
    ("m" magit-merge "merge")
    ("l" magit-log "log")
    ("!" magit-git-command "command")
    ("$" magit-process "process"))
)

C++

(use-package modern-cpp-font-lock :ensure t)

(use-package ccls
  :ensure t
  :defer 5
  :hook ((c-mode c++-mode objc-mode) .
         (lambda () (require 'ccls) (lsp)))
  :config
  (setq ccls-executable (getenv "CCLSPATH"))
  )

(use-package clang-format
  :ensure t
  :defer t
)

(use-package clang-format+
  :ensure t
  :defer t
  :config
  (add-hook 'c-mode-common-hook #'clang-format+-mode))

(use-package ivy-xref
  :ensure t
  :init
  (setq xref-show-xrefs-function #'ivy-xref-show-xrefs)
)
(use-package projectile
  :ensure t
  :config
  (projectile-mode +1)
  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
)
(use-package treemacs
  :ensure t
  :defer t
  :init
  (with-eval-after-load 'winum
    (define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
  :config
  (progn
    (setq treemacs-collapse-dirs                 (if (executable-find "python") 3 0)
          treemacs-deferred-git-apply-delay      0.5
          treemacs-display-in-side-window        t
          treemacs-eldoc-display                 t
          treemacs-file-event-delay              5000
          treemacs-file-follow-delay             0.2
          treemacs-follow-after-init             t
          treemacs-git-command-pipe              ""
          treemacs-goto-tag-strategy             'refetch-index
          treemacs-indentation                   2
          treemacs-indentation-string            " "
          treemacs-is-never-other-window         nil
          treemacs-max-git-entries               5000
          treemacs-no-png-images                 nil
          treemacs-no-delete-other-windows       t
          treemacs-project-follow-cleanup        nil
          treemacs-persist-file                  (expand-file-name ".cache/treemacs-persist" user-emacs-directory)
          treemacs-recenter-distance             0.1
          treemacs-recenter-after-file-follow    nil
          treemacs-recenter-after-tag-follow     nil
          treemacs-recenter-after-project-jump   'always
          treemacs-recenter-after-project-expand 'on-distance
          treemacs-show-cursor                   nil
          treemacs-show-hidden-files             t
          treemacs-silent-filewatch              nil
          treemacs-silent-refresh                nil
          treemacs-sorting                       'alphabetic-desc
          treemacs-space-between-root-nodes      t
          treemacs-tag-follow-cleanup            t
          treemacs-tag-follow-delay              1.5
          treemacs-width                         35)

    ;; The default width and height of the icons is 22 pixels. If you are
    ;; using a Hi-DPI display, uncomment this to double the icon size.
    ;; (treemacs-resize-icons 44)

    (treemacs-follow-mode t)
    (treemacs-filewatch-mode t)
    (treemacs-fringe-indicator-mode t)
    (pcase (cons (not (null (executable-find "git")))
                 (not (null (executable-find "python3"))))
      (`(t . t)
       (treemacs-git-mode 'deferred))
      (`(t . _)
       (treemacs-git-mode 'simple))))
  :bind
  (:map global-map
        ("M-0"       . treemacs-select-window)
        ("C-x t 1"   . treemacs-delete-other-windows)
        ("C-x t t"   . treemacs)
        ("C-x t B"   . treemacs-bookmark)
        ("C-x t C-t" . treemacs-find-file)
        ("C-x t M-t" . treemacs-find-tag)))

(use-package treemacs-projectile
  :after treemacs projectile
  :ensure t)

(use-package treemacs-icons-dired
  :after treemacs dired
  :ensure t
  :config (treemacs-icons-dired-mode))

(use-package treemacs-magit
  :after treemacs magit
  :ensure t)

julia

(use-package julia-mode
  :mode "\\.jl\\'"
  :interpreter "julia"
  :ensure t)

(use-package julia-repl
  :ensure t
  :defer 5
  :config
  (add-hook 'julia-mode-hook 'julia-repl-mode)
  (setq julia-repl-executable-records
       '((default (getenv "JULIAPATH"))
         )))

;; (load "F:\\dev\\dotemacs\\lisp\\lsp-julia.el")
(load-relative "./lisp/lsp-julia")
(add-hook 'julia-mode-hook #'lsp-mode)
(setq lsp-julia-command (getenv "JULIAPATH"))
(setq lsp-julia-default-environment (getenv "JULIAENVPATH"))
(setq lsp-enable-snippet nil)

Cmake

(use-package cmake-mode
  :ensure t
  :mode
  ("CMakeLists\\.txt\\'" "\\.cmake\\'")
  )

(use-package cmake-font-lock
  :ensure t
  :after (cmake-mode)
  :hook (cmake-mode . cmake-font-lock-activate)
  )

;; (use-package cmake-ide
;;   :ensure t
;;   :after projectile
;;   :hook (c++-mode . my/cmake-ide-find-project)
;;   :preface
;;   (defun my/cmake-ide-find-project ()
;;     "Finds the directory of the project for cmake-ide."
;;     (with-eval-after-load 'projectile
;;       (setq cmake-ide-project-dir (projectile-project-root))
;;       (setq cmake-ide-build-dir (concat cmake-ide-project-dir "build")))
;;     (setq cmake-ide-compile-command
;;        (concat "cd " cmake-ide-build-dir " && cmake .. && make"))
;;     (cmake-ide-load-db)
;;     )

;;   (defun my/switch-to-compilation-window ()
;;     "Switches to the *compilation* buffer after compilation."
;;     (other-window 1))
;;   :bind ([remap comment-region] . cmake-ide-compile)
;;   :init (cmake-ide-setup)
;;   :config (advice-add 'cmake-ide-compile :after #'my/switch-to-compilation-window)
;;   )

Misc

(use-package htmlize
  :ensure t)

(setq org-html-htmlize-output-type 'css)