Skip to content

Latest commit

 

History

History
3301 lines (2872 loc) · 118 KB

my-usepackages.org

File metadata and controls

3301 lines (2872 loc) · 118 KB

My use-package configuration in org-mode

SYSENV Setup

SYSENV is an env variable i set to enable environment specific config (work / uni / private). Copied from the great baron42bba.

Set a SYSENV default.

(setenv "SYSENV" "work")

;; useful for non-mac systems where such kind of env variables can be easily set outside of emacs.
(if (equal (getenv "SYSENV") nil)
    (setenv "SYSENV" "home"))

Detect the SYSENV based on the wifi.

(message "Updating the SYSENV based on the connected wifi...")
(setq home-wifi "FRITZ!Box 7530 RG\n")
(if (string-equal home-wifi (shell-command-to-string "nmcli -g NAME connection show --active"))
    (setenv "SYSENV" "home"))
(if (or (string-equal system-type "gnu/linux") (string-equal system-type "darwin"))
    (setq fbr/home-dir "~"))
(if (string-equal system-type "windows-nt")
  (setq fbr/home-dir (concat "C:/Users/" (getenv "USERNAME"))))

Ignore Emacs 29.1 Warnings

(setq warning-minimum-level :error)

Initialization

(require 'use-package)
;; (setq debug-on-error t) (turn on if needed)
(setq package-check-signature nil) ;; disables public key errors that i dont feel like investigating

Keep .emacs.d clean

(use-package no-littering
  :ensure t
  :config
  (require 'recentf)
  (add-to-list 'recentf-exclude no-littering-var-directory)
  (add-to-list 'recentf-exclude no-littering-etc-directory)
  ;; stop undo-tree explicitly from littering
  (no-littering-theme-backups)
)
;; have elfeeds database in the cloud instead of ~/.emacs.d/var/
(setq elfeed-db-directory "~/Dropbox/org/elfeed/db/")

Keyboard macros

Convert a parameter in yaml-form to its json counterpart to be used by CloudFormation.

(fset 'convert_ceptre_to_cf
 (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([123 return tab 6 11 16 5 return tab 32 32 34 80 97 114 97 109 101 116 101 114 75 101 121 5 58 32 25 21 67108896 67108896 134217830 34 return 34 80 97 114 97 109 101 116 101 114 86 97 108 117 101 16 5 44 14 14 44 14 134217826 1 134217830 134217826] 0 "%d")) arg)))

Multiple Cursors

(use-package multiple-cursors
  :ensure t
  :config
  (global-set-key (kbd "C->") 'mc/mark-next-like-this)
  (global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
  (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
  )

File-browsing and text-searching

CamelCase

(global-subword-mode 1)
(use-package diminish
  :ensure t)
(diminish  'subword-mode)

Nerdtree

A file explorer side bar.

A couple of things annoyed me even after some time with the default behavior. Checking out the docs I found out all of these can be fixed with extra config. 😢 https://www.emacswiki.org/emacs/NeoTree

(use-package neotree
:ensure t
:config
(global-set-key [f12] 'neotree-toggle)
(setq neo-auto-refresh t)
(setq neo-show-hidden-files t)
(setq neo-theme 'icons)
(setq neo-window-fixed-size nil)
;; Every time when the neotree window is opened, let it find current file and jump to node.
(setq neo-smart-open t)
;; When running ‘projectile-switch-project’ (C-c p p), ‘neotree’ will change root automatically.
(setq projectile-switch-project-action 'neotree-projectile-action)

)
;(add-to-list 'load-path "/some/path/neotree")
;(require 'neotree)

All the icons

Required by neotree and requires also font setup

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

After install, run this once:

(all-the-icons-install-fonts)

Recentf

I hate browsing for files (I frequently use), this package is supposed to help me out with that.

Enriches the recentf view in helm browsing and enables crazy-fast file openings in combination with idos `C-x C-r`. Personally I only use helm though.

(use-package recentf
  :ensure t
  :config
  ;; When using TrampMode with recentf.el, it’s advisable to turn off the cleanup feature
  ;; of recentf that attempts to stat all the files and remove them from the recently accessed
  ;; list if they are readable. Tramp means that this requires recentf to open up a remote site
  ;; which will block your emacs process at the most inopportune times.
  (setq recentf-auto-cleanup 'never)
  (recentf-mode 1)
  (setq recentf-max-saved-items 0)
  ;; get rid of `find-file-read-only' and replace it with something more useful.
  (global-set-key (kbd "C-x C-r") 'ido-recentf-open)
  (defun ido-recentf-open ()
    "Use `ido-completing-read' to \\[find-file] a recent file"
    (interactive)
    (if (find-file (ido-completing-read "Find recent file: " recentf-list))
        (message "Opening file...")
      (message "Aborting")))
  )

Helm

A convenient interface to select about anything from a list: Browse files, select themes, show and select search-results and much more.

Helm-mini is a revolution to navigating through buffers!

(use-package helm
  :ensure t
  :init
  (define-key global-map "\C-xb" 'helm-mini)
  :config
  (setq helm-mini-default-sources '(helm-source-buffers-list
				    helm-source-recentf
				    helm-source-bookmarks
				    helm-source-buffer-not-found))
  (helm-mode 1)
  (global-set-key (kbd "M-x") 'helm-M-x)
  (define-key global-map "\C-c\C-s" 'helm-grep-do-git-grep)
  ;;(define-key global-map "\C-s" 'isearch-forward)
  ;; automatically resize the search window based on results (feels convenient)
  ;; (helm-autoresize-mode 1) ;; currently disabled since i keep using track of it due to the resizing
  )

A package that helps searching for text within the current file. Each matching line gets listed in an overview which is really good. A downfall to this is that it cant be used for keyboard-macros, for these the standard isearch works way better.

helm-swoop kept braking on my and didnt support coloring. Replaced it with swiper, which works great.

(global-set-key (kbd "C-s") 'swiper)
(use-package helm-ag
  :ensure t)

Projectile

(use-package projectile
  :ensure t
  :config
  (define-key projectile-mode-map (kbd "C-x p") 'projectile-command-map)
  (define-key projectile-mode-map (kbd "C-x p s") 'helm-projectile-ag)
  (projectile-mode +1)
  (setq helm-ag-ignore-patterns '("node_modules"))
  )

(use-package helm-projectile
  :ensure t
)

;; needed for projectile
(use-package ag
  :ensure t
  )

(use-package ripgrep
  :ensure t
  )

Finding files

As great as helm is, there is an even better file-finding package, however it hinders me from remote file editing, for which i then manually have to call “find-file”, which is an inconvenience.

(use-package counsel
  :ensure t
  :config
  (require 'swiper)
  (global-set-key (kbd "C-x C-f") 'counsel-find-file)
  )

Make this more convenient

Ideas:

  • Try the helm function again with better customization so it is convenient
  • Customize this open more so it does enable me to edit remote-files

Searching for strings

Deft searches for strings in my org-files, at work this takes forever to load though, so it is not a core part of my workflow. I might have to adapt to only search through text-files.

;; documentation over here: http://jblevins.org/projects/deft/
(use-package deft
  :if (or (equal "home" (getenv "SYSENV"))
          (equal "work" (getenv "SYSENV"))
       )
  :config
  (setq deft-extensions '("txt" "tex" "org" "md"))
  (setq deft-directory (concat fbr/home-dir "/Dropbox/org"))
  (setq deft-recursive t)
  (setq deft-use-filename-as-title t)
  )

This package searches for strings in the current textfile very conveniently since it gives you a quick overview over all of the search-results. This package however frequently breaks on windows, such that suddenly i can only scroll down in the result-list. Reinstalling the package fixes that, however that is a huge inconvenience. After reinstalling this package can break just by searching for “magit” in this file. That’s it, I’m suspending this package.

;; (use-package swiper-helm
;;   :ensure t
;;   :config
;;   (global-set-key (kbd "C-s") 'swiper-helm)
;;   (global-set-key (kbd "C-c u") 'swiper-all)
;;   )

Open the explorer

To open the OS-specific file-browser either use this command: M-! explorer . or the following code snippet:

(defun browse-current-folder ()
  "open the current buffer’s folder"
  (interactive)
  (browse-url (concat "file://" (file-name-directory (buffer-file-name))))
)
(global-set-key [M-f9] 'browse-current-folder)

Conveniences

Emojify mode

(use-package emojify
  :hook (after-init . global-emojify-mode)
  :config
  (custom-set-variables
   '(emojify-display-style 'image)
   '(emojify-emoji-styles '(unicode)))
  )

Undo-tree

Undo-tree provides a graphical representation of recent changes made to the file. When I first starting to use it it felt terrible, since a whole new window opens every time i call it. With time it has proven to be very helpful though.

This package is best used selectively, when i just want to undo something I use M-S-_, when I am not sure what just happened (maybe I deleted text on accident) I’ll definately use C-x u and go through the last couple of iterations.

(use-package undo-tree
  :ensure t
  :config
  (global-undo-tree-mode)
  )

Which-key

My guide for shortcuts i forget in part and for exploring options after already having pressed parts of a key-combination.

(use-package which-key
  :ensure t
  :config
  (which-key-setup-side-window-right)
  (setq which-key-popup-type 'side-window)
  (which-key-mode)
  :defer 5
  )

Immortal-scratch

Respawns the scratch buffer when its killed, feels just right

(use-package immortal-scratch
  :ensure t
  :config
  (immortal-scratch-mode t)
  )

Yasnippet

;; Currently there is a problem "package does not untar cleanly"
(use-package yasnippet
  :ensure t
  :init
  (define-key global-map "\C-cy" 'yas/insert-snippet)
  ;;(setq yas-snippet-dirs (append yas-snippet-dirs
  ;;"~/.emacs.d/elpa/yasnippet-20150912.1330/snippets/"))
  :config
  (yas-global-mode 1)
  (yas-reload-all)
  (setq yas-indent-line nil)
  (setq yas-triggers-in-field t)
  :defer 5
)

AWS snippets

(use-package aws-snippets
  :ensure t
  )

Beginend

Beginend is a package that is supposed to improve on the navigation to the beginning and end of buffer, depending on the mode of course.

(use-package beginend
  :ensure t
  :config
  (beginend-global-mode)
  )

Hydras

Code to easily, incrementally adjust the transparency settings:

(use-package hydra
  :ensure t
  )

(defun my--set-transparency (inc)
  "Increase or decrease the selected frame transparency"
  (let* ((alpha (frame-parameter (selected-frame) 'alpha))
         (next-alpha (cond ((not alpha) 100)
                           ((> (- alpha inc) 100) 100)
                           ((< (- alpha inc) 0) 0)
                           (t (- alpha inc)))))
    (set-frame-parameter (selected-frame) 'alpha next-alpha)))

(defhydra hydra-transparency (:columns 2)
  "
  ALPHA : [ %(frame-parameter nil 'alpha) ]
  "
  ("j" (lambda () (interactive) (my--set-transparency +1)) "+ more")
  ("k" (lambda () (interactive) (my--set-transparency -1)) "- less")
  ("J" (lambda () (interactive) (my--set-transparency +10)) "++ more")
  ("K" (lambda () (interactive) (my--set-transparency -10)) "-- less")
  ("=" (lambda (value) (interactive "nTransparency Value 0 - 100 opaque:")
         (set-frame-parameter (selected-frame) 'alpha value)) "Set to ?" :color blue))

Smooth-scrolling

This mode doesnt have a good interaction with C-l which centers the current line in the buffer to the middle, top and bottom. Using C-l to put the current line to the top of the buffer and then pressing UP results in an unpleasant shift of the buffer position. However for simple scrolling this is nice.

This mode also makes next-line and previous-line so slow that it is uncomfortable to use.

However scrolling is nice with this, lol. I have it disabled right now for its disadvantages

(use-package smooth-scrolling
  :ensure t
  :init
  (add-hook 'org-mode-hook (lambda () (smooth-scrolling-mode 1)))
  )

Smartparens

This package is sometimes not so smart, sometimes it inserts parenthesis when i dont want them, especially in org-mode. I need to customize this more.

;; smartparens, a mode that tries to be smart around parentheses of all kinds
(use-package smartparens
  :ensure t
  :init
  (smartparens-global-mode t)
  ;; make the overlay disappear
  (custom-set-faces '(sp-pair-overlay-face ((t nil))))
  )

Writeroom extension

(use-package writeroom-mode
:ensure t
:config
(setq writeroom-width 100)
)

Rainbow delimiters

This package is kind of a useless extension since the colors it uses are way too subtle

(use-package rainbow-delimiters
  :ensure t
  :init
  (add-hook 'emacs-lisp-mode-hook 'rainbow-delimiters-mode)
  )

Flyspell

Prerequisite on ubuntu is the following

sudo apt-get install aspell-de

I dont use this hook right now since it slow editing down a bit and correct spelling is actually not that crucial. Also writing german and english in the same document seems confusing for flyspell (as for every / most grammar correction programms).

(if (equal "home" (getenv "SYSENV"))
    (add-hook 'org-mode-hook 'turn-on-flyspell)
  )

The flyspell settings for work and home, requires a manual “aspell” installation.

(use-package flyspell
  :if (or (equal "home" (getenv "SYSENV")) (equal "work" (getenv "SYSENV")))
  :config
  (if (string-equal system-type "windows-nt") (add-to-list 'exec-path "C:/Program Files (x86)/Aspell/bin/"))
  (setq ispell-program-name "aspell")
  (global-set-key (kbd "<f8>") 'ispell-word)
  (global-set-key (kbd "C-<f8>") 'flyspell-mode)
  )

Exclude src-blocks from ispell spell-checking. Taken from here: https://github.com/jkitchin/jmax/blob/master/jmax.el

(add-to-list 'ispell-skip-region-alist '(org-property-drawer-re))
(add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
(add-to-list 'ispell-skip-region-alist '("cite:" . " "))
(add-to-list 'ispell-skip-region-alist '("label:" . " "))
(add-to-list 'ispell-skip-region-alist '("ref:" . " "))
(add-to-list 'ispell-skip-region-alist '("=" . "="))
(add-to-list 'ispell-skip-region-alist '("~" . "~"))
(add-to-list 'ispell-skip-region-alist '(":RESULTS:" . ":END:"))

Exclude src-blocks from flyspell spell-checking. Taken from here: https://emacs.stackexchange.com/questions/9333/how-does-one-use-flyspell-in-org-buffers-without-flyspell-triggering-on-tangled

;; NO spell check for embedded snippets
(defadvice org-mode-flyspell-verify (after org-mode-flyspell-verify-hack activate)
  (let* ((rlt ad-return-value)
         (begin-regexp "^[ \t]*#\\+begin_\\(src\\|html\\|latex\\|example\\|quote\\)")
         (end-regexp "^[ \t]*#\\+end_\\(src\\|html\\|latex\\|example\\|quote\\)")
         (case-fold-search t)
         b e)
    (when ad-return-value
      (save-excursion
        (setq b (re-search-backward begin-regexp nil t))
        (if b (setq e (re-search-forward end-regexp nil t))))
      (if (and b e (< (point) e)) (setq rlt nil)))
    (setq ad-return-value rlt)))
(use-package flyspell-correct-helm
  :ensure t
  :config
  (require 'flyspell-correct-helm)
  (define-key flyspell-mode-map (kbd "C-;") 'flyspell-correct-previous-word-generic)
  )

Copy-clipboard hack

Save whatever’s in the current (system) clipboard before replacing it with the Emacs’ text.

More tricks like this: https://github.com/dakrone/eos/blob/master/eos.org

(setq save-interprogram-paste-before-kill t)

Jump to split window

When splitting a window, I invariably want to switch to the new window. This makes that automatic.

(defun fbr/split-window-below-and-switch ()
  "Split the window horizontally, then switch to the new pane."
  (interactive)
  (split-window-below)
  (balance-windows)
  (other-window 1))

(defun fbr/split-window-right-and-switch ()
  "Split the window vertically, then switch to the new pane."
  (interactive)
  (split-window-right)
  (balance-windows)
  (other-window 1))

(global-set-key (kbd "C-x 2") 'fbr/split-window-below-and-switch)
(global-set-key (kbd "C-x 3") 'fbr/split-window-right-and-switch)

Tramp

Tramp can be used to edit remote files.

How to use tramp:

  • M-x load-file
  • /<remote username>@<remote host>:

Hint that my setup currently cannot work on windows:

(use-package tramp
  :ensure t
  :config
  ;; (setq tramp-verbose 5)
  (if (equal "home" (getenv "SYSENV"))
      (progn
        (setq default-tramp-method "plink")
        (setq ssh-program "TortoisePlink.exe")
        (setenv "PATH" (concat ssh-program ";" (getenv "PATH")))
        ;; Do autosaves locally
        (set-default 'tramp-auto-save-directory (concat "C:\\Users\\" (getenv "USERNAME") "\\AppData\\Local\\Temp"))
        )
    )
  ;; When connecting to a remote server it usually does source the profile, but for some
  ;; reason doesn't do that for $PATH by default. You'll have to specifically tell tramp
  ;; to do that from your .emacs with
  (add-to-list 'tramp-remote-path 'tramp-own-remote-path)
  ;; With this you can do /sudo:ssh-host:/path-to-file-on-ssh-host
  (add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
  )

A mode which reduces file interactions to a minimum, which i rarely use.

(define-minor-mode sensitive-mode
  "For sensitive files like password lists.
   It disables backup creation and auto saving.

   With no argument, this command toggles the mode.
   Non-null prefix argument turns on the mode.
   Null prefix argument turns off the mode."
  ;; The initial value.
  nil
  ;; The indicator for the mode line.
  " Sensitive"
  ;; The minor mode bindings.
  nil
  (if (symbol-value sensitive-mode)
      (progn
        ;; disable backups
        (set (make-local-variable 'backup-inhibited) t)
        ;; disable auto-save
        (if auto-save-default
            (auto-save-mode -1)))
    ;; resort to default value of backup-inhibited
    (kill-local-variable 'backup-inhibited)
    ;; resort to default auto save setting
    (if auto-save-default
        (auto-save-mode 1))))

Make bash files executable on save

This also makes groovy files executable which is undesired

(add-hook `after-save-hook
          #'(lambda ()
              (if (not
                   (or
                    (string-match ".htm" buffer-file-name)
                    (string-match ".org" buffer-file-name))
                   )
                  (check-parens))

              (and (save-excursion
                     (save-restriction
                       (widen)
                       (goto-char (point-min))
                       (save-match-data
                         (looking-at "^#!"))))
                   (if (file-remote-p buffer-file-name)
                       (progn
                         (not (file-executable-p buffer-file-name))
                         (shell-command (concat "chmod u+x " (file-name-nondirectory buffer-file-name)))
                         (message
                          (concat "Saved as script via tramp: " buffer-file-name))
                         )
                     (progn
                       (not (file-executable-p buffer-file-name))
                       (shell-command (concat "chmod u+x " buffer-file-name))
                       (message
                        (concat "Saved as script: " buffer-file-name)))))))

Tramp fixes

From Howards Blog: http://www.howardism.org/Technical/Emacs/literate-devops.html this is supposed to overwrite the standard org-mode function in ob-core.el which is buggy and can completely block the org-babel functionality on windows.

On windows the faulty file is here: <path_to_emacs>\emacs\share\emacs\24.5\lisp\org

(defun org-babel-temp-file (prefix &optional suffix)
  "Create a temporary file in the `org-babel-temporary-directory'.
Passes PREFIX and SUFFIX directly to `make-temp-file' with the
value of `temporary-file-directory' temporarily set to the value
of `org-babel-temporary-directory'."
  (if (file-remote-p default-directory)
      (let ((prefix
             ;; We cannot use `temporary-file-directory' as local part
             ;; on the remote host, because it might be another OS
             ;; there.  So we assume "/tmp", which ought to exist on
             ;; relevant architectures.
             (concat (file-remote-p default-directory)
                     ;; REPLACE temporary-file-directory with /tmp:
                     (expand-file-name prefix "/tmp/"))))
        (make-temp-file prefix nil suffix))
    (let ((temporary-file-directory
           (or (and (boundp 'org-babel-temporary-directory)
                    (file-exists-p org-babel-temporary-directory)
                    org-babel-temporary-directory)
               temporary-file-directory)))
      (make-temp-file prefix nil suffix))))

Fix for base64 error (currently unused / unnecessary) See footnotes here: http://www.howardism.org/Technical/Emacs/literate-devops.html

(setq tramp-remote-coding-commands '(b64 "base64" "base64 -d -i"))

Elfeed

(use-package elfeed
  :ensure t
  :bind (:map elfeed-search-mode-map
              ("m" . elfeed-toggle-star)
              ("U" . elfeed-update)
              )
  )
  :config
  (setq elfeed-search-filter "@6-months-ago")
(use-package elfeed-org
  :ensure t
  :config
  (elfeed-org)
  (if (equal "home" (getenv "SYSENV"))
  (setq rmh-elfeed-org-files (list (concat "C:\\Users\\" (getenv "USERNAME") "\\Dropbox\\org\\hobby\\elfeed.org")) ))
  )
  (if (equal "work" (getenv "SYSENV"))
  (setq rmh-elfeed-org-files (list "~/Dropbox/org/hobby/elfeed.org"))
  )

SQL

Thanks to baron42bba and https://truongtx.me/2014/08/23/setup-emacs-as-an-sql-database-client I yet have to actually test this config.

Also check:

;; truncate lines such that tables with many columns dont line-wrap
(add-hook 'sql-interactive-mode-hook
       (lambda ()
         (toggle-truncate-lines t)))

(defun my-sql-connect ()
  (interactive)
  (require 'my-password "~/.emacs_secrets.el.gpg")
  (setq sql-product 'mysql)

  (let ((connection (helm-comp-read
                     "Select server: "
                     my-sql-servers-alist
                     )))
    (sql-connect connection))
  (sql-rename-buffer)
  )

your ~/.emacs_secrets.el.gpg might look like:

(setq my-sql-servers-alist
      '("serverA" "serverB"))

(setq sql-connection-alist
      '((bbaprd (sql-product 'mysql)
                (sql-server "host42.foo.com")
                (sql-user "dbadmin")
                (sql-password "foo")
                (sql-database "serverA"))
        (bbatst (sql-product 'mysql)
                (sql-server "host42.foo.com")
                (sql-user "dbadmin")
                (sql-password "foo")
                (sql-database "serverB"))
        ))

(provide 'my-password)

Modeline

I never learned how to successfully edit the modeline yet, i just keep copying configs from nice screenshots which then only work in part so i have to delete them again lol. Some themes come with okay modeline configurations.

I Load it after the theme since themes sometimes set their own mode-line.

Former problem: use-package doesnt find spaceline-config or spaceline, doest this still exist?

Telephone Line

(use-package telephone-line
  :ensure t
  :config
  (telephone-line-mode 1)
  )

Spaceline config

Another modeline config taken from here: https://github.com/prassee/prassee-emacs-theme

(use-package spaceline
  :init
  (progn
    (require 'spaceline-config)
    (setq powerline-default-separator 'slant)
    (setq spaceline-workspace-numbers-unicode t)
    (setq spaceline-separator-dir-left '(left . left))
    (setq spaceline-separator-dir-right '(right . right))
    (setq powerline-height 27)
    (spaceline-toggle-window-number-on)
    (spaceline-toggle-buffer-modified-on)
    (spaceline-toggle-major-mode-on)
    (spaceline-toggle-battery-off)
    (spaceline-toggle-hud-on)
    (spaceline-toggle-projectile-root-off)
    (spaceline-emacs-theme)
    (spaceline-toggle-minor-modes-off)
    ))
;; first try to make the inactive face more readable
;; (custom-set-faces
;;  `(mode-line-inactive
;;    ((t (:background "grey40")))))

Modeline helpers

Idea taken from: http://manuel-uberti.github.io/emacs/2018/03/10/moody-and-minions/

(use-package minions
  :ensure t
  :init (minions-mode)
  :config
  (setq minions-mode-line-lighter "#")
  (setq minions-direct '(flycheck-mode))
  )
(use-package moody
  :ensure t
  :config
  (moody-replace-mode-line-buffer-identification)
  (moody-replace-vc-mode))

Magit

On some systems the “GIT_ASKPASS” variable i set leads to a nice GUI for entering usename on passwords, on other systems i get an ugly error-message everytime i “git push”. This is open for improvement but not a big issue.

I dont load this package on systems where i dont have the “SYSENV” environment variable set. The reason being that magit requires a relatively new git version, and to avoid the magit warning about the old version of git that is probably installed on fresh systems i rather dont even use it.

;; set the key-binding unconditionally for times when magit is not yet loaded yet due to the
;; usepackage-defer option
(define-key global-map (kbd "C-c m") 'magit-status)
;; Warning: The Windows User-Home needs to be in some kind of path such that magit finds the
;; .gitconfig
(use-package magit
  :ensure t
  :config
  (if (string-equal system-type "windows-nt")
      (progn
        (add-to-list 'exec-path "C:/Program Files/Git/bin")
        (setenv "GIT_ASKPASS" "git-gui--askpass")
        )
    )
  (if (string-equal system-type "darwin")
      (progn
        (add-to-list 'exec-path "/usr/bin")
        (add-to-list 'exec-path "/opt/homebrew/bin")
        (setenv "PATH" (concat (getenv "PATH") ":/Library/TeX/texbin"))
        (setenv "PATH" (concat "/opt/homebrew/opt/node@14/bin" ":" (getenv "PATH")))
        (add-to-list 'exec-path "/opt/homebrew/opt/node@14/bin")
        (setenv "PATH" (concat "/opt/homebrew/bin" ":" (getenv "PATH")))
        (add-to-list 'exec-path "/opt/homebrew/bin")
        (setenv "PATH" (concat "/opt/homebrew/sbin" ":" (getenv "PATH")))
        (add-to-list 'exec-path "/opt/homebrew/sbin")
        (add-to-list 'exec-path "/Users/felix.brilej/.nvm/versions/node/v14.19.1/bin/astro-ls")
        (setenv "GIT_SSH_COMMAND" "/usr/bin/ssh")
        (add-to-list 'exec-path "/Users/felix.brilej/.cargo/bin")
        (setenv "PATH" (concat "/Users/felix.brilej/.cargo/bin" ":" (getenv "PATH")))
        )
    )
  )

Also use this:

(use-package git-timemachine
  :ensure t
  )
(use-package magit-todos
  :ensure t
  :config
  (require 'magit-todos)
  )
(use-package git-link
  :ensure t
  :config
  (setq git-link-open-in-browser t)
  (global-set-key (kbd "C-x l g") 'git-link)
  )

Warn if username and useremail are not set

Define emacs shutdown function (taken from baron42bba)

Emacs is a powerful tool, so powerfull that i need to protect myself from deleting huge chunks of my org-files on accident without noticing. I can do this by committing after each day of work, so if i find out today that recently i must have deleted some part of my org-file i can go back into the file-history to bring it back. The emacs backup-files dont help in this scenario.

;; define function to shutdown emacs server instance
(defun server-shutdown ()
  "Save buffers, Quit, and Shutdown (kill) server"
  (interactive)
  (save-some-buffers)
  (if (equal "home" (getenv "SYSENV"))
      (progn
        (setq fbr/my-git-dir (concat fbr/home-dir "/Dropbox/org/gtd/"))
        (shell-command (concat "git --work-tree " fbr/my-git-dir " --git-dir " fbr/my-git-dir ".git commit -a -m 'autocommit'"))
        (shell-command (concat "git --work-tree " fbr/my-git-dir " --git-dir " fbr/my-git-dir ".git push backup master"))
        ))
  (if (equal "work" (getenv "SYSENV"))
      (progn
        (setq fbr/my-git-dir (concat "~/Documents/org/"))
        (shell-command (concat "git --work-tree " fbr/my-git-dir " --git-dir " fbr/my-git-dir ".git commit -a -m 'autocommit'"))
        ;; (shell-command (concat "git --work-tree " fbr/my-git-dir " --git-dir " fbr/my-git-dir ".git push backup master")) ;; we dont need a backup here
        ))
  (kill-emacs)
  )

Programming

Rust

Using the rust-analyzer + rustic which i installed like so: https://rust-analyzer.github.io/manual.html#emacs

Issues with my setup:

  • debugging does not work
    • workaround: use logging
  • I cannot resolve std:: crates

Enable Debugging: (work in progress)

(use-package dap-mode
  :ensure t
  :config
  (require 'dap-cpptools)
  )
(use-package rustic
  :ensure t
  :config
  (require 'dap-cpptools)
  :after (company flycheck)
  :hook ((rustic-mode . display-line-numbers-mode))
  )

(with-eval-after-load 'rustic
  (define-key company-active-map (kbd "<tab>") #'company-indent-or-complete-common))

Gitlab

(use-package gitlab-ci-mode
  :ensure t)

Astro Build

Needs first a manual installation:

npm i -g @astrojs/language-server @astrojs/ts-plugin
;;(add-to-list 'auto-mode-alist '("\\.astro\\'" . lsp-mode))

Astro LSP Workaround

    (use-package web-mode
      :ensure t
      :custom
(web-mode-markup-indent-offset 2)
(web-mode-css-indent-offset 2)
(web-mode-code-indent-offset 2))
    (define-derived-mode astro-mode web-mode "astro")
    (setq auto-mode-alist
          (append '((".*\\.astro\\'" . astro-mode))
                  auto-mode-alist))

    (with-eval-after-load 'lsp-mode
      (add-to-list 'lsp-language-id-configuration
                   '(astro-mode . "astro"))

      (lsp-register-client
       (make-lsp-client :new-connection (lsp-stdio-connection '("astro-ls" "--stdio"))
                        :activation-fn (lsp-activate-on "astro")
                        :server-id 'astro-ls)))
(add-hook 'astro-mode-hook 'my-astro-mode-hook)
(defun my-astro-mode-hook ()
  (lsp-mode 1))

Git Highlight changes

(use-package diff-hl
  :ensure t
  :config
  (global-diff-hl-mode)
  (global-diff-hl-show-hunk-mouse-mode 1)
)

Line numbers (linum)

(add-hook 'groovy-mode-hook (lambda () (display-line-numbers-mode)))
(add-hook 'python-mode-hook (lambda () (display-line-numbers-mode)))
(add-hook 'bash-mode-hook (lambda () (display-line-numbers-mode)))
(add-hook 'yaml-mode-hook (lambda () (display-line-numbers-mode)))
(add-hook 'go-mode-hook (lambda () (display-line-numbers-mode)))

Highlight todo, fixme, etc.

(setq hl-todo-keyword-faces
      '(("TODO"   . "#efe4a1")
        ("BUGBUG"  . "#ff5faf")
        ("FIXME"  . "#ff5faf")
        ("NICETOHAVE" . "#1E90FF")
        ("DEBUG"  . "#1E90FF")
        ("GOTCHA" . "#1E90FF")
        ("STUB"   . "#1E90FF")
        ("DONE"   . "#7FFFD4")))
(global-hl-todo-mode)

Yaml

(use-package yaml-mode
  :ensure t
  )

Add a horizontal line while editing yaml.

(use-package highlight-indent-guides
  :ensure t
  :config
  (setq highlight-indent-guides-method 'column)
  (setq highlight-indent-guides-responsive 'top)
  (require 'yaml-mode)
  (add-hook 'yaml-mode-hook 'highlight-indent-guides-mode)
  )

GraphQl

(use-package graphql-mode
  :ensure t
  :config
  ;; support also weird .graphqls file ending at work
  (add-to-list 'auto-mode-alist '("\\.graphqls\\'" . graphql-mode))
  )

CloudFormation

(defun bba-aws-cfn-lint()
  "Check buffer with cfn_lint."
  (interactive)
  (shell-command (concat "cfn-lint -i W E3008 E3012 -t" buffer-file-name)))
(require 'yaml-mode)
(define-key yaml-mode-map (kbd "C-c C-l") 'bba-aws-cfn-lint)
(use-package flycheck
  :ensure t
  )
(require 'flycheck)
(flycheck-define-checker yaml-cfnlint
  "A YAML syntax checker using cfn-lint."
  :command ("cfn-lint" "-f" "parseable" source)
  :error-patterns
  ((error line-start (file-name) ":" line ":" column ":" num ":" num ":" word ":" (message) line-end)
   (warning line-start (file-name) ":" line ":" column ":" num ":" num ":" word ":" (message) line-end))
  :modes yaml-mode)

;;;###autoload
(defun flycheck-yamllint-setup ()
  "Setup Flycheck YAMLLint integration."
  (interactive)
  (add-to-list 'flycheck-checkers 'yaml-cfnlint))

(provide 'flycheck-cfnlint)

Terraform

(use-package company-terraform
  :ensure t
  :init
  (company-terraform-init)
  :config
  (add-hook 'terraform-mode-hook (lambda () (company-mode)))
  )

Other hooks:

(add-hook 'terraform-mode-hook (lambda () (display-line-numbers-mode)))
(add-hook 'terraform-mode-hook (lambda () (flycheck-mode)))
(setq flycheck-terraform-tflint-executable "/usr/local/bin/tflint")

Golang

Guide: http://tleyden.github.io/blog/2014/05/22/configure-emacs-as-a-go-editor-from-scratch/

(add-to-list 'exec-path "/Users/felix.brilej/go/bin")
(defun my-go-mode-hook ()
  ; Call Gofmt before saving
  ;(add-hook 'before-save-hook 'gofmt-before-save)
  ; Godef jump key binding
  (local-set-key (kbd "M-.") 'godef-jump)
  (local-set-key (kbd "M-*") 'pop-tag-mark)
  )
(add-hook 'go-mode-hook 'my-go-mode-hook)
(add-hook 'go-mode-hook (lambda () (lsp-mode)))

VTL Velocity Template Language

Super old mode for vtl templates. Does coloring only. Only works when activated ad-hoc, not on file load.

;;; vtl.el --- fontify velocity template language code

;; Author: Brian Leonard <brian@brainslug.org>
;; Maintainer: brian@brainslug.org
;; Keywords: extensions
;; Created: 2002-01-19

;; $Id: vtl.el 191743 2005-06-21 23:22:20Z dlr $

;;; Commentary:

;; $variable     - font-lock-variable-name-face
;; #foreach      - font-lock-keyword-face
;; #mymacro      - font-lock-function-name-face
;; ## comment    - font-lock-comment-face
;; #* comment *# - font-lock-comment-face
;;
;; $customer.Address
;;    ^^^      ^^^
;;     |        +--- font-lock-variable-name-face
;;     +--- font-lock-type-face
;;
;; $customer.getAddress()
;;    ^^^        ^^^
;;     |          +--- font-lock-function-name-face
;;     +--- font-lock-type-face
;;

;; One useful way to enable this minor mode is to put the following in your
;; .emacs:
;;
;;      (autoload 'turn-on-vtl-mode "vtl" nil t)
;;      (add-hook 'html-mode-hook 'turn-on-vtl-mode t t)
;;      (add-hook 'xml-mode-hook 'turn-on-vtl-mode t t)
;;      (add-hook 'text-mode-hook 'turn-on-vtl-mode t t)

;;; Code:

(require 'font-lock)
(require 'cl)


(defgroup vtl nil
  "Fontifies VTL code.  see http://jakarta.apache.org/velocity/"
  :group 'vtl
  :group 'font-lock
  :group 'extensions)

;;;###autoload
(defcustom vtl-mode nil
  "*If non-nil, fontify vtl code

This variable is buffer-local."
  :type 'boolean)
(make-variable-buffer-local 'vtl-mode)

;;;###autoload
(defcustom vtl-minor-mode-string " VTL"
  "*String to display in mode line when VTL Mode is enabled."
  :type 'string
  :group 'vtl)

;;;###autoload
(defun turn-on-vtl-mode ()
  "Unequivocally turn on vtl-mode (see variable documentation)."
  (interactive)
  (font-lock-mode 1)
  (vtl-mode 1))

;; Put minor mode string on the global minor-mode-alist.
;;;###autoload
(cond ((fboundp 'add-minor-mode)
       (add-minor-mode 'vtl-mode 'vtl-minor-mode-string))
      ((assq 'vtl-mode (default-value 'minor-mode-alist)))
      (t
       (setq-default minor-mode-alist
                     (append (default-value 'minor-mode-alist)
                             '((vtl-mode vtl-minor-mode-string))))))



;;;###autoload
(defun vtl-mode (&optional prefix)
  "Toggle VTL Mode.

If called interactively with no prefix argument, toggle current condition
of the mode.
If called with a positive or negative prefix argument, enable or disable
the mode, respectively."
  (interactive "P")

  (setq vtl-mode
	(if prefix
	    (>= (prefix-numeric-value prefix) 0)
	  (not vtl-mode)))

  (cond (vtl-mode
	 ;; first, grab default
	 (font-lock-mode 0)
	 (font-lock-set-defaults)

	 ;; add vtl regexps
	 (setq font-lock-keywords
	       (let ((new-keywords
		      (cond ((null font-lock-keywords)
			     vtl-keywords)
			    (t
			     (list* (car font-lock-keywords)
				    (append (cdr font-lock-keywords)
					    vtl-keywords))))))
		 new-keywords))

	 ;; and restart font-lock
	 (font-lock-mode 1)
	 (font-lock-fontify-buffer))

	(t
	 ;; reset to major mode's defaults
	 (font-lock-mode 0)
	 (font-lock-set-defaults)
	 (font-lock-mode 1)
	 (font-lock-fontify-buffer)))

  (and (interactive-p)
       (if vtl-mode
           (message "vtl-mode is enabled")
         (message "vtl-mode is disabled")))
  vtl-mode)



(defvar vtl-keywords
  (let
      ((directive (concat "\\(#\\(set\\|if\\|elseif\\|else\\|foreach\\|end\\|"
			  "include\\|parse\\|stop\\|macro\\)\\)"))
       (variable "\\(\\$[!]?[{]?[a-zA-Z][a-zA-Z0-9---_]*[}]?\\)")
       (property
	(concat "\\(\\$[{]?[a-zA-Z][a-zA-Z0-9---_]*\\.\\)"
		"\\([a-zA-Z][a-zA-Z0-9---_]*\\)\\([}]?\\)"))
       (method
	(concat "\\(\\$[{]?[a-zA-Z][a-zA-Z0-9---_]*\\.\\)"
		"\\([a-zA-Z][a-zA-Z0-9---_]*\\)[ ]*\\(([^)]*)\\)[}]?"))
       (vmmacro "\\(#[a-zA-Z][a-zA-Z0-9---_]*\\)[ ]*\\(([^)]*)\\)")
       (line-comment "##.*$")
       (long-comment "\\(#\\*\\([^\\*]\\|\\*[^#]\\)*\\*#\\)"))

    (list
     (list variable '(1 font-lock-variable-name-face t))
     (list property '(1 font-lock-type-face t))
     (list property '(2 font-lock-variable-name-face t))
     (list property '(3 font-lock-type-face t))
     (list method '(1 font-lock-type-face t))
     (list method '(2 font-lock-function-name-face t))
     (list vmmacro '(1 font-lock-function-name-face t))
     (list directive '(1 font-lock-keyword-face t))
     (list line-comment '(0 font-lock-comment-face t))
     (list long-comment '(0 font-lock-comment-face t)))))



(provide 'vtl)

Jenkins Groovy

(setq groovy-indent-offset 2)

Paranthesis highlighting

Taken from https://github.com/baron42bba/.emacs.d/blob/master/bba.org#set-theme-bba1

(show-paren-mode 1)
(setq show-paren-style 'expression)

       '(show-paren-match ((t (:underline (:color "#07e30d" :style line)))))
       '(show-paren-mismatch ((t (:underline (:color "red" :style wave)))))
 ;(use-package highlight-sexp)
(require 'highlight-sexp)
(add-hook 'lisp-mode-hook 'highlight-sexp-mode)
(add-hook 'emacs-lisp-mode-hook 'highlight-sexp-mode)

Markdown mode

(use-package markdown-mode
  :ensure t
  :commands (markdown-mode gfm-mode)
  :mode (("README\\.md\\'" . gfm-mode)
         ("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :init (setq markdown-command "multimarkdown"))

Flycheck for Puppet

Taken from baron42bba’s config: https://github.com/baron42bba/.emacs.d/blob/master/bba.org#flycheck

Install the prerequisites

sudo apt install ruby
sudo gem install puppet-lint

Setup flycheck. Modified puppet-lint definition to include no-80chars-check and fixed log-format.

(use-package flycheck
  :if (equal "work" (getenv "SYSENV"))
  :config
  ;(add-hook 'after-init-hook #'global-flycheck-mode)
  (flycheck-define-checker puppet-lint
   "A Puppet DSL style checker using puppet-lint.
    See URL `http://puppet-lint.com/'."
   ;; We must check the original file, because Puppetlint is quite picky on the
   ;; names of files and there place in the directory structure, to comply with
   ;; Puppet's autoload directory layout.  For instance, a class foo::bar is
   ;; required to be in a file foo/bar.pp.  Any other place, such as a Flycheck
   ;; temporary file will cause an error.
   :command ("puppet-lint"
             "--no-80chars-check" "--no-140chars-check" "--log-format" "%{path}:%{line}:%{kind}: %{message} (%{check})"
             source-original)
         :error-patterns
         ((warning line-start (file-name) ":" line ":warning: " (message) line-end)
          (error line-start (file-name) ":" line ":error: " (message) line-end))
         :modes puppet-mode
         ;; Since we check the original file, we can only use this syntax checker if
         ;; the buffer is actually linked to a file, and if it is not modified.
         :predicate flycheck-buffer-saved-p)
  (setq puppet-lint-command
	(concat
	 "puppet-lint --with-context "
	 "--no-80chars-check "
	 "--no-puppet_url_without_modules-check "
	 "--fail-on-warnings "
	 "--log-format \"%{path}:%{line}: %{kind}: %{message} (%{check})\""
	 )
        )
  (setq flycheck-json-python-json-executable "python2.7")
  )

Json

 (setq json-reformat:indent-width 2)
 (setq js-indent-level 2)
(add-to-list 'auto-mode-alist '("\\.json\\'" . js-mode))
(use-package flymake
:ensure t
)
(use-package flymake-json
:ensure t
)
(defun fbr/json-mode-before-save-hook ()
  (when (eq major-mode 'json-mode)
    (flymake-json-load)))
(add-hook 'before-save-hook #'fbr/json-mode-before-save-hook)

Editorconfig

There is a project which provides a coding style configuration accross editors called “Editorconfig”: http://editorconfig.org/

This is used only at work.

(use-package editorconfig
  :if (equal "work" (getenv "SYSENV"))
  :config
  (editorconfig-mode '1)
)

Typescript

Company coding style: 2 tab indentation

(setq typescript-indent-level 2)

Prettier

(use-package prettier-js
  :ensure t)
;; (eval-after-load 'web-mode
;;     '(progn
;;        (add-hook 'web-mode-hook #'prettier-js-mode))

Helpers

(defun convert-to-template-string ()
  "Converts the string around point to a template string."
  (interactive)
  (save-excursion
    (let ((start-point (re-search-backward "[\"'].*\\${" (line-beginning-position) t))
          (end-point (re-search-forward "}.*[\"']" (line-end-position) t)))
      (when (and start-point end-point (< start-point end-point))
       (message "Start point: %s, End point: %s" start-point end-point)
        (goto-char start-point)
        (delete-char 1)
        (insert "`")
        (goto-char end-point)
        (delete-char -1)
        (insert "`")
        ))))


(defun templatestring-tab-function ()
  "Wrapper for both default Tab behavior and convert-to-template-string."
  (interactive)
  (call-interactively 'company-indent-or-complete-common) ; Call the default Tab behavior
  (convert-to-template-string))

Typescript programing (LSP-Mode)

I’m attempting to move to LSP-mode but it is giving me issues on my work laptop with many big projects. Tide still seems more battle-tested.

Helpful:

(use-package lsp-mode
  :init
  ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
  (setq lsp-keymap-prefix "C-c l")
  :after company
  :config
  (local-set-key (kbd "TAB") #'company-indent-or-complete-common)
  :after (typescript-mode company flycheck)
  :bind
  (:map lsp-mode-map
  ("<tab>" . company-indent-or-complete-common))
  :hook (;; replace XXX-mode with concrete major-mode(e. g. python-mode)
         (typescript-mode . lsp)
         (js-mode . lsp)
         ;; if you want which-key integration
         (lsp-mode . lsp-enable-which-key-integration)
         (lsp-mode . display-line-numbers-mode))
  :commands lsp)

;; optionally
(use-package lsp-ui :commands lsp-ui-mode)
;; if you are helm user
(use-package helm-lsp :commands helm-lsp-workspace-symbol)
;; if you are ivy user
(use-package lsp-ivy :commands lsp-ivy-workspace-symbol)
(use-package lsp-treemacs :commands lsp-treemacs-errors-list)

;; optionally if you want to use debugger
(use-package dap-mode)
;; (use-package dap-LANGUAGE) to load the dap adapter for your language

;; optional if you want which-key integration
(use-package which-key
    :config
    (which-key-mode))

(with-eval-after-load 'lsp-mode
  (define-key company-active-map (kbd "<tab>") #'company-indent-or-complete-common))

Typescript programming (Tide, inactive)

Helpful for editing CDK stacks and infrastructure code!

I’m attempting to move away from it though as lsp-mode has a nice headerline and it seems the more future proof approach tide issue.

Tide: typescript mode for emacs

(use-package tide
  :ensure t
  :config
  (define-key company-mode-map (kbd "TAB") #'company-indent-or-complete-common)
  (define-key tide-mode-map (kbd "C-x f") #'tide-fix)
  (define-key tide-mode-map (kbd "C-x lr") #'tide-references)
  (define-key tide-mode-map (kbd "C-x rs") #'tide-rename-symbol)
  (define-key tide-mode-map (kbd "C-x rf") #'tide-rename-file)
  (define-key tide-mode-map (kbd "C-x re") #'next-error)
  (define-key tide-mode-map (kbd "TAB") #'templatestring-tab-function)
  :after (typescript-mode company flycheck)
  :hook ((typescript-mode . tide-setup)
         (typescript-mode . tide-hl-identifier-mode)
         (before-save . tide-format-before-save))
  )

(defun setup-tide-mode ()
    (interactive)
    (tide-setup)
    (flycheck-mode +1)
    (setq flycheck-check-syntax-automatically '(save mode-enabled))
    (eldoc-mode +1)
    (tide-hl-identifier-mode +1)
    (display-line-numbers-mode +1)
    ;; company is an optional dependency. You have to
    ;; install it separately via package-install
    ;; `M-x package-install [ret] company`
    (company-mode +1))

  ;; aligns annotation to the right hand side
  (setq company-tooltip-align-annotations t)

  ;; formats the buffer before saving
  (add-hook 'before-save-hook 'tide-format-before-save)

  (add-hook 'typescript-mode-hook #'setup-tide-mode)

  ;; javascript
  (add-hook 'js2-mode-hook #'setup-tide-mode)
  (add-hook 'js-mode-hook #'setup-tide-mode)
  (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode))
  (add-to-list 'auto-mode-alist '("\\.mjs\\'" . typescript-mode))
  ;; configure javascript-tide checker to run after your default javascript checker

;;(setq tide-tsserver-executable "/Users/felix.brilej/.nvm/versions/node/v14.19.1/lib/node_modules/ts-node/node_modules/.bin/tsserver")
(defun my-tide-hook ()
  (when (and (eq major-mode 'typescript-mode)
             (projectile-project-p))
    ;; Your custom hook logic for TypeScript projects goes here
    (message "Executing hook for TypeScript projects")))

Company mode for auto-completion

(with-eval-after-load 'tide
  (define-key company-active-map (kbd "M-ö") #'company-complete)
  (define-key company-active-map (kbd "M-.") #'company-show-location)
  ;;(define-key company-active-map (kbd "RET") nil)
  (define-key company-active-map (kbd "<tab>") #'company-indent-or-complete-common)
  (define-key company-active-map (kbd "TAB") #'company-complete-common-or-cycle)
  (define-key company-active-map (kbd "<backtab>") (lambda () (interactive)
      (company-complete-common-or-cycle -1))))

;; company
(setq company-idle-delay "0")

Python programming

Disable the eldoc-mode which brings up that python-help buffer everytime:

(global-eldoc-mode -1)

My attempt at linting. Based on this blog post: https://blog.ironboundsoftware.com/2016/12/05/improving-your-python-pylint-and-flake8-emacs/

(use-package elpy
  :ensure t
  :init
  (elpy-enable)
  :config
  (when (require 'flycheck nil t)
    (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
    (add-hook 'elpy-mode-hook 'flycheck-mode))
  )
  (setq elpy-formatter "flake8")

C Lang

The main thing i use from the following is the “jump to definition” function, which is otherwise a tedious manual task.

Needs the external tool ggtags!

(use-package helm-gtags
  :config
  ;; Enable helm-gtags-mode
  (add-hook 'dired-mode-hook 'helm-gtags-mode)
  (add-hook 'eshell-mode-hook 'helm-gtags-mode)
  (add-hook 'c-mode-hook 'helm-gtags-mode)
  (add-hook 'c++-mode-hook 'helm-gtags-mode)
  (add-hook 'asm-mode-hook 'helm-gtags-mode)

  (define-key helm-gtags-mode-map (kbd "C-c g a") 'helm-gtags-tags-in-this-function)
  (define-key helm-gtags-mode-map (kbd "C-j") 'helm-gtags-select)
  (define-key helm-gtags-mode-map (kbd "M-.") 'helm-gtags-dwim)
  (define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack)
  (define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history)
  (define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)

  (setq-local imenu-create-index-function #'ggtags-build-imenu-index)
  )

Themes

This section should be at the end, since some of the modes come with their own color-settings and these are supposed to be overwritten by the theme-config, the theme-config should have the final say in coloring, so I can appreciate the themes in all their beauty.

Themes usually dont touch the helm-interface, for that there is a package called “helm-themes” and it usually makes sense to load the helm-theme along with the “main” theme.

Search for “current theme”. Cool themes:

  • afternoon-theme
  • ample-zen-theme
  • challenger-deep-theme
  • cherry-blossom-theme
  • cyberpunk-theme
  • flatland-theme
  • github-theme
  • night-owl-theme
  • zenburn-theme
  • weyland-yutani

Themes i never used for long

  • alect-themes
  • avk-emacs-themes
  • dark-mint-theme
  • dracula-theme
  • eziam-theme
  • kaolin-theme
  • moe-theme
  • occidental-theme
  • oceanic-theme
  • solarized-theme
  • twilight-bright-theme
  • spacegray-theme
  • toxi-theme

Current theme:

(load-theme 'doom-acario-light t)
;; (use-package dichromacy-theme
;; :ensure t
;; :config
;; (load-theme 'dichromacy t)
;; )

Theme Looper

(use-package theme-looper
  :ensure t
  :config
  (global-set-key (kbd "C-}") 'theme-looper-enable-next-theme)
  (global-set-key (kbd "C-{") 'theme-looper-enable-previous-theme)
  (global-set-key (kbd "C-\\") 'theme-looper-enable-random-theme)
  (global-set-key (kbd "C-|") 'theme-looper-select-theme)
  (global-set-key (kbd "C-M-|") 'theme-looper-select-theme-from-all)
  )

Good Colors

I set some general CoLor variables with the prefix CL and i try to stick to these throughout this document whenever i redefine colors. I consider this my standard-library of “good colors” that i should use as my kind of color-palette when i go around and change defaults.

Somewhat of a hangover from times when themes supported not all of the modes I used.

(setq cl-selection-background "ivory1")
(setq cl-selection-foreground "gray5")

(setq cl-headline "ghost white")
(setq cl-first-level "royal blue")
(setq cl-second-level "IndianRed3")
(setq cl-second-level "cornflower blue")
(setq cl-third-level "SlateBlue3")
;; alternative for lighter themes
(setq cl-third-level "SkyBlue1")
(setq cl-meta-information-one "cornflower blue")

Rebecca theme

(use-package rebecca-theme
:ensure t
:config
(load-theme 'rebecca t)
)

These keyword faces have an added background face. This looks good in some themes and i might toggle it from theme to theme.

(setq org-todo-keyword-faces
      '(("TODO" . org-warning)
        ("PENDING" :foreground "#87ffd7" :background nil :weight bold)
        ("DELEGATED" :foreground "#5fafff" :background "#456887" :box (:line-width 1 :style none))
        ("REVIEW" :foreground "#A3FFE3" :background nil)
        ("CANCELED" :foreground "#b5bd68" :weight bold :box
         (:line-width 1 :style none))
         )
         )

Catpuccing theme

(use-package catppuccin-theme
  :ensure t)

Helm is poorly stylized, this makes it a bit better:

               (helm-selection :background ,ctp-surface0 :extend t)
               (helm-selection-line)
;; ...
               (helm-source-header :foreground ,ctp-green)

Seti theme

I used this theme for a long time and it is pretty good, but sometimes i have to mix it up! Care for the workaround though!

(use-package seti-theme
  :ensure t
  :config
  (custom-set-faces
   '(font-lock-function-name-face ((t (:foreground "royal blue"))))
   '(font-lock-comment-face ((t (:foreground "light sea green")))) ;9FCA56
   '(helm-source-header ((t (:background "gray14" :foreground "white" :weight bold :height 1.3 :family "Sans Serif"))))
   `(helm-candidate-number ((t (:foreground ,cl-meta-information-one))))
   ;;'(helm-candidate-number ((t (:foreground "goldenrod2"))))
   `(helm-selection ((t (:background ,cl-selection-background :foreground ,cl-selection-foreground))))
   ;;'(helm-selection ((t (:background "light gray" :foreground "gray5"))))
   ;; added the outline definitions to blindly work towards a global color theme
   ;; which variables inherit from these "outline" variables?
   `(org-level-1 ((t (:inherit org-level-1 :foreground ,cl-first-level))))
   `(outline-2 ((t (:foreground ,cl-second-level))))
   `(outline-3 ((t (:foreground ,cl-third-level))))
   `(org-document-title ((t (:foreground ,cl-headline :weight bold :height 1.44))))
   `(org-headline-done ((((class color) (min-colors 16) (background dark)) (:strike-through t))))
   `(org-date ((t (:foreground ,cl-meta-information-one :underline t))))
   `(org-link ((t (:inherit nil :foreground ,cl-meta-information-one))))
   ;; Color the Org-Blocks beautifully for color schemes that do not do that
   `(org-block-foreground ((t (:foreground "dark orange"))))
   `(org-block-begin-line ((t (:foreground "medium slate blue"))))
   `(org-block-end-line ((t (:foreground "medium slate blue"))))
   `(org-document-info ((t (:foreground "medium sea green"))))
   `(org-document-info-keyword ((t (:foreground "light sea green"))))
   ;; make ~words~ pop in this theme
   `(org-code ((t (:inherit shadow :foreground "DarkOrange3"))))
   ;; my attempt to remove the line striking through the modeline by resetting the face
   `(mode-line ((t (:foreground "#D4D7D6"))))
   )
  (set-background-color "grey12")
  )

Manually uncommented “mode-line” settings of this theme in the package itself for now.

Seti-theme workaround

I had to uncomment two lines in the official package for this theme. If i dont do so the html-export breaks.

# Here are the two lines
grep "breaks" ~/.emacs.d/elpa/seti-theme-20161208.836/seti-theme.el

Apart from that i now (<2017-04-13 Do>) get an error that the face “bold” does not exist. A bunch of settings in the theme inherit from this face. I guess i have to fix this or use a different theme.

Sanityinc tomorrow

(use-package color-theme-sanityinc-tomorrow
:ensure t
:config
(load-theme 'sanityinc-tomorrow-bright t)
)

Gruvbox theme

(use-package gruvbox-theme
:ensure t
:config
(load-theme 'gruvbox-dark-hard t)
;; increase the fontsize
(if (equal "work" (getenv "SYSENV"))
  (set-frame-font "-PfEd-DejaVu Sans Mono-normal-normal-normal-*-16-*-*-*-m-0-iso10646-1"))
)

Monokai +gnome madness

Installed packages ontop of gnome:

(use-package monokai-theme
  :ensure t
  :config
  (load-theme 'monokai t)
  (set-background-color "#2f343f")
  )

Spacemacs theme

Taken from: http://pragmaticemacs.com/emacs/get-that-spacemacs-look-without-spacemacs/

(use-package spacemacs-common
  :ensure spacemacs-theme
  :config
  (load-theme 'spacemacs-light t)
  (setq spacemacs-theme-org-agenda-height nil)
  (setq spacemacs-theme-org-height nil)
)

This contains a couple of options to stop the theme using variable heights for org-mode agenda items and headings. However, they didn’t have the desired effect for me to I also needed to add the following lines to my org-mode configuration:

;; set sizes here to stop spacemacs theme resizing these
(set-face-attribute 'org-level-1 nil :height 1.0)
(set-face-attribute 'org-level-2 nil :height 1.0)
(set-face-attribute 'org-level-3 nil :height 1.0)
(set-face-attribute 'org-scheduled-today nil :height 1.0)
(set-face-attribute 'org-agenda-date-today nil :height 1.1)
(set-face-attribute 'org-table nil :foreground "#008787")

Monokai alt theme

(use-package monokai-alt-theme
  :ensure t
  :config
  (load-theme 'monokai-alt t)
  )

Prassee theme

Taken from: https://github.com/prassee/prassee-emacs-theme

mkdir -p themes
cd themes
git clone https://github.com/prassee/prassee-emacs-theme

Check content of download:

ls -l ~/.emacs.d/themes/prassee-emacs-theme

Load the theme

(add-to-list 'custom-theme-load-path "~/.emacs.d/themes/prassee-emacs-theme")
(load-theme 'prassee t)
;; do my costumization:
(custom-set-faces
 `(org-block-begin-line      ((t (:background "#3D3D48" :foreground "#65737E"))))
 `(org-formula      ((t (:foreground "azure4"))))
 )

Org-mode Size settings

Regardless of the theme i got used to having the org-headlines at certain sizes.

;; Org-mode Size-Customizations
(custom-set-faces
 `(org-level-1 ((t (:inherit outline-1 :height 1.4))))
 `(org-level-2 ((t (:inherit outline-2 :height 1.3))))
 `(org-level-3 ((t (:inherit outline-3 :height 1.2))))
 `(org-level-4 ((t (:inherit outline-4 :height 1.1))))
 )

Purple-haze theme

This theme is great, some of the monitors i use however dont display the slight color-differences between the different tones of purple nicely, such that it just looks black. Playing with the monitor-settings sadly doesnt resolve this, this might not be my final theme. “Final theme”.. smirk

(use-package purple-haze-theme
  :ensure t
  :config
  (load-theme 'purple-haze t)
  )

(use-package helm-themes
  :ensure t
  :config
  ;; (helm-themes--load-theme "purple-haze")
  )

The cursor style

Set this after the themes since some themes reset this.

Currently untangled since the cursor seems to adapt the text color which makes it hard to spot at times.

(set-default 'cursor-type 'box)
(set-cursor-color "#6aaf6a")

Org-mode

(use-package org
  ;;:pin manual ;; update manually
  :ensure org
  :pin elpa
  :init
  ;; Taken from: http://endlessparentheses.com/applying-markup-to-strings-in-org-mode.html
  ;; This HAS to come before (require 'org) / the init section of use-package
  (setq org-emphasis-regexp-components
        '("     ('\"{“”"
          "-   .,!?;''“”\")}/\\“”"
          "    \t\r\n,"
          "."
          5))
  :config
  ;; Add org-mode as the default major-mode for .org files
  (add-to-list 'auto-mode-alist '("\\.org$" . org-mode))
  ;; Remove windows CTRL characters
  (add-hook 'comint-output-filter-functions
                   'comint-strip-ctrl-m)
  ;; autofill hooks for automatic indentation
  (add-hook 'change-log-mode-hook 'turn-on-auto-fill)
  (add-hook 'org-mode-hook 'turn-on-auto-fill)
  ;; dont scroll automatically such that "point" is visible
  (setq auto-hscroll-mode nil)
  ;; when i narrow down to the current subsection using `org-tree-to-indirect-buffer' i dont want
  ;; to create a new window, but rather open the new buffer at the current position
  (setq org-indirect-buffer-display 'current-window)
  )

Org-mode operation speed improvments

Keyboard shortcuts are probably the first place to start

(fset 'fbr/convert-listitem-into-checklistitem
      "\355\C-f\C-f[]\C-f\C-b \C-b\C-b \C-a\C-n")
(define-key global-map "\C-cb" 'fbr/convert-listitem-into-checklistitem)
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(define-key global-map "\C-cc" 'org-capture)
(define-key global-map "\M-n" 'org-metadown)
(define-key global-map "\M-p" 'org-metaup)
(define-key org-mode-map "\C-m" 'nil) ;; why do i do this?
(define-key org-mode-map (kbd "<f5>") 'org-babel-execute-src-block)
(global-set-key (kbd "<f9>") 'org-todo)
(define-key global-map (kbd "<f10>") 'org-clock-goto)

Jump to beginning / end of heading by default (should make navigation faster once i get used to this)

(setq org-special-ctrl-a/e t)

Truely global org-mode keybindings (taken from here: https://stackoverflow.com/questions/683425/globally-override-key-binding-in-emacs)

Sadly i didnt get this to work with C-c C-x C-j, C-j always created a newline. However i think this is a good start, therefor im keeping this!

(defvar my-keys-minor-mode-map
  (let ((map (make-sparse-keymap)))
    ;; make this one global so i can jump from everywhere
    (define-key map (kbd "\C-c\C-x\C-j") 'org-clock-goto)
    map)
  "my-keys-minor-mode keymap.")

(define-minor-mode my-keys-minor-mode
  "A minor mode so that my key settings override annoying major modes."
  :init-value t
  :lighter " my-keys")

(my-keys-minor-mode 1)

(add-hook 'after-load-functions 'my-keys-have-priority)

(defun my-keys-have-priority (_file)
  "Try to ensure that my keybindings retain priority over other minor modes.

Called via the `after-load-functions' special hook."
  (unless (eq (caar minor-mode-map-alist) 'my-keys-minor-mode)
    (let ((mykeys (assq 'my-keys-minor-mode minor-mode-map-alist)))
      (assq-delete-all 'my-keys-minor-mode minor-mode-map-alist)
      (add-to-list 'minor-mode-map-alist mykeys))))

Explicitly enable the sourceblock shortcuts (i.e. automatically expanding “<s” to an org-mode sourceblock). Once this worked out of the box, after an update I now need this. syl20bnr/spacemacs#11798

(require 'org-tempo)

Org-mode visual improvements

Strike through DONE headlines

(setq org-fontify-done-headline t)

Don’t hide the markdown markers

(setq org-hide-emphasis-markers nil)

Change from … to the arrow

(setq org-ellipsis "")
(custom-set-faces '(org-ellipsis ((t (:inherit org-ellispsis :height 0.7)))))

Fontify done checkbox items in org-mode

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

Circulate Bullets instead of asteriks for list items

(font-lock-add-keywords 'org-mode
                        '(("^ +\\([-*]\\) "
                           (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) ""))))))

Org-mode capture

Makes it so org-capture takes up the whole screen.

Taken from here: https://fuco1.github.io/2017-09-02-Maximize-the-org-capture-buffer.html

(defvar my-org-capture-before-config nil
  "Window configuration before `org-capture'.")

(defadvice org-capture (before save-config activate)
  "Save the window configuration before `org-capture'."
  (setq my-org-capture-before-config (current-window-configuration)))

(add-hook 'org-capture-mode-hook 'delete-other-windows)

(defun my-org-capture-cleanup ()
  "Clean up the frame created while capturing via org-protocol."
  ;; In case we run capture from emacs itself and not an external app,
  ;; we want to restore the old window config
  (when my-org-capture-before-config
    (set-window-configuration my-org-capture-before-config))
  (-when-let ((&alist 'name name) (frame-parameters))
    (when (equal name "org-protocol-capture")
      (delete-frame))))

(add-hook 'org-capture-after-finalize-hook 'my-org-capture-cleanup)

Org-mode tags

The horizontal position of tags is set here.

(setq org-tags-column -70)

This setting should work together with your line-wrapping limit, such that tagged headings match the line-wrapped text below.

To align the tags that already exist simple execute org-align-all-tags on the file. This is useful when changing the above setting, since it doesnt affect existing org-files.

Org-mode agenda

Org-mode agenda-files

Depending on my system-environment which i deduce from the system environment variable “SYSENV” which i manually set on the systems i use i have different workflows.

At work i have more todo states, and different agenda files than for example at home. This is reflected by the following settings.

Home

(if (equal "home" (getenv "SYSENV"))
    (progn
      (setq org-agenda-files
            (list
             (concat fbr/home-dir "/Dropbox/org/gtd/tasks.org")
             (concat fbr/home-dir "/Dropbox/org/gtd/tasks.org_archive")
             (concat fbr/home-dir "/Dropbox/org/hobby/dactyl-keyboard/dactyl-keyboard-guide/index.org")
             (concat fbr/home-dir "/Dropbox/org/uni/bachelor_thesis/bachelor_thesis.org")
             (concat fbr/home-dir "/Dropbox/org/gtd/tasks_2015")
             (concat fbr/home-dir "/Dropbox/org/gtd/tasks_2016")
             (concat fbr/home-dir "/Dropbox/org/gtd/tasks_2017")
             ))
      ;; org-capture setup
      (setq org-default-notes-file (concat fbr/home-dir "/Dropbox/org/gtd/tasks.org"))
      (setq org-capture-templates
            '(("t" "todo" entry (file+headline org-default-notes-file "Events / Aufgaben")
               "* TODO %?\n  New task appeared on: %u\n  Interrupted from doing: %a. Click to get back.\n" :clock-in t :clock-resume t)
              ("m" "Meeting" entry (file+headline org-default-notes-file "Events / Aufgaben")
               "* Meeting mit %? :meeting:\n%t" :clock-in t :clock-resume t)
              ("i" "Idea" entry (file+headline org-default-notes-file "Events / Aufgaben")
               "* %? :idea: \n%t" :clock-in t :clock-resume t)
              )
            )
      (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6))))
      )
  )

Work

(if (equal "work" (getenv "SYSENV"))
    (progn
      (setq org-agenda-files
            (list (concat fbr/home-dir "/Dropbox/work/org/projects.org")))
      ;; org-capture setup
      (setq org-default-notes-file (concat fbr/home-dir "/Dropbox/work/org/projects.org"))
      (setq org-capture-templates
            '(("t" "todo" entry (file+headline org-default-notes-file "Aufgaben")
               "* TODO %?\n  New task appeared on: %u\n  Interrupted from doing: %a. Click to get back.\n" :clock-in t :clock-resume t)
              ("m" "Meeting" entry (file+headline org-default-notes-file "Aufgaben")
               "* Meeting mit %? :meeting:\n%t" :clock-in t :clock-resume t)
              ("i" "Idea" entry (file+headline org-default-notes-file "Aufgaben")
               "* %? :idea: \n%t" :clock-in t :clock-resume t)
              )
            )
      (setq org-refile-targets '((org-agenda-files . (:maxlevel . 3))))
      )
  )

Shortcut to open my main agenda file

(defun fbr/open_main_agenda_file()
  (interactive)
  (case (intern (getenv "SYSENV"))
    (home (find-file (concat fbr/home-dir "/Dropbox/org/gtd/tasks.org")))
    (work (find-file (concat fbr/home-dir "/Dropbox/work/org/projects.org")))
    (otherwise (message "No SYSENV found. Don't know what to open."))
    )
  )

(define-key global-map (kbd "<f6>") 'fbr/open_main_agenda_file)

Super-agenda (disabled)

Org-super-agenda source: https://github.com/alphapapa/org-super-agenda

Disabled for now because I dont use it anymore.

In the following i cut down the example from the github source from the things that cant possibly match to the stuff i use in my config

(use-package org-super-agenda
  :ensure t
  :config
  (org-super-agenda-mode)
  (setq org-super-agenda-groups
        '(;; Each group has an implicit boolean OR operator between its selectors.
          (:name "Today"  ; Optionally specify section name
                 :time-grid t)  ; Items that appear on the time grid
          (:name "Important"
                 ;; Single arguments given alone
                 :tag ("budget" "sprint" "kanban" "promise")
                 :priority "A")
          (:priority<= "B"
                       ;; Show this section after "Today" and "Important", because
                       ;; their order is unspecified, defaulting to 0. Sections
                       ;; are displayed lowest-number-first.
                       :order 1)
          ;; After the last group, the agenda will display items that didn't
          ;; match any of these groups, with the default order position of 99
          ))
  )

Idle org agenda

(use-package idle-org-agenda
     :after org-agenda
     :ensure t
     :config
     (idle-org-agenda-mode)
     (setq idle-org-agenda-interval 900)
)

Org-mode agenda settings

;; (time consuming!) appends a list of how much time was spend on which heading (project) at the
;; end of the default agenda view. Disabled by default, sometimes i like to toggle it on.
(setq org-agenda-start-with-clockreport-mode nil)
;; Set default column view headings: Task Total-Time Time-Stamp
(setq org-columns-default-format "%50ITEM(Task) %10CLOCKSUM %16TIMESTAMP_IA")
;; A package to visualize repeated tasks in the org agenda
(require 'org-habit)
(add-to-list 'org-modules 'org-habit)
(setq org-habit-show-habits-only-for-today nil)
;; add archived tasks to the agenda and clocktable, otherwise they dont show up
(setq org-agenda-archives-mode t)
(defun fbr/org-agenda-reduce-to-current-file()
  (interactive)
  (setq org-agenda-files (list (buffer-file-name)))
  )
;; start the agenda in a full window
(setq org-agenda-window-setup 'current-window)
;; indicate the markdown-level when displaying tasks in agenda
(setq org-tags-match-list-sublevels 'indented)

Set the default priority to C. This reflects how i use priorities:

  • A: urgent, do this right now or it will blow up in your face
  • B: do this one of these days, a possible candidate for priority A (it might blow up in my face soon if i don’t act on it)
  • C: do this whenever you feel like it some day in the future
(setq org-default-priority 67) ;; the ascii code for C

Make it so that tags are put to the right-hand side of the window in org-agenda

(add-hook 'org-finalize-agenda-hook 'place-agenda-tags)
(defun place-agenda-tags ()
  "Put the agenda tags by the right border of the agenda window."
  (setq org-agenda-tags-column (- 4 (window-width)))
  (org-agenda-align-tags))

Org-mode agenda custom views

Monthly budget view

Taken from here: http://jcardente.blogspot.de/2010/06/org-mode-hack-tasks-done-last-month.html

I use it to create my monthly financial report.

(if (equal "home" (getenv "SYSENV"))
    (progn

      (require 'calendar)

      (defun fbr/org-tasks-closed-in-month (&optional month year match-string)
        "Produces an org agenda tags view list of the tasks completed
in the specified month and year. Month parameter expects a number
from 1 to 12. Year parameter expects a four digit number. Defaults
to the current month when arguments are not provided. Additional search
criteria can be provided via the optional match-string argument "
        (interactive)
        (let* ((today (calendar-current-date))
               (for-month (or month (calendar-extract-month today)))
               (for-year  (or year  (calendar-extract-year today))))
          (org-tags-view nil
                         (concat
                          match-string
                          (format "+CLOSED>=\"[%d-%02d-01]\""
                                  for-year for-month)
                          (format "+CLOSED<=\"[%d-%02d-%02d]\""
                                  for-year for-month
                                  (calendar-last-day-of-month for-month for-year))))))

      (defun fbr/budget-tasks-last-month ()
        "Produces an org agenda tags view list of all the tasks completed
last month with the tag budget."
        (interactive)
        (let* ((today (calendar-current-date))
               (for-month (calendar-extract-month today))
               (for-year  (calendar-extract-year today)))
          (calendar-increment-month for-month for-year -1)
          (fbr/org-tasks-closed-in-month
           for-month for-year "TODO=\"DONE\"+budget")))
      )
  )

Org-mode todo-keywords

(if (equal "work" (getenv "SYSENV"))
    (progn (setq org-todo-keywords
                 '((sequence "TODO(t)" "PENDING(p)" "DELEGATED(e)" "REVIEW(r)" "|" "CANCELED(c)" "DONE(d)"))))
  )
(if (or (equal "home" (getenv "SYSENV"))
        (equal "linux-vm" (getenv "SYSENV")))
    (progn (setq org-todo-keywords
                 '((sequence "TODO(t)" "PENDING(p)" "|" "CANCELED(c)" "DONE(d)"))))
  )

Keyword-faces, these are independant of the system in use, even when org-todo-keywords differ from system to system.

(setq org-todo-keyword-faces
      '(("TODO" . org-warning)
        ("PENDING" . "#f0c674")
        ("DELEGATED" . "#81a2be")
        ("CANCELED" . (:foreground "#b5bd68" :weight bold))))

These keyword faces have an added background face. This looks good in some themes and i might toggle it from theme to theme.

(setq org-todo-keyword-faces
      '(("TODO" . org-warning)
        ("PENDING" . (:foreground "#f0c674" :background nil))
        ("DELEGATED" . (:foreground "#81a2be" :background "#456887" :box (:line-width 1 :style none)))
        ("CANCELED" . (:foreground "#b5bd68" :weight bold :box (:line-width 1 :style none)))
        ("REVIEW" (:foreground "#A3FFE3" :background nil))
        ))

Org-mode alerts and notifications

This section is a work-in-progress. It works in some places, it throws no errors but thats it.

This allows me to have super-cool appointment-reminders (sometimes causes error on start).

;; Make appt aware of appointments from the agenda
(defun fbr/org-agenda-to-appt ()
  "Activate appointments found in `org-agenda-files'."
  (interactive)
  (require 'org)
  (let* ((today (org-date-to-gregorian
                 (time-to-days (current-time))))
         (files org-agenda-files) entries file)
    (while (setq file (pop files))
      (setq entries (append entries (org-agenda-get-day-entries
                                     file today :timestamp))))
    (setq entries (delq nil entries))
    (mapc (lambda(x)
            (let* ((event (org-trim (get-text-property 1 'txt x)))
                   (time-of-day (get-text-property 1 'time-of-day x)) tod)
              (when time-of-day
                (setq tod (number-to-string time-of-day)
                      tod (when (string-match
                                 "\\([0-9]\\{1,2\\}\\)\\([0-9]\\{2\\}\\)" tod)
                            (concat (match-string 1 tod) ":"
                                    (match-string 2 tod))))
                (if tod (appt-add tod event))))) entries)))
(defadvice fbr/org-agenda-to-appt (before wickedcool activate)
  "Clear the appt-time-msg-list."
  (defvar appt-time-msg-list)
  (setq appt-time-msg-list nil))
(org-agenda-to-appt)

Org-mode alert extension

This is a package on top of the original alert.el

Im pretty sure this makes my “fbr/tea-timer” possible which is defined somewhere else. This way i can basically remind myself to not spend too much time on a task by setting a timer before-hand. This can also be done similarly with “C-c C-x C-e” after clocking into a task. This way an expected time-consumption can be set and the timer gets red once we exceed this time, which is not as convenient as having an extra alert-window in my oppinion.

Go through this: https://emacs.stackexchange.com/questions/3844/good-methods-for-setting-up-alarms-audio-visual-triggered-by-org-mode-events

(use-package org-alert
  :if (string-equal system-type "gnu/linux")
  :config
  (setq alert-default-style 'libnotify)
  (setq org-alert-interval 300)
  (org-alert-enable)
  )

Experimental part taken from here: http://emacs-fu.blogspot.de/2009/11/showing-pop-ups.html

Ideas / Programs I brought in:

  • [X] Use notify.exe
  • [X] Use start-process instead of shell-command for better testing
  • [ ] use “Media Player Classic” for the sound
    • it probably works like this: “/play /minimized / close”
(defun djcb-popup (title msg &optional icon sound)
  "Show a popup if we're on windows, or echo it otherwise; TITLE
  is the title of the message, MSG is the context. Optionally,
  you can provide an ICON and a sound to be played"

  (interactive)
  ;; (when sound (shell-command
  ;;              (concat "mplayer -really-quiet " sound " 2> /dev/null")))
  (if (equal "home" (getenv "SYSENV"))
      (start-process "process-name" nil (concat "c:/users/" (getenv "USERNAME") "/.emacs.d/notifu/notifu64.exe")
                     "/p"  title
                     "/m" msg
                     "/i" (concat "c:/users/" (getenv "USERNAME") "/.emacs.d/notifu/appointment-soon.ico"))
    ;; text only version as fall-backn
    (message (concat title " : "  msg)))
  )
;; test:
;; (djcb-popup "org-mode Notification" "time is up")

;; the appointment notification facility
(setq
 appt-message-warning-time 15 ;; warn 15 min in advance

 appt-display-mode-line t     ;; show in the modeline
 appt-display-format 'window) ;; use our func
(appt-activate 1)              ;; active appt (appointment notification)
(display-time)                 ;; time display is required for this...

;; update appt each time agenda opened
(add-hook 'org-finalize-agenda-hook 'org-agenda-to-appt)

;; our little façade-function for djcb-popup
(defun djcb-appt-display (min-to-app new-time msg)
  (djcb-popup (format "Appointment in %s minute(s)" min-to-app) msg
              ))
(setq appt-disp-window-function (function djcb-appt-display))

Org-mode notifications

Disabled since it gives error “not compiled with dbus support”.

(require 'notifications)

(notifications-notify :title "Achtung!"
                      :body (format "You have an appointment in %d minutes" 10)
                      :app-name "Emacs: Org"
                      :sound-name "alarm-clock-elapsed")

Org-mode sourceblocks / org-babel

Languages to load

This hints towards renaming “sh” to shell: http://thread.gmane.org/gmane.emacs.orgmode/102877/focus=102882

(org-babel-do-load-languages
 'org-babel-load-languages
 '(
   (python . t)
   (R . t)
   (latex . t)
   (lisp . t)
   (shell . t)
   (perl . t)
   (sql . t)
   (dot . t) ;; activates graphviz dot support
   ))

Remove ^M Errors in Babel

(add-to-list 'process-coding-system-alist
             '("bash" . (undecided-unix)))

Send stderror into the result drawer instead of an extra window

(setq org-babel-default-header-args:sh
      '((:prologue . "exec 2>&1") (:epilogue . ":"))
      )

Make TAB act as if it were issued in a buffer of the language’s major mode (doesnt work completely how i want it to yet, therefor untangled)

(setq org-src-tab-acts-natively t)

When editing a code snippet, use the current window rather than opening up a new one (which shows the same information). This feels so much better!

(setq org-src-window-setup 'current-window)

Load syntax-highlighting for source-blocks

(setq org-src-fontify-natively t)

Dont format (indent) the source-code when exiting the special environment (for more info on this look into the function “org-edit-src-code”).

(setq org-src-preserve-indentation t)

Dont try to evaluate source-blocks on export (this setting has fixed a weird bug for me, which showed this message: org-babel-exp-process-buffer: Wrong type argument: stringp, nil).

(setq org-export-babel-evaluate nil)

Enable asynchronous org-babel execution. A :async flag needs to be added to the code-blocks which should use this behaviour. Can also be set per file with: #+PROPERTY: header-args :async

Source seems to be over here: https://github.com/astahlman/ob-async

Currently untangled since it seems to be obsolete: Warning (emacs): ob-async-org-babel-execute-src-block is longer needed in org-ctrl-c-ctrl-c-hook

(use-package ob-async
  :ensure t
  :config
  (add-to-list 'org-ctrl-c-ctrl-c-hook 'ob-async-org-babel-execute-src-block)
  )

Enables me to toggle source-block results and hides result blocks which is great. Inspired from here: https://emacs.stackexchange.com/questions/7211/collapse-src-blocks-in-org-mode-by-default

(defvar org-blocks-hidden nil)

(defun org-toggle-blocks ()
  (interactive)
  (if org-blocks-hidden
      (org-show-block-all)
    (org-hide-block-all))
  (setq-local org-blocks-hidden (not org-blocks-hidden)))

;(add-hook 'org-mode-hook 'org-toggle-blocks)

(defun org-hide-results-blocks ()
  (interactive)
  (org-hide-block-all)
  (org-show-block-all)
  )

(add-hook 'org-mode-hook 'org-hide-results-blocks)

(define-key org-mode-map (kbd "C-c t") 'org-toggle-blocks)

Copy previous source-block

This is helpful in training sessions (or when being lazy). (taken from here: https://github.com/baron42bba/.emacs.d/commit/41e2ab53e32abc12a1fbaf050e277228605f1338)

(defun bba-copy-and-yank-org-src-block()
  "copy last org src block and insert it at point.
If region is active copy only the src begin and src end lines."
  (interactive)
  (if (use-region-p)
      (progn
        (let (-p1 -p2 srclength)
          (setq -p1 (region-beginning) -p2 (region-end))
          (setq mark-active nil)
          (re-search-backward "\#\\+BEGIN_SRC")
          (set-mark-command nil)
          (forward-line)
          (beginning-of-line)
          (kill-ring-save 1 1 1)
          (goto-char -p1)
          (set-mark-command nil)
          (insert (pop kill-ring))
          (setq srclength (- (region-end) (region-beginning)))
          (setq mark-active nil)
          (re-search-backward "\#\\+END_SRC")
          (set-mark-command nil)
          (forward-line)
          (beginning-of-line)
          (kill-ring-save 1 1 1)
          (kill-append "\n" nil)
          (goto-char (+ -p2 srclength))
          (insert (pop kill-ring))
          )
        )
    (progn
      (push-mark)
      (re-search-backward "\#\\+BEGIN_SRC")
      (set-mark-command nil)
      (re-search-forward "\#\\+END_SRC")
      (forward-line)
      (beginning-of-line)
      (kill-ring-save 1 1 1)
      (set-mark-command '1)
      (set-mark-command '1)
      (insert (pop kill-ring))
      (re-search-backward "\#\\+BEGIN_SRC")
      (forward-line)
      ))
  )

(defun bba-copy-org-src-block()
  "copy last org src block and insert it at point."
  (interactive)
  (push-mark)
  (re-search-backward "\#\\+BEGIN_SRC")
  (set-mark-command nil)
  (re-search-forward "\#\\+END_SRC")
  (forward-line)
  (beginning-of-line)
  (kill-ring-save 1 1 1)
  (set-mark-command '1)
  (set-mark-command '1)
  )

(define-key org-mode-map "\C-c\S-w" 'bba-copy-and-yank-org-src-block)
(define-key org-mode-map (kbd "C-c s-w") 'bba-copy-org-src-block)

Org-mode time logging

log the time when a task is “done”

(setq org-log-done t)

Set the format of the logged time

;; log times into a hideable logbook drawer
(setq org-log-into-drawer t)
;; makes sure LOGBOOK and PROPERTIES go first
(setq org-log-state-notes-insert-after-drawers t)

Org-mode html export

I have a bunch of css files within the “styles”-folder which i use on and off. They can then be used by adding the following line to the beginning of the file (path has to be adapted). This is not optimal yet, since i have to copy over the “styles” folder to every org-mode directory

#+HTML_HEAD:   <link rel="stylesheet" type="text/css" href="styles\\markdown.css" />

Remove the “validate”-link from the org-html export

(setq org-html-postamble nil)

Makes it so that names that include underscores dont look weird on html-export in case the org-mode exporter recognizes it as a superscript (my_hostname otherwise gets exported weird)

(setq org-export-with-sub-superscripts nil)

Include a couple of information into the html-export and set the codig-system

(setq org-export-coding-system 'utf-8-unix)
(setq org-export-with-clocks t)
(setq org-export-preserve-breaks t)

ox-twbs package for better html export

This package really has a good, yet simply html export and conveniently adds itself as a menu-entry to the html export-menu (triggered by C-c C-e and w o)

(use-package ox-twbs
  :ensure t
)

Orgmode htmlize extension

Inserts highlighting of Org Source-Blocks on Html-Export

(use-package htmlize
  :ensure t
  )

Make presentations with org-reveal

Downloaded this repo: https://github.com/hakimel/reveal.js.git

(use-package ox-reveal
  :ensure t
  :config
  (if (equal "work" (getenv "SYSENV"))
      (setq org-reveal-root (concat "file:///home/" (getenv "USERNAME") "/node_modules/reveal.js")))
  )

Export with specific html theme

Taken from here: http://correl.phoenixinquis.net/2016/02/23/org-publish-with-theme.html

(defun my/with-theme (theme fn &rest args)
  (let ((current-themes custom-enabled-themes))
    (mapcar #'disable-theme custom-enabled-themes)
    (load-theme theme t)
    (let ((result (apply fn args)))
      (mapcar #'disable-theme custom-enabled-themes)
      (mapcar (lambda (theme) (load-theme theme t)) current-themes)
      result)))

(advice-add #'org-export-to-file :around (apply-partially #'my/with-theme 'deeper-blue))
(advice-add #'org-export-to-buffer :around (apply-partially #'my/with-theme 'deeper-blue))

Org-mode org-clock-csv extension

Exports clock-data to csv which is a useful data-format for generating graphs!

(use-package org-clock-csv
  :ensure t
  )

Org-mode openwith extension

Open pdfs with an external pdf-viewer to get a good resolution.

(use-package openwith
  :if (string-equal system-type "gnu/linux")
  :config
  (setq openwith-associations '(("\\.pdf\\'" "evince" (file))))
  (openwith-mode t)
)

Ox-Jira

Manually copied from baron42bba’s config

(use-package ox-jira
:config

)

We are lazy and want to speed up things:

(defun bba-org-export-jira-clipboard()
  "narrow to org subtree and store content in jira format in clipboard."
  (interactive)
  (org-narrow-to-subtree)
  (bba-export-jira-org)
  (let ((org-export-use-babel nil))
    (ox-jira-export-as-jira))
  (delete-region (point) (progn (forward-line 1)(point)))
  (push-mark (point))
  (push-mark (point-max) nil t)
  (goto-char (point-min))
  (kill-ring-save 1 1 1)
  (other-window -1)
  (widen)
  (other-window 1)
  )

(define-key org-mode-map "\C-c\S-j" 'bba-org-export-jira-clipboard)

Besides the clipboard we want also an org file in /tmp/ to attach to the jira ticket. Of course some boiler plate for the poor souls who never heard of orgmode.

(defun bba-export-jira-org()
  "export current narrowed view to file in tmp and open a finder window on OS-X."
  (interactive)
  (goto-char (point-min))
  (insert "# This file is just plain text called orgmode")
  (newline)
  (insert "# https://en.wikipedia.org/wiki/Org-mode")
  (newline)
  (insert "# You can open it in any text editor or file reader.")
  (newline)
  (insert "# You might want to use Emacs for best experience.")
  (newline)
  (if (re-search-forward "jira:" nil t 1)
      (if (org-in-regexp org-bracket-link-regexp 1)
          (let ((remove (list (match-beginning 0) (match-end 0)))
                (description (last (split-string (if (match-end 3)
                                                     (match-string-no-properties 3)
                                                   (match-string-no-properties 1)) ":"))))
            (push-mark (point))
            (push-mark (point-max) nil t)
            (goto-char (point-min))
            (write-region (mark) (point) (concat "/tmp/" (car description) ".org") nil nil )
            (deactivate-mark)
            (if (string-equal system-type "darwin")(shell-command "open /tmp/"))
            )))
  (goto-char (point-min))
  (kill-line 4)
  )

Latex-settings

bjm-article Template

Including this into the usepackage-definition of org doesnt seem to work. This is some sample-template called bjmarticle i copied from the webs.

(require 'ox-latex)
(add-to-list 'org-latex-classes
             '("bjmarticle"
               "\\documentclass{article}
                \\usepackage[utf8]{inputenc}
                \\usepackage[T1]{fontenc}
                \\usepackage{graphicx}
                \\usepackage{longtable}
                \\usepackage{hyperref}
                \\usepackage{natbib}
                \\usepackage{amssymb}
                \\usepackage{amsmath}
                \\usepackage{geometry}
                \\geometry{a4paper,left=2.5cm,top=2cm,right=2.5cm,bottom=2cm,marginparsep=7pt, marginparwidth=.6in,headheight=30pt}
                \\setlength{\\parskip}{\\baselineskip}
                \\hypersetup{pdflang={German},colorlinks, linkcolor={red!50!black}, citecolor={blue!50!black}, urlcolor={blue!80!black}}
                \\setlength{\\parindent}{0pt}"
               ("\\section{%s}" . "\\section*{%s}")
               ("\\subsection{%s}" . "\\subsection*{%s}")
               ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
               ("\\paragraph{%s}" . "\\paragraph*{%s}")
               ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             )

stsreport Template

A latex-template that is actually useful and that I will use for my bachelor-thesis.

;; Latex settings (somehow doesn't work if i put it in usepackage definition of org)
(require 'ox-latex)
(add-to-list 'org-latex-classes
             '("stsreprt"
               "\\documentclass[fancyheadings]{stsreprt}
               [NO-DEFAULT-PACKAGES]"
               ("\\chapter{%s}" . "\\chapter*{%s}")
               ("\\section{%s}" . "\\section*{%s}")
               ("\\subsection{%s}" . "\\subsection*{%s}")
               ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
               ("\\paragraph{%s}" . "\\paragraph*{%s}")
               ("\\subparagraph{%s}" . "\\subparagraph*{%s}")
               )
             )

Enable specific latex-headers

Taken from here: http://emacs.stackexchange.com/questions/7890/org-plus-contrib-and-org-with-require-or-use-package?noredirect=1&lq=1

Disabled since org-contrib-plus seems to be causing issues now (<2020-04-12 Sun>).

(use-package org
  :ensure org-plus-contrib
  :config
  (require 'ox-extra)
  (ox-extras-activate '(ignore-headlines))
  )

Pdftools for org-ref

(use-package pdf-tools)
;; (pdf-tools-install)

Orgmode bibliography and latex compiler settings

Inspired from J. Kitchin’s youtube video: https://www.youtube.com/watch?v=2t925KRBbFc

(use-package org-ref
  :ensure t
  :config
  (setq org-ref-completion-library 'org-ref-helm-cite)
  (require 'org-ref)
  (require 'org-ref-pdf) ;; enable pdf drag n' drop ;; requires manual post-install step from pdf-tools package
  (require 'doi-utils)
  (require 'org-ref-latex)
  (require 'org-ref-bibtex)
  (require 'org-ref-url-utils)

  ;; -shell-escape added for "minted" package
  (setq org-latex-pdf-process
        '("%latex -interaction nonstopmode -shell-escape -output-directory %o %f"
          "%bib %b"
          "%latex -interaction nonstopmode -shell-escape -output-directory %o %f"
          "%latex -interaction nonstopmode -shell-escape -output-directory %o %f")
        )
  (define-key org-mode-map (kbd "C-c [") 'org-reftex-citation)
  )

If we are at home I know where the paths should be

(if (equal "home" (getenv "SYSENV"))
    (progn
      ;; see org-ref for use of these variables
      (setq org-ref-bibliography-notes (concat fbr/home-dir "/Dropbox/org/uni/bachelor_thesis/notes.org")
            org-ref-default-bibliography '((concat fbr/home-dir "/Dropbox/org/uni/bachelor_thesis/bachelor_thesis.bib"))
            org-ref-pdf-directory (concat fbr/home-dir "/Dropbox/org/uni/bachelor_thesis/")
            org-ref-pdf-directory (concat fbr/home-dir "/Dropbox/org/uni/bachelor_thesis/bibtex-pdfs/")
            )
      )
  )

Customize the markdown export

I use verbatim markup to surround file-paths, in order to have them highlighted. The following exports this markup to a more capable format.

(setq org-latex-text-markup-alist '((bold . "\\textbf{%s}")
                                  (code . protectedtexttt)
                                  (italic . "\\emph{%s}")
                                  (strike-through . "\\sout{%s}")
                                  (underline . "\\uline{%s}")
                                  (verbatim . "\\path{%s}"))) ;; default: protectedtexttt

It however requires the following additional settings to actually work. This setting makes it so paths are preferably broken near slashes. When there is no slash nearby the path simply gets broken at a letter.

#+LaTeX_HEADER: \usepackage[colorlinks]{hyperref}
#+LATEX_HEADER: \usepackage{etoolbox}
#+LATEX_HEADER: \renewcommand{\UrlBreaks}{\do\/\do\a\do\b\do\c\do\d\do\e\do\f\do\g\do\h\do\i\do\j\do\k\do\l\do\m\do\n\do\o\do\p\do\q\do\r\do\s\do\t\do\u\do\v\do\w\do\x\do\y\do\z\do\A\do\B\do\C\do\D\do\E\do\F\do\G\do\H\do\I\do\J\do\K\do\L\do\M\do\N\do\O\do\P\do\Q\do\R\do\S\do\T\do\U\do\V\do\W\do\X\do\Y\do\Z}

Minted, coloured source-blocks in latex

Enables the “minted” package with its required options for the source-block highlighting to work. In addition to this I need the minted latex package, which relies on the external tool pygmentize to be in path: https://tex.stackexchange.com/questions/23458/how-to-install-syntax-highlight-package-minted-on-windows-7

(require 'ox-latex)
(add-to-list 'org-latex-packages-alist '("" "minted"))

(setq org-latex-listings 'minted)

(setq org-latex-minted-options
      '(("frame=single") ("linenos=true") ("breaklines=true") ("breakanywhere=true")))

In my case i had to delete the temporary folder in the same directory to make the coloring work. Got this hint from here: https://tex.stackexchange.com/questions/237075/minted-not-working

Pretty quotations for nice latex exports

Taken from here: http://endlessparentheses.com/prettify-your-quotation-marks.html

(define-key org-mode-map "\"" #'endless/round-quotes)
(eval-after-load 'markdown-mode
  '(define-key markdown-mode-map "\""
     #'endless/round-quotes))

(defun endless/round-quotes (italicize)
  "Insert “” and leave point in the middle.
With prefix argument ITALICIZE, insert /“”/ instead
\(meant for org-mode).
Inside a code-block, just call `self-insert-command'."
  (interactive "P")
  (if (and (derived-mode-p 'org-mode)
           (org-in-block-p '("src" "latex" "html")))
      (call-interactively #'self-insert-command)
    (if (looking-at "”[/=_\\*]?")
        (goto-char (match-end 0))
      (when italicize
        (if (derived-mode-p 'markdown-mode)
            (insert "__")
          (insert "//"))
        (forward-char -1))
      (insert "“”")
      (forward-char -1))))

Cdlatex

From: http://www.clarkdonley.com/blog/2014-10-26-org-mode-and-writing-papers-some-tips.html “speed-up insertion of environments and math templates”

From cdlatex.el: “CDLaTeX requires texmathp.el which is distributed with AUCTeX.”

;; ;; Debugger entered--Lisp error: (error "tex-jp.el:0:0: error: scan-error: (Unbalanced parentheses 22806 42543)")
;; (use-package auctex
;; :ensure t
;; )

;; (use-package cdlatex
;; :ensure t
;; :config
;; (require 'auctex)
;; (add-hook 'org-mode-hook 'turn-on-org-cdlatex)
;; )

Enable R codeblocks

For this to work i had to install the ess-package:

sudo apt-get install ess

After installation of ess the following works.

(if (equal "home" (getenv "SYSENV"))
    (progn
      ;; found out about the path with dpkg -L ess
      (add-to-list 'load-path "/usr/share/emacs/site-lisp/ess/")
      (require 'ess-site))
  )

In addition we also need to load the org-babel language R over here: Org-mode section.

cm-mode for advanced authoring markup

I like the idea of inserting comments like this package suggests, but I am still just trying this mode out.

Demo: http://criticmarkup.com/

Notes:

  • Breaks my indentation-shortcut M-q (fill-paragraph)
  • Creates notes that I havent figured out how to delete yet, there seems to be no delete command, just a command that inserts a “delete comment”.
(use-package cm-mode
  :ensure t
  :config
  (setq cm-read-only-annotations nil)
  )

Blogging

Doesnt work out of the box, needs some setup! See “setup the blog” for more info.

Makes syntax highlighting work by exporting it properly: https://emacs.stackexchange.com/questions/42471/how-to-export-markdown-from-org-mode-with-syntax

(use-package ox-gfm
  :ensure t
  :config
  (eval-after-load "org"
    '(require 'ox-gfm nil t))
  )

Taken from: http://www.holgerschurig.de/en/emacs-blog-from-org-to-hugo/

(if (or (equal "home" (getenv "SYSENV"))
        (equal "work" (getenv "SYSENV"))
        )
    (progn
      (defvar hugo-content-dir "~/Dropbox/org/blog/content/"
        "Path to Hugo's content directory")

      (defun hugo-ensure-property (property)
        "Make sure that a property exists. If not, it will be created.

     Returns the property name if the property has been created,
     otherwise nil."
        (if (org-entry-get nil property)
            nil
          (progn (org-entry-put nil property "")
                 property)))

      (defun hugo-ensure-properties ()
        "This ensures that several properties exists. If not, these
     properties will be created in an empty form. In this case, the
     drawer will also be opened and the cursor will be positioned
     at the first element that needs to be filled.

     Returns list of properties that still must be filled in"
        (require 'dash)
        (let ((current-time (format-time-string (org-time-stamp-format t t) (org-current-time)))
              first)
          (save-excursion
            (unless (org-entry-get nil "TITLE")
              (org-entry-put nil "TITLE" (nth 4 (org-heading-components))))
            (setq first (--first it (mapcar #'hugo-ensure-property '("HUGO_TAGS" "HUGO_FILE"))))
            (unless (org-entry-get nil "HUGO_DATE")
              (org-entry-put nil "HUGO_DATE" current-time)))
          (when first
            (goto-char (org-entry-beginning-position))
            ;; The following opens the drawer
            (forward-line 1)
            (beginning-of-line 1)
            (when (looking-at org-drawer-regexp)
              (org-flag-drawer nil))
            ;; And now move to the drawer property
            (search-forward (concat ":" first ":"))
            (end-of-line))
          first))

      (defun hugo ()
        (interactive)
        (unless (hugo-ensure-properties)
          (let* ((title    (concat "title = \"" (org-entry-get nil "TITLE") "\"\n"))
                 (date     (concat "date = \"" (format-time-string "%Y-%m-%d" (apply 'encode-time (org-parse-time-string (org-entry-get nil "HUGO_DATE"))) t) "\"\n"))
                 (tags     (concat "tags = [ \"" (mapconcat 'identity (split-string (org-entry-get nil "HUGO_TAGS") "\\( *, *\\)" t) "\", \"") "\" ]\n"))
                 (fm (concat "+++\n"
                             title
                             date
                             tags
                             "+++\n\n"))
                 (file     (org-entry-get nil "HUGO_FILE"))
                 (coding-system-for-write buffer-file-coding-system)
                 (backend  'md)
                 (blog))
            ;; try to load org-mode/contrib/lisp/ox-gfm.el and use it as backend
            ;;(if (require 'ox-gfm nil t) TODO My changes
            (setq backend 'gfm)
            ;;(require 'ox-md))
            (setq blog (org-export-as backend t))
            ;; Normalize save file path
            (unless (string-match "^[/~]" file)
              (setq file (concat hugo-content-dir file))
              (unless (string-match "\\.md$" file)
                (setq file (concat file ".md")))
              ;; save markdown
              (with-temp-buffer
                (insert fm)
                (insert blog)
                (untabify (point-min) (point-max))
                (write-file file)
                (message "Exported to %s" file))
              ))))
      )
  )

Blogging Setup: How to blog from org-mode to github-pages

Github pages cn are really an optimal way for org-mode nerds to blog. We usually have a github account anyway to manage our 1000+ commits big emacs config accross multiple devices, and we have learned enough about emacs to dish out some knowledge through our own blog.

How can you blog comfortably in this setup? Let’s get started…

Steps:

  • Create a directory where I want the blog to be, in my case ~/Dropbox/org/blog
  • Follow the steps from here: http://www.holgerschurig.de/en/emacs-blog-from-org-to-hugo/
  • Install hugo (on Windows 10)
    1. Install chocolatey https://chocolatey.org/install#install-with-cmdexe
      # for the powershell, close it after execution
      Set-ExecutionPolicy Bypass; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
              
    2. Install hugo using chocolatey:
      # on the normal shell
      choco install hugo -confirm
              
  • Follow the startup steps for hugo to setup a site and get the server running
    # some command to create a default site from the tutorial
    # then download a theme
    # copy the exampleSite structure from the theme directoy into the main blog directory to have some dummy content
    # - usually this dummy content also explains the theme capabilities
    cp -R theme/$theme_name/exampleSite .
    hugo server
    # look at the site
        
  • Create a github.io repository and connect it to the directory
    • Create the github repository
      • Navigate to your github account and create this repo: username.github.io
    • Create the local repository
      cd ~/Dropbox/org/blog
      git init
      git remote add origin https://github.com/username/username.github.io.git
              
  • Further steps:

Blogging Setup: Workflow for writing a new blogpost

Creating a new blog post using the previously describe setup should be easy and comfortable. These are the generic steps for adding a blog-post.
  1. Create the content in org-mode: Open any org-file on the computer and write a blogpost.
    • Any existing org-mode heading could be turned into a blogpost, but most generic notes dont make for a good blog post. Some of them can be a good basis though.
  2. Tag it so i can find it again later: Tag it with “blog” so I can find it through the agenda. Enables me to list how much time i spend blogging in a week / month / year.
  3. Create hugo variable placeholders: Navigate to the headline and press M-x hugo
  4. Fill in the hugo variables. An example is below:
    :PROPERTIES:
    :TITLE:    Setting up the blog
    :HUGO_TAGS: emacs blogging
    :HUGO_TOPICS: emacs
    :HUGO_FILE: setting_up_the_blog.md
    :HUGO_DATE: [2017-08-15 Di 22:14]
    :END:
        
    • It is hidden in an org-mode drawer which makes it easy to hide
  5. Convert the headline into a markdown file according to the hugo variables: Navigate to the headline and press M-x hugo
  6. Regenerate the website including the new markdown file: Open a shell (I use git bash on Windows), navigate to the blog directory and execute hugo
    • Optional: Debugging, check the blog post formatting before uploading it
    • For this execute “hugo server” and navigate to the local blog
    • Downside: pictures dont get resolved correctly
  7. Publish the website
    cd public
    git add * && git commit -m "site update" && git push origin master