Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
17287 lines (14401 sloc) 677 KB

This is the GNU/Emacs config file of Karl Voit.

This file is named config.org. My init.el got some nifty Elisp code that converts/tangles (only) the Elisp blocks into the config.el. And here I explained how this is done. This generated file is interpreted by my GNU/Emacs on startup.

Note that all Elisp blocks part of a DISABLED heading or which are marked with :tangle no won’t be tangled to the config.el file. Unfortunately, within the Org-mode rendering of GitHub, you won’t see the =DISABLED= keyword nor the =:tangle no= parameter of the babel blocks. Please get the Org-mode file and open it in your Emacs directly.

Originally, I found this process on this web page. However, I adapted its code and write additional features.

Links that start with id: won’t work for you because they link to my personal Org-mode files.

Some tasks I plan to do with my config.org:

  • [ ] FIXXME: think of merging the default dir .emacs.d/quelpa/ with .emacs.d/contrib/
  • [ ] FIXXME: migrate existing GitHub projects to quelpa
  • [ ] FIXXME: check why Python “auto-complete mode” is disabled in my config
  • [ ] FIXXME: check why Python > Ropemacs (for refactoring) is disabled in my config
  • [ ] FIXXME: add a table to each package with its history in my config:
    2020-01-13installed because of X
    2020-01-15disabled because issue Y
    2020-01-19enabled again after fixing with Z

What Solution I Am Using for Which I Consider My Main Use-Cases

Corresponding to my general blog article What App am I Using for What and How? I maintain this brief overview of my most important workflows for Emacs and what package solution I am using for it. If you want to learn more about my workflows, I recommend reading and following my Blog Series: Using Org Mode Features (UOMF).

If you want to read how my init.el is auto-generated from this Org mode file, read this article.

I do not maintain links to the sections below since this would be a very fragile task anyway considering the way GitHub links work for now. Therefore: if you are interested in details on a certain workflow, please do search for corresponding keywords. There are seldom multiple search hits except for separate key binding definitions or hydras.

WorkflowSolutionNotes
Installing software packagesuse-package with packages and git repositories
“Window management”eyebrowse with a decent hydra-bufferstop feature
Remembering bindings; cheatcheata hydra on F1 for each major mode; which-keytop feature
Naked and full-screen Emacsmy-toggle-naked-emacs()unclutter screen
Getting rid of scrollbarnyan-modeGet more horizontal screen space
Reducing clutter in mode linesmart-mode-line, mode-icons
Filter Org filessparse trees
Focus on Org sub-hierarchycustomized org-tree-to-indirect-buffer
Enhanced search/selection usabilityswiper, counsel, helm, helm-org-rifle
Switching buffersibuffer
Desktop notificationsalert
Inserting date/time-stampsmy-insert-timestamp(), my-insert-datestamp(),
Inserting characterschar-menu, M-x insert-char
Copying region to Org propertymy-org-region-to-property()very handy for org-contacts
Org to PDF exportnormal Org mode export via LaTeX (not pandoc)
Passwordsorg-crypt on Org mode headings
Coding pythonelpy, flycheck
Coding: Highlighting lines/wordsbm, highlight-symbol
Coding: Folding/unfoldingyafolding
Versioning filesmagit
Snippet managementyankpad with yasnippetadvanced workflows
Spell checkingflyspell with aspell
Formatting paragraphsmy-fill-or-unfill()
Formatting headingsmy-title-capitalization()
File managementdired with some very cool extensionsI’m still getting used to
Quickly jumping to a directorymy-dired-recent-dirs()top featurel; based on frecency
PDF readingpdf-toolsI’m still getting used to
PDF annotatingpdf-toolsI’m still getting used to
Record screencastsgif-screencast and non-emacs methods

What I’m not using at the moment:

  • projectile or other source code project management tools
  • vim bindings (evil, …)
  • configuration frameworks
  • reading and managing emails: I’d love to use notmuch but I can’t

You might want to take a look at the next section where I list my most important generic hydras in contrast to the F1-mapped mode hydras.

bug-hunter

;; remove comment characters when using but-hunter to bi-sect this file:
; -------------------------------------------------------------------------------------------
; (package-initialize)
; (defvar my-init-el-start-time (current-time) "Time when init.el was started")
; (setq my-user-emacs-directory "~/.emacs.d/")
; (add-to-list 'load-path (concat my-user-emacs-directory "contrib/org-mode/contrib/lisp"))
; (add-to-list 'load-path (concat my-user-emacs-directory "contrib/org-mode/lisp"))
; (require 'org)
; -------------------------------------------------------------------------------------------

literate test 1

Testing the noweb principle as shown on this page: https://www.hhyu.org/posts/literate_config/

  • [2021-02-05 Fri 11:09] issue: my (very fast) custom function to tangle does not handle noweb syntax and Holger’s page (the original author of the tangle function) doesn’t exist any more.
;; nowebtest3
(setq nowebtest3 t)
;; nowebtest1
<<nowebtest>>

Function keys

Here are my function-key-mappings that are included in most hydra help screens:

(setq my-f-key-settings (concat
"⇧             Git   ←change→ ┃  yp-exp yp-map            ┃  Project minimap  Beginner  Bright
"                                                                                                     (propertize
"    F1        F2    F3   F4  ┃  F5     F6       F7  F8   ┃  F9      F10      F11       F12
"                                                                                                      'face '(:foreground "green"))
"    Hydra  Windows        ★  ┃  spell  (←) error →  fix  ┃  Search  Menu     maximize  naked

"))

General settings

Here, I do set some very general settings for my GNU/Emacs.

profiling:

(defvar my-config-el-start-time (current-time) "Time when config.el was started")
;(profiler-start 'cpu);; test startup performance - create report with M-x profiler-report

;; from http://ergoemacs.org/emacs/elisp_datetime.html
(setq my-config-el-start-time-iso (concat
 (format-time-string "%Y-%m-%dT%T")
 ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5)))
  (format-time-string "%z"))))

2011-04-20: turn off backup files

(setq-default backup-inhibited t)

set start of week to Monday (not sunday) http://sunsite.univie.ac.at/textbooks/emacs/emacs_33.html

(setq-default calendar-week-start-day 1)

omit usage of TAB for C-x r o: indent-tabs-mode

(setq-default indent-tabs-mode nil)

append and update time-stamps for Time-stamp: <> in headers:

(add-hook 'write-file-hooks 'time-stamp)

set warning of opening large files to 100MB

(setq-default large-file-warning-threshold 100000000)

do not add double space after periods Real sentence in Emacs : emacs

(setq-default sentence-end-double-space nil)

https://www.emacswiki.org/emacs/TruncateLines M-x toggle-truncate-lines

(setq-default truncate-lines t)

elisp - Emacs truncate lines in all buffers - Stack Overflow

(setq-default global-visual-line-mode t)

inhibit the startup screen

(setq inhibit-startup-screen t)

English time-stamps in Org-mode (instead of localized German ones):

(setq system-time-locale "C")

Adaptive cursor width | Pragmatic Emacs: make cursor the width of the character it is under; i.e. full width of a TAB:

(setq x-stretch-cursor t)

Remember the position of a buffer and go to that position when re-opening the file: (2018-07-26 disabled because it is not always a good thing to do)

(setq-default save-place t)
(setq save-place-file (expand-file-name ".places" user-emacs-directory))
(save-place-mode 1)
(load-file (concat my-user-emacs-directory "private.el"))

Tip via irreal. I share the same rationale: I never answer anything different to “y”. So I disabled it:

(setq confirm-kill-processes nil)

Moves the mouse cursor out of the way when the text cursor seems to crash: documentation.

Possible values: banish, exile, jump, animate, proteus

(when (display-mouse-p) (setq mouse-avoidance-mode "animate"))

A tip from this wonderful blog article: map scroll-lock mode to the corresponding scroll-lock key:

(global-set-key (kbd "<Scroll_Lock>") 'scroll-lock-mode)

To avoid “Error saving to X clipboard manager.” as well as endless loop on exiting (see this):

(setq x-select-enable-clipboard-manager nil)

Turn off header when printing with M-x ps-print-buffer-with-faces and format according to this page:

(setq ps-paper-type 'a4
	  ps-font-size 9.0
	  ps-print-header nil
	  ps-landscape-mode nil
	  ps-number-of-columns 1)

Open file system read-only files as read-only in Emacs as well: (via this article)

(setq view-read-only t)

I’m not using abbrev mode and get annoyed by its questions:

;(save-abbrevs 'silently) ;; Silently save abbrevs: http://ergoemacs.org/emacs/emacs_abbrev_mode_tutorial.html
(setq save-abbrevs nil) ;; not saving abbrevs
(setq-default abbrev-mode nil)

Guru mode

(defun disable-guru-mode ()
  (guru-mode -1)
  )
(add-hook 'prelude-prog-mode-hook 'disable-guru-mode t)

Package

Configure the package manager(s) of my GNU/Emacs.

MELPA

http://www.reddit.com/r/emacs/comments/2u1bml/gnu_or_melpa_version_of_yasnippet_both_in_mx/

MELPA packages are usually built automatically from a project’s repository; the GNU repository has stable releases that are explicitly submitted to it.

package-user-dir holds the directory where Emacs package manager installs its local copies of the packages:

(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3") ;; from https://irreal.org/blog/?p=8243
(setq package-user-dir (concat my-user-emacs-directory "elpa"))
(require 'package)
(package-initialize)

;;2019-12-07;;  ;;(add-to-list 'package-archives '("marmalade" . "https://marmalade-repo.org/packages/"))
;;2019-12-07;;  ;;OLD:(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/"));; moved to stable.melpa.org https://www.reddit.com/r/emacs/comments/4zqbz0/whats_up_with_melpa_stable/
;;2019-12-07;;  (add-to-list 'package-archives '("melpa" . "http://stable.melpa.org/packages/"))
;;2019-12-07;;  ;;unstable;; (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
;;2019-12-07;;
;;2019-12-07;;  ;; 2017-03-26: from https://www.reddit.com/r/emacs/comments/61jsvy/melpa_stopped_working_over_https_for_me_any_ideas/
;;2019-12-07;;  (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/"))
;;2019-12-07;;  (add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/"))

;; 2019-12-07: severe issues with old package versions brings me to remove old config and start with this from docu:
(setq package-archives '(
                         ("melpa" . "https://melpa.org/packages/")
                         ("gnu" . "https://elpa.gnu.org/packages/")
                         ))

Elpy

Add elpy repository:

(add-to-list 'package-archives '("elpy" . "https://jorgenschaefer.github.io/packages/"))

fix certificate issue

Bugfixing: 2016-01-26: fix certificate issue: “gnutls.c: [0] (Emacs) fatal error: The TLS connection was non-properly terminated.”

(if (fboundp 'gnutls-available-p)
    (fmakunbound 'gnutls-available-p))
(setq tls-program '("gnutls-cli --tofu -p %p %h")
      imap-ssl-program '("gnutls-cli --tofu -p %p %s")
      smtpmail-stream-type 'starttls
      starttls-extra-arguments '("--tofu")
      )

Initialize misc packages

;; 2015-11-25: https://github.com/jwiegley/use-package
;(when (string-equal system-type "windows-nt")
;   (add-to-list 'load-path (concat package-user-dir "/use-package-20190405.2047"))
;)
(eval-when-compile
   (require 'use-package))
;(require 'diminish)
(require 'bind-key)

;; http://www.lunaryorn.com/2015/01/06/my-emacs-configuration-with-use-package.html
(setq package-enable-at-startup nil)
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(use-package f
  :ensure t
)
(use-package ivy
  :ensure t
  :config
    ;; 2019-12-07: this is found in https://github.com/abo-abo/swiper/blob/master/ivy.el (Version: 0.13.0)
    ;;    but not in the elpa package version 0.13.0 on my disk. Don't know why/how, just adding it as a workaround:
    (defcustom ivy-use-group-face-if-no-groups t
      "If t, and the expression has no subgroups, highlight whole match as a group.
    It will then use the second face (first of the \"group\" faces)
    of `ivy-minibuffer-faces'.  Otherwise, always use the first face
    in this case."
      :type 'boolean)
)
(use-package ht
  :ensure t
)

Quelpa

DISABLED because of:

Debugger entered--Lisp error: (file-error "Cannot open load file" "No such file or directory" "use-package-core")
  require(use-package-core)
  eval-buffer(#<buffer  *load*-463556> nil "/home/vk/.emacs.d/elpa/quelpa-use-package-20190210.1938/quelpa-use-package.el" nil t)  ; Reading at buffer position 1691
  load-with-code-conversion("/home/vk/.emacs.d/elpa/quelpa-use-package-20190210.1938/quelpa-use-package.el" "/home/vk/.emacs.d/elpa/quelpa-use-package-20190210.1938/quelpa-use-package.el" nil t)
  require(quelpa-use-package)
  eval-buffer(#<buffer  *load*-218457> nil "/home/vk/.emacs.d/config.el" nil t)  ; Reading at buffer position 4033
  load-with-code-conversion("/home/vk/.emacs.d/config.el" "/home/vk/.emacs.d/config.el" nil nil)
  load("/home/vk/.emacs.d/config.el" nil nil t)
  load-file("~/.emacs.d/config.el")

… including auto-update:

(if (require 'quelpa nil t)
    (quelpa-self-upgrade)
  (with-temp-buffer
    (url-insert-file-contents "https://framagit.org/steckerhalter/quelpa/raw/master/bootstrap.el")
    (eval-buffer)))

quelpa-use-package:

(quelpa
 '(quelpa-use-package
   :fetcher git
   :url "https://framagit.org/steckerhalter/quelpa-use-package.git"))
(require 'quelpa-use-package)

After that it is possible to call use-package with the :quelpa keyword:

EXAMPLES:

;; installs abc-mode with quelpa
(use-package abc-mode :quelpa)

;; does the same (`t' is optional)
(use-package abc-mode :quelpa t)

;; again... (if the package would have another name)
(use-package abc-mode :quelpa abc-mode)

;; passes upgrade parameter to quelpa
(use-package abc-mode :quelpa (:upgrade t))

;; uses the given recipe
(use-package abc-mode
  :quelpa (abc-mode :fetcher github :repo "mkjunker/abc-mode"))

;; recipe with plist arguments
(use-package abc-mode
  :quelpa ((abc-mode :fetcher github :repo "mkjunker/abc-mode") :upgrade t))

Read https://github.com/alphapapa/unpackaged.el#upgrade-a-quelpa-use-package-forms-package for upgrading quelpa packages.

Upper/lower-case

Many times, I do need to uppercase or lowercase a word. Those commands offer me quick shortcuts to do so.

See: id:2014-03-04-M-l-subword

(global-set-key [M-l] 'downcase-word)
(global-set-key [M-u] 'upcase-word)
(global-set-key [M-c] 'capitalize-word)

yes-or-no-p: prefer y/n

«True #Emacs Knights are lazy and hate typing yes/no - they prefer y/n instead. Use this (fset ‘yes-or-no-p ‘y-or-n-p) in your config.» … from: http://twitter.com/emacs_knight/status/128339316417101825

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

Deletes duplicate entries of the history of the minibuffer

«If the value of this variable is t, that means when adding a new history element, all previous identical elements are deleted.» from: http://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffer-History.html

(setq history-delete-duplicates t)

This is also necessary to avoid duplicate entries when searching with helm on Emacs 27 as shown here.

Pasting with the mouse without moving the point

«middle-clicking pastes at the current location instead of moving it» from: http://sachachua.com/blog/2017/04/emacs-pasting-with-the-mouse-without-moving-the-point-mouse-yank-at-point/

(setq mouse-yank-at-point t)

Un-setting some keys

Here, I do unset some keys I don’t use so that they are not in my way when I accidentially use them:

;;   \C-v   scroll up
;;   \C-t   transpose-chars
(dolist (key '("\C-v" "\C-t"))
    (global-unset-key key))

delete-trailing-whitespace before saving

I don’t see any use of trailing whitespace. Previously, I had a function to remove them mapped to my-map SPC but then I found out that adding this as a general before-save-hook does the job automatically:

2019-12-14: disabled because it consumed 20-40% of the time when saving large files. 22% on http://paste.grml.org/hidden/27a87675/

;;(bind-key (kbd "SPC") #'delete-trailing-whitespace my-map)
;  (define-key org-mode-map (kbd "C-c C-, SPC") #'delete-trailing-whitespace);; workaround since line above doesn't work

;; 2016-02-06: https://www.reddit.com/r/emacs/comments/445w6s/whats_some_small_thing_in_your_dotemacs_that_you/
(add-hook 'before-save-hook 'delete-trailing-whitespace)

Maximize frame window

Details: id:2016-03-27-maximize-window-init.el

[2020-12-10 Thu] Good read: Maximize the Emacs Frame on Startup | Emacs Redux

(toggle-frame-maximized)

Alternative from: Tip: Setting initial frame size and position

;; Set initial frame size and position
(defun my/set-initial-frame ()
  (let* ((base-factor 0.70)
	(a-width (* (display-pixel-width) base-factor))
        (a-height (* (display-pixel-height) base-factor))
        (a-left (truncate (/ (- (display-pixel-width) a-width) 2)))
	(a-top (truncate (/ (- (display-pixel-height) a-height) 2))))
    (set-frame-position (selected-frame) a-left a-top)
    (set-frame-size (selected-frame) (truncate a-width)  (truncate a-height) t)))
(setq frame-resize-pixelwise t)
(my/set-initial-frame)

Also mentioned:

I believe this works both in windows and in character terminals:

(setq default-frame-alist '((left . 0) (width . 141) (fullscreen . fullheight)))
  

(You might have to change 141 to something larger if you have a huge monitor.)

Window Management

See hydra-buffers() near the end of this file for a nice summary.

See GitHub - karthink/popper: Emacs minor-mode to summon and dismiss buffers easily for defining pop-up buffers.

my-vsplit-last-buffer() my-hsplit-last-buffer ()

This is using the last buffer for splitting windows instead of the current one:

From this emacs config which stole it from Sacha and reddit:

(defun my-vsplit-last-buffer ()
  (interactive)
  (split-window-vertically)
  (other-window 1 nil)
  (switch-to-next-buffer))

(defun my-hsplit-last-buffer ()
  (interactive)
  (split-window-horizontally)
  (other-window 1 nil)
  (switch-to-next-buffer))

(bind-key "C-x 2" 'my-vsplit-last-buffer)
(bind-key "C-x 3" 'my-hsplit-last-buffer)

my-frame-is-landscape() my-frame-is-portrait()

Following frame-width and frame-height values are returned when the Emacs frame (the thing which is called “window” on OS-level) is either higher or wider:

(frame-width) ;; portrait frame: 73; landscape frame: 190; quadratic frame: 47
(frame-height);; portrait frame: 56; landscape frame: 60 ; quadratic frame: 47

In order to find out whether or not there is more space in the horizontal or in the vertical line, I divide the width by two. This is because characters (the measure returned by (frame-width) and (frame-height)) are higher than wide approximately by factor two as well:

(if (< (/ (frame-width) 2) (frame-height))
  (message "portrait frame")
(message "landscape frame")
)

So I define functions to check the frame aspect that return boolean values:

(defun my-frame-is-landscape ()
  "Return true if Emacs frame is landscape and not portrait mode"
  (< (/ (frame-width) 2) (frame-height))
  )

;; (if (my-frame-is-landscape)
;;  (message "portrait frame")
;; (message "landscape frame")
;; )

(defun my-frame-is-portrait ()
  "Return true if Emacs frame is portrait and not landscape mode"
  (not (my-frame-is-landscape))
  )

(if (my-frame-is-portrait)
  (message "The frame is in landscape mode")
  (message "The frame is in portrait mode")
)

Default split direction according to frame aspect ratio

On wide screens, I want my default split direction being side-by-side (vertical split). On tilted/high screens, the default split should be up/down (horizontal split). (Source)

Note: this might be no good idea when you are not working with single/maximized windows like I prefer for now.

The values of the thresholds on sting (30”, landscape) before I started overwriting them here:

split-width-threshold  ;; Its value is 9999; Original value was 160
split-height-threshold ;; Its value is 80
(if (my-frame-is-landscape)
  (setq split-width-threshold nil);; for vertical split
  (setq split-width-threshold 1)  ;; for horizontal split
)

bookmarks

2021-06-05started to use bookmarks after watching this video
(setq bookmark-save-flag 1) ;; save bookmarks on every change

(setq bookmark-default-file (concat my-user-emacs-directory "/var/bookmark-default.el")) ;; this was set somewhere else; I did not look how/why. I just set it here again to make it explicit.

use-package and quelpa

My setup is using John Wiegley’s use-package for configuration and startup of external libraries. This has many advantages: flexibility, startup performance, readability.

Bootstrap use-package is stolen from this file:

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (require 'use-package))

(use-package use-package
   :ensure t
   ;;:pin MELPA
   :config
   (require 'use-package))

Until 2020-06-30, I only used use-package and manually cloned git repositories I included with hard-coded path. The latter were seldomly updated (if ever). With quelpa, there seems to be a much better way.

(use-package quelpa
  :ensure t
  :config
  (setq quelpa-upgrade-interval 7);; upgrade all packages once a week according to https://github.com/quelpa/quelpa
  (add-hook #'after-init-hook #'quelpa-upgrade-all-maybe)
)

The quelpa-use-package package offers a more or less transparent bridge between sites like GitHub and the use-package features.

(use-package quelpa-use-package
  :ensure t
)

Examples

Here are some examples for future reference:

A very simple example for installing a package via package management and ensure it is installed when Emacs launches:

(use-package dumb-jump
  :ensure t
  :defer 110
)

An example of loading a local package (not from Melpa or other package service):

(use-package define-word
   :if (my-system-type-is-gnu)
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/mypackage/")))
   :after org
)

Key binding example from docu:

(use-package helm
  :bind (("M-x" . helm-M-x)
         ("M-<f5>" . helm-find-files)
         ([f10] . helm-buffers-list)
         ([S-f10] . helm-recentf)))

more binding examples:

  :bind (:map my-map ("SPC" . yankpad-insert))

  :bind (("M-f" . sp-forward-sexp)
         ("M-b" . sp-backward-sexp)
         )


OR:

(bind-keys :map pdf-view-mode-map
        ("f9" . hydra-pdftools/body)
        ("<s-spc>" .  pdf-view-scroll-down-or-next-page)
        ("g"  . pdf-view-first-page)
        ("G"  . pdf-view-last-page)
        ("l"  . image-forward-hscroll)
        ("h"  . image-backward-hscroll)
        ("j"  . pdf-view-next-page)
        ("k"  . pdf-view-previous-page)
        ("e"  . pdf-view-goto-page)
        ("u"  . pdf-view-revert-buffer)
        ("al" . pdf-annot-list-annotations)
        ("ad" . pdf-annot-delete)
        ("aa" . pdf-annot-attachment-dired)
        ("am" . pdf-annot-add-markup-annotation)
        ("at" . pdf-annot-add-text-annotation)
        ("y"  . pdf-view-kill-ring-save)
        ("i"  . pdf-misc-display-metadata)
        ("s"  . pdf-occur)
        ("b"  . pdf-view-set-slice-from-bounding-box)
        ("r"  . pdf-view-reset-slice))

Use of :defer

:defer also accepts an optional numeric argument which causes the package to be loaded after N seconds of idle time.

From: https://www.gnu.org/software/emacs/manual/html_node/elisp/Idle-Timers.html

Emacs becomes idle when it starts waiting for user input, and it remains idle until the user provides some input.

My GNU/Emacs 26 takes approximately 70s to start. This is very long but it includes all my many “autostart” activities that also cover visibility settings in opened Org mode files and my complex agenda.

Therefore, my defer times start with 90s which is clearly after the startup.

Ocurrences in config.el (without disabled or not tangled code):

grep ":defer " ~/.emacs.d/config.el |  # extract all occurrences of ":defer" from the tangled init file
  sed 's/;;.*//' |         # remove emacs-lisp comments
  sed 's/ //g' |           # remove all space characters to normalize strings
  sed 's/defer/defer /' |  # add space character again only after ":defer"
  sort |                   # sort the resulting strings alphabetically
  uniq -c ;                # uniq them and count their occurrences
  date                     # add the current time stamp in order to know how recent this output is
      1 :defer 110
     21 :defer 110
      6 :defer 120
     11 :defer 90
Tue Apr 16 10:31:52 WEDT 2019

no-littering

From:

It sets some default paths in order to separate automatically created files and directories.

(use-package no-littering
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/no-littering/")))
   )
(require 'no-littering)

Logging

host-specific log file: my-log-hostspecific()

Here’s the idea: on every Emacs startup, a file like ~/.emacs.d/var/log/HOSTNAME.txt is overwritten with the current time-stamp and emacs-version. The path scheme follows the no-littering package I’m using as well.

While loading miscellaneous packages, I might decide to append a version string.

This way, I get a list of files from all of my hosts sharing the same Emacs configuration. Each of these files hold the time of the last startup and the version strings of interesting packages. This simplifies generating bug reports and finding issues with version conflicts.

Here is an example file content for one host:

Started on 2019-04-16T14:35:04+02:00
emacs-version 26.0.90
cygwin-mount-version 1.4.8
yas--version 0.11.0
org-version 9.1.6
plantuml-mode-version 1.2.3
magit-version 2.10.3

So how is it done? Here we go. Let’s define the common file name, one per host:

(setq my-var-log-hostname-file (concat no-littering-var-directory "log/host-" system-name ".txt"))

At Emacs startup, overwrite the file content and initializing it with the current time stamp:

(write-region (concat "Started on " my-config-el-start-time-iso "\n") nil my-var-log-hostname-file)

Define the function that is called to append lines to the file:

(defun my-log-hostspecific (mystring mycommand)
  "append a string and the result of a command to the my-var-log-hostname-file file"
  (interactive)
  (write-region (concat mystring " " mycommand "\n") nil my-var-log-hostname-file t)
)

And let’s use this new function to log the version of the GNU/Emacs that is starting:

(my-log-hostspecific "emacs-version" emacs-version)

general log file: my-log-misc()

I’m using a central logging file for all kind of logging messages. I started with my agenda genreation performance.

Where do I log to?

(setq my-log-file (concat no-littering-var-directory "log/misc.log"))

How do I log?

(defun my-log-misc (message)
   (interactive)
   (let ((current-timestamp
        (concat
          (format-time-string "%Y-%m-%dT%T")
          ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5)))
          (format-time-string "%z")))
        ))
  (write-region
    (concat (format-message "%s %s: %s\n" current-timestamp system-name message))
     nil my-log-file "append"))
)

Example:

(my-log "foo bar")

my-load-local-el()

Using this function, I am able to easily load lisp files within my Emacs config hierarchy. It contains minimal error handling for a missing file.

from: http://www.zonix.de/html40/linux/emacsgnus.html

(defun my-load-local-el (part)
  "load lisp file and warn if not found"
  (let ((fullname (concat my-user-emacs-directory part)))
    (if (file-exists-p fullname)
	(load fullname)
      (message (format "Loading %s (source)...failed" fullname)))))

Server mode

Start Emacs as a server process: new files can be visited via emacsclient (instead of parallel emacs instances). Therefore, I don’t have to run multiple instances (which occupies RAM storage) and I am able to open new files instantly.

(server-start)

my-system-is-FOOBAR

Emacs config switch depending on hostname or operating system: Idea found here: Single dot emacs file and per-computer configuration | SIGQUIT

This is so cool: with those functions, I am able to maintain one single Emacs configuration for all of my hosts. If there is something I want to do or do not on a specific platform or host, those functions allow me to express my restrictions easily:

;; Get current system's name
(defun my-insert-system-name()
  (interactive)
  "Get current system's name"
  (insert (format "%s" system-name))
  )

;; Get current system type
(defun my-insert-system-type()
  (interactive)
  "Get current system type"
  (insert (format "%s" system-type))
  )

;; Check if system is Darwin/Mac OS X
(defun my-system-type-is-darwin ()
  "Return true if system is darwin-based (Mac OS X)"
  (string-equal system-type "darwin")
  )

;; Check if system is Microsoft Windows
(defun my-system-type-is-windows ()
  "Return true if system is Windows-based (at least up to Win7)"
  (string-equal system-type "windows-nt")
  )

;; Check if system is GNU/Linux
(defun my-system-type-is-gnu ()
  "Return true if system is GNU/Linux-based"
  (string-equal system-type "gnu/linux")
  )

Here are host-specific functions which I should not use if possible because with them, I lose some generic approach:

(defun my-system-is-floyd-or-sting ()
  "Return true if the system we are running on is floyd or sting"
  (or
    (string-equal system-name "floyd")
    (string-equal system-name "floyd.lan")
    (string-equal system-name "sting")
    (string-equal system-name "sting.lan")
    )
  )

(defun my-system-is-sting ()
  "Return true if the system we are running on is sting"
  (or
    (string-equal system-name "sting")
    (string-equal system-name "sting.lan")
    )
  )

(defun my-system-is-floyd ()
  "Return true if the system we are running on is floyd"
  (or
    (string-equal system-name "floyd")
    (string-equal system-name "floyd.lan")
    )
  )

(defun my-system-is-rise ()
  "Return true if the system we are running on is floyd"
  (or
    (string-equal system-name "rise")
    )
  )

(defun my-system-is-blanche ()
  "Return true if the system we are running on is blanche"
  (or (string-equal system-name "blanche") (string-equal system-name "blanche.lan"))
  )

(defun my-system-is-karl-voit-at ()
  "Return true if the system we are running on is karl-voit.at"
  (string-equal system-name "friends.grml.info")
  )

(defun my-system-is-powerplantlinux ()
  "Return true if the system we are running on is powerplant"
  (or
   (string-equal system-name "powerplant")
   (string-equal system-name "powerplant.lan")
   )
  )

System-specific paths

The system PATH variable provides access to executables. However, I do tend to use programs which are not part of the PATH variable of the operating system as well. Therefore, I do extend the Emacs variable exec-path (further down and following headings).

http://www.emacswiki.org/emacs/MacOSTweaks#toc13

;; setting path so that Emacs finds aspell and such
(when (my-system-type-is-darwin)
  (setenv "PATH"
	  (concat (getenv "PATH")
		  ":/Users/vk/bin:/usr/local/texlive/2010/bin/x86_64-darwin:/opt/local/bin:/opt/local/sbin"))
  (setq exec-path (append exec-path
			  '("/opt/local/bin"
			    "/usr/local/texlive/2010/bin/x86_64-darwin"
			    "/usr/local/teTeX/bin/powerpc-apple-darwin-current"
			    )))
  (add-to-list 'load-path "/opt/local/share/emacs/site-lisp")

  ;; 2011-04-20: allow typing of german umlauts in OS X by Alt-u followed by u,o,a,...
  (setq mac-option-modifier nil)

  (setq org-ditaa-jar-path "~/data/hosts/blanche/config/ditaa.jar")

  ;; setting path to color-theme-mode.el from MacPorts
  (add-to-list 'load-path "/opt/local/share/emacs/site-lisp/color-theme-6.6.0")
  )

ditaa

(when (my-system-type-is-gnu)
  (setq org-ditaa-jar-path "/usr/share/ditaa/ditaa.jar")
  )

setting path so that Emacs finds aspell and such:

(if (my-system-type-is-windows)

    ;;disabled;(setenv "PATH"
    ;;disabled;               (concat (getenv "PATH")
    ;;disabled;		  ":/Users/vk/bin:/usr/local/texlive/2010/bin/x86_64-darwin:/opt/local/bin:/opt/local/sbin"))
    (setq exec-path (append exec-path
     			     '("C:/Program Files (x86)/Aspell/bin"
                                    "C:/ProgramData/chocolatey/bin"
     			       ;;disabled; "/usr/local/texlive/2010/bin/x86_64-darwin"
     			       ;;disabled; "/usr/local/teTeX/bin/powerpc-apple-darwin-current"
     			       )))
    ;;disabled;(add-to-list 'load-path "/opt/local/share/emacs/site-lisp")

 (
  ;; on all other systems:
  )
 )

Where my Org mode files reside. They are used all over this config and therefore, this has to be defined early:

(cond ((string-equal system-name "GRZN17009")
          (setq my-org-files-path "c:/Users/karl.voit/org/"))
      ((string-equal system-name "Cosmo")
          (setq my-org-files-path "c:/Users/John/AppData/Roaming/org/")
       )
      (t
          (setq my-org-files-path "~/org/"))
)
;;(message (format "Set \"my-org-files-path\" to: %s" my-org-files-path))

Setting the system-specific path for my-webarchive-tsfile-dir-path

;; different hosts do have the dir at different locations:
(setq my-webarchive-tsfile-dir-path (cond ((my-system-is-sting) "/home/vk/archive/backup/sting/webarchive")
                            ((my-system-is-rise) "/home/vk/Downloads/webarchive")
                            (t "/home/vk/Downloads/");; fallback path (should NOT be used)
                            ))

Emax64 settings

2019-11-09: settings according to the emax64 default .emacs file:

(when (my-system-type-is-windows)
;;  ;; Set repositories
;;  (require 'package)
;;  (setq-default
;;   load-prefer-newer t
;;   package-enable-at-startup nil)
;;  (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
;;  (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
;;  (setq package-user-dir "~/emax/elpa")
;;  (package-initialize)

;;  ;; Install dependencies
;;  (unless (and (package-installed-p 'delight)
;;               (package-installed-p 'use-package))
;;    (package-refresh-contents)
;;    (package-install 'delight t)
;;    (package-install 'use-package t))
;;  (setq-default
;;   use-package-always-defer t
;;   use-package-always-ensure t)

;;  ;; Use latest Org
;;  (use-package org
;;    ;;:pin org
;;    :ensure org-plus-contrib)

  (defvar emax-root (concat (expand-file-name "~") "/emax"))
  (defvar emax-bin (concat emax-root "/bin"))
  (defvar emax-bin64 (concat emax-root "/bin64"))
  (defvar emax-mingw64 (concat emax-root "/mingw64/bin"))
  (defvar emax-lisp (concat emax-root "/lisp"))

  (setq exec-path (cons emax-bin exec-path))
  (setenv "PATH" (concat emax-bin ";" (getenv "PATH")))

  (setq exec-path (cons emax-bin64 exec-path))
  (setenv "PATH" (concat emax-bin64 ";" (getenv "PATH")))

  (setq exec-path (cons emax-mingw64 exec-path))
  (setenv "PATH" (concat emax-mingw64 ";" (getenv "PATH")))

  (setenv "PATH" (concat "C:\\msys64\\usr\\bin;C:\\msys64\\mingw64\\bin;" (getenv "PATH")))

  (dolist (dir '("~/emax/" "~/emax/bin/" "~/emax/bin64/" "~/emax/mingw64/bin/" "~/emax/lisp/" "~/emax/elpa/" "~/bin/"))
  (add-to-list 'load-path dir))

  (set-language-environment 'utf-8)
  (setq locale-coding-system 'utf-8)
  (set-default-coding-systems 'utf-8)
  (set-terminal-coding-system 'utf-8)
  (prefer-coding-system 'utf-8)

  ;; Tangle configuration
  (org-babel-load-file (expand-file-name "~/emax/emax.org" user-emacs-directory))
  ;;(garbage-collect)

)

from emax.org:

(when (my-system-type-is-windows)
  ;  (setq-default
  ;      (defvar mp/font-family            "Consolas"  "The font to use.")
  ;  )

    ;; Running Windows Powershell from within Emacs
    ; (setq explicit-shell-file-name "c:\\windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe")
    ; (setq explicit-powershell.exe-args '("-Command" "-" )) ; interactive, but no command prompt

    ; (autoload 'powershell "powershell" "Run powershell as a shell within emacs." t)


    ;; Changes made for Aspell
  ;;  (setq-default ispell-program-name "~/emax/mingw64/bin/aspell.exe")
    (setq-default ispell-program-name "~/bin/aspell.cmd")
    (setq-default ispell-extra-args  '("--sug-mode=ultra"))
    ;; (setq ispell-dictionary "en_US")

    ;; Set "DICTDIR" variable
    (setenv "DICTDIR" (concat emax-mingw64 "/lib/aspell-0.60/"))


    ;; Automatically enable flyspell-mode in text-mode
    ;;(require 'flyspell)
    ;;(add-hook 'text-mode-hook 'flyspell-mode)
    (setq text-mode-hook '(lambda() (flyspell-mode t) ))
    ;;(setq text-mode-hook '(lambda()
    ;;                        (flyspell-mode t)))

    ;;(dolist (hook '(text-mode-hook))
    ;;  (add-hook hook (lambda () (flyspell-mode 1))))
    ;;(dolist (hook '(change-log-mode-hook log-edit-mode-hook))
    ;;  (add-hook hook (lambda () (flyspell-mode -1))))

    ;;(setq flyspell-issue-message-flag nil)

    ;;(require 'auto-dictionary)
    ;;(add-hook 'flyspell-mode-hook (lambda () (auto-dictionary-mode 1)))

    (require 'ispell)


;     (setq epg-gpg-home-directory "~/emax/mingw64/bin/")
;     (setq epg-gpg-program "~/emax/mingw64/bin/gpg.exe")
;     (setq epg-gpgconf-program "~/emax/mingw64/bin/gpgconf.exe")


;    (pdf-tools-install :no-query)
)

Cygwin Paths (Windows)

As mentioned in the chapter of system-specific paths, I do use programs which are not part of the PATH variable of the operating system. Cygwin executables (in form of babun) are one example of this kind of programs.

Links:

(when (and (my-system-type-is-windows) (string-equal system-name "GRZN17009"))

Hard-coding the cygwin install path (for babun):

  • id:2016-04-22-magit-not-working-on-windows
(setq cygwin-root-directory "c:/Users/karl.voit/.babun/cygwin/")

Check if Cygwin/babun inst found on the install path given:

(if (file-directory-p cygwin-root-directory)
    (progn

OLD method of extending the path:

(setenv "PATH"
        (concat
         ;;"c:\\cygwin64\\usr\\local\\bin" ";"  ;; Cygwin
         ;;"c:\\cygwin64\\bin" ";"  ;; Cygwin
         "C:\\Users\\karl.voit\\.babun\\cygwin\\bin" ";"
         "C:\\Users\\karl.voit\\.babun\\cygwin\\usr\\local\\bin" ";"
         "C:\\Python36\\" ";"
         "C:\\Program\ Files\ \(x86\)\\Java\\jre1.8.0_144\\bin" ";"
         (getenv "PATH")))

Extending the path:

(setq exec-path (cons (concat cygwin-root-directory "bin/") exec-path)) ;; Babun
(setq exec-path (cons (concat cygwin-root-directory "usr/local/bin/") exec-path)) ;; Babun
(setq exec-path (cons "C:/Program Files (x86)/Java/jre1.8.0_144/bin" exec-path)) ;; Babun

Adding cygwin mounts:

(use-package cygwin-mount)
(cygwin-mount-activate)

Adding cygwin bash shell

;;(setq shell-file-name "c:/cygwin64/bin/bash") ;; Cygwin
(setq shell-file-name (concat cygwin-root-directory "bin/zsh")) ;; Babun
;;(setq shell-file-name (concat cygwin-root-directory "bin/bash")) ;; Babun
(setenv "SHELL" shell-file-name)
(setq explicit-shell-file-name shell-file-name)
(setq ediff-shell shell-file-name)
(setq explicit-shell-args '("--login" "-i"))
(setq w32-quote-process-args ?\")

id:2015-11-02-tramp-windows-babel and Docu: help:tramp-methods

(setq tramp-default-method "plink")

requires: setup-cygwin.el and cygwin-mount.el in the contrib dir:

(add-to-list 'load-path (concat my-user-emacs-directory "contrib/"))
(require 'setup-cygwin)

END of Cygwin/babun configuration

    )
(message "»»» I could not locate the cygwin path")
)

end of Cygwin config

(my-log-hostspecific "cygwin-mount-version" cygwin-mount-version)
);; end of if-windows

Starting GNU/Emacs on Windows

First, I create a batch file which starts the emacs.exe with optional Org-mode files as parameters:

C:\Users\Karl.Voit\bin\windows-start-orgmode.bat

REM Here, invoke some syncronization mechanism like Unison:
REM "C:\Program Files\bin\unison-2.40.102-gtk.exe" grmlvrs

REM As of 2017, I switched from Unison to Syncthing

"C:\Program Files\emacs-24.5-bin-i686-mingw32\bin\emacs.exe"

REM Re-syncing after leaving Emacs:
REM "C:\Program Files\bin\unison-2.40.102-gtk.exe" grmlvrs

REM End

This batch file is included in a Visual Basic file. This way, I am able to start my GNU/Emacs using misc app-launcher solutions: batch files are not listed in typical app-launchers whereas VBS files work at least with my Hotstrings:

C:\Users\Karl.Voit\bin\orgmode.vbs or in Cygwin /home/karl.voit/bin/orgmode.vbs

'HideBat.vbs
CreateObject("Wscript.Shell").Run "C:\Users\Karl.Voit\bin\windows-start-orgmode.bat", 0, True

Looking for binaries

Some Emacs configuration snippets relate to external programs such as LaTeX. Instead of (a) blindly evaluating those snippets or (b) using per-host-configuration for them, I do prefer to check whether or not those programs are installed on the local host instead. This is just the sane way of doing those things.

In detail, it gets a bit dirty for Windows, since there are some tools that are installed but not listed in the PATH environment exec-path. See below for some workarounds for that.

my-binary-found(binaryname)

my-binary-found(binaryname) returns the path where a binary executable can be found within the exec-path.

It also checks certain operating system/binary combinations which aren’t likely in the exec-path.

  (defun my-binary-found(binaryname)
    "Returns the path where a binary executable can be found.

It also checks certain operating system/binary combinations which aren't likely in the exec path."
    (cond
     ((and (my-system-type-is-windows) (string= binaryname "firefox"))
      (when (file-exists-p "C:/Program Files/Mozilla Firefox/firefox.exe")
        (concat "C:/Program Files/Mozilla Firefox/firefox.exe")
        )
      )
     ((and (my-system-type-is-windows) (string= binaryname "python"))
      (when (file-exists-p "C:/Python27/python.exe")
        (concat "C:/Python27/python.exe")
        )
      )
     ((and (my-system-type-is-windows) (string= binaryname "outlook"))
      (when (file-exists-p "C:/Program Files/Microsoft Office/Office16/OUTLOOK.EXE")
        (concat "C:/Program Files/Microsoft Office/Office16/OUTLOOK.EXE")
        )
      )
     ;; this is the default check for all binaries which got no special handling above:
     (t
      (locate-file binaryname exec-path exec-suffixes 1))
     ))

Examples:

(message (concat "pdflatex found on: " (my-binary-found "pdflatex")))

(if (my-binary-found "pdflatex")
  (message "LaTeX found")
  (message "LaTeX not found")
)

my-binary-not-found-list and my-eval-if-binary-or-warn()

my-eval-if-binary-or-warn (binaryname &optional warningtext) checks if a binary can be found in the path via my-binary-found().

If not found, a warning message is printed which can be defined as an optional parameter as well. Additionally, the not found binaries are collected in the variable my-binary-not-found-list.

(defvar my-binary-not-found-list nil
  "Holds a list of binaries which could not be found via my-eval-if-binary-or-warn()"
  )

(defun my-eval-if-binary-or-warn (binaryname &optional warningtext)
  "Checks if a binary can be found in the path via my-binary-found().

If not found, a warning message is printed which can be defined as an optional parameter as well.
Additionally, the not found binaries are collected in the variable my-binary-not-found-list."
  (or warningtext (setq warningtext (concat "»»» I could not locate the PATH-binary for: " binaryname)))
  (let* ((binarypath (my-binary-found binaryname)))
    (if binarypath
       ;; binary was found in exec-path
       (concat binarypath)
      (progn
        ;; binary NOT found in exec-path:
        (message warningtext)
        (if my-binary-not-found-list
            (add-to-list 'my-binary-not-found-list binaryname)
          (setq my-binary-not-found-list (list binaryname))
          )
        ))))

Example usages:

(my-eval-if-binary-or-warn "yyy" "This is a warning text for yyy")
(my-eval-if-binary-or-warn "xxx")
(my-eval-if-binary-or-warn "xxx" "This is a warning text for xxx")
(my-eval-if-binary-or-warn "zzz" "This is a warning text for xxx")

(message "Binaries not found: %s" my-binary-not-found-list)

Example output for different hosts

This heading ist just for collecting example outputs:

sting output:

pdflatexTeX binary: /usr/bin/pdflatex
python binary: /usr/bin/python
firefox binary: /usr/bin/firefox
chrome binary:
aspell binary: /usr/bin/aspell
ispell binary:
pandoc binary: /usr/bin/pandoc
ditaa binary: /usr/bin/ditaa
gnuplot binary: /usr/bin/gnuplot
git binary: /usr/bin/git
Outlook binary:
grep binary: /bin/grep
scss binary: /usr/bin/scss
ag binary: /usr/bin/ag
biber binary: /usr/bin/biber

Windows output:

pdflatex binary: c:/Program Files/MiKTeX_2.9/miktex/bin/pdflatex.exe
python binary:
ipython binary:
firefox binary:
chrome binary:
aspell binary:
ispell binary:
pandoc binary: c:/Users/karl.voit/AppData/Local/Pandoc/pandoc.exe
ditaa binary:
gnuplot binary:
git binary:
Outlook binary:
grep binary:
scss binary:
ag binary:
biber binary: c:/Program Files/MiKTeX_2.9/miktex/bin/biber.exe
Binaries not found in checks above: (ag scss grep Outlook git gnuplot ditaa ispell aspell chrome firefox ipython python)

After moving system-specific paths above this checks: only aspell was found:

Binaries not found in checks above: (ag scss grep Outlook git gnuplot ditaa ispell chrome firefox ipython python)

but on Windows, there are following things installed:

  • [ ] python
  • [ ] ipython
  • [ ] firefox
  • [ ] chrome
  • [ ] (a/i?)spell
  • [ ] Outlook
    • real path: “C:\Program Files (x86)\Microsoft Office\root\Office16\OUTLOOK.EXE”
    • also holds for OUTLOOK.EXE and OUTLOOK
    • where outlook is also unsuccessful :-(
(message "★★★★★★★★★★")
(message (concat "pdflatex binary: " (my-binary-found "pdflatex")))
(message (concat "python binary: " (my-binary-found "python")))
(message (concat "ipython binary: " (my-binary-found "ipython")))
(message (concat "firefox binary: " (my-binary-found "firefox")))
(message (concat "chrome binary: " (my-binary-found "chrome")))
(message (concat "aspell binary: " (my-binary-found "aspell")))
(message (concat "ispell binary: " (my-binary-found "ispell")))
(message (concat "pandoc binary: " (my-binary-found "pandoc")))
(message (concat "ditaa binary: " (my-binary-found "ditaa")))
(message (concat "gnuplot binary: " (my-binary-found "gnuplot")))
(message (concat "git binary: " (my-binary-found "git")))
(message (concat "Outlook binary: " (my-binary-found "Outlook")))
(message (concat "grep binary: " (my-binary-found "grep")))
(message (concat "scss binary: " (my-binary-found "scss")))
(message (concat "ag binary: " (my-binary-found "ag")))
(message (concat "biber binary: " (my-binary-found "biber")))
(message "★★★★★★★★★★")

Test queries

Here, I do probe for some tools mostly because I want to test my code above.

When I am using tool-specific settings below, I do add comment characters to disable the check at this stage:

;;(my-eval-if-binary-or-warn "pdflatex")
;;(my-eval-if-binary-or-warn "python")
(my-eval-if-binary-or-warn "ipython")
;;(my-eval-if-binary-or-warn "firefox")
(my-eval-if-binary-or-warn "chrome")
;;(my-eval-if-binary-or-warn "aspell")
;;(my-eval-if-binary-or-warn "pandoc")
(my-eval-if-binary-or-warn "ditaa")
;;(my-eval-if-binary-or-warn "gnuplot")
;;(my-eval-if-binary-or-warn "git")
;;(my-eval-if-binary-or-warn "outlook")
(my-eval-if-binary-or-warn "grep")
;;(my-eval-if-binary-or-warn "scss")
(my-eval-if-binary-or-warn "ag")
(my-eval-if-binary-or-warn "biber")

System-specific browse-url-browser

Here, I do hard-code my preferred browser that is used when I open URLs within Emacs:

http://stackoverflow.com/questions/4506249/how-to-make-emacs-org-mode-open-links-to-sites-in-google-chrome

(setq firefox-path (my-eval-if-binary-or-warn "firefox"))
(setq chrome-path (my-eval-if-binary-or-warn "google-chrome"))

(cond
 ((my-system-type-is-darwin)
  (setq browse-url-browser-function 'browse-url-default-macosx-browser)
  )
 (firefox-path
  (setq browse-url-browser-function 'browse-url-generic
	browse-url-generic-program firefox-path)
  )
 (chrome-path
  (setq browse-url-browser-function 'browse-url-generic
	browse-url-generic-program chrome-path)
  )
 )

http://stackoverflow.com/questions/4506249/how-to-make-emacs-org-mode-open-links-to-sites-in-google-chrome

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

https://chrome.google.com/webstore/detail/ljobjlafonikaiipfkggjbhkghgicgoh?hl=de

  • Edit-server for Chrome
;(use-package edit-server)
(my-load-local-el "contrib/edit-server.el")
;won't work; (use-package edit-server
;won't work;    :load-path "~/.emacs.d/contrib/"
;won't work;    :config
;won't work;    (edit-server-start)
;won't work;    )

(if (locate-library "edit-server")
    (progn
      ;(use-package edit-server)
      (setq edit-server-new-frame nil)
      (edit-server-start)))

2017-06-20: A little trick with EWW : emacs - presents code to interactively select your browser of choice.

Styling

The (sub-)headings here deal with the visual appeal of my GNU/Emacs. I like dark themes and minimized interfaces. Therefore, I hide everyting I do not use.

Interesting read: http://www.tbray.org/ongoing/When/201x/2012/09/24/Typographic-notes

Show current column: 2020-01-01 disabled because of performance impact (re-drawing modeline at each keystroke)

(setq column-number-mode t)

Cursor settings:

;; Prevent the cursor from blinking
;(blink-cursor-mode 0)
(set-cursor-color "IndianRed")

Flat mode-line styling: 2014-05-24: from http://www.reddit.com/r/emacs/comments/23l9oi/flat_modeline/

(set-face-attribute 'mode-line nil :box nil)
(set-face-attribute 'mode-line-inactive nil :box nil)

Themes

2021-01-08I switch back to light theme (leuven or default) for now

Since a couple of major versions, GNU/Emacs has a built-in theme manager. This is for dealing with the themes.

(setq calendar-location-name "Graz, AT")
(setq calendar-latitude 47.07)
(setq calendar-longitude 15.43)
(use-package theme-changer)
(change-theme 'whiteboard 'misterioso)  ;; day and night theme

My favorite dark themes: wombat, misterioso, zenburn, material

;(load-theme 'wombat t) ;; dark theme
;;   (load-theme 'misterioso t)
;;   (load-theme 'zenburn t)
;;   (load-theme 'material t) ;; from http://www.reddit.com/r/emacs/comments/39dk64/escaping_from_org_mode/
;;              issues with *bold* stuff in org-mode :-(

My favorite light themes: leuven, whiteboard, solarized-light,

;;   (load-theme 'leuven t) ;; from http://www.reddit.com/r/emacs/comments/39dk64/escaping_from_org_mode/
;;   (load-theme 'whiteboard t)
;;   (load-theme 'solarized-light t)
(defadvice load-theme (before theme-dont-propagate activate) (mapcar #'disable-theme custom-enabled-themes))

Only one window on startup

«Make [current] WINDOW fill its frame.»

(add-hook 'emacs-startup-hook 'delete-other-windows t)

Font and Font sizes

2019-11-15: disabled because not used for a very long time:

(defun my-increase-fontsize ()
  (interactive)
  "Sets the font to bigger size"
  (set-face-attribute 'default (selected-frame) :height 130)
  )
(defun my-normal-fontsize ()
  (interactive)
  "Sets the font to normal size"
  (set-face-attribute 'default (selected-frame) :height 100)
  )

I was using DejaVu Sans Mono a while ago:

(set-face-attribute 'default nil :font "DejaVu Sans Mono-10")
;(add-to-list 'default-frame-alist
;                       '(font . "DejaVu Sans Mono-10"))
(add-to-list 'default-frame-alist '(font . "JetBrains Mono-12"))
;; (add-to-list 'default-frame-alist '(line-spacing . 0.2))
  • [2021-05-14 Fri] I’m switching to FantasqueSansMono-NoLoopK because JetBrains Mono does not emphasize boldface boldly enough for me
(add-to-list 'default-frame-alist '(font . "Fantasque Sans Mono-12"))

Host-specific font sizes: values are in 1/10pt → 100 are 10pt

;;(when (my-system-type-is-gnu)
;;  (my-increase-fontsize);; increase fonts on some hosts by default
;;  )
(when (my-system-type-is-darwin)
  (set-face-attribute 'default (selected-frame) :height 170);; 2011-04-20: increase/set font size http://www.emacswiki.org/emacs/SetFonts
  )
(when (my-system-type-is-windows)
  ;;(set-face-attribute 'default (selected-frame) :height 150)
  ;;(set-face-attribute 'default (selected-frame) :height 130);; 2016-08-19 let's test 130 after 150 seems too big
  (set-face-attribute 'default (selected-frame) :height 110);; 2017-09-06 detego
  )
(when (my-system-is-floyd)
  ;; (set-face-attribute 'default (selected-frame) :height 100) ;; 2020-08-20: switched back to 105
  ;; (set-face-attribute 'default (selected-frame) :height 105);; until 2019-12-23 -> not working
  (set-face-attribute 'default nil :height 105);; 2020-08-22 new command from https://stackoverflow.com/questions/294664/how-to-set-the-font-size-in-emacs
  )
(when (my-system-is-sting)
  ;;(set-face-attribute 'default (selected-frame) :height 110) ;; before 2018-02-24 (a bit large)
  ;;(set-face-attribute 'default (selected-frame) :height 105) ;; before 2019-10-24: I want to try smaller font
  ;;(set-face-attribute 'default (selected-frame) :height 102) ;; before 2019-12-04: even smaller on reduced resolution
  (set-face-attribute 'default (selected-frame) :height 110) ;; 2019-12-04: bigger font on native 30" resolution
  )
(when (my-system-is-rise)
  (set-face-attribute 'default (selected-frame) :height 100)
)

Different font size for mode-line (from this stackexchange page):

(let ((faces '(mode-line
               mode-line-buffer-id
               mode-line-emphasis
               mode-line-highlight
               mode-line-inactive)))
     (mapc
      (lambda (face) (set-face-attribute face nil :font "DejaVu Sans Mono-8"))
      faces))

Modeline with icons

There are two potentially nice packages in order to beautify my modeline even further:

FIXXME: So far, I did not try them because my current modeline is beautiful enough. Maybe in the future.

UTF-8 and codings

Activate UTF-8 mode:

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

When I paste from the Windows clipboard, I tend to get messed up Umlauts and special characters. This ought to fix it but I think that this does not work either:

(cond ((my-system-type-is-windows)
       ;; on Windows, 'utf-8 does not work properly when system
       ;; clipboard gets yanked
       (setq selection-coding-system 'utf-16le-dos)

       ;; For example: =\344= instead of =ä= on Windows 7:
       ;;(set-selection-coding-system 'iso-latin-1-dos)
       )

      ((my-system-type-is-gnu)
       (set-selection-coding-system 'utf-8)
       )
      (t
       (set-selection-coding-system 'utf-8)
       )
      )

;; 2013-12-10 IRC #Emacs
(set-clipboard-coding-system 'utf-8)

;; http://www.masteringemacs.org/articles/2012/08/09/working-coding-systems-unicode-emacs/
;; in addition to the lines above:

(set-default-coding-systems 'utf-8)
;; backwards compatibility as default-buffer-file-coding-system
;; is deprecated in 23.2.
(if (boundp 'buffer-file-coding-system)
    ;; NOTE: default-buffer-file-coding-system is obsolete; use
    ;;       buffer-file-coding-system if found
    (setq-default buffer-file-coding-system 'utf-8)
  (setq default-buffer-file-coding-system 'utf-8))
;; Treat clipboard input as UTF-8 string first; compound text next, etc.
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))

From: https://www.masteringemacs.org/article/working-coding-systems-unicode-emacs

[…] One problem with the universal coding system argument is that it only cares about Emacs’s settings, not those of your shell or system. That’s a problem, because tools like Python use the environment variable PYTHONIOENCODING to set the coding system for the Python interpreter.

I have written the following code that advises the universal-coding-system-argument function so it also, temporarily for just that command, sets a user-supplied list of environment variables to the coding system. […]

(defvar universal-coding-system-env-list '("PYTHONIOENCODING")
  "List of environment variables \\[universal-coding-system-argument] should set")

(defadvice universal-coding-system-argument (around provide-env-handler activate)
  "Augments \\[universal-coding-system-argument] so it also sets environment variables

Naively sets all environment variables specified in
`universal-coding-system-env-list' to the literal string
representation of the argument `coding-system'.

No guarantees are made that the environment variables set by this advice support
the same coding systems as Emacs."
  (let ((process-environment (copy-alist process-environment)))
    (dolist (extra-env universal-coding-system-env-list)
      (setenv extra-env (symbol-name (ad-get-arg 0))))
    ad-do-it))

my-map: my own keyboard shortcut prefix

About defining keys: Emacs: How to Define Keys

If you are not satisfied with the default setup of Emacs keyboard shortcuts, you start with defining your own keyboard shortcuts (bindings).

To avoid binding conflicts with libraries/packages, it is a good habit of using a keyboard shortcut prefix no-one else is using. So if you stick to this prefix, you’ve got your own «name-space» where you are able to define your bindings freely.

My approach is to use my-map as a mapping which is bound to C-c C-,= . So my personal bindings start with =C-c C-,= such as =C-c C-, - for decreasing the font size of GNU/Emacs.

2015-11-10: Following code was replaced by bind-key below:

;; 2011-04-20, 2013-04-08: defining «C-c C-,» as my own prefix:
;; http://stackoverflow.com/questions/1024374/how-can-i-make-c-p-an-emacs-prefix-key-for-develperlysense
;; http://stackoverflow.com/questions/5682631/what-are-good-custom-keybindings-in-emacs
;; NOTE: (info "(elisp) Key Binding Conventions") warns about user prefixes other than C-c
(global-unset-key (kbd "C-c C-,")); causes error: "Invalid modifier in string"
;; same as: (global-unset-key (kbd "C-c C-,"))
(define-prefix-command 'my-map)

2019-12-04: With Org mode version 9.2, C-c C-,= got mapped to =org-insert-structure-template. In order to avoid any conflict situation (also for communication with peers), I switch to a new binding: C-c C-k which is bound to org-kill-note-or-show-branches but it’s a less popular function.

Using the bind-key package: (OLD method without use-package:)

(require 'bind-key);; https://github.com/emacsattic/bind-key

;;(org-defkey org-mode-map (kbd "C-c C-,") nil);; clear binding

(bind-keys
 :prefix-map my-map
 :prefix-docstring "My own keyboard map"
 :prefix "C-c C-,"
 ;; 2013-03-31: http://stackoverflow.com/questions/3124844/what-are-your-favorite-global-key-bindings-in-emacs
 ("-" . text-scale-decrease)
 ("+" . text-scale-increase)
 ("=" . text-scale-increase);; because "+" needs "S-=" and I might forget to press shift
 )

New method that allows overwriting of bindings (see this comment using the after feature of use-package):

(use-package bind-key
  :ensure t
  :bind (:prefix-map my-map
         :prefix-docstring "My own keyboard map"
         :prefix "C-c C-,"
         ("-" . text-scale-decrease)
         ("+" . text-scale-increase))
         ("=" . text-scale-increase);; because "+" needs "S-=" and I might forget to press shift
  :after org)

Usage example:

(bind-key "m w" #'mark-word my-map)

or:

(bind-keys
 :map my-map
 ("f" . forward-char)
 ("b" . backward-char))

or for use-package():

:bind (:map my-map ("8" . bm-toggle))

Alternative tipp: in case you run out of keybinding spaces, you can take a look at hydra and the “defhydra hydra-k” method. Hydra lists a menu of options and the hydra-k offers a prefix for it.

See 33min30s of the video linked in: Irreal: Hydra Video

Misc modes/packages (part I)

which-key - displays the available key bindings automatically

https://github.com/justbur/emacs-which-key

I got the recommendation via this reddit thread with the arguments, that which-key is inferior to guide-key which I used before::

  • more active
  • more features
  • more contributions

when I do press my prefix for my-map and wait a bit, I get a popup buffer that tells me what bindings I am able to use.

(use-package which-key
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/emacs-which-key/")))
  :defer 120
  :config ;; executed after loading package
  (which-key-setup-side-window-right)
  (add-to-list 'which-key-replacement-alist '(("TAB" . nil) . ("" . nil)))
  (add-to-list 'which-key-replacement-alist '(("RET" . nil) . ("" . nil)))
  (add-to-list 'which-key-replacement-alist '(("DEL" . nil) . ("" . nil)))
  (add-to-list 'which-key-replacement-alist '(("SPC" . nil) . ("" . nil)))

  (which-key-mode)
)

Please note this pull request that explains why my characters are non-standard ones. It also adds a symbol for ESC.

My helper functions (part I)

Here I defined some functions I am using in the configuration below.

measure-time()

From time to time, I want to measure, how long an Elisp snippet ran. This can be done with following code.

from: http://stackoverflow.com/questions/23622296/emacs-timing-execution-of-function-calls-in-emacs-lisp

(defmacro measure-time (&rest body)
  "Measure the time it takes to evaluate BODY."
  `(let ((time (current-time)))
     ,@body
     (message " Execution time: %.06f" (float-time (time-since time)))))

my-title-capitalization(): Proper English Title Capitalization of a Marked Region → my-map C

Read http://www.karl-voit.at/2015/05/25/elisp-title-capitalization/ where I wrote a verbose description of the topic and my solution.

;; additionally to the list defined in title-capitalization:
(defvar my-do-not-capitalize-words '("lazyblorg" "mutt")
  "My personal list of words that doesn't get capitalized in titles.")


(defun title-capitalization (beg end)
  "Proper English title capitalization of a marked region"
  ;; - before: the presentation of this heading of my own from my keyboard and yet
  ;; - after:  The Presentation of This Heading of My Own from My Keyboard and Yet
  ;; - before: a a a a a a a a
  ;; - after:  A a a a a a a A
  (interactive "r")
  (save-excursion
    (let* (
	   ;; basic list of words which don't get capitalized according to simplified rules:
	   ;; http://karl-voit.at/2015/05/25/elisp-title-capitalization/
           (do-not-capitalize-basic-words '("a" "ago" "an" "and" "as" "at" "but" "by" "for"
                                            "from" "in" "into" "it" "next" "nor" "of" "off"
                                            "on" "onto" "or" "over" "past" "so" "the" "till"
                                            "to" "up" "yet"
                                            "n" "t" "es" "s"))
	   ;; if user has defined 'my-do-not-capitalize-words, append to basic list:
           (do-not-capitalize-words (if (boundp 'my-do-not-capitalize-words)
                                        (append do-not-capitalize-basic-words my-do-not-capitalize-words )
                                      do-not-capitalize-basic-words
                                      )
                                    )
           )
      ;; go to begin of first word:
      (goto-char beg)
      (capitalize-word 1)
      ;; go through the region, word by word:
      (while (< (point) end)
        (skip-syntax-forward "^w" end)
        (let ((word (thing-at-point 'word)))
          (if (stringp word)
              ;; capitalize current word except it is list member:
              (if (member (downcase word) do-not-capitalize-words)
                  (downcase-word 1)
                (capitalize-word 1)))))
      ;; capitalize last word in any case:
      (backward-word 1)
      (if (and (>= (point) beg)
               (not (member (or (thing-at-point 'word) "s")
                            '("n" "t" "es" "s"))))
          (capitalize-word 1))))
)

(ert-deftest my-title-capitalization ()
  "Tests proper English title capitalization"
  (should (string= (with-temp-buffer
		     (insert "the presentation of this heading of my own from my keyboard and yet\n")
		     (goto-char (point-min))
		     (set-mark-command nil)
		     (goto-char (point-max))
		     ;(transient-mark-mode 1)
		     (title-capitalization)
		     (buffer-string))
		   "The Presentation of This Heading of My Own from My Keyboard and Yet\n"
		   )))
(bind-key "c" #'title-capitalization my-map)

my-toggle-vertical-horizontal-split()

Toggle the windows split between horizontally and vertically. I usually don’t use it though.

From: http://www.emacswiki.org/emacs/ToggleWindowSplit

(defun my-toggle-vertical-horizontal-split ()
  "Switch window split from horizontally to vertically, or vice versa.

i.e. change right window to bottom, or change bottom window to right."
  (interactive)
  (require 'windmove)
  (let ((done))
    (dolist (dirs '((right . down) (down . right)))
      (unless done
        (let* ((win (selected-window))
               (nextdir (car dirs))
               (neighbour-dir (cdr dirs))
               (next-win (windmove-find-other-window nextdir win))
               (neighbour1 (windmove-find-other-window neighbour-dir win))
               (neighbour2 (if next-win (with-selected-window next-win
                                          (windmove-find-other-window neighbour-dir next-win)))))
          ;;(message "win: %s\nnext-win: %s\nneighbour1: %s\nneighbour2:%s" win next-win neighbour1 neighbour2)
          (setq done (and (eq neighbour1 neighbour2)
                          (not (eq (minibuffer-window) next-win))))
          (if done
              (let* ((other-buf (window-buffer next-win)))
                (delete-window next-win)
                (if (eq nextdir 'right)
                    (split-window-vertically)
                  (split-window-horizontally))
                (set-window-buffer (windmove-find-other-window neighbour-dir) other-buf))))))))

;(bind-key "|" 'my-toggle-split-and-single-window my-map)

my-yank-windows → my-map y

Yanking from the windows clipboard results in messed up lists. When using this special yank function, common list formatting is fixed for Org-mode syntax.

  • id:2016-05-22-my-yank-windows
(when (my-system-type-is-windows)

  (defun my-yank-windows ()
    "yanks from clipboard and replaces typical (list) markup"
    (interactive)
    (let ((mybegin (point)))              ;; mark beginning of line as start point
      (clipboard-yank)
      (save-restriction
        (narrow-to-region mybegin (point))  ;; ignore everything outside of region
        (recode-region (point-min) (point-max) 'latin-1 'windows-1252); fix char encoding, e.g.: \366 -> ö
        (goto-char (point-min))
        (while (search-forward "\"	" nil t)
          (replace-match "- " nil t))
        (goto-char (point-min))
        (while (search-forward "o	" nil t)
          (replace-match "  - " nil t))
        (while (search-forward "" nil t)
          (replace-match "\"" nil t))
        (while (search-forward "" nil t)
          (replace-match "\"" nil t))
        (while (search-forward "" nil t)
          (replace-match "'" nil t))
        (while (search-forward "" nil t)
          (replace-match "-" nil t))
        ;;(while (search-forward "1.	" nil t) ;; FIXXME: replace with regex-methods for numbers in general
        ;; (replace-match "1. " nil t))
        ))
    )

  (bind-key "y" 'my-yank-windows my-map)

)

my-fill-or-unfill() paragraph

M-q does fix paragraph formatting and is one of my most favorite commands in GNU/Emacs. If you need to go back to «one line per paragraph», this function offers a toggle function for M-q. Applied twice, it re-formats the current paragraph to one line. Very handy for copy/paste to web forms or such where you need one paragraph per line.

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

(global-set-key [remap fill-paragraph]
                'my-fill-or-unfill)

my-open-in-external-app()

Some times, I want to use an external application for opening a certain file instead of opening it in Emacs. This can be done using following function:

(defun my-open-in-external-app (&optional file)
  "Open the current FILE or dired marked files in external app.
   The app is chosen from your OS's preference."
  (interactive)
  (message "%s" (concat "my-open-in-external-app called with \"" file "\" as argument"))
  ;; FIXXME: add check if FILE is an existing file; show error message if not
  (let ( doIt
         (myFileList
          (cond
           ((string-equal major-mode "dired-mode") (dired-get-marked-files))
           ((not file) (list (buffer-file-name)))
           (file (list file)))))

    (setq doIt (if (<= (length myFileList) 5)
                   t
                 (y-or-n-p "Open more than 5 files? ") ) )

    (when doIt
      (cond
       ((my-system-type-is-windows)
        (mapc (lambda (fPath) (w32-shell-execute "open" (replace-regexp-in-string "/" "\\" fPath t t)) ) myFileList))
       ((string-equal system-type "darwin")
        (mapc (lambda (fPath) (shell-command (format "open \"%s\"" fPath)) )  myFileList) )
       ((my-system-type-is-gnu)
        (mapc (lambda (fPath) (let ((process-connection-type nil)) (start-process "" nil "xdg-open" fPath)) ) myFileList)
) ) ) ) )

my-buffer-exists(bufname)

my-buffer-exists(bufname)

(defun my-buffer-exists (bufname)
  (not (eq nil (get-buffer bufname)))
  )

my-comment-box

I got this code from pragmaticemacs:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; example:                                                                ;;
;; from http://irreal.org/blog/?p=374                                      ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun my-comment-box (b e)
"Draw a box comment around the region but arrange for the region to extend to at least the fill column. Place the point after the comment box."

(interactive "r")

(let ((e (copy-marker e t)))
  (goto-char b)
  (end-of-line)
  (insert-char ?  (- fill-column (current-column)))
  (comment-box b e 1)
  (goto-char e)
  (set-marker e nil)))

my-scroll-up-command() my-scroll-down-command()

Usually, C-p and C-n are mapped to scroll-down-command and scroll-up-command. Contrary to this, I like to scroll only half of a screen so that I can follow the content in a better way.

The following implementation was inspired by (and copied from) https://www.emacswiki.org/emacs/HalfScrolling

(defun my-window-half-height ()
  (max 1 (/ (1- (window-height (selected-window))) 2)))

(defun my-scroll-up-half ()
  (interactive)
  (scroll-up (my-window-half-height)))

(defun my-scroll-down-half ()
  (interactive)
  (scroll-down (my-window-half-height)))

my-screnshot-svg

2021-03-26added to my config after test looks awesome
(defun my-screenshot-svg ()
  "Save a screenshot of the current frame as an SVG image.
Saves to a temp file to /tmp/ and puts the filename in the kill ring."
  (interactive)
  (let* ((filename (make-temp-file "Emacs" nil ".svg"))
         (data (x-export-frames nil 'svg)))
    (with-temp-file filename
      (insert data))
    (kill-new filename)
    (message filename)))

Resulting image can ge opened, e.g., in inkscape. Using the context menu feature “Enter group #…” you can go as deep into the elements as you wish. It really looks amazing.

Spell checking

«Flyspell enables on-the-fly spell checking in Emacs by the means of a minor mode.»

Please do evaluate this only if “aspell” is found on the system:

(when (my-eval-if-binary-or-warn "aspell")

General settings

setting path to flyspell-mode.el from MacPorts:

(when (my-system-type-is-darwin)
  (add-to-list 'load-path "/opt/local/share/emacs/lisp/textmodes")
  )

save to user dictionary without asking:

(setq ispell-silently-savep t)

flyspell

flyspell.el http://kaolin.unice.fr/~serrano/

(autoload 'flyspell-mode "flyspell" "On-the-fly spelling checking" t)

Dictionary Settings

;(set-default 'ispell-local-dictionary my-german-ispell-dictionary)

;;(autoload 'flyspell-mode "flyspell" "On-the-fly ispell." t)
(setq flyspell-issue-welcome-flag nil)

(when (my-system-type-is-windows)
  (setq flyspell-default-dictionary "american")
)
(when (my-system-type-is-gnu)
  (setq flyspell-default-dictionary "de_AT")
)

from here to my-toggle-ispell-english-deutsch: see id:2014-01-06-aspell-issue

(eval-after-load "ispell"
  '(add-to-list 'ispell-dictionary-alist
                '("german8"
                   "[a-zA-ZäöüßÄÖÜ]" "[^a-zA-ZäöüßÄÖÜ]" "[']" t
                  ("-C" "-d" "de_DE-neu.multi")
                  "~latin1" iso-8859-1)))

(when (my-system-type-is-windows)
    ;; use english on powerplantwin:
    (let ((langs '("american" "german8")))
      (setq lang-ring (make-ring (length langs)))
      (dolist (elem langs) (ring-insert lang-ring elem)))
  )
(when (my-system-type-is-gnu)
    ;; use US english on powerplantwin:
    (let ((langs '("de_AT" "en_US")))
      (setq lang-ring (make-ring (length langs)))
      (dolist (elem langs) (ring-insert lang-ring elem)))
)
;;  ;; use american english on all other systems:
;;  (let ((langs '("german8" "american")))
;;    (setq lang-ring (make-ring (length langs)))
;;    (dolist (elem langs) (ring-insert lang-ring elem)))
;;  )

my-toggle-ispell-language()

my-toggle-ispell-language() because I use two languages and switch between them:

(defun my-toggle-ispell-language ()
  (interactive)
  (let ((lang (ring-ref lang-ring -1)))
    (ring-insert lang-ring lang)
    (ispell-change-dictionary lang)))

auto-dictionary-mode

2021-06-20disabled since I can’t remember that it did anything for me

This mode determines the dictionary language for the current buffer according to the text found. It switches language automatically when you switch the language you’re typing.

What a relief for bilingual people like me (German/English).

(use-package auto-dictionary
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/auto-dictionary-mode/")))
)

(require 'auto-dictionary)
;;(add-hook 'text-mode-hook 'flyspell-mode) ;; according to https://github.com/nschum/auto-dictionary-mode/issues/11#issuecomment-557741953
;;(add-hook 'flyspell-mode-hook (lambda () (auto-dictionary-mode 1)))

Spellchecking Source Code

Modes for programming languages; check spelling only in comments/strings

(add-hook          'c-mode-hook 'flyspell-prog-mode)
(add-hook         'sh-mode-hook 'flyspell-prog-mode)
(add-hook        'c++-mode-hook 'flyspell-prog-mode)
(add-hook       'ruby-mode-hook 'flyspell-prog-mode)
(add-hook      'cperl-mode-hook 'flyspell-prog-mode)
(add-hook     'python-mode-hook 'flyspell-prog-mode)
(add-hook   'autoconf-mode-hook 'flyspell-prog-mode)
(add-hook   'autotest-mode-hook 'flyspell-prog-mode)
(add-hook   'makefile-mode-hook 'flyspell-prog-mode)
(add-hook 'emacs-lisp-mode-hook 'flyspell-prog-mode)

Keybindings

2018-06-19: disabled most bindings because I moved those functions to a hydra with F5

(define-key global-map [(f5)] 'flyspell-mode)
(bind-key "fm" 'flyspell-mode my-map);; also mapped to F5
(bind-key "fr" 'flyspell-region my-map)
(bind-key "fl" 'my-toggle-ispell-language my-map);; also mapped to Shift-F5
(define-key global-map [(shift f5)] 'my-toggle-ispell-language)
(bind-key "ft" 'my-toggle-ispell-language my-map);; can't remember if l(anguage) or t(oggle)
(bind-key "fn" 'flyspell-goto-next-error my-map)
(bind-key "ff" 'flyspell-correct-word-before-point my-map)

For quickly correcting text, I keep F7 (next error) and F8 (fix) for going through the findings one by one:

(define-key global-map [(f7)] 'flyspell-goto-next-error)
(define-key global-map [(f8)] 'flyspell-correct-word-before-point)

End of aspell

);; when aspell found

flycheck

«Flycheck is a modern on-the-fly syntax checking extension for GNU Emacs, intended as replacement for the older Flymake extension which is part of GNU Emacs.»

(use-package flycheck
  :ensure t
  :init
  (global-flycheck-mode)
  :config
  (setq flycheck-flake8-maximum-line-length 200); http://www.flycheck.org/manual/latest/Configuring-checkers.html#Configuring-checkers
  )

Snippets

German blog article on snippet systems: http://www.karl-voit.at/Textbausteine/

I do recommend to use snippet systems for quickly inserting static (words/numbers, sentences, paragraphs, …) or dynamic (current date/time) text.

Most snippets, I do define in a system-wide tool so that I am able to use them in every program. Some snippets I do define and use only within Emacs. Yasnippet and yankpad offers me very advanced functionality to define and use most elaborate snippets. Those snippets vary from simple ones (e.g., check-lists for packing for vacations) to rather advanced ones (e.g., a complete lecture organization with many tasks and their dependencies).

yasnippet

Yasnippet is the snippet tool to use within Emacs:

(use-package yasnippet
  ;:load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/yasnippet/")))
  :demand t
  :mode ("/\\.emacs\\.d/etc/yasnippet/snippets/" . snippet-mode)
  :diminish yas-minor-mode
  ;;:defer 90
  :config
  (yas-load-directory (concat my-user-emacs-directory "etc/yasnippet/snippets/"))
  (yas-global-mode 1)

  ;; http://yasnippet.googlecode.com/svn/trunk/doc/index.html
  ;;disabled;(my-load-local-el "contrib/yasnippet/yasnippet.el")
  ;;(autoload 'yas-minor-mode "yasnippet")

  ;;disabled 2015-04-01 - issues did not vanish;; ;; https://capitaomorte.github.io/yasnippet/faq.html#sec-4
  ;;disabled 2015-04-01 - issues did not vanish;; ;; How to I use alternative keys, i.e. not TAB?
  ;;disabled 2015-04-01 - issues did not vanish;; ;; see id:2015-02-01-yas-expand-not-TAB
  ;;disabled 2015-04-01 - issues did not vanish;; (define-key yas-minor-mode-map (kbd "<tab>") nil)
  ;;disabled 2015-04-01 - issues did not vanish;; (define-key yas-minor-mode-map (kbd "TAB") nil)
  ;;disabled 2015-04-01 - issues did not vanish;; (define-key yas-minor-mode-map (kbd "<f4>") 'yas-expand)

  (my-log-hostspecific "yas--version" yas--version)
)

As of 2019-12-07, I moved more or less all snippets from plain yasnippet to yankpad.

yankpad

yankpad is an add-on that enables easy management of yasnippet snippets within an Org-mode file. I do define Org-mode-independent snippets with the basic yasnippet methods. Any snippet that is used within Org-mode only is defined in my yankpad file.

  • see also: id:2016-08-08-yankpad-test
(use-package yankpad
  :ensure t
  ;;:defer 110
  :init
  (setq yankpad-file (concat my-org-files-path "yankpad.org"))
  :bind (:map my-map ("SPC" . yankpad-insert)
                     ("y" . yankpad-expand)
        )
  :config
  (bind-key "<S-f5>" 'yankpad-expand)
  (bind-key "<S-f6>" 'yankpad-map)
  (setq yankpad-default-category "org-mode")
)

Programming

company (completion)

2021-04-04stolen config from https://github.com/zamansky/dot-emacs for playing with LSP
(use-package company
    :ensure t
    :config
    (setq company-idle-delay 0)
    (setq company-minimum-prefix-length 3)

    (add-hook 'after-init-hook 'global-company-mode)
    ;;  (global-company-mode t)

    ;; disable company mode in org mode:
    (add-hook 'org-mode-hook (lambda () (company-mode -1)))
)

Git

This is a section where all Git-related configuration is happening.

magit → my-map g

«Magit is an interface to the version control system Git, implemented as an Emacs package. Magit aspires to be a complete Git porcelain. While we cannot (yet) claim that Magit wraps and improves upon each and every Git command, it is complete enough to allow even experienced Git users to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains.»

Some people start using Emacs just to be able to use this nifty Git interface of Magit.

;;2018-07-09 test when using GitHub version;;(setq with-editor-file-name-history-exclude 1) ;; https://github.com/syl20bnr/spacemacs/issues/7225

(use-package magit
  ;;2018-07-09 disabled because lots of errors on load;; :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/magit/lisp/")))

  :if (and (my-eval-if-binary-or-warn "git") (my-system-type-is-gnu))
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  ;;  :bind (:map magit-status-mode-map ("q" magit-quit-session))
  :config ;; executed after loading package

  (setq magit-diff-refine-hunk 'all) ;; enable in-line diff highlighting

  ;; full screen magit-status
  ;; http://whattheemacsd.com//setup-magit.el-01.html
  (defadvice magit-status (around magit-fullscreen activate)
    (window-configuration-to-register :magit-fullscreen)
    ad-do-it
    (delete-other-windows))

  (defun magit-quit-session ()
    "restores the previous window configuration and kills the magit buffer"
    (interactive)
    (kill-buffer)
    (jump-to-register :magit-fullscreen))
(bind-key "g" #'magit-status my-map)

smeargle (highlighting)

Disabled 2020-01-07 because I don’t use it.

  • smeargle - Highlighting Regions by Last Updated Time (my-map c)
    • https://github.com/syohex/emacs-smeargle/
    • M-x smeargle - Highlight regions by last updated time.
    • M-x smeargle-age - Highlight regions by age of changes.
    • M-x smeargle-clear - Clear overlays in current buffer
(use-package smeargle
  :ensure t
  :defer 110
  :config ;; executed after loading package
  ;;:bind (:map my-map ("c" . smeargle)) ;; CONFLICTS with my title capitalization

You can set highlighted colors of smeargle by changing smeargle-colors:

(custom-set-variables
 '(smeargle-colors '((older-than-1day   . "red")
                     (older-than-3day   . "green")
                     (older-than-1week  . "yellow")
                     (older-than-2week  . nil)
                     (older-than-1month . "orange")
                     (older-than-3month . "pink")
                     (older-than-6month . "cyan")
                     (older-than-1year . "grey50"))))

And you can also set colors of smeargle-commits by smeargle-age-colors:

(custom-set-variables
 '(smeargle-age-colors '((0 . nil)
                         (1 . "grey80")
                         (2 . "grey70")
                         (3 . "grey60")
                         (4 . "grey50")
                         (5 . "grey40")
                         (6 . "grey30")
                         (7 . "grey20")
                         (8 . "grey10"))))

You can specify parameters until smeargle-age-threshold. age is set to smeargle-age-threshold if actual age of changes is older than smeargle-age-threshold. Default value of smeargle-age-threshold is 7.

Misc settings:

(global-set-key (kbd "C-x v s") 'smeargle)
(global-set-key (kbd "C-x v c") 'smeargle-commits)

;; Highlight regions at opening file
(add-hook 'find-file-hook 'smeargle)

;; Updating after save buffer
(add-hook 'after-save-hook 'smeargle)

End of smeargle:

);; end of smeargle

GitGutter

2019-12-31: DISABLED for performance reasons: https://www.reddit.com/r/orgmode/comments/e9p84n/scaling_org_better_to_use_more_medsize_files_or/fcm5bsc/

GitGutter is visualizing modified lines within the source code buffer.

(use-package git-gutter
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/emacs-git-gutter/")))
  :config

Either you use the global minor mode …

(global-git-gutter-mode +1)

;; inactivate git-gutter-mode in asm-mode and image-mode
(custom-set-variables
  '(git-gutter:disabled-modes '(asm-mode image-mode)))

… or activate the minor mode for specific modes:

(add-hook 'python-mode-hook 'git-gutter-mode)
(add-hook 'ruby-mode-hook 'git-gutter-mode)

Keyboard bindings: Jump to next/previous hunk

(global-set-key (kbd "S-<f2>") 'git-gutter:previous-hunk)
(global-set-key (kbd "S-<f3>") 'git-gutter:next-hunk)

More bindings:

(global-set-key (kbd "C-x C-g") 'git-gutter)
(global-set-key (kbd "C-x v =") 'git-gutter:popup-hunk)

;; Jump to next/previous hunk
(global-set-key (kbd "C-x p") 'git-gutter:previous-hunk)
(global-set-key (kbd "C-x n") 'git-gutter:next-hunk)

;; Stage current hunk
(global-set-key (kbd "C-x v s") 'git-gutter:stage-hunk)

;; Revert current hunk
(global-set-key (kbd "C-x v r") 'git-gutter:revert-hunk)

;; Mark current hunk
(global-set-key (kbd "C-x v SPC") #'git-gutter:mark-hunk)

If you set git-gutter:update-interval seconds larger than 0, git-gutter updates diff information in real-time by idle timer.

(custom-set-variables
'(git-gutter:update-interval 2))

Pass option to ‘git diff’ command: You can pass git diff option to set git-gutter:diff-option.

;; ignore all spaces
(custom-set-variables
 '(git-gutter:diff-option "-w"))

Customize visualization:

(custom-set-variables
 '(git-gutter:modified-sign "~ ") ;; two space
 '(git-gutter:added-sign "++")    ;; multiple character is OK
 '(git-gutter:deleted-sign "--"))

(set-face-background 'git-gutter:modified "purple") ;; background color
(set-face-foreground 'git-gutter:added "green")
(set-face-foreground 'git-gutter:deleted "red")

You can change minor-mode name in mode-line to set git-gutter:lighter. Default is GitGutter. First character should be a space.

(custom-set-variables
 '(git-gutter:lighter " GG"))

End of git-gutter:

)

git-timemachine

2019-12-08: disabled because I was not using it.

Step through historic versions: https://github.com/pidu/git-timemachine (2018-09-02: repo has been removed)

A page with an animated GIF showing its functionality.

Step through historic versions of git controlled file using everyone’s favourite editor

Visit a git-controlled file and issue M-x git-timemachine (or bind it to a keybinding of your choice). If you just need to toggle the time machine you can use M-x git-timemachine-toggle.

Use the following keys to navigate historic version of the file

pVisit previous historic version
nVisit next historic version
wCopy the abbreviated hash of the current historic version
WCopy the full hash of the current historic version
gGoto nth revision
qExit the time machine.
bRun magit-blame on the currently visited revision (if magit available).
(use-package git-timemachine
  :ensure t
  :defer 120
  :init

Source -> start from selected revision instead of HEAD

(defun my-git-timemachine-show-selected-revision ()
  "Show last (current) revision of file."
  (interactive)
  (let (collection)
    (setq collection
          (mapcar (lambda (rev)
                    ;; re-shape list for the ivy-read
                    (cons (concat (substring (nth 0 rev) 0 7) "|" (nth 5 rev) "|" (nth 6 rev)) rev))
                  (git-timemachine--revisions)))
    (ivy-read "commits:"
              collection
              :action (lambda (rev)
                        (git-timemachine-show-revision rev)))))

Open git snapshot with the selected version. Based on ivy-mode:

(defun my-git-timemachine ()
  "Open git snapshot with the selected version.  Based on ivy-mode."
  (interactive)
  (unless (featurep 'git-timemachine)
    (require 'git-timemachine))
  (git-timemachine--start #'my-git-timemachine-show-selected-revision))

end of git-timemachine:

);; end of git-timemachine

magit-log–add-date-headers

From: https://github.com/alphapapa/unpackaged.el

This requires ov.el: https://github.com/emacsorphanage/ov

(use-package ov
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/ov/")))
)
(defun unpackaged/magit-log--add-date-headers (&rest _ignore)
  "Add date headers to Magit log buffers."
  (when (derived-mode-p 'magit-log-mode)
    (save-excursion
      (ov-clear 'date-header t)
      (goto-char (point-min))
      (cl-loop with last-age
               for this-age = (-some--> (ov-in 'before-string 'any (line-beginning-position) (line-end-position))
                                        car
                                        (overlay-get it 'before-string)
                                        (get-text-property 0 'display it)
                                        cadr
                                        (s-match (rx (group (1+ digit) ; number
                                                            " "
                                                            (1+ (not blank))) ; unit
                                                     (1+ blank) eos)
                                                 it)
                                        cadr)
               do (when (and this-age
                             (not (equal this-age last-age)))
                    (ov (line-beginning-position) (line-beginning-position)
                        'after-string (propertize (concat " " this-age "\n")
                                                  'face 'magit-section-heading)
                        'date-header t)
                    (setq last-age this-age))
               do (forward-line 1)
               until (eobp)))))

(define-minor-mode unpackaged/magit-log-date-headers-mode
  "Display date/time headers in `magit-log' buffers."
  :global t
  (if unpackaged/magit-log-date-headers-mode
      (progn
        ;; Enable mode
        (add-hook 'magit-post-refresh-hook #'unpackaged/magit-log--add-date-headers)
        (advice-add #'magit-setup-buffer-internal :after #'unpackaged/magit-log--add-date-headers))
    ;; Disable mode
    (remove-hook 'magit-post-refresh-hook #'unpackaged/magit-log--add-date-headers)
    (advice-remove #'magit-setup-buffer-internal #'unpackaged/magit-log--add-date-headers)))

End of Git

) ;; end of magit use-package
;(my-log-hostspecific "magit-version" magit-version) ;; doesn't work (anywhere here) for some reason

highlight-symbol → my-map h

This package does highlight all occurrences of a given word. Very handy when programming: visualize all occurrences of a variable/function.

Note: This package here somehow overlaps with the “hover” feature of a LSP server that supports it. In that case, you should disable the highlight-symbol-mode below.

(use-package highlight-symbol
  :ensure t
  :defer 110
  ;;(bind-key (kbd "h") #'highlight-symbol my-map)
  :bind (:map my-map ("h" . highlight-symbol))
  :hook (python-mode . highlight-symbol-mode)
  )
;; original: (global-set-key [(control f3)] 'highlight-symbol)
;; original: (global-set-key [f3] 'highlight-symbol-next)
;; original: (global-set-key [(shift f3)] 'highlight-symbol-prev)
;; original: (global-set-key [(meta f3)] 'highlight-symbol-query-replace)

projectile

2020-12-10initial setup
(use-package projectile
  :ensure t
  :defer 110
)

Language Server Protocol (LSP) → C-c l

2021-04-03initial setup for testing with Python/pyls

Why? Python code completion was always a bit of a drag. I don’t code that often. When there was a long break between my Python sessions, somehow code completion was a fragile thing that often did not work. Because of this thread I do give LSP a try.

lsp-mode:

(use-package lsp-mode
  :ensure t
  :init
  ;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
  (setq lsp-keymap-prefix "C-c l")
  :hook ((python-mode . lsp)
         ;; if you want which-key integration
         ;; (lsp-mode . lsp-enable-which-key-integration) ;; 2021-04-04: I'm using lsp-deferred instead
       )
  :commands lsp
  )
  • [ ] FIXXME: maybe customize
    • lsp-pyls-plugins-flake8-ignore
    • lsp-pyls-plugins-pycodestyle-max-line-length
    • lsp-pyls-plugins-flake8-max-line-length

lsp-ui:

(use-package lsp-ui
    :ensure t
    :commands lsp-ui-mode
    :hook (lsp-mode . lsp-ui-mode)
    :config
    (setq lsp-ui-sideline-enable t)
    (setq lsp-ui-sideline-show-hover nil)
    (setq lsp-ui-doc-position 'bottom)
    ;; lsp config stuff
    (setq lsp-enable-links t)
    (setq lsp-signature-render-documentation t)
    (setq lsp-headerline-breadcrumb-enable t)
    (setq lsp-ui-doc-enable t)
    (setq lsp-completion-enable-additional-text-edit nil)
    (setq web-mode-enable-current-element-highlight t)
    (lsp-ui-doc-show)
)

for helm:

(use-package helm-lsp :ensure t :commands helm-lsp-workspace-symbol)

others:

;; ;; 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
;; watch https://www.youtube.com/watch?v=0bilcQVSlbM to get an idea
;; (use-package dap-mode :ensure t)
;; (use-package dap-python :ensure t) ;; to load the dap adapter for your language

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

Elisp

This heading contains configurations for editing Elisp code.

separate color for highlightning () brackets: http://compgroups.net/comp.emacs/to-use-special-color-for-brackets-in-emacs-lisp-mo/222015

;; ######################################################
(defface paren-face
  '((((class color) (background dark))
     (:foreground "grey30"))
    (((class color) (background light))
     (:foreground "grey60")))
  "Face used to dim parentheses.")
(defun egoge-dim-parens ()
  (font-lock-add-keywords nil
			  '(("(\\|)" . 'paren-face))))
(add-hook 'emacs-lisp-mode-hook 'egoge-dim-parens)

Do not use Auto Fill Mode for Lisp mode:

(add-hook 'emacs-lisp-mode-hook 'turn-off-auto-fill)

When editing code that uses parenthesis, enabling this does highlight the matching parenthesis:

(show-paren-mode t)

ert

for using unit tests of yasnippet (see id:2013-02-07yasnippetdebuggen and yasnippet-tests.el)

(my-load-local-el "contrib/cl-lib.el")
(my-load-local-el "contrib/ert.el")
(my-load-local-el "contrib/ert-x.el")

buttercup - Elisp test suite

Buttercup is a behavior-driven development framework for testing Emacs Lisp code. It allows to group related tests so they can share common set-up and tear-down code, and allows the programmer to “spy” on functions to ensure they are called with the right arguments during testing.

The framework is heavily inspired by Jasmine.

Disabled for now because I do not use it at the moment.

(use-package buttercup
  :ensure t
;  :if (my-system-is-floyd)
  :defer 110
  :config
)

smartparens - highlight corresponding parens

(use-package smartparens
  :init
  (smartparens-global-mode 1)
  (show-smartparens-global-mode +1)

  :bind (;; ("M-n" . sp-next-sexp)
         ;; ("M-p" . sp-previous-sexp)
         ("M-f" . sp-forward-sexp)
         ("M-b" . sp-backward-sexp)
         )

  :config
  ;; Enable smartparens everywhere
  (use-package smartparens-config)

  ;; ;; Require and disable paredit because some packages rely on it.
  ;; (use-package paredit)
  ;; (disable-paredit-mode)

  (setq
   smartparens-strict-mode t
   sp-autoinsert-if-followed-by-word t
   sp-autoskip-closing-pair 'always
   ;;sp-base-key-bindings 'paredit
   sp-hybrid-kill-entire-symbol nil)

  ;; (sp-use-paredit-bindings)

  ;; (sp-with-modes '(markdown-mode gfm-mode rst-mode)
  ;;   (sp-local-pair "*" "*" :bind "C-*")
  ;;   (sp-local-tag "2" "**" "**")
  ;;   (sp-local-tag "s" "```scheme" "```")
  ;;   (sp-local-tag "<"  "<_>" "</_>" :transform 'sp-match-sgml-tags))

  ;; ;; Close a backtick with another backtick in clojure-mode
  ;; (sp-local-pair 'clojure-mode "`" "`" :when '(sp-in-string-p))

  (sp-local-pair 'emacs-lisp-mode "`" nil :when '(sp-in-string-p))
  )

s - «The long lost Emacs string manipulation library.»

https://github.com/magnars/s.el

(use-package s
  :ensure t
  :defer 90
  :config
)

Elisp: → my-map er|el|ef

Misc bindings for Elisp:

(bind-key "er" #'eval-region my-map)
(bind-key "el" #'find-library my-map)
(bind-key "ef" #'find-function-at-point my-map)

macrostep

I found the macrostep package through the Irreal article John Wiegley and Sacha Chua on use-package which links 2015-04-01 Emacs package highlight: use-package from YouTube.

(use-package macrostep
  ;;:ensure t
  :defer 120
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/macrostep/")))
  :config ;; executed after loading package
  (define-key emacs-lisp-mode-map (kbd "C-c e") 'macrostep-expand)
)

From the README:

The standard keybindings in macrostep-mode are the following:

e, =, RET
expand the macro form following point one step
c, u, DEL
collapse the form following point
q, C-c C-c
collapse all expanded forms and exit macrostep-mode
n, TAB
jump to the next macro form in the expansion
p, M-TAB
jump to the previous macro form in the expansion

It’s not very useful to enable and disable macrostep-mode directly. Instead, bind macrostep-expand to a key in emacs-lisp-mode-map, for example C-c e:

 (define-key emacs-lisp-mode-map (kbd "C-c e") 'macrostep-expand)
  

You can then enter macrostep-mode and expand a macro form completely by typing C-c e e e ... as many times as necessary.

Exit macrostep-mode by typing q or C-c C-c, or by successively typing c to collapse all surrounding expansions.

lisp-format

2021-07-31I wanted to test the Elisp formatter for formatting my code
(use-package elisp-format
  :ensure t
  :defer 110
)

Python

2021-04-04shift from previous elpy-based setup to a LSB-based setup

This heading contains configurations for editing Python code. Python is the programming language I prefer for my private projects. I do like its easy-to-read syntax, providing a high level of maintainability. It also ships with a large set of libraries.

Selected keyboard commands (summary): (see defined hydra for python mode!)

KeyCommandCommand
M-hhide/show current functionhs-cycle
C-c l g gfind definitionlsp-find-definition
C-c l g rfind referenceslsp-find-references
<missing>function overview

BEGIN of Python-related stuff

The code blocks here are only executed when python is found on the current system:

(when (my-eval-if-binary-or-warn "python")

auto-mode-list for Python files

(add-to-list 'auto-mode-alist '("\\.py$" . python-mode))
(add-to-list 'auto-mode-alist '("\\.py$" . company-mode))

  (add-hook 'python-mode-hook
      (lambda ()
        (lsp-mode)
        ))

pyls (LSP)

sudo python3 -m pip install 'python-language-server[all]'

or even better:

python3 -m pip install --user 'python-language-server[all]'

Optional:

sudo python3 -m pip install pyls-mypy

On [2021-08-27 Fri] my Emacs wrote:

Warning (emacs): The palantir python-language-server (pyls) is unmaintained; a maintained fork is the python-lsp-server (pylsp) project; you can install it with pip via: pip install python-lsp-server Disable showing Disable logging

So I did:

sudo python3 -m pip uninstall 'python-language-server[all]'
sudo python3 -m pip install python-lsp-server

jedi (LSP)

[2021-04-04 Sun 16:56] disabled: I want to test pure pyls

Setup according to https://github.com/zamansky/dot-emacs

(use-package lsp-jedi
  :ensure t
  :config
  (with-eval-after-load "lsp-mode"
    (add-to-list 'lsp-disabled-clients 'pyls)
    (add-to-list 'lsp-enabled-clients 'jedi)))

(setq lsp-ui-doc-show-with-cursor nil)

Switch to ipython (NOT YET TESTED)

From this reddit and this solution: NOT TESTED YET! (2017-10-02)

2019-01-20: this reddit thread suggests overwriting python-shell-interpreter in order to switch to Python 3. (not tested/confirmed yet)

(if (my-eval-if-binary-or-warn "ipython3")
    (setq python-shell-interpreter "ipython3"
        python-shell-interpreter-args "--simple-prompt -i")
    ;; else:
    (when (my-eval-if-binary-or-warn "python3")
      (setq python-shell-interpreter "python3")
    )
)

Note: Org mode babel is using org-babel-python-command which is set elsewhere (to python3 as of 2019-03-05).

flymake, flycheck

2021-04-04I’m unsure if this is still necessary after switching to LSP/pyls

FlyMake performs on-the-fly syntax checks on the files being edited using the external syntax check tool (usually the compiler). Highlights erroneous lines and displays associated error messages.

Unfortunately, this project is outdated and last change was 3 years ago.

For a modern alternative, check out Flycheck.

(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
    (let* ((temp-file (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-inplace))
           (local-file (file-relative-name
                        temp-file
                        (file-name-directory buffer-file-name))))
      (list "~/bin/pycheckers"  (list local-file))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init)))

better than flymake (and maintained): http://stackoverflow.com/a/1621489 Flycheck

(add-hook 'python-mode-hook
    (lambda ()
      (unless (eq buffer-file-name nil) (flymake-mode 1)) ;dont invoke flymake on temporary buffers for the interpreter
      (local-set-key [f6] 'flymake-goto-prev-error)
      (local-set-key [f7] 'flymake-goto-next-error)
      ))

hideshow-orgmode

I found hideshow-orgmode via this reddit thread. It provides (Python) code outlining similar to Org-mode TAB visibility cycling. This is a very nice thing to have. So far, I used yafolding-mode for it.

This needs the hideshow minor mode M-x hideshow-minor-mode enabled to work.

  (use-package hideshow-orgmode
    :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/hideshow-orgmode")))
    :config
    (add-hook 'python-mode-hook (lambda ()
                                (hs-minor-mode 1)
                                ;;(hs-cycle-all)
                                (global-set-key (kbd "M-h") 'hs-cycle)
                                (global-set-key (kbd "M-H") 'hs-cycle-all)
                                ))
)

sphinx-doc.el

Source: https://github.com/naiquevin/sphinx-doc.el

sphinx-doc is an emacs minor mode for inserting docstring skeleton for Python functions and methods. The structure of the docstring is as per the requirement of the Sphinx documentation generator.

  (use-package sphinx-doc
    :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/sphinx-doc.el")))
    :ensure t
    :config
    (add-hook 'python-mode-hook (lambda ()
                                  (require 'sphinx-doc)
                                  (sphinx-doc-mode t)))
)

Issue:

let: Symbol’s value as variable is void: sphinx-doc-python-indent

… when applied. I could not find anything related.

elpygen → C-c i

From GitHub: “Generate Python function/method stub for a call-like symbol under point”

Just write a_function_call(first_named, 2, second_named), invoke the command elpygen-implement and elpygen either jumps to the existing function or it generates a stub for a new one. The example above results in def a_function_call(first_named, arg1, second_named):\npass.

(use-package elpygen
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/elpygen")))
  :ensure t
  :config
  (require 'elpygen)
  (define-key python-mode-map (kbd "C-c i") 'elpygen-implement)
)

END of Python-related stuff

);; if python binary found

dired

Usually, I do file management in tmux and zsh. There are my aliases, my functions, the features I like. Having a file manager in Emacs does have some advantages.

Dired tipps from ergoemacs. Mastering Emacs on Dired.

Here are some minor tweaks related to file management in Emacs with dired.

From Emacsrocks #16: two window file management. From the documentation:

If non-nil, Dired tries to guess a default target directory. This means: if there is a Dired buffer displayed in the next window, use its current directory, instead of this Dired buffer’s current directory.

(setq dired-dwim-target t)
;;(setq dired-listing-switches "-al  --group-directories-first")

from: Marcin Borkowski: 2018-12-10 Lesser known Dired stuff: create parent directories when slashes are used when renaming files:

;(setq wdired-create-parent-directories t)  FIXXME: enable when my old installation gets an update

dired-garbage-files-regexp - define garbage file regex

In dired, you can press %& which calls dired-flag-garbage-files(). By default, it uses the regular expression =”\(?:\.\(?:aux\|bak\|dvi\|log\|orig\|rej\|toc\)\)\’”= which does not include miscelaneous file extensions I am working with.

Therefore, I overwrite the regex with my own values:

(setq dired-garbage-files-regexp "\\(?:\\.\\(?:aux\\|bak\\|bbl\\|bcf\\|dvi\\|log\\|rej\\|toc\\)\\)\\'")

dired-details → (

  • [ ] FIXXME 2018-07-06: think of switching to dired-details+ (which offers some functionality I currently do not use).

Also from Emacsrocks #16: hide and show file details with ( and ):

(use-package dired-details
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
  ;;:defer 90
  :config
  (setq-default dired-details-hidden-string "")
  )

dired-x, dired+, dired-icon

Enabling already pre-insalled dired-x:

(require 'dired-x)

Dired+ has lots of useful features

(use-package dired+
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-plus/")))
;;  :ensure t
  ;;:defer 90
  :config
  (diredp-toggle-find-file-reuse-dir 1) ;; https://www.emacswiki.org/emacs/DiredReuseDirectoryBuffer
)

2019-02-05: disabled because loading a new dired buffer took very long with it although it really looked nicely:

(use-package dired-icon
:ensure t
;;:defer 110
:config
(add-hook 'dired-mode-hook 'dired-icon-mode)
)

Bind backspace to visit higher level directory:

(define-key dired-mode-map (kbd "<backspace>") 'diredp-up-directory-reuse-dir-buffer)

helm-dired-history

  • [ ] ivy-dired-history is an alternative to:
(use-package helm-dired-history
:ensure t
:config
(require 'savehist)
(add-to-list 'savehist-additional-variables 'helm-dired-history-variable)
(savehist-mode 1)
(with-eval-after-load 'dired
  (require 'helm-dired-history)
  (define-key dired-mode-map "," 'dired))
)

dired-recent → C-z

This is one of the killer-features of (any) file-browser application: offer a quick search of recently visited directories. I never maintain any directory bookmarks any more. I use a similar feature in my zsh via z. You might also look into GoTo (on steroids) of fman.

“Press C-x C-d to select a previously visited directory to open.”

(use-package dired-recent
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-recent.el/")))
   ;;:defer 90
   :config
   (require 'dired-recent)
   (dired-recent-mode 1)
   (setq dired-recent-max-directories nil) ;; nil means to remember all
)

Make better use of dired-recent-open using ivy:

(defun my-dired-recent-dirs ()
  "Present a list of recently used directories and open the selected one in dired"
  (interactive)
    (let ((dir (ivy-read "Directory: "
                         dired-recent-directories
                         :re-builder #'ivy--regex
                         :sort nil
                         :initial-input nil)))
      (dired dir)))

(global-set-key (kbd "C-z") 'my-dired-recent-dirs)

Maybe, this can be optimized by using frecency for scoring entries (like in fman or this feature-request for FreeCommander). So far, I’m quite happy with the current feature.

dired-narrow → /

From http://pragmaticemacs.com/emacs/dynamically-filter-directory-listing-with-dired-narrow/ with https://github.com/Fuco1/dired-hacks

It narrows down the list of files using a pattern. g resets the view.

(use-package dired-narrow
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/")))
  ;;:defer 90
  :bind (:map dired-mode-map
              ("/" . dired-narrow)))

dired-open

From https://github.com/Fuco1/dired-hacks

Provides:

  • dired-open-xdg try to open the file using xdg-open
  • dired-open-guess-shell-alist try to open the file by launching applications from dired-guess-shell-alist-user
  • dired-open-call-function-by-extension call an elisp function based on extension.
(use-package dired-open
  ;;:defer 90
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/")))
)

dired-collapse

From https://github.com/Fuco1/dired-hacks#dired-collapse

Provides:

  • dired-open-xdg try to open the file using xdg-open
  • dired-open-guess-shell-alist try to open the file by launching applications from dired-guess-shell-alist-user
  • dired-open-call-function-by-extension call an elisp function based on extension.
(use-package dired-collapse
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/")))
  ;;:defer 90
  :config
  ;(dired-collapse-mode)
)

image-dired+

Image-dired extensions: https://www.emacswiki.org/emacs/ImageDired

Emacs manual:

To enter Image-Dired, mark the image files you want to look at in the Dired buffer, using m as usual. Then type C-t d (image-dired-display-thumbs). This creates and switches to a buffer containing image-dired, corresponding to the marked files.

You can also enter Image-Dired directly by typing M-x image-dired. This prompts for a directory; specify one that has image files. This creates thumbnails for all the images in that directory, and displays them all in the thumbnail buffer. This takes a long time if the directory contains many image files, and it asks for confirmation if the number of image files exceeds image-dired-show-all-from-dir-max-files.

FIXXME: 2018-06-30: There is a issue on floyd. I get following error when I mark files and invoke C-t d:

[...]
error in process sentinel: image-diredx--invoke-process: Wrong type argument: processp, [nil 23351 46922 931735 nil image-dired-thumb-queue-run nil nil 787000]
error in process sentinel: Wrong type argument: processp, [nil 23351 46922 931735 nil image-dired-thumb-queue-run nil nil 787000]
[...]
Marking files...
377 files newly marked
image-diredx--invoke-process: Wrong type argument: processp, [nil 23351 47004 248326 nil image-dired-thumb-queue-run nil nil 669000]
[...]
(use-package image-dired+
  :ensure t
  :defer 110
  :config
  (require 'image-dired+)
  (image-diredx-async-mode 1)
  (image-diredx-adjust-mode 1)
  (define-key image-dired-thumbnail-mode-map "\C-n" 'image-diredx-next-line)
  (define-key image-dired-thumbnail-mode-map "\C-p" 'image-diredx-previous-line)
  (define-key image-dired-thumbnail-mode-map "g" 'revert-buffer);; revert all thumbnails if `image-diredx-async-mode' is on
  (define-key image-dired-thumbnail-mode-map "x" 'image-diredx-flagged-delete);; Delete confirmation prompt with thumbnails
  (setq image-dired-track-movement nil) ;; Suppress unknown cursor movements
  (setq image-dired-external-viewer "/usr/bin/geeqie") ;; FIXXME: configure different for Windows
)

dired-ranger → M-c; M-v; M-m

From https://github.com/Fuco1/dired-hacks:

With the multi-stage operations, you can gather files from multiple dired buffers into a single “clipboard”, then copy or move all of them to the target location. Another huge advantage is that if the target dired buffer is already opened, switching to it via ido or ibuffer is often faster than selecting the path.

Call dired-ranger-copy to add marked files (or the file under point if no files are marked) to the “clipboard”. With non-nil prefix argument, add the marked files to the current clipboard.

Past clipboards are stored in dired-ranger-copy-ring so you can repeat the past pastes.

Call dired-ranger-paste or dired-ranger-move to copy or move the files in the current clipboard to the current dired buffer. With raw prefix argument (usually C-u), the clipboard is not cleared, so you can repeat the copy operation in another dired buffer.

(use-package dired-ranger
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-hacks/")))
  :defer 110 ;; has to be after dired+ in able to overwrite its bindings below
  :config
  (define-key dired-mode-map (kbd "M-c") 'dired-ranger-copy)  ;; overwrites: diredp-capitalize-this-file
  (define-key dired-mode-map (kbd "M-v") 'dired-ranger-paste) ;; overwrites: scroll-down-command
  (define-key dired-mode-map (kbd "M-m") 'dired-ranger-move)  ;; overwrites: back-to-indentation
)

dired-isearch

Via EmacsWiki and download from http://www.emacswiki.org/emacs/download/dired-isearch.el

(use-package dired-isearch
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
  :defer 110
  :config
)

Not necessary any more. There is built-in functionality which I just have to re-map to C-s (because I don’t need reverse or RegEx search):

(define-key dired-mode-map (kbd "C-s") 'dired-isearch-filenames)

looking for: filetags, date2name, appendfilename

(setq my-filetags-file (my-binary-found "filetags"))
(when (and (not my-filetags-file) (my-system-type-is-gnu))
    (progn (message "using manual src path for \"filetags\"")
           (setq my-filetags-file (my-binary-found "/home/vk/src/filetags/filetags/__init__.py"))
    )
)

(setq my-date2name-file (my-binary-found "date2name"))
(when (and (not my-date2name-file) (my-system-type-is-gnu))
    (progn (message "using manual src path for \"date2name\"")
           (setq my-date2name-file (my-binary-found "/home/vk/src/date2name/date2name/__init__.py"))
    )
)

(setq my-appendfilename-file (my-binary-found "appendfilename"))
(when (and (not my-appendfilename-file) (my-system-type-is-gnu))
    (progn (message "using manual src path for \"appendfilename\"")
           (setq my-appendfilename-file (my-binary-found "/home/vk/src/appendfilename/appendfilename/__init__.py"))
    )
)

my-dired-filetags → M-t

(defun my-dired-filetags ()
  "Run \"filetags\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
    (when (string-equal system-name "GRZN17009")
      ;;works            (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe" "/K" "echo \"Hello\"")))
      ;;(message (concat "CALLING: c:/Users/karl.voit/bin/filetags.bat -sv " marked-files))
      (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe" "/C"
                                 "c:/Users/karl.voit/bin/filetags.bat -sv"
                                 (shell-quote-argument marked-files)))
        (set-process-query-on-exit-flag proc nil)))
      ;;(dired-do-shell-command "cmd.exe /K c:/Users/karl.voit/bin/filetags.bat *" nil marked-files)
      )

    (when (string-equal system-name "cosmo")
      (let ((proc (start-process "cmd" nil "cmd.exe" "/C" "start" "cmd.exe" "/C"
                                 "C:/Users/John/AppData/Roaming/filetags.bat -sv"
                                 (shell-quote-argument marked-files)))
        (set-process-query-on-exit-flag proc nil)))
      )

    (when (my-system-type-is-gnu)
      ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal")
      ;; --disable-server → provides a blocking terminal window (instead of a non-blocking one which swallows the revert-buffer afterward)
        (dired-do-shell-command (concat "xfce4-terminal --disable-server --geometry=100x20+330+5 --hide-menubar -x " my-filetags-file " --interactive *") nil marked-files)
    )

  (revert-buffer nil t t) ;; refresh listing of files
  )
)

(define-key dired-mode-map (kbd "M-t") 'my-dired-filetags)

my-dired-appendfilename → M-a

(defun my-dired-appendfilename ()
  "Run \"appendfilename\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
    (when (my-system-type-is-windows)
      (dired-do-shell-command "FIXXME xfce4-terminal --geometry=100x20+330+5 --hide-menubar -x /home/vk/bin/filetags --interactive *" nil marked-files)
      )
    (when (my-system-type-is-gnu)
      ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal")
      ;; --disable-server → provides a blocking terminal window (instead of a non-blocking one which swallows the revert-buffer afterward)
          (dired-do-shell-command (concat "xfce4-terminal --disable-server --geometry=90x5+330+5 --hide-menubar -x " my-appendfilename-file " *") nil marked-files)
      )
    )
  (revert-buffer nil t t)
  )

(define-key dired-mode-map (kbd "M-a") 'my-dired-appendfilename)

my-dired-filetags-filter → F1

(defun my-dired-filetags-filter ()
  "Run \"filetags --filter\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
    (when (my-system-type-is-windows)
      (dired-do-shell-command "FIXXME xfce4-terminal --geometry=100x20+330+5 --hide-menubar -x /home/vk/bin/filetags --interactive *" nil marked-files)
      )
    (when (my-system-type-is-gnu)
      ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal")
      (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --filter *") nil marked-files)
      )
    )
  )

my-dired-filetags-filter-recursive → F1

(defun my-dired-filetags-filter-recursive ()
  "Run \"filetags --filter --recursive\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
    (when (my-system-type-is-windows)
      (dired-do-shell-command "FIXXME xfce4-terminal --geometry=100x20+330+5 --hide-menubar -x /home/vk/bin/filetags --interactive *" nil marked-files)
      )
    (when (my-system-type-is-gnu)
      ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal")
      (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --filter --recursive *") nil marked-files)
      )
    )
  )

my-dired-tagtrees → F1

(defun my-dired-tagtrees ()
  "Run \"filetags --tagtrees\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
    (when (my-system-type-is-windows)
      (dired-do-shell-command "filetags --tagtrees --tagtrees-handle-no-tag no-tags" nil marked-files)
      )
    (when (my-system-type-is-gnu)
      ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal")
      (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --tagtrees --tagtrees-handle-no-tag no-tags *") nil marked-files)
      )
    )
  )

my-dired-tagtrees-recursive → F1

(defun my-dired-tagtrees-recursive ()
  "Run \"filetags --tagtrees --recursive\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
    (when (my-system-type-is-windows)
      (dired-do-shell-command "C:\\Python36\\Scripts\\filetags.exe --tagtrees --recursive --tagtrees-handle-no-tag no-tags *" nil marked-files)
      )
    (when (my-system-type-is-gnu)
      ;; FIXXME: maybe add check for binary: (when (my-eval-if-binary-or-warn "xfce4-terminal")
      (dired-do-shell-command (concat "xfce4-terminal --geometry=90x5+330+5 --hide-menubar -x " my-filetags-file " --tagtrees --recursive --tagtrees-handle-no-tag no-tags *") nil marked-files)
      )
    )
  )

my-dired-date2name → F1

(defun my-dired-date2name ()
  "Run \"time2name\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
      (dired-do-shell-command (concat my-date2name-file " *") nil marked-files)
    )
  (revert-buffer nil t t) ;; refresh listing of files
  )

my-dired-time2name → F1

(defun my-dired-time2name ()
  "Run \"date2name --withtime\" on current or marked files"
  (interactive)
  (let* ((marked-files (f-uniquify (dired-get-marked-files)))) ;; apply to single file or marked files
    (dired-do-shell-command (concat my-date2name-file " --withtime *") nil marked-files)
  )
  (revert-buffer nil t t) ;; refresh listing of files
  )

my-open-in-external-app → C-c C-o

from http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html

(defun my-dired-open-in-external-app ()
  "Open the current file or dired marked files in external app.
The app is chosen from your OS's preference.
URL `http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html'
Version 2016-10-15"
  (interactive)
  (let* (
         ($file-list
          (if (string-equal major-mode "dired-mode")
              (dired-get-marked-files)
            (list (buffer-file-name))))
         ($do-it-p (if (<= (length $file-list) 5)
                       t
                     (y-or-n-p "Open more than 5 files? "))))
    (when $do-it-p
      (cond
       ((string-equal system-type "windows-nt")
        (mapc
         (lambda ($fpath)
           (w32-shell-execute "open" (replace-regexp-in-string "/" "\\" $fpath t t))) $file-list))
       ((string-equal system-type "darwin")
        (mapc
         (lambda ($fpath)
           (shell-command
            (concat "open " (shell-quote-argument $fpath))))  $file-list))
       ((string-equal system-type "gnu/linux")
        (mapc
         (lambda ($fpath) (let ((process-connection-type nil))
                            (start-process "" nil "xdg-open" $fpath))) $file-list))))))
(define-key dired-mode-map (kbd "C-c C-o") 'my-dired-open-in-external-app)

Alternative: openwith from this GitHub page mentioned by Using Emacs 71 Openwith.

my-dired-open-in-file-manager → F1

This is xah-show-in-desktop() from http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html and adapted a bit:

  • file-truename() to translate relative paths to absolute
  • thunar as default manager on Linux
  • [ ] FIXXME: OS switching commands
(defun my-dired-open-in-file-manager ()
  "Show current file in desktop.
 (Mac Finder, Windows Explorer, Linux file manager)
 This command can be called when in a file or in `dired'.
URL `http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html'
Version 2018-01-13 adapted by Karl Voit 2018-07-01"
  (interactive)
  (let (($path (file-truename (if (buffer-file-name) (buffer-file-name) default-directory ))))
    (cond
     ((string-equal system-type "windows-nt")
      (w32-shell-execute "explore" (replace-regexp-in-string "/" "\\" $path t t)))
     ((string-equal system-type "darwin")
      (if (eq major-mode 'dired-mode)
          (let (($files (dired-get-marked-files )))
            (if (eq (length $files) 0)
                (shell-command
                 (concat "open " (shell-quote-argument default-directory)))
              (shell-command
               (concat "open -R " (shell-quote-argument (car (dired-get-marked-files )))))))
        (shell-command
         (concat "open -R " $path))))
     ((string-equal system-type "gnu/linux")
      (let (
            (process-connection-type nil)
            (openFileProgram (if (file-exists-p "/usr/bin/thunar")
                                 "/usr/bin/thunar"
                               "/usr/bin/xdg-open")))
        (start-process "" nil openFileProgram $path))
      ;; (shell-command "xdg-open .") ;; 2013-02-10 this sometimes froze emacs till the folder is closed. eg with nautilus
      ))))

my-dired-mark-images-and-thumbnail → F1

(defun my-dired-mark-images-and-thumbnail ()
  "Mark all image files in dired (png, PNG, jpg, JPG, jpeg, JPEG) and start image-dired+."
  (interactive)
  (dired-mark-extension '("png" "jpg" "PNG" "JPG" "jpeg" "JPEG" "tif" "tiff" "TIF" "TIFF" "gif" "GIF"))
  (image-dired-display-thumbs)
)

my-dired-copy-filename-as-absolute-link → F1

I often link files in Org mode documents with their full path such as

[[file:c:/Users/karl.voit/2del/2018-07-04T15.35.42 Outlook - changing recurring events deletes all exceptions -- screenshots.png]]

This would require

  1. select a file
  2. copy the absolute path name in dired via M-0 w
  3. switch to the Org buffer
  4. type
    [[file:
        
  5. yank the kill ring element containing the absolute path
  6. finish the link with ]]

Following function avoids human error and reduces this process to:

  1. select a file
  2. call the function below via my hydra
  3. switch to a Org buffer
  4. yank the working link from the kill ring
(defun my-dired-copy-filename-as-absolute-link (&optional arg)
  "Copy current file name with absolute path as [[file:<absolute path>]] link.
   If the universal argument is given, the path is omitted in the link description."
  (interactive "P")
  (dired-copy-filename-as-kill 0) ;; current absolute path to kill ring
  (let* ((path (current-kill 0))) ;; get topmost kill ring element
  (if (equal arg '(4))
    ;; universal argument is set:
    (kill-new (concat "[[file:" path "][" (helm-basename path) "]]")) ;; write back new/modified kill ring element
    ;; universal argument is not set:
    (kill-new (concat "[[file:" path "]]")) ;; write back new/modified kill ring element
  )
  )
)

my-dired-copy-filename-as-tsfile-link → F1

Same explanation as my-dired-copy-filename-as-absolute-link holds but with the result being a tsfile: link I use to link to Memacs-indexed files (see Org Mode customized links):

(defun my-dired-copy-filename-as-tsfile-link ()
  "Copy current file name with its basename as [[tsfile:<basename>]] custom org-mode link."
  (interactive)
  (dired-copy-filename-as-kill) ;; current file name to kill ring
  (let* ((filename (current-kill 0))) ;; get topmost kill ring element
    (kill-new (concat "[[tsfile:" filename "]]")) ;; write back new/modified kill ring element
  )
)

my-dired-open-here-in-tmux-shell

Sometimes, I need the current directory showed in my tmux session running in background. This is how it’s done.

  • [ ] FIXXME: find a working solution for Windows 10
(defun my-dired-open-here-in-tmux-shell()
  (interactive)
  (cond
       ((my-system-type-is-windows)
        (message (concat "NOT Opening current dir in Windows/Cygwin tmux (NOT IMPLEMENTED AND TESTED YET): " dired-directory))
        ;; see id:2018-09-02-open-dir-in-tmux for details on the development and Windows issues
        ;;(mapc (lambda (fPath) (w32-shell-execute "open" (replace-regexp-in-string "/" "\\" fPath t t)) ) myFileList)
        )
       ((string-equal system-type "darwin")
        (message (concat "NOT Opening current dir in macOS tmux (NOT IMPLEMENTED AND TESTED YET): " dired-directory))
        )
       ((my-system-type-is-gnu)
        (message (concat "Opening current dir in linux tmux: " dired-directory))
        ;; OLD: (shell-command (concat "tmux new-window 'cd \"" dired-directory "\"; pwd; zsh -i'"))
        (dired-smart-shell-command "xfce4-terminal --execute tmux")
        )
        )
)

orly

2020-04-13setup for testing

This package got recommended for a specific issue I faced using interactive Python scripts.

(use-package orly
  ;;:if (my-system-type-is-gnu)
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/orly/")))
  ;;:defer 110
  :after org
)

filetags.el → F1

https://github.com/beutelma/filetags.el provides filetags-dired-update-tags() which is an Elisp-native re-implementation of my filetags:

(use-package filetags
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/filetags.el/")))
  :config
  (setq filetags-enforce-controlled-vocabulary nil) ;; let me invent new tags on the fly (might not be a good idea anyway!)
  (setq filetags-load-controlled-vocabulary-from-file t) ;; read CV from .filetags files within same or upper directories
  ;;ignored;; (setq filetags-controlled-vocabulary '("confidential" "restricted" "public" "internal" "internaluse"
  ;;ignored;;  "license" "demos" "proposals" "flipcharts" "data" "draft" "final" "screenshots" "travel"
  ;;ignored;;  "templates" "contracts" "processes"))
)

date2name → F1

https://github.com/beutelma/date2name.el provides date2name-dired-add-date-to-name() which is an Elisp-native re-implementation of my date2name:

(use-package date2name
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/date2name.el/")))
  :config
  (setq date2name-enable-smart-separation-character-chooser t)

  ;; 2018-07-21: https://github.com/DerBeutlin/date2name.el/issues/1#issuecomment-406787333
  (defun file-attribute-modification-time (attributes)
    "extracts the modification time from ATTRIBUTES"
    (nth 5 attributes))

)
  • [ ] FIXXME: replace date2name.py with it if it is well tested
  • [ ] FIXXME: map to a direct key
  • [ ] FIXXME: add to cheatsheet (hydra): ask for day when used with universal prefix
  • [ ] FIXXME: do for time2name as well

dired-show-readme

2020-04-11installed for testing purposes
2020-04-11disabled because it did not work on my README.org files

From this reddit thread I found dired-show-readme which displays README files of various formats (using pandoc conversion) within the directory they are located.

Although I don’t need this particular function, I set it up to test it.

(use-package dired-show-readme
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dired-show-readme/")))
  ;:defer 110
  ;:after dired
  :config
  (setq dired-show-readme-position "bottom")
  ;; (setq dired-show-readme-pandoc-executable "/usr/bin/pandoc");; on sting, this is the default
  (add-hook 'dired-mode-hook 'dired-show-readme-mode)
)

Email

isync + notmuch

2021-02-13disabled since I can’t use business email with Emacs

This is my email setup for notmuch I use together with isync/mbsync/

(use-package notmuch
   :if (my-system-type-is-gnu)
   :config

   (load-library "smtpmail")

   (setq smtpmail-default-smtp-server my-business-mail-server
         smtpmail-local-domain my-business-mail-server)

   (setq send-mail-function    'smtpmail-send-it
         smtpmail-smtp-server  my-business-mail-server
         smtpmail-stream-type  'starttls
         smtpmail-smtp-service 587
         mail-host-address my-business-mail-host-address)

   ;; Somehow, this variable gets overwritten by something to 'message-send-mail-with-outlook
   ;; and therefore it's been set in "custom variables" as well.
   (setq message-send-mail-function 'message-smtpmail-send-it)

   (setq notmuch-message-headers '("Subject" "To" "Cc" "Date" "Reply-To"))
   (setq notmuch-mua-cite-function 'message-cite-original-without-signature)
   (setq notmuch-saved-searches
     '((:name "inbox" :query "tag:inbox" :key "i")
       (:name "unread" :query "tag:unread" :key "u")
       (:name "flagged" :query "tag:flagged" :key "f")
       (:name "sent" :query "tag:sent" :key "t")
       (:name "drafts" :query "tag:draft" :key "d")
       (:name "all mail" :query "*" :key "a")
       (:name "Sent" :query "folder:archive")))
   (setq message-default-headers "Reply-to: \nCC: \nBCC: \n")
   (setq notmuch-fcc-dirs "archive")
   ;;(when (my-system-is-rise)
   ;;   (setq notmuch-command "notmuch.cmd")
   ;;)

   (add-hook 'notmuch-message-mode-hook #'footnote-mode)
   (add-hook 'notmuch-message-mode-hook #'auto-dictionary-mode)
   (add-hook 'notmuch-message-mode-hook #'flyspell-mode)

   ;; ignore email header for flyspell (and thus dictionary mode):
   ;; https://www-sop.inria.fr/members/Manuel.Serrano/flyspell/flyspell-1.7q.el
   ;; as of 2019-12-21: doesn't work as it uses in German emails the English one :-(
   (add-hook 'notmuch-message-mode-hook
             '(lambda () (setq flyspell-generic-check-word-p
                               'mail-mode-flyspell-verify)))

   (defun my-notmuch-sync-and-update-index-and-buffer ()
     "Update the index after sync."
     (interactive)
     (call-process (concat my-user-emacs-directory "bin/mbsync_notmuch.sh") nil nil t "");; necessary to untag my own emails with -new
     (notmuch-poll)
     (notmuch-refresh-this-buffer))

;   (when (not (my-system-is-rise))
     (define-key notmuch-hello-mode-map "g" 'my-notmuch-sync-and-update-index-and-buffer)
;   )

)

switch to open notmuch biffer or open new one:

(defun my-notmuch (&optional arg)
  "Opens the already opened notmuch buffer or opens new one instead."
  (interactive "P")
  (when (my-system-type-is-gnu)
      (my-notmuch-sync-and-update-index-and-buffer)
      (if (my-buffer-exists "*notmuch-hello*")
          (switch-to-buffer "*notmuch-hello*")
        (notmuch)
      )
  )
)

;; (bind-key "n" 'my-notmuch my-map) → within "Key bindings" heading since binding overwrites a standard Org mode binding

from: https://gist.github.com/fedxa/fac592424473f1b70ea489cc64e08911

Provides Org mode links to notmuch emails: copy with C-c l (org-notmuch-store-link) + paste with C-c C-l

(use-package org-notmuch
   :if (my-system-type-is-gnu)
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
)

Adding a key mapping for “d” to add “deleted” tag and remove “inbox” and “unread”: Source

(define-key notmuch-search-mode-map "d"
  (lambda ()
    "mark message as deleted"
    (interactive)
    (notmuch-show-tag (list "+deleted" "-inbox" "-unread"))))

(define-key notmuch-show-mode-map "d"
  (lambda ()
    "mark message as deleted"
    (interactive)
    (notmuch-show-tag (list "+deleted" "-inbox" "-unread"))))

(define-key notmuch-tree-mode-map "d"
  (lambda ()
    "mark message as deleted"
    (interactive)
    (notmuch-show-tag (list "+deleted" "-inbox" "-unread"))))

Open the current email in Thunderbird:

(define-key notmuch-search-mode-map "T"
  (lambda ()
    "open in Thunderbird"
    (interactive)
    ;; FIXXME: I can't find the appropriate method to get current message ID in search results:
    (my-open-message-id-in-thunderbird (notmuch-show-get-message-ids-for-open-messages t))
))

(define-key notmuch-show-mode-map "T"
  (lambda ()
    "open in Thunderbird"
    (interactive)
    (my-open-message-id-in-thunderbird (notmuch-show-get-message-id t))
))

As of 2021-01-07, I stop using notmuch (again) because of:

  • Thunderbird is good enough for now
  • I still need Thunderbird in parallel → I prefer to avoid the switching back and forth effort + additional Maildir data for notmuch
  • no appointment inviation handling on receiving
  • not being able to create standard appointment invitations
  • no HTML or rendering HTML content takes some time
  • notmuch does not offer an out-of-the-box possibility to delete emails: https://www.reddit.com/r/emacs/comments/6wqfp3/notmuch_delete_mail/

FIXXME: https://www.reddit.com/r/emacs/comments/kqixcg/notmuch_how_to_get_messageid_open_current_email/

In search you are normally looking at threads, not individual messages—that’s why you have notmuch-search-find-thread-id. But if you write a function that picks an appropriate ID from the result of notmuch-search-find-stable-query that should be the easiest way to go.

FIXXME: https://www.reddit.com/r/emacs/comments/kqixcg/notmuch_how_to_get_messageid_open_current_email/gi64fu2/?context=3

As /u/oritron explained, in default search view, you get results not in form of message ids, but in form on thread ids, even if there is a single message in that thread.

However, if you use notmuch-tree (see M-x notmuch-tree), you will get message ids, because threads will be represented as a tree. To access message id for highlighted/selected mail, see notmuch-show-stash-message-id function.

For or certain (Confluence notification) emails, rendering the HTML content takes 20-30 seconds, blocking my Emacs instance which is very upsetting at last to me

My approach is to use lynx for rendering html, because it is really fast. If I need to look it further, I open that message part in browser (go with cursor to text/html box, hit . o and notmuch will ask you for viewer. Enter firefox or chromium… You can’t beat html rendering with the real browser :D

To set lynx as default html renderer use this:

(setq mm-text-html-renderer ‘lynx) or check other options.

Thunderbird

2021-02-26With an unintended upgrade from Thunderbird 68 to 78, the original thunderlink is broken.
2021-02-28Setup of cb_thunderlink as a TB 78.x replacement
2021-05-26Moved from Thunderbird to GNOME Evolution, disabling this

I got this workflow from https://vxlabs.com/2019/04/20/link-thunderbird-emails-from-emacs-orgmode/

Internal notes: id:2020-01-09-link-emails-from-to-Thunderbird-Org

Helper function to open any given message-id in Thunderbird:

;; modify this for your system
(setq thunderbird-program "/usr/bin/thunderbird")

(defun my-open-message-id-in-thunderbird (message-id)
"open an email with a given message-ID in Thunderbird"
(interactive)
(start-process
 (concat "thunderlink: " message-id)
 nil
 thunderbird-program
 "-thunderlink"
 (concat "thunderlink://messageid=" message-id)
 )
)
;; modify this for your system
(setq thunderlink-program "/home/vk/cb_thunderlink/cb_thunderlink")

(defun my-open-message-id-in-thunderbird (message-id)
"open an email with a given message-ID in Thunderbird"
(interactive)
(start-process
 (concat "thunderlink: " message-id)
 nil
 thunderlink-program
 (concat "thunderlink://messageid=" message-id)
 )
)
;; with org-mac-link message:// links are handed over to the macOS system,
;; which has built-in handling. On Windows and Linux, we can use thunderlink!
(when (not (string-equal system-type "darwin"))

  (defun org-message-thunderlink-open (slash-message-id)
    "Handler for org-link-set-parameters that converts a standard message:// link into
   a thunderlink and then invokes thunderbird."
    ;; remove any / at the start of slash-message-id to create real message-id
    (let ((message-id
           (replace-regexp-in-string (rx bos (* ":"))
                                     ""
                                     slash-message-id)))
      (my-open-message-id-in-thunderbird message-id)
  ))

  ;; on message://aoeu link, this will call handler with //aoeu
  (org-link-set-parameters "messageid" :follow #'org-message-thunderlink-open)
  )

Note that the link colors are set via my-set-linkcolors.

  • test link for testing color: 2020-07-27T15:57:45.000Z First Last: Subject

Installation:

  1. install “Thunderlink” add-on in Thunderbird
  2. close Thunderbird
  3. manually add the snippet below to the prefs.js of the Thunderbird profile
  4. activate the Elisp code above within Emacs
  5. start Thunderbird
user_pref("extensions.thunderlink.custom-tl-string-1-title", "Org mode message-ID");
user_pref("extensions.thunderlink.custom-tl-string-1", "[[messageid:<messageid>][<time> <sender>: <subject>]]");
user_pref("extensions.thunderlink.custom-tl-string-1-selection-delimiter", " / ");
user_pref("extensions.thunderlink.custom-tl-string-1-clipboard-checkbox", true);
user_pref("extensions.thunderlink.custom-tl-string-1-tagcheckbox", false);
user_pref("extensions.thunderlink.custom-tl-string-1-tag", 1);
user_pref("extensions.thunderlink.custom-tl-string-1-appendtofile-checkbox", false);
user_pref("extensions.thunderlink.custom-tl-string-1-appendtofile-path", "");

Possible values for the thunderlink template: https://github.com/mikehardy/thunderlink/blob/master/chrome/thunderlink/content/preferences.xul#L108

<thunderlink> <messageid> <subject> <filteredSubject> <sender> <tbexe> <time>

My feature request for more format options: https://github.com/mikehardy/thunderlink/issues/49

Workflow to use it:

  1. Click on the message with the secondary mouse button (context menu)
  2. Select: “Thunderlink …” > “Org mode message-ID”
    • alternatively: C-M-1 (1 reflecting the format position in the Thunderlink menu)
  3. Switch to Emacs and yank from the clipboard

You should then get something similar to:

[[messageid:1578475923.390512.037689999@example.com][[1/9/2020 - 11:30:41 First Last <name@example.com>: Things I wanted to say to you]]

When C-c C-o onto it, Thunderbird should pop up showing the email with the corresponding message ID.

GNOME Evolution

2021-05-26migrated from Thunderbird to GNOME Evolution, re-creating the workflow here

Helper function to open any given message-id in Evolution:

;; modify this for your system
(defun my-open-message-id-in-evolution (message-id)
"open an email with a given message-ID in Evolution"
(interactive)
(start-process
 (concat "mid: " message-id)
 nil
 "/usr/bin/flatpak"
 "run" "org.gnome.Evolution" (concat "mid:<" message-id ">")
 )
)

(org-link-set-parameters "messageid" :follow #'my-open-message-id-in-evolution)
  (defun my-convert-mail-header-to-org-link ()
  "Assumes an email header in the killring, parses it and returns an org mode link for it."
  (interactive)
  (with-temp-buffer
    (save-match-data

    (yank) ;; yank from clipboard
    (goto-char (point-min)) ;; start from top
    (re-search-forward "^Message-Id:.+<\\(.+\\)>[ ]*$" nil nil 1)
    (setq messageid (match-string 1))

    (goto-char (point-min))
    (re-search-forward "^From:[	 ]+\\(.+?\\)[ ]*$" nil nil 1)
    (setq from (string-replace "\"" "" (match-string 1)))

    (goto-char (point-min))
    (re-search-forward "^Subject:[	 ]+\\(.+?\\)[ ]*$" nil nil 1)
    (setq subject (match-string 1))

    (goto-char (point-min))
    (re-search-forward "^Date:[	 ]+\\(.+?\\)[ ]*$" nil nil 1)
    (setq rawdate (match-string 1))
    (setq date
    (let ((time (date-to-time rawdate)))
      (set-time-zone-rule t) ;; Use Universal time.
      (prog1 (format-time-string "%Y-%m-%d %H:%M" time)
        (set-time-zone-rule nil))))

    ;;(message (concat "MID: " messageid " F:" from " S:" subject "RD:" rawdate " D:" date))
    ))
    (insert (concat "[[messageid:" messageid "][" date " " from ": " subject "]]"))
)

(bind-key "e" #'my-convert-mail-header-to-org-link my-map)

Note that the link colors are set via my-set-linkcolors.

  • test link for testing color: 2020-07-27T15:57:45.000Z First Last: Subject

Installation:

  1. install GNOME Evolution in version 3.39+ because Evolution added the command line switch with this version.
    • flatpak install --user --from https://dl.flathub.org/repo/appstream/org.gnome.Evolution.flatpakref
  2. if you need the flatpak version (because your distro has only older versions), you should be finished
  3. if you did not install Evolution via flatpak, adapt the code above
  4. Evolution: Account preferences → Receiving Options → [X] Synchronize remote mail locally in all folders

Workflow to use it:

  1. FIXXME: find a workflow to generate Message-ID links in Evolution

You should then get something similar to:

[[messageid:1578475923.390512.037689999@example.com][[1/9/2020 - 11:30:41 First Last <name@example.com>: Things I wanted to say to you]]

When C-c C-o onto it, Evolution should pop up showing the email with the corresponding message ID.

LaTeX

LaTeX is a powerful text setting system I use for creating letters, books, presentations, and so forth.

AucTeX is an awesome handy mode for working with TeX code.

BEGIN of LaTeX settings (only if “pdflatex” is found on the system):

(when (my-eval-if-binary-or-warn "pdflatex")

General LaTeX settings:

(autoload 'tex-site "tex-site.el")  ;; acticate AucTeX and set general preferences

(setq TeX-PDF-mode t)  ;; compile to PDF using pdflatex (instead to DVI)

(add-hook 'LaTeX-mode-hook 'turn-on-auto-fill) ;; word-wrap in TeX files

(setq TeX-auto-save nil);; avoid auto directories; read https://emacs.stackexchange.com/questions/32760/how-to-get-rid-of-the-auto-folder-with-el-files
(setq TeX-parse-self t)

;(setq-default TeX-master nil);; 2015-03-22 deactivated because it doesn't seem to have any influence: id:2013-12-31-org-master-file
(make-variable-buffer-local 'TeX-master) ;; I think this is need because the variable is not buffer local until Auctex is active

Synctex is a nice add-on that synchronizes the editing tool (Emacs/AucTeX) with a PDF viewing tool (e.g., Okular): http://www.bleedingmind.com/index.php/2010/06/17/synctex-on-linux-and-mac-os-x-with-emacs/

(when (my-eval-if-binary-or-warn "synctex")
  (add-hook 'LaTeX-mode-hook 'TeX-source-correlate-mode)
  (setq TeX-source-correlate-method 'synctex)
)

Define system-specific PDF viewers and further Synctex settings:

(defun okular-make-url () (concat
                     "file://"
                     (expand-file-name (funcall file (TeX-output-extension) t)
                                       (file-name-directory (TeX-master-file)))
                     "#src:"
                     (TeX-current-line)
                     (TeX-current-file-name-master-relative))
       "./"
       (TeX-current-file-name-master-relative)
       )

(defun skim-make-url () (
                   concat
                   (TeX-current-line)
                   " "
                   (expand-file-name (funcall file (TeX-output-extension) t)
                                     (file-name-directory (TeX-master-file)))
                   " "
                   (buffer-file-name))
       )

(setq TeX-view-program-list '(
                        ("Okular" "okular --unique %u")
                        ("Skim" "/Applications/Skim.app/Contents/SharedSupport/displayline %q")
                        )
      )

(when (my-system-type-is-gnu)
  (setq TeX-view-program-selection '((output-pdf "Okular") (output-dvi "Okular")))
  (eval-after-load "tex"
    '(add-to-list 'TeX-expand-list '("%u" okular-make-url))
    )
  )

(when (my-system-type-is-darwin)
  (setq TeX-view-program-selection '((output-pdf "Skim")))
  (eval-after-load "tex"
    '(add-to-list 'TeX-expand-list '("%q" skim-make-url))
    )
  )

https://tex.stackexchange.com/questions/60170/how-to-set-up-okular-for-forward-backward-search-with-tex-live-2011-not-trivia

(add-hook ‘LaTeX-mode-hook
(lambda ()
  (add-to-list ‘TeX-expand-list
  ‘(“%u” okular-make-url))))

CDLaTeX is a minor mode for Emacs supporting fast insertion of environment templates and math stuff in LaTeX.

I tried it once but do not use it any more.

(when (or (my-system-type-is-gnu) (my-system-is-powerplantlinux))
  (my-load-local-el "contrib/cdlatex.el")
  )

RefTeX is the package for LaTeX that does manage references.

http://www.tug.org/pipermail/macostex-archives/2005-November/018997.html

  • reftex
  • TeX-fold-mode
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)   ; with AUCTeX LaTeX mode
(add-hook 'LaTeX-mode-hook '(lambda () (TeX-fold-mode 1)))

BibLaTeX provides bibliographic facilities. Biber is a moder implementation of it. I prefer it for generating references and its indexes.

http://www.mail-archive.com/auctex@gnu.org/msg04137.html

(eval-after-load "tex"
  '(add-to-list 'TeX-command-list
          '("Biber" "biber %s" TeX-run-Biber nil t :help "Run Biber") t))

(defun TeX-run-Biber (name command file)
  "Create a process for NAME using COMMAND to format FILE with Biber."
  (let ((process (TeX-run-command name command file)))
    (setq TeX-sentinel-function 'TeX-Biber-sentinel)
    (if TeX-process-asynchronous
        process
      (TeX-synchronous-sentinel name file process))))

(defun TeX-Biber-sentinel (process name)
  "Cleanup TeX output buffer after running Biber."
  (goto-char (point-max))
  (cond
   ;; Check whether Biber reports any warnings or errors.
   ((re-search-backward (concat
                   "^(There \\(?:was\\|were\\) \\([0-9]+\\) "
                   "\\(warnings?\\|error messages?\\))") nil t)
    ;; Tell the user their number so that she sees whether the
    ;; situation is getting better or worse.
    (message (concat "Biber finished with %s %s. "
               "Type `%s' to display output.")
             (match-string 1) (match-string 2)
             (substitute-command-keys
        "\\\\[TeX-recenter-output-buffer]")))
   (t
    (message (concat "Biber finished successfully. "
               "Run LaTeX again to get citations right."))))
  (setq TeX-command-next TeX-command-default))
(setq reftex-bibpath-environment-variables
      '("~/archive/library/"))
(defun guess-TeX-master (filename)
    "Guess the master file for FILENAME from currently open files according to their extension."
    (let ((candidate nil)
          (filename (file-name-nondirectory filename)))
      (save-excursion
        (dolist (buffer (buffer-list))
          (with-current-buffer buffer
            (let ((name (buffer-name))
                  (file buffer-file-name))
              ;(if (and file (string-match "\\.\(org\|tex\)$" file))
              (if (and file (string-match "\\.org$" file))
                  (progn
                    (goto-char (point-min))
                    (if (re-search-forward (concat "\\\\input{" filename "}") nil t)
                        (setq candidate file))
                    (if (re-search-forward (concat "\\\\include{" (file-name-sans-extension filename) "}") nil t)
                        (setq candidate file))))))))
      (if candidate
          (message "TeX master document: %s" (file-name-nondirectory candidate)))
      candidate))

;; ONLY for special file modes with a recognized extension!
;; Causes Lisp error (that's a afact) when used with buffers like *scratch* (that's my guess)
;;(setq TeX-master (guess-TeX-master (buffer-file-name)))

END of LaTeX settings

)

GnuPlot

«Gnuplot is a portable command-line driven graphing utility for Linux, OS/2, MS Windows, OSX, VMS, and many other platforms.»

Also very handy when visualizing table data within Org-mode! (see Org-mode/babel configuration)

Example: place the cursor within the table and evaluate org-plot/gnuplot or use the keyboard shortcut C-c " g

WhenHow many
[2016-11-17 Thu]3
[2016-11-23 Wed]4
[2016-12-10 Sat]1
;; gnuplot
(when (my-eval-if-binary-or-warn "gnuplot")
  (use-package gnuplot
    :ensure t
    :defer 110
    :if (my-system-type-is-gnu)
  )
)

Org mode

Org-mode is my digital life. I do almost anything within Org-mode: http://karl-voit.at/tags/emacs/

I am doing Personal Information Management (PIM) for decades, tried many different methods and tools. With Org-mode my quest for the best PIM-tool out there finally came to an end. It’s an endless pile of Lego-bricks from where I can draw some bricks and assemble it to meet my requirements. Therefore, Org-mode is something different for everybody. It depends, what Lego bricks you took and how you combined them. Org-mode scales well from a simple outliner or todo-list up to something very, very big.

Almost half of my Emacs configuration deals with Org-mode. Fasten your seat belt and dive into my rabbit hole of Org …

Profiling Org-mode config loading time:

(defvar my-org-config-start-time (current-time) "Time when my org-mode config was started")
(message "★→ Org-mode")
(my-log-hostspecific "org-version" org-version)

Load Org and misc contrib packages

Since a couple of major releases GNU/Emacs comes with an Org-mode version built in. However, I do prefer the “maint” branch of the Org-mode Git repository instead. See also Installation - The Org Manual.

Note that the Org-mode paths to my manually installed Org-mode are set within init.el already.

assign file extensions to Org-mode:

(add-to-list 'auto-mode-alist '("\\.\\(org\\|org_archive\\|txt\\)$" . org-mode))

2014-10-29 test

(setq org-babel-safe-header-args nil)

Loading contributed packages:

(use-package org-checklist
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)

(use-package org-expiry
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)

;; 2021-11-23: to avoid "org-timestamp-change: Symbol’s function definition is void: org-clock-update-time-maybe"
(use-package org-clock
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)

(use-package org-attach
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)

(use-package org-element
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)

(use-package org-mobile
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)

;;disabled 2019-06-26;; (use-package ob-restclient
;;disabled 2019-06-26;;   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/ob-restclient.el/")))
;;disabled 2019-06-26;; )

  (when (my-system-is-rise)
     (my-load-local-el "contrib/org-contrib/lisp/ox-confluence.el")

     ;; https://www.reddit.com/r/emacs/comments/fk5z1b/how_to_remove_foo_barfoo_bar_links_via/fkrbc0e/
     ;; Do not handle radio links (and generate broken page links):
     (defun export-radio-links-as-plain-text (link desc info)
       (when (string= "radio" (org-element-property :type link))
         desc))

     (advice-add #'org-confluence-link :before-until
                 #'export-radio-links-as-plain-text)

  )
  ;;disabled;; (my-load-local-el "contrib/org-contrib/lisp/ox-freemind.el")
  (autoload 'org-checklist "org-checklist.el")

  ;; http://repo.or.cz/w/org-mode.git?a=blob_plain;f=contrib/lisp/org-expiry.el;hb=HEAD
  ;; Expiry dates handling
  (autoload 'org-expiry "org-expiry.el")

  ;; managing bookmarks with Org-mode
  ;; http://orgmode.org/worg/org-contrib/org-protocol.html
  (autoload 'org-protocol "org-protocol")

Enable misc org modules:

(setq org-modules (quote
                   (org-crypt
                    org-id
                    org-info
                    org-habit
                    org-inlinetask
                    org-protocol
                    )
                   )
      )

2019-12-09: “Problems while trying to load feature” and therefore removed from the list above:

  • org-mew
  • org-vm
  • org-wl

2019-12-09: I’ve got no idea why they are in this list and therefore removed:

  • org-bbdb
  • org-gnus
  • org-bibtex
  • org-irc
  • org-mhe
  • org-rmail
  • org-w3m

org-favtable: I was not able to find the advantage of favtables in comparison to search or id-links:

(require 'org-favtable)
(setq org-favtable-id "my-favtable")
(global-set-key (kbd "C-+") 'org-favtable)

Dependencies between todos

2010?initial setup of org-depend
2019-11-13temporary testing phase of org-edna instead of org-depend
2020-01issue with org-depend and batch-generation of ICS export of agenda
2020-05-13re-enabling after org upgrade: test again
2020-05-18disabled again: Variable binding depth exceeds max-specpdl-size persists
2020-07-09enabled org-edna for testing

One of my initial reasons to try Org mode was the ability to define dependencies between tasks.

This article also shows some handy functions related to this topic.

Please do read this page with a very interesting discussion by u/TeMPOraL\_PL on org-edna and task dependency with visualizations and a BLOCKER status.

org-depend

The default method is using org-depend. It has a very simple syntax based on the :TRIGGER: and :BLOCKER: properties.

(use-package org-depend
;  :if (not noninteractive)  ;; I do have issues with org-depend
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)

org-edna

2019-11-13I’m testing a fork: https://github.com/akirak/org-edna via reddit
2020-09-10This fork is discontinued → switched to original org-edna v1.1.2 with issues
2020-10-01I migrated all my Org files from org-depend to org-edna using this

Enable only when org-depend is disabled because both use same properties and report format errors when other format is detected.

(use-package org-edna
  :config
  (require 'org-edna)
  (org-edna-load)
)

org-edna has a syntax that is more complex when compared to org-depend. However, org-edna also features much more possibilities. My main driver to switch from org=depend to org-edna are relative SCHEDULED dates. This way, a follow-up task could be scheduled for, e.g., three days after the previous task was finished, whenever that happens.

The more complex syntax does come with no manual effort since I’d like to define dependencies via Elisp functions instead of manually typing :TRIGGER: properties which I’ve done so far. For that purpose, org-linker-edna is a very nice help.

Internal project link: id:2019-11-14-Org-Project-Management-Workflow

General Org-mode settings

http://www.reddit.com/r/emacs/comments/2m4b7j/help_setting_orgmode_as_the_default_major_mode/ - «This will make it that any file without an auto-mode alist entry gets associated with org-mode by default.»

(add-to-list 'auto-mode-alist '("'" . org-mode) t)

Might cause performance issues; http://orgmode.org/manual/Clean-view.html

(setq org-startup-indented t)

For a more fine-grained control on expanded headings when visiting a Org file, look at org-auto-expand.

(setq org-enforce-todo-dependencies t)
(setq org-insert-heading-respect-content nil)
(setq org-reverse-note-order nil)
(setq org-show-following-heading t)
(setq org-show-hierarchy-above t)
(setq org-show-siblings nil)
(setq org-deadline-warning-days 7)
(setq org-blank-before-new-entry (quote ((heading . t)
                                         (plain-list-item . nil))))
  • http://orgmode.org/org.html - show blocked tasks in agenda in gray color
  • 2020-07-07: I switched to show any scheduled task, independent of blocking. Because:
    1. When I forget to schedule an unresolved sub-task, the parent task which is scheduled gets hidden. → Don’t want that.
    2. Parent tasks that do contain tasks beneath should be marked as projects and should be finished with its last task that closes the project.
    3. I plan to switch from org-depend to org-edna and a set of yet to be written functions to make planning easier:
      • Define dependencies via helm (or simple: add next task below this one)
      • Use of relative SCHEDULED date-stamps: e.g., when X is DONE, mark X+1 as TODO and add a relative SCHEDULED for +1d.
;;disabled;(setq org-agenda-dim-blocked-tasks t)
;;disabled 2020-07-07;; (setq org-agenda-dim-blocked-tasks 'invisible)
(setq org-agenda-dim-blocked-tasks nil);; show blocked tasks

Logging into drawers: (also do read this blog article)

(setq org-log-done (quote time))
(setq org-log-into-drawer t)

;; record when the deadline or scheduled date of a tasks is modified
;;(setq org-log-redeadline (quote note));; performance risk due to long LOG drawers!
(setq org-log-redeadline nil)
;;(setq org-log-reschedule (quote time));; performance risk due to long LOG drawers!

(setq org-log-reschedule nil)
(setq org-return-follows-link t)
(setq org-remove-highlights-with-change nil)
(setq org-read-date-prefer-future nil)
(setq org-list-demote-modify-bullet (quote (("+" . "-")
                                            ("*" . "-")
                                            ("1." . "-")
                                            ("1)" . "-"))))
(setq split-width-threshold 9999);; Minimum width for splitting windows sensibly.

(setq require-final-newline nil)
(setq org-adapt-indentation nil);; do not indent drawers/body according to heading level

Performance implications! See reddit comment for details:

(setq global-auto-revert-mode t)

Default state for repeating/recurring events

(setq org-todo-repeat-to-state "NEXT")

Smart navigation: begin/end of line is different for headings, list items, …

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

Smart yanking: https://www.gnu.org/software/emacs/manual/html_node/org/Structure-editing.html

(setq org-yank-adjusted-subtrees t)
  • until 2016-11-10, the defaults were OK to me
    • with update to Org 9, jumping from agenda to hidden heading reveales only heading but not ancestors as before
(setq org-show-context-detail
      '((agenda . lineage) ;; instead of "local"
        (bookmark-jump . lineage)
        (isearch . lineage)
        (default . ancestors))
      )

Set the timestamps of expiry.el to inactive ones: http://comments.gmane.org/gmane.emacs.orgmode/20934

(setq org-expiry-inactive-timestamps t)

Prevent accidental deleting of hole subtrees or similar

(setq org-catch-invisible-edits "smart")

Use IDO for target completion:

(setq org-completion-use-ido t)

Disable property inheritance (in order to seed up)

(setq org-use-property-inheritance nil)

https://www.gnu.org/software/emacs/manual/html_node/org/Matching-tags-and-properties.html

(setq org-tags-match-list-sublevels nil)

2018-04-08: I now keep org-tags-match-list-sublevels to its default value (t) because I could not generate sparse trees with all unscheduled open tasks and setting this to nil (can’t remember why I did it in the first place) was the reason.

This variable is semi-obsolete and probably should always be true. It is better to limit inheritance to certain tags using the variables ‘org-use-tag-inheritance’ and ‘org-tags-exclude-from-inheritance’.

Prevent auto-filling for source code:

;(setq org-src-prevent-auto-filling t)

From: Release Notes v8.1: http://orgmode.org/worg/agenda-optimization.html

(setq org-agenda-ignore-drawer-properties '(effort appt stats));; agenda performance

Automatically write CREATED properties in the PROPERTIES drawer:

(org-expiry-insinuate)
;; not checked yet: (setq org-expiry-handler-function 'org-expiry-archive-subtree)

Checking org-mode syntax:

(require 'org-lint)

Open corresponding .org_archive file with ff-find-other-file

https://twitter.com/_wilfredh/status/708046038200950787 « M-x describe-function shows the docstring, which mentions ff-other-file-alist.»

;;
(defvar my-cpp-other-file-alist
'(("\\.org\\'" (".org_archive"))
  ;;("\\.ipp\\'" (".hpp" ".cpp"))
  ;;("\\.hpp\\'" (".ipp" ".cpp"))
  ;;("\\.cxx\\'" (".hxx" ".ixx"))
  ;;("\\.ixx\\'" (".cxx" ".hxx"))
  ;;("\\.hxx\\'" (".ixx" ".cxx"))
  ;;("\\.c\\'" (".h"))
  ;;("\\.h\\'" (".c"))
  ))
(setq-default ff-other-file-alist 'my-cpp-other-file-alist)

Yasnippet settings: http://yasnippet.googlecode.com/svn/trunk/doc/index.html

;;disabled;(my-load-local-el "contrib/yasnippet/yasnippet.el")
(add-hook 'org-mode-hook 'yas-minor-mode)
(setq yas-indent-line 'fixed) ;; fixes Org-mode issue with yasnippets: https://github.com/capitaomorte/yasnippet/issues/362

org-bullets on Windows: workaround that significantly improves speed and also from org-superstar-mode readme:

(when (my-system-type-is-windows)
  (setq inhibit-compacting-font-caches t)
)

Inheritance of checkbox toggling: should parent checkboxes be checked when all children are checked as well?

  • Non-nil means checkbox statistics counts only the state of direct children.
  • When nil, all boxes below the cookie are counted.
(setq org-checkbox-hierarchical-statistics t)

From this blog entry I got the hint that setting the variable org-cycle-separator-lines to zero will omit empty lines between headings in the collapsed view, which I prefer:

(setq org-cycle-separator-lines 0)

org-inlinetask is a method to define tasks via C-c C-x t anywhere in the hierarchy by using at least org-inlinetask-min-level number of asterisks. Since some of my normal heading levels do reach the standard value for it of 15, I had to extend it to 20 for now:

(setq org-inlinetask-min-level 20)
(setq org-id-link-to-org-use-id 'use-existing)

Using that setting, _ and ^ are interpreted literally. Except for cases like _{3} which makes 3 a subscript:

(setq org-use-sub-superscripts "{}")

Reverting a changed behavior in indentation (explanation and fix):

(add-hook 'org-mode-hook (lambda () (electric-indent-local-mode -1)))

scimax/org-return

Smart return does add new list item, … if appropriate

(require 'org-inlinetask)

(defun scimax/org-return (&optional ignore)
  "Add new list item, heading or table row with RET.
A double return on an empty element deletes it.
Use a prefix arg to get regular RET. "
  (interactive "P")
  (if ignore
      (org-return)
    (cond
     ((eq 'line-break (car (org-element-context)))
      (org-return-indent))
     ;; Open links like usual
     ((eq 'link (car (org-element-context)))
      (org-open-at-point-global))
     ;; It doesn't make sense to add headings in inline tasks. Thanks Anders
     ;; Johansson!
     ((org-inlinetask-in-task-p)
      (org-return))
     ;; add checkboxes
     ((org-at-item-checkbox-p)
      (org-insert-todo-heading nil))
     ;; lists end with two blank lines, so we need to make sure we are also not
     ;; at the beginning of a line to avoid a loop where a new entry gets
     ;; created with only one blank line.
     ((and (org-in-item-p) (not (bolp)))
      (if (org-element-property :contents-begin (org-element-context))
          (org-insert-heading)
        (beginning-of-line)
        (setf (buffer-substring
               (line-beginning-position) (line-end-position)) "")
        (org-return)))
     ;;disabled;; ((org-at-heading-p)
     ;;disabled;;  (if (not (string= "" (org-element-property :title (org-element-context))))
     ;;disabled;;      (progn (org-end-of-meta-data)
     ;;disabled;;             (org-insert-heading))
     ;;disabled;;    (beginning-of-line)
     ;;disabled;;    (setf (buffer-substring
     ;;disabled;;           (line-beginning-position) (line-end-position)) "")))
     ((org-at-table-p)
      (if (-any?
           (lambda (x) (not (string= "" x)))
           (nth
            (- (org-table-current-dline) 1)
            (org-table-to-lisp)))
          (org-return)
        ;; empty row
        (beginning-of-line)
        (setf (buffer-substring
               (line-beginning-position) (line-end-position)) "")
        (org-return)))
     (t
      (org-return)))))


(define-key org-mode-map (kbd "RET")
  'scimax/org-return)

org-file-apps -> open files in external apps

Here is a list of file extensions that should be openend outside of Emacs:

;;(add-to-list 'org-file-apps '("\\.odp" . system))
;;(add-to-list 'org-file-apps '("\\.odp" . mailcap))
(add-to-list 'org-file-apps '("\\.odp" . "open %s"))
;;(add-to-list 'org-file-apps '("\\.odp" . "/usr/bin/xdg-open %s"))

remove spaces from org-link-escape-chars

  • Why
    • I got issues on Windows when linking to a file which results in something like this which does not work when visited using C-c C-o:
      file:~/my%20dir/my%20file.txt
              
    • Something like this works tough:
      [[file:~/my dir/my file.txt]]
              

This might be dangerous since I neglect any changes of this (internal) variable. So far, it gets the job done. Let’s hope for the best that I don’t get into any nasty side-effects and don’t remember or recognize the reason caused by overwriting this setting here.

(setq org-link-escape-chars
  ;;%20 %5B %5D %25
  '(?\[ ?\] ?%)
  )

Styling

Omit the headline-asterisks except the last one:

(setq org-hide-leading-stars t)

syntax highlighting in source code:

from Eric Schulte <eric.schulte@gmx.com>
     Newsgroups: gmane.emacs.orgmode
     Subject: Re: org mode in press
     Date: Sat, 28 Jan 2012 10:06:08 -0700
     Message-ID: <87ipjv92pr.fsf@gmx.com>
  • 2014-04-04: set to nil in order to avoid performance issues!
  • 2015-12-26: set to t to test again these days
    • seems to be OK now
(setq org-src-fontify-natively t)

automatically change status of a heading to DONE when all children are done:

(defun org-summary-todo (n-done n-not-done)
  "Switch entry to DONE when all subentries are done, to TODO otherwise."
  (let (org-log-done org-log-states)   ; turn off logging
    (org-todo (if (= n-not-done 0) "DONE" "TODO"))))
(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)

Statistic cookies count ALL subtasks not only direkt ones

(setq org-hierarchical-todo-statistics t)

Stop the mouse cursor from highlighting lines in the agenda: http://orgmode.org/worg/org-faq.html Somehow this stopped working with org-super-agenda I guess.

(add-hook 'org-finalize-agenda-hook
          (lambda () (remove-text-properties
                      (point-min) (point-max) '(mouse-face t))))

Changing the default ellipsis to something that can’t be mixed up with normal characters: http://endlessparentheses.com/changing-the-org-mode-ellipsis.html

Note: on some computers, this results in higher line height as described on http://emacs.stackexchange.com/questions/251/line-height-with-unicode-characters See: id:2016-08-19-unicode-enlarges-line-height

(setq org-ellipsis "")
From: Bastien <bzg@altern.org>
Newsgroups: gmane.emacs.orgmode
Subject: Re: scale inline images in orgmode
Date: Thu, 30 Aug 2012 15:52:59 +0200
Message-ID: <87a9xcsczo.fsf@altern.org>

:

You can now (from git master) use `org-image-actual-width'.
(setq org-image-actual-width 300)
  => always resize inline images to 300 pixels
(setq org-image-actual-width '(400))
  => if there is a #+ATTR.*: width="200", resize to 200,
     otherwise resize to 400
(setq org-image-actual-width nil)
  => if there is a #+ATTR.*: width="200", resize to 200,
     otherwise don't resize
(setq org-image-actual-width t)
  => Never resize and use original width (the default)

Set the width of inline images:

(setq org-image-actual-width '(600))

Nice looking bullets for headings:

(use-package org-bullets
  :ensure t
  :config ;; executed after loading package
  (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
)

An alternative for org-bullets (above) would be: https://github.com/integral-dw/org-superstar-mode which I did not test so far. It also affects the simple lists which I do like as they are.

Note to myself: if you include org-superstar-mode you also have to adapt the beginner mode setting.

org-fancy-priorities replaces, e.g., “[A]” (for “highest priority”) with a nice graphic.

2018-07-23: disabled since it does not seem to work on my side. It somehow messes up my TODO keywords and my Windows font does not feature the icon characters.

(use-package org-fancy-priorities
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-fancy-priorities/")))
)

Nice symbold instead of keywords. I got this from this config but his UTF-8 symbols were not in my current (Windows) font.

(add-hook 'org-mode-hook
              (lambda ()
                (push '("TODO"  . ?█) prettify-symbols-alist)
                (push '("DONE"  . ?✓) prettify-symbols-alist)
                (push '("WAITING"  . ?…) prettify-symbols-alist)
                (push '("CANCELLED"  . ) prettify-symbols-alist)
                (push '("SOMEDAY"  . ??) prettify-symbols-alist)))
;  (face-spec-set 'org-block-begin-line
;    '((t (:underline "#FFFFFF" :foreground "#404040" :background "#b3b3b3")))
;    "Face used for the line delimiting the begin of source blocks.")

  ;(defface org-block-begin-line
  ;  '((t (:underline "#FFFFFF" :foreground "#cccccc" :background "#4d4d4d")))
  ;  "Face used for the line delimiting the begin of source blocks.")

  (defface org-block
    ;; defface org-block-background was removed from org:
    ;; http://emacs.stackexchange.com/questions/14824/org-block-background-font-not-having-effect
    ;; read also: https://www.reddit.com/r/emacs/comments/415imd/prettier_orgmode_source_code_blocks/
    '((t (:background "#1a1a1a")))
    "Face used for the source block background.")

  ;(defface org-block-end-line
  ;  '((t (:overline "#FFFFFF" :foreground "#cccccc" :background "#4d4d4d")))
  ;  "Face used for the line delimiting the end of source blocks.")

  ;;test: (set-face-background 'org-block-background "#1a1a1a")

General key bindings

Standard key bindings:

  (global-set-key "\C-cl" 'org-store-link)
  (global-set-key "\C-ca" 'org-agenda)
;;obsolete:  (global-set-key "\C-cb" 'org-iswitchb)

unset C-c , (org-priority) because I get confused when I mistype C-c C-,

;;(global-unset-key (kbd "C-c ,"))
(global-set-key (kbd "C-c ,") 'my-map)

Remembering positions:

(global-set-key (kbd "C-c %") 'org-mark-ring-push)
(global-set-key (kbd "C-c <left>") 'org-mark-ring-goto)
(global-set-key (kbd "C-c <down>") 'org-mark-ring-push)

MISC Apple bindings

(setq mac-command-modifier 'apple)
(global-set-key [(<apple> <up>)] 'org-move-subtree-up)
(global-set-key "\S-<down>" 'org-move-subtree-down)
(global-set-key "\S-<left>" 'org-do-promote)
(global-set-key "\S-<right>" 'org-do-demote)

Org-mode keys for Mac

  • I wanted to map Alt-left|right|… but Alt has to be used by the system in order to type umlauts :-(
(setq mac-command-modifier 'apple)
(global-set-key [(<apple> <up>)] 'org-move-subtree-up)
(global-set-key "\S-<down>" 'org-move-subtree-down)
(global-set-key "\S-<left>" 'org-do-promote)
(global-set-key "\S-<right>" 'org-do-demote)

fix broken mapping (because of prelude and so on).

  • disabled 2014-01-19
(defun my-org-mode-hook ()
  (define-key prelude-mode-map (kbd "C-c +") nil)
  (define-key prelude-mode-map (kbd "C-c -") nil)
  )
(add-hook 'org-mode-hook 'my-org-mode-hook)
(org-defkey org-mode-map (kbd "C-c C-,") nil);; clear binding
(org-defkey org-mode-map (kbd "C-c C-k") nil);; clear binding
(org-defkey org-mode-map (kbd "C-c k") nil);; clear binding

My general Org helper functions

my-org-startup-visibility()

Sometimes, I get a mess with all kinds of sub-hierarchies openend in my most important Org-mode buffers. When I want to get the startup visibility, I invoke this function to get a fresh environment again.

Take a look at my-reset-org() as well.

(defun my-org-startup-visibility (&optional ignore)
  "Sets the startup visibility in my most important buffers"
  (interactive "P")
  (save-window-excursion ;; Why save-excursion is not sufficient here: https://emacs.stackexchange.com/questions/24133/save-excursion-doesnt-restore-the-currently-visible-buffer
    (when (my-buffer-exists "misc.org")
      (switch-to-buffer "misc.org")
      (org-set-startup-visibility)
      )
    (when (my-buffer-exists "projects.org")
      (switch-to-buffer "projects.org")
      (org-set-startup-visibility)
      )
    (when (my-buffer-exists "issues.org")
      (switch-to-buffer "issues.org")
      (org-set-startup-visibility)
      )
    (when (my-buffer-exists "contacts.org")
      (switch-to-buffer "contacts.org")
      (org-set-startup-visibility)
      )
    (when (my-buffer-exists "notes.org")
      (switch-to-buffer "notes.org")
      (org-set-startup-visibility)
      )
    (when (my-buffer-exists "hardware.org")
      (switch-to-buffer "hardware.org")
      (org-set-startup-visibility)
      )
    (when (my-buffer-exists "public_voit.org")
      (switch-to-buffer "public_voit.org")
      (org-set-startup-visibility)
      )
    (when (my-buffer-exists "rise.org")
      (switch-to-buffer "rise.org")
      (org-set-startup-visibility)
      )
    ;; (when (my-system-type-is-windows)
    ;;   (when (my-buffer-exists "detego.org")
    ;;     (switch-to-buffer "detego.org")
    ;;     (org-set-startup-visibility)
    ;;     )
    ;;   (when (my-buffer-exists "ciso.org")
    ;;     (switch-to-buffer "ciso.org")
    ;;     (org-set-startup-visibility)
    ;;     )
    ;;   )
    )
  )

For a more fine-grained control on expanded headings when visiting a Org file, look at org-auto-expand.

my-reset-org() - reset some Org-mode stuff

This function summarizes some other functions that clear up the current Org-mode, re-building some caches and so fort.

Take a look at my-org-startup-visibility() as well.

(defun my-reset-org ()
  "Clears all kinds of Org-mode caches and re-builds them if possible"
  (interactive)
  (measure-time
   (org-element-cache-reset)
   (org-refile-cache-clear)
   (org-refile-get-targets)
   (setq org-agenda-tags-column (- (- (window-total-width) 3))) ;; total width minus 3
   (when (my-buffer-exists "*Org Agenda*")
     (kill-buffer "*Org Agenda*")
     (org-agenda-list)
     )
   )
  )

when being idle for 15 minutes, run my-reset-org()

  • See id:2016-06-05-reset-things-after-15-min-idle

current-idle-time example: (0 420 1000 0)

Disabled because it doesn’t work:

(setq my-reset-org-previous-idle-time-invocation (current-time))
(run-with-idle-timer (* 60 15) t (lambda ()
                                   (if (< 2 (float-time (time-since my-reset-org-previous-idle-time-invocation)))
                                       (sit-for 2)
                                     (when (< (nth 1 (current-idle-time)) (* 60 16));; run only once per idle period
                                       (message "Idle for 15 minutes, invoking my-reset-org in 10 seconds ...")
                                       (sit-for 10);; give user 10s to press a button to prevent this
                                       (when (< (nth 1 (current-idle-time)) (* 60 16));; run only once per idle period
                                         (my-reset-org)
                                         (setq my-reset-org-previous-idle-time-invocation (current-time))
                                         (message (concat "my-reset-org finished at " (current-time-string)))
                                         )
                                       )
                                     )
                                   ))

;;(defun mytest ()
;;     (when (< (nth 1 (or (current-idle-time) (list 0 0 0 0)))) (* 60 16));; run only once per idle period
;;       (message "yes")
;;       )
;;     )
;;
;;(sit-for 3)
;;(message (or (current-idle-time) (number-to-string 0)))

Functions for Working Hour Calculation

I used this code to derive working hours until the company switched to a stupid new tool everybody hates. Yes, even worse than SAP.

This is just for the record because it contains much Elisp sweat from my side:

(defun my-extract-minutes-of-hm-string(hm-string)
  "returns the minutes of a string like 9:42 -> 42 (and 0 if there are no minutes)"
  (let (
        ;; minutes is the second element after splitting with ":"
        (minutes (nth 1 (split-string hm-string ":")))
        )
    ;; if there is no second element, return "0" (instead of nil)
    (if (eq minutes 'nil)
        0
      (string-to-number minutes)
      )
    )
  )

(defun my-extract-hours-of-hm-string(hm-string)
  "returns the hours of a string like 9:42 -> 9"
  (string-to-number
   (car
    (split-string hm-string ":")
    )
   )
)

(defun my-hm-string-to-minutes(hm-string)
  "returns the minutes of a string like 2:42 -> 162"
  (let (
        ;; minutes is the second element after splitting with ":"
        (minutes (my-extract-minutes-of-hm-string hm-string))
        (hours (my-extract-hours-of-hm-string hm-string))
        )
    (+ minutes (* hours 60))
    )
  )


;; EXAMPLE USAGE:
;; | [2015-01-13 Di] | Tue | 08:53-17:23 |   |   | 8:30 | 8:30 | 100 | Product Development |       |
;; |                 |     |             |   |   |      | korr |   % | Was                 | Notiz |
;; #+TBLFM: $7=$6::$9=Product Development::$8 = '(my-percentage-of-hm-string-with-day $7 $2)

(defun my-percentage-of-hm-string-with-day(hm-string day)
  "percentage of HH:MM when 8h30min (Mon-Thu) or 4h30min (Fri) are 100 percent"
  (let (
        (hours (my-extract-hours-of-hm-string hm-string));; integer of hours from hm-string
        (minutes (my-extract-minutes-of-hm-string hm-string));; integer of minutes from hm-string
        (norm-hour-minutes (cond
                            ((string= day "Mon") 8.5)
                            ((string= day "Mo")  8.5)
                            ((string= day "Tue") 8.5)
                            ((string= day "Di")  8.5)
                            ((string= day "Wed") 8.5)
                            ((string= day "Mi")  8.5)
                            ((string= day "Thu") 8.5)
                            ((string= day "Do")  8.5)
                            ((string= day "Fri") 8.5)
                            ((string= day "Fr")  8.5)
                            )
                           )
        )
    ;;debug;;(message (concat "norm-hour-minutes for " day " is " (number-to-string norm-hour-minutes)))
    (let (
          (hoursminutes (+ hours (/ minutes 60.00))) ;; 8h30min -> 8.5h
          )
      (round (* 100 (/ hoursminutes norm-hour-minutes)));; hoursminutes in relation to norm-hoursminutes
      )
    )
  )

(defun my-calculate-office-hour-total(officestart officeend lunchstart lunchend)
  "calculates the total hours:minutes of a work-day depending on time of arrival/leave and lunch break in HH:MM"
  (let (
        (officestartminutes (my-hm-string-to-minutes officestart));; integer of minutes
        (officeendminutes (my-hm-string-to-minutes officeend));; integer of minutes
        (lunchstartminutes (my-hm-string-to-minutes lunchstart));; integer of minutes
        (lunchendminutes (my-hm-string-to-minutes lunchend));; integer of minutes
        )
    (let* (
          (officeminutes (- (- officeendminutes officestartminutes) (- lunchendminutes lunchstartminutes)))
          (officeminutesstring (format-time-string "%H:%M" (seconds-to-time (* 60 officeminutes)) t))
          )
      ;;(message (concat "Minutes epoch: " (number-to-string officeminutes)))
      ;;(message (concat "Minutes string: " officeminutesstring))
      (symbol-value 'officeminutesstring)
      )
    )
  )
;; (my-calculate-office-hour-total "09:57" "17:22" "11:35" "12:08") -> Minutes epoch: 412 | Minutes string: 06:52


;; #############################################################################

my-insert-orgmode-url-from-clipboard() → my-map U

Inserts URL from clipboard and retrieves title as Org-mode link

straight-string()

(defun straight-string (s)
  "Spliting the string and then concatenating it back."
  (mapconcat #'(lambda (x) x) (split-string s) " "))

my-cliplink-format-and-trim-title(title) does replace HTML entities with their Unicode characters and trims the title to 100 characters.

The replacement table is taken from this ErgoEmacs page.

(defun my-cliplink-format-and-trim-title (title)
  (let (;; Table of replacements which make this title usable for
        ;; org-link. Can be extended.
        (replace-table '(("\\[" . "{")
                         ("\\]" . "}")
                         ("&#8217;" . "")
                         ("&amp;" . "&") ("&#039;" . "'") ("&#8211;" . "") ("&#8212;" . "")
                         ("" . "")  ("  | heise online • " . " - heise online") (" | heise online • " . " - heise online")
                               ("&nbsp;" . " ") ("&ensp;" . "") ("&emsp;" . "") ("&thinsp;" . "")
                               ("&rlm;" . "") ("&lrm;" . "") ("&zwj;" . "") ("&zwnj;" . "")
                               ("&iexcl;" . "¡") ("&cent;" . "¢") ("&pound;" . "£") ("&curren;" . "¤") ("&yen;" . "¥") ("&brvbar;" . "¦") ("&sect;" . "§")
                               ("&uml;" . "¨") ("&copy;" . "©") ("&ordf;" . "ª") ("&laquo;" . "«") ("&not;" . "¬") ("&shy;" . "­") ("&reg;" . "®")
                               ("&macr;" . "¯") ("&deg;" . "°") ("&plusmn;" . "±") ("&sup2;" . "²") ("&sup3;" . "³") ("&acute;" . "´") ("&micro;" . "µ")
                               ("&para;" . "") ("&middot;" . "·") ("&cedil;" . "¸") ("&sup1;" . "¹") ("&ordm;" . "º") ("&raquo;" . "»") ("&frac14;" . "¼")
                               ("&frac12;" . "½") ("&frac34;" . "¾") ("&iquest;" . "¿") ("&Agrave;" . "À") ("&Aacute;" . "Á") ("&Acirc;" . "Â")
                               ("&Atilde;" . "Ã") ("&Auml;" . "Ä") ("&Aring;" . "Å") ("&AElig;" . "Æ") ("&Ccedil;" . "Ç") ("&Egrave;" . "È") ("&Eacute;" . "É")
                               ("&Ecirc;" . "Ê") ("&Euml;" . "Ë") ("&Igrave;" . "Ì") ("&Iacute;" . "Í") ("&Icirc;" . "Î") ("&Iuml;" . "Ï") ("&ETH;" . "Ð")
                               ("&Ntilde;" . "Ñ") ("&Ograve;" . "Ò") ("&Oacute;" . "Ó") ("&Ocirc;" . "Ô") ("&Otilde;" . "Õ") ("&Ouml;" . "Ö") ("&times;" . "×")
                               ("&Oslash;" . "Ø") ("&Ugrave;" . "Ù") ("&Uacute;" . "Ú") ("&Ucirc;" . "Û") ("&Uuml;" . "Ü") ("&Yacute;" . "Ý") ("&THORN;" . "Þ")
                               ("&szlig;" . "ß") ("&agrave;" . "à") ("&aacute;" . "á") ("&acirc;" . "â") ("&atilde;" . "ã") ("&auml;" . "ä") ("&aring;" . "å")
                               ("&aelig;" . "æ") ("&ccedil;" . "ç") ("&egrave;" . "è") ("&eacute;" . "é") ("&ecirc;" . "ê") ("&euml;" . "ë") ("&igrave;" . "ì")
                               ("&iacute;" . "í") ("&icirc;" . "î") ("&iuml;" . "ï") ("&eth;" . "ð") ("&ntilde;" . "ñ") ("&ograve;" . "ò") ("&oacute;" . "ó")
                               ("&ocirc;" . "ô") ("&otilde;" . "õ") ("&ouml;" . "ö") ("&divide;" . "÷") ("&oslash;" . "ø") ("&ugrave;" . "ù") ("&uacute;" . "ú")
                               ("&ucirc;" . "û") ("&uuml;" . "ü") ("&yacute;" . "ý") ("&thorn;" . "þ") ("&yuml;" . "ÿ") ("&fnof;" . "ƒ") ("&Alpha;" . "Α")
                               ("&Beta;" . "Β") ("&Gamma;" . "Γ") ("&Delta;" . "Δ") ("&Epsilon;" . "Ε") ("&Zeta;" . "Ζ") ("&Eta;" . "Η") ("&Theta;" . "Θ")
                               ("&Iota;" . "Ι") ("&Kappa;" . "Κ") ("&Lambda;" . "Λ") ("&Mu;" . "Μ") ("&Nu;" . "Ν") ("&Xi;" . "Ξ") ("&Omicron;" . "Ο") ("&Pi;" . "Π")
                               ("&Rho;" . "Ρ") ("&Sigma;" . "Σ") ("&Tau;" . "Τ") ("&Upsilon;" . "Υ") ("&Phi;" . "Φ") ("&Chi;" . "Χ") ("&Psi;" . "Ψ")
                               ("&Omega;" . "Ω") ("&alpha;" . "α") ("&beta;" . "β") ("&gamma;" . "γ") ("&delta;" . "δ") ("&epsilon;" . "ε") ("&zeta;" . "ζ")
                               ("&eta;" . "η") ("&theta;" . "θ") ("&iota;" . "ι") ("&kappa;" . "κ") ("&lambda;" . "λ") ("&mu;" . "μ") ("&nu;" . "ν") ("&xi;" . "ξ")
                               ("&omicron;" . "ο") ("&pi;" . "π") ("&rho;" . "ρ") ("&sigmaf;" . "ς") ("&sigma;" . "σ") ("&tau;" . "τ") ("&upsilon;" . "υ")
                               ("&phi;" . "φ") ("&chi;" . "χ") ("&psi;" . "ψ") ("&omega;" . "ω") ("&thetasym;" . "ϑ") ("&upsih;" . "ϒ") ("&piv;" . "ϖ")
                               ("&bull;" . "") ("&hellip;" . "") ("&prime;" . "") ("&Prime;" . "") ("&oline;" . "") ("&frasl;" . "") ("&weierp;" . "")
                               ("&image;" . "") ("&real;" . "") ("&trade;" . "") ("&alefsym;" . "") ("&larr;" . "") ("&uarr;" . "") ("&rarr;" . "")
                               ("&darr;" . "") ("&harr;" . "") ("&crarr;" . "") ("&lArr;" . "") ("&uArr;" . "") ("&rArr;" . "") ("&dArr;" . "") ("&hArr;" . "")
                               ("&forall;" . "") ("&part;" . "") ("&exist;" . "") ("&empty;" . "") ("&nabla;" . "") ("&isin;" . "") ("&notin;" . "")
                               ("&ni;" . "") ("&prod;" . "") ("&sum;" . "") ("&minus;" . "") ("&lowast;" . "") ("&radic;" . "") ("&prop;" . "")
                               ("&infin;" . "") ("&ang;" . "") ("&and;" . "") ("&or;" . "") ("&cap;" . "") ("&cup;" . "") ("&int;" . "") ("&there4;" . "")
                               ("&sim;" . "") ("&cong;" . "") ("&asymp;" . "") ("&ne;" . "") ("&equiv;" . "") ("&le;" . "") ("&ge;" . "") ("&sub;" . "")
                               ("&sup;" . "") ("&nsub;" . "") ("&sube;" . "") ("&supe;" . "") ("&oplus;" . "") ("&otimes;" . "") ("&perp;" . "")
                               ("&sdot;" . "") ("&lceil;" . "") ("&rceil;" . "") ("&lfloor;" . "") ("&rfloor;" . "") ("&lang;" . "") ("&rang;" . "")
                               ("&loz;" . "") ("&spades;" . "") ("&clubs;" . "") ("&hearts;" . "") ("&diams;" . "") ("&quot;" . "\"") ("&OElig;" . "Œ")
                               ("&oelig;" . "œ") ("&Scaron;" . "Š") ("&scaron;" . "š") ("&Yuml;" . "Ÿ") ("&circ;" . "ˆ") ("&tilde;" . "˜") ("&ndash;" . "")
                               ("&mdash;" . "") ("&lsquo;" . "") ("&rsquo;" . "") ("&sbquo;" . "") ("&ldquo;" . "") ("&rdquo;" . "") ("&bdquo;" . "")
                               ("&dagger;" . "") ("&Dagger;" . "") ("&permil;" . "") ("&lsaquo;" . "") ("&rsaquo;" . "") ("&euro;" . "")
                         ))
        ;; Maximum length of the title.
        (max-length 100)
        ;; Removing redundant whitespaces from the title.
        (result (straight-string title)))
    ;; Applying every element of the replace-table.
    (dolist (x replace-table)
      (setq result (replace-regexp-in-string (car x) (cdr x) result t t)))
    ;; Cutting off the title according to its maximum length.
    (when (> (length result) max-length)
      (setq result (concat (substring result 0 max-length) "")))
    ;; Returning result.
    result))

extract-title-from-html(html)

(defun extract-title-from-html (html)
  (let (;; Start index of the title.
        (start (string-match "<title>" html))
        ;; End index of the title.
        (end (string-match "</title>" html))
        ;; Amount of characters to skip the openning title tag.
        (chars-to-skip (length "<title>")))
    ;; If title is found ...
    (if (and start end (< start end))
        ;; ... extract it and return.
        (substring html (+ start chars-to-skip) end)
      nil)))

cliplink-decode-content-and-return-orgmode-link-of-title (buffer url content)

(defun cliplink-decode-content-and-return-orgmode-link-of-title (buffer url content)
  (let* (;; Decoding the content from UTF-8.
         (decoded-content (decode-coding-string content 'utf-8))
         ;; Extrating and preparing the title.
         (title (my-cliplink-format-and-trim-title
                 (extract-title-from-html decoded-content))))
    ;; Inserting org-link.
    (with-current-buffer buffer
      (insert (format "[[%s][%s]]" url title)))))

my-insert-orgmode-url-from-clipboard ()

(defun my-insert-orgmode-url-from-clipboard ()
  "It inserts the URL which is taken from the system clipboard in Org-mode"
  ;; Of course, this function is interactive. :)
  (interactive)
  (let (;; Remembering the current buffer, 'cause it is a destination
        ;; buffer we are inserting the org-link to.
        (dest-buffer (current-buffer))
        ;; Getting URL from the clipboard. Since it may contain
        ;; some text properties we are using substring-no-properties
        ;; function.
        (url (substring-no-properties (current-kill 0))))
    ;; Retrieving content by URL.
    (url-retrieve
     url
     ;; Performing an action on the retrieved content.
     `(lambda (s)
        (cliplink-decode-content-and-return-orgmode-link-of-title ,dest-buffer ,url
                          (buffer-string))))))

bind to my-map U

(bind-key "U" 'my-insert-orgmode-url-from-clipboard my-map)

my-url-linkify() → my-map u

Replaces URL with Org-mode link including description

  (defun my-www-get-page-title (url)
    "retrieve title of web page.
from: http://www.opensubscriber.com/message/help-gnu-emacs@gnu.org/14332449.html"
    (let ((title))
      (with-current-buffer (url-retrieve-synchronously url)
        (goto-char (point-min))
        (re-search-forward "<title>\\([^<]*\\)</title>" nil t 1)
        (setq title (match-string 1))
        (goto-char (point-min))
        (re-search-forward "charset=\\([-0-9a-zA-Z]*\\)" nil t 1)
        (string-replace "&nbsp;" " "
                        ;;(decode-coding-string title (intern (match-string 1)))
                        ;; following line fixes charset issues from
                        ;; previous line:
                        (decode-coding-string title 'utf-8)
                        ))
      )
    )
  (defun my-url-linkify ()
    "Make URL at cursor point into an Org-mode link.
If there's a text selection, use the text selection as input.

Example: http://example.com/xyz.htm
becomes
\[\[http://example.com/xyz.htm\]\[Source example.com\]\]

Adapted code from: http://ergoemacs.org/emacs/elisp_html-linkify.html"
    (interactive)
    (let (resultLinkStr bds p1 p2 domainName)
      ;; get the boundary of URL or text selection
      (if (region-active-p)
          (setq bds (cons (region-beginning) (region-end)) )
        (setq bds (bounds-of-thing-at-point 'url))
        )
      ;; set URL
      (setq p1 (car bds))
      (setq p2 (cdr bds))
      (let (
            (url (buffer-substring-no-properties p1 p2))
            )
        ;; retrieve title
        (let ((title (my-cliplink-format-and-trim-title (replace-regexp-in-string "\n" "" (my-www-get-page-title url)))))
          ;;(message (concat "title is: " title))
          ;;(setq url (replace-regexp-in-string "&" "&amp;" url))
          (let ((resultLinkStr (concat "[[" url "][" title "]]")))
            ;; delete url and insert the link
            (delete-region p1 p2)
            (insert resultLinkStr)
            )
          )
        )
      )
    )

Bind the key:

(bind-key "u" 'my-url-linkify my-map)

my-org-region-to-property() → my-map p

This is ultra-handy for writing properties. For example for my contact management contacts.org I maintain properties such as phone numbers. When I mark a (changed) phone number within the body of a heading and invoke this function, I get asked for an existing property and the marked region gets the new value for this property.

Please do read my blog article on this topic for all the details. You’re gonna like it. It also features a short screencast where you see this in action.

Internal link: id:2015-05-28-ask-for-properties

Version that tries to read only properties of current entry:

(defun org-read-entry-property-name ()
  "Read a property name from the current entry."
  (let ((completion-ignore-case t)
        (default-prop (or (and (org-at-property-p)
                               (org-match-string-no-properties 2))
                          org-last-set-property)))
    (org-completing-read
     (format "Property [%s]: " (if default-prop default-prop ""))
     (org-entry-properties nil nil)
     nil nil nil nil default-prop)))

(defun my-org-region-to-property (&optional property)
  "Copies the region as value to an Org-mode property"
  (interactive)
  ;; if no region is defined, do nothing
  (if (use-region-p)
      ;; if a region string is found, ask for a property and set property to
      ;; the string in the region
      (let ((val (replace-regexp-in-string
                  "\\`[ \t\n]*" ""
                  (replace-regexp-in-string "[ \t\n]*\\'" ""
                                            (substring (buffer-string)
                                                       (- (region-beginning) 1)
                                                       (region-end))))
                 )
            ;; if none was stated by user, read property from user
            (prop (or property
                      (org-read-entry-property-name))))
        ;; set property
        (org-set-property prop val))))

(bind-key (kbd "p") #'my-org-region-to-property my-map)

my-0d() - add a 0 day deadline to a headline

On an agenda entry: add “-0d” to deadline

(fset 'my-0d
      [return ?\C-s ?> left ?  ?- ?0 ?d ?\C-x ?b return down])

my-agenda-cancel-event-and-set-to-inactive() - Change active timestamp to inactive and cancel event in the agenda

(fset 'my-agenda-cancel-event-and-set-to-inactive
        (lambda (&optional arg) "Keyboard macro."
          (interactive "p")
          (kmacro-exec-ring-item (quote ([return S-up 3 20 99] 0 "%d")) arg)
          )
        )

my-cancel-event-and-set-to-inactive() - Change active timestamp to inactive and cancel event outside of the agenda

(fset 'my-cancel-event-and-set-to-inactive
        (lambda (&optional arg) "Keyboard macro."
          (interactive "p")
          (kmacro-exec-ring-item (quote ([5 18 62 13 S-up 3 20 99] 0 "%d")) arg)
          )
        )

my-org-time-string-to-seconds(s)

Example 1: normal dates and times

DateStartLunchBackEndSum
[2011-03-01 Tue]8:0012:0012:3018:159:45

Example 2: my-org-time-string-to-seconds simple case

13:59839
13:59:0550345

Example 3: calculating with my-org-time-string-to-seconds results

21:42:1321:41:0073
(defun my-org-time-string-to-seconds (s)
  "Convert a string HH:MM:SS to a number of seconds.
   Omitted third element will be interpreted as MM:SS with missing hours."
  ;; test with:
  ;; (message (concat "result is: " (number-to-string (my-org-time-string-to-seconds "57:45:03"))))
  ;; (message (concat "result is: " (number-to-string (my-org-time-string-to-seconds "57:45"))))
  (cond
   ((and (stringp s)
         (string-match "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)" s))
    (let ((hour (string-to-number (match-string 1 s)))
          (min (string-to-number (match-string 2 s)))
          (sec (string-to-number (match-string 3 s))))
      (+ (* hour 3600) (* min 60) sec)))
   ((and (stringp s)
         (string-match "\\([0-9]+\\):\\([0-9]+\\)" s))
    (let ((min (string-to-number (match-string 1 s)))
          (sec (string-to-number (match-string 2 s))))
      (+ (* min 60) sec)))
   ;;((stringp s) (string-to-number s))
   ;;(t s)
   )
  )

my-org-time-string-to-hours(s)

13:590.23305555555555554
13:59:0513.984722222222222
(defun my-org-time-string-to-hours (s)
  "Convert a string HH:MM:SS to hours (float).
   When only two values given, they will be interpreted as MM:SS with missing hours."
  ;; test via:
  ;; (message (concat "result is: " (number-to-string (my-org-time-string-to-hours "57:45:03"))))
  ;; (message (concat "result is: " (number-to-string (my-org-time-string-to-hours "57:45"))))
  (/ (my-org-time-string-to-seconds s) 3600.0)
  )

my-org-time-seconds-to-string(secs)

4242
9876527:26:05
(defun my-org-time-seconds-to-string (secs)
  "Convert a number of seconds to a time string."
  (cond ((>= secs 3600) (format-seconds "%h:%.2m:%.2s" secs))
        ((>= secs 60) (format-seconds "%m:%.2s" secs))
        (t (format-seconds "%s" secs))))

with-time() - evaluate formula and return time

  (defmacro with-time (time-output-p &rest exprs)
    "Evaluate an org-table formula, converting all fields that look
like time data to integer seconds.  If TIME-OUTPUT-P then return
the result as a time value."
    (list
     (if time-output-p 'my-org-time-seconds-to-string 'identity)
     (cons 'progn
           (mapcar
            (lambda (expr)
              `,(cons (car expr)
                      (mapcar
                       (lambda (el)
                         (if (listp el)
                             (list 'with-time nil el)
                           (my-org-time-string-to-seconds el)))
                       (cdr expr))))
            `,@exprs))))

org-decrypt-entries()

I never use org-decrypt-entries() since my Org files tend to be large and contain several encrypted entries. In order to get a decent performance, I overwrite org-decrypt-entries() so that I am able to select org-decrypt-entry() much faster in helm search.

(defun org-decrypt-entries()
  (interactive)
  (org-decrypt-entry)
)

my-sparse-tree-with-tag-filter() - ask for a tag and filter open Org-tasks → my-map F

The code asks for one or more tags and derives a sparse tree with all related open headings.

See: id:2014-11-02-filter-org-tasks-by-tag

(defun my-sparse-tree-with-tag-filter()
  "asks for a tag and generates sparse tree for all open tasks in current Org buffer
  that are associated with this tag"
  (interactive "*")
  (setq tag-for-filter
        (org-trim
         (org-icompleting-read "Tags: "
                               'org-tags-completion-function
                               nil nil nil 'org-tags-history))
        )
  (org-occur
   (concat "^\\*+ \\(NEXT\\|TODO\\|WAITING\\|STARTED\\) .+:"
           tag-for-filter
           ":")
   )
  )
(bind-key "F" #'my-sparse-tree-with-tag-filter my-map)

my-sparse-tree-WAITING()

2021-07-11created
(defun my-sparse-tree-WAITING()
  "shows org sparse tree with all WAITING tasks of current buffer"
  (interactive "*")
  (org-occur
   (concat "^\\*+ WAITING .+")
   )
  )

my-reddit-export-via-pandoc

This is a simple shortcut because I can not remember which of the many markdown dialects is the one for reddit and ox-pandoc doesn’t show me markdown at all which I have to fix some day.

My workflow is:

  1. mark the region where the content to export is
  2. M-x my-reddit TAB RET
  3. copy the content from the temporary buffer to my browser window
  4. destroy the temporary buffer
(defun my-reddit-export-via-pandoc ()
"This is a simple wrapper function that converts the currently
marked region to the markdown dialect that reddit understands."
  (interactive)
  (org-pandoc-export-to-markdown_mmd-and-open)
)

my-org-in-any-block-p()

This is part 1/4 of the soluiton to split up blocks via M-RET:

(defun my-org-in-any-block-p ()
      "Return non-nil if the point is in any Org block.
The Org block can be *any*: src, example, verse, etc., even any
Org Special block.
This function is heavily adapted from `org-between-regexps-p'."
      (save-match-data
        (let ((pos (point))
              (case-fold-search t)
              (block-begin-re "^[[:blank:]]*#\\+begin_\\(?1:.+?\\)\\(?: .*\\)*$")
              (limit-up (save-excursion (outline-previous-heading)))
              (limit-down (save-excursion (outline-next-heading)))
              beg end)
          (save-excursion
            ;; Point is on a block when on BLOCK-BEGIN-RE or if
            ;; BLOCK-BEGIN-RE can be found before it...
            (and (or (org-in-regexp block-begin-re)
                     (re-search-backward block-begin-re limit-up :noerror))
                 (setq beg (match-beginning 0))
                 ;; ... and BLOCK-END-RE after it...
                 (let ((block-end-re (concat "^[[:blank:]]*#\\+end_"
                                             (match-string-no-properties 1)
                                             "\\( .*\\)*$")))
                   (goto-char (match-end 0))
                   (re-search-forward block-end-re limit-down :noerror))
                 (> (setq end (match-end 0)) pos)
                 ;; ... without another BLOCK-BEGIN-RE in-between.
                 (goto-char (match-beginning 0))
                 (not (re-search-backward block-begin-re (1+ beg) :noerror))
                 ;; Return value.
                 (cons beg end))))))

my-org-split-block()

This is part 2/4 of the soluiton to split up blocks via M-RET:

    (defun my-org-split-block ()
      "Sensibly split the current Org block at point.
(1) Point in-between a line
    #+EXAMPLE+begin_src emacs-lisp             #+EXAMPLE+begin_src emacs-lisp
    (message▮ \"one\")                   (message \"one\")
    (message \"two\")          -->       #+EXAMPLE+end_src
    #+EXAMPLE+end_src                          ▮
                                       #+EXAMPLE+begin_src emacs-lisp
                                       (message \"two\")
                                       #+EXAMPLE+end_src
(2) Point at EOL
    #+EXAMPLE+begin_src emacs-lisp             #+EXAMPLE+begin_src emacs-lisp
    (message \"one\")▮                   (message \"one\")
    (message \"two\")          -->       #+EXAMPLE+end_src
    #+EXAMPLE+end_src                          ▮
                                       #+EXAMPLE+begin_src emacs-lisp
                                       (message \"two\")
                                       #+EXAMPLE+end_src
(3) Point at BOL
    #+EXAMPLE+begin_src emacs-lisp             #+EXAMPLE+begin_src emacs-lisp
    (message \"one\")                    (message \"one\")
    ▮(message \"two\")          -->      #+EXAMPLE+end_src
    #+EXAMPLE+end_src                          ▮
                                       #+EXAMPLE+begin_src emacs-lisp
                                       (message \"two\")
                                       #+EXAMPLE+end_src
"
      (interactive)
      (if (my-org-in-any-block-p)
          (save-match-data
            (save-restriction
              (widen)
              (let ((case-fold-search t)
                    (at-bol (bolp))
                    block-start
                    block-end)
                (save-excursion
                  (re-search-backward "^\\(?1:[[:blank:]]*#\\+begin_.+?\\)\\(?: .*\\)*$" nil nil 1)
                  (setq block-start (match-string-no-properties 0))
                  (setq block-end (replace-regexp-in-string
                                   "begin_" "end_" ;Replaces "begin_" with "end_", "BEGIN_" with "END_"
                                   (match-string-no-properties 1))))
                ;; Go to the end of current line, if not at the BOL
                (unless at-bol
                  (end-of-line 1))
                (insert (concat (if at-bol "" "\n")
                                block-end
                                "\n\n"
                                block-start
                                (if at-bol "\n" "")))
                ;; Go to the line before the inserted "#+begin_ .." line
                (beginning-of-line (if at-bol -1 0)))))
        (message "Point is not in an Org block")))

my-org-meta-return-advice()

This is part 3/4 of the soluiton to split up blocks via M-RET:

;; When point is in any Org block, make M-return split the block
;; instead of inserting heading.
(defun my-org-meta-return-advice (&rest args)
  "Do not call the original function if point is in an Org block."
  (let ((do-not-run-orig-fn (my-org-in-any-block-p)))
    (when do-not-run-orig-fn
      (my-org-split-block))
    do-not-run-orig-fn))

advice-add: M-RET splits up current block

This is part 4/4 of the soluiton to split up blocks via M-RET:

(advice-add 'org-meta-return :before-until #'my-org-meta-return-advice)

my-newsrob-capture-fix()

2021-07-06Situation with NewsRob and capture did change: not needed for quite some time → disabling it

Currently as of 2019-02-16, I’m using NewsRob Android for reading Atom and RSS feeds.

Unfortunately, when I capture NewsRob articles using Mobile Org, I end up with a messed up format in my inbox.org:

* NEXT Bookmark
Some text is here http://example.com/path/page.html[2019-02-16 Sat. 16:07]

In contrast, I would prefer:

* NEXT Bookmark [[http://example.com/path/page.html][Some text is here]]
[2019-02-16 Sat. 16:07]

Using this preferred format, I may apply my-save-bookmark() as usual.

This is why I had to come up with this helper function:

(defun my-newsrob-capture-fix ()
  "Fixes NewsRob OrgMobile capture format error (content starts in 2nd line) and generates proper Org URL link"
  ;; for details, see id:2019-02-16-my-newsrob-capture-fix

  (interactive)
  ;; ASSUMPTION: cursor is in FIRST line of the captured heading
  (beginning-of-line)
  (when (re-search-forward "^\\(\\*.*\\)
\\(.*\\)\\s-* \\(http.*\\)\\s-*\\(\\[20.*\\]\\)" nil t)
    (replace-match "\\1 [[\\3][\\2]]\n\\4" t nil)))

(bind-key "B" 'my-newsrob-capture-fix my-map)

my-filename-to-attr-snippet

A macro that is very handy when inserting images to a lazyblorg entry.

  • Process:
    1. Copy and paste a file base name as a new line
      • example: 2019-08-25T18.43 An example image file -- publicvoit.jpg
    2. Place the cursor at the begin of its line
    3. Invoke the macro
    4. Resulting snippet looks like:
#+CAPTION:
#+ATTR_HTML: :align center :width 560
[[tsfile:2019-08-25T18.43 An example image file -- publicvoit.jpg][2019-08-25T18.43 An example image file -- publicvoit.jpg]]
(fset 'my-filename-to-attr-snippet
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([return up 35 43 67 65 80 84 73 79 78 58 32 return 35 43 65 84 84 82 95 72 84 77 76 58 32 58 97 108 59 backspace 105 103 110 32 99 101 110 116 101 114 32 58 119 105 100 116 104 32 53 54 48 1 down 91 91 116 115 102 105 108 101 58 67108896 5 escape 119 93 91 25 93 93 15 1 down down] 0 "%d")) arg)))

my-mark-as-project

With UOMF: On How to Define Projects in Org Mode I started to use marking projects with a specific tag and made sure the COOKIE_DATA property ignores the checkboxes.

Following function makes sure that these things are set properly (and a bit more):

(defun my-mark-as-project ()
"This function makes sure that the current heading has
(1) the tag :project:
(2) has property COOKIE_DATA set to \"todo recursive\"
(3) has any TODO keyword and
(4) a leading progress indicator
(5) expand a yankpad/yasnippet element which is inserted at the top of the body of the heading"
    (interactive)
    (org-toggle-tag "project" 'on)
    (org-set-property "COOKIE_DATA" "todo recursive")
    (org-back-to-heading t)
    (let* ((title (nth 4 (org-heading-components)))
           (keyword (nth 2 (org-heading-components))))
       (when (and (bound-and-true-p keyword) (string-prefix-p "[" title))
           (message "TODO keyword and progress indicator found")
           )
       (when (and (not (bound-and-true-p keyword)) (string-prefix-p "[" title))
           (message "no TODO keyword but progress indicator found")
           (forward-whitespace 1)
           (insert "NEXT ")
           )
       (when (and (not (bound-and-true-p keyword)) (not (string-prefix-p "[" title)))
           (message "no TODO keyword and no progress indicator found")
           (forward-whitespace 1)
           (insert "NEXT [/] ")
           )
       (when (and (bound-and-true-p keyword) (not (string-prefix-p "[" title)))
           (message "TODO keyword but no progress indicator found")
           (forward-whitespace 2)
           (insert "[/] ")
           )
       )
     (search-forward "

");; goto the first paragraph of the body
     (insert "pchecklist

");; insert snippet name for yankpad project management checklist snippet
     (search-backward "list")
     (org-end-of-line);; goto back to the snippet name
     (yankpad-expand);; expand snippet
)

Personal notes from the implementation task: id:2019-11-08-my-mark-as-project

I found following interesting elisp sources for implementing this function:


You also might be interested to read A Draft Workflow for Advanced Project Management Using Org Mode and Org Edna where this is a part of the proposed project management workflow.

my-org-auto-tag

I got the code and the idea from this stackoverflow page. Invoking this function tags the current headline with words that can also be found in the combined lists of:

  1. my-org-tag-alist
    • defined below just for this function
  2. org-tag-persistent-alist
    • according to standard Org mode usage
  3. org-tag-alist
    • according to standard Org mode usage
(setq my-org-tag-alist (quote (
                              ("Org" . ?@)
                              ("keywords" . ?@)
                              )))

(defun my-org-auto-tag ()
  (interactive)
  (let ((alltags (append my-org-tag-alist org-tag-persistent-alist org-tag-alist))
        (headline-words (split-string (org-get-heading t t)))
        )
    (mapcar (lambda (word) (if (assoc word alltags)
                             (org-toggle-tag word 'on)))
            headline-words))
    )

my-generate-sanitized-alnum-dash-string

(defun my-generate-sanitized-alnum-dash-string(str)
"Returns a string which contains only a-zA-Z0-9 with single dashes
 replacing all other characters in-between them.

 Some parts were copied and adapted from org-hugo-slug
 from https://github.com/kaushalmodi/ox-hugo (GPLv3)."
(let* (;; Remove "<FOO>..</FOO>" HTML tags if present.
       (str (replace-regexp-in-string "<\\(?1:[a-z]+\\)[^>]*>.*</\\1>" "" str))
       ;; Remove URLs if present in the string.  The ")" in the
       ;; below regexp is the closing parenthesis of a Markdown
       ;; link: [Desc](Link).
       (str (replace-regexp-in-string (concat "\\](" ffap-url-regexp "[^)]+)") "]" str))
       ;; Replace "&" with " and ", "." with " dot ", "+" with
       ;; " plus ".
       (str (replace-regexp-in-string
             "&" " and "
             (replace-regexp-in-string
              "\\." " dot "
              (replace-regexp-in-string
               "\\+" " plus " str))))
       ;; Replace German Umlauts with 7-bit ASCII.
       (str (replace-regexp-in-string "[Ä]" "Ae" str t))
       (str (replace-regexp-in-string "[Ü]" "Ue" str t))
       (str (replace-regexp-in-string "[Ö]" "Oe" str t))
       (str (replace-regexp-in-string "[ä]" "ae" str t))
       (str (replace-regexp-in-string "[ü]" "ue" str t))
       (str (replace-regexp-in-string "[ö]" "oe" str t))
       (str (replace-regexp-in-string "[ß]" "ss" str t))
       ;; Replace all characters except alphabets, numbers and
       ;; parentheses with spaces.
       (str (replace-regexp-in-string "[^[:alnum:]()]" " " str))
       ;; On emacs 24.5, multibyte punctuation characters like ":"
       ;; are considered as alphanumeric characters! Below evals to
       ;; non-nil on emacs 24.5:
       ;;   (string-match-p "[[:alnum:]]+" ":")
       ;; So replace them with space manually..
       (str (if (version< emacs-version "25.0")
                (let ((multibyte-punctuations-str "")) ;String of multibyte punctuation chars
                  (replace-regexp-in-string (format "[%s]" multibyte-punctuations-str) " " str))
              str))
       ;; Remove leading and trailing whitespace.
       (str (replace-regexp-in-string "\\(^[[:space:]]*\\|[[:space:]]*$\\)" "" str))
       ;; Replace 2 or more spaces with a single space.
       (str (replace-regexp-in-string "[[:space:]]\\{2,\\}" " " str))
       ;; Replace parentheses with double-hyphens.
       (str (replace-regexp-in-string "\\s-*([[:space:]]*\\([^)]+?\\)[[:space:]]*)\\s-*" " -\\1- " str))
       ;; Remove any remaining parentheses character.
       (str (replace-regexp-in-string "[()]" "" str))
       ;; Replace spaces with hyphens.
       (str (replace-regexp-in-string " " "-" str))
       ;; Remove leading and trailing hyphens.
       (str (replace-regexp-in-string "\\(^[-]*\\|[-]*$\\)" "" str)))
  str)
)

History of this function: id:2019-11-14-Org-Project-Management-Workflow

my-id-get-or-generate

2019-11-14wrote this function to get nice ID properties

I don’t like UUIDs as they tell the user nothing. Therefore, I generate ID properties like slugs.

You may want to read this reddit discussion for alternative methods to generate nice IDs.

(defun my-id-get-or-generate()
"Returns the ID property if set or generates and returns a new one if not set.
 The generated ID is stripped off potential progress indicator cookies and
 sanitized to get a slug. Furthermore, it is prepended with an ISO date-stamp
 if none was found before."
    (interactive)
        (when (not (org-id-get))
            (progn
               (let* (
                      (my-heading-text (nth 4 (org-heading-components)));; retrieve heading string
                      (my-heading-text (replace-regexp-in-string "[[][0-9%/]+[]] " "" my-heading-text));; remove progress indicators like "[2/7]" or "[25%]"
                      (new-id (my-generate-sanitized-alnum-dash-string my-heading-text));; get slug from heading text
                     )
                   ;;(message (concat "HEADING: " my-heading-text))
                   (when (not (string-match "[12][0-9][0-9][0-9]-[01][0-9]-[0123][0-9]-.+" new-id))
                           ;; only if no ISO date-stamp is found at the beginning of the new id:
                           (setq new-id (concat (format-time-string "%Y-%m-%d-") new-id)))
                   (org-set-property "ID" new-id)
                   )
                 )
        )
        (kill-new (concat "id:" (org-id-get)));; put ID in kill-ring
        (org-id-get);; retrieve the current ID in any case as return value
)

(bind-key (kbd "I") #'my-id-get-or-generate my-map)

History of this function: id:2019-11-14-Org-Project-Management-Workflow

my-org-tree-to-indirect-buffer

This beautiful piece of code was done by alphapapa and published on reddit. Its purpose is to provide more than one indirect buffer when using org-tree-to-indirect-buffer() (via C-c C-x b). Further more, it has a different way of naming these buffers.

Using an advice, the original function gets overwritten.

(defun my-org-tree-to-indirect-buffer (&optional arg)
  "Create indirect buffer and narrow it to current subtree.
The buffer is named after the subtree heading, with the filename
appended.  If a buffer by that name already exists, it is
selected instead of creating a new buffer."
  (interactive "P")
  (let* ((new-buffer-p)
         (pos (point))
         (buffer-name (let* ((heading (org-get-heading t t))
                             (level (org-outline-level))
                             (face (intern (concat "outline-" (number-to-string level))))
                             (heading-string (propertize (org-link-display-format heading)
                                                         'face face)))
                        (concat heading-string "::" (buffer-name))))
         (new-buffer (or (get-buffer buffer-name)
                         (prog1 (condition-case nil
                                    (make-indirect-buffer (current-buffer) buffer-name 'clone)
                                  (error (make-indirect-buffer (current-buffer) buffer-name)))
                           (setq new-buffer-p t)))))
    (switch-to-buffer new-buffer)
    (when new-buffer-p
      ;; I don't understand why setting the point again is necessary, but it is.
      (goto-char pos)
      (rename-buffer buffer-name)
      (org-narrow-to-subtree))))

(advice-add 'org-tree-to-indirect-buffer :override 'my-org-tree-to-indirect-buffer)

my-refile-recache

2020-02-12written by myself to clear and re-fill the refile cache
(defun my-refile-recache ()
  "Clears and re-populates the org-refile-cache"
  (interactive)
  (setq my-refile-recache-start-time (current-time))

  (save-some-buffers t) ;; get latest refile targets
  (org-refile-cache-clear) ;; Clear the target cache. Caching of refile targets can be turned on by setting org-refile-use-cache. To make the command see new possible targets, you have to clear the cache with this command.
  (setq org-refile-target-table (org-refile-get-targets))

  (setq current-timestamp
    (concat
      (format-time-string "%Y-%m-%dT%T")
      ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5)))
      (format-time-string "%z"))))
  (my-log-misc (format-message "my-refile-recache-start-time took %.2fs" (float-time (time-subtract (current-time) my-refile-recache-start-time))))
  (when (> (string-to-number (emacs-uptime "%m")) 2) ;; only flash when not part of the boot process (= Emacs runs longer than 2 minutes)
     (my-flash (format-message "Refile re-cache took %.2fs"                 (float-time (time-subtract (current-time) my-refile-recache-start-time)))))
)

my-delete-next-collapsed-property-drawer

2020-04-23Added to clean up misc Org files
(defun my-delete-next-collapsed-property-drawer()
   "isearch-forward → \":PROPERTIES:\" → remove line (with collapsed drawer)"
    (search-forward ":PROPERTIES:")
    (beginning-of-line)
    (org-kill-line)
    (org-kill-line)
)

my-org-retrieve-url-from-point → C-c o

2020-05-18added

I wanted a function that does not open an web URL within Org mode (via C-c C-o) but rather copies its URL to the system clipboard for non-Emacs apps to paste.

Lucky me, I found the ready-to-use solution on this page which I bind to previously unused C-c o:

(defun my-org-retrieve-url-from-point ()
  (interactive)
  (let* ((link-info (assoc :link (org-context)))
         (text (when link-info
                 ;; org-context seems to return nil if the current element
                 ;; starts at buffer-start or ends at buffer-end
                 (buffer-substring-no-properties (or (cadr link-info) (point-min))
                                                 (or (caddr link-info) (point-max))))))
    (if (not text)
        (error "Not in org link")
      (add-text-properties 0 (length text) '(yank-handler (my-yank-org-link)) text)
      (kill-new text))))
(global-set-key (kbd "C-c o") 'my-org-retrieve-url-from-point)

my-webarchive-tsfile

2020-12-28initial version (see this internal id)

This is basically a file-picker for a specific directory that holds HTML files of all of my visited web pages I archive via SingleFileZ. The function then inserts a “tsfile:” link. Look for other occurances of “tsfile” in this file for further explanation on “tsfile” or read this.

I added a cache for the list of files to minimize unnecessary re-reading of the (long) directory. This cache gets invalidated and updated when one of the following conditions occur:

  1. there was no previous invocation
  2. the last function invocation (not cache update!) is older than 90 seconds
  3. FUTURE IDEA: the universal argument is given
    • not implemented yet because I call this function from the org hydra only which would require a second hydra entry for the call with the universal argument.
(defun my-webarchive-tsfile ()
  "Asks for a file name within the webarchive dir and returns a tsfile-link of the basename"
  (interactive)
  ;; NOTE: my-webarchive-tsfile-dir-path is defined in the section where system-specific paths are defined in general
  ;; check if updating the filename cache is necessary:
  (when (or
         (not (boundp 'my-webarchive-tsfile-file-list))
         (not (boundp 'my-webarchive-tsfile-last-invocation-time))
         (eq my-webarchive-tsfile-file-list nil)
         (< 90.0 (float-time (time-since my-webarchive-tsfile-last-invocation-time)))
         )
    (progn
      (message (concat "Re-reading the list of files from " my-webarchive-tsfile-dir-path))
      (setq my-webarchive-tsfile-file-list (f-files my-webarchive-tsfile-dir-path)))
    )
  ;; ask the user for a file:
  (setq myfile (helm-basename (helm-comp-read "Which webarchive file:" my-webarchive-tsfile-file-list)))
  ;; save the current time in order to compare it next invocation:
  (setq my-webarchive-tsfile-last-invocation-time (current-time))
  ;; insert the custom link to the current position:
  (insert (concat "[[tsfile:" myfile "][" myfile "]]"))
  )

my-mark-block

2021-07-06Marks the current block at point including BEGIN and END lines.

Just like org-babel-mark-block but for all block types (between #+BEGIN_ and #+END_) and it marks including the BEGIN and END lines. It’s not clever enough to detect quoted block begin/end strings.

(defun my-mark-block()
  "marks the block at point including BEGIN and END lines."
  (interactive)
  ;; you don't want to use save-excursion here since it resets your point, not staying at the located begin of block position.
  (search-forward (concat "#+" "END_") nil t);; go to end of the block
  (end-of-line)
  (set-mark-command nil)
  (search-backward (concat "#+" "BEGIN_") nil t);; go to start of the block
  (setq deactivate-mark nil)
  )

(bind-key "b" 'my-mark-block my-map)

my-rise-update-project-tables

2021-07-10established to update two column view dynamic block tables which takes ~20 minutes somehow (performance)
(defun my-rise-update-project-tables ()
  "Updates the two tables that contain focus and non-focus projects"
  (interactive)
  (save-excursion
      (save-some-buffers t) ;; get latest contact changes
      (setq my-rise-update-project-tables-start-time (current-time))

      (switch-to-buffer "rise.org")
      (beginning-of-buffer)
      (search-forward (concat "Name: RISE " "focus projects"))
      (org-ctrl-c-ctrl-c)

      (search-forward (concat "Name: RISE " "non-focus projects"))
      (org-ctrl-c-ctrl-c)

      ;; log info and inform the user:
      (let ((my-tmp-log-string (format-message "my-rise-update-project-tables took %.1f minutes"
                                   (/ (float-time (time-subtract (current-time) my-rise-update-project-tables-start-time)) 60.0))))
          (my-log-misc my-tmp-log-string)
          (my-flash my-tmp-log-string)
      ))
)

my-replace-id-property

2021-07-31Added to my config
  • Why? https://www.reddit.com/r/orgmode/comments/ouihd3/how_to_modify_searchreplace_an_id_property/

    I do think that many Orgers are changing IDs all the time as long as they tend to keep a human readable ID aligned with a changed heading text.

    When I do have the urge to change an existing ID property which is just used within the same file, I need to close the Org file in Emacs, re-open the buffer either in Emacs in basic mode or in vim, apply search&replace for the ID and re-open it in Emacs/Org mode again.

    The reason is that - by default or at least in my setup - text in link targets is not affected by search&replace.

    Is there a more clever way of doing this?

    Optimum would be something like “change this ID (either by yanking manually, point on property or point on link to an ID) in all agenda files”. But I’m also interested in an improved workaround in comparison to my method above.

alphapapa helped me with a stub which I expanded to an interactive function:

(defun my-replace-id-property ()
"Replaces the ID of the current heading to a different one and replaces all occurrences in agenda files."
(interactive)
  (let* ((my-old-id (org-entry-get nil "ID"))
         (my-new-id (read-string "Enter new ID: " nil nil my-old-id))
         (my-old-target (concat "id:" my-old-id))
         (my-new-target (concat "id:" my-new-id)))
    (org-set-property "ID" my-new-id)
    (org-ql-select (org-agenda-files)
      `(link :target ,my-old-target)
      :action `(save-excursion (cl-loop while (re-search-forward ,my-old-target
                                                                 (org-entry-end-position) t) do
                                                                 (replace-match ,my-new-target t t))))
    ))

As alphapapa pointed out, there is no error handling yet (undo boundaries in each buffer). If you know how to implement this properly, please do submit a pull request.

org-mode-hook

Set some modes when openening a file in Org-mode:

(add-hook 'org-mode-hook
          (lambda ()
            ;; yasnippet
            ;;disabled;            (make-variable-buffer-local 'yas/trigger-key)
            ;;disabled;            (org-set-local 'yas/trigger-key [tab])
            ;;disabled;            (define-key yas/keymap [tab] 'yas/next-field-group)
            ;; flyspell mode for spell checking everywhere
            ;;disabled; (flyspell-mode 1)
            ;; auto-fill mode on
            (auto-fill-mode 1)))

Make TAB the yas trigger key in the org-mode-hook and enable flyspell mode and autofill:

(add-hook 'org-mode-hook
          (lambda ()
            ;; flyspell mode for spell checking everywhere
            ;;disabled; (flyspell-mode 1)
            ;; Undefine C-c [ and C-c ] since this breaks my org-agenda files when directories are include
            ;; It expands the files in the directories individually
            (org-defkey org-mode-map "\C-c["    'undefined)
            (org-defkey org-mode-map "\C-c]"    'undefined)
            ;;            (local-set-key (kbd "C-c M-o") 'bh/mail-subtree)
            )
          )

Opening image files with external viewer:

(add-hook 'org-mode-hook
          '(lambda ()
             (setq org-file-apps
                   (append '(
                             ("\\.png\\'" . default)
                             ("\\.jpg\\'" . default)
                             ("\\.jpeg\\'" . default)
                             ("\\.tiff\\'" . default)
                             ("\\.doc\\'" . default)
                             ("\\.docx\\'" . default)
                             ("\\.xlsx\\'" . default)
                             ("\\.pptx\\'" . default)
                             ) org-file-apps ))))

TODO keywords and faces

Define my default keywords:

(setq org-todo-keywords (quote
                         (
                          (sequence "TODO(t)" "NEXT(n)" "STARTED(s)" "WAITING(w@/!)" "SOMEDAY(S!)" "|" "DONE(d!/!)" "CANCELLED(c@/!)")
                          )
                         )
      )

Define the style of the keywords:

(setq org-todo-keyword-faces
      (quote (("TODO"      :foreground "lightblue"    :weight bold)
              ("NEXT"      :foreground "red"          :weight bold)
              ("STARTED"   :foreground "red"          :weight bold)
              ("DONE"      :foreground "forest green" :weight bold)
              ("WAITING"   :foreground "orange"       :weight bold)
              ("TEAM"      :foreground "orange"       :weight bold)
              ("SOMEDAY"   :foreground "magenta"      :weight bold)
              ("CANCELLED" :foreground "forest green" :weight bold)
              ("QUOTE"     :foreground "red"          :weight bold)
              ("QUOTED"    :foreground "magenta"      :weight bold)
              ("APPROVED"  :foreground "forest green" :weight bold)
              ("EXPIRED"   :foreground "forest green" :weight bold)
              ("REJECTED"  :foreground "forest green" :weight bold)
              ("OPEN"      :foreground "blue"         :weight bold)
              ("CLOSED"    :foreground "forest green" :weight bold)
              ("PHONE"     :foreground "forest green" :weight bold))))

«Non-nil means use the fast todo selection scheme with ‘C-c C-t’. This variable describes if and under what circumstances the cycling mechanism for TODO keywords will be replaced by a single-key, direct selection scheme.» https://www.gnu.org/software/emacs/manual/html_node/org/TODO-basics.html

(setq org-use-fast-todo-selection t)

«Non-nil means switching TODO states with S-cursor counts as state change. This is the default behavior. However, setting this to nil allows a convenient way to select a TODO state and bypass any logging associated with that.» https://www.gnu.org/software/emacs/manual/html_node/org/TODO-basics.html

(setq org-treat-S-cursor-todo-selection-as-state-change nil)

CANCELED -> add ARCHIVE-tag: http://article.gmane.org/gmane.emacs.orgmode/64852

  • disabled 2015-12-07
(setq org-todo-state-tags-triggers
      (quote (("CANCELLED"
         ("ARCHIVE" . t))
        ("WAITING"
         ("WAITING" . t))
        (done
         ("WAITING"))
        ("TODO"
         ("WAITING")
         ("CANCELLED"))
        ("NEXT"
         ("WAITING"))
        ("STARTED"
         ("WAITING"))
        ("DONE"
         ("WAITING")
         ("CANCELLED")))))

Change font for DONE tasks

(setq org-fontify-done-headline t)
(custom-set-faces
 '(org-done ((t (:foreground "PaleGreen"
                 :weight normal
                 :strike-through t))))
 '(org-headline-done
            ((((class color) (min-colors 16) (background dark))
               (:foreground "LightSalmon" :strike-through t)))))

Tagging

Tags with fast selection keys http://orgmode.org/org.html#Setting-tags

(setq org-tag-alist (quote (
                            ;;("Kommunikation" . ?k)
                            ("Besorgung" . ?B)
                            ("issue" . ?i)
                            ;;("nonComputer" . ?n)
                            ;;("fitness" . ?f)
                            (:startgroup)
                            ("@BWG" . ?b)
                            ;;("@Infonova" . ?i)
                            ;;("@out_of_town" . ?o)
                            ;;("@FHStP" . ?F)
                            ;;("@Ebreichsdorf" . ?e)
                            ;;("@TUG" . ?t)
                            (:endgroup)
                            ;;(:startgroup)
                            ;;("private" . ?p)
                            ;;("public" . ?P)
                            ;;(:endgroup)
                            (:startgroup)
                            ;;("bigRock" . ?b)
                            ("MIT" . ?m)
                            ("lp" . ?l)
                            ("reward" . ?r)
                            ("focus" . ?f)
                            (:endgroup)
                            )))

Allow setting single tags without the menu http://orgmode.org/org.html#Setting-tags

(setq org-fast-tag-selection-single-key (quote expert))

my-set-tags-including-inherited

The problem: when I do have the following heading structure and I export “My Project”, e.g., to HTML, the tags projectX and @Peter are not associated to “My Task”:

* My Project           :projectX:
** My Workpackage        :@Peter:
*** My Task                 :foo:

Within Org-mode, tag inheritance works perfectly. However, the export modules do not consider tag inheritance at all. This way, “My Task” does not get the tags projectX and @Peter.

When invoking the following function when the cursor is on a heading, all inherited tags get written to the heading. In the example above, when invoking on the heading “My Task”, the end result would be:

* My Project           :projectX:
** My Workpackage        :@Peter:
*** My Task        :projectX:@Peter:foo:
(defun my-set-tags-including-inherited ()
  (interactive)
  (let (
        (alltags (org-get-tags-at))
        ;(ignored-tags '(ISAE3402 2del crypt))
        )

    ;; 2018-01-23: any method I tried to remove certain tags did not work due to my inability to filter according to strings:
    ;; example string: (#("ISAE3402" 0 8 (inherited t)) #("test1" 0 5 (inherited t)) #("foobar" 0 6 (inherited t)) #("test2" 0 5 (inherited t)) #("baz" 0 3 (inherited t)))

    ;;(delete 'ISAE3402 alltags)
    ;; remove "a" from al, using equal as the test, applied to the car of each element
;    (setq alltags
    ;(remove* "ISAE3402" alltags :test 'equal :key 'get-text-property)
                                        ; 'get-text-property
                                        ; 'car
                                        ;)
    (org-set-tags alltags)
    )
  )

Capture

http://orgmode.org/manual/Capture.html «Capture lets you quickly store notes with little interruption of your work flow.»

One of my most used Org-mode features - a simple must-have.

My general inbox for Org-mode is my inbox.org file. It mostly gets new headings from MobileOrg but I also fill it from other sources: emails, manual editing in vim, …

Setting it up: http://orgmode.org/org.html#Setting-up-capture

(setq org-default-notes-file (concat my-org-files-path "inbox.org"))
(define-key global-map "\C-cc" 'org-capture)

Capture tricks

http://storax.github.io/blog/2016/05/02/org-capture-tricks/

  • See id:2016-05-05-yasnippet-like-capture-templates
 * JIRA Ticket %(my-capture-promt "JIRA Project" 'jr-prj)-%(my-capture-promt "JIRA Ticket No." 'jr-no)
 For project %(my-capture-insert 'jr-prj) I have to do the following stuff:
 %(my-capture-optional "triage" (format
  "** Triage %s-%s
 Do the triage."
  jr-prj jr-no))
 %(my-capture-optional "implementation" (format
  "** Implement %s-%s
 Implement stuff
 - [ ] Tests pass?"
  jr-prj jr-no))

my-capture-* - Functions for prompting for different things

(defvar my-capture-promt-history nil
  "History of prompt answers for org capture.")

(defun my-capture-prompt (prompt variable)
  "PROMPT for string, save it to VARIABLE and insert it."
  (make-local-variable variable)
  (set variable (read-string (concat prompt ": ") nil my-capture-promt-history)))

(defun my-capture-prompt-date (prompt variable)
  "PROMPT for a date, save it to VARIABLE and insert it."
  (make-local-variable variable)
  (set variable
       (format-time-string
        (org-time-stamp-format nil nil)
        (org-read-date nil t nil prompt))
       ))

(defun my-capture-insert (variable)
  "Insert content of VARIABLE."
  (symbol-value variable))

(defun my-capture-optional (what text)
  "Ask user to include WHAT.  If user agrees return TEXT."
  (when (y-or-n-p (concat "Include " what "?"))
    text))

(defun my-capture-selection (list variable)
  "Let the user choose between a pre-defined set of strings"
  (make-local-variable variable)
  (let ((selected-value (ido-completing-read "Select from list: " list)))
    (set variable selected-value)
    selected-value)
  )

org-capture-templates - Prelude

A shortcut for a simple heading with keyword NEXT which will be used multiple times below:

(setq my-capture-template-next "* NEXT %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n")

A test capture template:

  (setq my-capture-template-test "** Capture test

- Entering values: %(my-capture-prompt \"Please enter FOO\" 'my-foo) %(my-capture-prompt \"Please enter BAR\" 'my-bar)
- Entering a date: %(my-capture-prompt-date \"Enter a date\" 'my-date)
- Selection: %(my-capture-selection '(\"one\" \"two\" \"three\") 'my-number)
- Optional: %(my-capture-optional \"an optional snippet\" \"The content for the optional thing\")

Re-using:
- Here comes %(my-capture-insert 'my-foo) and %(my-capture-insert 'my-bar)
- The date: %(my-capture-insert 'my-date)
- Your number choice: %(my-capture-insert 'my-number)

\n\n")

Using test org-capture-templates:

(setq org-capture-templates
`(
  ("1" "first version with string" entry (file+headline (concat my-org-files-path "misc.org") "shorts")
   "* NEXT %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n" :empty-lines 1)
  ("2" "second version with variable" entry (file+headline (concat my-org-files-path "misc.org") "shorts")
   ,my-capture-template-next :empty-lines 1)
        ))

org-capture-templates

BEGIN of the templates:

(setq org-capture-templates
      `(

My general templates:

("s" "shorts-todo" entry (file+headline ,(concat my-org-files-path "misc.org") "shorts")
 ,my-capture-template-next :empty-lines 2)
("e" "Event" entry (file+headline ,(concat my-org-files-path "misc.org") "Events")
 "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n" :empty-lines 2)
("b" "Bookmark" entry (file+headline ,(concat my-org-files-path "notes.org") "Bookmarks")
 "* %x%?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n" :empty-lines 2)
("p" "public voit" entry (file+headline ,(concat my-org-files-path "public_voit.org") "Unfinished (non-series, non-persistent)")
 "* NEXT %?        :blog:%^g\n:PROPERTIES:\n:CREATED: %U\n:ID: %^{prompt}\n:END:\n\n-----------------------\n- [ ] link on older/similar articles?\n- [ ] link on tag pages?\n\n" :empty-lines 2)
("a" "anzuschauen" entry (file+headline ,(concat my-org-files-path "misc.org") "Anzuschauen")
 "* NEXT %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n%x\n\n" :empty-lines 2)
("B" "Besorgung" entry (file+headline ,(concat my-org-files-path "hardware.org") "Besorgungen")
 ,my-capture-template-next :empty-lines 2)

Hardware templates:

("h" "hardware")
("hs" "sting" entry (file+olp ,(concat my-org-files-path "hardware.org") "Inventar" "intel NUC (<2015-07-25 Sat>, € 486.84, e-tec)" "shorts")
 ,my-capture-template-next :empty-lines 2)
("hf" "floyd" entry (file+olp ,(concat my-org-files-path "hardware.org") "Inventar" "lenovo Thinkpad X260 (<2016-03-22 Tue>, 899€, u:book)" "shorts")
 ,my-capture-template-next :empty-lines 2)
("hp" "RasPlay" entry (file+olp ,(concat my-org-files-path "hardware.org") "Inventar" "Raspberry Pi 2 Model B (<2015-06-29 Mon>, 38€, Pollin.de)")
 ,my-capture-template-next :empty-lines 2)
;;old;;("hb" "blanche" entry (file+olp "~/org/hardware.org" "Inventar" "Mac Mini mit OS X 10.5 (2009-0?0??)" "shorts")
;;old;; "* NEXT %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n" :empty-lines 2)
("hw" "Winora T3" entry (file+olp ,(concat my-org-files-path "hardware.org") "Inventar" "Fahrrad: Winora T3 ([[contact:Kotnik][Kotnik]], 2464€, <2013-08-02 Fri>)")
 ,my-capture-template-next :empty-lines 2)

Templates for my home:

("w" "Breitenweg")
("ws" "Breitenweg shorts" entry (file+headline ,(concat my-org-files-path "bwg.org") "shorts")
 ,my-capture-template-next :empty-lines 2)
("we" "Breitenweg event" entry (file+headline ,(concat my-org-files-path "bwg.org") "Events")
 "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n" :empty-lines 2)
;;old;;("wa" "Breitenweg Ausgaben" table-line (file+headline "~/org/bwg.org" "getätigte Ausgaben") "| %t | %? ||||")

Company templates:

      ("r" "RISE")
("rs" "shorts" entry (file+headline ,(concat my-org-files-path "rise.org") "shorts")
       ,my-capture-template-next :empty-lines 2)
      ("re" "event" entry (file+headline ,(concat my-org-files-path "rise.org") "Events")
       "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n" :empty-lines 2)
      ("ro" "RB onboarding" entry (file+headline ,(concat my-org-files-path "rise.org") ,my-business-rbos-heading)
       ,my-business-rbo-template :empty-lines 2)
      ("rO" "RB offboarding" entry (file+headline ,(concat my-org-files-path "rise.org") ,my-business-rbos-heading)
       ,my-business-rboff-template :empty-lines 2)

Template for my lecture:

("f" "FH St. Pölten shorts" entry (file+headline ,(concat my-org-files-path "fhsp.org") "shorts")
 ,my-capture-template-next :empty-lines 2)

Put it in the inbox, refile it later:

("I" "inbox, refile later" entry (file ,(concat my-org-files-path "inbox.org"))
 "\n* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n" :empty-lines 2)
("W" "WWW: inbox, refile later" entry (file ,(concat my-org-files-path "inbox.org"))
 "* %a :website:\n\n%U %?\n\n%:initial\n" :empty-lines 2)

Old templates for the records:

("x" "xlog")
("xf" "xlog FNS" table-line (id "xlog-fns-id") "| %T |")
("xz" "xlog ZNS" table-line (id "xlog-zns-id") "| %T |")
("xh" "xlog hometrainer" table-line (id "xlog-hometrainer") "| %T |  |  |  |")
("xb" "xlog Bettwäsche" table-line (id "xlog-bettwaesche-id") "| %T |  |  |  |  |")
("xg" "xlog Gewicht" table-line (id "xlog-gewicht") "| %T |  |")
("xr" "Reinigung Geschirrspüler" table-line (id "xlog-Geschirrspuelerreinigung") "| %T |")
("xp" "Pollenallergie Symptome" table-line (id "ad5f7363-e280-4566-912d-1fb5699725da") "| %T |")
("xt" "Pollenallergie Tabletteneinnahme" table-line (id "b718be27a93a35207bac9b18ec390cc3") "| %T |")
("xG" "elmex grün" table-line (id "d705cdf9-40e5-4677-9662-e0e17d05798f") "| %T |")
("xR" "elmex rot" table-line (id "fbd9be0e-5077-4ba9-89eb-6041f945991a") "| %T |")
("xD" "dentalux Complex 3" table-line (id "2013-08-06-detalux3") "| %T |")
("xk" "Keyboard Akkus leer" table-line (id "3407c9b7-1b41-443b-9254-32c4af3a54e8") "| %T |")
("xx" "xlogtest" table-line (file+headline ,(concat my-org-files-path "misc.org") "xlogtest2012-06-17") "| %T |")

Test template:

("X" "test" entry (file+headline ,(concat my-org-files-path "misc.org") "Tests")
 ,my-capture-template-test :empty-lines 1)

END of the templates:

  )
)

Moving web bookmarks from inbox.org to notes.org → my-map b

2021-07-06Not used for quite some time → disabled

Smart moving bookmark headings from inbox.org to notes.org

  (defun my-save-bookmark()
    "removes NEXT/Bookmark, (NOT YET: FIXXME: retrieves title),
move time-stamp to CREATED, re-file to bookmarks, invoke Org-mode tagging process"
    (interactive)
    (save-excursion
      ;; get myself to the beginning of the current heading:
      ;;(outline-previous-visible-heading 1)  ;; jump to previous heading
      ;;(outline-next-visible-heading 1)      ;; jumps to beginning of the current (interesting) heading
      (beginning-of-line)                   ;; jump to beginning of line
      (let ((mybegin (point)))              ;; mark beginning of line as start point
        (outline-next-visible-heading 1)    ;; jumps to EOF if it is the last entry
        (save-restriction
          (narrow-to-region mybegin (point))  ;; ignore everything outside of region
          ;; search/replace unwanted keywords at the beginning:
          (goto-char (point-min))
          (while (search-forward "* NEXT Bookmark " nil t) (replace-match "* " nil t))
          (goto-char (point-min))
;;    (join-line -1) ;; join line because with capturing via NewsBlur app, the content starts in line 2
;;        (goto-char (point-min))
          (while (search-forward "* NEXT " nil t) (replace-match "* " nil t))
          (goto-char (point-min))
          (while (search-forward "* Bookmark " nil t) (replace-match "* " nil t))
          (goto-char (point-min))
          (while (search-forward "//m.heise.de" nil t) (replace-match "//heise.de" nil t));; remove mobile heise URL
          (goto-char (point-min))
          (while (search-forward "/from/atom10?wt_mc=rss.ho.beitrag.atom" nil t);; remove heise RSS tags
            (replace-match "" nil t)
            )
          (goto-char (point-min))
          (while (search-forward "?wt_mc=rss.ho.beitrag.atom" nil t);; remove heise RSS tags
            (replace-match "" nil t)
            )
          (goto-char (point-min))
          ;; insert second asterisk (modify to second level heading)
          (insert "*")
          ;; move time-stamp to properties-drawer:
          (search-forward-regexp "^\\[20")  ;; jump to second line (with time-stamp) via search
          (beginning-of-line)
          (insert ":PROPERTIES:\n:CREATED:  ")
          (end-of-line)
          (newline)
          (insert ":END:\n")
          ;; move region to end of notes.org
          (kill-region mybegin (point)) ;; kill region to kill-ring
          (switch-to-buffer "notes.org")
          (end-of-buffer)
          (newline)
          (yank)
          ;; add tags
          (outline-previous-visible-heading 1)  ;; jump to heading
          (org-set-tags-command)
          )
        )
      )
    )

  (bind-key "b" 'my-save-bookmark my-map)

Mobile capture

General OrgMobile setup:

(setq org-directory "~/org")
(setq org-mobile-directory my-org-files-path)
(setq org-mobile-inbox-for-pull (concat my-org-files-path "inbox.org"))

Do not generate IDs for all headings: http://orgmode.org/manual/Pushing-to-MobileOrg.html

(setq org-mobile-force-id-on-agenda-items nil)

my-mobile-org-import() → my-map i

On my Android phone, I use MobileOrg to capture stuff. Following binding brings me the most current captured items into my inbox.org:

(defun my-merge-mobileorg-inbox-files-to-mobileorg-file () 
  "Merges individual inbox files from different hosts and appends their content to the mobileorg.org file." 
  (let ((my-mobileorg-files `( ,(concat my-org-files-path "mobileorg-pixel4a.org") 
                               ,(concat my-org-files-path "mobileorg-dylan.org"))) 
        (my-mobileorg-result-file (concat my-org-files-path "mobileorg.org")))

    (find-file my-mobileorg-result-file) ;; open mobileorg.org
    (goto-char (point-max)) ;; go to the end of the buffer (for appending content)

    (dolist (file my-mobileorg-files) ;; loop over all input files and copy content to mobileorg.org
      (when (file-regular-p file) 
        (insert-file-contents file)))
  
    (save-buffer) ;; save all new changes to mobileorg.org
    (kill-buffer) ;; close mobileorg.org buffer

    (dolist (file my-mobileorg-files) ;; loop over all input files for deleting their content which already got moved to mobileorg.org above
      (when (file-regular-p file) 
        (find-file file) 
        (delete-region (point-min) (point-max)) 
        (save-buffer) 
        (kill-buffer)))))
(defun my-mobile-org-import ()
  "Imports mobile-org-data from mobile-org to inbox.org and openes inbox.org"
  (interactive "P")
  (my-merge-mobileorg-inbox-files-to-mobileorg-file) ;; Merges individual inbox files from different hosts and appends their content to the mobileorg.org file.
  (org-mobile-pull)
  (find-file (concat my-org-files-path "inbox.org"))
  (delete-trailing-whitespace)
  )
(bind-key "i" (lambda ()
                         """foobar"""
                         (interactive) (my-mobile-org-import)) my-map )

Note that even though I use Orgzly to view Org-mode data on my Android phone, I use MobileOrg to capture. This might change in future, when I am able to choose whether or not single SyncThing folders gets synced on WiFi or on 4G networks (instead of all or nothing). Take a look at my feature wish report and the other issue I was referred to.

my-org-mobile-push() - pushing to org-mobile

The function generates misc files for MobileOrg.

(defun my-org-mobile-push (&optional arg)
  (interactive)
  ;; when called with universal argument (C-u), Emacs will be closed
  ;;      after pushing to files
  ;; save original agenda in temporary variable
  (setq ORIGSAVED-org-agenda-custom-commands org-agenda-custom-commands)
  ;; set agenda for MobileOrg (omit some agenda
  ;; views I do not need on my phone):
  (setq org-agenda-custom-commands
        (quote (

                ("1" "1 month"
                 ((agenda "1 month"
                          ((org-agenda-ndays 31)
                           (org-agenda-time-grid nil)
                           (org-agenda-entry-types '(:timestamp :sexp))
                           )
                          )))

                ("B" "borrowed" tags "+borrowed"
                 (
                  (org-agenda-overriding-header "borrowed or lend")
                  (org-agenda-skip-function 'tag-without-done-or-canceled)
                  ))

                ("$" "Besorgungen" tags "+Besorgung"
                 (
                  (org-agenda-overriding-header "Besorgungen")
                  (org-agenda-skip-function 'tag-without-done-or-canceled)
                  ))

                )))
  ;; generate MobileOrg export:
  (org-mobile-push)
  ;; restore previously saved agenda:
  (setq org-agenda-custom-commands
        ORIGSAVED-org-agenda-custom-commands)
  (if (equal arg '(4))
      ;; save buffers and exit emacs;; FIXXME: not working yet
      (save-buffers-kill-terminal 't)
    )
  )

MobileOrg push → my-map I

As of 2017-04, I moved from MobileOrg to Orgzly for mobile viewing data within my Org-mode data. Therefore, this function is not of any use any more:

(bind-key "I" #'my-org-mobile-push my-map)

Refiling

Targets include this file and any file contributing to the agenda - up to 5 levels deep

(setq org-refile-targets (quote (
                                 ;; ignore my-org-memacs-files here
                                 (my-work-agenda-files :maxlevel . 4)
                                 (my-nonwork-agenda-files :maxlevel . 4)
                                 ;;OLD: (nil :maxlevel . 3)
                                 ;;OLD: ("contacts.org" :maxlevel . 6)
                                 )))

Targets start with the file name - allows creating level 1 tasks

(setq org-refile-use-outline-path (quote file))

Activate caching of targets: (a must-have)

(setq org-refile-use-cache t)

Targets complete directly with IDO: so much better!

(setq org-outline-path-complete-in-steps nil)

Allow refile to create parent tasks with confirmation:

(setq org-refile-allow-creating-parent-nodes (quote confirm))

Refiling to a specific heading stolen from this page:

(defun my-org-refile (file headline &optional arg)
  (let ((pos (save-excursion
               (find-file file)
               (org-find-exact-headline-in-buffer headline))))
    (org-refile arg nil (list headline file nil pos)))
  (switch-to-buffer (current-buffer)))

;; example:
;; (my-org-refile "misc.org" "Off-site-backup")

Attaching

(setq org-attach-use-inheritance t)
(setq org-attach-preferred-new-method 'dir)
(setq org-attach-archive-delete nil)

As of 2019-12-08, org-attach-git does have an issue:

cd: No such directory found via CDPATH environment variableInvalid face reference: t

I did not invest much in finding the reason. So it’s disabled for now:

(require 'org-attach-git)

org-attach-insert

2021-08-09Found this nugget on reddit
(defun my-org-attach-insert (&optional in-emacs)
  "Insert attachment from list."
  (interactive "P")
  (let ((attach-dir (org-attach-dir)))
    (if attach-dir
    (let* ((file (pcase (org-attach-file-list attach-dir)
               (`(,file) file)
               (files (completing-read "Insert attachment: "
                           (mapcar #'list files) nil t))))
           (path (expand-file-name file attach-dir))
               (desc (file-name-nondirectory path)))
          (let ((initial-input
             (cond
              ((not org-link-make-description-function) desc)
              (t (condition-case nil
                 (funcall org-link-make-description-function link desc)
               (error
                (message "Can't get link description from %S"
                     (symbol-name org-link-make-description-function))
                (sit-for 2)
                nil))))))
        (setq desc (if (called-interactively-p 'any)
                   (read-string "Description: " initial-input)
                 initial-input))
            (org-insert-link nil path (concat "attachment:" desc))))
      (error "No attachment directory exist"))))
;; (define-key org-mode-map (kbd "C-c o i") #'org-attach-insert)

Archiving - preserve top level node and tags when archiving

preserving one level of heading + tags when archiving

2020-02-03disabled because I switched to org-archive-subtree-hierarchically()

When I archive a heading (and its sub-headings), it gets moved from foo.org to foo.org_archive. Following code does preserve at least the top level node so that the archive file gets the rough structure of the non-archive file.

http://orgmode.org/worg/org-hacks.html#sec-1-7-1

(defun my-org-inherited-no-file-tags ()
  (let ((tags (org-entry-get nil "ALLTAGS" 'selective))
        (ltags (org-entry-get nil "TAGS")))
    (mapc (lambda (tag)
            (setq tags
                  (replace-regexp-in-string (concat tag ":") "" tags)))
          (append org-file-tags (when ltags (split-string ltags ":" t))))
    (if (string= ":" tags) nil tags)))
(defadvice org-archive-subtree (around my-org-archive-subtree-low-level activate)
    (let ((tags (my-org-inherited-no-file-tags))
          (org-archive-location
           (if (save-excursion (org-back-to-heading)
                               (> (org-outline-level) 1))
               (concat (car (split-string org-archive-location "::"))
                       "::* "
                       (car (org-get-outline-path)))
             org-archive-location)))
      ad-do-it
      (with-current-buffer (find-file-noselect (org-extract-archive-file))
        (save-excursion
          (while (org-up-heading-safe))
          (org-set-tags tags)))))

preserving all heading levels when archiving

2020-02-03switching from my-org-inherited-no-file-tags() tp this

Preserve the hierarchy when archiving: blog article, source code (GitHub gist)

(setq org-archive-default-command #'org-archive-subtree-hierarchically)

(defun org-archive-subtree-hierarchically (&optional prefix)
  (interactive "P")
  (let* ((fix-archive-p (and (not prefix)
                             (not (use-region-p))))
         (afile  (car (org-archive--compute-location
                       (or (org-entry-get nil "ARCHIVE" 'inherit) org-archive-location))))
         (buffer (or (find-buffer-visiting afile) (find-file-noselect afile))))
    (org-archive-subtree prefix)
    (when fix-archive-p
      (with-current-buffer buffer
        (goto-char (point-max))
        (while (org-up-heading-safe))
        (let* ((olpath (org-entry-get (point) "ARCHIVE_OLPATH"))
               (path (and olpath (split-string olpath "/")))
               (level 1)
               tree-text)
          (when olpath
            (org-mark-subtree)
            (setq tree-text (buffer-substring (region-beginning) (region-end)))
            (let (this-command (inhibit-message t)) (org-cut-subtree)) ; we don’t want to see "Cut subtree" messages
            (goto-char (point-min))
            (save-restriction
              (widen)
              (-each path
                (lambda (heading)
                  (if (re-search-forward
                       (rx-to-string
                        `(: bol (repeat ,level "*") (1+ " ") ,heading)) nil t)
                      (org-narrow-to-subtree)
                    (goto-char (point-max))
                    (unless (looking-at "^")
                      (insert "\n"))
                    (insert (make-string level ?*)
                            " "
                            heading
                            "\n"))
                  (cl-incf level)))
              (widen)
              (org-end-of-subtree t t)
              (org-paste-subtree level tree-text))))))))

Searching, querying

helm-org

2019-12-17initial setup

Completion package for Org mode: https://github.com/emacs-helm/helm-org

Used by: org-ql

(use-package helm-org
  ;;:defer 90
  :ensure t
  :config
  (add-to-list 'helm-completing-read-handlers-alist '(org-capture . helm-org-completing-read-tags))
  (add-to-list 'helm-completing-read-handlers-alist '(org-set-tags . helm-org-completing-read-tags))
)

helm-org-rifle

2020-04-07setup for testing

org-rifle is a swiss army knife for searching within Org mode files. So far, I was using mostly sparse trees, my-search-method-according-to-numlines() (isearch-forward and swiper-isearch) and org-occur.

(use-package helm-org-rifle
  :ensure t
  :defer 110
  :after org
;  :bind (:map my-map ("SPC" . yankpad-insert))
)

helm-org-agenda-files-headings: grep within headings → my-map H

This is a neat and fast way of looking for string only within heading lines:

(bind-key "H" #'helm-org-agenda-files-headings my-map)

peg

2020-12-07switched to a manually downloaded version

peg is required by org-ql (and was installed via ELPA as dependency) but the most recent version I got via list-package was 20150708.641 which caused issues. So I had to set it up via manual download:

(use-package peg
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/peg/")))
)

org-ql

2019-12-17initial setup

A powerful query language for Org mode: https://github.com/alphapapa/org-ql

Make sure that you install org-ql after you have installed helm-org. Otherwise, it may be the case that you don’t get helm-org-ql as this comment suggests and the README of org-ql clearly states.

(use-package org-ql
  :ensure t
  :config
  (require 'org-ql-search) ;; workaround for https://github.com/alphapapa/org-ql/issues/53
)

FIXXME: Workaround in order to make helm-org-ql available according to https://github.com/alphapapa/org-ql/issues/129#issuecomment-667310696:

(require 'org-ql)
(require 'helm-org-ql)

Links

I love customized links. I created a bunch of them in order to link certain kind of data.

Please note that my-business-... variables are not available to you for privacy reasons.

Do not use org-link-abbrev-alist for defining links that are handled via functions. Use org-link-set-parameters instead.

  (setq org-link-abbrev-alist
        `(
          ("bib" . "~/archive/library/%s.bib")
          ("cite" . ,(concat "file:" my-org-files-path "references.org::/%s/"))
                                        ;       ("mynotes" . "file:~/org/references.org::%s")
                                        ;       ("papers" . "~/archive/library/%s.pdf")
          ("photo" . "file:~/people/all_photographs/%s")
          ("notes" . "~/archive/library/%s-notes.pdf")
          ("contact" . ,(concat my-org-files-path "contacts.org::/\*.*%s/"))
;         ("tsfile" . ,(concat my-org-files-path "memacs/files.org_archive::/\*.*%s/")) replaced by org-link-set-parameters() + my-handle-tsfile-link()
          ;; 2020-12-10 old: ("ifile" . ,(concat my-org-files-path "memacs/ifiles.org::/\*.*%s/"))
          ;;("mbox2001" . "file:~/archive/events_memories/backup_2002-06-23/2002-06-23/home/vk/Emails_from_approx_2000-07-01_to_2002-06-24.mbox::/\%s/")
          ;; 2020-12-10 old: ("postings2002" . "file:~/archive/usenet/memacs-archive/2002-03-13_to_2002-06-23_postings_Karl_Voit_usenet::%s")
          ;; 2020-12-10 old: ("postings2001" . "file:~/archive/usenet/memacs-archive/2000-07-06_to_2002-01-28_postings_Karl_Voit_usenet::%s")
          ;;("bank" . "file:~/institutions/easybank/Memacs-easybank-summary.csv::%s")
          ;;("ipd" . "https://r6portal-defects.infonova.com/browse/IPD-%s")
          ;;("IPD" . "https://r6portal-defects.infonova.com/browse/IPD-%s")
          ;;("tfs" . "http://grzd-tfs02:8080/tfs/DefaultCollection/Detego/_workitems?id=%s")
          ;;("TFS" . "http://grzd-tfs02:8080/tfs/DefaultCollection/Detego/_workitems?id=%s")
          ("EPA" . ,(concat my-business-jira-server "/EPA-%s"))
          ("EPAAFO" . ,(concat my-business-jira-server "/EPAAFO-%s"))
          ("JAFO" . ,(concat my-business-jira-server "/EPAAFO-0?jql=project%20%3D%20EPAAFO%20AND%20Afo-ID%20~%20%22%s%22"))
          ("EPARISE" . ,(concat my-business-sa-server "%s"))
          ("DAKEPA" . ,(concat my-business-jira-b-server "DAKEPA-%s"))
          ("EPABETR" . ,(concat my-business-jira-b-server "EPABETR-%s"))
          ("BMTSK" . ,(concat "file:" my-business-bmtsk-path "/"))
          ("IAFO" . ,(concat my-business-jira2-server "/GEMIDPANF-200?jql=project%20%3D%20GEMIDPANF%20AND%20Afo-ID%20~%20%22%s%22"))
          ("ISO" . ,(concat my-business-jira2-server "/ISO-%s"))
          ("ISMS" . ,(concat my-business-jira2-server "/ISMS-%s"))
          ("RB" . ,(concat my-business-jira2-server "/RB-%s"))
          ("GEMIDP" . ,(concat my-business-jira2-server "/GEMIDP-%s"))
          ("GEMIDPANF" . ,(concat my-business-jira2-server "/GEMIDPANF-%s"))
          ("IDP" . ,(concat my-business-sd-server "/IDP-%s"))
          ))

I’ve got the PDF files of my archive only on these hosts:

(when (or (my-system-is-sting) (my-system-is-floyd))
    (add-to-list 'org-link-abbrev-alist '("pdf" . "~/archive/library/%s.pdf"))
)

Custom Link Completion

(defun org-make-link (&rest strings)
  "Concatenate STRINGS."
  (apply 'concat strings))

You might as well be interested in Pragmatic Emacs: Insert internal org-mode links the ivy way

Links to Outlook entities

Please do read my blog article that explains that those links get broken very easily.

(when (my-eval-if-binary-or-warn "outlook")

  (org-add-link-type "outlook" 'org-outlook-open)

  (defun org-outlook-open (id)
    "Open the Outlook item identified by ID.  ID should be an Outlook GUID."
    ;; 2017-03-02: following line stopped working with "org-outlook-open: ShellExecute failed: Access is denied."
    ;;(w32-shell-execute "open" (concat "outlook:" id))
    ;; fix:
    (w32-shell-execute "open"
                       "C:/Program Files/Microsoft Office/Office16/OUTLOOK.EXE"
                       (concat "/select " "outlook:" id))
    )
)

gemSpec links

2020-12-08created

This is business-related:

(defun my-gemAnbT_IDP-Dienst_ATV (afo)
  (start-process "" nil "okular" my-gemAnbT_IDP-Dienst_ATV-pdf "--find" afo)
   "")
(defun my-gemSpec_DS_Anbieter (afo)
  (start-process "" nil "okular" my-gemSpec_DS_Anbieter-pdf "--find" afo)
   "")
(defun my-gemSpec_Net (afo)
  (start-process "" nil "okular" my-gemSpec_Net-pdf "--find" afo)
   "")
(defun my-gemSpec_PKI (afo)
  (start-process "" nil "okular" my-gemSpec_PKI-pdf "--find" afo)
   "")
(defun my-gemSpec_IDP_Dienst (afo)
  (start-process "" nil "okular" my-gemSpec_IDP_Dienst-pdf "--find" afo)
   "")
(defun my-gemLB_FD_IDP (afo)
  (start-process "" nil "okular" my-gemLB_FD_IDP-pdf "--find" afo)
   "")
(defun my-gemRL_Betr_TI (afo)
  (start-process "" nil "okular" my-gemRL_Betr_TI-pdf "--find" afo)
   "")

(org-link-set-parameters "gemAnbT_IDP-Dienst_ATV"
                         :follow #'my-gemAnbT_IDP-Dienst_ATV)
(org-link-set-parameters "gemSpec_DS_Anbieter"
                         :follow #'my-gemSpec_DS_Anbieter)
(org-link-set-parameters "gemSpec_Net"
                         :follow #'my-gemSpec_Net)
(org-link-set-parameters "gemSpec_PKI"
                         :follow #'my-gemSpec_PKI)
(org-link-set-parameters "gemSpec_IDP_Dienst"
                         :follow #'my-gemSpec_IDP_Dienst)
(org-link-set-parameters "gemLB_FD_IDP"
                         :follow #'my-gemLB_FD_IDP)
(org-link-set-parameters "gemRL_Betr_TI"
                         :follow #'my-gemRL_Betr_TI)

;; do NOT use this for links handled by functions! This results in links "opened" on things like line modification, redrawing of screen, ...
;; NOT: (add-to-list 'org-link-abbrev-alist '("gemSpec_DS_Anbieter" . "%(my-gemSpec_DS_Anbieter)"))
;; NOT: (add-to-list 'org-link-abbrev-alist '("gemSpec_Net" . "%(my-gemSpec_Net)"))
;; NOT: (add-to-list 'org-link-abbrev-alist '("gemSpec_PKI" . "%(my-gemSpec_PKI)"))
;; NOT: (add-to-list 'org-link-abbrev-alist '("gemSpec_IDP_Dienst" . "%(my-gemSpec_IDP_Dienst)"))

Reference management: link handling functions

Helper function string-replace (this withthat in)

(defun string-replace (this withthat in)
  "replace THIS with WITHTHAT' in the string IN"
  (with-temp-buffer
    (insert in)
    (goto-char (point-min))
    (replace-string this withthat)
    (buffer-substring (point-min) (point-max))))

org-pdf-complete-link ()

(defun org-pdf-complete-link (&optional arg)
  "Create a papers link using completion."
  (let (file link)
    (setq file (read-file-name "pdf: " "~/archive/library/"))
    (let ((pwd (file-name-as-directory (expand-file-name ".")))
          (pwd1 (file-name-as-directory (abbreviate-file-name
                                         (expand-file-name ".")))))
      (setq file (string-replace "~/archive/library/" "" file))
      (setq file (string-replace pwd "" (string-replace pwd1 "" file)))
      (setq file (string-replace ".bib" "" file))
      (setq file (string-replace ".pdf" "" file))
      (setq link (concat "pdf:" file)))
    link))
(defun org-ref-complete-link (&optional arg)
  "Create a reference link using completion."
  (let (file link)
    (setq file (read-file-name "ref: " "~/archive/library/"))
    (let ((pwd (file-name-as-directory (expand-file-name ".")))
          (pwd1 (file-name-as-directory (abbreviate-file-name
                                         (expand-file-name ".")))))
      (setq file (string-replace "~/archive/library/" "" file))
      (setq file (string-replace pwd "" (string-replace pwd1 "" file)))
      (setq file (string-replace ".bib" "" file))
      (setq file (string-replace ".pdf" "" file))
      (setq link (concat "ref:" file)))
    link))
(defun org-photo-complete-link (&optional arg)
  "Create a reference link using completion."
  (let (file link)
    (setq file (read-file-name "photo: " "~/people/all_photographs/"))
    (let ((pwd (file-name-as-directory (expand-file-name ".")))
          (pwd1 (file-name-as-directory (abbreviate-file-name
                                         (expand-file-name ".")))))
      (setq file (string-replace "~/people/all_photographs/" "" file))
      (setq file (string-replace pwd "" (string-replace pwd1 "" file)))
                                      ;(setq file (string-replace ".jpg" "" file))
                                      ;(setq file (string-replace ".jpeg" "" file))
                                      ;(setq file (string-replace ".tiff" "" file))
      (setq link (concat "photo:" file)))
    link))
(my-load-local-el "contrib/format-bib.el")

handling tsfile links (Memacs)

Defining memacs variables:

(defvar memacs-root (concat my-org-files-path "memacs/"))
(defvar memacs-file-pattern "files.org_archive") ;; also possible: "*.org"

my-handle-tsfile-link (querystring)

  • 2016-12-31 by John Kitchin
(defun my-handle-tsfile-link (querystring)
  (message (concat "DEBUG1: querystring: " querystring))
  (message (concat "DEBUG2: "
                          "grep \""
                          querystring
                          "\" "
                          (concat memacs-root memacs-file-pattern)))
  ;; get a list of hits
  (let ((queryresults (split-string
                       (s-trim
                        (shell-command-to-string
                         (concat
                          "grep \""
                          querystring
                          "\" "
                          (concat memacs-root memacs-file-pattern))))
                       "\n" t)))
    (message (concat "DEBUG3: queryresults: " (car queryresults)))
    ;; check length of list (number of lines)
    (cond
     ((= 0 (length queryresults))
      ;; edge case: empty query result
      (message "Sorry, no results found for query: %s" querystring))
     (t
      (with-temp-buffer
        (insert (if (= 1 (length queryresults))
                    (car queryresults)
                  (completing-read "Choose: " queryresults)))
        (org-mode)
        (goto-char (point-min))
        (org-next-link)
        (org-open-at-point))))))

Setting link parameters:

(org-link-set-parameters
 "tsfile"
 :follow (lambda (path) (my-handle-tsfile-link path))
 :help-echo "Opens the linked file with your default application"
 :face '(:foreground "DarkSeaGreen" :underline t)
)

OLD code:

  (defun my-handle-tsfile-link (querystring)
    ;; get a list of hits
    (let ((queryresults (split-string (replace-regexp-in-string
                                       "\r?\n$" ""
                                       (shell-command-to-string
                                        (concat "grep "
                                                querystring
                                                (concat memacs-root memacs-file-pattern))))
                                      "\n")))

      ;; doesn't work because queryresults is not a string:
      ;; (message "%s" (concat "DEBUG: queryresults: " queryresults))

      ;; check length of list (number of lines)
      (cond
       ((= 0 (length queryresults))
        ;; edge case: empty query result
        (message "Sorry, empty querystring."))

;; I get «split-string: Wrong type argument: stringp, ("")»
       ((= 1 (length (split-string queryresults "\n")))
        ;; queryresults is unique
        (with-temp-buffer
          (insert queryresults)
          (org-mode)
          (org-element-map (org-element-parse-buffer) 'link
            (lambda (ln)
              (when (string= (org-element-property :type ln) "file")
                (org-element-property :path ln)
                (message "%s" (concat "DEBUG: file -> " ln))
                )))))

;; I get the «File: » prompt but no completion:
       (t
        ;; querystring results multiple matches
        (org-open-file (completing-read
                        "File: "
                        (remove-if-not    ;remove nils from list
                         'identity
                         (loop for queryresult in queryresults
                               collect
                               ;; get the filename the match is in. assumes no : in the file name
                               (let* ((f (car (split-string queryresult ":")))
                                      (basedir (file-name-directory f)))
                                 (with-temp-buffer
                                   (insert queryresult)
                                   (org-mode)
                                   (org-element-map (org-element-parse-buffer) 'link
                                     (lambda (ln)
                                       (when (string= (org-element-property :type ln) "file")
                                         (expand-file-name  (org-element-property :path ln) basedir))))))))))))))

links color (OLD)

Don’t know why I disabled this:

(require 's)

(defun color-comp (&optional arg)
  "Completion function for color links."
  (let ((color-data (prog2
                        (save-selected-window
                          (list-colors-display))
                        (with-current-buffer (get-buffer "*Colors*")
                          (mapcar (lambda (line)
                                    (append (list line)
                                            (s-split " " line t)))
                                  (s-split "\n" (buffer-string))))
                      (kill-buffer "*Colors*"))))
    (format "color:%s"
            (s-trim (cadr (assoc (completing-read "Color: " color-data) color-data))))))


(defun color-link-face (path)
  "Face function for color links."
  (or (cdr (assoc path org-link-colors))
      `(:foreground ,path)))


(defun color-link-export (path description backend)
  "Export function for color links."
  (cond
   ((eq backend 'html)
    (let ((rgb (assoc (downcase path) color-name-rgb-alist))
          r g b)
      (setq r (* 255 (/ (nth 1 rgb) 65535.0))
            g (* 255 (/ (nth 2 rgb) 65535.0))
            b (* 255 (/ (nth 3 rgb) 65535.0)))
      (format "<span style=\"color: rgb(%s,%s,%s)\">%s</span>"
              (truncate r) (truncate g) (truncate b)
              (or description path))))))

(org-link-set-parameters "color"
                         :face 'color-link-face
                         :complete 'color-comp
                         :export 'color-link-export)

link colors

2021-01-11moved commands to my-set-linkcolors and defined 3 categories of colors
(setq my-linkcolor-org "wheat3")
(setq my-linkcolor-file "MediumSeaGreen")
(setq my-linkcolor-web "DeepSkyBlue")

(defun my-set-linkcolors ()
  "Defines the colors of various link colors"
  (interactive)

  ;; Org links --------------------------------------------------------------------------

  (org-link-set-parameters "id" :face `(:foreground ,my-linkcolor-org :underline t))
  (org-link-set-parameters "contact" :face `(:foreground ,my-linkcolor-org :underline t))

  ;; File links --------------------------------------------------------------------------

  (org-link-set-parameters "file" :face `(:foreground ,my-linkcolor-file :underline t))
  ;; defined elsewhere;; (org-link-set-parameters "tsfile" :face '`(:foreground "DarkSeaGreen" :underline t))
  (org-link-set-parameters "pdf" :face `(:foreground ,my-linkcolor-file :underline t))

  (org-link-set-parameters "EPA" :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "EPAAFO" :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "JAFO" :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "DAKEPA" :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "BMTSK" :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "ISO" :face `(:foreground ,my-linkcolor-file :underline t))

  (org-link-set-parameters "gemSpec_DS_Anbieter"
                           :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "gemSpec_Net"
                           :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "gemSpec_PKI"
                           :face `(:foreground ,my-linkcolor-file :underline t))
  (org-link-set-parameters "gemSpec_IDP_Dienst"
                           :face `(:foreground ,my-linkcolor-file :underline t))

  (org-link-set-parameters "messageid"
                           :face `(:foreground ,my-linkcolor-file :underline t))

  ;; Web links --------------------------------------------------------------------------

  (org-link-set-parameters "http" :face `(:foreground ,my-linkcolor-web :underline t))
  (org-link-set-parameters "https" :face `(:foreground ,my-linkcolor-web :underline t))

)

(defun my-set-linkcolors ()
  "Defines the colors of various link colors"
  (interactive)

  ;; Org links --------------------------------------------------------------------------

  (org-link-set-parameters "id" :face '(:foreground "wheat3" :underline t))
  (org-link-set-parameters "contact" :face '(:foreground "wheat3" :underline t))

  ;; File links --------------------------------------------------------------------------

  (org-link-set-parameters "file" :face '(:foreground "MediumSeaGreen" :underline t))
  ;; defined elsewhere;; (org-link-set-parameters "tsfile" :face ''(:foreground "DarkSeaGreen" :underline t))
  (org-link-set-parameters "pdf" :face '(:foreground "MediumSeaGreen" :underline t))

  (org-link-set-parameters "EPA" :face '(:foreground "MediumSeaGreen" :underline t))
  (org-link-set-parameters "EPAAFO" :face '(:foreground "MediumSeaGreen" :underline t))
  (org-link-set-parameters "JAFO" :face '(:foreground "MediumSeaGreen" :underline t))
  (org-link-set-parameters "DAKEPA" :face '(:foreground "MediumSeaGreen" :underline t))
  (org-link-set-parameters "BMTSK" :face '(:foreground "MediumSeaGreen" :underline t))

  (org-link-set-parameters "gemSpec_DS_Anbieter"
                           :face '(:foreground "MediumSeaGreen" :underline t))
  (org-link-set-parameters "gemSpec_Net"
                           :face '(:foreground "MediumSeaGreen" :underline t))
  (org-link-set-parameters "gemSpec_PKI"
                           :face '(:foreground "MediumSeaGreen" :underline t))
  (org-link-set-parameters "gemSpec_IDP_Dienst"
                           :face '(:foreground "MediumSeaGreen" :underline t))

  (org-link-set-parameters "messageid"
                           :face '(:foreground "MediumSeaGreen" :underline t))

  ;; Web links --------------------------------------------------------------------------

  (org-link-set-parameters "http" :face '(:foreground "DeepSkyBlue" :underline t))
  (org-link-set-parameters "https" :face '(:foreground "DeepSkyBlue" :underline t))

)

(my-set-linkcolors) ;; set colors when loading
  • test links
  • as of [2021-01-11 Mon] (before unifying color concept):
    • Org links had: snow3
    • File links: DarkSeaGreen, wheat2
    • Web links: DeepSkyBlue

Open in external app

Found via reddit thread:

Add a type of link so that the emacs will open the linked file with the default external application (useful for media such as movies, pdfs, etc.)

  • 2017-09-14: FIXXME: does not work on Windows: Unable to start '~\path\to\2017-09-12 a file.pdf': The specified file was not found.
    • I guess that the backslashes have to be replaced by forward slashes for Windows/Cygwin

Alternative approach for Windows:

(w32-shell-execute "open"
                         "C:/Program Files (x86)/.../cygstart"
                         (concat " \"" path-to-media "\""))
(defun my-open-ext (path-to-media)
  (if (my-system-type-is-windows)
      (shell-command (concat "cygstart \"" path-to-media "\""))
    (shell-command (concat "open " \"" path-to-media \""))
    )
)
(org-add-link-type "open" 'my-open-ext)

org-super-links

2020-06-30initial setup for testing

This reddit comment brought me this nice package: https://github.com/toshism/org-super-links

To my surprise, C-c s, the default prefix of this package, was not defined in my setup yet. So I re-use it here.

Make sure that org-id-link-to-org-use-id is not nil when you want to link using existing IDs instead of fragile links.

(use-package org-super-links
  :quelpa (org-super-links :repo "toshism/org-super-links" :fetcher github :commit "develop")
  :after helm-org
  :bind (("C-c s s" . sl-link)
	 ("C-c s l" . sl-store-link)
	 ("C-c s C-l" . sl-insert-link)             ;; inserts links to heading title (not property ID)
	 ("C-c s d" . sl-quick-insert-drawer-link)
	 ("C-c s i" . sl-quick-insert-inline-link))
  :config
  (setq sl-related-into-drawer t
  	sl-link-prefix 'sl-link-prefix-timestamp)

  ;; use my custom function to generate ID properties accordin to https://karl-voit.at/2019/11/16/UOMF-Linking-Headings/
  (add-hook 'sl-pre-link-hook 'my-id-get-or-generate)
  (add-hook 'sl-pre-backlink-hook 'my-id-get-or-generate)

  ;; Formats link descriptions as suggested on: https://github.com/toshism/org-super-links#limit-length-of-link-description
  ;; development: id:2020-08-05-implement-filter-function
  (defun my-org-super-links-filter-description (link desc)
      ;; replace double bracket links with their description
      (replace-regexp-in-string org-link-bracket-re "\\2"
          ;; removes: <2020-08-04 Tue>--<2020-08-04 Tue 23:37>  (2nd time/date-stamp is optional; including inactive variants)
          (replace-regexp-in-string org-element--timestamp-regexp ""
                ;; removes priority indicators such as [#A]
  	      (replace-regexp-in-string org-priority-regexp ""
                    ;; removes staistic cookies with absolute numbers such as [2/5]
         	          (replace-regexp-in-string " ?\\[[0-9]+/[0-9]\\]" ""
                            ;; removes staistic cookies with percentages such as [33%]
           	          (replace-regexp-in-string " ?\\[[0-9]+%\\]" "" desc)
  			      ))))
  )
  (setq sl-default-description-formatter 'my-org-super-links-filter-description)
  (setq sl-backlink-into-drawer "LINKS"
        sl-related-into-drawer "LINKS") ;; according to https://github.com/toshism/org-super-links/issues/33#issuecomment-678815869

)

Testing my-org-super-links-filter-description:

(mapcar (lambda (s)
   (my-org-super-links-filter-description "foo bar" s))
'("<2020-08-04 Tue> [1/2] [66%] [#A] an example heading"
  "[2020-08-04 Tue] [1/2] [66%] [#A] an example heading"
  "<2020-08-04 Tue 23:07> [1/2] [66%] [#A] an example heading"
  "<2020-08-04 Tue 23:07>-<2020-08-04 Tue> [66%] [#A] an example heading"
  "<2020-08-04 Tue 23:07>-<2020-08-04 Tue> [2/3] [#A] an example heading"
  "<2020-08-04 Tue 23:07>--<2020-08-04 Tue> [2/3] [#A] an example heading"
  "[2020-08-04 Tue 23:07]--[2020-08-04 Tue] [2/3] [#A] an example heading"
  "[#A] [2020-08-04 Tue 23:07]-<2020-08-04 Tue> [2/3] an example heading"
  "<2020-08-05 Wed 19:09>--<2020-08-05 Wed> fixxme: dashes"
  "<2020-08-05 Wed 19:09>-<2020-08-05 Wed> fixxme: dash"
)
)

org-linker and org-linker-edna

2020-09-25initial setup for testing

I asked the author of org-super-links with this feature request to extend org-super-links such that it can be used to define dependencies for org-edna. He denied for org-usper-links but implemented it as extra packages:

  1. extract heading selection interface stuff: org-linker
  2. org-edna interface that uses it: org-linker-edna

This is looking great from intial testing. I need to test it even further in my daily life to come to a conclusion.

My optimistic first approach was (again) with QUELPA:

(use-package org-linker
  :quelpa (org-linker :repo "toshism/org-linker" :fetcher github)
)

However, I still get errors using QUELPA:

Debugger entered--Lisp error: (error "Package ‘helm-org-ql-0’ is unavailable")
  signal(error ("Package ‘helm-org-ql-0’ is unavailable"))
  error("Package `%s-%s' is unavailable" helm-org-ql "0")
  package-compute-transaction(nil ((org (0)) (helm-org-ql (0))))
  package-install-from-buffer()
  package-install-file("/home/vk/.emacs.d/quelpa/packages/org-linker-20200829.2118.el")
  quelpa-package-install-file("/home/vk/.emacs.d/quelpa/packages/org-linker-20200829.2118.el")
  quelpa-package-install((org-linker :repo "toshism/org-linker" :fetcher github))
  apply(quelpa-package-install (org-linker :repo "toshism/org-linker" :fetcher github) nil)
  quelpa((org-linker :repo "toshism/org-linker" :fetcher github))
  apply(quelpa (org-linker :repo "toshism/org-linker" :fetcher github))
  (if (and quelpa-use-package-inhibit-loading-quelpa (package-installed-p (quote org-linker))) nil (apply (quote quelpa) (quote ((org-linker :repo "toshism/org-linker" :fetcher github)))))
  (progn (if (and quelpa-use-package-inhibit-loading-quelpa (package-installed-p (quote org-linker))) nil (apply (quote quelpa) (quote ((org-linker :repo "toshism/org-linker" :fetcher github))))) (defvar use-package--warning297 (function (lambda (keyword err) (let ((msg (format "%s/%s: %s" ... keyword ...))) (display-warning (quote use-package) msg :error))))) (condition-case err (if (not (require (quote org-linker) nil t)) (display-warning (quote use-package) (format "Cannot load %s" (quote org-linker)) :error)) ((debug error) (funcall use-package--warning297 :catch err))))
  eval((progn (if (and quelpa-use-package-inhibit-loading-quelpa (package-installed-p (quote org-linker))) nil (apply (quote quelpa) (quote ((org-linker :repo "toshism/org-linker" :fetcher github))))) (defvar use-package--warning297 (function (lambda (keyword err) (let ((msg ...)) (display-warning (quote use-package) msg :error))))) (condition-case err (if (not (require (quote org-linker) nil t)) (display-warning (quote use-package) (format "Cannot load %s" (quote org-linker)) :error)) ((debug error) (funcall use-package--warning297 :catch err)))) nil)
  elisp--eval-last-sexp(nil)
  eval-last-sexp(nil)
  funcall-interactively(eval-last-sexp nil)
  call-interactively(eval-last-sexp nil nil)
  command-execute(eval-last-sexp)

Maybe I’m to stupid to use QUELPA. :-( I had to manually clone it and install via:

(use-package org-linker
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-linker/")))
)
(use-package org-linker-edna
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-linker-edna/")))
  :bind (("C-c s e" . org-linker-edna))
  :config
    (setq link-id-function 'my-id-get-or-generate) ;; use my ID generation function instead of UUIDs: https://github.com/toshism/org-linker-edna/issues/3#issuecomment-703815638
)

Agenda

Org-mode is my digital everything. And therefore, Org is also my calendar which is called “agenda” in Org-mode speak. I see my todos (scheduled), my appointments and all date- & time-stamps on it.

But it gets even more crazy with Memacs: https://github.com/novoid/Memacs/ With Memacs, I get email, text messages, phone calls, downloaded files, visited web pages, Git commits, photos, and so forth on my agenda. This is really cool.

Irreal wrote a blog article about a nice Agenda demo. I’m using almost all features explained (except column mode, effort, clocking).

Agenda files

I maintain two categories of agenda files: work and non-work files which are defined for Windows and non-windows separately (path format differs).

Using my-toggle-agenda-files() I can toggle between host-specific default agenda and all agenda files.

Definition of work files: (only used in cron-job shell script)

(setq my-work-agenda-files (append `(
;; 2019-06-26: backtick above and ,() below are because of: https://stackoverflow.com/questions/9449364/elisp-alist-and-strings-type-confusion
;; the (quote (("foo/bar.pro")) from before had to be changed when introducing the concat method for the path
     ,(concat my-org-files-path "rise.org")
     ;;,(concat my-org-files-path "detego.org")
     ;;,(concat my-org-files-path "ciso.org")
     ;;,(concat my-org-files-path "exported-detego-calendar.org")
     ;;,(concat my-org-files-path "r6-stories.org")
     ;;,(concat my-org-files-path "infonova.org")
     )))

The following file is only accessible on my work computer:

(when (my-system-is-rise)
  (add-to-list 'my-work-agenda-files my-business-siko-notes))

Definitions of non-work files: (only used in cron-job shell script)

(setq my-nonwork-agenda-files (append ` (
            ,(concat my-org-files-path "misc.org")
            ,(concat my-org-files-path "issues.org")
            ,(concat my-org-files-path "projects.org")
            ,(concat my-org-files-path "finanzen_behoerden_versicherungen.org")
            ,(concat my-org-files-path "bwg.org")
            ,(concat my-org-files-path "contacts.org")
            ;;,(concat my-org-files-path "foodandbeverages.org")
            ,(concat my-org-files-path "hardware.org")
            ,(concat my-org-files-path "tugraz.org")
            ,(concat my-org-files-path "fhsp.org")
            ,(concat my-org-files-path "notes.org")
            ,(concat my-org-files-path "public_voit.org")
            ,(concat my-org-files-path "errors.org")
            ,(concat my-org-files-path "errors_public_voit.org")
            ;;,(concat my-org-files-path "movies.org")
            ;;,(concat my-org-files-path "references.org")
            ;;"c:/Users/karl.voit/src/lazyblorg/lazyblorg.org")
            ;;,(concat my-org-files-path "memacs/error.org")
            ;;,(concat my-org-files-path "memacs/git.org")
            ;;,(concat my-org-files-path "memacs/ifiles.org")
            ;;,(concat my-org-files-path "memacs/phonecalls.org")
            ;;,(concat my-org-files-path "memacs/roylog.org")
            ;;,(concat my-org-files-path "memacs/SMS.org")
         )))

2021-01-03: Instead of my previous complex org-agenda setup with work and non-work agenda files and the ability to toggle them, I moved to a simplified setup. Reason: I don’t use the toggle-feature and I want to be able to refresh the super-agenda (which was not possible in my complex setup: refreshed agenda was not org-super-agenda but normal agenda).

(setq org-agenda-files (append my-work-agenda-files my-nonwork-agenda-files))

OLD:

my-toggle-agenda-files() toggles between work/everything and nonwork/everything:

Default agenda files: on my business host, start with the work-related files; on my other machines, start with my non-work-related files.

my-toggle-agenda-files() → my-map A

2021-01-03disabled: I want to test and switch to standard org-super-agenda setup
(defun my-toggle-agenda-files ()
  "Toggle my agenda files between work/everything and nonwork/everything
depending on the current system.
Source for the toggle code: `http://ergoemacs.org/emacs/elisp_toggle_command.html'"
  (interactive)
  ;; use a property “state”. Value is t or nil
  (if (get 'my-toggle-agenda-files 'state)
      (progn
        (message "Agenda files: host-specific")
        (if (string-equal system-name "GRZN17009")
            (setq org-agenda-files (append my-work-agenda-files ))
          (setq org-agenda-files (append my-nonwork-agenda-files ))
          )
        (put 'my-toggle-agenda-files 'state nil))
    (progn
      (message "Agenda files: all")
      (setq org-agenda-files (append my-work-agenda-files my-nonwork-agenda-files))
      (put 'my-toggle-agenda-files 'state t))))


(bind-key "A" 'my-toggle-agenda-files my-map)

(setq org-agenda-files (append my-work-agenda-files my-nonwork-agenda-files))
;; separate agenda files for work/nonwork: ;; (if (my-system-type-is-windows)
;; separate agenda files for work/nonwork: ;;     (setq org-agenda-files (append my-work-agenda-files my-nonwork-agenda-files))
;; separate agenda files for work/nonwork: ;;     (setq org-agenda-files (append my-nonwork-agenda-files ))
;; separate agenda files for work/nonwork: ;;     )

Misc agenda helper functions

my-skip-tag(tag)

From: Memnon Anon <gegendosenfleisch@googlemail.com>
Newsgroups: gmane.emacs.orgmode
Subject: Re: Exclude tag from custom agenda
Date: Sun, 9 Dec 2012 15:59:48 +0000 (UTC)
Message-ID: <871uezql9d.fsf@mean.albasani.net>
Based on http://article.gmane.org/gmane.emacs.orgmode/41427
(defun my-skip-tag(tag)
  "Skip entries that are tagged TAG"
  (let* ((entry-tags (org-get-tags-at (point))))
    (if (member tag entry-tags)
        (progn (outline-next-heading) (point))
      nil)))

tag-without-done-or-canceled()

2012-12-09 From: Memnon Anon <gegendosenfleisch@googlemail.com>
To: news1142@Karl-Voit.at
Subject: Re: Custom agenda: search by tag and exclude DONE items
(defun tag-without-done-or-canceled ()
  "Show items with tag \"borrowed\" that are neither in \"DONE\" or \"CANCELED \" state."
  (let ((state (org-entry-get (point) "TODO")))
    (if (and (member "borrowed" (org-get-tags-at (point)))
             (not (string= state "DONE"))
             (not (string= state "CANCELED")))
        nil ; do not skip
      (line-end-position)))) ; skip

MISC functions from Bernt Hansen’s famous http://doc.norang.ca/org-mode.html

  (defun bh/is-project-p ()
    "Any task with a todo keyword subtask"
    (let ((has-subtask)
          (subtree-end (save-excursion (org-end-of-subtree t))))
      (save-excursion
        (forward-line 1)
        (while (and (not has-subtask)
                    (< (point) subtree-end)
                    (re-search-forward "^\*+ " subtree-end t))
          (when (member (org-get-todo-state) org-todo-keywords-1)
            (setq has-subtask t))))
      has-subtask))

  (defun bh/skip-non-stuck-projects ()
    "Skip trees that are not stuck projects"
    (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
           (has-next (save-excursion
                       (forward-line 1)
                       (and (< (point) subtree-end)
                            (re-search-forward "^\\*+ \\(NEXT\\|STARTED\\) " subtree-end t)))))
      (if (and (bh/is-project-p) (not has-next))
          nil ; a stuck project, has subtasks but no next task
        subtree-end)))

  (defun bh/skip-non-projects ()
    "Skip trees that are not projects"
    (let* ((subtree-end (save-excursion (org-end-of-subtree t))))
      (if (bh/is-project-p)
          nil
        subtree-end)))

  (defun bh/skip-projects ()
    "Skip trees that are projects"
    (let* ((subtree-end (save-excursion (org-end-of-subtree t))))
      (if (bh/is-project-p)
          subtree-end
        nil)))

  (defun bh/skip-non-archivable-tasks ()
    "Skip trees that are not available for archiving"
    (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
           (daynr (string-to-int (format-time-string "%d" (current-time))))
           (a-month-ago (* 60 60 24 (+ daynr 1)))
           (last-month (format-time-string "%Y-%m-" (time-subtract (current-time) (seconds-to-time a-month-ago))))
           (this-month (format-time-string "%Y-%m-" (current-time)))
           (subtree-is-current (save-excursion
                                 (forward-line 1)
                                 (and (< (point) subtree-end)
                                      (re-search-forward (concat last-month "\\|" this-month) subtree-end t)))))
      (if subtree-is-current
          subtree-end ; Has a date in this month or last month, skip it
        ;; Make sure the ARCHIVE property is set for this task
        ;; Create one at the parent task if necessary
        (save-excursion
          (save-restriction
            (widen)
            (let ((archive-prop (org-entry-get nil "ARCHIVE" 'inherit))
                  (parent-task))
              (org-up-heading-safe)
              (setq parent-task (nth 4 (org-heading-components)))
              (unless archive-prop
                (setq archive-prop (org-entry-put nil "ARCHIVE" (concat "%s_archive::* " parent-task)))))))
        nil)))

  (defmacro bh/agenda-sort-test (fn a b)
    "Test for agenda sort"
    `(cond
      ;; if both match leave them unsorted
      ((and (apply ,fn (list ,a))
            (apply ,fn (list ,b)))
       (setq result nil))
      ;; if a matches put a first
      ((apply ,fn (list ,a))
       ;; if b also matches leave unsorted
       (if (apply ,fn (list ,b))
           (setq result nil)
         (setq result -1)))
      ;; otherwise if b matches put b first
      ((apply ,fn (list ,b))
       (setq result 1))
      ;; if none match leave them unsorted
      (t nil)))

  (defmacro bh/agenda-sort-test-num (fn compfn a b)
    `(cond
      ((apply ,fn (list ,a))
       (setq num-a (string-to-number (match-string 1 ,a)))
       (if (apply ,fn (list ,b))
           (progn
             (setq num-b (string-to-number (match-string 1 ,b)))
             (setq result (if (apply ,compfn (list num-a num-b))
                              -1
                            1)))
         (setq result -1)))
      ((apply ,fn (list ,b))
       (setq result 1))
      (t nil)))

  (defun bh/is-not-scheduled-or-deadline (date-str)
    (and (not (bh/is-deadline date-str))
         (not (bh/is-scheduled date-str))))

  (defun bh/is-due-deadline (date-str)
    (string-match "Deadline:" date-str))

  (defun bh/is-late-deadline (date-str)
    (string-match "In *\\(-.*\\)d\.:" date-str))

  (defun bh/is-pending-deadline (date-str)
    (string-match "In \\([^-]*\\)d\.:" date-str))

  (defun bh/is-deadline (date-str)
    (or (bh/is-due-deadline date-str)
        (bh/is-late-deadline date-str)
        (bh/is-pending-deadline date-str)))

  (defun bh/is-scheduled (date-str)
    (or (bh/is-scheduled-today date-str)
        (bh/is-scheduled-late date-str)))

  (defun bh/is-scheduled-today (date-str)
    (string-match "Scheduled:" date-str))

  (defun bh/is-scheduled-late (date-str)
    (string-match "Sched\.\\(.*\\)x:" date-str))

  (defun bh/agenda-sort (a b)
    "Sorting strategy for agenda items.
Late deadlines first, then scheduled, then non-late deadlines"
    (let (result num-a num-b)
      (cond
       ;; time specific items are already sorted first by org-agenda-sorting-strategy

       ;; non-deadline and non-scheduled items next
       ((bh/agenda-sort-test 'bh/is-not-scheduled-or-deadline a b))

       ;; late deadlines next
       ((bh/agenda-sort-test-num 'bh/is-late-deadline '< a b))

       ;; late scheduled items next
       ;;   ((bh/agenda-sort-test-num 'bh/is-scheduled-late '> a b))

       ;; deadlines for today next
       ((bh/agenda-sort-test 'bh/is-due-deadline a b))

       ;; scheduled items for today next
       ((bh/agenda-sort-test 'bh/is-scheduled-today a b))

       ;; late deadlines next
       ;;   ((bh/agenda-sort-test-num 'bh/is-late-deadline '< a b))

       ;; late scheduled items next
       ((bh/agenda-sort-test-num 'bh/is-scheduled-late '> a b))

       ;; pending deadlines last
       ((bh/agenda-sort-test-num 'bh/is-pending-deadline '< a b))

       ;; finally default to unsorted
       (t (setq result nil)))
      result))

Removes things tagged with “lp” or “reward” when typing “/ RET” in agenda

From: http://doc.norang.ca/org-mode.html#CustomAgendaViewFilteringContext
Also: http://orgmode.org/manual/Filtering_002flimiting-agenda-items.html
(defun bh/org-auto-exclude-function-private (tag)
  "Automatic task exclusion in the agenda with / RET"
  (and (cond
        ((string= tag "lp") t)
        ((string= tag "reward") t)
        ((string= tag "test") t)
        ((string= tag "2read") t)
        )
       (concat "-" tag)))

For business, I use a different setup:

(defun bh/org-auto-exclude-function-infonova (tag)
  "Automatic task exclusion in the agenda with / RET"
  (and (cond
        ((string= tag "lp") t)
        ((string= tag "reward") t)
        ((string= tag "test") t)
        ((string= tag "@BWG") t)
        ((string= tag "blog") t)
        ((string= tag "2read") t)
        )
       (concat "-" tag)))

(if (my-system-type-is-windows)
    (setq org-agenda-auto-exclude-function 'bh/org-auto-exclude-function-infonova)
  (setq org-agenda-auto-exclude-function 'bh/org-auto-exclude-function-private)
  )

my-narrow-agenda()

(defun my-narrow-agenda ()
  (interactive "P")
;  (org-agenda-filter-apply "-\(WAITING\|:reward:\|:lp:\)" 'regexp)

  (org-agenda-filter-apply "-NEXT.*:\\(@BWG\\|reward\\):" 'regexp)
;; returns: wrong number of arguments

;  (setq current-prefix-arg '(4)) ; C-u
;  (org-agenda-filter-by-regexp "\(WAITING\|:reward:\|:lp:\)")

;;  (org-agenda-filter-by-regexp '(4) "WAITING")
;; NEXT.*:\(@BWG\|reward\):   -> keyword "NEXT" with either tag "@BWG" OR "reward"
  )

my-super-agenda()

2021-01-03disabled: I want to test and switch to standard org-super-agenda setup

Supercharge your Org daily/weekly agenda by grouping items

See also: id:2017-08-12-org-super-agenda

Loading the code:

(use-package org-super-agenda
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-super-agenda/")))
)

Definition of my-super-agenda-groups, my central configuration of super-agenda:

Original version (before testing the next one):

(setq my-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 "DEADLINES" :deadline t :order 1)
        (:name "Focus" :tag "Focus" :order 2 :face (:append t :weight bold))
        (:name "Important" :priority "A" :order 4)
        (:priority<= "B"
                     ;; Show this section after "Today" and "Important", because
                     ;; their order is unspecified, defaulting to 0. Sections
                     ;; are displayed lowest-number-first.
                     :order 6)
;        (:name "Habits" :habit t :order 3)
        (:name "Shopping" :tag "Besorgung" :order 8)
               ;; Boolean AND group matches items that match all subgroups
               ;;  :and (:tag "shopping" :tag "@town")
               ;; Multiple args given in list with implicit OR
               ;;  :tag ("food" "dinner"))
               ;;  :habit t
               ;;  :tag "personal")
        (:name "Started" :todo "STARTED" :order 10)
        ;;(:name "Space-related (non-moon-or-planet-related)"
        ;;       ;; Regexps match case-insensitively on the entire entry
        ;;       :and (:regexp ("space" "NASA")
        ;;                     ;; Boolean NOT also has implicit OR between selectors
        ;;                     :not (:regexp "moon" :tag "planet")))
        (:name "BWG" :tag "@BWG" :order 16)
        (:todo "WAITING" :order 18)  ; Set order of this section
        (:name "read" :tag "2read" :order 22)
        ;; Groups supply their own section names when none are given
        (:todo ("SOMEDAY" "WATCHING")
               ;; Show this group at the end of the agenda (since it has the
               ;; highest number). If you specified this group last, items
               ;; with these todo keywords that e.g. have priority A would be
               ;; displayed in that group instead, because items are grouped
               ;; out in the order the groups are listed.
               :order 25)
        (:name "reward"
               :tag ("reward" "lp")
               :order 100
               )

        ;; After the last group, the agenda will display items that didn't
        ;; match any of these groups, with the default order position of 99
        )
      )

Test version (not working yet):

(setq my-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 "r DEADLINES" :tag "rise" :deadline t :order 1)
        (:name "r Focus" :and (:tag "focus" :tag "rise") :order 2 :face (:append t :weight bold))
        (:name "r Important" :and (:tag "rise" :priority "A") :order 4)
        (:priority<= "B"
                     ;; Show this section after "Today" and "Important", because
                     ;; their order is unspecified, defaulting to 0. Sections
                     ;; are displayed lowest-number-first.
                     :tag "rise" :order 6)
        ;;(:name "r Shopping" :tag ("Besorgung" "rise") :order 8)
               ;; Boolean AND group matches items that match all subgroups
               ;;  :and (:tag "shopping" :tag "@town")
               ;; Multiple args given in list with implicit OR
               ;;  :tag ("food" "dinner"))
               ;;  :habit t
               ;;  :tag "personal")
        (:name "r Started" :and (:tag "rise" :todo "STARTED") :order 10)
        ;;(:name "Space-related (non-moon-or-planet-related)"
        ;;       ;; Regexps match case-insensitively on the entire entry
        ;;       :and (:regexp ("space" "NASA")
        ;;                     ;; Boolean NOT also has implicit OR between selectors
        ;;                     :not (:regexp "moon" :tag "planet")))
        ;;(:name "BWG" :tag "@BWG" :order 16)
        (:todo "r WAITING" :tag "rise" :order 18)  ; Set order of this section
        ;;(:name "read" :tag "2read" :order 22)
        ;; Groups supply their own section names when none are given
        (:todo ("SOMEDAY" "WATCHING")
               ;; Show this group at the end of the agenda (since it has the
               ;; highest number). If you specified this group last, items
               ;; with these todo keywords that e.g. have priority A would be
               ;; displayed in that group instead, because items are grouped
               ;; out in the order the groups are listed.
               :tag "rise" :order 25)
        (:name "r reward"
               :and (:tag "rise" :tag ("reward" "lp"))
               :order 30
               )

        (:name "r Habits" :tag "rise" :habit t :order 33)
      ;; ======= Private: =================================================

          (:name "DEADLINES" :and (:not (:tag "rise") :deadline t) :order 50)
          (:name "Focus" :and (:not (:tag "rise") :tag "focus") :order 52 :face (:append t :weight bold))
          (:name "Important" :and (:not (:tag "rise") :priority "A") :order 54)
          (:and (:priority<= "B"
                       ;; Show this section after "Today" and "Important", because
                       ;; their order is unspecified, defaulting to 0. Sections
                       ;; are displayed lowest-number-first.
                       :not (:tag "rise")) :order 56)
          ;;(:name "Habits" :habit t :order 53)
          (:name "Shopping" :and (:not (:tag "rise") :tag "Besorgung") :order 58)
                 ;; Boolean AND group matches items that match all subgroups
                 ;;  :and (:tag "shopping" :tag "@town")
                 ;; Multiple args given in list with implicit OR
                 ;;  :tag ("food" "dinner"))
                 ;;  :habit t
                 ;;  :tag "personal")
          (:name "Started" :and (:not (:tag "rise") :todo "STARTED") :order 60)
          ;;(:name "Space-related (non-moon-or-planet-related)"
          ;;       ;; Regexps match case-insensitively on the entire entry
          ;;       :and (:regexp ("space" "NASA")
          ;;                     ;; Boolean NOT also has implicit OR between selectors
          ;;                     :not (:regexp "moon" :tag "planet")))
          (:name "BWG" :and (:not (:tag "rise") :tag "@BWG") :order 66)
          (:and (:todo "WAITING" :not (:tag "rise")) :order 68)  ; Set order of this section
          (:name "read" :and (:not (:tag "rise") :tag "2read") :order 72)
          ;; Groups supply their own section names when none are given
          (:and (:todo ("SOMEDAY" "WATCHING")
                 ;; Show this group at the end of the agenda (since it has the
                 ;; highest number). If you specified this group last, items
                 ;; with these todo keywords that e.g. have priority A would be
                 ;; displayed in that group instead, because items are grouped
                 ;; out in the order the groups are listed.
                 :not (:tag "rise")) :order 75)
          (:name "reward"
                 :and (:not (:tag "rise") :tag ("reward" "lp"))
                 :order 80
                 )


        ;; After the last group, the agenda will display items that didn't
        ;; match any of these groups, with the default order position of 99
        )
      )

my-super-agenda() is a function so that I am able to call the agenda interactively or within my-org-agenda() which is defined further down below.

(defun my-super-agenda()
  "generates my super-agenda"
  (interactive)
  (org-super-agenda-mode)
  (let
      ((org-super-agenda-groups my-super-agenda-groups))
    (org-agenda nil "a")
    )
  )

super-agenda()

2021-01-03new, standard org-super-agenda setup instead of old, complex setup

Supercharge your Org daily/weekly agenda by grouping items

See also: id:2017-08-12-org-super-agenda

(use-package org-super-agenda
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-super-agenda/")))
  :ensure t
  ;; :hook (org-agenda-mode . org-super-agenda-mode)
  :config
    (org-super-agenda-mode)
    (setq 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 "DEADLINES" :deadline t :order 1)
            (:name "Focus" :tag "Focus" :order 2 :face (:append t :weight bold))
            (:name "Important" :priority "A" :order 4)
    ;        (:name "Habits" :habit t :order 3)
            (:name "Shopping" :tag "Besorgung" :order 8)
                   ;; Boolean AND group matches items that match all subgroups
                   ;;  :and (:tag "shopping" :tag "@town")
                   ;; Multiple args given in list with implicit OR
                   ;;  :tag ("food" "dinner"))
                   ;;  :habit t
                   ;;  :tag "personal")
            (:name "Started" :todo "STARTED" :order 10)
            ;;(:name "Space-related (non-moon-or-planet-related)"
            ;;       ;; Regexps match case-insensitively on the entire entry
            ;;       :and (:regexp ("space" "NASA")
            ;;                     ;; Boolean NOT also has implicit OR between selectors
            ;;                     :not (:regexp "moon" :tag "planet")))
            ;;(:name "BWG" :tag "@BWG" :order 16)
            (:name "read" :tag "2read" :order 22)
            ;; Groups supply their own section names when none are given
            (:todo ("SOMEDAY" "WATCHING")
                   ;; Show this group at the end of the agenda (since it has the
                   ;; highest number). If you specified this group last, items
                   ;; with these todo keywords that e.g. have priority A would be
                   ;; displayed in that group instead, because items are grouped
                   ;; out in the order the groups are listed.
                   :order 25)

            ;; "other items": an auto-group with order 99 ----------------------------

            (:priority<= "B"
                         ;; Show this section after "Today" and "Important", because
                         ;; their order is unspecified, defaulting to 0. Sections
                         ;; are displayed lowest-number-first.
                         :order 105)
            (:name "reward"
                   :tag ("reward" "lp")
                   :order 110
                   )
            (:todo "WAITING" :order 118)  ; Set order of this section

            ;; After the last group, the agenda will display items that didn't
            ;; match any of these groups, with the default order position of 99
            ))

);; end of org-super-agenda

Test version (not working yet):

(setq my-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 "r DEADLINES" :tag "rise" :deadline t :order 1)
        (:name "r Focus" :and (:tag "focus" :tag "rise") :order 2 :face (:append t :weight bold))
        (:name "r Important" :and (:tag "rise" :priority "A") :order 4)
        (:priority<= "B"
                     ;; Show this section after "Today" and "Important", because
                     ;; their order is unspecified, defaulting to 0. Sections
                     ;; are displayed lowest-number-first.
                     :tag "rise" :order 6)
        ;;(:name "r Shopping" :tag ("Besorgung" "rise") :order 8)
               ;; Boolean AND group matches items that match all subgroups
               ;;  :and (:tag "shopping" :tag "@town")
               ;; Multiple args given in list with implicit OR
               ;;  :tag ("food" "dinner"))
               ;;  :habit t
               ;;  :tag "personal")
        (:name "r Started" :and (:tag "rise" :todo "STARTED") :order 10)
        ;;(:name "Space-related (non-moon-or-planet-related)"
        ;;       ;; Regexps match case-insensitively on the entire entry
        ;;       :and (:regexp ("space" "NASA")
        ;;                     ;; Boolean NOT also has implicit OR between selectors
        ;;                     :not (:regexp "moon" :tag "planet")))
        ;;(:name "BWG" :tag "@BWG" :order 16)
        (:todo "r WAITING" :tag "rise" :order 18)  ; Set order of this section
        ;;(:name "read" :tag "2read" :order 22)
        ;; Groups supply their own section names when none are given
        (:todo ("SOMEDAY" "WATCHING")
               ;; Show this group at the end of the agenda (since it has the
               ;; highest number). If you specified this group last, items
               ;; with these todo keywords that e.g. have priority A would be
               ;; displayed in that group instead, because items are grouped
               ;; out in the order the groups are listed.
               :tag "rise" :order 25)
        (:name "r reward"
               :and (:tag "rise" :tag ("reward" "lp"))
               :order 30
               )

        (:name "r Habits" :tag "rise" :habit t :order 33)
      ;; ======= Private: =================================================

          (:name "DEADLINES" :and (:not (:tag "rise") :deadline t) :order 50)
          (:name "Focus" :and (:not (:tag "rise") :tag "focus") :order 52 :face (:append t :weight bold))
          (:name "Important" :and (:not (:tag "rise") :priority "A") :order 54)
          (:and (:priority<= "B"
                       ;; Show this section after "Today" and "Important", because
                       ;; their order is unspecified, defaulting to 0. Sections
                       ;; are displayed lowest-number-first.
                       :not (:tag "rise")) :order 56)
          ;;(:name "Habits" :habit t :order 53)
          (:name "Shopping" :and (:not (:tag "rise") :tag "Besorgung") :order 58)
                 ;; Boolean AND group matches items that match all subgroups
                 ;;  :and (:tag "shopping" :tag "@town")
                 ;; Multiple args given in list with implicit OR
                 ;;  :tag ("food" "dinner"))
                 ;;  :habit t
                 ;;  :tag "personal")
          (:name "Started" :and (:not (:tag "rise") :todo "STARTED") :order 60)
          ;;(:name "Space-related (non-moon-or-planet-related)"
          ;;       ;; Regexps match case-insensitively on the entire entry
          ;;       :and (:regexp ("space" "NASA")
          ;;                     ;; Boolean NOT also has implicit OR between selectors
          ;;                     :not (:regexp "moon" :tag "planet")))
          (:name "BWG" :and (:not (:tag "rise") :tag "@BWG") :order 66)
          (:and (:todo "WAITING" :not (:tag "rise")) :order 68)  ; Set order of this section
          (:name "read" :and (:not (:tag "rise") :tag "2read") :order 72)
          ;; Groups supply their own section names when none are given
          (:and (:todo ("SOMEDAY" "WATCHING")
                 ;; Show this group at the end of the agenda (since it has the
                 ;; highest number). If you specified this group last, items
                 ;; with these todo keywords that e.g. have priority A would be
                 ;; displayed in that group instead, because items are grouped
                 ;; out in the order the groups are listed.
                 :not (:tag "rise")) :order 75)
          (:name "reward"
                 :and (:not (:tag "rise") :tag ("reward" "lp"))
                 :order 80
                 )

        ;; After the last group, the agenda will display items that didn't
        ;; match any of these groups, with the default order position of 99
        )
      )

my-super-agenda() is a function so that I am able to call the agenda interactively or within my-org-agenda() which is defined further down below.

2021-01-03: disabled (not needed when simplified org-super-agenda is applied to any agenda)

(defun my-super-agenda()
  "generates my super-agenda"
  (interactive)
  (org-super-agenda-mode)
  (let
      ((org-super-agenda-groups super-agenda-groups))
    (org-agenda nil "a")
    )
  )

my-super-agenda-business()

2021-01-03disabled: I want to test and switch to standard org-super-agenda setup

Same as my-super-agenda but with much stricter filters so that I only see important business stuff.

(setq my-super-agenda-important-business-only-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 "DEADLINES" :order 1
                :and (:deadline t :not (:tag ("reward" "@BWG"))))
        (:name "Important" :order 2
               :and (:priority "A" :not (:tag ("reward" "@BWG"))))
        ;;(:name "Habits" :habit t :order 3 :and (:not (:tag ("reward" "@BWG"))))
        (:name "Shopping" :order 4
               :and (:tag "Besorgung" :not (:tag ("reward" "@BWG"))))
               ;; Boolean AND group matches items that match all subgroups
               ;;  :and (:tag "shopping" :tag "@town")
               ;; Multiple args given in list with implicit OR
               ;;  :tag ("food" "dinner"))
               ;;  :habit t
               ;;  :tag "personal")
        (:name "Started" :order 6
               :and (:todo "STARTED" :not (:tag ("reward" "@BWG"))))
        ;;(:name "Space-related (non-moon-or-planet-related)"
        ;;       ;; Regexps match case-insensitively on the entire entry
        ;;       :and (:regexp ("space" "NASA")
        ;;                     ;; Boolean NOT also has implicit OR between selectors
        ;;                     :not (:regexp "moon" :tag "planet")))
        ;;(:name "BWG" :tag "@BWG" :order 7)
        (:name "Low Prio"
                     ;; Show this section after "Today" and "Important", because
                     ;; their order is unspecified, defaulting to 0. Sections
                     ;; are displayed lowest-number-first.
                     :and (:priority<= "B" :not (:tag ("reward" "@BWG")))
                     :order 7)
        (:name "WAITING" :order 9
               :and (:todo "WAITING" :not (:tag ("reward" "@BWG"))))  ; Set order of this section
        (:name "2read" :order 15
               :and (:tag "2read" :not (:tag ("reward" "@BWG"))))
        (:name "Other (Business)" :order 20
               :and (:category ("rise") :not (:tag ("reward" "@BWG"))))
        ;; Groups supply their own section names when none are given
        (:name "SOMEDAY or WATCHING"
               ;; Show this group at the end of the agenda (since it has the
               ;; highest number). If you specified this group last, items
               ;; with these todo keywords that e.g. have priority A would be
               ;; displayed in that group instead, because items are grouped
               ;; out in the order the groups are listed.
               :and (:todo ("SOMEDAY" "WATCHING") :not (:tag ("reward" "@BWG")))
               :order 25)
        ;;(:name "reward"
        ;;       :tag ("reward" "lp")
        ;;       :order 100
        ;;       )

        ;; After the last group, the agenda will display items that didn't
        ;; match any of these groups, with the default order position of 99
        )
      )
(defun my-super-agenda-business()
  "generates my super-agenda"
  (interactive)
  (org-super-agenda-mode)
  (let
      ((org-super-agenda-groups my-super-agenda-important-business-only-groups))
    (org-agenda nil "a")
    )
  )

org-agenda-custom-commands → long list of agenda definitions

(if noninteractive
  ;; if Emacs is started in batch mode: omit org-super-agenda since I don't need it here and there were issues with it:
  (setq org-agenda-custom-commands
        ` (
                ("n" "no TODO events +180d"
                 ((agenda "no TODO events +180d"
                          ((org-agenda-span 180)
                           (org-agenda-time-grid nil)
                           (org-agenda-entry-types '(:timestamp :sexp))
                           (org-agenda-skip-function
                            '(or
                              (org-agenda-skip-entry-if 'todo 'any);; skip if any TODO state is found
                              (org-agenda-skip-entry-if 'category "errors");; skip if any TODO state is found
                              (my-skip-tag "lp")
                              )
                            )
                           ;;(org-agenda-skip-function '(my-skip-tag "lp"))
                          )))
                 nil (,(concat my-org-files-path "agenda_180d_filtered_raw.html")))

                ("D" "detail agenda"
                 ((agenda "detail agenda"
                          ((org-agenda-span 31)
                           (org-agenda-time-grid nil)
                          )))
                 nil (,(concat my-org-files-path "agenda_details_raw.html")))
                ))

  ;; if Emacs is started in interactive mode:
  (setq org-agenda-custom-commands
        ` (

                ("s" "Super Agenda" agenda "FIXXME: does work but w/o super-agenda"
                 (org-super-agenda-mode)
                 ((org-super-agenda-groups my-super-agenda-groups))
                 (org-agenda nil "a"))

                ("b" "Business Super Agenda" agenda "FIXXME: does work but w/o super-agenda"
                 (org-super-agenda-mode)
                 ((org-super-agenda-groups my-super-agenda-important-business-only-groups))
                 (org-agenda nil "a"))

                ("g" "Agenda" agenda ""
                 (org-agenda nil "a"))

                ;; disabled 2014-08-17 ;;          ;; https://lists.gnu.org/archive/html/emacs-orgmode/2011-07/msg01374.html
                ;; disabled 2014-08-17 ;;          ("E" "events only" agenda ""
                ;; disabled 2014-08-17 ;;           (
                ;; disabled 2014-08-17 ;;            (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'todo))
                ;; disabled 2014-08-17 ;;            ))
                ("n" "no TODO events +180d"
                ((org-ql-block '(and (tags "project")
                              (ts-active :from -1 :to +180)
                              (not (todo))
                              ;(not (descendants (not (done))))
                              ;(not (descendants (scheduled)))
                              )
                        ((org-ql-block-header "no TODO events +180d")))))
                ("7" "no TODO events +180d"
                 ((agenda "no TODO events +180d"
                          ((org-agenda-span 180)
                           (org-agenda-time-grid nil)
                           (org-agenda-entry-types '(:timestamp :sexp))
                           (org-agenda-skip-function
                            '(or
                              (org-agenda-skip-entry-if 'todo 'any);; skip if any TODO state is found
                              (org-agenda-skip-entry-if 'category "infonova");; skip if any TODO state is found
                              (my-skip-tag "lp")
                              )
                            )
                           ;;(org-agenda-skip-function '(my-skip-tag "lp"))
                          )))
                 nil (,(concat my-org-files-path "agenda_180d_filtered.html")))

                ("D" "detail agenda"
                 ((agenda "detail agenda"
                          ((org-agenda-span 31)
                           (org-agenda-time-grid nil)
                          )))
                 nil (,(concat my-org-files-path "agenda_details_raw.html")))

                ;; disabled 2015-02-15 - replaced by no TODO events ;; ("p" "events Prio [#A]"
                ;; disabled 2015-02-15 - replaced by no TODO events ;;  ((agenda "+PRIORITY=\"A\""
                ;; disabled 2015-02-15 - replaced by no TODO events ;;    ((org-agenda-ndays 31)
                ;; disabled 2015-02-15 - replaced by no TODO events ;;     (org-agenda-time-grid nil)
                ;; disabled 2015-02-15 - replaced by no TODO events ;;     (org-agenda-entry-types '(:timestamp :sexp))
                ;; disabled 2015-02-15 - replaced by no TODO events ;;     (org-agenda-skip-function
                ;; disabled 2015-02-15 - replaced by no TODO events ;;      '(org-agenda-skip-entry-if 'notregexp "\\=.*\\[#A\\]")))
                ;; disabled 2015-02-15 - replaced by no TODO events ;;    ;; (
                ;; disabled 2015-02-15 - replaced by no TODO events ;;    ;;  (org-agenda-skip-function 'tag-without-done-or-canceled)
                ;; disabled 2015-02-15 - replaced by no TODO events ;;    ;;  )
                ;; disabled 2015-02-15 - replaced by no TODO events ;;    )))

                ;; disabled 2015-02-15 - replaced by no TODO + normal agenda ;; ("1" "1 month"
                ;; disabled 2015-02-15 - replaced by no TODO + normal agenda ;;  ((agenda "1 month"
                ;; disabled 2015-02-15 - replaced by no TODO + normal agenda ;;           ((org-agenda-ndays 31)
                ;; disabled 2015-02-15 - replaced by no TODO + normal agenda ;;            (org-agenda-time-grid nil)
                ;; disabled 2015-02-15 - replaced by no TODO + normal agenda ;;            (org-agenda-entry-types '(:timestamp :sexp))
                ;; disabled 2015-02-15 - replaced by no TODO + normal agenda ;;            )
                ;; disabled 2015-02-15 - replaced by no TODO + normal agenda ;;           )))

                ("r" "reward tasks" (
                                     (tags-todo "reward/!STARTED"
                                                (
                                                 (org-agenda-overriding-header "rewards: STARTED")
                                                 ))
                                     (tags-todo "reward/!NEXT"
                                                (
                                                 (org-agenda-overriding-header "rewards: NEXT")
                                                 ))
                                     (tags-todo "reward/!TODO"
                                                (
                                                 (org-agenda-overriding-header "rewards: TODO")
                                                 ))
                                     (tags-todo "reward/!SOMEDAY"
                                                (
                                                 (org-agenda-overriding-header "rewards: SOMEDAY")
                                                 ))
                                     ))
                ("i" "issues" (
                                     (tags-todo "issue/!STARTED"
                                                (
                                                 (org-agenda-overriding-header "issues: STARTED")
                                                 ))
                                     (tags-todo "issue/!NEXT"
                                                (
                                                 (org-agenda-overriding-header "issues: NEXT")
                                                 ))
                                     (tags-todo "issue/!TODO"
                                                (
                                                 (org-agenda-overriding-header "issues: TODO")
                                                 ))
                                     (tags-todo "issue/!SOMEDAY"
                                                (
                                                 (org-agenda-overriding-header "issues: SOMEDAY")
                                                 ))
                                     ))

                ;;disabled;              ("R" "grab reward" tags-todo "reward/!TODO|SOMEDAY"
                ;;disabled;            (
                ;;disabled;             (org-agenda-overriding-header "rewards: TODO or SOMEDAY")
                ;;disabled;             ))

                ("B" "borrowed"
                ((org-ql-block '(and (tags "borrowed")
                              (not (done))
                              )
                        ((org-ql-block-header "borrowed")))))
                ;;2019-12-17 replaced by org-ql-block ;; ("8" "borrowed" tags "+borrowed"
                ;;2019-12-17 replaced by org-ql-block ;;  (
                ;;2019-12-17 replaced by org-ql-block ;;   (org-agenda-overriding-header "borrowed or lend")
                ;;2019-12-17 replaced by org-ql-block ;;   (org-agenda-skip-function 'tag-without-done-or-canceled)
                ;;2019-12-17 replaced by org-ql-block ;;   ))

                ("$" "Besorgungen"
                ((org-ql-block '(and (tags "Besorgungen")
                              (not (done))
                              )
                        ((org-ql-block-header "Besorgungen")))))
                ;;2019-12-17 replaced by org-ql-block ;; ("9" "OLDBesorgungen" tags "+Besorgung"
                ;;2019-12-17 replaced by org-ql-block ;;  (
                ;;2019-12-17 replaced by org-ql-block ;;   (org-agenda-overriding-header "Besorgungen")
                ;;2019-12-17 replaced by org-ql-block ;;   (org-agenda-skip-function 'tag-without-done-or-canceled)
                ;;2019-12-17 replaced by org-ql-block ;;   ))

                ;; 2020-10-26: open focus projects
                ("p" "Nonbusiness: Open focus projects: open tasks tagged with \"project\" and \"focus\""
                ((org-ql-block '(and (tags "project") (tags "focus")
                                (not (category "rise"))
                                (not (done))
                                )
                        ((org-ql-block-header "Open focus projects: open tasks tagged with \"project\" and \"focus\"")))))

                ;; 2020-10-26: open focus projects business
                ("P" "Business: Open focus projects: open tasks tagged with \"project\" and \"focus\""
                ((org-ql-block '(and (tags "project") (tags "focus")
                                (category "rise")
                                (not (done))
                                )
                        ((org-ql-block-header "Open focus projects: open tasks tagged with \"project\" and \"focus\"")))))

                ;; examples: https://github.com/alphapapa/org-ql/blob/master/examples.org#stuck-projects-block-agenda
                ;; 2020-01-23: not doing what it is supposed to show: only shows one heading from one org mode file: id:2020-01-23-Security-Policies
                ("1" "Stuck Projects: tagged with \"project\", open sub-tasks not scheduled"
                ((org-ql-block '(and (tags "project")
                              (not (done))
                              (not (todo "SOMEDAY"))
                              (not (descendants (todo "NEXT")))
                              ;;(not (descendants (not (done))))
                              (not (descendants (scheduled))))
                        ((org-ql-block-header "Stuck Projects: tagged with \"project\", open sub-tasks not scheduled")))))

                ;; 2020-01-23: not doing what it is supposed to show at all
                ("2" "Stuck: open todos with unscheduled open sub-tasks"
                ((org-ql-block '(and
                              (not (done))
                              (or (todo "NEXT") (todo "STARTED") (todo "WAITING"))
                              ; (todo "NEXT STARTED WAITING");; no result instead of "just get rid of SOMEDAY"
                              (descendants (not (done)))
                              (descendants (not (scheduled))))
                        ((org-ql-block-header "Stuck: open todos with unscheduled open sub-tasks")))))

                ;; 2020-01-23: "with scheduled sub-tasks" does not work -> lists open todos but not all - can't tell what is shown
                ("3" "Stuck: scheduled todos with scheduled sub-tasks (FIXXME: also DONE subtasks match)"
                ((org-ql-block '(and
                              (not (done))
                              (scheduled)
                              (not (descendants (not (done))))
                              (descendants (scheduled))) ;; 2020-08-06: even tasks that are DONE are matching
                              ;;(descendants (and (scheduled) (not (done))))
                        ((org-ql-block-header "Stuck todos: scheduled open todos with scheduled sub-tasks")))))

                ;; disabled 2015-02-15 - can filter by tag ;; ("O" "SOMEDAY" tags-todo "+TODO=\"SOMEDAY\""
                ;; disabled 2015-02-15 - can filter by tag ;;  (
                ;; disabled 2015-02-15 - can filter by tag ;;   (org-agenda-overriding-header "SOMEDAY is today! :-)")
                ;; disabled 2015-02-15 - can filter by tag ;;   ))
                ;; disabled 2015-02-15 - can filter by tag ;;
                ;; disabled 2015-02-15 - can filter by tag ;; ("h" "home @ALW" tags-todo "+@ALW"
                ;; disabled 2015-02-15 - can filter by tag ;;  (
                ;; disabled 2015-02-15 - can filter by tag ;;   (org-agenda-overriding-header "home tasks")
                ;; disabled 2015-02-15 - can filter by tag ;;   ))
                ;; disabled 2015-02-15 - can filter by tag ;;
                ;; disabled 2015-02-15 - can filter by tag ;; ("b" "Breitenweg @BWG" tags-todo "+@BWG"
                ;; disabled 2015-02-15 - can filter by tag ;;  (
                ;; disabled 2015-02-15 - can filter by tag ;;   (org-agenda-overriding-header "home tasks")
                ;; disabled 2015-02-15 - can filter by tag ;;   ))

                ;; disabled 2014-08-17 because of error ;;;; 2014-02-18: from Org-mode ML Subject: Re: Get a list of tasks completed today
                ;; disabled 2014-08-17 because of error ;;("." "Completed today"
                ;; disabled 2014-08-17 because of error ;; ((todo "TODO|DONE|CANCELED"
                ;; disabled 2014-08-17 because of error ;;        ((org-agenda-skip-function
                ;; disabled 2014-08-17 because of error ;;          '(org-agenda-skip-entry-if 'notregexp (format-time-string "CLOSED: \\[%Y-%m-%d")))))
                ;; disabled 2014-08-17 because of error ;;  (org-agenda-sorting-strategy '(priority-down)))
                ;; disabled 2014-08-17 because of error ;; )

                ;; disabled 2015-02-15 - don't use it any more ;; ;; 2014-02-18: from Org-mode ML Subject: Re: Get a list of tasks completed today
                ;; disabled 2015-02-15 - don't use it any more ;; ("W" "Closed within a week."
                ;; disabled 2015-02-15 - don't use it any more ;;  tags "CLOSED>\"<-1w>\""
                ;; disabled 2015-02-15 - don't use it any more ;;  ((org-agenda-sorting-strategy '(priority-down))))

                ;; disabled 2015-02-15 - don't know what's for ;; ("o" "overview Agenda" (
                ;; disabled 2015-02-15 - don't know what's for ;;                       (agenda ""
                ;; disabled 2015-02-15 - don't know what's for ;;                               nil )
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled by nil above;                 ((org-agenda-skip-function '(my-skip-tag "reward"))
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled by nil above;                  (org-agenda-overriding-header "Agenda without rewards: ")))
                ;; disabled 2015-02-15 - don't know what's for ;;                       (tags "+TODO=\"DONE\"+CLOSED>=\"<today>\""
                ;; disabled 2015-02-15 - don't know what's for ;;                             (
                ;; disabled 2015-02-15 - don't know what's for ;;                              (org-agenda-overriding-header "DONE today")
                ;; disabled 2015-02-15 - don't know what's for ;;                              ))
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                (tags "+reward"
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                           (
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                          (org-agenda-overriding-header "Rewards")
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                            ;(org-agenda-skip-function 'bh/skip-non-stuck-projects))
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                            ;(org-agenda-todo-ignore-scheduled 'future)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                            ;(org-agenda-todo-ignore-deadlines 'future)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                         )
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;diabled;                         )
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;too slow - dont need;                (tags-todo "-CANCELLED/!"
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;too slow - dont need;                           ((org-agenda-overriding-header "Stuck Projects")
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;too slow - dont need;                            (org-agenda-skip-function 'bh/skip-non-stuck-projects)))
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;slow;                (tags-todo "-CANCELLED+WAITING/!"
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;slow;                           ((org-agenda-overriding-header "Waiting and Postponed Tasks")
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;slow;                            (org-agenda-skip-function 'bh/skip-stuck-projects)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;slow;                            (org-tags-match-list-sublevels nil)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;slow;                            (org-agenda-todo-ignore-scheduled 'future)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;slow;                            (org-agenda-todo-ignore-deadlines 'future)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;slow;                     ))
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                (tags "REFILE"
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                      ((org-agenda-overriding-header "Tasks to Refile")
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                       (org-tags-match-list-sublevels nil)))
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                (tags "-REFILE/"
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                      ((org-agenda-overriding-header "Tasks to Archive")
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                       (org-agenda-skip-function 'bh/skip-non-archivable-tasks)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                       (org-tags-match-list-sublevels nil)))
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                (tags-todo "-HOLD-CANCELLED/!"
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                           ((org-agenda-overriding-header "Projects")
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                            (org-agenda-skip-function 'bh/skip-non-projects)
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                            (org-agenda-sorting-strategy
                ;; disabled 2015-02-15 - don't know what's for ;;                       ;;                             '(category-keep))))
                ;; disabled 2015-02-15 - don't know what's for ;;                       )
                ;; disabled 2015-02-15 - don't know what's for ;;  nil)

                ;;disabled;;          ("x" "Borrowed"
                ;;disabled;;           ((agenda ""
                ;;disabled;;                    ((org-agenda-skip-function 'tag-without-done-or-canceled)
                ;;disabled;;                     (org-agenda-overriding-header "Fun: ")))))

                ;;disabled 2014-08-17;; ("X" "calfw" open-calfw-agenda-org)

                ;;2012-12-10 deactivated;             ("c" . "custom searches") ; description for "c" prefix
                ;;2012-12-10 deactivated;              ("cr" "rewards" agenda "+reward"
                ;;2012-12-10 deactivated;              (
                ;;2012-12-10 deactivated;               (org-agenda-overriding-header "rewards")
                ;;2012-12-10 deactivated;               (org-agenda-time-grid nil)
                ;;2012-12-10 deactivated;               (org-agenda-entry-types '(:deadline))
                ;;2012-12-10 deactivated;              ))
                ;;2012-12-10 deactivated;              ("cr" "rewards" agenda "+reward"
                ;;2012-12-10 deactivated;              (
                ;;2012-12-10 deactivated;               (org-agenda-overriding-header "rewards")
                ;;2012-12-10 deactivated;               (org-agenda-time-grid nil)
                ;;2012-12-10 deactivated;               (org-agenda-entry-types '(:deadline))
                ;;2012-12-10 deactivated;              ))
                ;;2012-12-10 deactivated;              ("ct" "@TUG" tags-todo "+@TUG"
                ;;2012-12-10 deactivated;               ((org-agenda-overriding-header "TUG Tasks")))
                ;;2012-12-10 deactivated;              ("ca" "@ALW" tags-todo "+@ALW"
                ;;2012-12-10 deactivated;               ((org-agenda-overriding-header "ALW Tasks")))
                ;;2012-12-10 deactivated;              ("cb" "Besorgungen" tags-todo "+Besorgung"
                ;;2012-12-10 deactivated;               ((org-agenda-overriding-header "Besorgungen")))
                ;;2012-12-10 deactivated;              ("cs" "Started tasks" tags-todo "/!STARTED"
                ;;2012-12-10 deactivated;               ((org-agenda-overriding-header "Started Tasks")))
                ;;2012-12-10 deactivated;              ("n" "Next and Started tasks" tags-todo "-WAITING-CANCELLED/!NEXT|STARTED"
                ;;2012-12-10 deactivated;               ((org-agenda-overriding-header "Next Tasks")))
                ;;2012-12-10 deactivated;              ("p" "Projects" tags-todo "LEVEL=2-REFILE|LEVEL=1+REFILE/!-DONE-CANCELLED-WAITING-SOMEDAY"
                ;;2012-12-10 deactivated;               ((org-agenda-skip-function 'bh/skip-non-projects)
                ;;2012-12-10 deactivated;                (org-agenda-overriding-header "Projects")))
                ;; ("o" "Other (Non-Project) tasks" tags-todo "LEVEL=2-REFILE|LEVEL=1+REFILE/!-DONE-CANCELLED-WAITING-SOMEDAY"
                ;;  ((org-agenda-skip-function 'bh/skip-projects)
                ;;   (org-agenda-overriding-header "Other Non-Project Tasks")))
                ;; ("A" "Tasks to be Archived" tags "LEVEL=2-REFILE/DONE|CANCELLED"
                ;;  ((org-agenda-overriding-header "Tasks to Archive")
                ;;   (org-agenda-skip-function 'bh/skip-non-archivable-tasks)))
                                        ;2012-12-10 deactivated;              ("h" "Habits" tags-todo "STYLE=\"habit\""
                                        ;2012-12-10 deactivated;               ((org-agenda-todo-ignore-with-date nil)
                                        ;2012-12-10 deactivated;                (org-agenda-todo-ignore-scheduled nil)
                                        ;2012-12-10 deactivated;                (org-agenda-todo-ignore-deadlines nil)
                                        ;2012-12-10 deactivated;                (org-agenda-overriding-header "Habits")))
                ;;              ("#" "Stuck Projects" tags-todo "LEVEL=2-REFILE|LEVEL=1+REFILE/!-DONE-CANCELLED"
                ;;               ((org-agenda-skip-function 'bh/skip-non-stuck-projects)
                ;;                (org-agenda-overriding-header "Stuck Projects")))
                ;;               ("*" "All open TODO tasks" tags-todo "-CANCELLED"
                ;;               ((org-agenda-overriding-header "All Open TODO tasks")
                ;;                (org-agenda-todo-ignore-with-date nil)
                ;;                (org-agenda-todo-ignore-scheduled nil)
                ;;                (org-agenda-todo-ignore-deadlines nil)
                ;;                (org-agenda-todo-ignore-timestamp nil)
                ;;                (org-agenda-todo-list-sublevels t)
                ;;                (org-tags-match-list-sublevels 'indented)))
                ))
)

Agenda settings

start Agenda in follow-mode:

;(setq org-agenda-start-with-follow-mode t)
;;(setq org-agenda-inhibit-startup nil);; slower but visibility of buffers is correctly shown
(setq org-agenda-inhibit-startup t);; faster with no hidden headings (agenda performance)

Compact the block agenda view

(setq org-agenda-compact-blocks t)
(setq org-agenda-use-tag-inheritance (quote (agenda)));; agenda performance

http://orgmode.org/org.html#Weekly_002fdaily-agenda

(setq org-agenda-span 1)

For tag searches ignore tasks with scheduled and deadline dates

(setq org-agenda-tags-todo-honor-ignore-options t)

Always highlight the current agenda line:

(add-hook 'org-agenda-mode-hook '(lambda () (hl-line-mode 1)))

The following custom-set-faces create the highlights

(custom-set-faces
  ;; custom-set-faces was added by Custom.
  ;; If you edit it by hand, you could mess it up, so be careful.
  ;; Your init file should contain only one such instance.
  ;; If there is more than one, they won't work right.
 '(highlight ((t (:background "cyan"))))
 '(hl-line ((t (:inherit highlight :background "darkseagreen2"))))
 '(org-mode-line-clock ((t (:background "grey75" :foreground "red" :box (:line-width -1 :style released-button)))) t))

Keep tasks with dates off the global todo lists:

(setq org-agenda-todo-ignore-with-date nil)

Allow deadlines which are due soon to appear on the global todo lists:

(setq org-agenda-todo-ignore-deadlines (quote far))

Keep tasks scheduled in the future off the global todo lists

(setq org-agenda-todo-ignore-scheduled (quote future))

Remove completed deadline tasks from the agenda view

(setq org-agenda-skip-deadline-if-done t)

Remove completed scheduled tasks from the agenda view

(setq org-agenda-skip-scheduled-if-done t)

Remove completed items from search results

(setq org-agenda-skip-timestamp-if-done t)

Include agenda archive files when searching for things

(setq org-agenda-text-search-extra-files (quote (agenda-archives)))

show state changes in log-mode of agenda

(setq org-agenda-log-mode-items (quote (state)))

http://orgmode.org/worg/org-faq.html

;(setq org-agenda-skip-additional-timestamps-same-entry t)
(setq org-agenda-skip-additional-timestamps-same-entry nil)

do not search for time in heading when displaying a date-stamp

(setq org-agenda-search-headline-for-time nil)

open agenda in same buffer, full size

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

add diary entries in agenda view http://orgmode.org/org.html#Weekly_002fdaily-agenda

(setq org-agenda-include-diary t)

Show all future entries for repeating tasks

(setq org-agenda-repeating-timestamp-show-all t)

Show all agenda dates - even if they are empty

(setq org-agenda-show-all-dates t)

Sorting order for tasks on the agenda

(setq org-agenda-sorting-strategy
      (quote ((agenda habit-down time-up user-defined-up priority-down category-keep)
              (todo priority-down category-keep)
              (tags priority-down category-keep)
              (search category-keep))))

Start the weekly agenda today

(setq org-agenda-start-on-weekday nil)

Non-nil means skip timestamp line if same entry shows because of deadline.

(setq org-agenda-skip-timestamp-if-deadline-is-shown t)

Agenda sorting functions

(setq org-agenda-cmp-user-defined 'bh/agenda-sort)

Enable display of the time grid so we can see the marker for the current time

(setq org-agenda-time-grid
      ((daily today remove-match)
       #("----------------" 0 16
         (org-heading t))
       (800 1000 1200 1400 1600 1800 2000)))

Display tags farther right

;;(setq org-agenda-tags-column -102)
(setq org-tags-column -101); for powerplantwin 23" TFT turned 90
                                      ; degrees; should *not* differ between
                                      ; systems! Otherwise Org-files gets
                                      ; re-formatted after switching
                                      ; system
;;(when (my-system-type-is-windows)
;;    ;;(setq org-agenda-tags-column -103);; for 23" TFT turned 90 degrees
;;      (setq org-agenda-tags-column -117);; for 24" TFT turned 90 degrees
;;      )
;;(when (my-system-is-sting)
;;    (setq org-agenda-tags-column -117);; -117 for 23" TFT sting, rotated 90°
;;    )
(setq org-agenda-tags-column (- (- (window-total-width) 3))) ;; total width minus 3

Sticky agendas remain opened in the background so that you don’t need to regenerate them each time you hit the corresponding keystroke. This is a big time saver.

(setq org-agenda-sticky t)

Scrolling through agenda using C-p and C-n instead of PageUp/PageDown also in agenda. Default setting is C-p/C-n for scrolling one line at a time.

(define-key org-agenda-mode-map (kbd "C-p") 'my-scroll-down-half)
(define-key org-agenda-mode-map (kbd "C-n") 'my-scroll-up-half)

From reddit I got the settings that deadlines are not shown when SCHEDULED is set:

(setq org-agenda-skip-scheduled-if-deadline-is-shown nil)
;;(setq org-agenda-skip-deadline-prewarning-if-scheduled t)

From reddit: Adding a separator line between days. Disabled 2020-01-03 because I usually see one single day only.

(setq org-agenda-format-date (lambda (date) (concat "\n"
        (make-string (window-width) 9472)
        "\n"
        (org-agenda-format-date-aligned date))))

Agenda category icons

There is the possibility of adding icons to categories: http://julien.danjou.info/blog/2010/icon-category-support-in-org-mode

This is a neat way of beautifying the agenda.

Unfortunately, the clean way of defining the data directory relatively to the path stored in my-user-emacs-directory does not work:

(concat my-user-emacs-directory "bin/images/R6-logo_18x12.jpg") nil nil :ascent center)

I don’t know how to fix this and so I stick with the hard coded path and with a bleeding heart.

  (setq org-agenda-category-icon-alist nil)
  ;(when (my-system-type-is-windows)
    (add-to-list 'org-agenda-category-icon-alist
                 '(".*" '(space . (:width (16))))
                 )
    (add-to-list 'org-agenda-category-icon-alist
            `("rise" ,(concat my-user-emacs-directory "bin/images/RISE_icon_16x16_dark.png") nil nil :ascent center))
;;    (add-to-list 'org-agenda-category-icon-alist
;;                '("r6" "~/.emacs.d/bin/images/R6-logo_18x12.jpg" nil nil :ascent center)
;;                )
;;    (add-to-list 'org-agenda-category-icon-alist
;;                '("infonova" "~/.emacs.d/bin/images/R6-logo_18x12.jpg" nil nil :ascent center)
;;                )
;;    (add-to-list 'org-agenda-category-icon-alist
;;            `("detego" ,(concat my-user-emacs-directory "bin/images/detego-inwarehouse-logo-D_only_16x16.png") nil nil :ascent center))
;;    (add-to-list 'org-agenda-category-icon-alist
;;            `("ciso" ,(concat my-user-emacs-directory "bin/images/detego-inwarehouse-logo-D_only_16x16.png") nil nil :ascent center))
;;    (add-to-list 'org-agenda-category-icon-alist
;;            `("outlook" ,(concat my-user-emacs-directory "bin/images/detego-inwarehouse-logo-D_only_16x16.png") nil nil :ascent center))
;;    (add-to-list 'org-agenda-category-icon-alist
;;            `("ISAE3402" ,(concat my-user-emacs-directory "bin/images/detego-inwarehouse-logo-D_only_16x16.png") nil nil :ascent center))
;; OLD version without my-user-emacs-directory; with help of: https://github.com/novoid/dot-emacs/issues/2
;;OLD:    (add-to-list 'org-agenda-category-icon-alist
;;OLD:            '("ciso" "~/.emacs.d/bin/images/detego-inwarehouse-logo-D_only_16x16.png" nil nil :ascent center)
;;OLD:            )
    ;;(add-to-list 'org-agenda-category-icon-alist
    ;;           '("misc" '(space . (:width (18))))
    ;;           )
  ;  )

  (when (and (not (my-system-type-is-windows)) (not (my-system-is-karl-voit-at)))
    (add-to-list 'org-agenda-category-icon-alist
                 '(".*" '(space . (:width (16))))
                 )
    (add-to-list 'org-agenda-category-icon-alist
                 '("contacts" "~/.emacs.d/bin/images/user-identity.png" nil nil :ascent center)
                     ;; /usr/share/icons/gnome/16x16/emotes/face-smile.png
                  )
    (add-to-list 'org-agenda-category-icon-alist
                 '("public_voit" "~/.emacs.d/bin/images/application-rss+xml.png" nil nil :ascent center)
                 ;; /usr/share/icons/oxygen/16x16/mimetypes/application-rss+xml.png
                  )
;;    (add-to-list 'org-agenda-category-icon-alist
;;               '("misc" "~/.emacs.d/bin/images/emblem-new.png" nil nil :ascent center)
;;                 ;; /usr/share/icons/oxygen/16x16/emblems/emblem-new.png
;;                )
    (add-to-list 'org-agenda-category-icon-alist
                 '("hardware" "~/.emacs.d/bin/images/camera-photo.png" nil nil :ascent center)
                 ;; /usr/share/icons/oxygen/16x16/devices/camera-photo.png
                  )
    (add-to-list 'org-agenda-category-icon-alist
                 '("bwg" "~/.emacs.d/bin/images/go-home.png" nil nil :ascent center)
                 ;; /usr/share/icons/oxygen/16x16/actions/go-home.png
                  )
   )

my-org-agenda() → my-map a

Using the universal argument C-u before my-map a, I can invoke the “other” agenda (normal agenda vs. business agenda):

switch to open Agenda or open new one:

(defun my-org-agenda (&optional arg)
  "Opens the already opened agenda or opens new one instead. With
   universal prefix, use business agenda."
  (interactive "P")
  (setq my-org-agenda-start-time (current-time))

  (setq my-org-agenda-tags-column (- (- (window-total-width) 3)))
  (setq org-agenda-tags-column my-org-agenda-tags-column) ;; total width minus 3

  (if (my-buffer-exists "*Org Agenda*")
      (switch-to-buffer "*Org Agenda*")
    (progn
      (my-super-agenda)

      (setq current-timestamp
            (concat
             (format-time-string "%Y-%m-%dT%T")
             ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5)))
              (format-time-string "%z"))))
      (when (> (string-to-number (emacs-uptime "%m")) 2) ;; only flash when not part of the boot process (= Emacs runs longer than 2 minutes)
         (my-flash (format-message "Agenda built.\n(took %.2fs)" (float-time (time-subtract (current-time) my-org-agenda-start-time))))
      )
      (my-log-misc (format-message "my-org-agenda took %.2fs" (float-time (time-subtract (current-time) my-org-agenda-start-time))))

      )
    )
  )

(bind-key "a" 'my-org-agenda my-map)

my-memacs-org-agenda() → my-map m C-cm

Memacs org-agenda shortcut

(defun my-memacs-org-agenda ()
  "Opens an org-agenda with activated archive"
  (interactive)
  ;;(setq org-agenda-files (append (quote ("~/org/issues.org"))));; for testing purposes
  (org-agenda-list)
  ;;(call-interactively 'org-agenda-log-mode)
  (org-agenda-log-mode '(4))
  (call-interactively 'org-agenda-archives-mode)
  (org-agenda-archives-mode 'files)
  )
;;disabled because I needed "m";; (bind-key "m" 'my-memacs-org-agenda my-map)
(global-set-key "\C-cm" 'my-memacs-org-agenda)

Or within a shell as separate Emacs instance:

/usr/bin/emacs --load /home/vk/.emacs.d/init.el --eval '(progn (my-memacs-org-agenda))'

I aliased it within ~/.zshrc.local to memacs

my-export-agenda()

  • 2019-05-07: commented out previous postprocessing steps and switched to different output folder “var/export/” that gets synced among my devices. Postprocessing is done via cronjob.
(defun my-export-agenda()
  "Exports monthly Org-mode agenda to agenda.ics file"
  (interactive)
  (save-some-buffers)

  ;; I don't want the error messages in my exported agenda:
  (setq org-agenda-files (remove "~/org/errors.org" org-agenda-files))

  (setq max-specpdl-size 10000)
  (setq max-lisp-eval-depth 50000)
  (org-agenda-list nil nil 60)
  ;(org-agenda-list nil nil 7)
  (message "after org-agenda-list")
  ;;test;  (org-agenda-list nil nil 15)
;;  (org-agenda-write "~/org/agenda-export-raw2.ics")
  (org-agenda-write (concat my-user-emacs-directory "var/export/agenda-export.ics"))
  (message "after org-agenda-write")
;;  (setq scriptpath "~/src/postprocess_Org-mode_iCal_export/")
;;  (setq icspath (concat my-user-emacs-directory "var/export/"))
;;  (setq icspath "~/org/")
;;  (shell-command-to-string (concat
;;                          scriptpath "postprocess_Org-mode_iCal_export.py "
;;                          "-i " icspath "agenda-export-raw2.ics "
;;                          "-o " icspath "agenda-export-postprocessed2.ics "
;;                          "--overwrite "
;;                          "--remove-summary-timestamp"
;;                          )
;;                         )
;;  (shell-command-to-string (concat
;;                          scriptpath "postprocess_Org-mode_iCal_export.py "
;;                          "-i " icspath "agenda-export-raw2.ics "
;;                          "-o " icspath "agenda-export-freebusy2.ics "
;;                          "--overwrite "
;;                          "--obfuscate"
;;                          )
;;                         )
;;  (message "after shell-command-to-string")
;;  (if (my-system-type-is-gnu)
;;      (shell-command-to-string "/home/vk/bin/vk-cronjob-gary-do-unison-sync-unattended-share-all_if_host_is_reachable.sh")
;;    (message "Please do sync using unison!")
;;    )
  )

desktop notifications

2020-08-20initial setup

This article explains the basic mechanism. Also helpful: this and that.

The creation of the ~/diary file with %%(org-diary) as content:

(write-region "%%(org-diary)" nil (substitute-in-file-name "~/diary") nil)

Setup of the notification mechanism such that Org mode appointments cause desktop notifications via notify-send:

  (require 'appt)    ;; activate appointment notification
  (appt-activate t)  ;; activate appointment notification
  (setq org-agenda-include-diary t)         ;; push Org agenda items to diary
  (setq calendar-mark-diary-entries-flag t) ;; mark dates with diary entries, in the calendar window
  (setq appt-time-msg-list nil)             ;; clear list of appointments for today.
  (setq appt-message-warning-time 10        ;; warn 10 min in advance
        appt-display-interval 10            ;; repeat notification this amount of minutes; must not be 0 (arith-error)
        appt-display-diary nil              ;; do not display diary when (appt-activate) is called
        appt-display-mode-line t            ;; show in the modeline
        appt-display-format 'window         ;; display notification in window
        appt-disp-window-function 'my-appt-disp-window ;; use this function for appointment notifications
        calendar-mark-diary-entries-flag t) ;; mark diary entries in calendar

    (defun my-appt-disp-window (min-to-app new-time msg)
      "My function to display appt notifications: I prefer notify-send as I'm using GNU/Linux on all of my current hosts."
      (save-window-excursion
        (let ((msg (replace-regexp-in-string ":[a-zA-Z0-9@_:]*:$" ""  ;; remove tags
                   (replace-regexp-in-string "/" "·"                ;; get rid of slashes
                   (replace-regexp-in-string "\\[" ""               ;; get rid of opening brackets
                   (replace-regexp-in-string "\\]" ""               ;; get rid of closing brackets
                   (replace-regexp-in-string "https://" ""          ;; get rid of URL protocol
                   (replace-regexp-in-string "\\(\\[\\[\\)\\(.*?\\)\\]\\]" "\\2"  ;; replace links with their description
                   (replace-regexp-in-string "\\(\\[\\[.*\\]\\[\\)\\(.*?\\)\\]\\]" "\\2"  ;; replace links with their description
                   msg))))))))) ;; elisp org mode heading title sanitization
          (progn
          (message msg)
          (shell-command
           (concat my-user-emacs-directory "bin/desktop-notification.sh '" msg "'")
             nil nil)))));; date-string must not contain spaces (don't know why)
;; original w/o wrapper        (shell-command
;; original w/o wrapper         (concat
;; original w/o wrapper          "notify-send --urgency=critical \"Org `date +%Y-%m-%dT%H.%M`\" \"" msg "\"") nil nil)));; date-string must not contain spaces (don't know why)

    ;; add agenda→diary mechanism to the agenda hook
    (add-hook 'org-finalize-agenda-hook
      (lambda ()
        (setq appt-time-msg-list nil) ;; clear list of appointments for today.
        (org-agenda-to-appt)          ;; copy all agenda schedule to appointments
        (appt-activate 1)))           ;; active appt (appointment notification)

    ;; add agenda→diary mechanism to the org-super-agenda hook
    (add-hook 'org-super-agenda-mode-hook
      (lambda ()
        (setq appt-time-msg-list nil) ;; clear list of appointments for today.
        (org-agenda-to-appt)          ;; copy all agenda schedule to appointments
        (appt-activate 1)))           ;; active appt (appointment notification)

Unfortunately, I don’t get notifications in locked desktop state with the default setup: see this reddit thread. Therefore, I had to set up a wrapper shell script and use this within my-appt-disp-window: /home/vk/.emacs.d/bin/desktop-notification.sh

#!/bin/bash
message="${1}"
timestamp="$(date +%Y-%m-%dT%H:%M:%S+02:00)"
notify-send --urgency=critical "Org `date +%Y-%m-%dT%H.%M`" "${message}"
#end

Following thing could also be handy: add the tag rem30 for 30min pre-warning time instead of the default one. From the manual:

This pre-warning does not work yet according to my tests on id:2020-09-01-setup-desktop-notifications:

;;(setq appt-warning-time-regexp "warntime \\([0-9]+\\)");; original
(setq appt-warning-time-regexp ":rem\\([0-9]+\\):");; to be used, e.g., as tags: =:rem3:= → 3 minutes

I haven’t invested this issue such that I know a fix yet.

my-org-agenda-to-appt

For org appointment reminders http://orgmode.org/worg/org-hacks.html#sec-3_1 Get appointments for today

(when (or (my-system-type-is-gnu) (my-system-is-powerplantlinux))
  (defun my-org-agenda-to-appt ()
    (interactive)
    (setq appt-time-msg-list nil)
    (let ((org-deadline-warning-days 0))    ;; will be automatic in org 5.23
        (org-agenda-to-appt)))
  ;; Run once, activate and schedule refresh
  (my-org-agenda-to-appt)
  (appt-activate t)
  (run-at-time "24:01" nil 'org-agenda-to-appt)
  ;; 5 minute warnings
  (setq appt-message-warning-time 15)
  (setq appt-display-interval 15)
  ;; Update appt each time agenda opened.
  (add-hook 'org-finalize-agenda-hook 'org-agenda-to-appt)
  ;; Setup zenify, we tell appt to use window, and replace default function
  (setq appt-display-format 'window)
  (setq appt-disp-window-function (function appt-disp-window))
  (defun appt-disp-window (min-to-app new-time msg)
    (save-window-excursion
        (shell-command
         (concat "/usr/bin/zenity --info --title='Appointment' --text='" msg "' &") nil nil)
        )
    )
  )

my-export-month-agenda-to-png-via-screenshot()

Generates my agenda and creates a screenshot with it. I used this as a workaround before I customized my agenda export to HTML.

  • id:2016-04-12-my-export-month-agenda-to-png-via-screenshot
(defun my-export-month-agenda-to-png-via-screenshot()
  (interactive)
  (when (my-system-is-sting)
    (message "Generating agenda ...")
    (org-agenda nil "n") ; generates agenda "n" (one month without todos)
    (if (my-buffer-exists "*Org Agenda*")
        (switch-to-buffer "*Org Agenda*")
      (org-agenda-list)
      )
    (message "Waiting for Screenshot ...")
    (sit-for 1) ; (sleep 1) ... doesn't re-display and thus screenshot
                ; showed buffer before switching to agenda
    (message "Say cheese ...")

    (setq myoutput
          (shell-command-to-string "/usr/bin/import -window root /home/vk/share/roy/from_sting/agenda.png"))
    (message (concat "Screenshot done (" myoutput ")"))
    )
  )

calfw - A calendar framework for Emacs

https://github.com/kiwanami/emacs-calfw

I am not using it because of a missing visualization option I described on https://github.com/kiwanami/emacs-calfw/issues/22

Open calendar using: M-x cfw:open-org-calendar

(use-package calfw-org
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/calfw/")))
)

Provide a command to use calfw in org-agenda-custom-commands

(defun open-calfw-agenda-org(&rest args)
  (let
      (
       ;; do not duplicate deadlines
       (org-deadline-warning-days 0)
       )
    (cfw:open-org-calendar)
    )
  )

habits

«Org has the ability to track the consistency of a special category of TODOs, called “habits”.»

(setq org-global-properties (quote (("STYLE_ALL" . "habit"))))
  • position the habit graph on the agenda to the right of the default
(setq org-habit-graph-column 100)

my-reset-org-with-visibility-and-super-agenda() - reset some Org-mode stuff and reset startup visibility

This function is a combination of my-reset-org() and my-org-startup-visibility() from above.

(defun my-reset-org-with-visibility-and-super-agenda ()
  "Clears all kinds of Org-mode caches and re-builds them if possible and resets the most important buffers to their startup visibility"
  (interactive)
  (my-reset-org)
  (my-org-startup-visibility)
  )

org-agenda-exporter-settings

I export my agendas defined in org-agenda-custom-commands that have an export file associated (as of 2017-06-03: agenda_180d_filtered.html and agenda_details.html) using a daily cronjob that looks like:

0 4 * * * /usr/bin/emacs --batch --load /home/vk/.emacs.d/init.el --eval '(progn (setq org-agenda-files (append my-work-agenda-files my-nonwork-agenda-files)) (org-store-agenda-views))' >/dev/null 2>&1

As you can see, I override org-agenda-files with both, my work and my non-work agenda files. Otherwise, I’d get the host-specific non-work-only agenda which I don’t want to see in my exported agenda HTML files.

The generated HTML files are placed in a directory that gets automatically synced via Syncthing to my Android phone. The phone has browser bookmarks set for the agenda files and my desktop has icons for those bookmarks. This is how I access my agenda files on my phone.

customizing the agenda export of C-x C-w

(setq org-agenda-exporter-settings
      '((ps-number-of-columns 2)
        (ps-landscape-mode t)
        ;;disabled;                  (org-agenda-add-entry-text-maxlines 5)
        (htmlize-output-type 'css)))

my-org-obfuscate-agenda-item

This was originally developed by alphapapa as org-agenda-sharpie() and published on GitHub.

When invoked on an agenda item, you can enter some text and the agenda item gets temporarily overwritten. You can use this to obfuscate or “overwrite” agenda entries before making a screenshot for public use.

(defun org-agenda-sharpie ()
  "Censor the text of items in the agenda."
  (interactive)
  (let (regexp old-heading new-heading properties)
    ;; Save face properties of line in agenda to reapply to changed text
    (setq properties (text-properties-at (point)))

    ;; Go to source buffer
    (org-with-point-at (org-find-text-property-in-string 'org-marker
                                                         (buffer-substring (line-beginning-position)
                                                                           (line-end-position)))
      ;; Save old heading text and ask for new text
      (line-beginning-position)
      (unless (org-at-heading-p)
        ;; Not sure if necessary
        (org-back-to-heading))
      (setq old-heading (when (looking-at org-complex-heading-regexp)
                          (match-string 4))))
    (unless old-heading
      (error "Can't find heading.  How can this be?"))
    ;; Back to agenda buffer
    (setq new-heading (read-from-minibuffer "Overwrite visible heading with: "))
    (add-text-properties 0 (length new-heading) properties new-heading)
    ;; Replace agenda text
    (save-excursion
      (let ((inhibit-read-only t))
        (goto-char (line-beginning-position))
        (when (search-forward old-heading (line-end-position))
          (replace-match new-heading 'fixedcase 'literal))))))

iCal

iCal -> Org

Import iCal to Org-mode

(my-load-local-el "contrib/org-import-calendar.el")
;won't work; (use-package org-import-calendar
;won't work;  :load-path "~/.emacs.d/contrib/"
;won't work; )

(use-package org-import-icalendar)

Austrian Holidays

(require 'holidays)
(setq holiday-austria-holidays '((holiday-fixed  1  1 "Neujahr (frei)")
                                   (holiday-fixed  1  6 "Heilige Drei Könige (frei)")
                                   (holiday-easter-etc 1 "Ostermontag (frei)")
                                   (holiday-easter-etc -46 "Aschermittwoch")
                                   (holiday-easter-etc -2 "Karfreitag")
                                   (holiday-fixed  5  1 "Österreichischer Staatsfeiertag (frei)")
                                   (holiday-easter-etc 39 "Christi Himmelfahrt (frei)")
                                   (holiday-easter-etc 50 "Pfingstmontag (frei)")
                                   (holiday-easter-etc 60 "Fronleichnam (frei)")
                                   (holiday-float 5 0 2 "Muttertag")
                                   (holiday-float 6 0 2 "Vatertag")
                                   (holiday-fixed  8 15 "Mariä Himmelfahrt (frei)")
                                   (holiday-fixed 10 26 "Nationalfeiertag (frei)")
                                   (holiday-fixed 11  1 "Allerheiligen (frei)")
                                   (holiday-fixed 12  8 "Maria Empfängnis (frei)")
                                   (holiday-fixed 12 24 "Heiliger Abend (nicht frei)")
                                   (holiday-fixed 12 25 "Erster Weihnachtstag (frei)")
                                   (holiday-fixed 12 26 "Zweiter Weihnachtstag (frei)")))
  ;;(setq holiday-other-holidays '((holiday-fixed 10  3 "Tag der Deutschen Einheit")))
  (setq holiday-local-holidays holiday-austria-holidays)
  (setq calendar-holidays (append holiday-local-holidays holiday-other-holidays))
  ;; and add (load "~/Notes/holidays" t) to your .emacs and add
  ;; #+CATEGORY: Feiertag
  ;; %%(org-calendar-holiday)
  ;; to an agenda file
  ;; ######################################################
  ;; Muttertag... from http://debianforum.de/forum/viewtopic.php?f=29&t=67024

time-zone for iCal

(setq org-icalendar-timezone "Europe/Vienna")

setting destination file for iCal export

(setq org-combined-agenda-icalendar-file "~/public_html/orgmodevk478.ics")

org-mycal-export-limit()

define filter. The filter is called on each entry in the agenda. It defines a regexp to search for two timestamps, gets the start and end point of the entry and does a regexp search. It also checks if the category of the entry is in an exclude list and returns either t or nil to skip or include the entry.

(defun org-mycal-export-limit ()
  "Limit the export to items that have a date, time and a range. Also exclude certain categories."
  (setq org-tst-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ... [0-9]\\{2\\}:[0-9]\\{2\\}[^\r\n>]*?\\)>")
  (setq org-tstr-regexp (concat org-tst-regexp "--?-?" org-tst-regexp))
  (save-excursion
    ;; get categories
    (setq mycategory (org-get-category))
    ;; get start and end of tree
    (org-back-to-heading t)
    (setq mystart    (point))
    (org-end-of-subtree)
    (setq myend      (point))
    (goto-char mystart)
    ;; search for timerange
    (setq myresult (re-search-forward org-tstr-regexp myend t))
    ;; search for categories to exclude
    (setq mycatp (member mycategory org-export-exclude-category))
    ;; return t if ok, nil when not ok
    (if (and myresult (not mycatp)) t nil)))

;; activate filter and call export function
(defun org-mycal-export ()
  (let ((org-icalendar-verify-function 'org-mycal-export-limit))
    (org-export-icalendar-combine-agenda-files)))

org-mode export of calendar events to Google

http://orgmode.org/worg/org-tutorials/org-google-sync.html

Categories that should be excluded

(setq org-export-exclude-category (list "google" "private"))

Ignore :noexport: entries in iCal-export

http://comments.gmane.org/gmane.emacs.orgmode/36415

(setq org-icalendar-honor-noexport-tag t)

iCal-export

http://comments.gmane.org/gmane.emacs.orgmode/19148

(setq org-icalendar-categories (quote (all-tags category)))
'(org-icalendar-include-body 42) ;; 2020-02-24: reduced from 1000 to 42 (recommended by Bastien)
'(org-icalendar-include-sexps nil)
'(org-icalendar-include-todo nil)
'(org-icalendar-store-UID t)
'(org-icalendar-timezone "Europe/Berlin")
'(org-icalendar-use-deadline (quote (event-if-not-todo event-if-todo)))
'(org-icalendar-use-plain-timestamp nil)
'(org-icalendar-use-scheduled (quote (event-if-not-todo event-if-todo)))
(setq org-agenda-before-write-hook nil);; 2020-02-24: recommended by Bastien

Tables

(setq org-table-export-default-format "orgtbl-to-csv")

orgaggregate - Aggregate Values in a Table

https://github.com/tbanel/orgaggregate «Aggregating a table is creating a new table by computing sums, averages, and so on, out of material from the first table.»

(use-package orgtbl-aggregate
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/orgaggregate/")))
)

;won't work; (use-package org-insert-dblock
;won't work;    :load-path "~/.emacs.d/contrib/orgaggregate/"
;won't work; )
(my-load-local-el "contrib/orgaggregate/org-insert-dblock.el")

Sticky header lines

2020-02-06moved from org-table-sticky-header to org-table-header-line-mode
2021-01-01moved back to org-table-sticky-header because I can’t make it work

A minor mode to show the sticky header for org-mode tables.

(use-package org-table-sticky-header
  :ensure t
  :config
  (add-hook 'org-mode-hook 'org-table-sticky-header-mode)
  )

2020-02-01: According to this toot, this should be replaced by standard feature M-x org-table-electric-header-mode. Will have to check after I got this Org version. Already renamed, it’s now `org-table-header-line-mode`.

2020-02-06: this does not seem to be in my code so far. I keep it until it “appears”. It is reported to be part of Org v9.4.

2020-05-16: It’s now part of Org mode maint git branch. Beginning to test this feature …

2021-01-01: I don’t know why but this did never work. org-table-header-line-mode was somehow nil all the time. When enabled manually, sticky headers were not working as well. Maybe it would have required a restart. Anyhow, since org-table-sticky-header worked flowelessly for years, I go back for now.

(setq org-table-header-line-mode t)
(setq org-table-sticky-header-mode t)

see internal note id:2020-02-09-Upgrade-org-mode-for-org-table-header-line-mode

patching orgtbl-ascii-draw to accept references for min/max values

I created an issue on Github with a feature request which was posted as a patch by the original author.

Here, I apply the patch by overwriting the orgmode function:

(defun orgtbl-ascii-draw (value min max &optional width characters)
  "Draw an ascii bar in a table.
VALUE is the value to plot, it determines the width of the bar to draw.
MIN is the value that will be displayed as empty (zero width bar).
MAX is the value that will draw a bar filling all the WIDTH.
WIDTH is the span in characters from MIN to MAX.
CHARACTERS is a string that will compose the bar, with shades of grey
from pure white to pure black.  It defaults to a 10 characters string
of regular ascii characters."
  (let* ((width      (ceiling (or width 12)))
         (characters (or characters " .:;c!lhVHW"))
         (len        (1- (length characters)))
         (value      (float (if (numberp value)
                                value (string-to-number value))))
         (min        (float (if (numberp min)  ;; <------ patch
                                min (string-to-number min))))
         (max        (float (if (numberp max)  ;; <------ patch
                                max (string-to-number max))))
         (relative   (/ (- value min) (- max min)))
         (steps      (round (* relative width len))))
    (cond ((< steps             0) "too small")
          ((> steps (* width len)) "too large")
          (t (let* ((int-division (/ steps len))
                    (remainder    (- steps (* int-division len))))
               (concat (make-string int-division (elt characters len))
                       (string (elt characters remainder))))))))

This can be removed when the patch hits orgmode/maint in git.

my-thousands-separate()

Formats a long number with thousands separator like 1,234,567.89. This can not be taken as input for further calculations!

From: https://stackoverflow.com/questions/35661173/how-to-format-table-fields-as-currency-in-org-mode

(defun my-thousands-separate (num)
  "Formats the (possibly floating point) number with a thousands
separator."
  (let* ((nstr (number-to-string num))
         (dot-ind (string-match "\\." nstr))
         (nstr-no-decimal (if dot-ind
                               (substring nstr 0 dot-ind)
                             nstr))
         (nrest (if dot-ind
                    (substring nstr dot-ind)
                  nil))
         (pretty nil)
         (cnt 0))
    (dolist (c (reverse (append nstr-no-decimal nil)))
      (if (and (zerop (% cnt 3)) (> cnt 0))
          (setq pretty (cons ?, pretty)))
      (setq pretty (cons c pretty))
      (setq cnt (1+ cnt)))
    (concat pretty nrest)))
ItemQuantityPriceExt
Widget 1101001001.0010010010.00
Widget 25501001.002505005.00
Widget 3151001.0051001.00
Total12,566,016.0

Exporting

Not necessary any more:

;;(require 'ox-beamer)
;;(require 'ox-odt)
;;(require 'ox-freemind)
;;(require 'ox-taskjuggler)

Add bibtex to pdf export method:

(when (my-eval-if-binary-or-warn "pdflatex")
   (setq org-latex-pdf-process
      '("pdflatex -interaction nonstopmode -output-directory %o %f"
        "bibtex %b"
        "pdflatex -interaction nonstopmode -output-directory %o %f"
        "pdflatex -interaction nonstopmode -output-directory %o %f"))
)

Guess the master file for FILENAME from currently open files according to their extension

  • disabled 2015-03-22 because it did not help
(add-hook 'org-mode-hook
            (lambda ()
            (setq TeX-master (guess-TeX-master (buffer-file-name)))
              (message (concat "set master file to: " buffer-file-name))
              )
            )

Export subtree (by default) instead of whole buffer: http://orgmode.org/manual/The-Export-Dispatcher.html

(setq org-export-initial-scope 'subtree)

With a densly interconnected Org knowledge-base (e.g., see org-super-links) and a “few but large Org mode files” in combination with “I’m using export methods on sub-heading levels mostly”, you end up with errors that are caused by links that link stuff which is outside of the sub-heading hierarchy which should be currently exported.

Therefore, you’ll need this setting for preventing those errors. Please be aware that you won’t get notified when links that should be part of the export result get broken because of a typo or similar.

(setq org-export-with-broken-links t)

using alternative LaTeX exporter

For the records:

invoke: M-x org-export-dispatch

(require 'org-export)
(require 'org-e-latex)
(require 'ox-latex)
(add-to-list 'org-latex-classes
             '("beamer"
               "\\documentclass\[presentation\]\{beamer\}"
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))
(unless (boundp 'org-export-latex-classes)
  (setq org-export-latex-classes nil))
(add-to-list 'org-export-latex-classes
             '("article"
               "\\documentclass{article}"
               ("\\section{%s}" . "\\section*{%s}")))

org-export-latex-classes → koma-article

(add-to-list 'org-export-latex-classes
          '("koma-article"
             "\\documentclass{scrartcl}
             [NO-DEFAULT-PACKAGES]
             [EXTRA]"
             ("\\section{%s}" . "\\section*{%s}")
             ("\\subsection{%s}" . "\\subsection*{%s}")
             ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
             ("\\paragraph{%s}" . "\\paragraph*{%s}")
             ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

org-export-latex-classes → ACM

(add-to-list 'org-export-latex-classes
          '("ACM"
             "\\documentclass{acm_proc_article-sp}
             [NO-DEFAULT-PACKAGES]
             [EXTRA]"
             ("\\section{%s}" . "\\section*{%s}")
             ("\\subsection{%s}" . "\\subsection*{%s}")
             ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
             ("\\paragraph{%s}" . "\\paragraph*{%s}")
             ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

LaTeX classes

http://orgmode.org/org.html#Header-and-sectioning

BEGIN of LaTeX class definitions

(when (my-eval-if-binary-or-warn "pdflatex")
  (with-eval-after-load 'ox-latex
  ;;(message (concat "################################################\norg-latex-classes = [" org-latex-classes "]"))

Customized «scrartcl»

(add-to-list 'org-latex-classes
             '("scrartcl"
               "\\documentclass\[a4paper,parskip=half\]\{scrartcl\}"
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))

«scrartclsmall»

  • 2014-10-16: does NOT work yet. Most probably because savetrees does not work well with inputenc
(add-to-list 'org-latex-classes
             '("scrartclsmall"
               "\\documentclass\[a4paper,parskip=half\]\{scrartcl\}\\usepackage\{savetrees\}"
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))

«detego»

  • 2017-09-13:
(add-to-list 'org-latex-classes
             '("detego"
               "\\documentclass\[a4paper,parskip=half,11pt,headinclude=false,footinclude=false\]\{scrartcl\}
                \\usepackage\[ngerman,american\]\{babel\}\\usepackage\{eurosym\}\\usepackage\{xspace\}\\usepackage\[usenames,dvipsnames\]\{xcolor\}
                \\usepackage\[protrusion=true,factor=900\]\{microtype\}\\usepackage\{enumitem\}
                \\definecolor\{DispositionColor\}\{RGB\}\{0,54,90\}
                \\usepackage\{helvet\}
                \\renewcommand\{\\familydefault\}\{\\sfdefault\}
                \\DeclareRobustCommand\{\\myacro\}\[1\]\{\\textsc\{\\lowercase\{#1\}\}\} %%  abbrevations using small caps
                \\usepackage{scrlayer-scrpage} \\rehead{\\includegraphics\[height=1cm\]{{c:/Users/karl.voit/.emacs.d/bin/images/Detego-Logo-209x41.png}}} \\pagestyle{scrheadings} %% Logo in header
                \\newenvironment{NOTES}{}{}  %% declares org-reveal environment in PDF output
                \\usepackage[space]{grffile} %% enable spaces in filenames of includegraphics
                %% colorful headings:
                %\\setheadsepline\{.4pt\}\[\\color\{DispositionColor\}\]
                \\renewcommand\{\\headfont\}\{\\normalfont\\sffamily\\color\{DispositionColor\}\}
                \\renewcommand\{\\pnumfont\}\{\\normalfont\\sffamily\\color\{DispositionColor\}\}
                \\addtokomafont\{disposition\}\{\\color\{DispositionColor\}\}
                \\addtokomafont\{caption\}\{\\color\{DispositionColor\}\\footnotesize\}
                \\addtokomafont\{captionlabel\}\{\\color\{DispositionColor\}\}

                \\usepackage\{enumitem\}
                \\setlist\{noitemsep\} %% kills the space between items

               "
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))

«rise»

  • 2019-12-16
(add-to-list 'org-latex-classes
             '("rise"
               "\\documentclass\[a4paper,parskip=half,11pt,headinclude=false,footinclude=false\]\{scrartcl\}
                \\usepackage\[ngerman,american\]\{babel\}\\usepackage\{eurosym\}\\usepackage\{xspace\}\\usepackage\[usenames,dvipsnames\]\{xcolor\}
                \\usepackage\[protrusion=true,factor=900\]\{microtype\}\\usepackage\{enumitem\}
                \\definecolor\{DispositionColor\}\{RGB\}\{0,54,90\}
                \\usepackage\{helvet\}
                \\renewcommand\{\\familydefault\}\{\\sfdefault\}
                \\DeclareRobustCommand\{\\myacro\}\[1\]\{\\textsc\{\\lowercase\{#1\}\}\} %%  abbrevations using small caps
                \\usepackage{scrlayer-scrpage} \\rehead{\\includegraphics\[height=1cm\]{{c:/Users/karl.voit/.emacs.d/bin/images/RISE_logo_202x500.jpeg}}} \\pagestyle{scrheadings} %% Logo in header
                \\newenvironment{NOTES}{}{}  %% declares org-reveal environment in PDF output
                \\usepackage[space]{grffile} %% enable spaces in filenames of includegraphics
                %% colorful headings:
                %\\setheadsepline\{.4pt\}\[\\color\{DispositionColor\}\]
                \\renewcommand\{\\headfont\}\{\\normalfont\\sffamily\\color\{DispositionColor\}\}
                \\renewcommand\{\\pnumfont\}\{\\normalfont\\sffamily\\color\{DispositionColor\}\}
                \\addtokomafont\{disposition\}\{\\color\{DispositionColor\}\}
                \\addtokomafont\{caption\}\{\\color\{DispositionColor\}\\footnotesize\}
                \\addtokomafont\{captionlabel\}\{\\color\{DispositionColor\}\}

                \\usepackage\{enumitem\}
                \\setlist\{noitemsep\} %% kills the space between items

               "
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))

«lyrics»

  • 2017-03-23: 2-column layout sans-serif for lyrics
(add-to-list 'org-latex-classes
             '("lyrics"
               "\\documentclass\[a4paper,parskip=half\]\{scrartcl\}\\usepackage\{savetrees\}
                \\usepackage\{lmodern\} \\renewcommand*\\sfdefault\{lcmss\} \\renewcommand*\\familydefault\{\\sfdefault\}"
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))

«lyrics2» 2 column version of «lyrics»

(add-to-list 'org-latex-classes
             '("lyrics2"
               "\\documentclass\[a4paper,parskip=half,twocolumn\]\{scrartcl\}\\usepackage\{savetrees\}
                \\usepackage\{lmodern\} \\renewcommand*\\sfdefault\{lcmss\} \\renewcommand*\\familydefault\{\\sfdefault\}"
               ("\\section\{%s\}" . "\\section*\{%s\}")
               ("\\subsection\{%s\}" . "\\subsection*\{%s\}")
               ("\\subsubsection\{%s\}" . "\\subsubsection*\{%s\}")))

Adding TUGRAZ letter export class format

(add-to-list 'org-export-latex-classes
             '("TUGRAZletter"
               "\\documentclass{scrlttr2}
                \\usepackage{tugrazletter}
                [NO-DEFAULT-PACKAGES]
                [EXTRA]"
               ("\\section{%s}" . "\\section*{%s}")))

END of LaTeX class definitions

   );; with-eval-after-load
);; if pdflatex is found

htmlize

htmlize is an HTML export functionality used by org-reveal or ox-clip (when not in org-mode).

(use-package htmlize
  :ensure t
  :defer 110
  :config
  (require 'htmlize)
)

ox-slack

From GitHub: derived from MD export but optimized for syntax sub-set of slack.

This package provides the interactive function org-slack-export-to-clipboard-as-slack, which copies the region to the kill-ring in slack format. From there it should be easy to paste the resultant text into your slack client.

ox-gfm (GitHub flavoured markdown) is needed for ox-slack:

(use-package ox-gfm
  :defer 110
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :if (my-system-type-is-windows)
  )
(use-package ox-slack
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/ox-slack/")))
  :defer 110
  :if (my-system-type-is-windows)
  )

ox-pandoc - Export via Pandoc

https://github.com/kawabata/ox-pandoc - «This is another exporter that translates Org-mode file to various other formats via Pandoc.»

(when (my-eval-if-binary-or-warn "pandoc")
  (use-package ox-pandoc
    :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/ox-pandoc/")))
    :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
    :defer 110
    ;; :if (or (my-system-type-is-gnu) (my-system-type-is-windows))
    :init

    ;; define the list of entries manually because the default one is somewhat arbitrary: https://github.com/kawabata/ox-pandoc/issues/9
    ;; for example, markdown was missing in my list
    ;; see also id:2018-07-14-markdown-missing-in-ox-pandoc
    ;; export-to vs. export-as → file vs. buffer
    (setq org-pandoc-menu-entry
    '(
      (?x "to docx and open." org-pandoc-export-to-docx-and-open)
      (?X "to docx." org-pandoc-export-to-docx)
      (?r "to revealjs and open." org-pandoc-export-to-revealjs-and-open)
      (?R "as revealjs." org-pandoc-export-as-revealjs)
      (?o "to odt and open." org-pandoc-export-to-odt-and-open)
      (?O "to odt." org-pandoc-export-to-odt)
      (?8 "to opendocument and open." org-pandoc-export-to-opendocument-and-open)
      (?8 "to opendocument." org-pandoc-export-to-opendocument)
      ;;(?( "as opendocument." org-pandoc-export-as-opendocument)
      ;;(?0 "to jats." org-pandoc-export-to-jats)
      ;;(?0 "to jats and open." org-pandoc-export-to-jats-and-open)
      ;;(?  "as jats." org-pandoc-export-as-jats)
      ;;(?2 "to tei." org-pandoc-export-to-tei)
      ;;(?2 "to tei and open." org-pandoc-export-to-tei-and-open)
      ;;(?" "as tei." org-pandoc-export-as-tei)
      (?l "to latex-pdf and open." org-pandoc-export-to-latex-pdf-and-open)
      (?L "to latex-pdf." org-pandoc-export-to-latex-pdf)
      ;;(?k "to markdown." org-pandoc-export-to-markdown)
      (?k "to markdown and open." org-pandoc-export-to-markdown-and-open)
      (?K "as markdown." org-pandoc-export-as-markdown)
      ;;(?3 "to markdown_mmd." org-pandoc-export-to-markdown_mmd)
      (?m "to markdown_mmd and open." org-pandoc-export-to-markdown_mmd-and-open)
      (?M "as markdown_mmd. (reddit|Wiki.js)" org-pandoc-export-as-markdown_mmd)
      (?s "to markdown_strict & open" org-pandoc-export-to-markdown_strict-and-open)
      (?S "as markdown_strict." org-pandoc-export-as-markdown_strict)
      ;;(?: "to rst." org-pandoc-export-to-rst)
      (?1 "to rst and open." org-pandoc-export-to-rst-and-open)
      (?2 "as rst." org-pandoc-export-as-rst)
      ;;(?p "to plain." org-pandoc-export-to-plain)
      (?p "to plain and open." org-pandoc-export-to-plain-and-open)
      (?P "as plain." org-pandoc-export-as-plain)
      ;;(?4 "to html5." org-pandoc-export-to-html5)
      (?h "to html5 and open." org-pandoc-export-to-html5-and-open)
      (?H "as html5." org-pandoc-export-as-html5)
      (?3 "to html5-pdf and open." org-pandoc-export-to-html5-pdf-and-open)
      (?4 "to html5-pdf." org-pandoc-export-to-html5-pdf)
      ;;(?6 "to markdown_phpextra." org-pandoc-export-to-markdown_phpextra)
      ;;(?6 "to markdown_phpextra and open." org-pandoc-export-to-markdown_phpextra-and-open)
      ;;(?& "as markdown_phpextra." org-pandoc-export-as-markdown_phpextra)
      ;;(?7 "to markdown_strict." org-pandoc-export-to-markdown_strict)
      ;;(?9 "to opml." org-pandoc-export-to-opml)
      ;;(?9 "to opml and open." org-pandoc-export-to-opml-and-open)
      ;;(?\) "as opml." org-pandoc-export-as-opml)
      ;;(?< "to slideous." org-pandoc-export-to-slideous)
      ;;(?< "to slideous and open." org-pandoc-export-to-slideous-and-open)
      ;;(?, "as slideous." org-pandoc-export-as-slideous)
      (?= "to ms-pdf and open." org-pandoc-export-to-ms-pdf-and-open)
      (?- "to ms-pdf." org-pandoc-export-to-ms-pdf)
      ;;(?> "to textile." org-pandoc-export-to-textile)
      (?t "to textile and open." org-pandoc-export-to-textile-and-open)
      (?T "as textile." org-pandoc-export-as-textile)
      ;;(?a "to asciidoc." org-pandoc-export-to-asciidoc)
      (?a "to asciidoc and open." org-pandoc-export-to-asciidoc-and-open)
      (?A "as asciidoc." org-pandoc-export-as-asciidoc)
      (?b "to beamer-pdf and open." org-pandoc-export-to-beamer-pdf-and-open)
      (?B "to beamer-pdf." org-pandoc-export-to-beamer-pdf)
      ;;(?c "to context-pdf and open." org-pandoc-export-to-context-pdf-and-open)
      ;;(?C "to context-pdf." org-pandoc-export-to-context-pdf)
      ;;(?d "to docbook5." org-pandoc-export-to-docbook5)
      (?d "to docbook5 and open." org-pandoc-export-to-docbook5-and-open)
      (?D "as docbook5." org-pandoc-export-as-docbook5)
      (?e "to epub3 and open." org-pandoc-export-to-epub3-and-open)
      (?E "to epub3." org-pandoc-export-to-epub3)
      ;;(?f "to fb2." org-pandoc-export-to-fb2)
      ;;(?f "to fb2 and open." org-pandoc-export-to-fb2-and-open)
      ;;(?F "as fb2." org-pandoc-export-as-fb2)
      ;;(?g "to gfm." org-pandoc-export-to-gfm)
      ;;(?g "to gfm and open." org-pandoc-export-to-gfm-and-open)
      ;;(?G "as gfm." org-pandoc-export-as-gfm)
      ;;(?h "to html4." org-pandoc-export-to-html4)
      (?h "to html4 and open." org-pandoc-export-to-html4-and-open)
      (?H "as html4." org-pandoc-export-as-html4)
      ;;(?i "to icml." org-pandoc-export-to-icml)
      ;;(?i "to icml and open." org-pandoc-export-to-icml-and-open)
      ;;(?I "as icml." org-pandoc-export-as-icml)
      ;;(?j "to json." org-pandoc-export-to-json)
      (?j "to json and open." org-pandoc-export-to-json-and-open)
      (?J "as json." org-pandoc-export-as-json)
      ;;(?m "to man." org-pandoc-export-to-man)
      ;;(?m "to man and open." org-pandoc-export-to-man-and-open)
      ;;(?M "as man." org-pandoc-export-as-man)
      ;;(?n "to native." org-pandoc-export-to-native)
      ;;(?n "to native and open." org-pandoc-export-to-native-and-open)
      ;;(?N "as native." org-pandoc-export-as-native)
      ;;(?q "to commonmark." org-pandoc-export-to-commonmark)
      ;;(?q "to commonmark and open." org-pandoc-export-to-commonmark-and-open)
      ;;(?Q "as commonmark." org-pandoc-export-as-commonmark)
      ;;(?r "to rtf." org-pandoc-export-to-rtf)
      (?f "to rtf and open." org-pandoc-export-to-rtf-and-open)
      (?F "as rtf." org-pandoc-export-as-rtf)
      ;;(?s "to s5." org-pandoc-export-to-s5)
      ;;(?s "to s5 and open." org-pandoc-export-to-s5-and-open)
      ;;(?S "as s5." org-pandoc-export-as-s5)
      ;;(?t "to texinfo." org-pandoc-export-to-texinfo)
      ;;(?t "to texinfo and open." org-pandoc-export-to-texinfo-and-open)
      ;;(?T "as texinfo." org-pandoc-export-as-texinfo)
      ;;(?u "to dokuwiki." org-pandoc-export-to-dokuwiki)
      (?u "to dokuwiki and open." org-pandoc-export-to-dokuwiki-and-open)
      (?U "as dokuwiki." org-pandoc-export-as-dokuwiki)
      ;;(?v "to revealjs." org-pandoc-export-to-revealjs)
      ;;(?w "to mediawiki." org-pandoc-export-to-mediawiki)
      (?5 "to mediawiki and open." org-pandoc-export-to-mediawiki-and-open)
      (?6 "as mediawiki." org-pandoc-export-as-mediawiki)
      ;;(?y "to slidy." org-pandoc-export-to-slidy)
      ;;(?y "to slidy and open." org-pandoc-export-to-slidy-and-open)
      ;;(?Y "as slidy." org-pandoc-export-as-slidy)
      ;;(?z "to dzslides." org-pandoc-export-to-dzslides)
      ;;(?z "to dzslides and open." org-pandoc-export-to-dzslides-and-open)
      ;;(?Z "as dzslides." org-pandoc-export-as-dzslides)
      ;;(?{ "to muse." org-pandoc-export-to-muse)
      ;;(?{ "to muse and open." org-pandoc-export-to-muse-and-open)
      ;;(?[ "as muse." org-pandoc-export-as-muse)
      ;;(?} "to zimwiki." org-pandoc-export-to-zimwiki)
      ;;(?} "to zimwiki and open." org-pandoc-export-to-zimwiki-and-open)
      ;;(?] "as zimwiki." org-pandoc-export-as-zimwiki)
      ;;(?~ "to haddock." org-pandoc-export-to-haddock)
      ;;(?~ "to haddock and open." org-pandoc-export-to-haddock-and-open)
      ;;(?^ "as haddock." org-pandoc-export-as-haddock)
      (?7 "to epub2 and open." org-pandoc-export-to-epub2-and-open)
      (?8 "to epub2." org-pandoc-export-to-epub2)
      (?9 "Slack (clipboard)" org-slack-export-to-clipboard-as-slack)
      (?0 "as Slack" org-slack-export-as-slack)
      )
    )

  )
)

ox-asciidoc - Export to AsciiDoc

https://github.com/yashi/org-asciidoc - «An Org Mode Exporter Backend For AsciiDoc»

(use-package ox-asciidoc
  ;;:ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :defer 110
)

ox-rst - Export to reStructuredText

2019-09-28: disabled because I don’t need it at the moment

https://github.com/msnoigrs/ox-rst

(my-load-local-el "contrib/ox-rst/ox-rst.el")
(require 'ox-rst)

FIXXME: I don’t know why loading via use-package is not working with this one: package-compute-transaction: Package ‘ox-rst-’ is unavailable

(use-package ox-rst
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/ox-rst/")))
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :defer 110
  :if (my-system-type-is-windows)
  )

Org-Reveal - generate nice presentations out of Org-mode

https://github.com/yjwen/org-reveal

  • Reveal.js is a tool for creating good-looking HTML presentations, authored by Hakim El Hattab.
  • For an example of a reveal.js presentation, see here.
  • Org-Reveal exports your Org documents to reveal.js presentations.
  • With Org-reveal, you can create beautiful presentations with 3D effects from simple but powerful Org contents.
(use-package ox-reveal
  :ensure t
  ;;:if (my-system-type-is-windows)
  :defer 110
  :config

  ;;(setq org-reveal-root "file:///d:/reveal.js")
  (cond ((my-system-type-is-gnu)
         (setq org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js")
         (setq org-reveal-extra-css "file:///home/vk/.emacs.d/bin/reveal_theme_night_local.css"))
        ((string-equal system-name "GRZN17009")
         (setq org-reveal-root "file:///C:/Users/karl.voit/.emacs.d/bin/reveal.js/")
         (setq org-reveal-extra-css "file:///C:/Users/karl.voit/.emacs.d/bin/reveal_theme_night_local.css"))
        ((string-equal system-name "cosmo")
         (setq org-reveal-root "file:///C:/Users/John/AppData/Roaming/.emacs.d/bin/reveal.js/")
         (setq org-reveal-extra-css "file:///C:/Users/John/AppData/Roaming/.emacs.d/bin/reveal_theme_night_local.css"))
        (t
         (setq org-reveal-root "http://cdn.jsdelivr.net/reveal.js/3.0.0/"))
    )

  ;; my preferred defaults:
  (setq org-reveal-hlevel 2)
  (setq org-reveal-postamble "<p> Created by Karl. </p>")
  (setq org-reveal-center nil)
  (setq org-reveal-progress t)
  (setq org-reveal-history nil)
  (setq org-reveal-control t)
  (setq org-reveal-keyboard t)
  (setq org-reveal-overview nil)
  (setq org-reveal-transition "default")
  ;; - transitions:
  ;;   - default
  ;;   - cube
  ;;   - page
  ;;   - concave
  ;;   - zoom
  ;;   - linear
  ;;   - fade
  ;;   - none
  (setq org-reveal-theme "night")
  ;; - Styles:
  ;;   - black (default)
  ;;   - white
  ;;   - league
  ;;     - gray one
  ;;   - sky
  ;;     - nice bright one
  ;;   - beige
  ;;     - nice bright one
  ;;   - simple
  ;;     - bright
  ;;   - serif
  ;;     - old school
  ;;   - blood
  ;;     - cool!
  ;;   - *night*
  ;;     - very nice
  ;;   - moon
  ;;   - solarized
)

ox-clip - formatted copy from Org-mode to system clipboard

This module copies selected regions in org-mode as formatted text on the clipboard that can be pasted into other applications. When not in org-mode, the htmlize library is used instead.

For Windows the html-clip-w32.py script will be installed. It works pretty well, but I noticed that the hyperlinks in the TOC to headings don’t work, and strike-through doesn’t seem to work. I have no idea how to fix either issue.

Mac OSX needs textutils and pbcopy, which should be part of the base install.

Linux needs a relatively modern xclip. https://github.com/astrand/xclip

There is one command: `ox-clip-formatted-copy’ that should work across Windows, Mac and Linux.

(require ‘htmlize)

  • https://libraries.io/emacs/ox-clip
  • https://github.com/jkitchin/scimax
  • use: M-x ox-clip-formatted-copy
  • 2017-11-20: moved from ELPA package to a checkout from https://github.com/jkitchin/ox-clip
    • resulted in:
      [...]
      config • ox-clip - formatted copy from Org-mode to system clipboard …
      Importing package-keyring.gpg...done
      ad-handle-definition: ‘url-cache-extract’ got redefined
      Contacting host: jorgenschaefer.github.io:443
      gnutls.c: [1] (Emacs) GnuTLS library not found
      Opening TLS connection to ‘jorgenschaefer.github.io’...
      Opening TLS connection with ‘gnutls-cli --x509cafile /usr/ssl/certs/ca-bundle.crt -p 443 jorgenschaefer.github.io’...done
      Opening TLS connection to ‘jorgenschaefer.github.io’...done
      Contacting host: jorgenschaefer.github.io:443
      Contacting host: orgmode.org:80
      Contacting host: stable.melpa.org:80
      Contacting host: elpa.gnu.org:80
      Package refresh done
      Setting ‘package-selected-packages’ temporarily since "emacs -q" would overwrite customizations
      For information about GNU Emacs and the GNU system, type C-h C-a.
      <C-lwindow> is undefined
      Error running timer ‘require’: (error "Unknown keyword: :export-block")
              
    • I’ll have to re-check later-on when I’ve time to fix this.
(when (or
       (and (my-system-type-is-gnu) (my-eval-if-binary-or-warn "xclip") (not (my-system-is-karl-voit-at)))
       (and (my-system-type-is-darwin) (my-eval-if-binary-or-warn "textutils") (my-eval-if-binary-or-warn "pbcopy"))
       (my-system-type-is-windows);; For Windows the html-clip-w32.py script will be installed.
       )
  (use-package ox-clip
    :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/ox-clip/")))
      ;;:if
    :ensure t
    :defer 110
    )
  )

lazyblorg

I wrote my own blogging system named lazyblorg and generate my own blog with it.

my-lazyblorg-test() - blog article preview

When writing a blog article, this function generates a local version of the blog article and shows it in the browser.

(if (my-system-type-is-gnu)
    (defun my-lazyblorg-test()
      "Saves current blog entry to file and invoke lazyblorg process with it"
      (interactive)
      (save-excursion
        (search-backward ":blog:");; search begin of current (previous) blog entry
        (beginning-of-line nil)
        (set-mark-command nil);; set mark
        (org-cycle);; close org-mode heading and sub-headings
        (next-line);; goto next org-mode heading (this should be next line after blog entry)
        (beginning-of-line nil)
        (let ((p (point));; copy region
              (m (mark)))
          (if (< p m)
              (kill-ring-save p m)
            (kill-ring-save m p)))
        (find-file "/tmp/lazyblorg-preview.org");; fixed temporary file (will be overwritten)
        (erase-buffer);; I told you!
        (yank);; paste region from above
        (save-buffer);; save to disk
        (kill-buffer "lazyblorg-preview.org");; destroy last evidence
        (previous-line);;
        (org-cycle);; close org-mode heading and sub-headings
        ;; invoke lazyblorg:
        (shell-command-to-string "/home/vk/src/lazyblorg/preview_blogentry.sh");; invoke shell script
        )
      )
  )

my-jump-to-lazyblorg-heading-according-to-URL-in-clipboard() → my-map l

One of the advantages of lazyblorg is, that a blog entry can be written anywhere in my Org-mode files. This is great for composing blog articles but not so great for locating it in my Org-mode files when I need to access the source of an article.

Therefore, I wrote the following function. The process is now very easy: I locate the article (using my blog search?) in the web browser. Then I copy the URL to the system clipboard. I switch to Emacs and call the function below to jump to the article. Easy as that. :-)

Gets “public voit”-URL from clipboard and jumps to its Org-mode heading:

(defun my-jump-to-lazyblorg-heading-according-to-URL-in-clipboard ()
  "Retrieves an URL from the clipboard, gets its Org-mode source,
   extracts the ID of the article and jumps to its Org-mode heading"
  (interactive)
  (let (
        ;; Getting URL from the clipboard. Since it may contain
        ;; some text properties we are using substring-no-properties
        ;; function
        (url (substring-no-properties (current-kill 0)))
        ;; This is a check string: if the URL in the clipboard
        ;; doesn't start with this, an error message is shown
        (domain "karl-voit.at")
      )
    ;; Check if URL string is from my domain (all other strings do
    ;; not make any sense here)
    (if (string-match (upcase domain) (upcase url))
        ;; Retrieving content by URL into new buffer asynchronously
        (url-retrieve url
                      ;; call this lambda function when URL content is retrieved
                      (lambda (status)
                         ;; Extrating and preparing the ID
                         (let* (
                                ;; Limit the ID search to the top 1000 characters of the buffer
                                (pageheader (buffer-substring 1 1000))
                                ;; Start index of the id
                                (start (string-match "<meta name=\"orgmode-id\" content=\"" pageheader))
                                ;; End index of the id
                                (end (string-match "\" />" pageheader start))
                                ;; Amount of characters to skip for the openning tag
                                (chars-to-skip (length "<meta name=\"orgmode-id\" content=\""))
                                ;; Extract ID
                                (lazyblorg-id (if (and start end (< start end))
                                                  ;; ... extract it and return.
                                                  (substring pageheader (+ start chars-to-skip) end)
                                                nil))
                                )
                           (message (concat "Looking for id:" lazyblorg-id " ..."))
                           (org-open-link-from-string (concat "id:" lazyblorg-id))
                           )
                         )
                      )
      (message (concat "Sorry: the URL \"" (substring url 0 (length domain)) "...\" doesn't contain \"" domain "\". Aborting."))
      ;;(message (concat "domain: " domain))
      ;;(message (concat "url:    " url))
      )
    )
  )

binding the function: 2021-07-07 disabled because I’m happy with M-x ... and I don’t use this binding

(bind-key "l" #'my-jump-to-lazyblorg-heading-according-to-URL-in-clipboard my-map)

ox-koma-letter

2019-09-28: disabled because I don’t need it at the moment.

I configured the KOMA letter exporter according to this page.

You can get a default drawer template by invoking C-c C-e for export and then choose # and koma-letter.

FIXXME: there is a big KOMA letter on the result page which I don’t know how to get rid of.

(use-package ox-koma-letter
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-contrib/lisp/")))
)
(eval-after-load 'ox '(require 'ox-koma-letter))

I prefer the language German in my letters:

(eval-after-load 'ox-koma-letter
  '(progn
     (add-to-list 'org-latex-classes
                  '("my-letter"
                    "\\documentclass\{scrlttr2\}
     \\usepackage[german]{babel}
     \\setkomavar{frombank}{(1234)\\,567\\,890}
     \[DEFAULT-PACKAGES]
     \[PACKAGES]
     \[EXTRA]"))

     (setq org-koma-letter-default-class "my-letter")))

Contact management

Yes, of course I do manage contact data about people within Org-mode.

See http://julien.danjou.info/org-contacts.html

These are rather simple settings for it:

Set org-contacts defaults that differ from standard

(setq org-contacts-address-property "CITY")
(setq org-contacts-birthday-property "BORN")
(setq org-contacts-files (list (concat my-org-files-path "contacts.org")))
(setq org-contacts-icon-property "PHOTOGRAPH")
(custom-set-variables
 '(org-contacts-address-property "CITY")
 '(org-contacts-birthday-property "BORN")
 '(org-contacts-icon-property "PHOTOGRAPH")
 )

Take a look at my-org-region-to-property() as well.

Loading novoid/helm-org-contacts (a fork of tmalsburg/helm-org-contacts) to quickly link contacts.

(use-package helm-org-contacts
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/helm-org-contacts/")))
   :after org
)
(defun my-helm-org-contacts-refresh-cache ()
  "Wrapper for helm-org-contacts-cache that adds time measurement and logging."
  (interactive)
  (setq my-helm-org-contacts-refresh-cache-start-time (current-time))

  (save-some-buffers t) ;; get latest contact changes
  (helm-org-contacts-refresh-cache)

  (setq current-timestamp
    (concat
      (format-time-string "%Y-%m-%dT%T")
      ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5)))
      (format-time-string "%z"))))
  (my-log-misc (format-message "helm-org-contacts-refresh-cache took %.2fs" (float-time (time-subtract (current-time) my-helm-org-contacts-refresh-cache-start-time))))
  (when (> (string-to-number (emacs-uptime "%m")) 2) ;; only flash when not part of the boot process (= Emacs runs longer than 2 minutes)
    (my-flash (format-message "helm-org-contacts-cache took %.2fs"            (float-time (time-subtract (current-time) my-helm-org-contacts-refresh-cache-start-time)))))
)

babel - working with source code

Activate Babel languages:

(when (my-system-type-is-windows)
  (org-babel-do-load-languages
   'org-babel-load-languages
   '(
     (python . t)
     (shell . t)
     (org . t)
     (emacs-lisp . t)
     (sql . t)
;;disabled 2019-06-26;;     (restclient . t)
     (plantuml . t)
     ))
  )

(when (my-system-type-is-gnu)
  (org-babel-do-load-languages
   'org-babel-load-languages
   '(
;     (ipython . t)
     (python . t)
     (ruby . t)
     (gnuplot . t)
     (shell . t)
     (org . t)
     (R . t)
     (emacs-lisp . t)
     (ditaa . t)
     (dot . t)
     (plantuml . t)
     ))
  )

DISABLED 2018-03-16 because of id:2018-03-16-exports-results-parameter-ignored: Inhibit evaluation of code blocks during export http://orgmode.org/manual/Exporting-code-blocks.html

;;  (setq org-export-babel-evaluate nil)

The issue with org-export-babel-evaluate set to nil disables the results parameter may be mitigated by #+Property: header-args :cache yes according to this page.

Do not prompt to confirm evaluation: This may be dangerous - make sure you understand the consequences of setting this – see the docstring for details

(setq org-confirm-babel-evaluate nil)

When some code generates an image file, display it in the results:

(add-hook 'org-babel-after-execute-hook 'org-display-inline-images)

http://orgmode.org/manual/Sparse-trees.html#index-org_002dshow_002dentry_002dbelow-179

(setq org-show-entry-below (quote ((default))))

see id:2014-12-21-org-screen

(require 'org-screen)

(require 'ob-screen)
(defvar org-babel-default-header-args:screen
  '(
    (:results . "silent")
    (:session . "default")
    (:cmd . "/bin/zsh")
    (:terminal . "/usr/bin/gnome-terminal"))
  "Default arguments to use when running screen source blocks.")

http://kitchingroup.cheme.cmu.edu/blog/2014/12/21/Capturing-stderr-from-Python-in-org-mode-take-2/

  • 2016-04-08: doesn’t work
(if (my-system-type-is-gnu)
    ;; does not seem to work with Windows:
    (setq org-babel-python-command "python -i -c \"import sys; sys.stderr = sys.stdout\"")
    (setq org-babel-python-command "python")
    )

Switch babel to python 3 (see id:2019-01-26-python3-src-blocks)

Following …

(setq org-babel-python-command "ipython3")

… causes an issue on Windows:

print('hello')

Use python3 instead of ipython3:

(setq org-babel-python-command "python3")

Note: The general Python interpretor is set elsewhere: python-shell-interpreter

Redirect stderr to stdout in order to see it in the results: id:2015-01-11-redirect-org-babel-sh-stderr-to-stdout

(if (my-system-type-is-gnu)
  ;outdated: org-babel-sh-command was removed with org-mode v8.3:
  ;outdated;  (setq org-babel-sh-command
  ;outdated;        "~/bin/zsh_stderr_redirected_to_stdout.sh")
  ;(setq shell-file-name "~/.emacs.d/bin/zsh_stderr_redirected_to_stdout.sh");; id:2015-01-11-redirect-org-babel-sh-stderr-to-stdout
  )

re-direct stderr to stdout and add an additional line:

From: Ken Mankoff <mankoff@gmail.com>
Newsgroups: gmane.emacs.orgmode
Subject: Re: No output from babel shell src block
Date: Thu, 12 May 2016 15:36:03 -0400
Message-ID: <m237pn83x8.fsf@gmail.com>
(setq org-babel-default-header-args:sh
      '((:prologue . "exec 2>&1") (:epilogue . ":"))
      '((:epilogue . ":"))
      )

ob-async: asynchronous babel execution

https://github.com/astahlman/ob-async

  • not yet available as a package
  • [ ] re-check availability
    • 2018-06-27 no package in my sources yet (again)
(use-package ob-async
  :ensure t
  :config
  (add-to-list 'org-ctrl-c-ctrl-c-hook 'ob-async-org-babel-execute-src-block)
  )

PlantUML

Forget dot. :-)

PlantUML is a handy tool for drawing simple diagrams. It is part of Org-mode since 2010 and is a wrapper to dot, allowing higher-level definitions.

As an example, the following block gets exported as a cool diagram:

Alice -> Bob: synchronous call
Alice ->> Bob: asynchronous call
(require 'ob-plantuml)
(setq org-plantuml-jar-path (concat my-user-emacs-directory "bin/plantuml.jar")) ;; I keep the jar file in my ".emacs.d/bin"

For a maximum of editing experience and a very cool preview, you also want to install plantuml-mode:

(use-package plantuml-mode
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/plantuml-mode")))
  :config

  (my-log-hostspecific "plantuml-mode-version" plantuml-mode-version)

  (add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode)) ;; Enable plantuml-mode for PlantUML files
  (add-to-list
   'org-src-lang-modes '("plantuml" . plantuml))
  )
M-x plantuml-previeworder of preference: SVG, PNG, ASCII
C-c C-cpreview: renders a PlantUML diagram from the current buffer in the best supported format
C-u C-c C-cpreview in other window
C-u C-u C-c C-cpreview in other frame

org-crypt

Activate org-crypt if gpg is installed:

(when (my-eval-if-binary-or-warn "gpg")
    (require 'org-crypt)

Encrypt all entries before saving

(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance (quote ("crypt" "project")))

GPG key to use for encryption:

Note for Windows 10 users: I had to import the private/secret key to my pgp4win/Kleopatra key management tool. ~/.gnupg/ or ~/.babun/cygwin/.gnupg/ did not result in Emacs being able to find the key.

(setq org-crypt-key "77B9E3C5")

OLD key:

(setq org-crypt-key "8A614641")

encrypting whole files: http://orgmode.org/worg/org-tutorials/encrypting-files.html

(require 'epa-file)

disabling auto-save for sensitive files http://anirudhs.chaosnet.org/blog/2005.01.21.html

DISABLED 2020-02-04 because of constand data loss when Emacs crashes.

    (define-minor-mode my-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))))
    ;; disabling auto-save for gpg file extension
    (setq auto-mode-alist
          (append '(("\\.gpg$" . sensitive-mode))
                  auto-mode-alist)
          )

Do not ask for disabling auto-save

(setq org-crypt-disable-auto-save nil)

From this page: Auto-saving does not cooperate with org-crypt.el: so you need to turn it off if you plan to use org-crypt.el quite often. Otherwise, you’ll get an (annoying) message each time you start Org.

To turn it off only locally, you can insert this:

-*- buffer-auto-save-file-name: nil; -*-

DISABLED 2020-02-04 because of constand data loss when Emacs crashes.

(setq auto-save-default nil)

END of org-crypt setup

)

Reference management → my-map (|)

Do read http://karl-voit.at/2015/12/26/reference-management-with-orgmode/

I do manage references to white papers and books using a self-made concept based on RefTeX and Org-mode.

If I’d start all over again, I’d take a look at org-ref which was not around yet back then.

Set my default bibliography file:

(setq reftex-default-bibliography '("~/archive/library/references.bib"))

Set citation format (no clue what I did here)

(defadvice reftex-format-citation (before eval-citation-format)
  (setq format (eval format)))

Inserting citations when using and when defining them:

(defun org-mode-reftex-setup ()
  (load-library "reftex")
  (and (buffer-file-name) (file-exists-p (buffer-file-name))
       (progn
         ;;enable auto-revert-mode to update reftex when bibtex file changes on disk
         (global-auto-revert-mode t)
         (reftex-parse-all)
         ;;add a custom reftex cite format to insert links
         (reftex-set-cite-format
          '((?b . "[[bib:%l][%l.bib]]")
            (?c . "[[cite:%l][%l]]")
            (?p . "[[pdf:%l][%l.pdf]]")
            (?a . "[[notes:%l][%l-notes.pdf]]")
            (?s . "[[pdf:%l-self][%l-self.pdf]]")
            (?t . "%t")
            (?h . (concat "** %l - %t\n:PROPERTIES:\n:CREATED: "
                          "<" (substring (format-time-string (org-time-stamp-format t t)) 1 -1) ">"
                          "\n:ID: %l\n:END:\n[[bib:%l][%l.bib]]\n[[pdf:%l][%l.pdf]]\n\n*** Abstract\n\n#+BEGIN_QUOTE\n#+END_QUOTE\n\n"))
            (?n . (concat "*** PDF Annotations: [[notes:%l][%l-notes.pdf]]\n:PROPERTIES:\n:CREATED: "
                          "<" (substring (format-time-string (org-time-stamp-format t t)) 1 -1) ">"
                          "\n:ID: %l-notes\n:END:\n\n"
                          "\#+begin_src sh :results output :eval no-export\n"
                          "${HOME}/bin/vkextract_annotations_to_orgmode_snippet.sh %l\n"
                          "#+end_src"))
            ))))

Binding the keyboard shortcuts:

(define-key org-mode-map (kbd "C-c )") 'reftex-citation)
(define-key org-mode-map (kbd "C-c (") 'org-mode-reftex-search))
  • disabled 2015-05-14 - double code from above?
;; http://orgmode.org/worg/org-faq.html#using-reftex-in-org-mode
(defun org-mode-reftex-setup ()
  (load-library "reftex")
  (and (buffer-file-name)
       (file-exists-p (buffer-file-name))
       (reftex-parse-all))
  (define-key org-mode-map (kbd "C-c )") 'reftex-citation))

disabled 2015-05-14: see id:2015-05-14-disable-orgmode-reftex-autoload

(add-hook 'org-mode-hook 'org-mode-reftex-setup)
  • disabled 2015-05-14 - I don’t use “CHECK_NEEDED” any more
(add-hook 'org-mode-hook
          (lambda ()
            (if (member "CHECK_NEEDED" org-todo-keywords-1)
                  (org-mode-reftex-setup))))

org-mode-reftex-search ()

(defun org-mode-reftex-search ()
  ;;jump to the notes for the paper pointed to at from reftex search
  (interactive)
  (org-open-link-from-string (format "[[cite:%s]]" (reftex-citation t))))

Setup my own org-mode-reftex-setup:

  • See also: id:2015-05-14-disable-orgmode-reftex-autoload
(defun org-mode-reftex-setup ()
  (setq TeX-master t)
  (load-library "reftex")
  (and (buffer-file-name)
     (file-exists-p (buffer-file-name))
     (progn
       (reftex-parse-all)
       (reftex-set-cite-format "[[cite:%l][%l]]")))
  (define-key org-mode-map (kbd "C-c )") 'reftex-citation)
  (define-key org-mode-map (kbd "C-c (") 'org-mode-reftex-search))
(add-hook 'org-mode-hook 'org-mode-reftex-setup)

(bind-key (kbd "R") #'org-mode-reftex-setup my-map)
;; 2015-05-14: does NOT work (yet). See id:2015-05-14-disable-orgmode-reftex-autoload

org-ref

On 2019-09-12, I disabled my DIY-reference-management (above) and started to test drive org-ref. This might not be in a stable status.

Setup according to https://github.com/jkitchin/org-ref:

;; setting the path using the my-org-files-path:
;;(setq reftex-default-bibliography '("~/org/org-ref.bib"))                         ;; Its value is ("~/org/org-ref.bib")
(setq reftex-default-bibliography `( ,(concat my-org-files-path "org-ref.bib")))  ;; Its value is ("~/org/org-ref.bib")


;; see org-ref for use of these variables
(setq org-ref-bibliography-notes (concat my-org-files-path "org-ref.org")  ;;"~/org/org-ref.org"
      org-ref-default-bibliography `( ,(concat my-org-files-path "org-ref.bib"))
      org-ref-pdf-directory "~/archive/library/org-ref/")



(setq bibtex-completion-bibliography (concat my-org-files-path "org-ref.bib")
      bibtex-completion-library-path "~/archive/library/org-ref"
      bibtex-completion-notes-path "~/archive/library/helm-bibtex-notes")

;; open pdf with system pdf viewer (works on mac)
(setq bibtex-completion-pdf-open-function
  (lambda (fpath)
    (start-process "open" "*open*" "open" fpath)))

;; alternative
;; (setq bibtex-completion-pdf-open-function 'org-open-file)


;(setq org-latex-pdf-process (list "latexmk -shell-escape -bibtex -f -pdf %f"))

(require 'org-ref)
(require 'doi-utils)

Org-mode docu → my-map o

One of the benefits of Emacs is, that it comes with its complete manual. Same holds for the Org-mode. With this shortcut, I am able to navigate through the org manual instantly:

Append the Org-mode documentation from the git repository to the info-paths:

(autoload 'info "info.el")
(eval-after-load 'info
  ;;(add-to-list 'Info-additional-directory-list (concat my-user-emacs-directory "contrib/org-mode/doc/")) ;; causes "void-variable" error
  (setq Info-additional-directory-list (concat my-user-emacs-directory "contrib/org-mode/doc/"))
  )

Bind a keyboard shortcut to open the Org manual:

(bind-key (kbd "o") (lambda()
                               (interactive)
                               (info "(org)")
                               )
  my-map
  )

Reading RSS feeds

I did test importing some RSS feeds into Orgmode but the decided to stay with my usual Android RSS reader.

org-feed - aggregating RSS feeds in news.org file:

(setq org-feed-alist
      '(
  ("heise"
         "http://www.heise.de/newsticker/heise.rdf"
         (concat my-org-files-path "news.org") "heise")
  ("Dilbert"
         "http://feeds.feedburner.com/DilbertDailyStrip"
         (concat my-org-files-path "news.org") "Dilbert")
  )
      )

org-protocol-capture-html - turn HTML into Org-mode

https://github.com/alphapapa/org-protocol-capture-html

org-protocol is awesome, but browsers do a pretty poor job of turning a page’s HTML content into plain-text. However, Pandoc supports converting from HTML to org-mode, so we can use it to turn HTML into Org-mode content! It can even turn HTML tables into Org tables!

  • see: id:2016-07-10-inst-org-protocol-capture
  • I disabled the package because I do have to play around with it to make it work on my hosts.
(when (my-eval-if-binary-or-warn "pandoc")
  (use-package org-protocol-capture-html
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-protocol-capture-html/")))
  )
  (require 'org-protocol-capture-html)
)

org-mind-map

I found org-mind-map via an article on irreal.

At the moment, I am not planning on using it intensively. It is maybe a cool method to visualize the structure of some Org-mode files of mine for demonstration purposes for novice or non-Org-users.

(use-package org-mind-map
  ;;:ensure t
  :defer 120
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-mind-map/")))
  :config ;; executed after loading package
)

2017-10-14: Unfortunately, I do have issues with this tool so that I had to disable it. Maybe I’d give it another try in a couple of months or so.

org-sidebar

2019-12-17DISABLED: I don’t need it at the moment

For testing org-sidebar-tree from https://github.com/alphapapa/org-sidebar

disabled setup via quelpa because of quelpa error (see above):

(use-package org-sidebar
  :quelpa (org-sidebar :fetcher github :repo "alphapapa/org-sidebar"))

Dependency = org-ql

(use-package org-sidebar
  :ensure t
  ;;:load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/org-sidebar/")))
)

my-recache-all

2020-02-12written by me

I tend to manually invoke this for executing all re-caching functions at once before leaving the computer for a longer period of time.

(defun my-recache-all ()
  "Calls misc re-cache functions to refresh caches and make new content accessible. This might take long."
  (interactive)

  (if (> (string-to-number (emacs-uptime "%m")) 2) ;; (= Emacs runs longer than 2 minutes)
     (setq my-boot-process nil)
     (setq my-boot-process t)
  )

  (my-helm-org-contacts-refresh-cache)
  (when (eq my-boot-process nil)
    (my-flash "continuing with \"my-refile-recache\" ..."))
  (my-refile-recache)

  (when (not my-boot-process)
     (my-rise-update-project-tables) ;; omit this on boot process since it takes ~20min
  )
)

Performance Optimizations

2020-05-04added to my config
2020-12-06disabled to avoid interference with experimental org branch for performance

In 2020-05-04, that reddit discussion pointed me to this Org ML thread where the following adaptations were published to compensate the performance degradation due to large Org mode files I do have:

;; Unfortunately isearch, sets inhibit-point-motion-hooks and we
;; cannot even use cursor-sensor-functions as a workaround
;; I used a less ideas approach with advice to isearch-search-string as
;; a workaround

(defun org-find-text-property-region (pos prop)
  "Find a region containing PROP text property around point POS."
  (require 'org-macs) ;; org-with-point-at
  (org-with-point-at pos
    (let* ((beg (and (get-text-property pos prop) pos))
           (end beg))
      (when beg
        (setq beg (or (previous-single-property-change pos prop)
                      beg))
        (setq end (or (next-single-property-change pos prop)
                      end))
        (unless (equal beg end)
          (cons beg end))))))

;; :FIXME: re-hide properties when point moves away
(define-advice isearch-search-string (:after (&rest _) put-overlay)
  "Reveal hidden text at point."
  (when-let ((region (org-find-text-property-region (point) 'invisible)))
    (with-silent-modifications
      (put-text-property (car region) (cdr region) 'org-invisible
(get-text-property (point) 'invisible)))
      (remove-text-properties (car region) (cdr region) '(invisible nil))))

;; this seems to be unstable, but I cannot figure out why
(defun org-restore-invisibility-specs (&rest _)
  ""
   (let ((pos (point-min)))
     (while (< (setq pos (next-single-property-change pos 'org-invisible nil
(point-max))) (point-max))
       (when-let ((region (org-find-text-property-region pos 'org-invisible)))
           (with-silent-modifications
             (put-text-property (car region) (cdr region) 'invisible
(get-text-property pos 'org-invisible))
             (remove-text-properties (car region) (cdr region) '(org-invisible
nil)))))))

(add-hook 'post-command-hook #'org-restore-invisibility-specs)

(defun org-flag-region (from to flag spec)
  "Hide or show lines from FROM to TO, according to FLAG.
SPEC is the invisibility spec, as a symbol."
  (pcase spec
    ('outline
     (remove-overlays from to 'invisible spec)
     ;; Use `front-advance' since text right before to the beginning of
     ;; the overlay belongs to the visible line than to the contents.
     (when flag
       (let ((o (make-overlay from to nil 'front-advance)))
         (overlay-put o 'evaporate t)
         (overlay-put o 'invisible spec)
         (overlay-put o 'isearch-open-invisible #'delete-overlay))))
    (_
     (with-silent-modifications
       (remove-text-properties from to '(invisible nil))
       (when flag
         (put-text-property from to 'invisible spec)
         )))))

;; This normally deletes invisible text property. We do not want this now.
(defun org-unfontify-region (beg end &optional _maybe_loudly)
  "Remove fontification and activation overlays from links."
  (font-lock-default-unfontify-region beg end)
  (let* ((buffer-undo-list t)
         (inhibit-read-only t) (inhibit-point-motion-hooks t)
         (inhibit-modification-hooks t)
         deactivate-mark buffer-file-name buffer-file-truename)
    (decompose-region beg end)
    (remove-text-properties beg end
                            '(mouse-face t keymap t org-linked-text t
                                         ;; Do not remove invisible during
fontification
                                         ;; invisible t
                                         intangible t
                                         org-emphasis t))
    (org-remove-font-lock-display-properties beg end)))

debug message: config orgmode finished.

(message "→★ orgmode finished in %.2fs" (float-time (time-subtract (current-time) my-org-config-start-time)))

PDF

For viewing and editing PDF files, Emacs has a lot to offer.

2019-04-08: Had to disable showing PDFs within Windows Emacs because of frequent Emacs crashes(!) after displaying PDF buffers. :-(

org-pdfview

This seems to be a pre-requisite to pdf-tools.

(use-package org-pdfview
  ;:if (my-system-type-is-gnu)
  :ensure t
  :defer 110
  :config
)

pdf-tools

pdf-tools provides really cool functionality to annotate PDF files within Emacs.

History:

  • My first steps with many drawbacks: id:2014-12-02-pdf-tools
    • This does not work so far. Unmet (and many) dependencies are in my way. This is quite frustrating.
  • 2018-08-12: first working installation after doing sudo apt install elpa-pdf-tools-server in Debian GNU/Linux stable

The package:

(use-package pdf-tools
  ;:if (my-system-type-is-gnu)
  :ensure t
  :defer 120
  :pin manual ;; manually update (Source: http://pragmaticemacs.com/emacs/view-and-annotate-pdfs-in-emacs-with-pdf-tools/ )
  :config
  (pdf-tools-install)
  (eval-after-load 'org '(require 'org-pdfview))

pdf-tools configuration:

Some default configs (as in id:2019-06-29-fix-pdf-tools-cosmo) do feature ("\\.pdf\\'" . default) which might then overwriting my desired setting. Therefore, I just make sure that this setting is not in the list of org-file-apps any more:

(setq org-file-apps (delete '("\\.pdf\\'" . default) org-file-apps))
;;(add-to-list 'org-file-apps '("\\.pdf\\'" . org-pdfview-open))
(add-to-list 'org-file-apps '("\\.pdf::\\([[:digit:]]+\\)\\'" . org-pdfview-open))

Open pdfs scaled to fit page: (Source)

(setq-default pdf-view-display-size 'fit-page)

Use normal isearch: (Source)

(define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward)

Workaround for this issue on Org-mode 9 on Windows:

;  (when (my-system-type-is-windows)
    (add-to-list 'org-file-apps '("\\.pdf\\'" . (lambda (file link) (org-pdfview-open link))))
;  )

Bindings:

  (bind-keys :map pdf-view-mode-map
   ;;       ("f1" . hydra-pdftools/body)
          ("<s-spc>" .  pdf-view-scroll-down-or-next-page)
          ("g"  . pdf-view-first-page)
          ("G"  . pdf-view-last-page)
          ("l"  . image-forward-hscroll)
          ("h"  . image-backward-hscroll)
          ("j"  . pdf-view-next-page)
          ("k"  . pdf-view-previous-page)
          ("e"  . pdf-view-goto-page)
          ("u"  . pdf-view-revert-buffer)
;;          ("al" . pdf-annot-list-annotations)
;;          ("ad" . pdf-annot-delete)
;;          ("aa" . pdf-annot-attachment-dired)
;;          ("am" . pdf-annot-add-markup-annotation)
;;          ("at" . pdf-annot-add-text-annotation)
          ("y"  . pdf-view-kill-ring-save)
          ("i"  . pdf-misc-display-metadata)
          ("s"  . pdf-occur)
          ("b"  . pdf-view-set-slice-from-bounding-box)
          ("r"  . pdf-view-reset-slice)
          ("m"  . pdf-annot-add-highlight-markup-annotation)
          ("<C-n>" . '(lambda nil (interactive) (pdf-view-next-line-or-page 20)))
          ("<C-p>" . '(lambda nil (interactive) (pdf-view-previous-line-or-page 20)))
)

Setting highlighting color:

;:init
(with-eval-after-load 'pdf-view-mode
  (when (my-system-type-is-windows)
    (push '(color . "yellow") pdf-annot-default-markup-annotation-properties)
  )
)
;    (setq pdf-annot-default-markup-annotation-properties '(color . "yellow"))
);; end of pdf-tools
  • [ ] FIXXME: this is a dirty workaround in order to make pdf-view mode work as expected by me:
    • I could not fix following settings:
      • F1 shows the hydra within pdf-view-mode
      • yellow is the default markup annotation color setting
(defun my-pdf-tools ()
  (interactive)
  (define-key pdf-view-mode-map [f1] 'hydra-pdftools/body)
  (push '(color . "yellow") pdf-annot-default-markup-annotation-properties)
)

pdf-view-restore

Support for opening last known pdf position in pdf-view-mode provided by pdf-tools.

(use-package pdf-view-restore
  ;:if (my-system-type-is-gnu)
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/pdf-view-restore/")))
  :after pdf-tools
  :defer 110
  :config

  ;; temporary workaround for https://github.com/007kevin/pdf-view-restore/issues/1
  ;; to prevent metadata files stored in each folder of a PDF-file
  ;; FIXXME: replace with corresponding setting when implemented
  (setq pdf-view-restore-filename "~/.emacs.d/var/pdf-view-restore")

  (add-hook 'pdf-view-mode-hook 'pdf-view-restore-mode)
)

Tramp

2020-02-13added for testing
(customize-set-variable 'tramp-default-user "vk")

Misc modes/packages (part II)

Misc sources for packages:

Garbage Collection Magic Hack

Recommended by this reddit comment because of performance issues.

(use-package gcmh
  :ensure t
  :config
  (setq garbage-collection-messages t)
  (setq gcmh-verbose t)
)

tabbar

«Tabbar is an emacs minor mode that displays a tab bar at the top, similar to the idea of web browser’s tabs.»

I just did not think that the screen space was used wisely for the minor advantage.

(when (my-system-type-is-gnu)
    (use-package tabbar
       :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
    )
  )

post-mode

post-mode was used for composing Usenet postings which I do in slrn since decades and not within Emacs as before.

(setq post-variable-signature-source "~/daten/nobackup/funnies/good_sigs/allsigs.txt")
(setq post-signature-directory "~/daten/nobackup/funnies/good_sigs/")

MiniMap

«Minimap is a feature provided by the Sublime editor. It shows a smaller, “minibar”, display of the current buffer alongside the main editing window.»

(use-package minimap
  :if (my-system-type-is-gnu)
  :ensure t
  :diminish minimap-mode
  :defer 110
  :config ;; executed after loading package
  (setq minimap-window-location 'right)
  ;;deactivated;; (setq minimap-window-location 'right)
  (global-set-key (kbd "S-<f10>") 'minimap-mode)
)

TWiki

TWiki syntax highlighting

;(use-package erin))
(my-load-local-el "contrib/erin.el")

Twitter

I shortly tested Emacs as a Twitter client but did not find advantages enough to use it instead of the Twitter webpage.

(add-to-list 'load-path (expand-file-name (concat my-user-emacs-directory "contrib/twittering-mode/")))
(use-package twittering-mode)
(setq twittering-timer-interval 300)  ; Update your timeline each 300 seconds (5 minutes)
(setq twittering-url-show-status nil) ; Keeps the echo area from showing all the http processes
(setq twittering-icon-mode t)         ; Show icons
(setq twittering-use-show-minibuffer-length t) ; Show character count in compose buffer
;; I added is.gd support myself, pull request sent.
;; standard options are tinyurl and toly
;(setq twittering-tinyurl-service 'is.gd)
;; See http://www.reverttoconsole.com/blog/nix/twitter-mode-for-emacs-with-oauth/
(setq twittering-use-master-password t)
;; This tells twittering-mode which time line buffers
;; to open when starting
(setq twittering-initial-timeline-spec-string
      '(":friends"
        ":replies"
        ":direct_messages"
        ":search/tugraz/"
        ":search/tagstore/"
       ))
;; some key bindings
(add-hook 'twittering-mode-hook
          (lambda ()
            (mapc (lambda (pair)
                    (let ((key (car pair))
                          (func (cdr pair)))
                      (define-key twittering-mode-map
                        (read-kbd-macro key) func)))
                  '(("R" . twittering-native-retweet)
                    ("l" . twittering-goto-next-thing)))))
;; enable spell check
(add-hook 'twittering-edit-mode-hook (lambda () (ispell-minor-mode) (flyspell-mode)))
;; filter by regex  http://www.emacswiki.org/emacs/TwitteringMode -> "10 May 2011"
(setq twittering-tweet-filters '("foobar42" "foobar 23"))
(defun twittering-filter-tweets ()
  (setq non-matching-statuses '())
  (dolist (status twittering-new-tweets-statuses)
    (setq matched-tweets 0)
    (dolist (pat twittering-tweet-filters)
      (if (string-match pat (cdr (assoc 'text status)))
          (setq matched-tweets (+ 1 matched-tweets))))
    (if (= 0 matched-tweets)
        (setq non-matching-statuses (append non-matching-statuses `(,status)))))
  (setq new-statuses non-matching-statuses))
(add-hook 'twittering-new-tweets-hook 'twittering-filter-tweets)

UndoTree

Some people prefer the undo-tree visualization and method for undoing things in Emacs.

(use-package undo-tree
  :ensure t
  :diminish undo-tree-mode
  :config ;; executed after loading package
  (autoload 'undo-tree "undo-tree.el")
)

open-resource

http://code.google.com/p/emacs-open-resource/ «It uses recentf’s files buffer to provide a nice interface for selecting found files. Files are searched using the “find” utility in Unix. The results are filtered with grep for unwanted patterns and with awk to return relative paths (relative paths are shorter and thus more readable).»

(add-to-list 'load-path (expand-file-name (concat my-user-emacs-directory "contrib/emacs-open-resource-read-only")))
(use-package open-resource)
(global-set-key "\C-cr" 'open-resource)

whitespace-mode + style

https://www.emacswiki.org/emacs/WhiteSpace

«This package is a minor mode to visualize blanks (TAB, (HARD) SPACE and NEWLINE).»

  • from Twitter 2012-05-22: @emacs_knight
;;(when (or (my-system-type-is-gnu) (my-system-is-blanche))
(whitespace-mode)
(setq whitespace-style '(trailing space-before-tab indentation empty space-after-tab)) ;; only show bad whitespace
  ;;(face trailing lines-tail) whitespace-line-column 80) ;; highlight long lines tails (setq whitespace-style
;;  )

(e)diff

Visualizing differences of files.

ediff from command line usage: emacs -diff file1 file2

(when (my-eval-if-binary-or-warn "diff")
  (defun command-line-diff (switch)
    (let ((file1 (pop command-line-args-left))
        (file2 (pop command-line-args-left)))
      ;;    (ediff file1 file2)))
      (ediff-merge-files file1 file2)))

  (add-to-list 'command-switch-alist '("diff" . command-line-diff))
)

FIXXME: Compare to https://github.com/alphapapa/unpackaged.el#smerge-mode smerge-mode with its hydra from alphapapa.


Here are some settings from this configuration mentioned in that reddit thread: not tested yet

(setq ediff-forward-word-function 'forward-char) ;; from https://emacs.stackexchange.com/a/9411/17066
(setq ediff-highlight-all-diffs t)
(setq ediff-keep-variants nil)
(setq ediff-window-setup-function 'ediff-setup-windows-plain)

Counting words → M-=

Counting lines, words, characters.

(use-package wc
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
)

Recent files

«Recentf is a minor mode that builds a list of recently opened files. This list is is automatically saved across sessions on exiting Emacs - you can then access this list through a command or the menu.»

(autoload 'recentf "recentf.el")
(recentf-mode 1)
(setq recentf-max-menu-items 50)
(setq recentf-max-saved-items 50)

Confluence: vk-open-as-confluence-page() → my-map C

Editing Confluence wiki pages (up to Confluence 3.x)

Unfortunately, Altlassian moved away from a Wiki style editing mode to a WYSIWYG editor. This killed my beautiful “edit in Emacs” method:

(when (my-system-type-is-windows)

 ;(add-to-list 'load-path (expand-file-name "~/.emacs.d/contrib/confluence-el-1.5/"))
 (use-package confluence)
 (setq confluence-url "http://product.infonova.at/confluence/rpc/xmlrpc")
 (add-to-list 'auto-mode-alist '("\\.\\(confluence\\)$" . confluence-mode))

 (dolist (hook '(confluence-mode-hook))
   (add-hook hook (lambda ()
             (flyspell-mode 1)
             (ispell-change-dictionary "american")
             (flyspell-buffer)
             ))
   )

 (defun vk-open-as-confluence-page ()
   "Takes current line (delimited by brackets, two spaces or pipe) and opens it as Confluence page in IR6 space"
   (interactive)
   (save-excursion
     (re-search-backward "\\(\\] \\|  \\|\* \\|| \\)")  ;; search for "] " or "  " or "| "
     (forward-char)
     (forward-char)
     (setq start-pos (point))
     (re-search-forward "\\( \\[\\|  \\| |\\)")  ;; search for " [" or "  " or " |"
     (backward-char)
     (backward-char)
     (setq end-pos (point))
     (setq myname (buffer-substring start-pos end-pos))
                                ;(message "Confluence page name: [%s]" myname)
     (confluence-get-page myname "IR6")
                                ;(confluence-get-page myname)
     )
   )

  (bind-key "C" #'vk-open-as-confluence-page my-map)

)

message-outlook.el - sending mail with Outlook

With this package, I can C-c C-o on mailto:user@example.com in my Org mode. A new Emacs message composing buffer appears and with message-send-and-exit() (C-c C-c) the composed email doesn’t get sent to the recipient(s) and instead appears as an email in a new composing window of Outlook where I may continue composing or send it to the recipient(s).

(when (my-eval-if-binary-or-warn "outlook")
  (use-package message-outlook
     :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
  )
)

Editing Outlook emails in Emacs

Continue editing an email in Emacs which is being currently composed within Outlook. When finished composing it in Emacs, it can then be sent back to the open Outlook window again.

Disabled, because there are some annoying things related to this workflow.

when (or (my-system-is-powerplantlinux) (my-system-type-is-windows))

  (use-package outlookedit
     :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
  )
  ;;(use-package outlookedit)

(defvar mno-get-outlook-body
  "cscript //B //Job:getMessage c:/Users/karl.voit/bin/outlook_emacs.wsf")
(defvar mno-put-outlook-body
  "cscript //B //Job:putMessage c:/Users/karl.voit/bin/outlook_emacs.wsf")

;; ######################################################
;; use mail-mode for email or usenet postings:
(add-to-list 'auto-mode-alist '("\\.\\(mail\\|email\\|posting\\)$" . mail-mode))
(dolist (hook '(mail-mode-hook))
  (add-hook hook (lambda ()
            (mail-mode-auto-fill)
            (auto-fill-mode 1)
            (flyspell-mode 1)
            (ispell-change-dictionary "german8")
            (flyspell-buffer)
            ))
  )

;; http://www.emacswiki.org/emacs/MailMode
(add-hook 'mail-mode-hook
   (lambda ()
     (font-lock-add-keywords nil
                      '(("^[ \t]*>[ \t]*>[ \t]*>.*$"
                         (0 'mail-multiply-quoted-text-face))
                        ("^[ \t]*>[ \t]*>.*$"
                         (0 'mail-double-quoted-text-face))))))

)

real-auto-save: Periodically auto-save buffers

2020-02-04re-activated after data loss when XOrg crashes on t490

Automatically save buffers more often within certain modes:

(use-package real-auto-save
  :ensure t
  :after org
  :config

  (setq real-auto-save-use-idle-timer t);; t → use *idle* timer instead; nil → use fixed timer

  ;; Auto save interval is 10 seconds by default. You can change it:
  (setq real-auto-save-interval 1800) ;; every 30 minutes of idle time

  ;; 2021-06-19 XOrg on Xubuntu 20.04 is stable ;; (when (my-system-is-rise)
  ;; 2021-06-19 XOrg on Xubuntu 20.04 is stable ;;   (setq real-auto-save-interval 60);; after one minute idle, save on the lenovo t490 + Xubuntu 19.10 due to XOrg instability issues
  ;; 2021-06-19 XOrg on Xubuntu 20.04 is stable ;; )

  ;;(setq real-auto-save-use-idle-timer t);; FIXXME: testing https://github.com/ChillarAnand/real-auto-save/issues/43
  ;;(setq real-auto-save-interval 15) ;; FIXXME: testing https://github.com/ChillarAnand/real-auto-save/issues/43
  ;;(real-auto-save-activate-advice) ;; suppress confirmation for Makefiles
  (add-hook 'org-mode-hook 'real-auto-save-mode)
)

spray (speed-reading region) → my-map s

A speed reading mode for Emacs.

(use-package spray
  :ensure t
  :defer 110
  :config ;; executed after loading package
  :bind (:map my-map ("s" . spray-mode))
)

yafolding - Folding based on identation → M-RET C-TAB

I do use this folding method for Python source code. It is not perfect but most of the time, it’s a good companion to me.

(use-package yafolding
  :ensure t
  :defer 110
  :mode ("\\.xml\\'" . yafolding-mode)

  :config ;; executed after loading package

  (add-to-list 'auto-mode-alist '("\\.xml$" . nxml-mode))
  ;;(add-to-list 'auto-mode-alist '("\\.xml$" . yafolding-mode))
  ;;(global-set-key (kbd "<C-S-return>") 'yafolding-toggle-all)
  ;;(global-set-key (kbd "<C-return>") 'yafolding-toggle-element)
  :bind (("<M-S-return>" . yafolding-toggle-all)
         ("<M-return>" . yafolding-toggle-element)
         ("<C-Tab>" . yafolding-toggle-element))
)

Naked full screen Emacs → F12

I love to work in full-screen mode where nothing is distracting me from the information I am working with: the content of Emacs.

There are some packages out there that provide this functionality such as writeroom-mode or darkroom-mode (see discussion of them here).

The code below was written by Bastien Guerry and adopted by me to meet my requirements: https://gist.github.com/bzg/8578998

Conditions when loading:

(when (my-system-type-is-gnu)
(defvar my-toggle-naked-emacs-status nil
  "state of fullscreen/naked Emacs mode. t means fullscreen, nil means normal")
(make-variable-buffer-local 'my-toggle-naked-emacs-status)

;; See http://bzg.fr/emacs-hide-mode-line.html
(defvar-local hidden-mode-line-mode nil)
(defvar-local hide-mode-line nil)

(define-minor-mode hidden-mode-line-mode
  "Minor mode to hide the mode-line in the current buffer."
  :init-value nil
  :global nil
  :variable hidden-mode-line-mode
  :group 'editing-basics
  (if hidden-mode-line-mode
      (setq hide-mode-line mode-line-format
            mode-line-format nil)
    (setq mode-line-format hide-mode-line
          hide-mode-line nil))
  (force-mode-line-update)
  ;; Apparently force-mode-line-update is not always enough to
  ;; redisplay the mode-line
  (redraw-display)
  (when (and (called-interactively-p 'interactive)
             hidden-mode-line-mode)
    (run-with-idle-timer
     0 nil 'message
     (concat "Hidden Mode Line Mode enabled.  "
             "Use M-x hidden-mode-line-mode to make the mode-line appear."))))

;; A small minor mode to use a big fringe
(defvar bzg-big-fringe-mode nil)
(define-minor-mode bzg-big-fringe-mode
  "Minor mode to hide the mode-line in the current buffer."
  :init-value nil
  :global t
  :variable bzg-big-fringe-mode
  :group 'editing-basics
  (if (not bzg-big-fringe-mode)
      (set-fringe-style nil)
    (set-fringe-mode
     (/ (- (frame-pixel-width)
           (* 100 (frame-char-width)))
        3)
     )
    ))

;; Command to toggle the display of the mode-line as a header
(defvar-local header-line-format nil)
(defun mode-line-in-header ()
  (interactive)
  (if (not header-line-format)
      (setq header-line-format mode-line-format
            mode-line-format nil)
    (setq mode-line-format header-line-format
          header-line-format nil))
  (set-window-buffer nil (current-buffer)))

(defun my-toggle-naked-emacs ()
  "Toggle fullscreen/naked Emacs and normal Emacs"
  (interactive)
  (cond (my-toggle-naked-emacs-status
         ;; make it naked!

         (setq my-toggle-naked-emacs-status nil)
         ;; Prevent the cursor from blinking
         (blink-cursor-mode 0)
         ;; Don't let Emacs hurt your ears
         (setq visible-bell t)

         ;; This is bound to f11 in Emacs 24.4
         (toggle-frame-fullscreen)
         ;; ;; Who use the bar to scroll?
         ;; (scroll-bar-mode 0)

         (menu-bar-mode 0)

         ;; You can also set the initial frame parameters
         ;; (setq initial-frame-alist
         ;;       '((menu-bar-lines . 0)
         ;;         (tool-bar-lines . 0)))

         ;; Activate hidden-mode-line-mode
         (hidden-mode-line-mode 1)

         ;; If you want to hide the mode-line in all new buffers
         ;; (add-hook 'after-change-major-mode-hook 'hidden-mode-line-mode)

         ;; Alternatively, you can paint your mode-line in White but then
         ;; you'll have to manually paint it in black again
         ;; (custom-set-faces
         ;;  '(mode-line-highlight ((t nil)))
         ;;  '(mode-line ((t (:foreground "white" :background "white"))))
         ;;  '(mode-line-inactive ((t (:background "white" :foreground "white")))))

         ;; reset fringe with:
         ;; (set-fringe-mode nil)

         ;; Now activate this global minor mode
         (bzg-big-fringe-mode 1)

         ;; To activate the fringe by default and deactivate it when windows
         ;; are split vertically, uncomment this:
         ;; (add-hook 'window-configuration-change-hook
         ;;           (lambda ()
         ;;             (if (delq nil
         ;;                       (let ((fw (frame-width)))
         ;;                         (mapcar (lambda(w) (< (window-width w) fw))
         ;;                                 (window-list))))
         ;;                 (bzg-big-fringe-mode 0)
         ;;               (bzg-big-fringe-mode 1))))

         ;; Use a minimal cursor
         ;; (setq cursor-type 'hbar)

         ;; ;; Get rid of the indicators in the fringe
         ;; (mapcar (lambda(fb) (set-fringe-bitmap-face fb 'org-hide))
         ;;         fringe-bitmaps)
         ;;
         ;; ;; Set the color of the fringe
         ;; (custom-set-faces
         ;;  '(fringe ((t (:background "white")))))
         ;;
         ;; (custom-set-faces
         ;;   '(default ((t (:background "black" :foreground "grey"))))
         ;;   '(fringe ((t (:background "black")))))

         ;;(global-set-key (kbd "C-s-SPC") 'mode-line-in-header)
         (bind-key "h" 'mode-line-in-header my-map)

         (message "Enjoy your concentration!")

         )
        (t
         ;; normal mode
         (setq my-toggle-naked-emacs-status t)

         (blink-cursor-mode t)
         (setq visible-bell nil)
         (toggle-frame-fullscreen)
         ;(scroll-bar-mode 1)
         ;;(menu-bar-mode 1)
         (hidden-mode-line-mode nil)

         ;; If you want to hide the mode-line in all new buffers
         ;; (add-hook 'after-change-major-mode-hook 'hidden-mode-line-mode)

         (bzg-big-fringe-mode nil)
         (set-fringe-mode nil)

         (message "See everything.")
         )
        )
  )

map it to F12 and end condition of loading:

  (global-set-key [f12] 'my-toggle-naked-emacs)
)

browse-kill-ring → M-y

https://github.com/browse-kill-ring/browse-kill-ring

«Are you tired of using the endless keystrokes of C-y M-y M-y M-y … to get at that bit of text you killed thirty-seven kills ago? Ever wish you could just look through everything you’ve killed recently to find out if you killed that piece of text that you think you killed, but you’re not quite sure? If so, then browse-kill-ring is the Emacs extension for you.»

(use-package browse-kill-ring
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
   ;:load-path (concat my-user-emacs-directory "contrib/")
   :config
   (browse-kill-ring-default-keybindings); map M-y to browse-kill-ring
)

;; 2017-09-05: to delete when above is working:
;;(require 'browse-kill-ring)
;;(browse-kill-ring-default-keybindings); map M-y to browse-kill-ring

pdf-mode - Edit raw PDF files in Emacs

«pdf-mode is a major mode for editing PDF files in Emacs. It’s not perfect, but it should be a good starting point. It might be useful for the poor souls who are working on generating PDF; definitely useful to me.»

2014-11-16 works at a quick test but I disable it for now since I don’t need it for now.

(use-package pdf-mode
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/pdf-mode/")))
)

guide-key - displays the available key bindings automatically

«guide-key.el displays the available key bindings automatically and dynamically. guide-key aims to be an alternative of one-key.el.»

This is great: when I do press my prefix for my-map and wait a bit, I get a popup buffer that tells me what bindings I am able to use.

(use-package guide-key
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :config ;; executed after loading package
  (setq guide-key/guide-key-sequence '("C-c C-,"))
  (setq guide-key/recursive-key-sequence-flag t)

  ;; show common Org mode keys
  (defun guide-key/my-hook-function-for-org-mode ()
    (guide-key/add-local-guide-key-sequence "C-c")
    (guide-key/add-local-guide-key-sequence "C-c C-x")
    (guide-key/add-local-highlight-command-regexp "org-")
  )
  (add-hook 'org-mode-hook 'guide-key/my-hook-function-for-org-mode)

  (guide-key-mode 1)  ; Enable guide-key-mode

)

vcard-mode

https://github.com/dochang/vcard-mode

«This package provides a major mode to edit vCard files in Emacs.»

(use-package vcard-mode
  :ensure nil ;; install package if not found OR: (setq use-package-always-ensure t)
  :load-path "contrib/vcard-mode/" ;; relative to emacs dir
  :pin manual
  :mode ("\\.vc\\(f\\|ard\\)\\'" . vcard-mode)
)

sunrise-mode - file management like midnight commander or FreeCommander

via http://www.emacswiki.org/emacs/Sunrise_Commander and GitHub

disabled 2015-08-31 since I don’t use it for now.

(use-package sunrise-commander
  :ensure nil ;; install package if not found OR: (setq use-package-always-ensure t)
  :mode ("\\.py\\'" . elpy-mode)
  ;; 3) Choose some unused extension for files to be opened in Sunrise VIRTUAL
  ;; mode and add it to `auto-mode-alist', e.g. if you want to name your virtual
  ;; directories like *.svrm just add to your .emacs file a line like the
  ;; following:
  :mode ("\\.srvm\\'" . sr-virtual-mode)
)

RAML-mode

(use-package raml-mode
   :if (my-system-type-is-windows)
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/raml-mode/")))
)

Synonyms → my-map S

(if (file-exists-p (concat my-user-emacs-directory "bin/mthes10/mthesaur.txt"))
  (use-package synonyms
    :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/synonyms/")))
    ;;:ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
    :init ;; executed before loading package
    (setq synonyms-file        (concat my-user-emacs-directory "bin/mthes10/mthesaur.txt"))
    (setq synonyms-cache-file  (concat my-user-emacs-directory "bin/vkcachefile"))
    :config
    (defun my-synonym-current-word ()
      "Lookup synonyms for current word."
      (interactive)
      (synonyms-lookup (thing-at-point 'word) nil nil))
    :bind (:map my-map ("S" . my-synonym-current-word))
  )
(message (concat "»»» I could not locate \"" my-user-emacs-directory "bin/mthes10/mthesaur.txt\""))
)

define-word

(use-package define-word
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/define-word/")))
;;   :config
)

Binding is done via hydra.

nyan-mode - Nyan Cat instead of scroll bar

«Nyan Mode is an analog indicator of your position in the buffer. The Cat should go from left to right in your mode-line, as you move your point from 0% to 100%.»

via https://www.reddit.com/r/emacs/comments/3xoins/totally_useless_and_utterly_awesome_packages/

This seems to be a bit silly but it is actually quite useful for me. I usually do work with a ninety degree tilted monitor where horizontal space is limited but vertical space not. By disabling the scroll bar for Emacs (see further above) and using the Nyan cat as a replacement for it, I can save precious horizontal space.

(use-package nyan-mode
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :init
  (when (my-system-type-is-windows)
    (setq nyan-bar-length 10);; reduce length on narrow upward/tilted display
  )
  (when (my-system-type-is-gnu)
    (setq nyan-bar-length 20);; reduce length on narrow upward/tilted display
  )
  :config
  (nyan-mode t)
)

If you do find Nyan too childish, mlscroll is an interactive neutral alternative.

highlight-tail

https://melpa.org/#/highlight-tail

This minor-mode draws a tail in real time, when you write. It changes the background color of some last typed characters and smoothly fade them out to the background color.

So from now on, your Emacs will be even more sexy! ;o )

If you do not understand what I mean, check the animation: http://nic-nac-project.net/~necui/img/htshow.gif

(use-package highlight-tail
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :init
  (setq highlight-tail-colors '(("#1c1c1c" . 0)
                                ;;("#bc2525" . 25)
                                ;;("black" . 66)
                                ))
  :config
  (highlight-tail-mode)
)

anzu-mode - showing number of matches when searching

«anzu.el is an Emacs port of anzu.vim. anzu.el provides a minor mode which displays current match and total matches information in the mode-line in various search modes.»

I love this visualization.

(use-package anzu
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :diminish anzu-mode
  :config
  (global-anzu-mode +1)
)

smart-mode-line - abbreviating paths, …

«Smart Mode Line is a sexy mode-line for Emacs. It aims to be easy to read from small to large monitors by using colors, a prefix feature, and smart truncation.»

(use-package smart-mode-line
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :config
  (setq sml/no-confirm-load-theme t)
  (setq sml/theme 'respectful) ;; select theme: light, dark, respectful
  ;; hiding minor modes from mode line (don't forget the leading space)
  (setq rm-blacklist '(" Fill" " Ind" " MRev" " hl-p" " Guide" " OrgStruct" " ," " PCRE" " counsel" " OTSH" " dired-icon" " GitGutter" " WK" " FlyC-" " Ddl" " Diary"))
  ;; does not hide in Org-agenda:  "Diary " "Ddl " "Grid " "Habit " "FlyC " "WK "
  ;; replacing path names with abbrevations:
  (add-to-list 'sml/replacer-regexp-list '("^~/hosts/all/config/emacs.d" ":EMACS:") t)
  (add-to-list 'sml/replacer-regexp-list '("^~/org" ":ORG:") t)
  (add-to-list 'sml/replacer-regexp-list '("^~/frankie/src/lazyblorg" ":LB:") t)
  (add-to-list 'sml/replacer-regexp-list '("^C:/Users/John/AppData/Roaming/org" ":ORG:") t)
  (add-to-list 'sml/replacer-regexp-list '("^~/frankie/" "~/") t)
  (smart-mode-line-enable)
)

Performance implications! See reddit comment for details.

display-time-mode - Enable the display of time in the modeline

http://www.emacswiki.org/emacs/DisplayTime

(setq display-time-string-forms
      '((propertize (format-time-string "%A %F %R" now) 'face 'bold)))
(display-time-mode t)

dash

https://github.com/magnars/dash.el «A modern list api for Emacs. No ‘cl required.»

  • required by eno (and most probably others in future)
  • disabled because I do not use eno for now
(use-package dash
  :ensure t
  :defer 110
  )

edit-at-point

  • required by eno (and most probably others in future)
  • disabled because I do not use eno for now
(use-package edit-at-point
  :ensure t
  :defer 110
  )

eno-mode: ace-jump/easymotion provides: goto certain char in view

https://github.com/enoson/eno.el

ace-jump/easymotion provides “goto certain char in view”, which let us moving without mouse, but it’s still not efficient or intuitive enough, so I create this package to not just goto but also edit(copy,cut..) any word/symbol/string/paren/line in view by directly selecting hints, similar to ace-jump/easymotion but don’t need to enter the leading char.

(use-package eno
  :ensure t
  ;;  :diminish eno
  :defer 110
  ;;  :config ;; executed after loading package
  :bind (:map my-map ("RET" . eno-word-goto))
)

markdown-mode

via: http://ikiwiki.info/tips/Emacs_and_markdown/

(use-package markdown-mode
  :ensure t
  ;:if (my-system-is-rise)
  ;;:defer 110
  :mode ("\\.md\\'" . markdown-mode)
  :mode ("\\.mkdn\\'" . markdown-mode)
)

swiper - ivy-enhanced alternative to isearch

flexible, simple tools for minibuffer completion in Emacs

This repository contains:

  1. Ivy, a generic completion mechanism for Emacs.
  2. Counsel, a collection of Ivy-enhanced versions of common Emacs commands.
  3. Swiper, an Ivy-enhanced alternative to isearch.
(use-package ivy :demand
      :config
      (setq ivy-use-virtual-buffers t    ;; Add recent files and bookmarks to the ivy-switch-buffer
            ivy-count-format "%d/%d ")   ;; Displays the current and total number in the collection in the prompt
      (ivy-mode 1)
)
KeyCommandDescription
M-nivy-next-lineNext line
M-pivy-previous-linePrevious line
M-<ivy-beginning-of-bufferBeginning of the Ivy minibuffer
M->ivy-end-of-bufferEnd of the Ivy minibuffer
C-vivy-scroll-up-commandPage up by one Ivy buffer size
M-vivy-scroll-down-commandPage down by one Ivy buffer size
C-m or RETivy-doneCalls the default action
C-M-mivy-callCalls the default action, keeps Ivy open
M-oivy-dispatching-doneDisplays the available actions
C-M-oivy-dispacthing-callDisplays available actions, keeps Ivy open
C-’ivy-avyUses Avy to select candidates
TABivy-partial-or-doneTab completion, repeated presses may call done
ivy-resumeRestart Ivy before last action
(use-package swiper
  :ensure t
  ;;:if (my-system-type-is-windows)
  :config

  (setq ivy-display-style 'fancy) ;; fancy highlighting

  ;;advise swiper to recenter on exit
  (defun bjm-swiper-recenter (&rest args)
    "recenter display after swiper"
    (recenter)
    )
  (when (my-system-type-is-gnu)
    (advice-add 'swiper :after #'bjm-swiper-recenter)
    )

  ;(bind-key "C-s" 'swiper)
  ;;(global-set-key "\C-s" 'swiper)
)

counsel - Ivy-enhanced versions of common Emacs commands → M-x → my-map J

flexible, simple tools for minibuffer completion in Emacs

This repository contains:

  1. Ivy, a generic completion mechanism for Emacs.
  2. Counsel, a collection of Ivy-enhanced versions of common Emacs commands.
  3. Swiper, an Ivy-enhanced alternative to isearch.
(use-package counsel
  :ensure t
  ;;:bind (:map my-map ("J" . counsel-imenu)) ;; http://irreal.org/blog/?p=6201 jumping to buffer org-heading
  ;; 2018-01-23: moved to jump-hydra!
  :config
  (counsel-mode 1)
)

char-menu - insert special characters → F4

«This package allows to insert arbitrary symbols in Emacs in a very efficient and straightforward way. Whether you ever need to insert only a couple of proper punctuation symbols or you’re a Unicode geek who likes all sorts of arrows and fancy math symbols, this package may be of some use.»

(use-package char-menu
  :ensure t
  :config
  (setq char-menu
        '("" "" "" "×" "·" "" "" "" "°" "" "" "§" "«»" "»«" "‘’" "“”" "" "©" "" "" "¥"
         ("Arrows"     "" "" "" "" "" "" "" "")
         ("Math"       "Δ" "¬" "" "" "" "" "×" "±" "" "÷" "" "" "")
         ("Greek"      "α" "β" "Y" "δ" "ε" "ζ" "η" "θ" "ι" "κ" "λ" "μ"
          "ν" "ξ" "ο" "π" "ρ" "σ" "τ" "υ" "φ" "χ" "ψ" "ω" "Σ" "Δ")
         ("Hatschek"   "Ǎ" "ǎ" "Č" "č" "Ď" "ď" "Ě" "ě" "Ǧ" "ǧ" "Ȟ" "ȟ"
          "Ǐ" "ǐ" "ǰ" "Ǩ" "ǩ" "Ľ" "ľ" "Ň" "ň" "Ǒ" "ǒ" "Ř" "ř" "Š" "š" "Ť" "ť"
          "Ǔ" "ǔ" "Ǚ" "ǚ" "Ž" "ž" "Ǯ" "ǯ")
         ("Umlaute"  "ä" "ö" "ü" "Ä" "Ö" "Ü" "ß")
        ))
  (global-set-key [f4] 'char-menu)
)

helm - completion and selection narrowing

This is something that really pushes Emacs usability.

https://github.com/emacs-helm/helm

«Emacs incremental completion and selection narrowing framework https://emacs-helm.github.io/helm/»

Helm is an Emacs framework for incremental completions and narrowing selections. It helps to rapidly complete file names, buffer names, or any other Emacs interactions requiring selecting an item from a list of possible choices. Helm is a fork of anything.el, which was originally written by Tamas Patrovic and can be considered to be its successor. Helm cleans the legacy code that is leaner, modular, and unchained from constraints of backward compatibility.

(use-package helm
  :ensure t
  :defer 110
)

wttrin - Weather in Emacs → my-map w

(use-package wttrin
  :ensure t
  :commands (wttrin)
  :defer 120
  :init
  (setq wttrin-default-cities '("graz" "ebreichsdorf" "st.poelten" "schladming" "malia"))
  (cond ((my-system-is-sting)
         ;; 2017-12-23 outdated: (bind-key "w" '(lambda () (interactive) (wttrin-query "graz") (toggle-truncate-lines)) my-map)
         (bind-key "w" (lambda () (interactive) (wttrin-query "graz")) my-map)
         )
        ((my-system-type-is-windows)
         (bind-key "w" '(lambda () (interactive) (wttrin-query "graz")) my-map)
          )
        (t
         (bind-key "w" '(lambda () (interactive) (wttrin)) my-map)
         )
        )
  )

pandoc-mode - An Emacs minor mode for interacting with Pandoc

(when (my-eval-if-binary-or-warn "pandoc")
  (use-package pandoc-mode
    :ensure t
    :defer 110
  )
)

bm - visible bookmarks → my-map 8|9|0

https://github.com/joodland/bm

This package provides visible, buffer local, bookmarks and the ability to jump forward and backward to the next bookmark.

It was created because I missed the bookmarks from M$ Visual Studio in GNU Emacs. I think they provide an easy way to navigate in a buffer.

Features:

  • Auto remove bookmark after jump to it by bm-next or bm-previous:
  • Cycle through bookmarks in all open buffers in LIFO order
  • Toggle bookmarks. Jump to next/previous bookmark.
  • Setting bookmarks based on a regexp. (Useful when searching logfiles.)
  • Mouse navigation.
  • Annotate bookmarks.
  • Different wrapping modes.
  • Different bookmarks styles, line-only, fringe-only or both.
  • Persistent bookmarks (buffer local), also in non-file buffers (info) and indirect buffers.
  • List bookmarks (in all buffers) in a separate buffer.
  • Cycle through bookmarks in all open buffers.

via: http://pragmaticemacs.com/emacs/use-visible-bookmarks-to-quickly-jump-around-a-file/

(use-package bm
  :ensure t
  :defer 90
  :bind (:map my-map ("8" . bm-toggle))
  :bind (:map my-map ("9" . bm-previous))
  :bind (:map my-map ("0" . bm-next))
  )

adoc-mode - asciidoc mode

https://github.com/sensorflo/adoc-mode/wiki

AsciiDoc is a text document format for writing short documents, articles, books and UNIX man pages. AsciiDoc files can be translated to HTML and DocBook markups.

adoc-mode is an Emacs major mode for editing AsciiDoc files. It emphasizes on the idea that the document is highlighted so it pretty much looks like the final output. What must be bold is bold, what must be italic is italic etc. Meta characters are naturally still visible, but in a faint way, so they can be easily ignored.

(use-package adoc-mode
  :ensure t
  :defer 110
  :config
  (add-to-list
   'auto-mode-alist (cons "\\.adoc\\'" 'adoc-mode))
  )

suggest - suggest Elisp for given input and output

Oh, this is really cool: http://www.wilfred.me.uk/blog/2016/07/30/example-driven-development/

  • “Hey $COLLEAGUE, is there any function that takes this list and returns a list like this?”

Just read the web page - it’s hard to explain otherwise.

Disabled for now until I want to impress someone using my Emacs power ;-)

M-x suggest

I ran into “suggest–possibilities: Symbol’s value as variable is void: it” when C-c C-c: See id:2016-08-04-suggest

(use-package suggest
  :ensure t
  :defer 110
  )

move-text - move line up/down → M-, | M-.

«MoveText is extracted from Basic edit toolkit. It allows you to move the current line using M-up / M-down (or any other bindings you choose) if a region is marked, it will move the region instead.»

I don’t use it for now. Maybe after I got the requirement more often and memorize the commands.

(use-package move-text
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/move-text/")))
   :config
   (global-set-key (kbd "M-,")          'move-text-up)
   (global-set-key (kbd "M-.")          'move-text-down)
)
;; (require 'move-text)
;; (move-text-default-bindings)

command-log-mode → my-map k (visualizing keyboard input in buffer)

2017-06-01: package was unavailable → disabled for now since I don’t use it anyway.

https://github.com/lewang/command-log-mode - «Show event history and command history of some or all buffers.»

Used in screencast video: https://www.reddit.com/r/emacs/comments/4yhfn6/emacs_screencast_acelink_swiper_lispy_and_macros/

To see the log buffer, call M-x clm/open-command-log-buffer.

The key strokes in the log are decorated with ISO9601 timestamps on the property `:time’ so if you want to convert the log for screencasting purposes you could use the time stamp as a key into the video beginning.

How to use:

  1. M-x command-log-mode
  2. my-map k
(use-package command-log-mode
  :ensure t
  :defer 110
  :diminish command-log-mode
  :config ;; executed after loading package
  (add-hook 'LaTeX-mode-hook 'command-log-mode)
  (bind-key "k" #'clm/open-command-log-buffer my-map)
)

A test for starting the mode probably together with the command-log-buffer:

(defun my-start-command-log-mode()
  "load the command-log mode and start it."
  (interactive "*")
  ;; M-x clm/open-command-log-buffer
  (clm/open-command-log-buffer)
)

scss-mode

https://github.com/antonj/scss-mode - «Major mode for editing SCSS files in Emacs.»

Command line utility sass is required, see http://sass-lang.com/

To install sass (haml): gem install haml

Also make sure sass location is in emacs PATH, example: (setq exec-path (cons (expand-file-name "~/.gem/ruby/1.8/bin") exec-path)) or =customize `scss-sass-command’= to point to your sass executable.

(when (my-eval-if-binary-or-warn "sass")
  (use-package scss-mode
    ;;:if (my-system-is-floyd-or-sting)
    :ensure t
    :defer 110
    :config
    (autoload 'scss-mode "scss-mode")
    (add-to-list 'auto-mode-alist '("\\.scss\\'" . scss-mode))
    )
)

json-mode

(use-package json-mode
  :if (my-system-type-is-windows)
  :ensure t
  :defer 110
)

mode-icons - Show icons instead of mode names

https://github.com/ryuslash/mode-icons

via: https://www.reddit.com/r/emacs/comments/5fjri7/how_to_use_git_logo_in_modeline_instead_of/

This enhances the style of Emacs IMHO.

(use-package mode-icons
  :ensure t
  :defer 120
  :config
  (mode-icons-mode)
  (add-hook 'dired-mode-hook #'mode-icons--mode-disable) ;; with mode-icons, visiting a dir with dired takes up *lots* of CPU for =mode-icons-reset= (performance-issue)
)

unicode-fonts - Configure Unicode fonts

https://github.com/rolandwalker/unicode-fonts

  • solved an issue where a host was using different-height-sized font for few special characters
  • see id:2016-08-19-unicode-enlarges-line-height
(use-package unicode-fonts
  :ensure t
  :if (my-system-is-floyd)
  :defer 110
  :config
  (unicode-fonts-setup)
)

goto-chg - visit places of previous changes in current buffer → S-F3|F4

(use-package goto-chg
   :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/")))
   :config
   (global-set-key [(shift f3)] 'goto-last-change)
   (global-set-key [(shift f4)] 'goto-last-change-reverse)
)

;(require 'goto-chg)

restclient

GitHub - pashky/restclient.el: HTTP REST client tool for emacs

The restclient here is particular handy when it is combined with the Org-mode: see use of ob-restclient.el within the Org-mode headings.

This way, I am able to write REST requests right beneath my Org-mode documentation. The REST answers are added there as well. This tool also allows for using variables. More flexibility is almost impossible. ;-)

(use-package restclient
  :ensure t ;; install package if not found OR: (setq use-package-always-ensure t)
  :defer 110
  :if (my-system-type-is-windows)
  :init ;; executed before loading package
  (use-package json-reformat
     :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/2del/restclient/")))
     )
  ;; :mode "\\.rb\\'"
)

neotree → F1

NeoTree offers a file tree side-panel like NerdTree for Vim.

  • installed on 2015-03-22
  • disabled 2018-06-19: I don’t use it in real life
(use-package neotree
  :ensure t
  :defer 120
  :config ;; executed after loading package
  (global-set-key [f1] 'neotree-toggle)
)

csv-mode

Manipulating CSV files.

As with many major modes, I do have a helpful hydra mapped to F1.

(use-package csv-mode
  :ensure t
  :defer 110
  :config
  (add-to-list 'auto-mode-alist '("\\.[Cc][Ss][Vv]\\'" . csv-mode))
  (autoload 'csv-mode "csv-mode"
    "Major mode for editing comma-separated value files." t)
)

pcre2el

I got this nice package from a screencast of dired. It offers simplified regular expressions instead of the standard Emacs RegEx.

Example: in dired, you can mark using %m followed by .*(jpg|png) instead of using the pattern .*\(jpg\|png\).

CAUTION: this changes regex in general from vanilla Emacs regex to PCRE regex!

(use-package pcre2el
:ensure t
:config
(pcre-mode)
)

dumb-jump

(use-package dumb-jump
:ensure t
)

keyfreq

I found it via this blog article: it logs the used commands and their keyboard shortcuts and gives you an overview. Most frequently used commands should be mapped to easy to type shortcuts.

(use-package keyfreq
:ensure t
:config
(keyfreq-mode 1)
(keyfreq-autosave-mode 1)
)

You can see the current result by calling keyfreq-show.

Pulse: Highlight lines on misc occasions

This is a tip I got from that blog article:

(defun my-pulse-line (&rest _)
      "Pulse the current line."
      (pulse-momentary-highlight-one-line (point)))

(dolist (command '(eyebrowse-post-window-switch-hook recenter-top-bottom other-window ace-window my-scroll-down-half my-scroll-up-half))
  (advice-add command :after #'my-pulse-line))

eyebrowse → my-map ,

When you are working with multiple tasks in parallel, you most likely know the issue of getting lost in your buffers or destroying your window setup for an in-between task.

eyebrowse helps mitigating those issues by providing “saved buffer configurations” and assign it to separate slots that are addressed by their number. If you know GNU screen or tmux in your shell, this is quite familiar to you.

I got the recommendation for it from this reddit thread.

The author is obviously using spacemacs. Unfortunately, the default prefix C-c C-w is overriding org-refile() which I use frequently. I chose C-: as alternative prefix in order to un-map the original. However, I am invoking eyebrowse functionality only via my hydra which is defined below and inviked via =my-map ,=.

Since my horizontal mode line space is sparse, I wanted a small modification. I need the whole indicator information (with labels) in the hydra (much space) but only the list of the slots in the mode line in order to keep it as small as possible. Therefore I modified the package by duplicating the modeline functions according to this GitHub issue explanation.

Please notice that with only one slot (the default one), the indicator is not shown in the modeline.

Key bindFunction
prefix <Switch to previous window config
prefix >Switch to next window config
prefix ’Switch to last window config
prefix ”Close current window config
prefix ,Rename current window config
prefix cCreate new window config
prefix 0Switch to window config 0
prefix 9Switch to window config 9
(use-package eyebrowse
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/eyebrowse/")))
  ;;:defer 90
  :init
  (setq eyebrowse-keymap-prefix (kbd "C-:"));; the default overrides org-refile: https://github.com/wasamasa/eyebrowse/issues/86
  :config
  (eyebrowse-mode t)

  ;; 2021-07-16: FIXXME: this does not work yet:
  ;;(add-hook 'eyebrowse-post-window-switch-hook 'my-pulse-line) ;; flash current line after switching
  ;;  (add-hook 'eyebrowse-post-window-switch-hook '(pulse-momentary-highlight-one-line (point)))
)

See hydra definition near the end of this file.

ibuffer

Replace list-buffers with ibuffer (ergoemacs: List Buffers; https://www.emacswiki.org/emacs/IbufferMode)

;;(defalias 'list-buffers 'ibuffer)
(global-set-key (kbd "C-x C-b") 'ibuffer)
(autoload 'ibuffer "ibuffer" "List buffers." t)
(setq ibuffer-saved-filter-groups
      (quote (("default"
               ("dired" (mode . dired-mode))
               ("PDF" (mode . pdf-view-mode))
               ("python" (mode . python-mode))
               ("org" (or (mode . org-mode)
                          (mode . org-agenda-mode)
                          ))
;;               ("erc" (mode . erc-mode))
               ("emacs" (or
                         (name . "^\\*scratch\\*$")
                         (name . "^\\*Messages\\*$")))
               ("planner" (or
                           (name . "^\\*Calendar\\*$")
                           (name . "^diary$")
                           (mode . muse-mode)))
;;               ("gnus" (or
;;                        (mode . message-mode)
;;                        (mode . bbdb-mode)
;;                        (mode . mail-mode)
;;                        (mode . gnus-group-mode)
;;                        (mode . gnus-summary-mode)
;;                        (mode . gnus-article-mode)
;;                        (name . "^\\.bbdb$")
;;                        (name . "^\\.newsrc-dribble")))
               ))))

  (add-hook 'ibuffer-mode-hook
            (lambda ()
              (ibuffer-switch-to-saved-filter-groups "default")))

nxml-mode

Read about the XML mode on http://lgfang.github.io/mynotes/emacs/emacs-xml.html

my-xml-pretty-print-region()

Source: http://stackoverflow.com/questions/12492/pretty-printing-xml-files-on-emacs

(defun my-xml-pretty-print-region (begin end)
  "Pretty format XML markup in region. You need to have nxml-mode
http://www.emacswiki.org/cgi-bin/wiki/NxmlMode installed to do
this.  The function inserts linebreaks to separate tags that have
nothing but whitespace between them.  It then indents the markup
by using nxml's indentation rules."
  (interactive "r")
  (save-excursion
    (nxml-mode)
    (goto-char begin)
    (while (search-forward-regexp "\>[ \\t]*\<" nil t)
      (backward-char) (insert "\n"))
    (indent-region begin end))
  (message "Ah, much better!"))

my-xml-pretty-print-buffer()

(defun my-xml-pretty-print-buffer()
  "marks whole buffer and calls my-xml-pretty-print-region"
  (interactive)
  (mark-whole-buffer)
  (my-xml-pretty-print-region);; FIXXME: provide (begin end)
  )

emojify

Emoticons for the Emacs: :org: :emacs: 😉 😄 ;^)

https://github.com/iqbalansari/emacs-emojify

(use-package emojify
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/emacs-emojify/")))
  :defer 90
  :init
  :config
  (setq emojify-emoji-styles '(github)) ;; omit "ascii" and "unicode" style

  ;; display emojis using images since looks nicer
  (setq emojify-display-style 'image)

  (setq emojify-user-emojis `((":org:" . (("name" . "Org mode")
                                          ("image" . ,(concat my-user-emacs-directory "bin/images/org-mode-logo_22x22.png"))
                                          ("style" . "github")))
                              (":emacs:" . (("name" . "Emacs")
                                            ("image" . ,(concat my-user-emacs-directory "bin/images/emacs_22x22.png"))
                                            ("style" . "github")))))
  ;; If emojify is already loaded refresh emoji data
  (when (featurep 'emojify)
    (emojify-set-emoji-data))

  (global-emojify-mode 1)
  ;;(add-hook 'after-init-hook #'global-emojify-mode)
)

alert

https://github.com/jwiegley/alert → Desktop notifications

(use-package alert
  :ensure t
  :config
   (setq alert-default-style 'libnotify)
   (setq alert-persist-idle-time 60);; After this many idle seconds, alerts will become sticky, and not fade away more.  The default is 15 minutes.

;;   ;; This is the most basic form usage
;;   (alert "This is an alert")
;;
;;   ;; You can adjust the severity for more important messages
;;   (alert "This is an alert" :severity 'high)
;;
;;   ;; Or decrease it for purely informative ones
;;   (alert "This is an alert" :severity 'trivial)
;;
;;   ;; Alerts can have optional titles.  Otherwise, the title is the
;;   ;; buffer-name of the (current-buffer) where the alert originated.
;;   (alert "This is an alert" :title "My Alert")
;;
;;   ;; Further, alerts can have categories.  This allows users to
;;   ;; selectively filter on them.
;;   (alert "This is an alert" :title "My Alert" :category 'debug)

)

;   (require 'alert)

My personal alert wrapper functions:

(defun my-alert (mymessage)
"wrapper for high-prio (sticky?) alert"
   (interactive)
   (when (not noninteractive)
     ;; only in interactive mode:

     (setq mymessage (concat mymessage "\n\n" (concat
         (format-time-string "%Y-%m-%dT%T")
         ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5)))
             (format-time-string "%z")))))
     (message mymessage)
     (alert mymessage :severity 'high))
)

(defun my-flash (mymessage)
"wrapper for low-prio (non-sticky) alert flash"
   (interactive)
   (when (not noninteractive)
     ;; only in interactive mode:

     (setq mymessage (concat mymessage "\n\n" (concat
         (format-time-string "%Y-%m-%dT%T")
         ((lambda (x) (concat (substring x 0 3) ":" (substring x 3 5)))
             (format-time-string "%z")))))
     (message mymessage)
     (alert mymessage))
)

Test of my alert function:

(my-alert "This is high prio sticky.")
(my-flash "This is low prio flash.")

gif-screencast

2020-01-23added to config after mentioned issue got resolved

From: https://gitlab.com/ambrevar/emacs-gif-screencast

This package enables you to do screencasts that result in animated GIF images (no sound). However, it takes only one image per screen content change and is therefore much more storage space efficient compared to other animated GIFs.

Requires external command line tools:

scrot
for creating the screenshots
convert
for post-processing the images
gifsicle
for optimizing resulting GIF

On Debian-based systems, they can be installed via:

sudo apt install scrot gifsicle imagemagick

To avoid crashes of the underlying convert job when doing high-resolution screencasts (as described in this issue), you have to increase the disk resource value:

In /etc/ImageMagick-6/policy.xml increase the value in the line

<policy domain="resource" name="disk" value="1GiB"/>

from 1GiB to 10GiB.

(use-package gif-screencast
   :if (my-system-type-is-gnu)
   :ensure t
)
  • Screencast process:
    • M-x gif-screencast
    • <do your stuff>
    • M-x git-screencast-stop
    • in your $HOME you will find a file like output-2020-01-23-12:37:14.gif if everything went well.

vimgolf

2020-02-11found via emacs news and set up to test
(use-package vimgolf
  :ensure t
  :defer 110
)

Snippets from the README

  1. Find the challenge you’d like to play on VimGolf.
  2. M-x vimgolf CHALLENGE-ID RET

    Point will be in the window containing the starting text and you’ll have the goal text on a second window. Edit the starting text until it matches the ending text and then finish with C-c C-v C.


CommandDefault BindingDescription
vimgolfM-x vimgolfInput a challenge ID and play!
vimgolf-browseM-x vimgolf-browseOpen an interactive buffer to browse challenge titles
vimgolf-submitC-c C-v CFinish and score the challenge
vimgolf-revertC-c C-v rRevert to the beginning of the challenge and clear your keystrokes
vimgolf-diffC-c C-v dOpen an ediff session for the challenge
vimgolf-pauseC-c C-v pPause keystroke recording
vimgolf-continueC-c C-v cStart keystroke recording where you left off
vimgolf-quitC-c C-v qStop the challenge

ace-window

2020-12-01disabled because of performance issue: with 3 buffers, it can take several seconds!

After watching Sacha Chua’s video on ace-window, I decided to give it a try.

It’s a better way of jumping and managing multiple windows.

(use-package ace-window
  :ensure t
  ;;:defer 110
  :config (setq aw-keys '(?f ?j ?a ?l))
  :bind ("C-x o" . ace-window)
)

Now, I may switch to a different window py invoking C-x o and the letter that got shown in the top left edge of the window.

Using the prefix version C-u C-c o I may swap the current window with another one. A second prefix will delete the target window: C-u C-u C-x o.

explain-pause-mode

2020-05-19cloned from GitHub and start testing
2020-05-23disabled because it spams my mini-buffer

Emacs minor mode that watches for long pauses and reports them.

I learned about this mode on on reddit where the developer was asking for testers. Since I do suffer from various performance bottlenecks, I decided to test this package myself.

(use-package explain-pause-mode
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/explain-pause-mode/")))
  ;;:defer 110
  :config
  (explain-pause-mode t)
)

Emacs Slime Volleyball

2020-05-26setup this little game after finding it via Emacs News on GitHub
(use-package slime-volleyball
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/slime-volleyball/")))
  :config (require 'slime-volleyball)
)

spatial-navigate

2020-10-0xstumbled over it and it seems to be a nice general navigation feature
2020-10-26disabled because of “((use-package “Cannot load spatial-navigate” :error nil) (use-package “Failed to install spatial-navigate: Package ‘emacs-26.2’ is unavailable” :error nil))”

This package enables a nice type of navgating through a document. It’s rather hard to explain - just try it out yourself or read the readme-file.

I love it for navigating Python code, skipping paragraphs, and so forth.

(use-package spatial-navigate
  :ensure t
  ;; :bind (:map my-map ("SPC" . yankpad-insert))
  :config
  (global-set-key (kbd "<C-up>") 'spatial-navigate-backward-vertical-bar)
  (global-set-key (kbd "<C-down>") 'spatial-navigate-forward-vertical-bar)
  ;; I prefer the usual jump to word navigation for horizontal movements:
  ;;(global-set-key (kbd "<C-left>") 'spatial-navigate-backward-horizontal-bar)
  ;;(global-set-key (kbd "<C-right>") 'spatial-navigate-forward-horizontal-bar)
)

bug-hunter → bisecting Emacs config issues

2020-12-10initial setup

Found via tip from this issue comment.

process for my situation:

  1. copy config.el to testconfig.el
  2. insert snippet below at the top of testconfig.el
    • this is part of my init.el which is ignored when using other file than init.el
  3. save all buffers
  4. start bisecting via M-x bug-hunter-file, select file and then =i=nteractive
(package-initialize)
(defvar my-init-el-start-time (current-time) "Time when init.el was started")
(setq my-user-emacs-directory "~/.emacs.d/")
(add-to-list 'load-path (concat my-user-emacs-directory "contrib/org-contrib/lisp"))
(add-to-list 'load-path (concat my-user-emacs-directory "contrib/org-mode/lisp"))
(require 'org)
(use-package bug-hunter
  :ensure t
  :defer 110
)

keycast - show pressed keys

2021-03-14installed for screen recording
(use-package keycast
  :ensure t
  :defer 110
)

copy-as-format

2021-07-13Got this tip on reddit
(use-package copy-as-format
  :ensure t
  :defer 110
  :after org
  :bind (:map my-map ("f" . (lambda () (interactive)
                  (setq current-prefix-arg '(4)) ; C-u (universal argument)
                  (call-interactively 'copy-as-format))))
  :config
(defalias 'copy-as-format-reddit 'copy-as-format-markdown) ;; idea from https://www.reddit.com/r/emacs/comments/oil7xw/i_made_a_thing_for_org_bespoke_completion_sparse/h517hps/?context=3
(defvar copy-as-format-format-alist
  '(;;("asciidoc"  copy-as-format--asciidoc)
    ;;("bitbucket" copy-as-format--github)
    ("disqus"    copy-as-format--disqus)
    ("github"    copy-as-format--github)
    ("gitlab"    copy-as-format--github)
    ;;("hipchat"   copy-as-format--hipchat)
    ("html"      copy-as-format--html)
    ("jira"      copy-as-format--jira)
    ("markdown"  copy-as-format--markdown)
    ("reddit"  copy-as-format--reddit)
    ;;("mediawiki" copy-as-format--mediawiki)
    ;;("org-mode"  copy-as-format--org-mode)
    ;;("pod"       copy-as-format--pod)
    ;;("rst"       copy-as-format--rst)
    ;;("slack"     copy-as-format--slack)
    )
  "Alist of format names and the function to do the formatting.")

)

dogears

2021-08-13found on reddit and set up

This looks like a cool method to jump back and forth between buffers. I need to test this.

(use-package dogears
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/dogears.el/")))
  :defer 90
  :config
  (dogears-mode 1)
)

qrencode

2021-09-21found via Emacs News and going to test it
commandexplanation
qrencode-regionShows the current selection as a QR Code.
qrencode-url-at-pointEncode URL at point as QR Code.
(use-package qrencode
  :ensure t
  :defer 110
)

secret-mode

2021-10-05found via Emacs News

“secret-mode is an Emacs minor mode to hide your current text.” (Source)

(use-package secret-mode
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/secret-mode.el/")))
  :defer 110
  :after org
  )

crdt

2021-11-03found via Emacs news video of Sacha for EmacsConf21

Collaborative editing using Conflict-free Replicated Data Types \o/

  • how to collaborate
    1. crdt-protocol-version needs to be the same on all peers
    2. make sure to use a computer that has a reachable IP
    3. M-x crdt-share-buffer
    4. enter session name
    5. enter port (default to 6530), optional password and your display name
  • how to join a session
    • M-x crdt-connect
    • enter address, port, and your display name.
  • interesting:
    • M-x crdt-list-users
    • M-x crdt-list-sessions
    • M-x crdt-stop-session stops a session you’ve started and disconnect all other users from it.
    • M-x crdt-disconnect then choose a session to disconnect from.
    • crdt-visualize-author-mode
    • Turn on crdt-org-sync-overlay-mode. All peers that have this enabled have their folding status synchronized.
  • [ ] test this with one host with public IPs and peers with private IPs
(use-package crdt
  :load-path  (lambda () (expand-file-name (concat my-user-emacs-directory "contrib/crdt.el/")))
  :defer 110
)

My helper functions (part II)

Here I defined some functions I am using interactively and probably map to keys in the next section.

Optimizing search methods

My Org-mode files got big and numerous. I maintain roughly a third million lines of Org-mode within my files. This has an enormous performance impact on certain operations.

For searching within my Emacs files, I do use more sophisticated methods than isearch if possible. On operating systems that provide a decent shell environment, I use grep or git grep or ag.

helm-do-grep-ag: grep within files → my-map G

This is for using ag, the silver searcher:

Preconfigured helm for grepping with AG in `default-directory’.

(when (my-eval-if-binary-or-warn "ag")
  (bind-key "G" #'helm-do-grep-ag my-map)
)

my-search-method-according-to-numlines() → C-s

Choose the best/fastest search method depending on the maximum number of lines of the current buffer.

Read http://karl-voit.at/2016/04/09/chosing-emacs-search-method/ for the whole story.

(defun my-search-method-according-to-numlines (&optional arg)
  "Choses search method according to buffer size: small → counsel-grep; huge → swiper-isearch; With C-u it's isearch-forward in any case."
  (interactive)
  (cond ((or (equal current-prefix-arg '(4)) (my-system-type-is-windows));; Windows OR universal argument → isearch-forward
             (isearch-forward))
        (t
            (if (and (buffer-file-name)
                     (not (ignore-errors (file-remote-p (buffer-file-name))))
                     (if (eq major-mode 'org-mode)
                         (> (buffer-size) 60000);; for Org mode buffers, the max size for counsel-grep is 60,000 characters
                       (> (buffer-size) 300000)));; for non-Org mode buffers, the max size for counsel-grep is 60,000 characters
                (progn
                  (save-buffer)
                  (counsel-grep))
              (swiper-isearch) ;; 2019-12-07: old command before upgrading everything and replacing with swiper-isearch;; (swiper--ivy (swiper--candidates))
             ))
))

(global-set-key "\C-s" 'my-search-method-according-to-numlines)
(global-set-key "\C-S" 'isearch-forward)

PREVIOUS (simple) approach:

(defun my-search-method-according-to-numlines ()
  "Determines the number of lines of current buffer and chooses a search method accordingly"
  (interactive)
  (if (< (count-lines (point-min) (point-max)) 20000)
      (swiper)
    (isearch-forward)
    )
  )
;;fancy search:  (global-set-key "\C-s" 'swiper)
;;normal search:
(global-set-key "\C-S" 'isearch-forward)

On 2017-06-17, I stubled over an even more sophisticated setup for deciding on a search tool: https://github.com/redguardtoo/emacs.d/blob/master/lisp/init-ivy.el

my-toggle-beginner-setup() → S-F11

When I am working with Emacs, I do not use the menu bar nor the icon bar, for example. Those things got hidden in my configuration.

However, when I teach Emacs to people not familiar with the vast amount of customizations, I use the following functions to toggle my setup to look like a default Emacs.

(defvar my-toggle-beginner-setup-status nil
  "state of Emacs setup which is least confusing for beginners. t means beginner, nil means normal")
;;(make-variable-buffer-local 'my-toggle-beginner-setup-status)

(defun my-emacs-normal-setup ()
  "Hide things for my normal usage"
  (interactive)
  (if (functionp 'tool-bar-mode) (tool-bar-mode -1)) ;; hide icons
  (menu-bar-mode 0) ;; hide menu-bar
  (when (not (my-system-is-karl-voit-at))
    (scroll-bar-mode 0) ;; hide scroll-bar, I do have Nyan-mode instead!
    )

  ;; 2020-06-21 disabled because it causes more effort when errors are sparse:
  ;;(setq debug-on-quit t);; show debug information on canceling endless loops and so forth

  (org-expiry-insinuate)
  (setq org-log-into-drawer t)
  (org-bullets-mode 1)

  ;; http://www.emacswiki.org/emacs/sylecn
  ;;show nothing in *scratch* when started
  (setq initial-scratch-message nil)

  ;; ######################################################
  ;; handle CamelCaseParts as distinct words
  ;; http://ergoemacs.org/emacs/emacs_adv_tips.html
  ;; disabled 2017-10-10: not that useful ;; (global-subword-mode 1) ; 1 for on, 0 for off
  ;; https://www.gnu.org/software/emacs/manual/html_node/ccmode/Subword-Movement.html
  ;; FIXXME: this is a test for getting it work independent of
  ;; CamelCase words

  ;;(setq org-hide-leading-stars t)

  ;; disabled 2021-02-15 since I switched to bright mode:  (load-theme 'wombat t) ;; dark theme

)

(defun my-emacs-beginner-setup ()
  "Make things nice for beginners"
  (interactive)
  (tool-bar-mode) ;; show icons
  (menu-bar-mode) ;; show menu-bar
  (scroll-bar-mode 1) ;; show scroll-bar
  (setq debug-on-quit nil);; no debug information on canceling endless loops and so forth

  ;; http://www.emacswiki.org/emacs/sylecn
  ;;show nothing in *scratch* when started
  (setq initial-scratch-message ";; This buffer is for notes you don't want to save\n;; If you want to create a file, visit that file with C-x C-f,\n;; then enter the text in that file's own buffer.\n\n")

  ;; http://ergoemacs.org/emacs/emacs_adv_tips.html
  ;; disabled 2017-10-10: not that useful ;; (global-subword-mode 0) ; 1 for on, 0 for off
  ;; https://www.gnu.org/software/emacs/manual/html_node/ccmode/Subword-Movement.html
  ;; FIXXME: this is a test for getting it work independent of CamelCase words

  ;;(setq org-hide-leading-stars nil)

  (org-bullets-mode 0)
  (org-expiry-deinsinuate);; omit automatically created drawers
  (setq org-log-into-drawer nil)

    ;; disabled 2021-02-15 since I switched to bright mode:    (disable-theme 'wombat)

  ;; http://stackoverflow.com/questions/24684979/how-to-add-a-tool-bar-button-in-emacs
  ;;(add-hook 'after-init-hook
  ;;          (lambda ()
  ;;            (define-key global-map [tool-bar pdf-button]
  ;;              '(menu-item "Export to PDF" org-latex-export-to-pdf
  ;;                          :image (image :type png :file "~/.emacs.d/bin/images/icon_PDF_16x16.png")
  ;;                          ))))
  (define-key global-map [tool-bar pdf-button]
    '(menu-item "Export to PDF" org-latex-export-to-pdf
                :image (image :type png :file (concat my-user-emacs-directory "bin/images/icon_PDF_16x16.png"))
                ))
)


(my-emacs-normal-setup)

(defun my-toggle-beginner-setup ()
  "Toggle Emacs beginner setup and normal Emacs"
  (interactive)
  (cond (my-toggle-beginner-setup-status
         ;; normal mode
         (my-emacs-normal-setup)
         (message "As you please")
         (setq my-toggle-beginner-setup-status nil)
         )
        (t
         ;; make it easy for beginners
         (my-emacs-beginner-setup)
         (message "Welcome to Emacs!")
         (setq my-toggle-beginner-setup-status t)
         )
        )
  )

(global-set-key [(shift f11)] 'my-toggle-beginner-setup)

my-toggle-dark-bright-theme() → S-F12

Some times, I do have to switch from my default dark theme to a bright one in order to get a decent result for a projector or similar.

(defvar my-toggle-dark-bright-theme-status nil
  "Toggle between dark emacs theme and bright emacs theme; nil means initial switch to dark theme, t means initial switch to bright theme")

(defun my-toggle-dark-bright-theme ()
  "Toggle between dark emacs theme and bright emacs theme"
  (interactive)
  (cond (my-toggle-dark-bright-theme-status
         (message "Loading bright theme")
         (disable-theme 'wombat)
         ;;(load-theme 'leuven t)
         (setq my-toggle-dark-bright-theme-status nil)
         )
        (t
         (message "Loading dark theme")
         ;;(disable-theme 'leuven)
         (load-theme 'wombat t) ;; dark theme
         (setq my-toggle-dark-bright-theme-status t)
         )
        )
  )

(global-set-key [(shift f12)] 'my-toggle-dark-bright-theme)

my-toggle-split-and-single-window() - Toggle between split windows and a single window

http://thornydev.blogspot.co.at/2012/08/happiness-is-emacs-trifecta.html

(defun my-toggle-split-and-single-window()
  "Switch back and forth between one window and whatever split of
windows we might have in the frame. The idea is to maximize the
current buffer, while being able to go back to the previous split
of windows in the frame simply by calling this command again."
  (interactive)
  (if (not (window-minibuffer-p (selected-window)))
      (progn
        (if (< 1 (count-windows))
            (progn
              (window-configuration-to-register ?u)
              (delete-other-windows))
          (jump-to-register ?u))))
                                        ;(my-iswitchb-close)
  )

Inserting time-stamps → my-map [dDtT]

Org-mode has some built-in methods to create active and inactive time-stamps. The following functions offer a shortcut to insert the current day as an Org-mode time-stamp when I am within an Org-mode buffer and in ISO 8601 format when I am in another major mode.

;; Insert immediate timestamp
(defun my-insert-timestamp()
  "Insert the current time in yyyy-mm-dd format."
  (interactive "*")
  (if (eq major-mode 'org-mode)
      (progn
	(org-insert-time-stamp nil t nil)
	(insert " ")
	)
    (insert (format-time-string "%Y-%m-%d" (current-time)))
    )
  )

(bind-key "t" #'my-insert-timestamp my-map)
(defun my-insert-timestamp-inactive()
  "Insert the current time in yyyy-mm-dd format."
  (interactive "*")
  (if (eq major-mode 'org-mode)
      (progn
	(org-insert-time-stamp nil t t)
	(insert " ")
	)
    (insert (format-time-string "%Y-%m-%d" (current-time)))
    )
  )

(bind-key "T" #'my-insert-timestamp-inactive my-map)
(defun my-insert-datestamp()
  "Insert the current date in yyyy-mm-dd format."
  (interactive "*")
  (if (eq major-mode 'org-mode)
      (progn
	(org-insert-time-stamp nil nil nil)
	(insert " ")
	)
    (insert (format-time-string "%Y-%m-%d" (current-time)))
    )
  )

(bind-key "d" #'my-insert-datestamp my-map)
(defun my-insert-datestamp-inactive()
  "Insert the current date in yyyy-mm-dd format."
  (interactive "*")
  (if (eq major-mode 'org-mode)
      (progn
	(org-insert-time-stamp nil nil t)
	(insert " ")
	)
    (insert (format-time-string "%Y-%m-%d" (current-time)))
    )
  )

(bind-key "D" #'my-insert-datestamp-inactive my-map)

OS X: mdfind (find via spotlight)

Code of this heading does provide access to the macOS spotlight search engine for Emacs. I did not use it quite often, as long as I was using macOS on my computers.

http://blog.zenspider.com/2007/03/locate-and-spotlight.html

(when (my-system-type-is-darwin)
  (defun locate-make-mdfind-command-line (search-string)
    (list "mdfind" (concat "kMDItemDisplayName=*" search-string "*")))
  (defun spotlight ()
    "Search for files by name using spotlight"
    (interactive)
    (let ((locate-command "mdfind")
	  (locate-make-command-line 'locate-make-mdfind-command-line))
      (call-interactively 'locate nil)))
  (defun spotlight-full ()
    "Search using spotlight"
    (interactive)
    (let ((locate-command "mdfind"))
      (call-interactively 'locate nil)))
  )

my-codenav-*: Code navigation → M-i | M-k

I found very handy navigation commands on Code Navigation in Emacs which I included here:

(defun my-codenav-imenu-candidates ()
  "Get the candidates list from imenu."
  (let* ((items (imenu--make-index-alist))
	 (items (delete (assoc "*Rescan*" items) items)))
    items))


(defun my-codenav-flatten-candidates (candidates)
  "Flatten CANDIDATES of imenu list."
  (let (result)
    (dolist (candidate candidates result)
      (if (imenu--subalist-p candidate)
          (setq result (append result (my-codenav-flatten-candidates (cdr candidate))))
        (add-to-list 'result candidate)))
    result))


(defun my-codenav-sort-candidates (candidates)
  (sort candidates (lambda (a b) (< (cdr a) (cdr b)))))


(defun my-codenav-current-symbol (names-and-pos)
  "Figure out current definition by checking positions of NAMES-AND-POS against current position."
  (let ((list-length (length names-and-pos))
        (current-pos (point))
        (current-index 0)
        (next-index 0))
    (dolist (symbol names-and-pos)
      ;; If we reaches the end, just return the last element
      ;; instead of returning index+1
      (setq next-index (if (< next-index (1- list-length))
                          (1+ current-index)
                         current-index))
      (let* ((current-symbol-pos (marker-position (cdr symbol)))
	     (next-symbol-pos (marker-position (cdr (nth next-index names-and-pos)))))
        (if (and (= current-index 0) (< current-pos current-symbol-pos))
            (return 0))
	(if (and (>= current-pos current-symbol-pos) (< current-pos next-symbol-pos))
	    (return current-index)))
      (setq current-index (1+ current-index)))
    ;; If last item, decrement index
    (if (eq current-index (length names-and-pos))
	(1- current-index)
      current-index)))

(defun my-codenav-next-definition ()
  "Navigate to next function/class definition."
  (interactive)
  (let* ((imenu-candidates (my-codenav-imenu-candidates))
         (names-and-pos (my-codenav-sort-candidates (my-codenav-flatten-candidates imenu-candidates)))
	 (current-symbol (my-codenav-current-symbol names-and-pos))
         (next-symbol-index (if (>= (1+ current-symbol) (length names-and-pos)) 0
                              (1+ current-symbol)))
	 (next-symbol (nth next-symbol-index names-and-pos)))
    (imenu next-symbol)))


(defun my-codenav-prev-definition ()
  "Navigate to previous function/class definition."
  (interactive)
  (let* ((imenu-candidates (my-codenav-imenu-candidates))
         (names-and-pos (my-codenav-sort-candidates (my-codenav-flatten-candidates imenu-candidates)))
	 (current-symbol (my-codenav-current-symbol names-and-pos))
         (prev-symbol-index (if (< (1- current-symbol) 0) (1- (length names-and-pos))
                              (1- current-symbol)))
	 (prev-symbol (nth prev-symbol-index names-and-pos)))
    (imenu prev-symbol)))

(global-set-key (kbd "M-i") (lambda () (interactive) (my-codenav-prev-definition)))
(global-set-key (kbd "M-k") (lambda () (interactive) (my-codenav-next-definition)))

my-lorem-ipsum-overlay

2020-02-09found on GitHub via Mastodon toot and added

First, I’m going to install lorem-ipsum which provides basic functionality to generate latin bullshit:

(use-package lorem-ipsum
  :ensure t
  :defer 110
)

I found this beauty within alphapapa’s diamonds on GitHub:

(defcustom unpackaged/lorem-ipsum-overlay-exclude nil
  "List of regexps to exclude from `my-lorem-ipsum-overlay'."
  :type '(repeat regexp))

(setq unpackaged/lorem-ipsum-overlay-exclude
  `(
   "NEXT" "TODO" "STARTED" "WAITING" "DONE" "SOMEDAY" "CANCELED"
   "Today"
   "Important" "Started" "reward" "Scheduled:"
   "Other"
   ;;,(rx "Other" space "items")                     ;; "Other items"   NOT working yet
   ;;,(rx "Sched\\." (one-or-more digit) "x:")    ;; "Sched.10x:"    NOT working yet
   ;;"Sched\\.[0-9]+:"    ;; NOT working
   "WAITING" "items"          ;; "WAITING items"         NOT working yet
   "Priority"                 ;; "Priority <= B items"   NOT working yet
   "misc" "projects" "issues" "hardware"
   "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"
   "January" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "November" "December"
   )
)

;;;###autoload
(defun my-lorem-ipsum-overlay ()
  "Overlay all text in current buffer with \"lorem ipsum\" text.
When called again, remove overlays.  Useful for taking
screenshots without revealing buffer contents.
Each piece of non-whitespace text in the buffer is compared with
regexps in `unpackaged/lorem-ipsum-overlay-exclude', and ones
that match are not overlaid.  Note that the regexps are compared
against the entire non-whitespace token, up-to and including the
preceding whitespace, but only the alphabetic part of the token
is overlaid.  For example, in an Org buffer, a line that starts
with:
  #+TITLE: unpackaged.el
could be matched against the exclude regexp (in `rx' syntax):
  (rx (or bol bos blank) \"#+\" (1+ alnum) \":\" (or eol eos blank))
And the line would be overlaid like:
  #+TITLE: parturient.et"
  (interactive)
  (require 'lorem-ipsum)
  (let ((ovs (overlays-in (point-min) (point-max))))
    (if (cl-loop for ov in ovs
                 thereis (overlay-get ov :lorem-ipsum-overlay))
        ;; Remove overlays.
        (dolist (ov ovs)
          (when (overlay-get ov :lorem-ipsum-overlay)
            (delete-overlay ov)))
      ;; Add overlays.
      (let ((lorem-ipsum-words (--> lorem-ipsum-text
                                    (-flatten it) (apply #'concat it)
                                    (split-string it (rx (or space punct)) 'omit-nulls)))
            (case-fold-search nil))
        (cl-labels ((overlay-match (group)
                                   (let* ((beg (match-beginning group))
                                          (end (match-end group))
                                          (replacement-word (lorem-word (match-string group)))
                                          (ov (make-overlay beg end)))
                                     (when replacement-word
                                       (overlay-put ov :lorem-ipsum-overlay t)
                                       (overlay-put ov 'display replacement-word))))
                    (lorem-word (word)
                                (if-let* ((matches (lorem-matches (length word))))
                                    (apply-case word (downcase (seq-random-elt matches)))
                                  ;; Word too long: compose one.
                                  (apply-case word (downcase (compose-word (length word))))))
                    (lorem-matches (length &optional (comparator #'=))
                                   (cl-loop for liw in lorem-ipsum-words
                                            when (funcall comparator (length liw) length)
                                            collect liw))
                    (apply-case (source target)
                                (cl-loop for sc across-ref source
                                         for tc across-ref target
                                         when (not (string-match-p (rx lower) (char-to-string sc)))
                                         do (setf tc (string-to-char (upcase (char-to-string tc)))))
                                target)
                    (compose-word (length)
                                  (cl-loop while (> length 0)
                                           for word = (seq-random-elt (lorem-matches length #'<=))
                                           concat word
                                           do (cl-decf length (length word)))))
          (save-excursion
            (goto-char (point-min))
            (while (re-search-forward (rx (group (1+ (or bol bos blank (not alpha)))
                                                 (0+ (not (any alpha blank)))
                                                 (group (1+ alpha))
                                                 (0+ (not (any alpha blank)))))
                                      nil t)
              (unless (cl-member (match-string 0) unpackaged/lorem-ipsum-overlay-exclude
                                 :test (lambda (string regexp)
                                         (string-match-p regexp string)))
                (overlay-match 2))
              (goto-char (match-end 2)))))))))

Note: I filed a feature request on ignoring some keywords from replacement.

my-insert-char

2020-02-12found and setup this nugget via this toot and that toot

This toot shows a nice method to enter Unicode characters system-wide:

  1. define my-insert-char below
  2. manually test in the command line using:
    emacsclient -c -e '(my-insert-char)'
        
  3. map to a system-wise keyboard shortcut and use it to put arbitrary Unicode characters in the system clipboard

I blogged about this.


Helper function to modify the behavior of counsel-unicode-char to match the one of insert-char taken from this reddit thread:

(defun counsel-unicode-char-to-kill (&optional count)
  "Insert COUNT copies of a Unicode character to kill ring.
  COUNT defaults to 1."
   (interactive "p")
   (setq ivy-completion-beg (point))
   (setq ivy-completion-end (point))
   (ivy-read "Unicode name: " counsel--unicode-table
             :history 'counsel-unicode-char-history
             :action (lambda (name)
                       (with-ivy-window
                         (kill-new (make-string count (get-text-property 0 'code name)))
                         ))
             :caller 'counsel-unicode-char-to-kill))
(defun my-insert-char ()
  (interactive)
  (with-temp-buffer
    (call-interactively 'insert-char) ;; classic method
    ;; (call-interactively 'counsel-unicode-char) ;; improved usability but inserts characters differently
    ;; (call-interactively 'counsel-unicode-char-to-kill)
    (kill-ring-save (point-min) (point-max))))

(defun my-insert-char-counsel ()
  (interactive)
  (with-temp-buffer
    (call-interactively 'counsel-unicode-char) ;; improved usability but inserts characters differently
    (kill-ring-save (point-min) (point-max))))

(defun my-insert-char-counsel-to-kill ()
  (interactive)
  (with-temp-buffer
    (call-interactively 'counsel-unicode-char-to-kill)
    (kill-ring-save (point-min) (point-max))))

hydra

Hydra is a method to customize personal and visual menus to summarize various functionality.


Please note: :color red is for repeating actions, :color blue for one-time actions. From the web site:

The :color key is a shortcut. It aggregates :exit and :foreign-keys key in the following way:

colortoggle
redstay
blue:exit t
amaranth:foreign-keys warn
teal:foreign-keys warn :exit t
pink:foreign-keys run

START of hydra

(use-package hydra
  :ensure t
  :defer 90
  :config ;; executed after loading package

toggle things with Ruby-style docstring → my-map M

Example 7 from hydra-examples.el

(defvar whitespace-mode nil)
(defhydra hydra-toggle (:color teal)
  "
_f_ auto-fill-mode:    %`auto-fill-function
_t_ truncate-lines:    %`truncate-lines
_w_ whitespace-mode:   %`whitespace-mode
_l_ org link display:  %`org-descriptive-links
_a_ abbrev-mode:       %`abbrev-mode
_d_ debug-on-error:    %`debug-on-error
"
;;  ("q" nil "quit")
  ("a" abbrev-mode nil)
  ("d" toggle-debug-on-error nil)
  ("f" auto-fill-mode nil)
  ("t" toggle-truncate-lines nil)
  ("w" whitespace-mode nil)
  ("l" org-toggle-link-display nil)
)
;; Recommended binding:
;;(global-set-key (kbd "C-c C-v") 'hydra-toggle/body)
(bind-key "M" #'hydra-toggle/body my-map)

s-expressions in the docstring

Example 9 from hydra-examples.el

;; You can inline s-expresssions into the docstring like this:
(defvar dired-mode-map)
(declare-function dired-mark "dired")
(when (bound-and-true-p hydra-examples-verbatim)
  (require 'dired)
  (defhydra hydra-marked-items (dired-mode-map "")
    "
Number of marked items: %(length (dired-get-marked-files))
"
    ("m" dired-mark "mark")))

apropos → C-c h

Example 10 from hydra-examples.el

(defhydra hydra-apropos (:color blue
                         :hint nil)
  "
_a_propos        _c_ommand
_d_ocumentation  _l_ibrary
_v_ariable       _u_ser-option
^ ^       valu_e_"
  ("a" apropos)
  ("d" apropos-documentation)
  ("v" apropos-variable)
  ("c" apropos-command)
  ("l" apropos-library)
  ("u" apropos-user-option)
  ("e" apropos-value))
;; Recommended binding:
(global-set-key (kbd "C-c h") 'hydra-apropos/body)

rectangle-mark-mode → C-x r h

Example 11 from hydra-examples.el

(require 'rect)
(defhydra hydra-rectangle (:body-pre (rectangle-mark-mode 1)
                           :color pink
                           :post (deactivate-mark))
  "
  ^_k_^     _d_elete    _s_tring
_h_   _l_   _o_k        _y_ank
  ^_j_^     _n_ew-copy  _r_eset
^^^^        _e_xchange  _u_ndo
^^^^        ^ ^         _p_aste
"
  ("h" rectangle-backward-char nil)
  ("l" rectangle-forward-char nil)
  ("k" rectangle-previous-line nil)
  ("j" rectangle-next-line nil)
  ("e" hydra-ex-point-mark nil)
  ("n" copy-rectangle-as-kill nil)
  ("d" delete-rectangle nil)
  ("r" (if (region-active-p)
           (deactivate-mark)
         (rectangle-mark-mode 1)) nil)
  ("y" yank-rectangle nil)
  ("u" undo nil)
  ("s" string-rectangle nil)
  ("p" kill-rectangle nil)
  ("o" nil nil))

(global-set-key (kbd "C-x r h") 'hydra-rectangle/body)

reStructuredText → F1

  (defhydra hydra-rst (:color blue)
    (concat my-f-key-settings
      "
    _a_ insert • complete • promote adornment ( C-c C-a C-a     )
    _c_ycle adornment                         ( C-- C-=         )        Let's love
    _r_e-adjust adornments of buffer          ( C-c C-a C-s     )                    reStructured Text
    _v_isualize adornment formats used        ( C-c C-a C-d     )

    _,_      ↑                                ( C-M-e           )
          section
    _._      ↓                                ( C-M-a           )

    _m_ark section                            ( C-M-h           )
    _n_ew line with indent                    ( C-j             )
  ────^^────────────────────────────────────────────────────────────
      _s_hift region →         ( C-c C-r TAB     )
    ← _S_hift region           ( M-- C-c C-r TAB )
  ────^^───────────────────────────────────────────^^───────────────────────────────────────────────────────────
    _C_omment region           ( M-;         )     _t_oc temp view  (close with c; zip with z) ( C-c C-t C-t )
    _b_ullet list region       ( C-c C-l C-b )     _T_oc insert TOC (did not work)             ( C-c C-t C-i )
    _e_numerated list region   ( C-c C-l C-e )     _u_pdate TOC                                ( C-c C-t C-u )
    _i_nsert item              ( C-c C-l C-i )
  ^^
    ")
    ("a" rst-adjust nil)
    ("c" (rst-adjust -1) nil :color red)
    ("r" rst-straighten-adornments nil)
    ("v" rst-display-adornments-hierarchy nil)
    ("," rst-forward-section nil :color red)
    ("." rst-backward-section nil :color red)
    ("m" rst-mark-section nil :color red)
    ("s" rst-shift-region nil :color red)
    ("S" rst-shift-region nil :color red)
    ("n" newline-and-indent nil)
    ("C" comment-dwim nil)
    ("b" rst-bullet-list-region nil)
    ("e" rst-enumerate-region nil)
    ("i" rst-insert-list nil)
    ("t" rst-toc nil)
    ("T" rst-toc-insert nil)
    ("u" rst-toc-update nil)
    ("q" nil "quit")
  )

(require 'rst)
(define-key rst-mode-map [f1] 'hydra-rst/body)

hydra-search → F9

As soon as I was able to test org-rifle, it has replaced many search workflows I was using before. Its speed combined with the result visualization is brilliant.

helm-org-rifle
Show results from all open Org buffers
helm-org-rifle-agenda-files
Show results from Org agenda files
helm-org-rifle-current-buffer
Show results from current buffer
helm-org-rifle-directories
Show results from selected directories; with prefix, recursively
helm-org-rifle-files
Show results from selected files
helm-org-rifle-org-directory
Show results from Org files in org-directory
(defhydra hydra-search (:color blue)
    (concat my-f-key-settings
  "
  ^^Rifle                   ^^Profiler          ^^Bookmarks                    ^^MISC                    Ex.:    #A NEXT :foo:bar: !unwanted
  ^^────────────────────────^^──────────────────^^─────────────────────────────^^────────────────
  rifle _c_urrent buffer    _p_rofile CPU       _m_ark new bookmark  C-x r m   _d_ired-jump
  rifle _o_pen buffers      _R_eport            jump _b_ookmark      C-x r b
  rifle _a_genda files      profiler sto_P_     _l_ist bookmarks     C-x r l
  rifle whole _O_rg dir     ^^                  ^^
  ^^                        ^^                  dogears-_g_o
  ^^                        ^^                  dogears-_r_emember
  ^^Filter                  ^^                  ^^                             ^^
  ^^────────────────────────────────────────^^─────────────────────────────^^────────────────
  tree: _w_aiting tasks
  tree: OPEN TASKS by tags, no completion: my-sparse-tree-with-_t_ag-filter
  tree: all tasks by tags: org-tags-sparse-_T_ree
  list: all tasks by tags: org-tags-_v_iew  (C-c a m)

  ")
  ("q" nil "quit")

  ("c" helm-org-rifle-current-buffer nil)
  ("o" helm-org-rifle nil)
  ("O" helm-org-rifle-org-directory nil)
  ("a" helm-org-rifle-agenda-files nil)

  ("p" (lambda () (interactive) (profiler-start 'cpu)) nil)
  ("R" profiler-report nil)
  ("P" profiler-stop nil)

  ("m" bookmark-set nil)
  ("b" bookmark-jump nil)
  ("l" bookmark-bmenu-list nil)
  ("g" dogears-go nil)
  ("r" dogears-remember nil)

  ("d" dired-jump nil)

  ("w" my-sparse-tree-WAITING nil)
  ("t" my-sparse-tree-with-tag-filter nil)
  ("T" org-tags-sparse-tree nil)
  ("v" org-tags-view nil)

)

(global-set-key [f9] 'hydra-search/body)

hydra-projectile → S-F9

2020-12-10initial setup; stolen from here
(defhydra hydra-projectile-other-window (:color teal)
  "projectile-other-window"
  ("f"  projectile-find-file-other-window        "file")
  ("g"  projectile-find-file-dwim-other-window   "file dwim")
  ("d"  projectile-find-dir-other-window         "dir")
  ("b"  projectile-switch-to-buffer-other-window "buffer")
  ("q"  nil                                      "cancel" :color blue))

(defhydra hydra-projectile (:color teal
                            :hint nil)
    (concat my-f-key-settings
  "
     PROJECTILE: %(projectile-project-root)

     Find File            Search/Tags          Buffers                Cache
------------------------------------------------------------------------------------------
_s-f_: file            _a_: ag                _i_: Ibuffer           _c_: cache clear
 _ff_: file dwim       _g_: update gtags      _b_: switch to buffer  _x_: remove known project
 _fd_: file curr dir   _o_: multi-occur     _s-k_: Kill all buffers  _X_: cleanup non-existing
  _r_: recent file                                               ^^^^_z_: cache current
  _d_: dir

")
  ("a"   projectile-ag)
  ("b"   projectile-switch-to-buffer)
  ("c"   projectile-invalidate-cache)
  ("d"   projectile-find-dir)
  ("s-f" projectile-find-file)
  ("ff"  projectile-find-file-dwim)
  ("fd"  projectile-find-file-in-directory)
  ("g"   ggtags-update-tags)
  ("s-g" ggtags-update-tags)
  ("i"   projectile-ibuffer)
  ("K"   projectile-kill-buffers)
  ("s-k" projectile-kill-buffers)
  ("m"   projectile-multi-occur)
  ("o"   projectile-multi-occur)
  ("s-p" projectile-switch-project "switch project")
  ("p"   projectile-switch-project)
  ("s"   projectile-switch-project)
  ("r"   projectile-recentf)
  ("x"   projectile-remove-known-project)
  ("X"   projectile-cleanup-known-projects)
  ("z"   projectile-cache-current-file)
  ("`"   hydra-projectile-other-window/body "other window")
  ("q"   nil "cancel" :color blue))

(global-set-key [(shift f9)] 'hydra-projectile/body)

hydra-nxml → F1

(defhydra hydra-nxml (:color blue)
    (concat my-f-key-settings
  "
  ^^                               ^^                           ^^                ←→ element  C-M n|p
  ^^View                           ^^                           ^^                ↑↓ element  C-M u|d
  ^────────^───────────────────────^──────^─────────────────────^─────────^─────
  _r_egion prettyfy                ^^                           ^^                C-M-i  auto-complete
  _b_uffer prettify                ^^                           ^^                C-/    finish element
  ^^                               ^^                           ^^
  ^^                               ^^                           ^^
  ")
  ("r" my-xml-pretty-print-region nil)
  ("b" my-xml-pretty-print-buffer nil)

  ("q" nil "quit")
)

(require 'nxml-mode)
(define-key nxml-mode-map [f1] 'hydra-nxml/body)

hydra-csv → F1

(defhydra hydra-csv (:color blue)
  (concat my-f-key-settings
    "
^^
_a_lign Fields into Columns     C-c C-a          _B_ Set Buffer's Comment Start       C-c C-c
_u_nalign Columns into Fields   C-c C-u          _L_ Sort By Field Lexicographically  C-c C-s
^^                                               _N_ Sort By Field Numerically        C-c C-n
    _,_  ← Field →  _._           C-M-b/f          _D_ Use Descending Sort Order        C-c C-d
^^                                               _r_everse Order of Lines             C-c C-r
_S_ Make Separators Invisible   C-c C-v          _t_ranspose Rows and Columns         C-c C-t
_i_ Toggle Field Index Mode                       ^^
^^                                               _k_ Kill Fields          C-c C-k
^^                                               _y_ank Fields (Columns)  C-c C-y
^^                                               _Y_ank As New Table      C-c C-z
^^
  ")
  ("a" csv-align-fields        nil :color red)
  ("u" csv-unalign-fields      nil :color red)
  ("B" csv-set-comment-start   nil)
  ("D" csv-toggle-descending   nil)
  ("k" csv-kill-fields         nil)
  ("N" csv-sort-numeric-fields nil)
  ("r" csv-reverse-region      nil)
  ("L" csv-sort-fields         nil)
  ("t" csv-transpose           nil)
  ("S" csv-toggle-invisibility nil :color red)
  ("y" csv-yank-fields         nil)
  ("Y" csv-yank-as-new-table   nil)
  ("." csv-forward-field       nil :color red)
  ("," (csv-forward-field -1)           nil :color red)
  ("i" csv-field-index-mode    nil :color red)
  ("q" nil "quit")
)

(require 'csv-mode)
(define-key csv-mode-map [f1] 'hydra-csv/body)

hydra-org → F1

In 2018-07 I started to create hydras for major modes that contain shortcuts to many functions I am using as well as cheatsheets that work as a reminder. I started with dired and Elpy mode.

For Org mode, I could not come up with a list of shortcuts and cheatsheets I want to see within the hydra. Most probably because all Org mode commands are already within my finger-brains ;-)

This is to collect ideas of commands that might be candidates for hydra-org:

  • [X] my-jump-to-lazyblorg-heading-according-to-URL-in-clipboard()
  • [X] jump to [123] and do org-decrypt-entry where
    • 1: notes > browser
    • 2: ciso > personal
    • 3: ciso > shared
  • [X] my-insert-orgmode-url-from-clipboard()
  • [X] my-set-tags-including-inherited () → I forgot meanwhile!
  • [X] my-sparse-tree-with-tag-filter() - ask for a tag and filter open Org-tasks → my-map F
  • [ ] toggle commands for private/business agenda
  • [ ] start memacs (agenda) views
  • [ ] my-url-linkify()
  • [ ] my-lazyblorg-test()

Org agenda hydra:

  • [ ] my-agenda-cancel-event-and-set-to-inactive() → I forgot meanwhile!
  • [ ] my-0d() → I forgot meanwhile!

Not org related but might be candidates as well:

(defhydra hydra-org (:color blue)
  (concat my-f-key-settings
  "
  ^^Go to                          ^^Inserting                        ^^Org-timer              ^^Properties                          ^^Tables
  ^────────^───────────────────────^──────^───────────────────────────^^───────────────────────^─────────^───────────────────────────^^────────────────────────────────────
  _L_azyblorg ID via clipboard ID  _u_rl clipboard → Org link         Start  C-c C-x _0_       _o_rdered dependency                  S-RET  fill from cell above
  _p_ersonal credentials           _T_ags include inherited           Insert C-c C-x _._       _N_oblocking (this is never blocked)  C-u C-u C-c =  edit cell formular
  _b_usiness credentials           _1_ split block (M-RET)            Pause  C-c C-x _,_       org-linker-_e_dna                     C-c ?  info on cell + reference
  org-_a_ttach-reveal              add _n_ote to logbook              Stop   C-c C-x ___       ^^                                    C-c {  debug formula mode
  ^^                               _c_ontact link                     ^^                       ^^                                    C-c }  toggle row/column overlay
  ^^                               mark as _P_roject                  ^^                       ^^                                    C-c '  edit formulas (S-<arrows> for changing references)
  ^^                               generate & copy _i_d               ^^                       ^^
  ^^                               _w_ebarchive tsfile                ^^                       ^^
  ^^C-c C-a  attachment menu       indent-_r_igidly   C-x TAB         ^^                       ^^
  ^^                               org-_A_ttach-set-directory         ^^                       ^^
  ^^                               my-org-attach-_I_nsert             ^^                       ^^
  ^^                               ^^                                 ^^                       ^^                                    ^^M-0 C-x e  kmacro-end-and-call-macro → do macro until end of buffer
  ^^Filter                         ^^Export                         ^^MISC                          my-map C-c C-,
  ^────────^───────────────────────^──────^─────────────────────────^─────────^───────────────────────────────────────────────────
  _f_ocus agenda (prio A; sched .) _R_eddit/Wiki.js (region)        _x_  secret-mode                y  yankpad-expand
  _F_ocus disabled for agenda      _d_efine word                    b  my-mark-block
  ^^                               ^^                               _W_eather Graz                  S  my-synonym-current-word
  ^^                               ^^                               _!_ save-buffers-kill-terminal  s  spray-mode (speed-reading)
  ")

  ("f" (lambda ()
          (interactive)
          (org-agenda-filter-apply '("+.*\\[#A\\].*") 'regexp)
  ) nil)
  ("F" (lambda ()
          (interactive)
          (org-agenda-filter-show-all-re)
  ) nil)

  ("p" (lambda ()
          (interactive)
          (switch-to-buffer "notes.org")
          (org-id-goto "browser-restart")
          (org-decrypt-entry)
  ) nil)

  ("P" my-mark-as-project nil)

  ("w" my-webarchive-tsfile nil)

  ;; 2020-05-20: we do not share credentials in this company *g*
  ;; ("B" (lambda ()
  ;;         (interactive)
  ;;         (switch-to-buffer "rise.org")
  ;;         (org-id-goto "rise-shared-credentials")
  ;;         (org-decrypt-entry)
  ;; ) nil)

  ("b" (lambda ()
          (interactive)
          (switch-to-buffer "rise.org")
          (org-id-goto "rise-personal-credentials")
          (org-decrypt-entry)
  ) nil)

  ("L" my-jump-to-lazyblorg-heading-according-to-URL-in-clipboard nil)
  ("u" my-insert-orgmode-url-from-clipboard nil)
  ("T" my-set-tags-including-inherited nil)
  ("1" my-org-split-block nil)


  ("R" my-reddit-export-via-pandoc nil)
  ("d" define-word-at-point nil)
  ("W" (lambda () (interactive) (wttrin-query "graz")) nil)
  ("n" org-add-note nil)
  ("c" helm-org-contacts nil)
  ("i" my-id-get-or-generate nil)
  ("e" org-linker-edna nil)

  ("0" org-timer-start nil)
  ("." org-timer nil)
  ("," org-timer-pause-or-continue nil)
  ("_" org-timer-stop nil)

  ("!" save-buffers-kill-terminal nil)

;;  ("t" my-dired-tagtrees nil)
;;  ("T" my-dired-tagtrees-recursive nil)

  ("N" (lambda () (interactive) (org-set-property "NOBLOCKING" "t")) nil)
  ("o" (lambda () (interactive) (org-set-property "ORDERED" "t")) nil)

  ("r" indent-rigidly nil)
  ("A" org-attach-set-directory nil)
  ("a" org-attach-reveal nil)
  ("I" my-org-attach-insert nil)

  ("x" secret-mode nil)

  ("q" nil "quit")

)

(define-key org-mode-map [f1] 'hydra-org/body)
(define-key org-agenda-mode-map [f1] 'hydra-org/body)

hydra-python → F1

(defhydra hydra-python (:color blue)
    (concat my-f-key-settings
  "
  ^View^                 ^Navigation^        ^^                   C-↑↓   goto line of same level
  ^^─────────────────────^^──────────────────^^────────────────   M-RET  yafolding-toggle-element
  _h_ide/show fun  M-h   _p_ ← error    F5   ^^
  _c_ycle all      M-H   _n_   error →  F6   ^^
  ^^                     _<_ ← symbol        ^^
  ^^                     _>_   symbol →      ^^
  ^^                     _d_ definition      ^^
  ^^                     _r_ references      ^^
  ^^                     ^^                  ^^
  ^Edit^                 ^Help^              ^^
  ^^─────────────────────^^──────────────────^^────────────────
  _i_mplement    C-c i   _H_elp (pylookup)   ^^
  ^^                     ^^                  ^^
  ^^                     ^^                  ^^
  ")
  ("q" nil "quit")
  ("h" hs-cycle nil :color red)
  ("c" hs-cycle-all nil)

  ("p" flymake-goto-prev-error nil :color red)
  ("n" flymake-goto-next-error nil :color red)
  ("<" highlight-symbol-prev nil)
  (">" highlight-symbol-next nil)

  ("d" lsp-find-definition nil)
  ("r" lsp-find-references nil)

  ;;old;; ("i" elpygen-implement nil)
  ;;old;; ("r" elpy-refactor nil)
  ;;old;; ("d" sphinx-doc nil)
  ;;old;; ("." elpy-goto-definition nil)

  ("H" pylookup-lookup nil)
;  (""  nil)
)

(with-eval-after-load 'python
  (define-key python-mode-map [f1] 'hydra-python/body)
)

hydra-notmuch → F1

2021-02-13disabled since I can’t use business email with Emacs
(defhydra hydra-notmuch (:color blue)
    (concat my-f-key-settings
  "
  ^^─────────────────────^^──────────────────^^────────────────
  _g_ fetch mails        ^^                  ^^
  _m_ new email          ^^                  ^^
  ^^                     ^^                  ^^
  ^^                     ^^                  ^^
  ")
  ("q" nil "quit")
  ("g" my-notmuch-sync-and-update-index-and-buffer nil)
  ("m" notmuch-mua-new-mail nil)

;  ("p" flymake-goto-prev-error nil :color red)
;  ("<" highlight-symbol-prev nil)

)

(when (my-system-type-is-gnu)
    (define-key notmuch-hello-mode-map [f1] 'hydra-notmuch/body)
)

hydra-notmuch-message-mode → F1

2021-02-13disabled since I can’t use business email with Emacs
(when (my-system-type-is-gnu)
(defhydra hydra-notmuch-message-mode (:color blue)
    (concat my-f-key-settings
  "
  ^^Header                      ^^Footnotes               ^^Format
  ^^────────────────────────────^^────────────────────────^^────────────────
  change _s_ubject (C-c C-s f)  _a_dd          (C-c ! a)  _i_nsert quote (M-RET)
  ^^                            _b_ack to text (C-c ! b)  _S_ign
  ^^                            _g_oto FN      (C-c ! g)  _E_ncrypt and sign
  ^^                            _d_elete       (C-c ! d)  ^^
  ^^                            _r_enumber     (C-c ! r)  ^^
  ^^                            ^^                        ^^
  ^^                            ^^                        ^^
  ")
  ("q" nil "quit")
  ("s" message-change-subject nil)
  ("i" message-newline-and-reformat nil)

  ("a" footnote-add-footnote       nil)
  ("b" footnote-back-to-message    nil)
  ("g" footnote-goto-footnote      nil)
  ("d" footnote-delete-footnote    nil)
  ("r" footnote-renumber-footnotes nil)

  ("S" mml-secure-sign-pgpmime nil)
  ("E" mml-secure-encrypt-pgpmime nil)

;  ("p" flymake-goto-prev-error nil :color red)
;  ("<" highlight-symbol-prev nil)

)

(define-key notmuch-message-mode-map [f1] 'hydra-notmuch-message-mode/body)
)

hydra-notmuch-show-mode → F1

2021-02-13disabled since I can’t use business email with Emacs
(when (my-system-type-is-gnu)
(defhydra hydra-notmuch-show-mode (:color blue)
    (concat my-f-key-settings
  "
  ^^Email                               ^^Thread
  ^^────────────────────────────────────^^────────────────────────
  raw message _V_                       _P_revious _N_ext message
  add/remove tag: _+_ _-_                 fi_l_ter thread
  toggle _h_eaders                      ^^
  _h_tml part → browser                 ^^
  save attachments _w_                  ^^
  ^^                                    ^^
  _r_eply   _R_eply all                   ^^
  _o_rg link (C-c l  paste: C-c C-l)    ^^
  ^^                                    ^^
  ")
  ("q" nil "quit")

  (""  nil)

  ("V" notmuch-show-view-raw-message nil)
  ("w" notmuch-show-save-attachments nil)
  ("+" notmuch-show-add-tag nil)
  ("-" notmuch-show-remove-tag nil)
  ("h" notmuch-show-toggle-visibility-headers nil)
  ("P" notmuch-show-previous-message nil)
  ("N" notmuch-show-next-message nil)
  ("R" notmuch-show-reply nil)
  ("r" notmuch-show-reply-sender nil)
  ("l" notmuch-show-filter-thread nil)
  ("w" notmuch-show-save-attachments nil)

  ("h" notmuch-show-view-part nil)
  ("o" org-notmuch-store-link nil)
)

(define-key notmuch-show-mode-map [f1] 'hydra-notmuch-show-mode/body)
)

hydra-git → Shift F2

(defhydra hydra-git (:color blue)
    (concat my-f-key-settings
  "
  ^^View                 ^^                  ^^
  ^^─────────────────────^^──────────────────^^────────────────
  _s_tatus    my-map g   ^^                  ^^
  _t_ime-machine         ^^                  ^^
  magit-_l_og-buffer-file^^                  ^^
  ^^                     ^^                  ^^
  ^^Smeargle             ^^                  ^^
  ^^─────────────────────^^──────────────────^^────────────────
  _h_ighlight on         ^^                  ^^
  smeargle _c_ommits     ^^                  ^^
  smeargle _C_lear       ^^                  ^^
  ^^                     ^^                  ^^
  ")
  ("q" nil "quit")

  ("s" magit-status nil)
  ("t" git-timemachine-toggle nil)
  ("l" magit-log-buffer-file nil)

  ("h" smeargle nil :color red)
  ("c" smeargle-commits nil :color red)
  ("C" smeargle-clear nil)

)

(with-eval-after-load 'magit
  (define-key global-map [(shift f2)] 'hydra-git/body)
  ;;(global-set-key [f9] 'hydra-git/body)
)

hydra-dired → F1

(defhydra hydra-dired (:color blue)
    (concat my-f-key-settings
  "
  _t_agtrees            _f_ilter              _d_ate2name        g  refresh           M-c      dired-ranger-copy       M-t   filetags
  _T_agtrees recursive  _F_ilter recursive    time_2_name        +  mkdir             M-v      dired-ranger-paste      M-a   appendfilename
  ^────────^────────────^──────^──────────────^─────────^─────   *. mark extensions   M-m      dired-ranger-move
  _a_bsolute link       _m_emacs tsfile link  _D_ate2name.el     D  delete marked
  _A_bsolute basename   ^^                    ^^                 tk hide marked       C-c C-o  open externally
  ^^                    ^^                    ^^                 U  unmark all        C-o      open in new frame
  ^View    ^            ^Edit^                ^Order^
  ^────────^────────────^──────^──────────────^─────────^─────   w  copy filename  →  M-0 w    copy absolute filename        T touch/set date
  _c_ollapse mode       _v_idir (C-x C-q)     _s_ize ordered     C  copy/clone        C-t d    image-dired+ of marked files  M chmod
  _o_pen in file manager      ^^              _h_uman size       r  rename/move       <percent> l  lowercase                 O chown
  _O_pen in tmux        _SPC_ filetags.el     _1_ time ordered   !  pipe to shell     <percent> u  uppercase                 S ln -s
  _i_mage thumbnails    ^^                    _n_ormal ordered   x  delete flagged    <percent> &  flag temp files           C-x C-f  create file
  _(_ toggle details    ^^                    ^^                 c  compress
  ^^                    ^^                    ^^                 Z  dired-do-compress (=unp)
  ^^                    ^^                    ^^
  ^^                    ^^                    ^^                 attach to org: _3_ symlink  _4_ ln  _5_ cp  _6_ mv
  ")

  ("t" my-dired-tagtrees nil)
  ("T" my-dired-tagtrees-recursive nil)

  ("f" my-dired-filetags-filter nil)
  ("F" my-dired-filetags-filter-recursive nil)

  ("d" my-dired-date2name nil)
  ("2" my-dired-time2name nil)
;  ("D" filetags-dired-update-tags nil)
  ("D" date2name-dired-add-date-to-name nil)

  ("a" my-dired-copy-filename-as-absolute-link nil)
  ("m" my-dired-copy-filename-as-tsfile-link nil)
  ("A" (let ((current-prefix-arg '(4))) ;; emulate C-u
         (call-interactively 'my-dired-copy-filename-as-absolute-link)
       )
   nil)

  ("c" dired-collapse-mode nil)
  ("o" my-dired-open-in-file-manager nil)
  ("O" my-dired-open-here-in-tmux-shell nil)
  ("i" my-dired-mark-images-and-thumbnail nil)
  ("(" dired-hide-details-mode nil)

  ("v" dired-toggle-read-only nil)
  ("SPC" filetags-dired-update-tags nil)

  ("s" (dired-sort-other "-alS --group-directories-first") nil)
  ("h" (dired-sort-other "-alSh --group-directories-first") nil)
  ("1" (dired-sort-other "-alt --group-directories-first") nil)
  ("n" (dired-sort-other "-al --group-directories-first") nil)

  ("3" (lambda ()
                (interactive)
                (let ((org-attach-method 'lns))
                  (call-interactively #'org-attach-dired-to-subtree)))
                  nil)
  ("4" (lambda ()
                (interactive)
                (let ((org-attach-method 'ln))
                  (call-interactively #'org-attach-dired-to-subtree)))
                  nil)
  ("5" (lambda ()
                (interactive)
                (let ((org-attach-method 'cp))
                  (call-interactively #'org-attach-dired-to-subtree)))
                  nil)
  ("6" (lambda ()
                (interactive)
                (let ((org-attach-method 'mv))
                  (call-interactively #'org-attach-dired-to-subtree)))
                  nil)

  ("q" nil "quit")

;  ("s" (setq dired-listing-switches "-alS --block-size=\'1") nil)
;  ("n" (setq dired-listing-switches "-al --block-size=\'1") nil)

)

(define-key dired-mode-map [f1] 'hydra-dired/body)

hydra-pdftools → F1

(defhydra hydra-pdftools (:color blue :hint nil)
    (concat my-f-key-settings
        "
                                                                      ╭───────────┐
       Move  History   Scale/Fit                                      │ PDF Tools │
   ╭──────────────────────────────────────────────────────────────────┴───────────╯
         ^^_g_^^      _B_    ^↧^    _+_    ^ ^      [_s_] search    [_u_] revert buffer
         ^^^↑^^^      ^↑^    _H_    ^↑^  ↦ _W_ ↤    [_o_] outline   [_i_] info
         ^^_p_^^      ^ ^    ^↥^    _0_    ^ ^      [_F_] link      [_d_] dark mode
         ^^^↑^^^      ^↓^  ╭─^─^─┐  ^↓^  ╭─^ ^─┐    [_f_] search link
    _h_ ←pag_e_→ _l_  _N_  │ _P_ │  _-_    _b_
         ^^^↓^^^      ^ ^  ╰─^─^─╯  ^ ^  ╰─^ ^─╯
         ^^_n_^^      ^ ^  _r_eset slice box
         ^^^↓^^^
         ^^_G_^^

   Navigation                                    Search                       Annotations
   ───────────────────────────────────────────────────────────────────────────^─────────^───────────────
   ↑   C-p  BSPC   p     <            M-<        C-s   search forward         C-c C-a l  list annotations (jump: SPC)
      line  view  page  page border  document    C-r   search backward        q          close annotations list
   ↓   C-n   SPC   n     >            M->        f     search in links        C-c C-a h  highlight (m)
                                                 F     pick link and jump     d          mark for delete
   M-g g  goto page                              M-s o occur (jump via RET)   x          delete marked
                                                                              u          unmark
   Display                         Margins              AuxTeX
   ───────────────────────────────────────────────────────────────────────────────────────────────────
   +/-    Zoom                     s b  trim margins    C-c C-g    jump to PDF spot
   0      reset zoom               s r  reset margins   C-mouse-1  jump to source in PDF
   W/H/P  fit width/height/page
   o      outline (jump via RET)          g → reload file     C-c C-p → print file

        ")
        ("\\" hydra-master/body "back")
        ("q" nil "quit")
;;        ("al" pdf-annot-list-annotations)
;;        ("ad" pdf-annot-delete)
;;        ("aa" pdf-annot-attachment-dired)
;;        ("am" pdf-annot-add-markup-annotation)
;;        ("at" pdf-annot-add-text-annotation)
        ("y"  pdf-view-kill-ring-save)
        ("+" pdf-view-enlarge :color red)
        ("-" pdf-view-shrink :color red)
        ("0" pdf-view-scale-reset)
        ("H" pdf-view-fit-height-to-window)
        ("W" pdf-view-fit-width-to-window)
        ("P" pdf-view-fit-page-to-window)
        ("n" pdf-view-next-page-command :color red)
        ("p" pdf-view-previous-page-command :color red)
        ("d" pdf-view-dark-minor-mode)
        ("b" pdf-view-set-slice-from-bounding-box)
        ("r" pdf-view-reset-slice)
        ("g" pdf-view-first-page)
        ("G" pdf-view-last-page)
        ("e" pdf-view-goto-page)
        ("o" pdf-outline)
        ("s" pdf-occur)
        ("i" pdf-misc-display-metadata)
        ("u" pdf-view-revert-buffer)
        ("F" pdf-links-action-perfom)
        ("f" pdf-links-isearch-link)
        ("B" pdf-history-backward :color red)
        ("N" pdf-history-forward :color red)
        ("l" image-forward-hscroll :color red)
        ("h" image-backward-hscroll :color red)
        ("m" pdf-annot-add-highlight-markup-annotation))

hydra-buffers → F2 + my-map ,

This hydra offers buffer management functionalty.

FIXXME: add more features:

  • [ ] resize functions:
  • [ ] go through cheatsheet
  • https://github.com/abo-abo/hydra/wiki/Window-Management
  • [ ] I’ve defined a swap function or so

    (global-set-key (kbd “S-C-<left>”) ‘shrink-window-horizontally) weniger hoch - (global-set-key (kbd “S-C-<right>”) ‘enlarge-window-horizontally) höher = (global-set-key (kbd “S-C-<down>”) ‘shrink-window) (global-set-key (kbd “S-C-<up>”) ‘enlarge-window)

    (“h” windmove-left) (“j” windmove-down) (“k” windmove-up) (“l” windmove-right)

  (defhydra hydra-buffers (:color blue)
    (concat my-f-key-settings
      "
      %s(eyebrowse-mode-line-indicator)
  ^^                                _0_ switch to window config 0     C-S-;     prefix
  _,_ ← window                      _1_ switch to window config 1     prefix c  create
  _._   window →                      ...                    ^^       prefix ,  rename
  ^↦^ previous window config        _9_ switch to window config 9     prefix l  last window
  _r_ename current window config
  _c_reate new window config        ^^                                _b_ ibuffer-list-buffers
  _C_lose current window config     ^^
  new _f_rame                       ^^
  _!_ save-buffers-kill-terminal    ^^                      ▄
  ^^            ▄                   C-x 2  split _v_ertical ▄      ^^  C-x 0  _d_elete this
       _t_oggle ▄ ←→▐▐              ^^                             ^^  C-x 1  _k_eep this, delete others
       ^^             ▄             C-x 3  split _h_orizontal ▐▐   ^^         _o_ther window
       _s_plit/single ▄ ←→ ▇        s_w_ap ▇ ←→ ▇                  ^^    _=_  enlarge window
  ^^                                                               ^^    _-_  shrink window
  ────^^────────────────────────────────────────────────────────────
    ")

    ;; red = stay; blue = close
    ("," eyebrowse-prev-window-config nil :color red)
    ("." eyebrowse-next-window-config nil :color red)
    ("<tab>" eyebrowse-last-window-config nil :color red)
    ("r" eyebrowse-rename-window-config nil :color red)
    ("c" eyebrowse-create-window-config nil :color red)
    ("C" eyebrowse-close-window-config nil :color red)
    ("0" eyebrowse-switch-to-window-config-0 nil :color blue)
    ("1" eyebrowse-switch-to-window-config-1 nil :color blue)
    ("2" eyebrowse-switch-to-window-config-2 nil :color blue)
    ("3" eyebrowse-switch-to-window-config-3 nil :color blue)
    ("4" eyebrowse-switch-to-window-config-4 nil :color blue)
    ("5" eyebrowse-switch-to-window-config-5 nil :color blue)
    ("6" eyebrowse-switch-to-window-config-6 nil :color blue)
    ("7" eyebrowse-switch-to-window-config-7 nil :color blue)
    ("8" eyebrowse-switch-to-window-config-8 nil :color blue)
    ("9" eyebrowse-switch-to-window-config-9 nil :color blue)

    ("d" delete-window nil :color blue)
    ("k" delete-other-windows nil :color blue)
    ("v" my-vsplit-last-buffer nil :color blue)
    ("h" my-hsplit-last-buffer nil :color blue)
    ("o" other-window nil :color red)
    ("f" new-frame nil :color red)

    ("t" my-toggle-vertical-horizontal-split nil :color blue)
    ("s" my-toggle-split-and-single-window nil :color blue)

    ("w" window-swap-states nil)

    ("b" ibuffer-list-buffers nil)

;;    ("-" shrink-window-horizontally nil :color red)
;;    ("=" enlarge-window-horizontally nil :color red)
    ("-" shrink-window nil :color red)
    ("=" enlarge-window nil :color red)

    ("!" save-buffers-kill-terminal nil)
    ("q" nil "quit")
  )

(define-key global-map [f2] 'hydra-buffers/body)
(define-key my-map (kbd "C-c C-,") 'hydra-buffers/body) ;; to get it on a more prominent binding (as well) because I use it quite often!

hydra-emojis → Shift F4

2019-12-31: DISABLED for performance reasons: https://www.reddit.com/r/orgmode/comments/e9p84n/scaling_org_better_to_use_more_medsize_files_or/fcm5bsc/

  (defhydra hydra-emojis (:color blue)
    (concat my-f-key-settings
      "
  _i_nteractively inserting emojis
  _a_propos emojis
  ────^^────────────────────────────────────────────────────────────
    ")

    ;; red = stay; blue = close
    ("i" emojify-insert-emoji nil :color blue)
    ("a" emojify-apropos-emoji nil :color blue)

    ("q" nil "quit")
  )

(define-key global-map [(shift f4)] 'hydra-emojis/body)

hydra-spelling → F5

Idea stolen from this reddit thread.

(defhydra hydra-spelling (:color red)
    (concat my-f-key-settings
  "
  ^
  ^Spelling^          ^Errors^            ^Checker^
  ^────────^──────────^──────^────────────^───────^───────
  check _r_egion      _n_ext error        _m_ode
  check _b_uffer      _c_orrect           toggle _l_anguage
  _s_ynonym
  _d_efine word
  ^^
  ")
  ("q" nil "quit")
  ("r" flyspell-region nil)
  ("l" my-toggle-ispell-language nil)
  ("n" flyspell-goto-next-error nil)
  ("s" my-synonym-current-word nil :color blue)
  ("d" define-word-at-point nil :color blue) ;; define-word
;;  ("<" flyspell-correct-previous :color pink nil)
;;  (">" flyspell-correct-next :color pink nil)
  ("c" flyspell-correct-word-before-point nil)
;;  ("d" ispell-change-dictionary)
  ("b" flyspell-buffer nil)
  ("m" flyspell-mode nil))

  (global-set-key [f5] 'hydra-spelling/body)

hydra-markdown → F1

2020-04-19Disabled because I got (void-variable markdown-mode-map) and could not fix it now
(defhydra hydra-markdown (:color blue)
    (concat my-f-key-settings
  "
  ^^─────────────────────^^──────────────────^^────────────────
  _b_old                 _c_omment           ^^
  _i_talics              ^^                  ^^
  ^^                     ^^                  ^^
  ^^                     ^^                  ^^
  ")
  ("q" nil "quit")
  ("b" markdown-insert-bold nil)
  ("i" markdown-insert-italics nil)

  ("c" (lambda ()
                (interactive)
                (insert "[//]: # ()")) nil)

)

(define-key markdown-mode-map [f1] 'hydra-markdown/body)

END of hydra

);; end of hydra

(with-eval-after-load 'pdf-view-mode
  (define-key pdf-view-mode-map [f1] 'hydra-pdftools/body)
)
;;    (define-key pdf-view-mode-map [f1] 'hydra-pdftools/body)

Key bindings

In this heading, I do define many key bindings.

Unset binding for C-x C-c (save-buffers-kill-terminal)

2020-12-18initial setup

I sometimes confise the order of C-c C-x (prefix for various commands) with C-x C-c which closes my Emacs session and all of its buffers. So I decided to remove this mapping and quit emacs via M-x save-buffers-kill-terminal or a hydra.

(global-set-key (kbd "C-x C-c") nil)

my-map, the ressurection → C-c C-,

=C-c ,= is defined by Org-mode and must be re-defined here, after Org-mode has messed it up:

(There might be a better way but this is my current workaround.)

(global-set-key (kbd "C-c C-,") 'my-map)
(global-set-key (kbd "C-c ,") 'my-map)

;; so that following is possible again:
(bind-key "," #'hydra-buffers/body my-map)

general navigation keys: Home, End, forward/backward word, scrolling

Home/End should behave like everywhere else:

(global-set-key [home] 'beginning-of-buffer)
(global-set-key [end]  'end-of-buffer)

Move back/forward word is essential to me:

(global-set-key [C-left] 'backward-word)
(global-set-key [C-right] 'forward-word)

2016-03-23: PageUp/Down (instead of line up/down) for keyboards without PgUp/Dn-keys:

(global-set-key (kbd "C-p") 'my-scroll-down-half)
(global-set-key (kbd "C-n") 'my-scroll-up-half)

I tried some of those but they did not stick:

;; https://www.reddit.com/r/emacs/comments/445w6s/whats_some_small_thing_in_your_dotemacs_that_you/czntjs2
;;(global-set-key (kbd "C-, l")          'avy-goto-line)
;;(global-set-key (kbd "C-, w")          'avy-goto-word-0)
;;(global-set-key (kbd "C-, .")          'winner-redo)
;;(global-set-key (kbd "C-, m")          'winner-undo)
;;(global-set-key (kbd "C-, w")          'ace-window)
;;(global-set-key (kbd "C-, s")          'workspace-goto)
;;(global-set-key (kbd "C-, ]")          'evil-jump-to-tag)
;;(global-set-key (kbd "C-, n")          'neotree-toggle)

C-f jumps 5 lines:

(global-set-key (kbd "C-f") '(lambda () (interactive) (forward-line 5)))

boxquote → my-map [qQ]

2021-07-07Disabled because I wasn’t using it for over a decade

Box quote does something like this:

,----
| This is an example.
`----
(bind-key "q" #'boxquote-region my-map)
(bind-key "Q" #'boxquote-title my-map)

switching lines → my-map <up/down>

http://whattheemacsd.com//editing-defuns.el-02.html

Swapping two lines:

(defun my-move-line-down ()
  (interactive)
  (let ((col (current-column)))
    (save-excursion
      (forward-line)
      (transpose-lines 1))
    (forward-line)
    (move-to-column col)))

(defun my-move-line-up ()
  (interactive)
  (let ((col (current-column)))
    (save-excursion
      (forward-line)
      (transpose-lines -1))
    (move-to-column col)))

(bind-key (kbd "<up>") #'my-move-line-up my-map)
(bind-key (kbd "<down>") #'my-move-line-down my-map)

joining lines → my-map j

Joining the current line with the next one: http://whattheemacsd.com//key-bindings.el-03.html

(bind-key "j"
  (lambda ()
    (interactive)
    (join-line -1))
  my-map
)

web-jump → my-map w

«WebJump is a programmable Web hotlist (or bookmark) facility that uses Emacs completion to select a hotlist item and can prompt for query and option parameters.»

(require 'webjump)
(bind-key "w" #'webjump my-map)
(setq webjump-sites ;(append   ;; append instead of overwrite
      '(
	;; ------------------------------------------------------------------
	("Emacs Lisp List" . "anc.ed.ac.uk/~stephen/emacs/ell.html")
	("Ohio State Emacs Lisp Archive" .
	 [simple-query "www.cis.ohio-state.edu/emacs-lisp/"
		       "neutral.verbum.org/search?q=" "&archive=archive"])
	("PGP Key Server" .
	 [simple-query "pgp.mit.edu"
		       "pgp.mit.edu:11371/pks/lookup?op=index&search=" ""])
	;; my own jumps
	("Org-mode docu" . "http://orgmode.org/org.html")
	("Org-mode mailinglist" .
	 [simple-query "orgmode.org"
		       "http://search.gmane.org/?group=gmane.emacs.orgmode&query=" ""])
	("Debian Bug Number" .
	 [simple-query "www.debian.org/Bugs/"
		       "bugs.debian.org/cgi-bin/bugreport.cgi?bug="
		       ""])
	("EmacsWiki" .
	 [simple-query "www.emacswiki.org/cgi-bin/wiki.pl"
		       "www.emacswiki.org/cgi-bin/wiki.pl?search="
		       "&dosearch=1"])
	("Google" .
	 [simple-query "www.google.at" "www.google.at/search?q=" ""])
	("IMDB" .
	 [simple-query "www.imdb.com" "www.imdb.com/Find?select=All&for=" ""])
	;; ------------------------------------------------------------------
	) webjump-sample-sites ;)  ;; append instead of overwrite
	  )

Show recently files → my-map r

Show a dialog to open a recent file.

;;(bind-key "r" #'recentf-open-files my-map) ;; old mapping
(bind-key "r" #'helm-recentf my-map)

Outlook: edit/save message → my-map oe|os

Some interaction with Outlook:

(when (my-eval-if-binary-or-warn "outlook")
  (bind-key "oe" #'mno-edit-outlook-message my-map)
  (bind-key "os" #'mno-save-outlook-message my-map)
  )

org-mark-ring-goto() → my-map <left>

Jump to the previous position in the mark ring.

(bind-key (kbd "<left>") #'org-mark-ring-goto my-map)

open this config.org file → my-map .

Very handy to modify my config file: open it ;-)

(bind-key (kbd ".") (lambda()  ;; open main.el
			       (interactive)
			       (find-file (concat my-user-emacs-directory "config.org"))
			       )
          my-map
          )

open my org-mode teaser → my-map O

I’ve written an org-mode teaser file which can be found on https://github.com/novoid/org-mode-workshop

With this keyboard shortcut, I am able to quickly open the teaser file.

(bind-key (kbd "O") (lambda()
			       (interactive)
                               (when (my-system-type-is-gnu)
                                 (find-file
                               "~/src/org-mode-workshop/featureshow/org-mode-teaser.org")
                                 )
                               (when (string-equal system-name "GRZN17009")
                                 (find-file
                               "c:/Users/karl.voit/src/org-mode-workshop/featureshow/org-mode-teaser.org")
                                 )
                               (when (string-equal system-name "cosmo")
                                 (find-file
                               "c:/Users/John/src/org-mode-workshop/featureshow/org-mode-teaser.org")
                                 )
			       )
          my-map
  )

OrgStruct folding

Until 2017-05, I was using the Orgstruct minor mode for navigating through my Emacs config file. With migrating my old main.el to this config.org, the Orgstruct mode got obsolete for me.

Following commands offer a better usability for folding and unfolding in OrgStruct mode:

2015-11-10 deactivated:

(bind-key "[" (lambda () (interactive) (org-cycle t)) my-map)
(bind-key "]" (lambda () (interactive) (org-cycle)) my-map)

my-fix-drawer-order() → my-map C

I once noticed broken PROPERTIES drawers because of a bug in the Org-mode version I was using back then. Unfortunately, it messed up my drawers unnoticed for some time. For fixing the most common stuff, I created a macro and stored it here.

It searches for :END: followed by :PROPERTIES: (assuming first drawer is :LOGBOOK: and toggles order of them:

(fset 'my-fix-drawer-order
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ([19 58 69 78 68 58 17 10 58 80 82 79 80 69 82 84 73 69 83 58 return 1 67108896 19 58 69 78 68 58 5 23 18 58 76 79 71 66 79 79 75 58 return 25 return down] 0 "%d")) arg)))
(bind-key "C" #'my-fix-drawer-order my-map)

hippie-expand → M-/

«HippieExpand looks at the word before point and tries to expand it in various ways including expanding from a fixed list (like `‘expand-abbrev’’), expanding from matching text found in a buffer (like `‘dabbrev-expand’’) or expanding in ways defined by your own functions. Which of these it tries and in what order is controlled by a configurable list of functions.»

;(add-hook 'undo-tree-mode (lambda () (local-unset-key "C-/")))
;;failed;(global-set-key (kbd "C-c /") 'hippie-expand)

;; I could not make it work with C-/ - so I stick to M-/
(global-set-key (kbd "M-/") 'hippie-expand)

my-fill-or-unfill → M-q

Function defined above.

(global-set-key (kbd "M-q") 'my-fill-or-unfill)

mark word|line|sentence|sexp|defun → my-map mw|ml|ms|mx|md

With these commands, I get great shortcuts to put the current word, line, sentence, sexp or defun into the marked region:

(bind-key (kbd "mw") #'mark-word my-map)

(defun mark-line (&optional arg)
  (interactive "p")
  (beginning-of-line)
  (let ((here (point)))
    (dotimes (i arg)
      (end-of-line))
    (set-mark (point))
    (goto-char here)))

(bind-key "m l" 'mark-line my-map)

(defun mark-sentence (&optional arg)
  (interactive "P")
  (backward-sentence)
  (mark-end-of-sentence arg))

(bind-key "m s" #'mark-sentence my-map)
(bind-key "m x" #'mark-sexp my-map)
(bind-key "m d" #'mark-defun my-map)

my-notmuch → my-map n

2021-02-13disabled since I can’t use business email with Emacs
(when (my-system-type-is-gnu)
  (bind-key "n" 'my-notmuch my-map)
)

hydra-search

2020-04-13created to test if this binding position works

Somehow, the binding from the definition of the hydra does not work.

(global-set-key [f9] 'hydra-search/body)

literate test 2

;; nowebtest2
(setq nowebtest2 t)

autostart

At the end of loading most of my configuration, I want to execute some things, some of them only in interactive mode.

Fast start of my Emacs: my GNU/Emacs starts within approximately 70 seconds as of 2019-04-17 on Windows. Large parts of the startup time is spent doing the tasks defined in this section. If I don’t need stuff like agenda or my startup visibility, I create an empty file ~/.emacs.d/var/faststart and the following code omits some time-intensive parts of the autostart activity. This brings me down to approximately 25 seconds as of 2019-04-17.

(message "→★ finished loading config.org (w/o autostart) in %.2fs" (float-time (time-subtract (current-time) my-config-el-start-time)))
(setq faststart-indicator-file (concat no-littering-var-directory "faststart"))
(setq recache-indicator-file (concat no-littering-var-directory "recache"))

;; omit some things when running in batch-mode:
(when (not noninteractive)
  ;; when interactive:

  (global-set-key (kbd "M-x") 'counsel-M-x) ;; id:2017-03-02-cool-command-completion

  (my-log-misc "interactive Emacs is started")

  (when (or (my-system-is-rise) (my-system-is-sting))
     (my-hsplit-last-buffer)
  )

  ;(sleep-for 2)
  (setq my-org-agenda-tags-column (- (- (window-total-width) 3)))
  (message (concat "Setting agenda tags column to " (number-to-string my-org-agenda-tags-column)))
  (setq org-agenda-tags-column my-org-agenda-tags-column) ;; total width minus 3

  (if (file-exists-p faststart-indicator-file)
    (progn
      (my-log-misc "Faststart activated → omitting some autostart things")
      (message "Faststart activated → omitting some autostart things") ;; see explanation above
    )
    (progn
       (message "Creating agenda …")
       ;;(my-log-misc "Creating agenda …")
       (my-org-agenda)
       (message "my-org-startup-visibility …")
       (my-org-startup-visibility)

       ;; setup my buffers the way I like it:
       (my-hsplit-last-buffer)          ;; split horizontal: left is agenda
       (my-mobile-org-import)           ;; switch to inbox.org (right side) and move latest input from mobileorg.org into inbox.org
       (eyebrowse-create-window-config) ;; create 2nd config for misc personal stuff
       (switch-to-buffer "notes.org")   ;; open notes buffer
       ;; MAYBE: open misc.org on the other side
       (eyebrowse-rename-window-config 2 "misc") ;; name 2nd config
       (eyebrowse-create-window-config) ;; create 3rd config for rise
       (switch-to-buffer "rise.org")    ;; open rise buffer
       (org-shifttab)                   ;; toggle visibility
       (eyebrowse-rename-window-config 3 "rise") ;; set name for rise config
       (other-window 1) ;; switch from rise.org to agenda on the left side → DOESN'T work yet because there is no agenda on the left for some reason
       (when (my-system-is-rise)
         (eyebrowse-create-window-config) ;; create 4th config for rise/dired
         (eyebrowse-rename-window-config 4 "rise-dired") ;; set name for config
         (other-window 1) ;; switch from on the left side → may not work yet (test!)
         (dired my-business-dired-folder);; open dired buffer with business config
         (eyebrowse-switch-to-window-config-3);; switch back to "rise"
       )
       )
      )
   (my-log-misc "end of autostart")

)

Note: Removing faststart-indicator-file or running my-recache-all is done later-on. This is to make sure that Emacs bootup statistics stay comparable.

custom variables

This somehow got written by Emacs. Honestly, I am not sure whether or not I should keep this here. Well, it does not hurt either.

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(org-contacts-address-property "CITY")
 '(org-contacts-birthday-property "BORN")
 '(org-contacts-icon-property "PHOTOGRAPH")
 '(safe-local-variable-values
   (quote
    ((eval ispell-change-dictionary "german8")
     (eval ispell-change-dictionary "american")
     (eval ispell-change-dictionary "en_US")
     (flyspell-default-dictionary . "german8")))))

;; Somehow, this variable got overwritten by something from the
;; email config section to here to 'message-send-mail-with-outlook
;; and therefore it's been set here as well:
(setq message-send-mail-function 'message-smtpmail-send-it)

Closing and end for profiling

This is the end of the Elisp blocks to be tangled. Finishing up loading my configuration (famous last words):

;; ignoring recache process below in emacs startup time:
(setq my-config-el-loading-time (float-time (time-subtract (current-time) my-config-el-start-time)))

(when (not noninteractive)
  ;; when interactive:
  (my-log-misc
    (format-message "interactive Emacs boot finished (took %.2fs)" (float-time (time-subtract (current-time) my-config-el-start-time)))
  )
  ;;(my-log-misc
  ;;  (format-message "batch Emacs boot finished (took %.2fs)" (float-time (time-subtract (current-time) my-config-el-start-time)))
  ;;)
)

(if (file-exists-p faststart-indicator-file)
  (progn
    (delete-file faststart-indicator-file)
  )
  (progn
     (when (and (file-exists-p recache-indicator-file) (not noninteractive))
        (my-recache-all)
        ;;(delete-file recache-indicator-file) ;; don't delete, since some computers may use this for every startup
     )
   )
)

(my-flash (format-message "Not found here:\n%s" my-binary-not-found-list))
(my-flash (format-message "Emacs boot finished\n(took %.2fs)" my-config-el-loading-time))

(message "»»» Binaries not found in checks above: %s" my-binary-not-found-list)
;;(my-log-hostspecific (format "Binaries not found at startup checks: %s" my-binary-not-found-list))
(message "→★ finished loading config.org in %.2fs" my-config-el-loading-time)

Current key mappings (sorted)

Here are some blocks that try to extract keyboard bindings from the configuration file here.

Mappings not using my-map (non-sorted output)

keyfunction
[M-l]downcase-word
[M-u]upcase-word
[M-c]capitalize-word
[remap fill-paragraph]
emacs-lisp-mode C-c emacrostep-expand
M-hhs-cycle
M-Hhs-cycle-all
M-hhs-cycle
M-Hhs-cycle-all
python-mode C-c ielpygen-implement
dired-mode ~,~dired
\C-clorg-store-link
\C-caorg-agenda
C-c %org-mark-ring-push
C-c <left>org-mark-ring-goto
C-c <down>org-mark-ring-push
global \C-ccorg-capture
\C-cmmy-memacs-org-agenda
org-mode C-c )reftex-citation
org-mode C-c (org-mode-reftex-search
[f8]minimap-mode
C-s-SPCmode-line-in-header
[f12]my-toggle-naked-emacs
[f4]char-menu
[f2]goto-last-change
[f3]goto-last-change-reverse
C-c hhydra-apropos/body
C-x r hhydra-rectangle/body
[f5]hydra-spelling/body
\C-smy-search-method-according-to-numlines
global [tool-bar pdf-button]
[f1]my-toggle-beginner-setup
[(shift f1)]my-toggle-dark-bright-theme
M-i (lambda () (interactive) (my-codenav-prev-definition
M-k (lambda () (interactive) (my-codenav-next-definition
[home]beginning-of-buffer
[end]end-of-buffer
[C-left]backward-word
[C-right]forward-word
C-pscroll-down-command
C-nscroll-up-command
C-f(lambda () (interactive) (forward-line 5
M-/hippie-expand
M-qmy-fill-or-unfill
M-xcounsel-M-x) ;; id:2017-03-02-cool-command-completion
[M-l]~downcase-word) ~
[M-u]~upcase-word) ~
[M-c]~capitalize-word) ~
[remap fill-paragraph]
global [(f5)]~flyspell-mode) ~
global [(shift f5)]~my-toggle-ispell-language) ~
global [(f6)]~flyspell-goto-next-error) ~
global [(f7)]~flyspell-correct-word-before-point) ~
org-mode RET
\C-cl~org-store-link) ~
\C-ca~org-agenda) ~
C-c %~org-mark-ring-push) ~
C-c <left>~org-mark-ring-goto) ~
C-c <down>~org-mark-ring-push) ~
global \C-cc~org-capture) ~
\C-cm~my-memacs-org-agenda) ~
org-mode C-c )~reftex-citation) ~
org-mode C-c (~org-mode-reftex-search)) ~
[f8]~minimap-mode) ~
C-s-SPC~mode-line-in-header) ~
[f12]~my-toggle-naked-emacs) ~
M-x~counsel-M-x) ;; id:2017-03-02-cool-command-completion ~
[f4]~char-menu) ~
[f2]~goto-last-change) ~
[f3]~goto-last-change-reverse) ~
[f1]~neotree-toggle) ~
\C-s~my-search-method-according-to-numlines) ~
global [tool-bar pdf-button]
[f1]~my-toggle-beginner-setup) ~
[(shift f1)]~my-toggle-dark-bright-theme) ~
[home]~beginning-of-buffer) ~
[end]~end-of-buffer) ~
[C-left]~backward-word) ~
[C-right]~forward-word) ~
C-p~scroll-down-command) ~
C-n~scroll-up-command) ~
C-f~(lambda () (interactive) (forward-line 5))) ~
M-/~hippie-expand) ~

Mappings not using my-map (sorted output)

keyfunction
\C-caorg-agenda
\C-ca~org-agenda) ~
C-c <down>org-mark-ring-push
C-c <down>~org-mark-ring-push) ~
C-c hhydra-apropos/body
C-c <left>org-mark-ring-goto
C-c <left>~org-mark-ring-goto) ~
\C-clorg-store-link
\C-cl~org-store-link) ~
\C-cmmy-memacs-org-agenda
\C-cm~my-memacs-org-agenda) ~
C-c %org-mark-ring-push
C-c %~org-mark-ring-push) ~
C-f(lambda () (interactive) (forward-line 5
C-f~(lambda () (interactive) (forward-line 5))) ~
[C-left]backward-word
[C-left]~backward-word) ~
C-nscroll-up-command
C-n~scroll-up-command) ~
C-pscroll-down-command
C-p~scroll-down-command) ~
[C-right]forward-word
[C-right]~forward-word) ~
\C-smy-search-method-according-to-numlines
\C-s~my-search-method-according-to-numlines) ~
C-s-SPCmode-line-in-header
C-s-SPC~mode-line-in-header) ~
C-x C-bibuffer
C-x r hhydra-rectangle/body
C-zmy-dired-recent-dirs
dired-mode <backspace>diredp-up-directory-reuse-dir-buffer
dired-mode C-c C-omy-dired-open-in-external-app
dired-mode C-sdired-isearch-filenames
dired-mode ~,~dired
dired-mode [f1]hydra-dired/body
dired-mode M-amy-dired-appendfilename
dired-mode M-cdired-ranger-copy) ;; overwrites: diredp-capitalize-this-file
dired-mode M-mdired-ranger-move) ;; overwrites: back-to-indentation
dired-mode M-tmy-dired-filetags
dired-mode M-vdired-ranger-paste) ;; overwrites: scroll-down-command
emacs-lisp-mode C-c emacrostep-expand
[end]end-of-buffer
[end]~end-of-buffer) ~
[f12]my-toggle-naked-emacs
[f12]~my-toggle-naked-emacs) ~
[f1]my-toggle-beginner-setup
[f1]~my-toggle-beginner-setup) ~
[f2]goto-last-change
[f2]~goto-last-change) ~
[f3]goto-last-change-reverse
[f3]~goto-last-change-reverse) ~
[f4]char-menu
[f4]~char-menu) ~
[f5]hydra-spelling/body
[f8]minimap-mode
[f8]~minimap-mode) ~
[f1]~neotree-toggle) ~
global \C-ccorg-capture
global \C-cc~org-capture) ~
global [(f5)]~flyspell-mode) ~
global [(f6)]~flyspell-goto-next-error) ~
global [(f7)]~flyspell-correct-word-before-point) ~
global [(shift f5)]~my-toggle-ispell-language) ~
global [tool-bar pdf-button]
global [tool-bar pdf-button]
[home]beginning-of-buffer
[home]~beginning-of-buffer) ~
image-dired-thumbnail-mode \C-nimage-diredx-next-line
image-dired-thumbnail-mode \C-pimage-diredx-previous-line
image-dired-thumbnail-mode grevert-buffer);; revert all thumbnails if `image-diredx-async-mode' is on
image-dired-thumbnail-mode ximage-diredx-flagged-delete);; Delete confirmation prompt with thumbnails
[M-c]capitalize-word
[M-c]~capitalize-word) ~
M-hhs-cycle
M-Hhs-cycle-all
M-/hippie-expand
M-/~hippie-expand) ~
M-i (lambda () (interactive) (my-codenav-prev-definition
M-k (lambda () (interactive) (my-codenav-next-definition
[M-l]downcase-word
[M-l]~downcase-word) ~
M-qmy-fill-or-unfill
[M-u]upcase-word
[M-u]~upcase-word) ~
M-xcounsel-M-x) ;; id:2017-03-02-cool-command-completion
M-x~counsel-M-x) ;; id:2017-03-02-cool-command-completion ~
org-mode C-c (org-mode-reftex-search
org-mode C-c (~org-mode-reftex-search)) ~
org-mode C-c )reftex-citation
org-mode C-c )~reftex-citation) ~
org-mode RET
python-mode C-c ielpygen-implement
python-mode [f1]hydra-python/body
[remap fill-paragraph]
[remap fill-paragraph]
[(shift f1)]my-toggle-dark-bright-theme
[(shift f1)]~my-toggle-dark-bright-theme) ~

Mapping from my-map outside of use-package

  • [ ] fix script
\texttt{C-c ,}functioncomment

config.el: (define-key my-map P | pylookup-lookup | | main_before_moving_to_config.org.el: (define-key my-map P | pylookup-lookup | | main_sting_before_configorg.el: (define-key my-map P | pylookup-lookup | | main_sting_before_configorg_ORIG.el: (define-key my-map P | pylookup-lookup |

Mapping from my-map within use-package

\texttt{C-c ,}functioncomment
0bm-next
8bm-toggle
9bm-previous
RETeno-word-goto
Smy-synonym-current-word
SPCyankpad-insert
csmeargle
hhighlight-symbol
sspray-mode

Mapping of F-keys

id:2017-05-22-f-key-mapping

New mapping for F-keys: id:2017-05-26-new-F-key-bindings

KeyNew binding
<f1>my-toggle-beginner-setup
Shift-<f1>my-toggle-dark-bright-theme
<f2>goto-last-change
<f3>goto-last-change-reverse
<f4>char-menu
<f5>flyspell hydra
<f6>flyspell-goto-next-error
<f7>flyspell-correct-word-before-point
<f8>
<f9>python hydra
<f10>menu-bar-open
<f11>toggle-frame-fullscreen
<f12>my-toggle-naked-emacs

Local Variables

;; Local Variables: ;; eval: (make-local-variable ‘org-insert-heading-hook) ;; eval: (remove-hook ‘org-insert-heading-hook ‘org-expiry-insert-created t) ;; eval: (make-local-variable ‘org-after-todo-state-change-hook) ;; eval: (remove-hook ‘org-after-todo-state-change-hook ‘org-expiry-insert-created t) ;; eval: (make-local-variable ‘org-after-tags-change-hook) ;; eval: (remove-hook ‘org-after-tags-change-hook ‘org-expiry-insert-created t) ;; End: