Everything with Emacs

Table of Contents

I do pretty much everything with Emacs…

1 Emacs configuration

1.1 .emacs org file

Make .emacs file an org file for readability! First, in the ~/.emacs file:

(setq my-user-emacs-directory "~/.emacs.d/")

(defvar my-init-el-start-time (current-time) "Time when init.el was started")

;; from: http://stackoverflow.com/questions/251908/how-can-i-insert-current-date-and-time-into-a-file-using-emacs
(defvar current-date-time-format "%a %b %d %Y-%m-%dT%H:%M:%S "
  "Format of date to insert with `insert-current-date-time' func
See help of `format-time-string' for possible replacements")

;; from: http://stackoverflow.com/questions/251908/how-can-i-insert-current-date-and-time-into-a-file-using-emacs
(defvar current-time-format "%a %H:%M:%S"
  "Format of date to insert with `insert-current-time' func.
Note the weekly scope of the command's precision.")

(require 'org)

(defun my-tangle-config-org ()
  "This function will write all source blocks from =config.org= into =config.el= that are ...
- not marked as =tangle: no=
- doesn't have the TODO state =DISABLED=
- have a source-code of =emacs-lisp="
  (require 'org)
  (let* ((body-list ())
         (output-file (concat my-user-emacs-directory "config.el"))
         (org-babel-default-header-args (org-babel-merge-params org-babel-default-header-args
                                                                (list (cons :tangle output-file)))))
    (message "—————• Re-generating %s …" output-file)
    (save-restriction
      (save-excursion
        (org-babel-map-src-blocks (concat my-user-emacs-directory "config.org")
      (let* (
         (org_block_info (org-babel-get-src-block-info 'light))
         ;;(block_name (nth 4 org_block_info))
         (tfile (cdr (assq :tangle (nth 2 org_block_info))))
         (match_for_TODO_keyword)
         )
        (save-excursion
          (catch 'exit
        ;;(when (string= "" block_name)
        ;;  (message "Going to write block name: " block_name)
        ;;  (add-to-list 'body-list (concat "message(\"" block_name "\")"));; adding a debug statement for named blocks
        ;;  )
        (org-back-to-heading t)
        (when (looking-at org-outline-regexp)
          (goto-char (1- (match-end 0))))
        (when (looking-at (concat " +" org-todo-regexp "\\( +\\|[ \t]*$\\)"))
          (setq match_for_TODO_keyword (match-string 1)))))
        (unless (or (string= "no" tfile)
            (string= "DISABLED" match_for_TODO_keyword)
            (not (string= "emacs-lisp" lang)))
          (add-to-list 'body-list (concat "\n\n;; #####################################################################################\n"
                          "(message \"config • " (org-get-heading) " …\")\n\n")
               )
          (add-to-list 'body-list body)
          ))))
      (with-temp-file output-file
        (insert ";; ============================================================\n")
        (insert ";; Don't edit this file, edit config.org' instead ...\n")
        (insert ";; Auto-generated at " (format-time-string current-date-time-format (current-time)) " on host " system-name "\n")
        (insert ";; ============================================================\n\n")
        (insert (apply 'concat (reverse body-list))))
      (message "—————• Wrote %s" output-file))))


;; following lines are executed only when my-tangle-config-org-hook-func()
;; was not invoked when saving config.org which is the normal case:
(let ((orgfile (concat my-user-emacs-directory "config.org"))
      (elfile (concat my-user-emacs-directory "config.el"))
      (gc-cons-threshold most-positive-fixnum))
  (when (or (not (file-exists-p elfile))
            (file-newer-than-file-p orgfile elfile))
    (my-tangle-config-org)
    ;;(save-buffers-kill-emacs);; TEST: kill Emacs when config has been re-generated due to many issues when loading newly generated config.el
    )
  (load-file elfile))

;; when config.org is saved, re-generate config.el:
(defun my-tangle-config-org-hook-func ()
  (when (string= "config.org" (buffer-name))
    (let ((orgfile (concat my-user-emacs-directory "config.org"))
          (elfile (concat my-user-emacs-directory "config.el")))
      (my-tangle-config-org))))
(add-hook 'after-save-hook 'my-tangle-config-org-hook-func)

(message "→★ loading init.el in %.2fs" (float-time (time-subtract (current-time) my-init-el-start-time)))

Then in ~/.emacs.d/config.org, list eLISP code blocks using

#+BEGIN_SRC lisp
...
#+END_SRC 

2 Packages

2.1 Useful packages

Here's a list of nice features and packages that can be useful for a research environment.

Feature Packages
TeX auctex, reftex
Emails mu4e, org-mu4e
PDF view/edit pdf-tools
bibtex helm-bibtex
Python elpy
Web development php-mode, web-mode, org, org-html-themes
Text editing auto-complete, google-translate, define-word, fuzzy, guess-language
GTD, agenda org, org-bullets, org-super-agenda
Git magit
RSS elfeed, elfeed-org
Calendars org, calfw, calfw-ical, calfw-org
Calculator literate-calc-mode

2.2 Install packages automatically

Useful script for when one installs a new computer. Run script with: run with emacs -q -l scriptname

(require 'package)

; list the packages you want
(setq package-list '(use-package guide-key rainbow-mode spaceline auctex reftex pdf-tools helm-bibtex elfeed calfw calfw-ical calfw-org neotree elpy php-mode undo-tree smex auto-complete google-translate org-bullets org-super-agenda magit dash dired-subtree dired-rainbow ranger unfill define-word fuzzy hydra guess-language web-mode symon))

; list the repositories containing them
(setq package-archives '(("melpa-stable" . "https://stable.melpa.org/packages/")
                         ("gnu" . "http://elpa.gnu.org/packages/")
             ("melpa" . "https://melpa.org/packages/")
             ))

; activate all the packages (in particular autoloads)
(package-initialize)

; fetch the list of packages available 
(unless package-archive-contents
  (package-refresh-contents))

; install the missing packages
(dolist (package package-list)
  (unless (package-installed-p package)
    (package-install package)))

(kill-emacs)

3 .emacs

3.1 Shortcuts

3.1.1 Main

  • Displays buffer with some help for shortcuts
;; General help
(defun help-exit ()
  (interactive) ;;required for local-set-key
  (quit-window t))

;; Help buffer
(defun show-help ()
  (interactive)
  (let ((buffer (get-buffer-create (format "*help.in"))))
    (switch-to-buffer buffer)
    (setq buffer-read-only nil)
    (erase-buffer)
    (insert "
----------------------
HELP (press q to exit)
----------------------

BUFFERS
-------
<C-escape>:     kill buffer (S: kill buffer and window)
<C-backspace>:  kill all invisible buffers
<C-x C-b>:      list buffers

WORKFLOW
--------
<C-c d>:    note taking (deft)
<C-c c>:    capture menu
<C-c x>:    capture bibtexendum
<C-x C-f>:  create/find file
<C-c i>:    load template
<C-x C-T>:  terminal here
<C-x C-t>:  terminal (dedicated)
<C-x g>:    magit-status
<C-x B>:    helm-bibtex (r: resume, C-g: exit)
<C-x p>:    helm-bibtex (my publications)
M-x lcalc:  literate calculation (also, quick-calc, calc & calculator)

HYDRAS
------
<C-c z>:    zoom/font actions
<C-c m>:    move actions (move, goto line...)
<C-c t>:    toggle actions (browser, whitespace, dicts...)
<C-c f>:    file action (file size, filename...)

EDITING
-------
<C-c p>:    parentheses actions
<C-c r>:    region actions (count, unfill, spell...)
<C-c w>:    word actions (spell, case, translate, lookup...)
<?> in PDF: pdf actions (annotate, goto...)
<f2>:       spell correct (C-f2: next)
<C-.>:      auto-correct
<C-space>:  start selection, continue with arrows (C-g to cancel)

MISC
----
<f1>:     general help (C: specific mode help)
<C-c e>:  reload .emacs
<C-x u>:  undo tree vizualizer
<C-c b>:  show bookmarks
<C-c T>:  world clock

SEARCH/REPLACE
--------------
<C-c s>:     search actions (search, occur...)
<C-s>:       iSearch (r: backwards)
<M-%>:       replace
M-x locate:  locate (use * first if using wildcards)

KILL-RING
---------
<C-y>:       paste (yank) repeat for kill-ring (C-S-y: unfill and add double-quotes as well)
<M-y>:       show kill-ring

M-x commands
------------
M-x quick-calc:  simple calculation
M-x calculator:  calculator (use ' for algebraic mode, u-v for units, =/u-b for value, u-c for conversion)

LAYOUTS
-------
<C-c l>:  layouts (incl. org/pdf)
<f8>:     winner undo (C: redo)
<f2>:     ranger

EIN
---
py & C-f7:    insert block snippet
M-x ein:run : launch ein
<C-c C-o>:    open dir
<C-x C-s>:    save
<C-x C-w>:    rename
<C-c C-a>:    insert cell above
<C-c C-b>:    insert cell below
<C-c C-k>:    kill cell
<C-c C-c>:    execute
<M-RET>  :    execute and next cell
<CM-arrows>:  move

MULTIPLE-CURSORS
----------------
<C-S-c C-S-c>: cursors on selected region
<C-S-mouse-1>: place cursors with mouse

ZATHURA
-------
/,?:   search forward/backward
n,N:   search last keyword forward/backward
<TAB>: index
r:     rotate
gg/GG: goto first/last page

")

    (setq buffer-read-only t)
    (local-set-key "q" 'help-exit)
    )
  )

(global-set-key (read-kbd-macro "<f1>") 'show-help)

3.1.2 Layout shortcuts

;; hydra to choose layout
(global-set-key (kbd "\C-cl")
                (defhydra hydra-layouts
                  (:exit t)
                  "layouts"
                  ("w" org-layout-work "all indiv.")
                  ("m" mu4e-elfeed "mu4e+elfeed")
                  ("W" show-workflow "workflow")
                  ("b" show-bookmarks "bookmarks")
                  ("d" dired-layout "dired")
                  ("D" dired-layout2 "dired bis")
                  ("f" elfeed-load "elfeed")
                  ("p" orgpdf-layout "org/pdf" :color blue)
                  ("y" elpy-layout "elpy")
                  ))

3.2 Emacs

3.2.1 Packages

  • Upgrades: list packages and then upgrade with U-x
  • M-x, type in list-packages to see all available, installed as well as built-in packages. To install a package, simply hit return when the cursor is on that package and select Install
;;; Emacs is not a package manager, and here we load its package manager!
(require 'package)

(add-to-list 'package-archives
             '("melpa-stable" . "https://stable.melpa.org/packages/") t)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)
;(add-to-list 'package-archives
;             '("marmalade" . "https://marmalade-repo.org/packages/") t)

;; automatically update the list of packages
(when (not package-archive-contents)
  (package-refresh-contents))

;;gpg signatures on list-packages
(setq package-check-signature nil)

3.2.2 Startup

;; Save initial launch directory
(setq launch-directory default-directory)

;; Turn on visible bell
(setq visible-bell t)
(setq ring-bell-function 'ignore)

;; No startup screen
(setq inhibit-startup-screen t)
(setq inhibit-startup-message t)
(setq inhibit-startup-echo-area-message t)
(setq initial-scratch-message nil)

(defun display-startup-echo-area-message ()
  (message ""))

3.2.3 Buffers/files

;; Removes *scratch* from buffer after the mode has been set
                                        ;(defun remove-scratch-buffer ()
                                        ;  (if (get-buffer "*scratch*")
                                        ;      (kill-buffer "*scratch*")))
                                        ;(add-hook 'after-change-major-mode-hook 'remove-scratch-buffer)

;; Removes *messages* from the buffer.
;; (setq-default message-log-max nil)
;; (kill-buffer "*Messages*")

;; Removes *Completions* from buffer after you've opened a file.
(add-hook 'minibuffer-exit-hook
          '(lambda ()
             (let ((buffer "*Completions*"))
               (and (get-buffer buffer)
                    (kill-buffer buffer)))))

;; Don't show *Buffer list* when opening multiple files at the same time.
(setq inhibit-startup-buffer-menu t)

;; replace buffer list
(global-set-key (kbd "C-x C-b") 'ibuffer)
;;or (global-set-key [remap list-buffers] 'ibuffer)

;; text mode is default for new buffers
(setq-default major-mode 'text-mode)

;; Transparently open compressed files
(auto-compression-mode t)

3.2.4 Always start at the end of buffer

;; Bottom-line function:
(defun bottom-line ()
  "Opens a file with the pointer at the bottom line."
  (interactive)
  (end-of-buffer))

;; Hook for every file opened, execute the bottom-line function:
(add-hook 'find-file-hook 'bottom-line)

3.2.5 init file

;; Reload .emacs init file
(defun reload-init-file ()
  (interactive)
  (load-file user-init-file))
(global-set-key (kbd "C-c e") 'reload-init-file)

3.2.6 Garbage, history

;;garbage collection
(add-hook 'focus-out-hook #'garbage-collect)

;; save history for minibuffer
(setq savehist-additional-variables    ;; also save...
      '(search-ring regexp-search-ring)    ;; ... my search entries
      ;;savehist-file "~/.emacs.d/savehist"
      ) ;; keep my home clean
(savehist-mode t)                      ;; do customization before activate

3.2.7 Backups

;; saved files
;(setq backup-directory-alist `((".*" . ,"~/.emacs_saves")))
;(setq auto-save-file-name-transforms `((".*" ,"~/emacs_saves" t)))
;(setq backup-by-copying t)
;(setq delete-old-versions t
;      kept-new-versions 6
;      kept-old-versions 2
;      version-control t)

;; saving after each save!
;; by default, Emacs never backs up versioned files. Since we’re going to be backing up intermediate copies, we want to backup versioned files too, since we don’t commit on every save:
(setq vc-make-backup-files t)

(setq version-control t ;; Use version numbers for backups.
        kept-new-versions 10 ;; Number of newest versions to keep.
        kept-old-versions 0 ;; Number of oldest versions to keep.
        delete-old-versions t ;; Don't ask to delete excess backup versions.
        backup-by-copying t) ;; Copy all files, don't rename them.
;; Default and per-save backups go here:
(setq backup-directory-alist '(("" . "~/.emacs_saves/backup/per-save")))

(defun force-backup-of-buffer ()
    ;; Make a special "per session" backup at the first save of each
    ;; emacs session.
    (when (not buffer-backed-up)
      ;; Override the default parameters for per-session backups.
      (let ((backup-directory-alist '(("" . "~/.emacs_saves/backup/per-session")))
            (kept-new-versions 3))
        (backup-buffer)))
    ;; Make a "per save" backup on each save.  The first save results in
    ;; both a per-session and a per-save backup, to keep the numbering
    ;; of per-save backups consistent.
    (let ((buffer-backed-up nil))
      (backup-buffer)))

;; backup before save
(add-hook 'before-save-hook  'force-backup-of-buffer)

;; If you want to avoid 'backup-by-copying', you can instead use
;;
;; (setq backup-by-copying-when-linked t)
;;
;; but that makes the second, "per save" backup below not run, since
;; buffers with no backing file on disk are not backed up, and
;; renaming removes the backing file.  The "per session" backup will
;; happen in any case, you'll just have less consistent numbering of
;; per-save backups (i.e. only the second and subsequent save will
;; result in per-save backups).

;; If you want to avoid backing up some files, e.g. large files,
;; then try setting 'backup-enable-predicate'.  You'll want to
;; extend 'normal-backup-enable-predicate', which already avoids
;; things like backing up files in '/tmp'.


;; recent files
;;(recentf-mode 1)
;;(setq recentf-max-menu-items 50)
;;(global-set-key "\C-x\ \C-r" 'recentf-open-files)
;;(run-at-time nil (* 5 60) 'recentf-save-list) ;;update every 5 mins (otherwise when emacs exits)

;; override the default "-c" (execute the following command). The addition of "-i" forces the bash shell into interactive mode, which leads to the sourcing of ~/.bashrc
;;(setq shell-command-switch "-ic")

3.2.8 Line number

(require 'hlinum)
(hlinum-activate)

3.2.9 Dialogs

;; Change "yes or no" to "y or n"
(fset 'yes-or-no-p 'y-or-n-p)

;; Don't ask for confirmation for "dangerous" commands
(put 'erase-buffer 'disabled nil)
(put 'narrow-to-page 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'scroll-left 'disabled nil)
(put 'scroll-right 'disabled nil)
(put 'set-goal-column 'disabled nil)

;; large file warning
(setq large-file-warning-threshold (* 15 1024 1024))

3.2.10 Toggles

  • Sets some hydras (series of shortcuts)
;; hydra toggle
(global-set-key (kbd "\C-ct")
                (defhydra hydra-toggle 
                  (:exit t)
                  "toggle"
                  ("df" (lambda () (interactive) (ispell-change-dictionary "fr_FR") (flyspell-buffer)) "french")
                  ("de" (lambda () (interactive) (ispell-change-dictionary "en_US") (flyspell-buffer)) "english")
                  ("g" guess-language-mode "guess-language") 
                                        ;("m" (lambda () (interactive) (ispell-change-dictionary "en_US,fr_FR") (ispell-set-spellchecker-params) (ispell-hunspell-add-multi-dic "en_US,fr_FR") (flyspell-buffer)) "mixed")
                  ("(" rainbow-delimiters-mode "Rainbow()") 
                  ("w" whitespace-mode "whitespace")
                  ;;("d" switch-dictionary "dictionary")
                  ("b" toggle-browser "browser")
                  ("s" symon-mode "symon")
                  ("W" global-visual-line-mode "wordwrap")
                  ("S" scroll-all-mode "scroll-all")
                  ("n" number-separator-mode "number-separator")
                  ("q" nil "cancel" :color blue)))

3.2.11 Refresh/revert

;; auto refresh (will still ask for confirmation if conflict)
(global-auto-revert-mode 1)

;; enable for image mode too (dired done below)
(add-hook 'image-mode-hook 'auto-revert-mode)

3.2.12 Screen/scroll/lines

;; nice to be able to see when a file actually ends. This will put empty line markers into the left hand side. 
(setq-default indicate-empty-lines t)
(when (not indicate-empty-lines)
  (toggle-indicate-empty-lines))

;; Scrolling done right
(setq scroll-error-top-bottom t)

;; Number of lines of continuity when scrolling by screenfulls
(setq next-screen-context-lines 0)

(setq-default 
 scroll-conservatively most-positive-fixnum       ; Always scroll by one line
 )

;;Page scrolling should keep the point at the same visual position, rather than force it to the top or bottom of the viewport. This eliminates the friction of guessing where the point has warped to.
(setq scroll-preserve-screen-position t)

3.2.13 Keys/cursor/mouse

;; Show keystrokes in progress
(setq echo-keystrokes 0.1)

;; make cursor the width of the character it is under
;; i.e. full width of a TAB
(setq x-stretch-cursor t)

;; Bar cursor
;;(setq-default cursor-type '(bar . 2))
;; Don't blink the cursor
(blink-cursor-mode 0)

;;(setq-default cursor-type '(hollow . 1)) ;; 'hollow
(setq default-cursor-type 'box)

(setq default-frame-alist
      '((cursor-color . "yellow")))

;; ;; blink b&w
;; (defvar blink-cursor-colors (list  "#FFF" "#000" )
;;   "On each blink the cursor will cycle to the next color in this list.")

;; (setq blink-cursor-count 0)
;; (defun blink-cursor-timer-function ()
;;   "Zarza wrote this cyberpunk variant of timer `blink-cursor-timer'. 
;; Warning: overwrites original version in `frame.el'.

;; This one changes the cursor color on each blink. Define colors in `blink-cursor-colors'."
;;   (when (not (internal-show-cursor-p))
;;     (when (>= blink-cursor-count (length blink-cursor-colors))
;;       (setq blink-cursor-count 0))
;;     (set-cursor-color (nth blink-cursor-count blink-cursor-colors))
;;     (setq blink-cursor-count (+ 1 blink-cursor-count))
;;     )
;;   (internal-show-cursor nil (not (internal-show-cursor-p)))
;;   )

;; mouse support in terminal mode
(when (eq window-system nil)
  (xterm-mouse-mode t))

;;(mouse-avoidance-mode 'cat-and-mouse)

;;for mouse wheel with scroll-all-mode (across several buffers, e.g., for diff)
(defun mwheel-scroll-all-function-all (func &optional arg)
  (if (and scroll-all-mode arg)
      (save-selected-window
        (walk-windows
         (lambda (win)
           (select-window win)
           (condition-case nil
               (funcall func arg)
             (error nil)))))
    (funcall func arg)))
(defun mwheel-scroll-all-scroll-up-all (&optional arg)
  (mwheel-scroll-all-function-all 'scroll-up arg))
(defun mwheel-scroll-all-scroll-down-all (&optional arg)
  (mwheel-scroll-all-function-all 'scroll-down arg))
(setq mwheel-scroll-up-function 'mwheel-scroll-all-scroll-up-all)
(setq mwheel-scroll-down-function 'mwheel-scroll-all-scroll-down-all)

;; scroll one line at a time (less "jumpy" than defaults)
;; useful for scrolling with inline images
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) ;; one line at a time
(setq mouse-wheel-progressive-speed t) ;; do accelerate scrolling (nil for not)
(setq mouse-wheel-follow-mouse 't) ;; scroll window under mouse
(setq scroll-step 1) ;; keyboard scroll one line at a time

3.2.14 Server

;; emacs25 --daemon=foo 
;; -c: GUI
;; emacsclient -c -s ~/.emacs.d/server/foo minimanifesto.org 


;; starteserver(){
;; 	if [[ $# -eq 0 ]] ; then
;; 	d="main"
;; else
;; d=$1
;;     fi
;;     echo $d
;; 	emacs25 --daemon=$d &
;; }
;; killeserver(){
;; 	if [[ $# -eq 0 ]] ; then
;; 	d="main"
;; else
;; d=$1
;;     fi
;; 	emacsclient -e -s ~/.emacs.d/server/$d '(save-buffers-kill-emacs)'
;; }
;; starteclient(){
;; aflag=
;; dflag=
;; while getopts ":had:" name
;; do
;;     case ${name} in
;;     a    aflag=1;;
;;     d    dflag=1
;;           dval="$OPTARG";;
;;     h    printf "Usage: %s: [-a] [-d value] args\n" $0
;;           return ;;
;;     * printf "Usage: %s: [-a] [-d value] args\n" $0 ;;
;;     esac
;; done
;; if [ ! -z "$aflag" ]; then
;;     printf "Option -a specified\n"
;; fi
;; if [ ! -z "$dflag" ]; then
;;     #printf 'Option -d "%s" specified\n' "$dval"
;;     d=$dval
;; else
;; d="main"
;; fi
;; #echo $d
;; shift $(($OPTIND - 1))
;; #printf "Remaining arguments are: %s\n" "$*"
;; emacsclient -c -s ~/.emacs.d/server/$d "$*"
;; }
;; alias es=starteserver
;; alias ec=starteclient
;; alias ke=killeserver

;;avoid the message server-start in other emacs sesssion
(require 'server)
(setq server-name (format-time-string "%Y-%m-%dT%H:%M:%S")) ;;provide unique server name
(setq server-socket-dir "~/.emacs.d/server")
(unless (server-running-p) (server-start))

3.2.15 Frames, Windows

  1. Configuration
    (setq-default
     window-combination-resize t                      ; Resize windows proportionally
     )
    
    ;; winner undo/redo to restore configuration
    (when (fboundp 'winner-mode)
      (winner-mode 1))
    (global-set-key [f8] 'winner-undo)
    (global-set-key [C-f8] 'winner-redo)
    
    
  2. Kill
    ;; kill buffer
    (global-set-key (kbd "<C-escape>") 'kill-this-buffer)
    
    ;; kill buffer and window
    (global-set-key (kbd "<S-escape>") 'kill-buffer-and-window)
    
    ;; kill invisible buffers (with no windows)
    (defun kill-invisible-buffers ()
      "Kill all buffers not currently shown in a window somewhere."
      (interactive)
      (dolist (buf  (buffer-list))
        (unless (get-buffer-window buf 'visible) (kill-buffer buf))))
    (global-set-key (read-kbd-macro "<S-backspace>") 'kill-invisible-buffers)
    
    
  3. Split/switch
    ;; Split horizontally for temporary buffers
    (defun split-horizontally-for-temp-buffers ()
      "Split the window horizontally for temp buffers."
      (when (and (one-window-p t)
                 (not (active-minibuffer-window)))
        (split-window-horizontally)))    
    (add-hook 'temp-buffer-setup-hook 'split-horizontally-for-temp-buffers)
    ;; split thresholds
    (setq split-height-threshold nil)
    (setq split-width-threshold 0)
    
    ;; splitting
    ;; Use (setq split-width-threshold nil) for vertical split.
    ;; Use (setq split-width-threshold 1 ) for horizontal split.
    
    ;; switch windows with S- arrows
    ;(windmove-default-keybindings)
    
    

3.2.16 Bars

  1. DISABLED modeline
    (set-face-attribute 'mode-line nil
                        :foreground "white"
                        :background "black"
                        :box nil)
    (set-face-attribute 'mode-line-buffer-id nil
                        :foreground "white"
                        :background "#200000"
                        :box nil)
    
    ;; number of characters in bottom bar
    ;; (add-to-list 'global-mode-string '("Nchars=%i %, "))
    
    
    ;; add line numbers in bar
    (add-hook 'prog-mode-hook 'linum-mode) ;only for programming ;(global-linum-mode t) freezes docview
    (add-hook 'prog-mode-hook 'display-line-numbers-mode) ;only for programming ;(global-linum-mode t) freezes docview
    
    ;; The following adds a space after the line-number
    (setq linum-format "%d ")
    
    (line-number-mode 1)    ; makes the line number show up
    (column-number-mode 1)  ; makes the column number show up
    (transient-mark-mode 1) ; makes the region visible
    
    ;; Display time in bar
    (setq display-time-day-and-date t)
    ;;(setq display-time--format "[%Z] %a %d %b %R")
    (display-time)
    
    
  2. DISABLED spaceline
    (use-package spaceline-config :ensure spaceline
      :config
      (spaceline-helm-mode 1)
      (spaceline-install
       'main
       '((buffer-modified)
         ((remote-host buffer-id) :face highlight-face)
         (process :when active))
       '((selection-info :face region :when mark-active)
         ((flycheck-error flycheck-warning flycheck-info) :when active)
         (which-function)
         (version-control :when active)
         (line-column)
         (global :when active)
         (major-mode))))
    
    (setq-default
     spaceline-flycheck-bullet "❖ %s"
     spaceline-separator-dir-left '(right . right)
     spaceline-separator-dir-right '(left . left))
    
    
  3. doom-modeline
    (require 'doom-modeline)
    (doom-modeline-mode 1)
    
    (setq column-number-mode t)
    
    (use-package doom-modeline
      :ensure t
      :config
      ;; How tall the mode-line should be. It's only respected in GUI.
      ;; If the actual char height is larger, it respects the actual height.
      (setq doom-modeline-height 20)
    
      ;; How wide the mode-line bar should be. It's only respected in GUI.
      (setq doom-modeline-bar-width 3)
    
      ;;(setq doom-modeline-percent-position t)
    
      ;; Determines the style used by `doom-modeline-buffer-file-name'.
      ;;
      ;; Given ~/Projects/FOSS/emacs/lisp/comint.el
      ;;   truncate-upto-project => ~/P/F/emacs/lisp/comint.el
      ;;   truncate-from-project => ~/Projects/FOSS/emacs/l/comint.el
      ;;   truncate-with-project => emacs/l/comint.el
      ;;   truncate-except-project => ~/P/F/emacs/l/comint.el
      ;;   truncate-upto-root => ~/P/F/e/lisp/comint.el
      ;;   truncate-all => ~/P/F/e/l/comint.el
      ;;   relative-from-project => emacs/lisp/comint.el
      ;;   relative-to-project => lisp/comint.el
      ;;   file-name => comint.el
      ;;   buffer-name => comint.el<2> (uniquify buffer name)
      ;;
      ;; If you are expereicing the laggy issue, especially while editing remote files
      ;; with tramp, please try `file-name' style.
      ;; Please refer to https://github.com/bbatsov/projectile/issues/657.
      (setq doom-modeline-buffer-file-name-style 'truncate-upto-project)
    
      (setq doom-modeline-icon t)
    
      ;; Whether display icons in mode-line or not.
      (setq doom-modeline-icon (display-graphic-p))
    
      ;; Whether display the icon for major mode. It respects `doom-modeline-icon'.
      (setq doom-modeline-major-mode-icon t)
    
      ;; Whether display color icons for `major-mode'. It respects
      ;; `doom-modeline-icon' and `all-the-icons-color-icons'.
      (setq doom-modeline-major-mode-color-icon t)
    
      ;; Whether display icons for buffer states. It respects `doom-modeline-icon'.
      (setq doom-modeline-buffer-state-icon t)
    
      ;; Whether display buffer modification icon. It respects `doom-modeline-icon'
      ;; and `doom-modeline-buffer-state-icon'.
      (setq doom-modeline-buffer-modification-icon t)
    
      ;; Whether display minor modes in mode-line or not.
      (setq doom-modeline-minor-modes (featurep 'minions))
    
      ;; If non-nil, a word count will be added to the selection-info modeline segment.
      (setq doom-modeline-enable-word-count nil)
    
      ;; Whether display buffer encoding.
      (setq doom-modeline-buffer-encoding t)
    
      ;; Whether display indentation information.
      (setq doom-modeline-indent-info nil)
    
      ;; If non-nil, only display one number for checker information if applicable.
      (setq doom-modeline-checker-simple-format t)
    
      ;; The maximum displayed length of the branch name of version control.
      (setq doom-modeline-vcs-max-length 12)
    
      ;; Whether display perspective name or not. Non-nil to display in mode-line.
      (setq doom-modeline-persp-name t)
    
      ;; Whether display icon for persp name. Nil to display a # sign. It respects `doom-modeline-icon'
      (setq doom-modeline-persp-name-icon nil)
    
      ;; Whether display `lsp' state or not. Non-nil to display in mode-line.
      ;;(setq doom-modeline-lsp t)
    
      ;; Whether display GitHub notifications or not. Requires `ghub` package.
      (setq doom-modeline-github nil)
    
      ;; The interval of checking GitHub.
      (setq doom-modeline-github-interval (* 30 60))
    
      ;; Whether display mu4e notifications or not. Requires `mu4e-alert' package.
      (setq doom-modeline-mu4e t)
    
      ;; Whether display irc notifications or not. Requires `circe' package.
      ;;(setq doom-modeline-irc t)
    
      ;; Function to stylize the irc buffer names.
      ;;(setq doom-modeline-irc-stylize 'identity)
    
      ;; Whether display environment version or not
      (setq doom-modeline-env-version t)
      ;; Or for individual languages
      (setq doom-modeline-env-enable-python t)
      (setq doom-modeline-env-enable-ruby t)
      (setq doom-modeline-env-enable-perl t)
      (setq doom-modeline-env-enable-go t)
      (setq doom-modeline-env-enable-elixir t)
      (setq doom-modeline-env-enable-rust t)
    
      ;; Change the executables to use for the language version string
      (setq doom-modeline-env-python-executable "python") ; or `python-shell-interpreter'
      (setq doom-modeline-env-ruby-executable "ruby")
      (setq doom-modeline-env-perl-executable "perl")
      (setq doom-modeline-env-go-executable "go")
      (setq doom-modeline-env-elixir-executable "iex")
      (setq doom-modeline-env-rust-executable "rustc")
    
      ;; What to dispaly as the version while a new one is being loaded
      (setq doom-modeline-env-load-string "...")
    
      ;; Hooks that run before/after the modeline version string is updated
      (setq doom-modeline-before-update-env-hook nil)
      (setq doom-modeline-after-update-env-hook nil)
    
    
    
      :hook (after-init . doom-modeline-mode))
    
    
    ;; Display time in bar
    (setq display-time-day-and-date t)
    ;;(setq display-time--format "[%Z] %a %d %b %R")
    (display-time)
    
    ;;indicates size
    (size-indication-mode)
    
                                            ;(setcar mode-line-position
                                            ;        '(:eval (format "%3d%%" (/ (window-end) 0.01 (point-max)))))
    
    
    ;; Removes *scratch* from buffer after the mode has been set
    (defun remove-scratch-buffer ()
      (if (get-buffer "*scratch*")
          (kill-buffer "*scratch*")))
    (add-hook 'after-change-major-mode-hook 'remove-scratch-buffer)
    
    
  4. DISABLED powerline
    ;; bottom bar
                                            ;(require 'powerline)
    (powerline-default-theme)
                                            ;(powerline-center-theme)
                                            ;(powerline-center-evil-theme)
                                            ;(powerline-vim-theme)
                                            ;(powerline-nano-theme)
                                            ;(setq powerline-arrow-shape 'curve)
    (setq-default
     powerline-height 12
     powerline-default-separator 'wave
     )
    
    

3.2.17 Minibuffer

  1. icomplete

    #+BEGINSRC emacs-lisp

    (icomplete-mode 1)

    #+ENDSRC emacs-lisp

  2. Smex
    • Better M-x
    (use-package smex
      :config
      (setq smex-save-file (expand-file-name ".smex-items" user-emacs-directory))
      (smex-initialize)
      (global-set-key (kbd "M-x") 'smex)
      (global-set-key (kbd "M-X") 'smex-major-mode-commands)
      )
    
    

3.2.18 Appearance

  1. General
    ;; Show the name of the file being edited in the title bar          
    ;; (setq frame-title-format "%b - Emacs")
    ;; (setq frame-title-format '(buffer-file-name "%m %b (%f)" ("%f")))
    
    ;; highlight current line
    (use-package hl-line
      :ensure nil
      :config (set-face-background hl-line-face "black")
      :preface (defun me/hl-line-mode-off () (setq-local global-hl-line-mode nil))
      :hook (after-init . global-hl-line-mode))
    
    ;; include the name of the file I'm working on instead, or, in case of non-file buffers, the buffer name
    (setq frame-title-format
          '((:eval (if (buffer-file-name)
                       (abbreviate-file-name (buffer-file-name))
                     "%b (%m) (%f)"))))
    
    ;; Default Frame
    (setq initial-frame-alist
          '(;(alpha . 85)
            (left-margin-width . 10)
            (width . 140) ; chars on line
            (height . 40) ;number of lines
                                            ;(menu-bar-lines . 0)
            (tool-bar-lines . 0)
            (horizontal-scroll-bars . nil)
            (vertical-scroll-bars . nil)))
    
    ;; Remove tool bar
    (tool-bar-mode -1)
    
    
  2. Fonts
    ;; hydra to choose font
    (global-set-key (kbd "\C-cz")
                    (defhydra hydra-zoom ()
                      "zoom"
                      ("+" text-scale-increase "+")
                      ("-" text-scale-decrease "-")
                      ("0" (text-scale-adjust 0) "reset")
                      ("n" use-nice-font "nice")
                      ("e" use-elpy-font "elpy")
                      ("c" use-cfw-font "cfw")
                      ("d" use-dired-font "dired")
                      ("m" use-mu4e-font "mu4e")
                      ("D" use-default-font "default")
                      ("q" nil "quit" :color blue)))
    
    ;; fonts
    ;;(set-frame-font "Ubuntu Mono 11" nil t)
    ;;(set-default-font "Monofur 13" nil t)
    ;;(set-default-font "Inconsolata 12" nil t)
    
    ;; set the fall-back font
    ;; this is critical for displaying various unicode symbols, such as those used in my init-org.el settings
    ;; http://endlessparentheses.com/manually-choose-a-fallback-font-for-unicode.html
    (set-fontset-font "fontset-default" nil 
                      (font-spec :height 100 :name "Inconsolata"))
    
    ;; Setting English Font
    (set-face-attribute
     'default nil :stipple nil :height 100 :width 'normal :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant 'normal :weight 'normal :foundry "outline" :family "Inconsolata")
    
    
    
                                            ;(set-face-attribute
                                            ;  'default nil :background "#151515" :stipple nil :height 80 :width 'normal :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant 'normal :weight 'normal :foundry "outline" :family "Monospace")
    ;;Source Code Pro
    ;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Face-Attributes.html
    
                                            ;(custom-set-faces
                                            ; '(dired-directory ((t (:background "#202020" :foreground "#9999EE" :bold t))))
                                            ;)
    ;;'(org-level-1 ((t (:background "#303030"))))
    
    (defun use-elpy-font ()
      (interactive)
      "Switch the current buffer to a monospace font."
      (face-remap-add-relative 'default '(:family "Monofur" :height 100)))
    (add-hook 'elpy-mode-hook 'use-elpy-font)
    
    (defun use-dired-font ()
      (interactive)
      "Switch the current buffer to a monospace font."
      (face-remap-add-relative 'default '(:family "Ubuntu Mono" :height 100)))
    (add-hook 'dired-mode-hook 'use-dired-font)
    
    (defun use-mu4e-font ()
      (interactive)
      "Switch the current buffer to a monospace font."
      (face-remap-add-relative 'default '(:family "Ubuntu Mono" :height 80)))
    (add-hook 'mu4e-headers-mode-hook 'use-mu4e-font)
    
    (defun use-nice-font ()
      (interactive)
      "Switch the current buffer to a monospace font."
      (face-remap-add-relative 'default '(:family "Purisa" :height 80)))
    
    (defun use-default-font ()
      (interactive)
      "Switch the current buffer to a monospace font."
      (face-remap-add-relative 'default '(:family "Inconsolata" :height 100)))
    
    
  3. Themes/background/selection
    ;; transparent background
                                            ; (set-frame-parameter (selected-frame) 'alpha '(95 . 80))
                                            ; (add-to-list 'default-frame-alist '(alpha . (95 . 80)))
    
    ;;theme
    (load-theme 'monokai)
    ;;other themes ;adwaita, deeper-blue, dichromancy, light-blue, manoj-dark, misterioso, tango, tango-dark, tsdh-dark, tsdh-light, wheatgrass, whiteboard, wombat
    
    ;;added downloaded solarized (solarized-dark/light) zenburn-theme (zenburn) monokai
    
    ;;selected region
    ;;(set-face-attribute 'region nil :background "#000" )
    (set-face-attribute 'region nil :background "#444" :underline "yellow"  )
    
    ;;background color
                                            ;(if (display-graphic-p)
                                            ;    (setq initial-frame-alist
                                            ;          '(
                                            ;            (tool-bar-lines . 0)
                                            ;            (width . 106)
                                            ;            (height . 60)
                                            ;            (background-color . "#121")
                                            ;            (left . 50)
                                            ;            (top . 50)))
                                            ;  (setq initial-frame-alist '( (tool-bar-lines . 0))))
                                            ;(setq default-frame-alist initial-frame-alist)
    
    
  4. Dimmer
    ;; dim unused buffers (not windows)
    (use-package dimmer
      :ensure t)
    (dimmer-mode)
    ;; dim by 30%
    (setq dimmer-fraction 0.3)
    
    

3.3 Printing

(require 'printing)		; load printing package
(setq ps-lpr-command "print_preview")

;; in /usr/local/bin/print_preview (777)
                                        ;#!/bin/sh
                                        ; PREVIEW_FILE=$(mktemp --suffix=.ps)
                                        ; cat >"$PREVIEW_FILE" && evince "$PREVIEW_FILE" || \
                                        ;     notify-send 'Print preview failed' --urgency=critical \
                                        ;     --expire-time=2000
                                        ; rm "$PREVIEW_FILE" 

3.4 Text

3.4.1 Templates

(global-set-key (kbd "\C-ci")
                (defhydra hydra-templates
                  (:exit t)
                  "templates"
                  ("d" insert-deft-note-template "Deft")
                  ("o" insert-template "Browse")
                  ("e" insert-ein-block-template "ein block")
                  ("q" nil "cancel" :color blue)))

(defun insert-template ()
  (interactive)
  (let ((filename (read-file-name "Enter file name:" "~/ownCloud/Templates/")))
    (insert-file-contents filename)
    (if (str= (file-name-extension filename) "org")
        (org-mode)))
  )

(defun insert-deft-note-template ()
  (interactive)
  (insert-file-contents "~/ownCloud/Templates/NotesDeft/notes.org"))


(defun insert-ein-block-template ()
  (interactive)
  (insert-file-contents "~/ownCloud/Templates/Python/ein-block.org"))

3.4.2 Hydras

;; hydra to move around text
(global-set-key (kbd "\C-cm")
                (defhydra hydra-move
                  (:body-pre (next-line))
                  "move"
                  ("n" next-line "next line")
                  ("p" previous-line "previous line")
                  ;;("p" (lambda () (interactive) (forward-line -1))  "up")
                                        ;("f" forward-char "forward")
                                        ;("b" backward-char "backward")
                  ("a" beginning-of-line "line start")
                  ("e" move-end-of-line "line end")
                  ("g" goto-line "goto line")
                  ;;("v" scroll-up-command "up")
                  ;; Converting M-v to V here by analogy.
                  ;;("V" scroll-down-command "down")
                  ("t" (lambda () (interactive)(move-to-window-line-top-bottom 0)) "top")
                  ("b" (lambda () (interactive)(move-to-window-line-top-bottom -1)) "bottom")
                  ("m" (lambda () (interactive)(move-to-window-line-top-bottom)) "middle")
                  ("c" recenter-top-bottom "center")
                  ("q" nil "cancel" :color blue)))

;; hydra for region actions
(global-set-key (kbd "\C-cr")
                (defhydra hydra-region 
                  (:exit t) ;;exit right after
                  "region"
                  ("s" ispell-region "spell check")
                  ("u" unfill-paragraph "unfill")
                  ("c" count-words-region "count words")))

;; hydra for word actions
(global-set-key (kbd "\C-cw")
                (defhydra hydra-word 
                  (:exit t) ;;exit right after
                  "word"
                  ("s" ispell-word "spell check")
                  ("S" helm-flyspell-correct "helm spell check")
                  ("$" flyspell-correct-word-generic "ivy spell check")
                  ("z" ac-fuzzy-complete "fuzzy complete")
                  ("t" google-translate-at-point "translate")
                  ("e" lookup-word-en "lookup-en")
                  ("f" lookup-word-fr "lookup-fr")
                  ("u" upcase-region "upcase")
                  ("d" downcase-region "downcase")
                  ("c" capitalize-region "capitalize")
                  ("q" nil "cancel" :color blue)))

3.4.3 Encoding

;; dead keys
(require 'iso-transl)

;; prefer UTF-8 encoding
;;(prefer-coding-system 'utf-8)

(when (display-graphic-p)
  (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))

(prefer-coding-system 'utf-8-unix)
(set-language-environment "UTF-8")
(set-locale-environment "en_US.UTF-8")
(set-default-coding-systems 'utf-8-unix)
(set-selection-coding-system 'utf-8-unix)
(set-buffer-file-coding-system 'utf-8-unix)
(set-clipboard-coding-system 'utf-8) ; included by set-selection-coding-system
(set-keyboard-coding-system 'utf-8) ; configured by prefer-coding-system
(set-terminal-coding-system 'utf-8) ; configured by prefer-coding-system
(setq buffer-file-coding-system 'utf-8) ; utf-8-unix
(setq save-buffer-coding-system 'utf-8-unix) ; nil
(setq process-coding-system-alist
      (cons '("grep" utf-8 . utf-8) process-coding-system-alist))


3.4.4 Pair parentheses/quotes

  1. DISABLED smartparens
    ;; Automatically create closing parentheses:
                                            ;(setq skeleton-pair t)
                                            ;(setq skeleton-pair-on-word t)
                                            ;(global-set-key (kbd "[") 'skeleton-pair-insert-maybe)
                                            ;(global-set-key (kbd "(") 'skeleton-pair-insert-maybe)
                                            ;(global-set-key (kbd "{") 'skeleton-pair-insert-maybe) 
    ;;(global-set-key (kbd "<") 'skeleton-pair-insert-maybe)
    ;;(global-set-key (kbd "$") 'skeleton-pair-insert-maybe)
    
    
    ;;https://gist.github.com/pvik/8eb5755cc34da0226e3fc23a320a3c95
    (use-package smartparens
      :ensure t
      :config 
                                            ;(custom-set-faces
                                            ;'(sp-show-pair-match-content-face ((t (:foreground "#0FF"))))
                                            ;)
                                            ;(custom-set-faces
                                            ;'(sp-show-pair-match-face ((t (:foreground "#0FF"))))
                                            ;)
      )
    (show-smartparens-global-mode t)
    (smartparens-global-mode t) 
    
    
  2. autopair
    (add-to-list 'load-path "~/.emacs.d/autopair")
    (require 'autopair)
    (autopair-global-mode) ;; enable autopair in all buffers
    
    ;;press ( or " will wrap word"
    (setq autopair-autowrap t)
    ;;but we wanna keep using delete-selection
    (put 'autopair-insert-opening 'delete-selection t)
    (put 'autopair-skip-close-maybe 'delete-selection t)
    (put 'autopair-insert-or-skip-quote 'delete-selection t)
    (put 'autopair-extra-insert-opening 'delete-selection t)
    (put 'autopair-extra-skip-close-maybe 'delete-selection t)
    (put 'autopair-backspace 'delete-selection 'supersede)
    (put 'autopair-newline 'delete-selection t)
    
                                            ;(require 'auto-pair+)
    

3.4.5 Parentheses

;; highlight parentheses when inside
(define-advice show-paren-function (:around (fn) fix)
  "Highlight enclosing parens."
  (cond ((looking-at-p "\\s(") (funcall fn))
        (t (save-excursion
             (ignore-errors (backward-up-list))
             (funcall fn)))))

;; Show matching parentheses
(setq show-paren-delay 1)
(show-paren-mode 1)
                                        ;(setq show-paren-style 'expression) ;; or 'parenthesis (default) or 'mixed or 'expression

                                        ;(require 'paren)
                                        ;(set-face-attribute 'show-paren-match-face nil 
                                        ;:foreground nil
                                        ;:background nil
                                        ;:box nil)

                                        ;(set-face-attribute 'region nil :background "#222" :foreground "#FF0" :underline t)
;;(set-face-foreground 'show-paren-match-face '#222')

;; highlight inside ()
(setq show-paren-style 'parenthesis)
(require 'paren)
                                        ;(set-face-background 'show-paren-match (face-foreground 'default))
;;(set-face-background 'show-paren-match (face-foreground 'default))
                                        ;(set-face-background 'show-paren-match nil)
(set-face-foreground 'show-paren-match nil)
(set-face-attribute 'show-paren-match nil :weight 'extra-bold)


                                        ;(add-hook 'minibuffer-setup-hook 'turn-on-smartparens-strict-mode)
                                        ;(add-hook 'prog-mode-hook 'turn-on-smartparens-strict-mode)
                                        ;(add-hook 'markdown-mode-hook 'turn-on-smartparens-strict-mode)

;; following already in smartparens
                                        ;(setq show-paren-highlight-openparen t
                                        ;      show-paren-when-point-inside-paren t)

;; hydra
(global-set-key (kbd "\C-cp")
                (defhydra smartparens-hydra ()
                  "Smartparens"
                  ("n" sp-forward-sexp "Next")
                  ("p" sp-backward-sexp "Previous")
                  ("d" sp-down-sexp "Forward-down")
                  ("u" sp-up-sexp "Forward-up")
                  ("U" sp-backward-up-sexp "Back-Up")
                  ("D" sp-backward-down-sexp "Back-Down")
                  ("k" sp-kill-sexp "Kill" :color blue)
                  ("c" sp-copy-sexp "Copy" :color blue)
                  ("s" sp-splice-sexp "Splice" :color blue)
                  ("q" nil "Quit" :color blue)))

;; colorful parentheses
(use-package rainbow-delimiters
  :ensure t
  :config
  (add-hook 'prog-mode-hook 'rainbow-delimiters-mode))

(custom-set-faces
 '(rainbow-delimiters-depth-1-face ((t (:foreground "#0F0"))))
 '(rainbow-delimiters-depth-2-face ((t (:foreground "#FF0"))))
 '(rainbow-delimiters-depth-3-face ((t (:foreground "#FA0"))))

 '(rainbow-delimiters-depth-4-face ((t (:foreground "#0D0"))))
 '(rainbow-delimiters-depth-5-face ((t (:foreground "#DD0"))))
 '(rainbow-delimiters-depth-6-face ((t (:foreground "#D80"))))

 '(rainbow-delimiters-depth-7-face ((t (:foreground "#0A0"))))
 '(rainbow-delimiters-depth-8-face ((t (:foreground "#AA0"))))
 '(rainbow-delimiters-depth-9-face ((t (:foreground "#A50"))))

 '(rainbow-delimiters-unmatched-face ((t (:background "black"))))
 )

3.4.6 General

(global-subword-mode 1)                           ; Iterate through CamelCase words

;; word wrap
(global-visual-line-mode)

;; highlight colors
(use-package rainbow-mode
  :load-path "~/elisp/rainbow-mode.el/"
  :unless (string-prefix-p "example.com" (system-name))
  :diminish rainbow-mode
  :config
  (add-hook 'emacs-lisp-mode-hook 'rainbow-mode)
  (add-hook 'css-mode-hook 'rainbow-mode)
  (add-hook 'html-mode-hook 'rainbow-mode)
  (add-hook 'js2-mode-hook 'rainbow-mode))

;; Remove text in active region if inserting text
(delete-selection-mode 1)

;; emacs clipboard available to other apps
(setq x-select-enable-clipboard t)

;; ends sentences with single space
(setq sentence-end-double-space nil)

;;unfill
                                        ;(defun unfill-region (beg end)
                                        ;  "Unfill the region, joining text paragraphs into a single
                                        ;    logical line.  This is useful, e.g., for use with
                                        ;    `visual-line-mode'."
                                        ;  (interactive "*r")
                                        ;  (let ((fill-column (point-max)))
                                        ;    (fill-region beg end)))

(defun unfill-paragraph (&optional region)
  "Takes a multi-line paragraph and makes it into a single line of text."
  (interactive (progn (barf-if-buffer-read-only) '(t)))
  (let ((fill-column (point-max))
        ;; This would override `fill-column' if it's an integer.
        (emacs-lisp-docstring-fill-column t))
    (fill-paragraph nil region)))

3.4.7 Whitespace

;; show white spaces
(require 'whitespace)
(global-whitespace-mode 1)

(progn
  ;; Make whitespace-mode with very basic background coloring for whitespaces.
  ;; http://ergoemacs.org/emacs/whitespace-mode.html
  (setq whitespace-style (quote (face spaces tabs newline space-mark tab-mark newline-mark )))


  ;;causing issues with some tex files
                                        ; Make whitespace-mode and whitespace-newline-mode use “¶” for end of line char and “▷” for tab.
  (setq whitespace-display-mappings
        ;; all numbers are unicode codepoint in decimal. e.g. (insert-char 182 1)
        '(
          (space-mark 32 [183] [46]) ; SPACE 32 「 」, 183 MIDDLE DOT 「·」, 46 FULL STOP 「.」
          ;;newline-mark 10 [182 10]) ; LINE FEED,
          (newline-mark 10 [8628 10])
                                        ;(tab-mark 9 [9655 9] [92 9]) ; tab
          (tab-mark 9 [8680 9] [92 9]) ; tab
          ))

  )

(set-face-attribute 'whitespace-tab nil
                    :background "#222244"
                    :foreground "#FFFF00"
                    :weight 'bold)

(set-face-attribute 'whitespace-newline nil
                    :background "#222244"
                    :weight 'normal)


3.4.8 Source code/indentation

(setq-default
 tab-width 4                                      ; Set width for tabs
 indent-tabs-mode nil                             ; Stop using tabs to indent
 )

;; Enable syntax coloring                                           
                                        ;(setq font-lock-maximum-decoration t)
                                        ;(global-font-lock-mode t)

(setq org-src-preserve-indentation nil 
      org-edit-src-content-indentation 0)

3.4.9 Spelling

;; spelling

;;enable flyspell
(dolist (hook '(text-mode-hook))
  (add-hook hook (lambda () (flyspell-mode 1))))
;;(add-hook 'text-mode-hook 'flyspell-mode) ;;sometimes freezes

;;spelling in comments
;;(add-hook 'prog-mode-hook 'flyspell-prog-mode)
;;see programming for list of progs
;; (dolist (mode '(emacs-lisp-mode-hook
;;                 lisp-mode-hook
;;                 python-mode-hook
;;                 php-mode-hook
;;                 c-mode-hook
;;                 cc-mode-hook
;;                 c++-mode-hook
;;                 java-mode-hook
;;                 perl-mode-hook
;;                 sh-mode-hook
;;                 fortran-mode-hook
;;                 f90-mode-hook
;;                 xml-mode-hook
;;                 latex-mode-hook
;;                 html-mode-hook
;;                 css-mode-hook
;;                 web-mode-hook
;;                 js-mode-hook
;;                 R-mode-hook))
;;   (add-hook mode '(lambda () (flyspell-prog-mode))))


(setq flyspell-issue-message-flag nil) ;; printing messages for every word (when checking the entire buffer) causes an enormous slowdown



;;spelling

;; sudo apt-get install aspell-fr hunspell

(global-set-key (kbd "<f2>") 'ispell-word)
(defun flyspell-check-next-highlighted-word ()
  "Custom function to spell check next highlighted word"
  (interactive)
  (flyspell-goto-next-error)
  (ispell-word))
(global-set-key (kbd "C-<f2>") 'flyspell-check-next-highlighted-word)
;; correct
                                        ;(global-set-key (kbd "<C-f3>") 'helm-flyspell-correct)
                                        ;(global-set-key (kbd "<C-f4>") 'flyspell-correct-word-generic)

(with-eval-after-load "ispell"
  ;; find aspell and hunspell automatically
  (cond
   ;; try hunspell at first
   ;; if hunspell does NOT exist, use aspell
   ((executable-find "hunspell")
    (setq ispell-program-name "hunspell")
    (setq ispell-dictionary "en_US")
    ;; ispell-set-spellchecker-params has to be called
    ;; before ispell-hunspell-add-multi-dic will work
    (ispell-hunspell-add-multi-dic "en_US")
    (setq ispell-local-dictionary "en_US")
    (setq ispell-local-dictionary-alist
          ;; Please note the list `("-d" "en_US")` contains ACTUAL parameters passed to hunspell
          ;; You could use `("-d" "en_US,en_US-med")` to check with multiple dictionaries
                                        ;'(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US,fr_FR") nil utf-8) ;;eiter do this or enable guess-language
          '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US") nil utf-8)
            )))

   ((executable-find "aspell")
    (setq ispell-program-name "aspell")
    ;; Please note ispell-extra-args contains ACTUAL parameters passed to aspell
    (setq ispell-extra-args '("--sug-mode=ultra" "--lang=en_US")))))



                                        ;(ispell-check-version)




;; use hunspell 
(with-eval-after-load "ispell"
  (setq ispell-check-comments t)
  )

;; ;; Automatically detect language for Flyspell for current paragraph! Also reruns flyspell, just on the paragraph
;; (use-package guess-language  
;;   :disabled t
;;   :ensure t
;;   :defer t
;;   :init (add-hook 'text-mode-hook #'guess-language-mode)
;;   :config
;;   (setq guess-language-langcodes '((en . ("en_US" "English"))
;;                                    (fr . ("fr_FR" "French")))
;;         guess-language-languages '(en fr)
;;         guess-language-min-paragraph-length 40) ;minimal length that a paragraph needs to have before guess-language-mode starts guessing
;; ;;keep only en and fr
;; (defcustom guess-language-langcodes
;;   '(   (en . ("en"         "English"))
;;        (fr . ("francais"   "French"))
;;        )
;;   "Language codes for spell-checker and typo-mode.

;; The key is a symbol specifying the ISO 639-1 code of the
;; language.  The values is a list with two elements.  The first is
;; the name of the dictionary that should be used by the
;; spell-checker (e.g., what you would enter when setting the
;; language with `ispell-change-dictionary').  The second element is
;; the name of the language setting that should be used with
;; typo-mode.  If a language is not supported by typo-mode, that
;; value is nil."
;;   :type '(alist :key-type symbol :value-type list))

;;   :diminish guess-language-mode)

                                        ;(require 'guess-language)
;; Optionally:
                                        ;(setq guess-language-languages '(en fr))
                                        ;(setq guess-language-min-paragraph-length 35)
                                        ;(guess-language-mode)



                                        ;(custom-set-faces
                                        ;'(flyspell-incorrect-face ((((class color)) (:foreground "black" :size "13" :bold t :underline t)))))
                                        ;(use-package flyspell
                                        ;  :diminish (flyspell-mode . "spell")
                                        ;  :config
                                        ;  (set-face-attribute 'flyspell-incorrect nil :background "selectedKnobColor" :underline '(:color "black") :weight 'bold)
                                        ;  )

                                        ;(ispell-change-dictionary "francais")
                                        ;(ispell-change-dictionary "en_US") 


(custom-theme-set-faces
 'user
                                        ;'(flyspell-duplicate ((t (:weight bold :overline "#FFFF00" :underline (:color "#ffff00" :style line)))))
                                        ;'(flyspell-incorrect ((t (:weight normal :overline "#AA0000" :underline (:color "#AA0000" :style line)))))
                                        ;'(flyspell-duplicate ((t (:overline "#FFFF00" :underline nil :background "#400")))) ;:weight bold 
                                        ;'(flyspell-incorrect ((t (:overline "#AA0000" :underline nil :background "#400")))) ;:weight normal
 '(flyspell-duplicate ((t (:underline nil :background "#400")))) ;:weight bold 
 '(flyspell-incorrect ((t (:underline nil :background "#440")))) ;:weight normal

 )

3.4.10 TeX/bibtex

  1. General
    ;; automatic org-mode-latex-preview
    ;; #+STARTUP: latexpreview
    
    ;; show compilation result and close if everything ok
    (setq TeX-show-compilation t)
    (defcustom TeX-buf-close-at-warnings-only t
      "Close TeX buffer if there are only warnings."
      :group 'TeX-output
      :type 'boolean)
    (defun my-tex-close-TeX-buffer (_output)
      "Close compilation buffer if there are no errors.
    Hook this function into `TeX-after-compilation-finished-functions'."
      (let ((buf (TeX-active-buffer)))
        (when (buffer-live-p buf)
          (with-current-buffer buf
            (when (progn (TeX-parse-all-errors)
                         (or
                          (and TeX-buf-close-at-warnings-only
                               (null (cl-assoc 'error TeX-error-list)))
                          (null TeX-error-list)))
              (cl-loop for win in (window-list)
                       if (eq (window-buffer win) (current-buffer))
                       do (delete-window win)))))))
    (add-hook 'TeX-after-compilation-finished-functions #'my-tex-close-TeX-buffer)
    
    ;; tex-site
    (use-package tex-site
      :defer t
      :init
      ;;(setq ispell-program-name "hunspell") ; could be ispell as well, depending on your preferences
      (setq ispell-program-name "aspell") ; could be ispell as well, depending on your preferences
      (setq ispell-dictionary "english") ; this can obviously be set to any language your spell-checking program supports
      :config 
      (setq TeX-source-correlate-method (quote synctex))
      (setq TeX-source-correlate-mode t)
      (setq TeX-source-correlate-start-server t)
      (setq TeX-auto-save t)
      (setq TeX-parse-self t)
      (setq TeX-save-query nil)
      (setq TeX-PDF-mode t) ;;To compile documents to PDF by default or ;;(require 'tex) and (TeX-global-PDF-mode t)
    
      ;; add line numbers
      (add-hook 'LaTeX-mode-hook 'linum-mode) ;only for programming ;(global-linum-mode t) freezes docview
    
      ;; reftex
      (autoload 'reftex-mode "reftex" "RefTeX Minor Mode" t)
      (autoload 'turn-on-reftex "reftex" "RefTeX Minor Mode" nil)
      (autoload 'reftex-citation "reftex-cite" "Make citation" nil)
      (autoload 'reftex-index-phrase-mode "reftex-index" "Phrase Mode" t)
    
      ;; Turn on RefTeX in AUCTeX
      (add-hook 'LaTeX-mode-hook 'turn-on-reftex)
      ;; Activate nice interface between RefTeX and AUCTeX
      (setq reftex-plug-into-AUCTeX t)
    
      ;;  misc.
      (setq LaTeX-eqnarray-label "eq"
            LaTeX-equation-label "eq"
            LaTeX-figure-label "fig"
            LaTeX-table-label "tab"
            LaTeX-myChapter-label "chap"
            TeX-auto-save t
            TeX-newline-function 'reindent-then-newline-and-indent
            TeX-parse-self t
            TeX-style-path
            '("style/" "auto/"
              "/usr/share/emacs21/site-lisp/auctex/style/"
              "/var/lib/auctex/emacs21/"
              "/usr/local/share/emacs/site-lisp/auctex/style/")
            LaTeX-section-hook
            '(LaTeX-section-heading
              LaTeX-section-title
              LaTeX-section-toc
              LaTeX-section-section
              LaTeX-section-label))
    
      ;; revert pdf-view after compilation
      (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer)
    
      ;; C-tab for auto-completion instead of M-tab
      (add-hook 'LaTeX-mode-hook
                (lambda()
                  (local-set-key [tab] 'TeX-complete-symbol)))
    
      ;; help
      (defun show-latex-help ()
        (interactive)
        (message-box "
    TEX
    ---
    <C-c =>:\t\t TOC
    <C-c C-a>:\t\t compile and view
    <C-c RET>:\t\t insert macro (e.g. cite), with completion
    <C-c C-g>/<f2>:\t\t jump from tex to pdf
    <C-mouse1>:\t jump from pdf to tex
    <tab>:\t\t auto-completion
    "))
    
      ;; define major mode shortcuts
      (defun my-latex-mode-config ()
        "For use in `LaTeX-mode-hook'."
        (local-set-key (kbd "<C-f1>") 'show-latex-help)
        (local-set-key (kbd "<f2>") 'pdf-sync-forward-search)
        ;;(local-set-key (kbd "C-c C-p") nil) ;  remove a key
        )
      ;; add to hook
      (add-hook 'LaTeX-mode-hook 'my-latex-mode-config)
      )
    
  2. Output PDF
    ;; output pdf
    ;; to use pdfview with auctex
    ;;(add-hook 'LaTeX-mode-hook 'pdf-tools-install)
    
    ;; internal pdf-tools?
    (setq TeX-view-program-selection '((output-pdf "PDF Tools"))
          TeX-source-correlate-start-server t
          )
    ;;(setq TeX-view-program-list '(("pdf-tools" "TeX-pdf-tools-sync-view")))
    
    ;; view output in Okular?
                                            ;(setq TeX-view-program-list '(("Okular" "okular --unique %u")))
                                            ;(add-hook 'LaTeX-mode-hook '(lambda ()
                                            ;                  (add-to-list 'TeX-expand-list
                                            ;                       '("%u" Okular-make-url))))
                                            ;(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)
                                            ;               (expand-file-name (TeX-master-directory))
                                            ;               "./"
                                            ;               (TeX-current-file-name-master-relative)))
                                            ;(setq TeX-view-program-selection '((output-pdf "Okular")))
    
    
  3. LaTeX Preview Pane
    • to debug latex file

3.4.11 PDF-tools

;;install from package manager and check that libtiff from conda is not first (remove or rename)
;; install libtiff and libpoppler from apt-get too

;;https://github.com/pinguim06/pdf-tools-org
;;http://tech.memoryimprintstudio.com/pdf-annotation-related-tools/

;;if you want to auto export the annotations after saving a pdf, also add this:
                                        ;(add-hook 'after-save-hook
                                        ;          (lambda ()
                                        ;            (when (eq major-mode 'pdf-view-mode) (pdf-tools-org-export-to-org))))

;; for annotations
(defun save-buffer-no-args ()
  "Save buffer ignoring arguments"
  (save-buffer))

;; hydra for PDF actions (type ? in PDF)
(defhydra hydra-pdf ()
  "pdf"
  ("<" pdf-view-first-page "first page")
  (">" pdf-view-last-page "last page")
  ("+" pdf-view-enlarge "+")
  ("-" pdf-view-shrink "-")
  ("g" pdf-view-goto-page "g")
  ("t" pdf-annot-add-text-annotation "text")
  ("h" pdf-annot-add-highlight-markup-annotation "highlight")
  ("/" pdf-annot-add-strikeout-markup-annotation "strikeout")
  ("u" pdf-annot-add-underline-markup-annotation "underline")
  ("~" pdf-annot-add-squiggly-annotation "squiggly")
  ("d" pdf-annot-delete "delete")
  ("p" pdf-tools-org-export-to-org "->org")
  ("o" pdf-outline "outline")
  ("s" pdf-occur "occur")
  ("n" org-noter "org-noter")
  ("S" org-noter-create-skeleton "org-noter skeleton")
  ("q" nil "cancel" :color blue))

                                        ;(use-package pdf-tools
                                        ;  :ensure t
                                        ;  :mode ("\\.pdf\\'" . pdf-tools-install)
                                        ;  ;;:bind ("C-c C-g" . pdf-sync-forward-search)
                                        ;  :defer t
                                        ;  :config
                                        ;  (setq mouse-wheel-follow-mouse t)
                                        ;  (setq pdf-view-resize-factor 1.10)
                                        ;  (pdf-tools-enable-minor-modes))

;; main
(use-package pdf-tools
  :defer t
  :init
  (add-to-list 'load-path "~/.emacs.d/pdf-tools-org-vian")
                                        ;(add-to-list 'load-path "~/.emacs.d/pdf-tools-org")
  (require 'pdf-tools-org)
  :bind (:map pdf-view-mode-map ("C-<f1>" . show-pdf-tools-help)
              ("?"  . hydra-pdf/body)
                                        ;("<f2>"  . pdf-annot-add-text-annotation)
                                        ;("<f3>" . pdf-annot-add-highlight-markup-annotation)
                                        ;("<f4>" . pdf-annot-add-strikeout-markup-annotation)
                                        ;("<f5>" . pdf-annot-add-underline-markup-annotation)
                                        ;("<f6>" . pdf-annot-add-squiggly-markup-annotation)
              ("<f10>" . pdf-tools-org-export-to-org)
              ("<f9>" . pdf-annot-delete)
              ("o" . pdf-outline)
              ("s" . pdf-occur)
              ("C-s" . isearch-forward) ;; use isearch instead of swiper
              ("/" . pdf-annot-add-strikeout-markup-annotation)
              ("h" . pdf-annot-add-highlight-markup-annotation)
              ("u" . pdf-annot-add-underline-markup-annotation)
              ("~" . pdf-annot-add-squiggly-markup-annotation)
              ("t" . pdf-annot-add-text-annotation)
              ("d" . pdf-annot-delete)
              ("n" . org-noter)
              ("S" . org-noter-create-skeleton)
              )
  :config

  ;; initialise
  (pdf-tools-install)

  ;; http://pragmaticemacs.com/emacs/even-more-pdf-tools-tweaks/
  ;; open pdfs scaled to fit page
  (setq-default pdf-view-display-size 'fit-page)



  ;; automatically annotate highlights
  (setq pdf-annot-activate-created-annotations t)

  ;; auto-revert
  ;;(add-hook 'pdf-view-mode-hook 'pdf-outline)

                                        ;(defun pdf-outline-tmp ()
                                        ;(pdf-outline)
                                        ;(let ((bn (file-name-nondirectory pdf-outline-pdf-document)))
                                        ;(next-multiframe-window)
                                        ;(switch-to-buffer bn)
                                        ;)
                                        ;)

                                        ;(add-hook 'pdf-tools-enabled-hook 'pdf-outline-tmp)
  (add-hook 'pdf-view-mode-hook (lambda () (auto-revert-mode 1)))
  (add-hook 'pdf-tools-enabled-hook (lambda () (auto-revert-mode 1)))
  ;;(setq auto-revert-interval 0.5) ?

  ;; use normal isearch
  ;;(define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward)

  ;; more fine-grained zooming
  (setq pdf-view-resize-factor 1.1)
  ;; wrapper for save-buffer ignoring arguments

  ;; http://pragmaticemacs.com/emacs/even-more-pdf-tools-tweaks/

  ;;display page number in outline
  (setq pdf-outline-display-labels 1)

  ;; wait until map is available
  (with-eval-after-load "pdf-annot"
    ;;(define-key pdf-annot-edit-contents-minor-mode-map (kbd "<return>") 'pdf-annot-edit-contents-commit)
    (define-key pdf-annot-edit-contents-minor-mode-map (kbd "<S-return>") 'newline)
    ;; save after adding comment
    (advice-add 'pdf-annot-edit-contents-commit :after 'save-buffer-no-args)
    )

  ;;colors
                                        ;(setq pdf-annot-default-text-annotation-properties
                                        ; '((color . "deep sky blue")))
                                        ;(setq pdf-annot-default-markup-annotation-properties
                                        ;      '((color . "orange")))

  (setq pdf-annot-default-annotation-properties
        '((t
           (label . ""))
          (text
           (color . "deep sky blue")
           (icon . "Insert"))
          (highlight
           (color . "yellow"))
          (underline
           (color . "red"))
          (squiggly
           (color . "red"))
          (strike-out
           (color . "red"))))

  ;; midnite mode hook
  ;;(add-hook 'pdf-view-mode-hook (lambda ()
  ;;                                 (pdf-view-midnight-minor-mode))) ; automatically turns on midnight-mode for pdfs

  (setq pdf-view-midnight-colors '("#ff9900" . "#0a0a12" )) ; set the amber profile as default (see below)

  ;; some filters
  (defun pdf-no-filter ()
    "View pdf without colour filter."
    (interactive)
    (pdf-view-midnight-minor-mode -1)
    )
  ;; change midnite mode colours functions
  (defun pdf-midnite-original ()
    "Set pdf-view-midnight-colors to original colours."
    (interactive)
    (setq pdf-view-midnight-colors '("#FFFFFF" . "#151515" )) ; original values
    (pdf-view-midnight-minor-mode)
    )
  (defun pdf-midnite-amber ()
    "Set pdf-view-midnight-colors to amber on dark slate blue."
    (interactive)
    (setq pdf-view-midnight-colors '("#101010" . "#FFFFEE" )) ; amber
    (pdf-view-midnight-minor-mode)
    )
  (defun pdf-midnite-white ()
    "Set pdf-view-midnight-colors to white on black."
    (interactive)
    (setq pdf-view-midnight-colors '("#000000" . "#EEEEEE" )) ; white
    (pdf-view-midnight-minor-mode)
    )
  (defun pdf-midnite-colour-schemes ()
    "Midnight mode colour schemes bound to keys"
    (local-set-key (kbd "!") (quote pdf-no-filter))
    (local-set-key (kbd "@") (quote pdf-midnite-amber)) 
    (local-set-key (kbd "#") (quote pdf-midnite-white))
    (local-set-key (kbd "$") (quote pdf-midnite-original))
    )  
  (add-hook 'pdf-view-mode-hook 'pdf-midnite-colour-schemes)


  ;; help
  (defun show-pdf-tools-help ()
    (interactive)
    (message-box "
PDF-TOOLS
---------
?: hydra
o: outline
t: text annotation
h: highlight
/: strikeout
u: underline
~: squiggly
d: delete annotation
s: occur
n: org-noter (i: insert, M-i: precise)
S: org-noter-create-skeleton
<f10>: export annotations to ORG file
"))

  )

3.4.12 Autocompletion

  1. DISABLED company
    (require 'company)
    (global-company-mode)
    ;;(setq company-backends '((company-capf company-dabbrev-code company-files)))
    (add-hook 'org-mode-hook
              (lambda ()
                (setq-local company-backends '((company-files company-dabbrev)))))
    
    (add-hook 'emacs-lisp-mode-hook
              (lambda ()
                (setq-local company-backends '((company-capf company-dabbrev-code)))))
    
    (define-key global-map (kbd "C-.") 'company-files)
    
  2. DISABLED Hippie-expand
    ;; hippie expand
                                            ;(defun my-hippie-expand-completions (&optional hippie-expand-function)
                                            ;      "Return the full list of possible completions generated by `hippie-expand'.
                                            ;    The optional argument can be generated with `make-hippie-expand-function'."
                                            ;      (let ((this-command 'my-hippie-expand-completions)
                                            ;            (last-command last-command)
                                            ;            (buffer-modified (buffer-modified-p))
                                            ;            (hippie-expand-function (or hippie-expand-function 'hippie-expand)))
                                            ;        (flet ((ding)) ; avoid the (ding) when hippie-expand exhausts its options.
                                            ;          (while (progn
                                            ;                   (funcall hippie-expand-function nil)
                                            ;                   (setq last-command 'my-hippie-expand-completions)
                                            ;                   (not (equal he-num -1)))))
                                            ;        ;; Evaluating the completions modifies the buffer, however we will finish
                                            ;        ;; up in the same state that we began.
                                            ;        (set-buffer-modified-p buffer-modified)
                                            ;        ;; Provide the options in the order in which they are normally generated.
                                            ;        (delete he-search-string (reverse he-tried-table))))
                                            ;    (defun my-ido-hippie-expand-with (hippie-expand-function)
                                            ;      "Offer ido-based completion using the specified hippie-expand function."
                                            ;      (let* ((options (my-hippie-expand-completions hippie-expand-function))
                                            ;             (selection (and options
                                            ;                             (ido-completing-read "Completions: " options))))
                                            ;        (if selection
                                            ;            (he-substitute-string selection t)
                                            ;          (message "No expansion found"))))
                                            ;    (defun my-ido-hippie-expand ()
                                            ;      "Offer ido-based completion for the word at point."
                                            ;      (interactive)
                                            ;      (my-ido-hippie-expand-with 'hippie-expand))
                                            ;    (global-set-key "\C-t" 'my-ido-hippie-expand)
    
    
  3. auto-complete
    1. DISABLED ivy
      ;https://sam217pa.github.io/2016/09/13/from-helm-to-ivy/
      ;(use-package ivy :ensure t
      ;  :diminish (ivy-mode . "")
      ;  :bind
      ;  (:map ivy-mode-map
      ;   ("C-'" . ivy-avy))
      ;  :config
      ;  (ivy-mode 1)
      ;  ;; add ‘recentf-mode’ and bookmarks to ‘ivy-switch-buffer’.
      ;  (setq ivy-use-virtual-buffers t)
      ;  ;; number of result lines to display
      ;  (setq ivy-height 10)
      ;  ;; does not count candidates
      ;  (setq ivy-count-format "")
      ;  ;; no regexp by default
      ;  (setq ivy-initial-inputs-alist nil)
      ;  ;; configure regexp engine.
      ;  (setq ivy-re-builders-alist
      ;	;; allow input not in order
      ;        '((t   . ivy--regex-ignore-order))))
      
    2. ac-ispell
      ;;ac-ispell ;;better if set before auto-complete otherwise hangs on grep process...
      (custom-set-variables
       '(ac-ispell-requires 4) ;; Required number of characters of this source completion
       '(ac-ispell-fuzzy-limit 0)) ;;Number of fuzzy completion candidates. 
      
      ;(eval-after-load "auto-complete"
      ;  '(progn
      ;     (ac-ispell-setup)))
      (ac-ispell-setup)
      (add-hook 'git-commit-mode-hook 'ac-ispell-ac-setup)
      (add-hook 'mail-mode-hook 'ac-ispell-ac-setup)
      (add-hook 'text-mode-hook 'ac-ispell-ac-setup)
      (add-hook 'latex-mode-hook 'ac-ispell-ac-setup)
      (add-hook 'html-mode-hook 'ac-ispell-ac-setup)
      (add-hook 'org-mode-hook 'ac-ispell-ac-setup)
      (add-hook 'mu4e-compose-mode-hook 'ac-ispell-ac-setup)
      
    3. ac
      
      (require 'auto-complete)
      (global-auto-complete-mode t)
      
      (require 'auto-complete-config)
      (ac-ropemacs-initialize)
      (global-auto-complete-mode t)
      (ac-config-default)
      ;; flyspell
      (ac-flyspell-workaround)
      
      ;; remove tab from auto-complete bindings
      ;;remove fuzzy for tab?
      ;;remove TAB, use ENTER instead
      (define-key ac-mode-map (kbd "TAB") nil)
      (define-key ac-completing-map (kbd "TAB") nil)
      (define-key ac-completing-map [tab] nil)
      
      
      (add-to-list 'ac-modes 'shell-script-mode)
      (add-to-list 'ac-modes 'lisp-interaction-mode)
      (add-to-list 'ac-modes 'perl-mode)
      (add-to-list 'ac-modes 'php-mode)
      (add-to-list 'ac-modes 'html-mode)
                                              ;(add-to-list 'ac-modes 'python-mode)
      (add-to-list 'ac-modes 'elpy-mode)
      (add-to-list 'ac-modes 'sql-mode)
      (add-to-list 'ac-modes 'text-mode)
      (add-to-list 'ac-modes 'java-mode)
      (add-to-list 'ac-modes 'org-mode)
      (add-to-list 'ac-modes 'tex-mode)
      (add-to-list 'ac-modes 'latex-mode)
      (add-to-list 'ac-modes 'mu4e-org-mode)
      (add-to-list 'ac-modes 'mu4e-main-mode)
      (add-to-list 'ac-modes 'mu4e-compose-mode)
      
      
      ;; Just ignore case
                                              ;(setq ac-ignore-case t)
      ;; Ignore case if completion target string doesn't include upper characters
                                              ;(setq ac-ignore-case 'smart)
      ;; Distinguish case
      (setq ac-ignore-case nil)
      
      ;; fuzzy
      (setq ac-use-fuzzy t)
      (setq ac-auto-start t)
      (setq ac-auto-show-menu 0.5)
      (setq ac-quick-help-delay 0.5)
      (setq ac-menu-height 5) ;; 20 lines
      
      
      
                                              ;where to get autocompletion from
                                              ;(add-to-list 'ac-dictionary-directories "/usr/share/dict/american-english")
      (setq ac-sources '(
                         ac-source-words-in-all-buffer
                         ac-source-words-in-buffer
                         ac-source-files-in-current-dir   
                         ac-source-words-in-same-mode-buffers    
                         ac-source-filename 
                         ac-source-ispell   
                         ac-source-dictionnary   
                         )
            )
      
      ;; faces
      (set-face-background 'ac-candidate-face "black")
      (set-face-foreground 'ac-candidate-face "lightgray")
      (set-face-underline 'ac-candidate-face "darkgray")
      (set-face-background 'ac-selection-face "purple")
      ;;(set-face-foreground 'ac-candidate-face "White")
                                              ;(set-face-background 'ac-selection-face foreground)
                                              ;(set-face-foreground 'ac-completion-face foreground)
      (set-face-background 'ac-completion-face "black")
      (set-face-foreground 'ac-completion-face "purple")
                                              ;(setq ac-auto-show-menu t)
                                              ;(setq ac-dwim t)
                                              ;(setq ac-use-menu-map t)
                                              ;(setq ac-quick-help-delay 1)
                                              ;(setq ac-quick-help-height 60)
                                              ;(setq ac-disable-inline t)
                                              ;(setq ac-show-menu-immediately-on-auto-complete t)
                                              ;(setq ac-auto-start 2)
                                              ;(setq ac-candidate-menu-min 0)
      
      
                                              ;just use right arrow instead of RET when new line and ac
                                              ;(define-key ac-mode-map (kbd "RET") nil)
                                              ;(define-key ac-completing-map (kbd "RET") nil)
                                              ;(define-key ac-completing-map [return] nil)
      
      

3.4.13 Translation

(require 'google-translate)
(require 'google-translate-default-ui)

(global-set-key "\C-cq" 'google-translate-query-translate)

                                        ;or
                                        ;(require 'google-translate)
                                        ;(require 'google-translate-smooth-ui)
                                        ;(global-set-key "\C-ct" 'google-translate-smooth-translate)

3.4.14 Lookup dictionary

(defun lookup-word-fr ()
  "Look up the word under cursor in Wikipedia.
If there is a text selection (a phrase), use that.

This command switches to browser."
  (interactive)
  (let (word)
    (setq word
          (if (use-region-p)
              (buffer-substring-no-properties (region-beginning) (region-end))
            (current-word)))
    (setq word (replace-regexp-in-string " " "_" word))
    (browse-url (concat "http://www.cnrtl.fr/definition/" word))
    ;;(browse-url (concat "https://fr.wiktionary.org/wiki/" word))
    ;; (eww myUrl) ; emacs's own browser
    ))

(defun lookup-word-en ()
  "Look up the word under cursor in Wikipedia.
If there is a text selection (a phrase), use that.

This command switches to browser."
  (interactive)
  (let (word)
    (setq word
          (if (use-region-p)
              (buffer-substring-no-properties (region-beginning) (region-end))
            (current-word)))
    (setq word (replace-regexp-in-string " " "_" word))
    (browse-url (concat "https://en.wiktionary.org/wiki/" word))
    ;; (eww myUrl) ; emacs's own browser
    ))

3.4.15 Diff

;; Usage: emacs -diff file1 file2

;; ediff
(require 'ediff)
;; don't start another frame
;; this is done by default in preluse
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
;; put windows side by side
(setq ediff-split-window-function (quote split-window-horizontally))
;;revert windows on exit - needs winner mode
(winner-mode)
(add-hook 'ediff-after-quit-hook-internal 'winner-undo)

(setq ediff-diff-options "-w")

(defun command-line-diff (switch)
  (let ((file1 (pop command-line-args-left))
        (file2 (pop command-line-args-left)))
    (ediff file1 file2)

    ;; if org files -> uncollapse!
    (dolist (buffer (buffer-list t))
      (set-buffer buffer)
      (if (string-match ".org" (buffer-name buffer))
          (outline-show-all)))

    ))
(add-to-list 'command-switch-alist '("diff" . command-line-diff))   ;; (add-to-list 'command-switch-alist '("-diff" . command-line-diff))

3.4.16 Search

                                        ;keep highlights until next C-S/R 
(setq lazy-highlight-cleanup nil)
;;(setq lazy-highlight-max-at-a-time nil)
;;(setq lazy-highlight-initial-delay 0)

;; hydra for search actions
(global-set-key (kbd "\C-cs")
                (defhydra hydra-search
                  (:exit t) ;;exit right after
                  "search"
                  ("s" isearch "case-insensitive")
                  ("S" isearch-case-sensitive "case-sensitive")
                  ("o" occur "occurences")))

;; case-sensitive search
(defun isearch-case-sensitive ()
  (interactive)
  (let* ((case-fold-search t))
    (isearch-forward))
  )

;; backspace behavior
(define-key isearch-mode-map [remap isearch-delete-char] 'isearch-del-char)

;; face for other matches when main one is highlighted
(custom-set-faces
 `(lazy-highlight ((t (:foreground "white" :background "SteelBlue")))))

;; isearch face
(custom-set-faces
 `(isearch ((t (:foreground "black" :background "yellow")))))


;; better replace
(use-package anzu
  :bind
  ([remap query-replace] . anzu-query-replace-regexp)
  :hook
  (after-init . global-anzu-mode)
  :custom
  (anzu-cons-mode-line-p nil))


3.4.17 Clipboard/yank

                                        ; Merge system's and Emacs' clipboard
(setq-default select-enable-clipboard t)

                                        ;AUTOMATICALLY COPY TEXT SELECTED WITH THE MOUSE
(setq mouse-drag-copy-region t)

;; paste (yank) from kill-ring by repeating C-y instead of C-y then M-y
(defun xah-paste-or-paste-previous ()
  "Paste. When called repeatedly, paste previous.
This command calls `yank', and if repeated, call `yank-pop'.

When `universal-argument' is called first with a number arg, paste that many times.

URL `http://ergoemacs.org/emacs/emacs_paste_or_paste_previous.html'
Version 2017-07-25"
  (interactive)
  (progn
    (when (and delete-selection-mode (region-active-p))
      (delete-region (region-beginning) (region-end)))
    (if current-prefix-arg
        (progn
          (dotimes ($i (prefix-numeric-value current-prefix-arg))
            (yank)))
      (if (eq real-last-command this-command)
          (yank-pop 1)
        (yank)))))
(global-set-key (kbd "C-y") 'xah-paste-or-paste-previous)




                                        ;(defadvice yank (before yank-if-overwrite)
                                        ;  (if (bound-and-true-p overwrite-mode)
                                        ;      (delete-char (length (current-kill 0))))
                                        ;  )
                                        ;(ad-activate 'yank)

(defun yank-unfill ()
  (interactive)     
                                        ;(insert (replace-regexp-in-string "\n" " " (car kill-ring-yank-pointer)));; eventually replace with insert-for-yank-1
  (setq tmp (replace-regexp-in-string "\n" " " (current-kill 0)))
  (setq tmp (replace-regexp-in-string "- " "" tmp))
  (setq tmp (replace-regexp-in-string "- " "" tmp))
  (insert (concat "\"" tmp "\""));; eventually replace with insert-for-yank-1
  )
(global-set-key (kbd "C-S-y") 'yank-unfill) ; Yank with the Shift key to swap instead of paste.



                                        ;replace actual yank
                                        ;(defadvice yank (before yank)
                                        ;  (kill-new (replace-regexp-in-string "\n" " " (car kill-ring-yank-pointer)))
                                        ;)
                                        ;(ad-activate 'yank)


;; (defun clipboard-swap () "Swaps the clipboard contents with the highlighted region"
;;     (interactive)
;;     (if (use-region-p)
;;         (progn
;;             (setq
;;                 reg-beg (region-beginning)
;;                 reg-end (region-end))
;;             (deactivate-mark)
;;             (goto-char reg-end)
;;             (clipboard-yank)
;;             (clipboard-kill-region reg-beg reg-end))
;;         (clipboard-yank)))

;; (global-set-key (kbd "C-S-Y") 'clipboard-swap) ; Yank with the Shift key to swap instead of paste.



3.5 Feeds (RSS)

3.5.1 Elfeed

;; ln -s ~/ownCloud/org/.elfeed ~/.elfeed

;; hydra for elfeed actions
                                        ;(defhydra mz/hydra-elfeed ()
                                        ;"filter"
                                        ;("c" (elfeed-search-set-filter "@6-months-ago +cs") "cs")
                                        ;("e" (elfeed-search-set-filter "@6-months-ago +emacs") "emacs")
                                        ;("d" (elfeed-search-set-filter "@6-months-ago +education") "education")
                                        ;("*" (elfeed-search-set-filter "@6-months-ago +star") "Starred")
                                        ;("M" elfeed-toggle-star "Mark")
                                        ;("A" (elfeed-search-set-filter "@6-months-ago") "All")
                                        ;("T" (elfeed-search-set-filter "@1-day-ago") "Today")
                                        ;("Q" bjm/elfeed-save-db-and-bury "Quit Elfeed" :color blue)
                                        ;("q" nil "quit" :color blue)
                                        ;)

;; load elfeed using db
(defun elfeed-load ()
  "Wrapper to save the elfeed db to disk before burying buffer"
  (interactive)
  (require 'elfeed)
  (elfeed-load-db-and-open))
;;(global-set-key (read-kbd-macro "<C-f6>") 'elfeed-load)

;; main
(use-package elfeed
  :ensure t
  :defer t
  :commands elfeed-load
  :bind ((:map elfeed-search-mode-map
               ("C-<f1>" . show-elfeed-help)
               ("?" . elfeed-update2)
               ("U" . elfeed-show-unread)
               ("R" . elfeed-show-read)
               ("q" . elfeed-save-db-and-bury))
         (:map elfeed-show-mode-map
               ("C-<f1>" . show-elfeed-help))
         )
  :init 

  (defun elfeed-update2 ()
    "Wrapper to save the elfeed db to disk before burying buffer"
    (interactive)
    (elfeed-update)
    (elfeed-db-save))

  (defun elfeed-save-db-and-bury ()
    "Wrapper to save the elfeed db to disk before burying buffer"
    (interactive)
    (elfeed-db-save)
    (quit-window))

  ;;functions to support syncing .elfeed between machines
  ;;makes sure elfeed reads index from disk before launching
  (defun elfeed-load-db-and-open ()
    "Wrapper to load the elfeed db from disk before opening"
    (interactive)
    (elfeed-db-load)
    (elfeed)
    (elfeed-search-update--force))

  ;; unread
  (defun elfeed-show-unread ()
    "Wrapper to save the elfeed db to disk before burying buffer"
    (interactive)
    (elfeed-search-set-filter "@6-months-ago +unread")
    )

  ;; read
  (defun elfeed-show-read ()
    "Wrapper to save the elfeed db to disk before burying buffer"
    (interactive)
    (elfeed-search-set-filter "@6-months-ago -unread")
    )
  :config

  (setq elfeed-search-title-min-width 60)
  (setq elfeed-search-title-max-width 100)
  (setq elfeed-search-trailing-min-width 0)

  (defun elfeed-search-format-date (date)
    (format-time-string "%m-%d" (seconds-to-time date)))

  (add-hook 'elfeed-show-mode-hook (text-scale-set 1.4))

                                        ;now done in elfeed-org


  ;;shortcut functions
  (setq-default elfeed-search-filter "@6-months-ago +unread")

;;; browse article in gui browser instead of eww
                                        ;(defun elfeed-show-visit-gui ()
                                        ;  "Wrapper for elfeed-show-visit to use gui browser instead of eww"
                                        ;  (interactive)
                                        ;  (let ((browse-url-generic-program "xdg-open"))
                                        ;    (elfeed-show-visit t)))

                                        ;(define-key elfeed-show-mode-map (kbd "G") 'elfeed-show-visit-gui)
  (define-key elfeed-show-mode-map (kbd "g") 'elfeed-show-visit)

  (defun show-elfeed-help ()
    (interactive)
    (message-box "
Elfeed
------

?: update
s: search
r/u: read/unread
R/U: show read/unread
g: visit URL
"))
  )

3.5.2 Elfeed-org

;; Load elfeed-org
(require 'elfeed-org)

;; Initialize elfeed-org
;; This hooks up elfeed-org to read the configuration when elfeed
;; is started with =M-x elfeed=
(elfeed-org)

;; Optionally specify a number of files containing elfeed
;; configuration. If not set then the location below is used.
;; Note: The customize interface is also supported.
(setq rmh-elfeed-org-files (list "~/ownCloud/org/elfeed.org"))

3.6 Org

3.6.1 Phone

  • Orgzly to view org files (import org file)
  • oCloud.be (blaucloud) to sync mycore

3.6.2 Layouts

;; org layout
(defun org-layout-work ()
  (interactive)
  ;;(delete-other-windows)
  (deft) 
  (cfw)

  ;(select-frame (make-frame))
  ;(delete-other-windows)
  ;(find-file "~/ownCloud/org/workflow.org")

  (select-frame (make-frame))
  (delete-other-windows)
  ;(split-window-horizontally)
  ;(org-agenda nil "P")
  ;(other-window 1)
  (org-agenda nil "A")

  (select-frame (make-frame))
  (delete-other-windows)
  (mu4e-elfeed)
  ;(select-window (mu4e)) ;;mu4e takes a long time to load...
  )

;; org layout
(defun org-layout-cal ()
  (interactive)
  ;;(delete-other-windows)
  (select-frame (make-frame))
  (delete-other-windows)
  (split-window-horizontally)
  (find-file "~/ownCloud/org/workflow.org")
  (other-window 1)
  (deft)
  (balance-windows) 
  )

;; org layout
(defun org-layout1 ()
  (interactive)
  ;;(delete-other-windows)
  (select-frame (make-frame))
  (delete-other-windows)
  (org-agenda nil "R")
  (split-window-horizontally)
  (find-file "~/ownCloud/org/workflow.org")
  )


;; org layout
(defun org-layout5 ()
  (interactive)
  ;;(delete-other-windows)
  (select-frame (make-frame))
  (delete-other-windows)
  (split-window-right)
  (split-window-right)
  (split-window-below)
  (balance-windows) 

  (other-window 4)
  (mu4e)
  (other-window 1)
  (elfeed-load)
  (other-window 1)
  (find-file "~/ownCloud/org/workflow.org")
  (other-window 1)
  (org-agenda nil "R")

  )

;; org layout
(defun org-layout6 ()
  (interactive)
  ;;(delete-other-windows)
  (select-frame (make-frame))
  (delete-other-windows)
  (split-window-right)
  (split-window-right)
  (split-window-below)
  (other-window 2)
  (split-window-below)
  (balance-windows) 

  (other-window 3)
  (mu4e)
  (other-window 1)
  (elfeed-load)
  (other-window 1)
  (find-file "~/ownCloud/org/workflow.org")
  (other-window 1)
  (org-agenda nil "P")
  (other-window 1)
  (org-agenda nil "A")

  )


;; org/pdf layout
(defun orgpdf-layout ()
  (interactive)
  (let ((nwin (length (cl-delete-duplicates (mapcar #'window-buffer (window-list))))))
    (org-latex-export-to-pdf)
    (if (= nwin 1)
        (progn (delete-other-windows)
               (split-window-right)
               (other-window 1)
               (find-file (replace-regexp-in-string ".org" ".pdf" buffer-file-name))))
    ))

3.6.3 General

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


;; specific shortcuts in org mode
(progn
  ;; modify org keys
  (require 'org )
  (define-key org-mode-map (kbd "<C-f1>") 'show-org-help)
  ;;(define-key org-mode-map (kbd "<f2>") 'org-agenda-show-agenda-and-todo)
  ;;(define-key org-mode-map (kbd "<f2>") 'org-agenda-show-agenda-and-todo-and-exportimport)
  (define-key org-mode-map (kbd "<f3>") 'exportimportics)
  (define-key org-mode-map (kbd "<f4>") 'org-todo)
  (define-key org-mode-map (kbd "<f5>") 'update-category)
  (define-key org-mode-map (kbd "<f6>") 'update-url)
  (define-key org-mode-map (kbd "C-c <f6>") 'goto-url)
                                        ;(define-key org-mode-map (kbd "C-c <f7>") 'goto-url-gui)
  (define-key org-mode-map (kbd "<f7>") 'update-location)
  (define-key org-mode-map (kbd "C-c <f10>") 'my-open-calendar)
  (define-key org-mode-map (kbd "<f9>") 'org-archive-subtree-default)
  (define-key org-mode-map (kbd "<C-S-mouse-1>") 'open-new-frame)
  (define-key org-mode-map (kbd "<C-return>") nil)
  (define-key org-mode-map (kbd "<C-S-down>") nil)
  (define-key org-mode-map (kbd "<C-S-up>") nil)
  (define-key org-mode-map (kbd "<M-S-up>") nil)
  (define-key org-mode-map (kbd "<M-S-down>") nil)
  )

;; Always start indented
(setq org-startup-indented t)


;; tag columns for table view (?)
(setq org-tags-column 20)

;; window wrap
(setq org-startup-truncated nil) 

;; category property
(defun update-category (cat)
  "Update entry single category via M-x update-category."
  (interactive "sInput category: ")
  (message "Setting category to %s" cat)
  (org-set-property "CATEGORY" cat))

;; url property
(defun update-url (url)
  "Update entry single category via M-x update-category."
  (interactive "sInput url : ")
  (if (not (string-match (regexp-quote "http") url))
      (setq url (concat "http://" url)))
  (org-set-property "URL" url))

(defun goto-url ()
  (interactive)
  (setq url (org-link-unescape (format "%S" (org-entry-get nil "URL"))))
  ;;(message-box url)
  ;;(org-open-at-point url)
  (setq urls (delete "" (split-string url))) ;;delete removes extra spaces
  (org-open-at-point urls)
  )
;;%S: Replace the specification with the printed representation of the object, made with quoting (that is, using prin1—see Output Functions). 

(defun open-new-frame ()
  "Jump to bookmark in another frame. See `bookmark-jump' for more."
  (interactive)
  (let ((org-link-frame-setup (cons (cons 'file 'find-file-other-frame) org-link-frame-setup)))
    (org-open-at-point))
  )

;; margin when exporting in latex
(setq org-latex-packages-alist '(("margin=1.5cm" "geometry" nil)))

(require 'org-bullets)
;; make available "org-bullet-face" such that I can control the font size individually
;;(setq org-bullets-face-name (quote org-bullet-face))
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
;;(setq org-bullets-bullet-list '("○" "☉" "◎" "◉" "○" "◌" "◎" "●" "◦" "◯" "⚪" "⚫" "⚬" "❍" "○" "⊙" "⊚" "⊛" "∙" "∘"))

3.6.4 Headings


;;Display the current Org header in the header-line.
(use-package org-sticky-header
  :custom
  (org-sticky-header-full-path 'full)
  (org-sticky-header-outline-path-separator " / ")
  :config
  (setq-default
   org-sticky-header-header-line-format
   '(:eval (setq org-sticky-header-stickyline (concat " " (org-sticky-header--fetch-stickyline))))))
(add-hook 'org-mode-hook (lambda () (org-sticky-header-mode 1)))

;; To never insert blank lines when inserting new headers
(setf org-blank-before-new-entry '((heading . nil) (plain-list-item . nil)))

;; replace C-enter shortcut to add subheading on top (alt/ret: add heading)
                                        ;(define-key org-mode-map (kbd "<C-return>") 'org-insert-subheading)

;; level colors
                                        ;(custom-theme-set-faces 'user
                                        ;                        `(org-level-1 ((t (:background "#303030")))))

;;The following setting hides blank lines between headings which keeps folded view nice and compact. 
(setq org-cycle-separator-lines 0)

                                        ;(setq org-fontify-whole-heading-line t)

;;Change the face of a headline if it is marked DONE. Normally, only the TODO/DONE keyword indicates the state of a headline. When this is non-nil, the headline after the keyword is set to the org-headline-done as an additional indication.
                                        ;(setq org-fontify-done-headline t)



                                        ;Add a special face to #+begin_quote and #+begin_verse block.
                                        ;(setq org-fontify-quote-and-verse-blocks t)

;;Show tags directly after headings (not on the right), which plays nicer with line-wrapping.
(setq org-tags-column 0)


3.6.5 Listings

;;A commonly used environment for source code is lstlisting, provided by the LaTeX package listings. To get Org-mode to use it, add it to org-latex-packages-alist and set the variable org-latex-listings to t

                                        ;(add-to-list 'org-latex-packages-alist '("" "listings" nil))
                                        ;(setq org-latex-listings t)

;; to then get listings to wrap, the breaklines=true option needs to be supplied to listings. Org-mode can do this:

(add-to-list 'org-latex-packages-alist '("" "listings" nil))
(setq org-latex-listings t)
(setq org-latex-listings-options '(("breaklines" "true")
                                   ("showstringspaces" "false")
                                   ("numbersep" "0")
                                   ("resetmargins" "true")
                                        ;("xleftmargin" "5pt")
                                        ;("xrightmargin" "5pt")
                                        ;("aboveskip" "\\bigskipamount")
                                        ;("belowskip" "\\bigskipamount")
                                   ("columns" "fullflexible")
                                   ("basicstyle" "\\small\\listingsfont")
                                        ;("literate" "{0}{0}{1}%
                                        ;{1}{1}{1}%
                                        ;{2}{2}{1}%
                                        ;{3}{3}{1}%
                                        ;{4}{4}{1}%
                                        ;{5}{5}{1}%
                                        ;{6}{6}{1}%
                                        ;{7}{7}{1}%
                                        ;{8}{8}{1}%
                                        ;{9}{9}{1}%
                                        ;")
                                   ))

3.6.6 Export

  • allow subscripts and superscripts but only with braces, otherwise show as _
(setq org-export-with-sub-superscripts "{}")

3.6.7 Org agenda

  1. General
    (require 'org-agenda)
    
    ;; agenda
    (global-set-key "\C-ca" 'org-agenda)
    
    ;;(setq org-agenda-compact-blocks t)
    ;;(setq org-agenda-span 'day)
    (setq org-agenda-span 60)
    
    (setq org-agenda-compact-blocks nil)
    
    
    ;; this is to have several buffers (e.g., review and day/week mode)
    (setq org-agenda-sticky t)
    (setq calendar-week-start-day 1) ;; start Monday
    
    ;; opens agenda in current window!
    (setq org-agenda-window-setup 'current-window) 
    
    ;; various
    (setq org-agenda-show-all-dates t)
    (setq org-agenda-skip-deadline-if-done t)
    (setq org-agenda-skip-scheduled-if-done t)
    (setq org-deadline-warning-days 15)
    (setq org-agenda-start-on-weekday nil)
    (setq org-reverse-note-order t)
    
    ;; change color for some categories
    (setq sequence '("svy:" "Vac. Scol.:" "Perso:" "Sorties:" "Birthdays:" "Récolte:" "RTT:"))     
    (add-hook 'org-agenda-finalize-hook
              (lambda ()
                (save-excursion                                           
                  (dolist (element sequence)
                    (goto-char (point-min))
    
                                            ;(message-box element)
                    (while (re-search-forward element nil t)
                      (add-text-properties (match-beginning 0) (point-at-eol)
                                           '(face (:foreground "#AAAAAA"))))
                    )
                  )))
    
    ;; custom agenda views
    (setq org-agenda-custom-commands
          '(("c" "Simple agenda view"
             ((agenda "")
              (alltodo "")))))
    
    
    ;;don't show tasks as scheduled if they are already shown as a deadline
    ;;(setq org-agenda-skip-scheduled-if-deadline-is-shown t)
    ;;don't show tasks that are scheduled or have deadlines in the
    ;;normal todo list
    ;;(setq org-agenda-todo-ignore-deadlines (quote all))
    ;;(setq org-agenda-todo-ignore-scheduled (quote all))
    
    
    ;; 
    (defun org-agenda-show-agenda-and-todo (&optional arg)
      (interactive "P")
      (org-agenda arg "R"))
    
    
    (defun org-agenda-show-projects (&optional arg)
      (interactive "P")
      (org-agenda arg "P"))
    
    (defun org-agenda-show-agenda (&optional arg)
      (interactive "P")
      (org-agenda arg "X"))
    ;; 
    (defun my-org-agenda-get-day-face-fn (date)
      "Return the face DATE should be displayed with."
      (let ((day-of-week (calendar-day-of-week date)))
        (if (or (= day-of-week 6) (= day-of-week 0))
            '(:foreground "white" :background "#000020")
          '(:foreground "white" :background "#002000"))
        ))
    (setq org-agenda-day-face-function 'my-org-agenda-get-day-face-fn)
    
    ;;(add-hook 'today-visible-calendar-hook 'calendar-mark-today)
    
    ;;add a line between days
    (defun pmg/org-agenda-format-date-aligned (date)
      "Format a DATE string for display in the daily/weekly agenda.
    This function makes sure that dates are aligned for easy reading."
      (require 'cal-iso)
      (let* ((dayname (calendar-day-name date))
         (day (cadr date))
         (day-of-week (calendar-day-of-week date))
         (month (car date))
         (monthname (calendar-month-name month))
         (year (nth 2 date))
         (iso-week (org-days-to-iso-week
                (calendar-absolute-from-gregorian date)))
         (weekyear (cond ((and (= month 1) (>= iso-week 52))
                  (1- year))
                 ((and (= month 12) (<= iso-week 1))
                  (1+ year))
                 (t year)))
         (weekstring (if (= day-of-week 1)
                 (format " W%02d" iso-week)
                   "")))
        (concat "\n" (make-string 50 9472) "\n"
                (format "%-10s %2d %s %4d%s    "
                        dayname day monthname year weekstring)
                )))
    (setq org-agenda-format-date 'pmg/org-agenda-format-date-aligned)
    
    ;; (setq org-icalendar-use-scheduled '(todo-start event-if-todo))
    
    ;;French holidays
    (setq french-holiday
          '((holiday-fixed 1 1 "Jour de l'an")
            (holiday-fixed 5 8 "Victoire 45")
            (holiday-fixed 7 14 "Fête nationale")
            (holiday-fixed 8 15 "Assomption")
            (holiday-fixed 11 1 "Toussaint")
            (holiday-fixed 11 11 "Armistice 18")
            (holiday-easter-etc 1 "Lundi de Pâques")
            (holiday-easter-etc 39 "Ascension")
            (holiday-easter-etc 50 "Lundi de Pentecôte")
            (holiday-fixed 1 6 "Épiphanie")
            (holiday-fixed 2 2 "Chandeleur")
            (holiday-fixed 2 14 "Saint Valentin")
            (holiday-fixed 5 1 "Fête du travail")
            (holiday-fixed 5 8 "Commémoration de la capitulation de l'Allemagne en 1945")
            (holiday-fixed 6 21 "Fête de la musique")
            (holiday-fixed 11 2 "Commémoration des fidèles défunts")
            (holiday-fixed 12 25 "Noël")
            ;; fêtes à date variable
            (holiday-easter-etc 0 "Pâques")
            (holiday-easter-etc 49 "Pentecôte")
            (holiday-easter-etc -47 "Mardi gras")
            (holiday-float 6 0 3 "Fête des pères") ;; troisième dimanche de juin
            ;; Fête des mères
            (holiday-sexp
             '(if (equal
                   ;; Pentecôte
                   (holiday-easter-etc 49)
                   ;; Dernier dimanche de mai
                   (holiday-float 5 0 -1 nil))
                  ;; -> Premier dimanche de juin si coïncidence
                  (car (car (holiday-float 6 0 1 nil)))
                ;; -> Dernier dimanche de mai sinon
                (car (car (holiday-float 5 0 -1 nil))))
             "Fête des mères")))
    
    (setq calendar-holidays (append french-holiday)
          calendar-mark-diary-entries-flag nil) ;calendar-mark-holidays-flag t
    
    ;; help
    (defun show-org-help ()
      (interactive)
      (message-box "
    ORG
    ---
    <f3>:\t\t\t export agenda to ICS
    <f4>:\t\t\t update todo
    <f5>:\t\t\t update category
    <f6>:\t\t\t update URL (C-c F6 to go)
    C-c <f10>:\t\t\t calendar
    <f9>:\t\t\t archive
    C-u C-c C-l:\t\t create file link
    C-S-mouse-1:\t open link in new frame / open mu4e mail
    "))
    
    (defun show-org-agenda-help ()
      (interactive)
      (message-box "
    AGENDA
    ------
    r:   refresh+export (R: refresh)
    b,f: dates before/after
    .:   today
    j:   jump
    "))
    
    
  2. Super-agenda
                                            ;(require 'org-super-agenda)
                                            ;(org-super-agenda-mode)
    (add-hook 'org-agenda-mode-hook
              (lambda ()
                      (local-set-key (kbd "r") 'org-agenda-redo-and-export)))
    (add-hook 'org-agenda-mode-hook
              (lambda ()
                      (local-set-key (kbd "R") 'org-agenda-redo-only)))
    (add-hook 'org-agenda-mode-hook
              (lambda ()
                      (local-set-key (kbd "C-<f1>") 'show-org-agenda-help)))
    
    ;; (progn
    ;;   ;; modify org keys
    ;;   (require 'org-super-agenda )
    ;;   (define-key org-agenda-mode-map (kbd "<C-f1>") 'show-org-agenda-help)
    ;;   (define-key org-agenda-mode-map (kbd "r") 'org-agenda-redo-and-export)
    ;;   (define-key org-agenda-mode-map (kbd "R") 'org-agenda-redo-only)
    ;;   (define-key org-super-agenda-header-map (kbd "<C-f1>") 'show-org-agenda-help)
    ;;   (define-key org-super-agenda-header-map (kbd "r") 'org-agenda-redo-and-export)
    ;;   (define-key org-super-agenda-header-map (kbd "R") 'org-agenda-redo-only)
    ;;   )
    
    (use-package org-super-agenda
      :defer t
      :init
      (org-super-agenda-mode)
    
      ;;Disable the super agenda header map.
      ;;don't do if using specific shortcuts
      (setq org-super-agenda-header-map nil)
    
      (setq org-agenda-block-separator ?\═) ;line
    
      (setq org-agenda-custom-commands
            '(("R" "Review"
               (
                (todo "ACTIVE!" ((org-agenda-overriding-header (concat "Active projects -- pending actions"))))
                (todo "WAITING" ((org-agenda-overriding-header (concat "Waiting items"))))
                (todo "HOLD!" ((org-agenda-overriding-header (concat "Projects on hold -- no pending actions"))))
                ;;(todo "STARTED" ((org-agenda-overriding-header (concat "ITEMS in progress"))))
                                            ;(agenda "" ((org-agenda-ndays 21))) ;; review upcoming deadlines and appointments
                                            ;                                 ;; type "l" in the agenda to review logged items 
                ;;(agenda "" ((org-super-agenda-groups '((:auto-group t)))) (org-agenda-list)) ;;(:auto-group t) (:name "Scheduled Today" :scheduled today)
                (agenda "" ((org-super-agenda-groups '(
                                                       (:name "⏰ Today               " :time-grid t) 
                                                       (:name "⭐⭐⭐  Due Today ⭐⭐⭐    " :deadline today :scheduled today) 
                                                       (:name "⇒ Due soon             " :deadline future) 
                                                       (:name "⚠ OVERDUE! ⚠           " :deadline past) 
                                                       (:name "⇒ Consider soon        " :scheduled future) 
                                                       (:name "⚠ Behind               " :and (:scheduled past :not (:category "catchup")))
                                                       (:name "⚠ Catchup              " :category "catchup") 
                                                       ))) 
                        (org-agenda nil "a")
                        )
                (todo "TODO" ((org-agenda-overriding-header (concat "All to-do ITEMS")))) ;; review waiting items 
                (todo "1DAY!" ((org-agenda-overriding-header (concat "Inactive projects"))))
                ;;(stuck "") ;; review stuck projects as designated by org-stuck-projects
                ;; ...other commands here
                )
               )
              ("P" "Projects"
               (
                (todo "ACTIVE!" ((org-agenda-overriding-header (concat "Active projects -- pending actions"))))
                (todo "WAITING" ((org-agenda-overriding-header (concat "Waiting items"))))
                (todo "HOLD!" ((org-agenda-overriding-header (concat "Projects on hold -- no pending actions"))))
                ;;(todo "STARTED" ((org-agenda-overriding-header (concat "ITEMS in progress"))))
                                            ;(agenda "" ((org-agenda-ndays 21))) ;; review upcoming deadlines and appointments
                                            ;                                 ;; type "l" in the agenda to review logged items 
                ;;(agenda "" ((org-super-agenda-groups '((:auto-group t)))) (org-agenda-list)) ;;(:auto-group t) (:name "Scheduled Today" :scheduled today)
                (todo "TODO" ((org-agenda-overriding-header (concat "All to-do ITEMS")))) ;; review waiting items 
                (todo "1DAY!" ((org-agenda-overriding-header (concat "Inactive projects"))))
                ;;(stuck "") ;; review stuck projects as designated by org-stuck-projects
                ;; ...other commands here
                )
               )
    
              ("A" "Agenda"
               (
                (agenda "" ((org-super-agenda-groups '(
                                                       (:name "⏰ Today              " :time-grid t) 
                                                       (:name "⭐⭐⭐ Due Today ⭐⭐⭐    " :deadline today :scheduled today) 
                                                       (:name "⇒ Due soon            " :deadline future) 
                                                       (:name "⚠ OVERDUE! ⚠          " :deadline past) 
                                                       (:name "⇒ Consider soon       " :scheduled future) 
                                                       (:name "⚠ Behind              " :and (:scheduled past :not (:category "catchup")))
                                                       (:name "⚠ Catchup             " :category "catchup") 
                                                       ))) 
                        (org-agenda nil "a")
                        )	  )
               )
    
    
              ))
      )
    
    
    
  3. Export/import
                                            ;export all agenda files?
    ;;(setq org-icalendar-combined-agenda-file "~/ownCloud/org/workflow.ics")
    ;;(global-set-key (kbd "<f4>") 'org-icalendar-combine-agenda-files)
    
    ;; export to icalendar
    (setq org-icalendar-include-todo t
          org-icalendar-use-deadline '(todo-start event-if-todo event-if-not-todo)
          org-icalendar-use-scheduled '(event-if-todo event-if-not-todo todo-start))
    (setq org-icalendar-include-sexp t)
    
    ;; ical2org
                                            ;(add-to-list 'load-path "~/.emacs.d/ical2org")
                                            ;(require 'ical2org)
    
    
                                            ;(setq org-export-async-init-file "~/try") :
                                            ;(require 'package)
                                            ;(setq package-enable-at-startup nil)
                                            ;(package-initialize)
                                            ;(require 'org) 
                                            ;(require 'ox)
                                            ;(require 'cl)  
    
    ;; fixes process "org-export-process" exited abnormally
    (require 'ox)
    (setq org-export-async-debug nil) 
    
    ;;
                                            ;(defun exportimportics2 ()
                                            ;  (interactive)
                                            ;  ;; export ORG calendars to ICS files
                                            ;  ;;(org-icalendar-export-to-ics t)
                                            ;  (org-icalendar-export-agenda-files)
                                            ;)
    
    ;;
    (defun exportimportics ()
      (interactive)
      ;; export ORG calendars to ICS files
      ;;(org-icalendar-export-to-ics t)
      (org-icalendar-export-agenda-files)
      ;;(run command)
      ;; import GCAL calendars
      (shell-command "/bin/bash ~/ownCloud/org/gcal/gcal2org.bash >& /dev/null ")
      ;; update makeics
      ;;(if at-cea
      ;;    ;(message-box "yep"))
      ;;    (shell-command "/local/home/xxx/miniconda3/bin/python ~/ownCloud/Python/Library/makeics.py >& /dev/null "))
      )
    
    ;; F2+F3
    (defun org-agenda-show-agenda-and-todo-and-exportimport ()
      (interactive)
      (exportimportics)
      (org-agenda-show-agenda-and-todo)
      )
    
    ;; redefine to export as well
    (defun org-agenda-redo-only ()
      (interactive)
      (org-agenda-to-appt)
      (org-agenda-redo t)
      ;;refresh cfw if needed
      (when (get-buffer "*cfw-calendar*")
        (switch-to-buffer-other-frame "*cfw-calendar*")
        (call-interactively 'cfw:refresh-calendar-buffer)
        ;(cfw-here)
        ;(cfw:refresh-calendar-buffer)
        )
      )
    ;; redefine to export as well
    (defun org-agenda-redo-only-nocfw ()
      (interactive)
      (org-agenda-to-appt)
      (org-agenda-redo t)
      )
    
    ;; redefine to export as well
    (defun org-agenda-redo-and-export ()
      (interactive)
      (org-agenda-to-appt)
      (org-agenda-redo t)
      (exportimportics)
      ;;refresh cfw if needed
      (when (get-buffer "*cfw-calendar*")
        (switch-to-buffer-other-frame "*cfw-calendar*")
        (call-interactively 'cfw:refresh-calendar-buffer)
        ;(cfw-here)
        ;(cfw:refresh-calendar-buffer)
        )
      )
    
    ;; Everyday at 12:05am (useful in case you keep Emacs always on)
    ;;(run-at-time "12:05am" (* 24 3600) 'org-agenda-redo-and-export) 
    
    
    
  4. Files
                                            ;(setq diary-file "~/ownCloud/org/diary")
    
    ;; important to show tags and todo in agenda
    ;;(setq org-agenda-files 
    ;;      (list "~/ownCloud/WorkingArea/todolist.org"))
                                            ;(setq org-agenda-files '("~/ownCloud/org"))
    (setq org-agenda-files '(
                             ;;"~/ownCloud/org/workflow.org" 
                             "~/ownCloud/org/diary.org" 
                             "~/ownCloud/org/recoltes.org" 
                             "~/ownCloud/org/routine.org" 
                             "~/ownCloud/org/gcal/nuages.org" 
                             "~/ownCloud/org/gcal/svy.org" 
                             "~/ownCloud/org/gcal/props.org" 
                                            ;"~/ownCloud/org/gcal/sflunch.org" 
                             "~/ownCloud/org/gcal/dapseminars.org" 
                             "~/ownCloud/org/notes/" 
                                            ;"~/ownCloud/org/gcal/gcal_main.org" 
                                            ;"~/ownCloud/WorkingArea/IRAM/reviews.org"
                                            ;"~/ownCloud/WorkingArea/ESO/reviews.org" 
                                            ;"~/ownCloud/org/dapseminars.org" 
                             ))
    
    (setq org-default-notes-file (concat org-directory "~/ownCloud/org/notes/bookmarks.org"))
                                            ;(define-key global-map "\C-cc" 'org-capture)
    
    
  5. Diary
    ;(setq view-diary-entries-initially t
    ;       mark-diary-entries-in-calendar t
    ;       number-of-diary-entries 7)
    ; (add-hook 'diary-display-hook 'fancy-diary-display)
    ; (add-hook 'today-visible-calendar-hook 'calendar-mark-today)
    
    ;(setq org-agenda-include-diary t)
    
    
  6. To-dos/checkboxes
    ;; todo
    ;; to get note when cancelled:      (quote ((sequence "TODO(t)" "STARTED(s)" "|" "DONE(d)" "CANCELLED(c@/!)")
    ;; @ logs, ! requires comment
                                            ;(setq org-todo-keywords
                                            ;      (quote ((sequence "TODO(t)" "STARTED(s)" "|" "DONE(d)" "WAITING(w)" "CANCELLED(c)")
                                            ;	      (sequence "ACTIVE!(A)" "ACTIVE(a)" "|" "HOLD(h)" "DONE!(d)" "CANCELLED!(c)")
                                            ;	      )))
    (setq org-todo-keywords
          (quote ((sequence "TODO(t)" "|" "DONE(d)" "WAITING(w)" "CANCELLED(c)")
                  (sequence "ACTIVE!(A)" "|" "HOLD!(h)" "1DAY!(l)" "DONE!(d)" "CANCELLED!(c)")
                  )))
    
    ;; ("NEXT" :foreground "purple" :background "#404040" :weight bold)
    (setq org-todo-keyword-faces
          (quote (("TODO" :foreground "green" :background "#404040" :weight bold)
                  ("DONE" :foreground "yellow" :background "#404040" :weight bold)
                  ("WAITING" :foreground "orange" :background "#404040" :weight bold)
                  ("CANCELLED" :foreground "black" :background "#404040" :weight bold)
                  ("ACTIVE!" :foreground "green" :background "#404040" :weight bold)
                  ("DONE!" :foreground "yellow" :background "#404040" :weight bold)
                  ("HOLD!" :foreground "purple" :background "#404040" :weight bold)
                  ("1DAY!" :foreground "black" :background "#404040" :weight bold)
                  ("CANCELLED!" :foreground "black" :background "#404040" :weight bold) )))
    
    ;; automatically updates status for checkboxes?
    ;;automatically update cookies ( [x/y] ) when saving
                                            ;problem is that it switches status then... (see above)
                                            ;(defun +org|update-cookies ()
                                            ;  "Update counts in headlines (aka \"cookies\")."
                                            ;  (when (and buffer-file-name (file-exists-p buffer-file-name))
                                            ;    (org-update-statistics-cookies t)))
                                            ;(add-hook 'before-save-hook #'+org|update-cookies)
    
    ;; automatically switches status for projects
                                            ;(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)
                                            ;		  "ACTIVE"
                                            ;		"ACTIVE!")
                                            ;	      )
                                            ;   ))
                                            ;(add-hook 'org-after-todo-statistics-hook 'org-summary-todo)
    
    

3.6.8 Org-capture

;;store org-mode links to messages
(add-to-list 'load-path "~/.emacs.d/mu/mu4e")
(require 'org-mu4e)

;;store link to message if in header view, not to header query. When you are in Headers view, M-x org-store-link links to the query if org-mu4e-link-query-in-headers-mode is non-nil, and to the particular message otherwise (which is the default).
(setq org-mu4e-link-query-in-headers-mode nil)

;; templates
(setq org-capture-templates
      '(
        ("r" "Todo-mail" entry (file+headline "~/ownCloud/org/notes/workflow.org" "Captured emails")
         "\n\n* TODO %:subject (from %:fromname) %?\nSCHEDULED: %(org-insert-time-stamp (org-read-date nil t \"+0d\"))\n%a\n")

        ;;("b" "Bookmark URL" entry (file+headline "~/ownCloud/org/notes/bookmarks.org" "Captured")
        ;; "\n\n* %?\n:PROPERTIES:\n:CREATED: %U\n:URL: http://\n:END:\n\n")

        ("B" "Bookmark clipboard URL" entry (file+headline "~/ownCloud/org/notes/bookmarks.org" "Captured")
         "\n\n* %?\n:PROPERTIES:\n:CREATED: %U\n:URL: %x\n:END:\n" :empty-lines 1)

        ("t" "To-do" entry (file+headline "~/ownCloud/org/notes/workflow.org" "Captured to-dos")
         "* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\nSCHEDULED: \nDEADLINE: \n" :empty-lines 1 :prepend t)

        ("T" "To-do clipboard" entry (file+headline "~/ownCloud/org/notes/workflow.org" "Captured to-dos")
         "* TODO %x\n:PROPERTIES:\n:CREATED: %U\n:END:\nSCHEDULED: \nDEADLINE: \n %?" :empty-lines 1 :prepend t)

        ("e" "Event" entry (file+headline "~/ownCloud/org/notes/events.org" "Capture events")
         "* %? %t--%t\n:PROPERTIES:\n:CREATED: %U\n:END:\n" :empty-lines 1 :prepend t)

        ("E" "Event clipboard" entry (file+headline "~/ownCloud/org/notes/events.org" "Captured events")
         "* %x %t--%t\n:PROPERTIES:\n:CREATED: %U\n:END:\n" :empty-lines 1 :prepend t)

))
;; https://orgmode.org/manual/Template-expansion.html
;;the extra %a adds a link to the file you are visiting when you invoke the capture template. 
;;;The beauty of this is that hitting C-c c t now generates a todo item that contains a link to the email you are currently viewing. So you have zero friction in creating a todo item to e.g. reply to an email by a certain deadline, and you can happily archive that email knowing that clicking the link in the todo item will take you directly back to it. 

;; function to capture a bookmark
(defun org-capture-bookmark ()
  (interactive)
  "Capture a bookmark item"
  (org-capture nil "b"))

;; function to capture a mail todo
(defun org-capture-todomail ()
  (interactive)
  "Capture a todo-mail item"
  (org-capture nil "r"))

;; bind
(define-key global-map "\C-cc" 'org-capture)
;;(define-key global-map "\C-cb" 'org-capture-bookmark)

                                        ;(define-key mu4e-headers-mode-map (kbd "C-c c") 'org-mu4e-store-and-capture)
                                        ;(define-key mu4e-view-mode-map    (kbd "C-c c") 'org-mu4e-store-and-capture)

3.6.9 Org-column

;; for wrap in org-columns
(defun wrap-fn () 
  (interactive) 
  (org-columns) 
  (setq truncate-lines nil word-wrap t)) 

(define-key (current-global-map) [remap org-columns] 'wrap-fn)

3.6.10 Bookmarks

3.6.11 Shortcuts

;; Shortcuts for showing bookmarks
(defun show-bookmarks ()
  (interactive)
  (find-file "~/ownCloud/org/notes/bookmarks.org"))
                                        ;(global-set-key "\C-cb" 'show-bookmarks)

3.7 Notes

3.7.1 org-noter

(use-package org-noter
  :defer t
  :after org
  :ensure t
  :config (setq org-noter-default-notes-file-names '("notes.org")
                org-noter-notes-search-path '("~/org/Research-Notes")
                org-noter-separate-notes-from-heading t))

3.7.2 Deft

(global-set-key (kbd "\C-cD") 'deft)

(global-set-key (kbd "\C-cd") 'deft-split)

(defun deft-split ()
  (interactive)
  (split-window-horizontally)
  (next-multiframe-window)
  (deft)
  )


(use-package deft
  :defer t
  :bind (:map deft-mode-map ("C-<f1>" . show-deft-help))
  :commands (deft)
  :config 

                                        ;(setq deft-extensions '("org" "txt" "tex"))
  (setq deft-text-mode 'org-mode)
  (setq deft-auto-save-interval 0) ;; don't automatically save, do it manually
  (setq deft-directory "~/ownCloud/org/notes/")
  (setq deft-recursive t)
                                        ;(setq deft-use-filename-as-title t) ;; rather than first line of file
  (setq deft-default-extension "org")
  (setq deft-extensions '("org" "txt" "tex"))

  (defun show-deft-help ()
    (interactive)
    (message-box "
  deft-bibtex
  -----------

  C-c C-n: new file
  C-c C-r: rename
  C-c C-d: delete
  C-c C-i: insert template
  "))
  )


                                        ;(defhydra hydra-deft 
                                        ;(:exit t) ;;exit right after
                                        ;   "deft"
                                        ;   ("n" deft-new-file "New file")
                                        ;   ("d" deft-delete-file "Delete file")
                                        ;   ("r" deft-rename-file "Rename")
                                        ;   ("q" nil "cancel" :color blue))


3.8 Files/file managers

3.8.1 General

;; replace find-files --> now using sidebar
;(global-set-key (kbd "C-x C-f") 'helm-find-files) 

;; enables yanking file names 
(defun insert-file-path (file &optional relativep)
  "Read file name and insert it at point.
With a prefix argument, insert only the non-directory part."
  (interactive "fFile: \nP")
  (when relativep (setq file  (file-name-nondirectory file)))
  (insert (file-truename file)))


(defun insert-file-name (file &optional relativep)
  "Read file name and insert it at point.
With a prefix argument, insert only the non-directory part."
  (interactive "fFile: \nP")
  (when relativep (setq file  (file-name-nondirectory file)))
  (insert (file-name-nondirectory file)))


(defun insert-file-directory (file &optional relativep)
  "Read file name and insert it at point.
With a prefix argument, insert only the non-directory part."
  (interactive "fFile: \nP")
  (when relativep (setq file  (file-name-nondirectory file)))
  (insert (file-name-as-directory file)))

;; hydra for current opened file actions
(global-set-key (kbd "\C-cf")
                (defhydra hydra-file 
                  (:exit t) ;;exit right after
                  "file"
                  ("yf" insert-file-name "Yank file name")
                  ("yd" insert-file-directory "Yank file directory")
                  ("yp" insert-file-path "Yank file path")
                  ("s" get-filesize "file size")
                  ("c" copy-file-name-to-clipboard "copy filename to clipboard")))

;; copy filename to clipboard
(defun copy-file-name-to-clipboard ()
  "Copy the current buffer file name to the clipboard."
  (interactive)
  (let ((filename (if (equal major-mode 'dired-mode)
                      default-directory
                    (buffer-file-name))))
    (when filename
      (kill-new filename)
      (message "Copied buffer file name '%s' to the clipboard." filename))))

3.8.2 File size

;; file size
(defun file-size-human-readable (file-size &optional flavor)
  "Produce a string showing FILE-SIZE in human-readable form.

Optional second argument FLAVOR controls the units and the display format:

 If FLAVOR is nil or omitted, each kilobyte is 1024 bytes and the produced
    suffixes are \"k\", \"M\", \"G\", \"T\", etc.
 If FLAVOR is `si', each kilobyte is 1000 bytes and the produced suffixes
    are \"k\", \"M\", \"G\", \"T\", etc.
 If FLAVOR is `iec', each kilobyte is 1024 bytes and the produced suffixes
    are \"KiB\", \"MiB\", \"GiB\", \"TiB\", etc."
  (let ((power (if (or (null flavor) (eq flavor 'iec))
                   1024.0
                 1000.0))
        (post-fixes
         ;; none, kilo, mega, giga, tera, peta, exa, zetta, yotta
         (list "" "k" "M" "G" "T" "P" "E" "Z" "Y")))
    (while (and (>= file-size power) (cdr post-fixes))
      (setq file-size (/ file-size power)
            post-fixes (cdr post-fixes)))
    (format "%.0f%s%s" file-size
            (if (and (eq flavor 'iec) (string= (car post-fixes) "k"))
                "K"
              (car post-fixes))
            (if (eq flavor 'iec) "iB" ""))))

;; file size
(defun get-filesize ()
  "Prompt user to enter a file name, with completion and history support."
  (interactive)
  (let* ((data (file-attributes (read-file-name "Enter file name:")))
         (d (nth 7 data)))
    (message "Size is %s" (file-size-human-readable d)))
  )

3.8.3 Neotree

;(require 'neotree)
;  (global-set-key [f2] 'neotree-toggle)

3.8.4 Dired

;; hydra for dired files
(defhydra hydra-files ()
  "files"
  ("h" dired-omit-switch "hidden")
  ("d" dired-hide-details-mode "details")
  ("l" locate "locate")
  ("f" find-alternate-file "find file")
  ("=" dired-equal "=")
  ("t" term-here "terminal")
  ("m" magit-status "magit")
  ("<tab>" dired-subtree-insert "+subtree")
  ("<backtab>" dired-subtree-remove "-subtree")
  ("<backspace>" dired-updirectory "up")
  ("q" nil "cancel" :color blue))

;; main
(use-package dired
  ;;:disabled
  :defer t
  :bind (:map dired-mode-map
              ("C-<f1>" . show-dired-help)
              ("<f7>" . hydra-files/body)
              ("<f2>" . dired-omit-switch)
              ("<f3>" . dired-hide-details-mode)
              ("<f4>" . locate)
              ("<f5>" . find-alternate-file)
              ("<f6>" . dired-equal)
              ("<f10>" . term-here) ;;#'term-here
              ("<f9>"  . magit-status)
              ("<tab>" . dired-subtree-insert)
              ("<backtab>" . dired-subtree-remove)
              ("<backspace>" . dired-up-directory)
              ("C-c C-a" . gnus-dired-attach)
              )
  :init

  ;; dired layout
  (defun dired-layout ()
    (interactive)
    (delete-other-windows)
    (dired launch-directory)
    )

  ;; dired layout
  (defun dired-layout2 ()
    (interactive)
    (delete-other-windows)
    (dired "~/WORK")
    (split-window-right)
    (dired launch-directory)
    )

  :config
  (require 'dired-subtree)
  (require 'dired-rainbow)
  (require 'dired-x)

  ;; If you want Emacs to automatically update a buffer if a file changes on disk,
  ;; auto refresh dired when file changes
  (add-hook 'dired-mode-hook 'auto-revert-mode)

  ;; If nil, don't ask whether to kill buffers visiting deleted files
  (setq dired-clean-confirm-killing-deleted-buffers nil)

  ;; get readable file sizes, dirs first
  (setq dired-listing-switches "-aBhl  --group-directories-first")

  ;; Hide details by default
                                        ;(defun dired-mode-setup ()
                                        ;  "to be run as hook for `dired-mode'."
                                        ;  (dired-hide-details-mode 1))
                                        ;(add-hook 'dired-mode-hook 'dired-mode-setup)

  ;;allow dired to delete or copy dir
  (setq dired-recursive-copies (quote always)) ; “always” means no asking
  (setq dired-recursive-deletes (quote top)) ; “top” means ask once

  ;;How to copy from one dired dir to the next dired dir shown in a split window
  (setq dired-dwim-target t)

  ;;toggle hidden files
  (setq dired-omit-files "^\\...+$")
  (add-hook 'dired-mode-hook (lambda () (dired-omit-mode 1)))

  ;;switch
  (defvar v-dired-omit t
    "If dired-omit-mode enabled by default. Don't setq me.")
  (defun dired-omit-switch ()
    "This function is a small enhancement for `dired-omit-mode', which will
   \"remember\" omit state across Dired buffers."
    (interactive)
    (if (eq v-dired-omit t)
        (setq v-dired-omit nil)
      (setq v-dired-omit t))
    (dired-omit-caller)
    (revert-buffer))
  (defun dired-omit-caller ()
    (if v-dired-omit
        (setq dired-omit-mode t)
      (setq dired-omit-mode nil)))
  (add-hook 'dired-mode-hook 'dired-omit-caller)

  ;; open with external application
  (defun open-in-external-app ()
    "Open the file where point is or the marked files in Dired in external
app. The app is chosen from your OS's preference."
    (interactive)
    (let* ((file-list
            (dired-get-marked-files)))
      (mapc
       (lambda (file-path)
         (let ((process-connection-type nil))
           (start-process "" nil "xdg-open" (shell-quote-argument file-path)))) file-list)))
  (define-key dired-mode-map (kbd "C-<return>") #'open-in-external-app)

  ;;don't try to docview following extensions (with mouse 1)
                                        ;(add-to-list 'auto-mode-alist '("\\.pdf\\'" . fundamental-mode))
  (add-to-list 'auto-mode-alist '("\\.dvi\\'" . fundamental-mode))
  (add-to-list 'auto-mode-alist '("\\.pptx\\'" . fundamental-mode))
  ;;better PDF handling?
  ;;(add-hook 'prog-mode-hook 'linum-on)

  ;; open terminal here
  ;;(defun term-here ()
  ;;  (interactive)
  ;;  (dired-smart-shell-command (concat "terminator --working-directory=\"$PWD\"") nil nil))
  (defun term-here ()
    (multi-term-dedicated))

  ;; have the same on both panels
  (defun dired-equal ()
    (interactive)
    (find-file (dired-dwim-target-directory))
    )

  ;; Lets you copy huge files and directories without Emacs freezing up and with convenient progress bar updates. That is all.
;;;###autoload
  (defun dired-rsync (dest)
    (interactive
     (list
      (expand-file-name
       (read-file-name
        "Rsync to:"
        (dired-dwim-target-directory)))))
    ;; store all selected files into "files" list
    (let ((files (dired-get-marked-files
                  nil current-prefix-arg))
          ;; the rsync command
          (tmtxt/rsync-command
           "rsync -arvz --progress "))
      ;; add all selected file names as arguments
      ;; to the rsync command
      (dolist (file files)
        (setq tmtxt/rsync-command
              (concat tmtxt/rsync-command
                      (shell-quote-argument file)
                      " ")))
      ;; append the destination
      (setq tmtxt/rsync-command
            (concat tmtxt/rsync-command
                    (shell-quote-argument dest)))
      ;; run the async shell command
      (async-shell-command tmtxt/rsync-command "*rsync*")
      ;; finally, switch to that window
      ;; (other-window 1)
      ;; (kill-buffer "*rsync*")
      (switch-to-buffer-other-window "*rsync*")
      ;;(previous-multiframe-window)
      ))
  (define-key dired-mode-map "Y" 'dired-rsync)

  ;; open in new frame
  (defun dired-find-file-other-frame ()
    "In Dired, visit this file or directory in another window."
    (interactive)
    (find-file-other-frame (dired-get-file-for-visit)))
  (eval-after-load "dired"
    '(define-key dired-mode-map (kbd "<C-S-mouse-1>") 'dired-find-file-other-frame))

  ;; colors for extensions
  (defconst my-dired-image-files-extensions
    '("png" "jpg" "jpeg" "tiff" "bmp" "gif" )
    "Image files.")
  (defconst my-dired-media-files-extensions
    '("mp3" "mp4" "MP3" "MP4" "avi" "mpg" "flv" "ogg" "mkv" "mov" "MOV" "webm" "m4a" "wav" )
    "Media files.")
  (defconst my-dired-prog-files-extensions
    '("py" "ipynb" "pro" "php" "c" "f" "f90" "css" "js" )
    "Program files.")
  (defconst my-dired-archive-files-extensions
    '("zip" "tar.gz" "tar" "7z" "rar" "tar.xz" )
    "Program files.")
  (defconst my-dired-docs-files-extensions
    '("pdf" "doc" "docx" "odp" "docx" "ppt" "pptx" )
    "Program files.")
  (defconst my-dired-ebooks-files-extensions
    '("mobi" "epub" )
    "Program files.")
  (dired-rainbow-define docs "#FFFF00" my-dired-docs-files-extensions)
  (dired-rainbow-define docs "#AAFF00" my-dired-docs-files-extensions)
  (dired-rainbow-define image "#99CCFF" my-dired-image-files-extensions)
  (dired-rainbow-define media "#6699FF" my-dired-media-files-extensions)
  (dired-rainbow-define prog "#FF6666" my-dired-prog-files-extensions)
  (dired-rainbow-define archive "#FF3300" my-dired-archive-files-extensions)

                                        ; highlight executable files, but not directories
  (dired-rainbow-define-chmod executable-unix "#999966" "-[rw-]+x.*")

  ;; help
  (defun show-dired-help ()
    (interactive)
    (message-box "
DIRED
-----
<C-x,d>:  go to directory
<s>:      toggle alphabetical/date
<f2>:     toggle dot files
<f3>:     toggle details
<f4>:     locate (use * first if using wildcard in name)
<f5>:     jump to location
<f6>:      =
<f6>:     Hydra
<f10>:    terminal here
<f9>:     magit status (s: stage, cc + C-c C-c: commit, P u: push, F u: pull)
!:        launch shell command on file (& async)
R:        rename
Y:        rsync
g:        refresh
o:        quick view
C-S-mouse1: open in new frame
C-RET:    open externally
C-c C-a:  attach to mu4e buffer
C-0 w:    clipboard copy location
(S)TAB:   subtree
<backspace>: parent directory
"))


  )

3.8.5 Ranger

;; main
(use-package ranger
  :disabled
  :defer t
  :bind (:map ranger-mode-map
              ("C-<f1>" . show-ranger-help)
              )
  :init

  ;;default file manager
  (ranger-override-dired-mode t)

  ;;When disabling/closing the ranger session, then you can choose to kill the buffers that were opened while browsing the directories.
  (setq ranger-cleanup-on-disable t)
  ;; Or you can choose to kill the buffers, after you move to another entry in the dired buffer.
  (setq ranger-cleanup-eagerly t)

  ;;To show hidden files when ranger starts,
                                        ;(setq ranger-show-hidden t)

  ;;panels
  (setq ranger-parent-depth 2)

  ;;previews
  (setq ranger-preview-file nil)
  (setq ranger-max-preview-size 10) ;;Mb
  (setq ranger-dont-show-binary t)
  (setq ranger-excluded-extensions '("mkv" "iso" "mp4"))

  ;; help
  (defun show-ranger-help ()
    (interactive)
    (message-box "
RANGER
-----
<arrows>:\t navigate
<i>:\t toggle preview panel
<;C>:\t copy (yy: mark)
<R>:\t move/rename (dd: mark)
<pp>:\t paste (po: and override, p?: show copy content)
<D>:\t delete
<;+>:\t create directory
<;=>:\t diff current file with...
<;d>:\t mark for deletion (;x: delete)
<zh>:\t toggle hidden files
<gh>:\t home
<du>:\t du
<!>:\t\t\t launch shell command on file (;& async)
<z-+>:\t add/remove panels
<we>:\t open externally
"))
  )

3.8.6 Images

(defun asciiview (imagefile)
  ;; use asciiview (part of aatools) to render image file as text to buffer
  (interactive "fChoose image file: ")
  (save-excursion
    (with-current-buffer (pop-to-buffer (format "*asciiview %s*" imagefile))
      (insert
       (car (last (butlast
                   (split-string
                    (shell-command-to-string
                     (format
                      "echo q | asciiview -driver stdout -kbddriver stdin %s 2>/dev/null"
                      (shell-quote-argument imagefile)))
                    "^L")))))
      (view-mode))))

3.8.7 Sidebar

(add-to-list 'load-path "~/.local/share/icons-in-terminal/") ;; If it's not already done
(add-to-list 'load-path "~/.emacs.d/sidebar.el/")
(add-to-list 'load-path "~/.emacs.d/font-lock-plus/")
(add-to-list 'load-path "~/.emacs.d/frame-local/")
(require 'sidebar)
(global-set-key (kbd "C-x C-f") 'sidebar-open)
(global-set-key (kbd "C-x C-a") 'sidebar-buffers-open)

(setq sidebar-mu4e-autostart nil) ;;do not start sidebar automatically


3.9 Programming

  • emacs-lisp-mode-hook lisp-mode-hook python-mode-hook php-mode-hook c-mode-hook cc-mode-hook c++-mode-hook java-mode-hook perl-mode-hook sh-mode-hook fortran-mode-hook f90-mode-hook xml-mode-hook latex-mode-hook html-mode-hook css-mode-hook web-mode-hook js-mode-hook R-mode-hook

3.9.1 Misc.

(if (version<= "26.0.50" emacs-version )
    (add-hook 'prog-mode-hook 'display-line-numbers-mode) ;only for programming ;(global-linum-mode t) freezes docview
  (add-hook 'prog-mode-hook 'linum-mode) ;only for programming ;(global-linum-mode t) freezes docview
  )

3.9.2 Hide/show

(defun toggle-selective-display (column)
  (interactive "P")
  (set-selective-display
   (or column
       (unless selective-display
         (1+ (current-column))))))

(defun toggle-hiding (column)
  (interactive "P")
  (if hs-minor-mode
      (if (condition-case nil
              (hs-toggle-hiding)
            (error t))
          (hs-show-all))
    (toggle-selective-display column)))
(load-library "hideshow")

3.9.3 Elpy

  • ensure: pip install jedi flake8 importmagic autopep8 yapf
  • in ~/.config/flake8:

[flake8] max-line-length = 999 ignore = W291,W293,E265,E303,E226,W391,E225,E231,E251,E302,E305,E261,E262,E201,E202 max-complexity = 10

(use-package elpy
  :defer t
  :bind (:map elpy-mode-map
              ("C-<f1>" . show-elpy-help)
              ("<f2>" . elpy-shell-switch-to-shell)
              ("C-<f2>" . elpy-shell-switch-to-shell-below)
              ("<f3>" . elpy-shell-send-statement)
              ("<f4>" . elpy-shell-send-region-or-buffer)
              ("C-<tab>" . toggle-hiding)
              )
  :hook (elpy-mode . hs-minor-mode)
                                        ;(add-hook 'elpy-mode-hook   'hs-minor-mode)
  :init
  ;; elpy layout

  (defun elpy-layout ()
    (interactive)
    (delete-other-windows)
    (find-file "~/ownCloud/Python/Library")
    (elpy-shell-switch-to-shell)
    (previous-multiframe-window)
    (split-window-vertically) 
    (dired launch-directory)
                                        ;(split-window-vertically (floor (* 0.75 (window-height))))
                                        ;(dired "~/")
                                        ;(split-window-right)
                                        ;(find-file "~/ownCloud/Python/Library")
    )

  (elpy-enable)
  :config

  ;;guess indent?
  (setq python-indent-guess-indent-offset t)  
  (setq python-indent-guess-indent-offset-verbose nil)

  (setq python-shell-interpreter "ipython3"
        python-shell-interpreter-args "--simple-prompt --pprint") ;;Since IPython 5 it has a new terminal interface, which is not compatible with Emacs’ inferior shells. To fix it, add the --simple-prompt flag to the IPython command:



  ;;
  (setenv "JUPYTER_CONSOLE_TEST" "1")
  (add-to-list 'python-shell-completion-native-disabled-interpreters "ipython3")
  (add-to-list 'python-shell-completion-native-disabled-interpreters "jupyter")

  (setq
   python-shell-prompt-detect-enabled nil
   python-shell-interpreter "jupyter"
   python-shell-interpreter-args "console"
   )
  ;; 

  ;; 
  (setq elpy-shell-send-region-or-buffer 0)
  (setq elpy-shell-switch-to-shell 0)

  ;;use %matplotlib

  ;;indent with highlight-indent-guides
  (add-hook 'elpy-mode-hook (lambda () (highlight-indentation-mode -1)))

  ;; use flycheck not flymake with elpy
  (when (require 'flycheck nil t)
    (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
    (add-hook 'elpy-mode-hook 'flycheck-mode))

                                        ;remove flycheck and flymake
                                        ;(setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
                                        ;(setq elpy-modules (delq 'elpy-module-flycheck elpy-modules))

                                        ;(setq python-shell-interpreter "jupyter"
                                        ;      python-shell-interpreter-args "console --simple-prompt") ;;Since IPython 5 it has a new terminal interface, which is not compatible with Emacs’ inferior shells. To fix it, add the --simple-prompt flag to the IPython command:


                                        ;(setq python-shell-prompt-detect-failure-warning nil)
                                        ;(setq python-shell-prompt-detect-enabled nil)
                                        ;(elpy-use-ipython)

  (defun elpy-shell-switch-to-shell-below ()
    (interactive)
    (split-window-vertically (floor (* 0.75 (window-height))))
    (previous-multiframe-window)
    (elpy-shell-switch-to-shell-in-current-window)
    (previous-multiframe-window)
    (delete-window)
    )


  ;; help
  (defun show-elpy-help ()
    (interactive)
    (message-box "
ELPY
----
<f2>:       run interpreter
<f3>:       eval statement
<f4>:       eval region
<C-RET>:    eval statement & step
<C-arrows>: navigate interpreter
<M-arrows>: indent blocks
<C-c C-o>:  outline
<C-TAB>:    toggle show/hide

EIN
---
py & C-f7:    insert block snippet
M-x ein:run : launch ein
<C-c C-o>:    open dir
<C-x C-s>:    save
<C-x C-w>:    rename
<C-c C-a>:    insert cell above
<C-c C-b>:    insert cell below
<C-c C-k>:    kill cell
<C-c C-c>:    execute
<M-RET>  :    execute and next cell
<CM-arrows>:  move
"))

  )

3.9.4 PHP/HTML

;;syntax coloring
;; ## sudo apt-get install php-elisp

(use-package php-mode
  :defer t
  )

(use-package web-mode
  :defer t
  :init
  (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.tpl\\.php\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
  (add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode)))

3.9.5 Indent

(use-package highlight-indent-guides
  :hook
  (python-mode . highlight-indent-guides-mode)
  :custom
  (highlight-indent-guides-method 'character)
  (highlight-indent-guides-responsive 'top)
  (highlight-indent-guides-delay 0)
  )
(add-hook 'prog-mode-hook 'highlight-indent-guides-mode)


;; indent automatically and live

                                        ;(add-hook 'emacs-lisp-mode-hook #'aggressive-indent-mode)
                                        ;(add-hook 'css-mode-hook #'aggressive-indent-mode)

                                        ;(global-aggressive-indent-mode 1)
                                        ;(add-to-list 'aggressive-indent-excluded-modes 'html-mode)

(use-package aggressive-indent
  :preface
  (defun me/aggressive-indent-mode-off ()
    (aggressive-indent-mode 0))
  :hook
  ((css-mode . aggressive-indent-mode)
   (emacs-lisp-mode . aggressive-indent-mode)
   (js-mode . aggressive-indent-mode)
   (lisp-mode . aggressive-indent-mode)
   (sgml-mode . aggressive-indent-mode))
  :custom
  (aggressive-indent-comments-too t)
  :config
  (add-to-list 'aggressive-indent-protected-commands 'comment-dwim))

3.9.6 DISABLED ob-ipython

                                        ;pip install --upgrade pip
                                        ;pip install --upgrade ipython (possibly pip install ipython==6.5.0 to avoid problems with prompt-toolkit)
                                        ;pip install --upgrade pyzmq
                                        ;pip install --upgrade jupyter

                                        ;install ob-ipython package

;;https://github.com/gregsexton/ob-ipython

(use-package ob-python
                                        ;:ensure t
  :config
  ;; Org-babel
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (lisp . t)
                                        ;(fortran . t)
                                        ;(C . t)
                                        ;(shell . t)
     ;;(http . t)
                                        ;(latex . t)
                                        ;(ipython . t) ;;Enabling it makes org-capture fail, see https://github.com/syl20bnr/spacemacs/issues/9941
     ))
  (setq org-confirm-babel-evaluate nil)  ;don't prompt me to confirm everytime I want to evaluate a block
  (add-hook 'org-babel-after-execute-hook 'org-display-inline-images 'append);;; display/update images in the buffer after I evaluate
  )

;; use package python-mode causes issues
                                        ;(setq python-shell-interpreter "ipython3"
                                        ;      python-shell-interpreter-args  "--simple-prompt -i"
                                        ;      python-indent-offset 4) ;;Since IPython 5 it has a new terminal interface, which is not compatible with Emacs’ inferior shells. To fix it, add the --simple-prompt flag to the IPython command:



;;   :session mysession :results raw drawer :exports both #:ipyfile /tmp/image.png #:async t

;;%matplotlib inline 

;; yasnippet
                                        ;# -*- mode: snippet -*-
                                        ;# name: ipython block
                                        ;# key: py
                                        ;# --
                                        ;#+BEGIN_SRC ipython :session ${1::ipyfile ${2:$$(let ((temporary-file-directory "./")) (make-temp-file "py" nil ".png"))} }:exports ;${3:both}
                                        ;$0
                                        ;#+END_SRC

;; or 
                                        ;#+BEGIN_SRC ipython :session :exports both :results raw drawer
                                        ;  $0
                                        ;#+END_SRC

;;(ob-ipython-kill-kernel)



3.9.7 ein

;;(setq abbrev-file-name '')

(use-package ein
  :defer t
  :config
  ;; Org-babel ;;in config otherwise slows down regular python file
  (org-babel-do-load-languages
   'org-babel-load-languages
   '( 
     (ein . t)
                                        ;(emacs-lisp . t)
                                        ;(lisp . t)
                                        ;(fortran . t)
                                        ;(C . t)
                                        ;(shell . t)
     ;;(http . t)
                                        ;(latex . t)
                                        ;(ipython . t) ;;Enabling it makes org-capture fail, see https://github.com/syl20bnr/spacemacs/issues/9941
     ))
  )

3.10 bibtex

3.10.1 bibtex

;; 2007
;; vianney xxx
;; phdthesis xxx
;; eye.?tracking
;; 2010 and 2011: \(2010\|2011\)
;; article xxx kunth
;; article caplan !kunth

;; actions
                                        ;(helm-add-action-to-source
                                        ; "Open annotated PDF (if present)" 'helm-bibtex-open-annotated-pdf
                                        ; helm-source-bibtex 1)

;; helm-bibtex
(use-package helm-bibtex
  :defer t
  :bind (:map helm-map ("C-<f1>" . show-helm-bibtex-help))
  :init
  ;;helm-bibtex
  (setq bibtex-completion-bibliography '("~/ownCloud/bibtexendum/bibtexendum.bib"))
  (setq bibtex-completion-notes-path "~/ownCloud/bibtexendum/bibtexendum_notes.org") ;; use directory if one per publication (setq bibtex-completion-notes-path "/path/to/notes") (setq bibtex-completion-notes-extension ".org")

  ;;PDFs
  (setq bibtex-completion-library-path '("~/ownCloud/bibtexendum/PDFLibrary/"))
  (setq bibtex-completion-pdf-field "File")

  ;; searching
  ;; default fields used for searching are: author, title, year, BibTeX key, entry type (article, inproceedings, …)
  (setq bibtex-completion-additional-search-fields '(firstauthor tags))

  ;; available pdf or notes
  (setq bibtex-completion-pdf-symbol "⌘")
  (setq bibtex-completion-notes-symbol "✎")

  (setq bibtex-completion-display-formats
        '((article       . "${=has-pdf=:1}${=has-note=:1}| ${=type=:3}| ${year:4}| ${author:25}| ${title:*} ")
          (inbook        . "${=has-pdf=:1}${=has-note=:1}| ${=type=:3}| ${year:4}| ${author:25}| ${title:*} ")
          (incollection  . "${=has-pdf=:1}${=has-note=:1}| ${=type=:3}| ${year:4}| ${author:25}| ${title:*} ")
          (inproceedings . "${=has-pdf=:1}${=has-note=:1}| ${=type=:3}| ${year:4}| ${author:25}| ${title:*} ")
          (t             . "${=has-pdf=:1}${=has-note=:1}| ${=type=:3}| ${year:4}| ${author:25}| ${title:*}")))

  (defun helm-bibtex-my-publications (&optional arg)
    "Search BibTeX entries authored by “Jane Doe”.
  With a prefix ARG, the cache is invalidated and the bibliography reread."
    (interactive "P")
    (helm-bibtex arg nil "xxx"))
  ;; Bind this search function to Ctrl-x p:
  (global-set-key (kbd "C-x p") 'helm-bibtex-my-publications)

  (global-set-key (kbd "C-x B") 'helm-bibtex)
  (global-set-key (kbd "C-x r") 'helm-resume)


  (defun show-helm-bibtex-help ()
    (interactive)
    (message-box "
helm-bibtex
-----------

C-SPACE: mark
TAB: actions 
ENTER: default action
helm-resume
"))
  )

3.10.2 Bibtexendum

                                        ;(defun run-bibtexendum (args)
                                        ;  (interactive "sInput arguments (e.g., -a xxxx.yyyy): ")
                                        ;  (eshell)
                                        ;  (with-current-buffer "*eshell*"
                                        ;    (message "Arguments: %s" args)
                                        ;    (eshell-return-to-prompt)
                                        ;    (insert "cd ~/ownCloud/bibtexendum/")
                                        ;    (eshell-send-input)
                                        ;    (insert (concat "python bibtexendum.py " args))
                                        ;    (eshell-send-input))
                                        ;  )


(defun multi-term-bibtexendum2 (args);
  ;(interactive)
                                        ;(defun multi-term-bibtexendum (args);
  (interactive "sInput argument(s) (e.g., -a xxxx.yyyy): ")
  (multi-term-dedicated-open)
  (with-current-buffer "*MULTI-TERM-DEDICATED*"
    (toggle-read-only)
    (insert (concat "\cd ~/ownCloud/bibtexendum; python bibtexendum.py " args)) 
    (term-send-input)
    ))

(defun multi-term-bibtexendum ();
  ;(interactive)
                                        ;(defun multi-term-bibtexendum (args);
  ;;(interactive "sInput argument(s) (e.g., -a xxxx.yyyy): ")
  (multi-term-dedicated-open)
  (with-current-buffer "*MULTI-TERM-DEDICATED*"
    (toggle-read-only)
    (insert (concat "\cd ~/ownCloud/bibtexendum; python bibtexendum.py " (read-string "Input argument(s) (e.g., -a xxxx.yyyy): "))) 
                                        ;(insert (concat "python bibtexendum.py " args) 
    (term-send-input)
    ))

;;(defun multi-term-foo ()
;;  (interactive)
;;  "Make a multi-term buffer running foo."
;;  (let ((multi-term-program (concat "\cd ~/ownCloud/bibtexendum; python bibtexendum.py " (read-string "Input argument(s) (e.g., -a xxxx.yyyy): "))))
;;    (multi-term)))

;; Shortcuts for bibtexendum
(global-set-key "\C-cx" 'multi-term-bibtexendum2)

;; shortcuts emacs keeps for itself
;; remove C-zxc
(defcustom term-unbind-key-list
  '("C-x" "C-c" "C-h" "C-y" "<ESC>")
  "The key list that will need to be unbind."
  :type 'list
  :group 'multi-term)

3.11 Functions

3.11.1 Location

;; check if we're at CEA or not (e.g., for mu4e contexts)
(defun process-exit-code-and-output (program &rest args)
  "Run PROGRAM with ARGS and return the exit code and output in a list."
  (with-temp-buffer 
    (list (apply 'call-process program nil (current-buffer) nil args)
          (buffer-string))))

;;more /usr/bin/hostalive 
;;#!/bin/bash
;;echo `nmap -Pn -p 22 T5 $1 | grep -c -e "filtered" -e "0 hosts up"` 
(defun check-if-at-CEA ()
  (interactive)
  (string= "1" (substring (format "%s" (process-exit-code-and-output "hostalive_ssh" "xxx.fr")) 3 4))
  )
(add-hook 'mu4e-default-hook
          (progn
            (setq at-cea (string= "1" (substring (format "%s" (process-exit-code-and-output "hostalive_ssh" "xxx.fr")) 3 4)) ))
          (if at-cea
              (message "@CEA")
            (message "not @CEA"))
          )

3.11.2 Strings

;;match strings in list and inversely
(defun xah-string-match-in-list-p (@str @list-of-string @match-case-p &optional @reverse-contain-p)
  "If @str occur in list @list-of-string, return true (the first element), else nil.
if @reverse-contain-p is true, change the direction of match. That is, true if any element in @list-of-string occur in @str.
@match-case-p determines whether case is literal for the match.
No regex is used.
Existing match data is changed. Wrap it with `save-match-data' if you need it restored.
URL `http://ergoemacs.org/emacs/elisp_string_match_in_list.html'
Version 2016-07-18"
  (let ((case-fold-search (not @match-case-p)))
    (if @reverse-contain-p
        (catch 'tag
          (mapc
           (lambda ($x)
             (when (string-match (regexp-quote $x) @str ) (throw 'tag $x)))
           @list-of-string)
          nil)
      (catch 'tag
        (mapc
         (lambda ($x)
           (when (string-match (regexp-quote @str) $x ) (throw 'tag $x)))
         @list-of-string)
        nil))))

;;get list of keys
(defun alist-keys (alist)
  (mapcar 'car alist))

3.12 Specific packages

3.12.1 Undo

                                        ;(setq undo-limit 500) ;that's in bytes

;; undo-tree
(use-package undo-tree
  :defer t
  :diminish undo-tree-mode
  :config
  (progn
    (global-undo-tree-mode)
    (setq undo-tree-visualizer-timestamps t)
    (setq undo-tree-visualizer-diff t)))

3.12.2 Magit


(use-package magit
  :defer t
  :bind (:map magit-mode-map
              ("C-<f1>" . show-magit-help))
  :bind (:map magit-hunk-section-map
              ("RET" . magit-diff-visit-file-other-window)
              ([return] . magit-diff-visit-file-other-window))
  :custom
  (magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
  (magit-diff-highlight-hunk-body nil)
  (magit-diff-highlight-hunk-region-functions
   '(magit-diff-highlight-hunk-region-dim-outside magit-diff-highlight-hunk-region-using-face))
  (magit-popup-display-buffer-action '((display-buffer-same-window)))
  (magit-refs-show-commit-count 'all)
  (magit-section-show-child-count t)
  :config
  (magit-section-cycle-diffs) ;; do it once to collapse everything
  (remove-hook 'magit-section-highlight-hook #'magit-section-highlight)
  ;; help
  (defun show-magit-help ()
    (interactive)
    (message-box "
MAGIT
-----
s/u:     stage/unstage
cc:      commit
C-c C-c: accept commit
Pu:      push
Fu:      pull 
"))
  )
(global-set-key (kbd "C-x g") 'magit-status)

3.13 Calendar/weather

3.13.1 Weather

;; based on emacs-wttrin
;;alias wtr='curl -s wttr.in/orsay?3qFm & curl -s wttr.in/{orsay,champfleur,northridge}?format="%l:+%c+(%C),%h,%t,%m,%w,%p,%P" '
(require 'url)

(defgroup wtr nil
  "Emacs frontend for weather web service wttr.in."
  :prefix "wtr-"
  :group 'comm)

(defcustom wtr-default-cities '("orsay" "champfleur" "northridge")
  "Specify default cities list for quick completion."
  :group 'wtr
  :type 'list)

(defcustom wtr-default-accept-language '("Accept-Language" . "en-US,en;fr-FR,fr")
  "Specify default HTTP request Header for Accept-Language."
  :group 'wtr
  :type '(list)
  )

(defun wtr-fetch-raw-string (query)
  "Get the weather information based on your QUERY."
  (let ((url-request-extra-headers '(("User-Agent" . "curl"))))
    (add-to-list 'url-request-extra-headers wtr-default-accept-language)
    (with-current-buffer
        (url-retrieve-synchronously
         (concat "http://wttr.in/" query "?m3qFT")
         (lambda (status) (switch-to-buffer (current-buffer))))
      (decode-coding-string (buffer-string) 'utf-8))))

(defun wtr-fetch-raw-string2 (query)
  "Get the weather information based on your QUERY."
  (let ((url-request-extra-headers '(("User-Agent" . "curl"))))
    (add-to-list 'url-request-extra-headers wtr-default-accept-language)
    (with-current-buffer
        (url-retrieve-synchronously
         (concat "http://wttr.in/" query "?format=\"%l:+%c+(%C), %h, %t, %m, %w, %p, %P&m\"") 
         (lambda (status) (switch-to-buffer (current-buffer))))
      (decode-coding-string (buffer-string) 'utf-8))))

(defun wtr-fetch-raw-string3 ()
  "Get the weather information based on your QUERY."
  (let ((url-request-extra-headers '(("User-Agent" . "curl"))))
    (add-to-list 'url-request-extra-headers wtr-default-accept-language)
    (with-current-buffer
        (url-retrieve-synchronously "http://wttr.in/moon?m3qFT") 
      (lambda (status) (switch-to-buffer (current-buffer)))
      (decode-coding-string (buffer-string) 'utf-8))))

(defun wtr-exit ()
  (interactive)
  (quit-window t))

(defun wtr-query (city-name)
  "Query weather of CITY-NAME via wtr, and display the result in new buffer."
  (let ((raw-string (wtr-fetch-raw-string city-name))
        (raw-string2 (wtr-fetch-raw-string2 city-name))
        (raw-string3 (wtr-fetch-raw-string3)))
    (if (string-match "ERROR" raw-string)
        (message "Cannot get weather data. Maybe you inputed a wrong city name?")
      (let ((buffer (get-buffer-create (format "*wttr.in - %s*" city-name))))
        (switch-to-buffer buffer)
        (setq buffer-read-only nil)
        (erase-buffer)

        (insert (propertize raw-string3 'face `(:family "Monospace")))
        (goto-char (point-min))
        (re-search-forward "^$")
        (delete-region (point-min) (1+ (point)))

        (insert (propertize raw-string 'face `(:family "Monospace")))
        (goto-char (point-min))
        (re-search-forward "^$")
        (delete-region (point-min) (1+ (point)))

        (insert (concat (propertize raw-string2 'face `(:family "Monospace")) "\n"))
        (goto-char (point-min))
        (re-search-forward "^$")
        (delete-region (point-min) (1+ (point)))

        (insert (concat "\n" (sunrise-sunset) "\n" "\n"))

        (use-local-map (make-sparse-keymap))
        (local-set-key "q" 'wtr-exit)
        (local-set-key "g" 'wtr)
        (setq buffer-read-only t)))))

;;;###autoload
(defun wtr (city)
  "Display weather information for CITY."
  (interactive
   (list
    (completing-read "City name: " wtr-default-cities nil nil
                     (when (= (length wtr-default-cities) 1)
                       (car wtr-default-cities)))))

  ;; check lat/lon ;; latlong.net
  (if (string= city "orsay")
      (progn (setq calendar-latitude 48.699010)
             (setq calendar-longitude 2.187860)
             (setq calendar-location-name "Orsay, France")))

  (if (string= city "champfleur")
      (progn (setq calendar-latitude 48.386670)
             (setq calendar-longitude 0.125470)
             (setq calendar-location-name "Champfleur, France")))

  (if (string= city "northridge")
      (progn (setq calendar-latitude 34.288471)
             (setq calendar-longitude -118.478394)
             (setq calendar-location-name "Northridge, CA, US")))

  (wtr-query city))

(provide 'wtr)

3.13.2 Timezones


;;calendar timezones
(set-time-zone-rule "CET")
(setq org-icalendar-timezone "CET")

;; timezones
;;https://github.com/emacs-mirror/emacs/blob/master/lisp/timezone.el
(makunbound 'display-time-world-list)
(defvar display-time-world-list
  `( ("UT" "UT")
     ("America/New_York" "New York")
     ("America/Los_Angeles" "Los Angeles")
     ("Europe/Paris" "Paris")
     ))
;; (setq display-time-world-time-format "[%Z] %a %d %b %R")
;;(global-set-key "\C-ct" 'display-time-world-list)


(defun worldtime-exit ()
  (interactive)
                                        ;(quit-window t)
  (delete-window))

(defun my-worldtime-display ()
  (interactive)
  (display-time-world)
  (next-multiframe-window)
  (delete-window)
  ;;
                                        ;(split-window-below)
  (split-window-vertically (floor (* 0.85 (window-height))))
  (next-multiframe-window)
  (switch-to-buffer "*wclock*")
  (local-set-key "q" 'worldtime-exit)
                                        ;(previous-multiframe-window)
  )
(global-set-key "\C-cT" 'my-worldtime-display)

3.13.3 Calendar

(use-package calfw
  :defer 1
  :bind ((:map cfw:calendar-mode-map
               ("C-<f1>" . show-cfw-help)
               ("r" . cfw-refresh)
         ))
  :init
  (require 'calfw-org)
  (require 'calfw-ical)
  (setq cfw:org-overwrite-default-keybinding t)
  ;;(toggle-frame-maximized)
  ;;(set-frame-parameter nil 'fullscreen 'maximized)

  :config
  ;; Month
  (setq calendar-month-name-array
        ["January" "February" "March"     "April"   "May"      "June"
         "July"    "August"   "September" "October" "November" "December"])
  ;; Week days
  (setq calendar-day-name-array
        ["Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday"])
  ;; First day of the week
  (setq calendar-week-start-day 1) ; 0:Sunday, 1:Monday

  (custom-set-faces
   '(cfw:face-title ((t (:foreground "#f0dfaf" :weight bold :height 2.0 :inherit variable-pitch))))
   ;;weekdays
   '(cfw:face-header ((t (:foreground "#cc9393" :background "black" :weight bold))))
   '(cfw:face-sunday ((t :foreground "#d0bf8f" :background "black" :weight bold)))
   '(cfw:face-saturday ((t :foreground "#d0bf8f" :background "black" :weight bold)))
   ;;
   '(cfw:face-holiday ((t :background "#808080" :foreground "#505090" :weight bold)))
   ;;
   '(cfw:face-grid ((t :foreground "#808080")))
   ;;
   '(cfw:face-default-content ((t :foreground "#bfebbf")))
   '(cfw:face-periods ((t :foreground "white")))
   ;;day number
   '(cfw:face-day-title ((t :background "grey10")))
   '(cfw:face-default-day ((t :weight bold :inherit cfw:face-day-title)))
   '(cfw:face-annotation ((t :foreground "RosyBrown" :inherit cfw:face-day-title)))
   '(cfw:face-disable ((t :foreground "DarkGray" :inherit cfw:face-day-title)))
   '(cfw:face-today-title ((t :background "#104020" :weight bold)))
   '(cfw:face-today ((t :background: "#505050" :weight bold)))
   '(cfw:face-select ((t :background "#505070")))
   '(cfw:face-toolbar ((t :foreground "Steelblue4" :background "black")))
   '(cfw:face-toolbar-button-off ((t :foreground "Gray10" :background "white" :weight bold)))
   '(cfw:face-toolbar-button-on ((t :foreground "Gray50" :background "white":weight bold))))

;; Default setting
(setq cfw:fchar-junction ?+
      cfw:fchar-vertical-line ?|
      cfw:fchar-horizontal-line ?-
      cfw:fchar-left-junction ?+
      cfw:fchar-right-junction ?+
      cfw:fchar-top-junction ?+
      cfw:fchar-top-left-corner ?+
      cfw:fchar-top-right-corner ?+ )
)

;; Calendar view for org-agenda.
  (with-eval-after-load "calfw-org"
    ;; Remove some strings (tags and filenames) from item summary.
    (defun cfw:org-summary-format (item)
      "Format an item (How should it be displayed?)."
      (let* ((time (cfw:org-tp item 'time))
             (time-of-day (cfw:org-tp item 'time-of-day))
             (time-str (and time-of-day
                            (format "%02i:%02i "
                                    (/ time-of-day 100)
                                    (% time-of-day 100))))
             (category (cfw:org-tp item 'org-category))
             (tags (cfw:org-tp item 'tags))
             (marker (cfw:org-tp item 'org-marker))
             (buffer (and marker (marker-buffer marker)))
             (text (cfw:org-extract-summary item))
             (props (cfw:extract-text-props item 'face 'keymap)))
        (propertize
         (concat
          (if time-str (apply 'propertize time-str props)) text " "
          ;; (and buffer (buffer-name buffer))
          )
         'keymap cfw:org-text-keymap
         ;; Delete the display property, since displaying images will break our
         ;; table layout.
         'display nil))))


;(require 'org-gcal)
;(setq org-gcal-client-id ".apps.googleusercontent.com"
;      org-gcal-client-secret "your-secret"
;      org-gcal-file-alist '(("your-mail@xxx.com" .  "~/ownCloud/org/gcal2org/schedule.org")
;                            ("another-mail@xxx.com" .  "~/ownCloud/org/gcal2org/task.org")))

(defun cfw-refresh ()
  (interactive)
  (call-interactively 'cfw:refresh-calendar-buffer)
  (when (get-buffer "*Org Agenda(A)*")
    (switch-to-buffer-other-frame "*Org Agenda(A)*")
    (org-agenda-redo-only-nocfw))
  )

(defun cfw-here ()
  (interactive)
(let ((buf (get-buffer "*cfw-calendar*")))
    (if buf
        (pop-to-buffer buf nil)
      (cfw:open-calendar-buffer
       :contents-sources
       (list
        (cfw:org-create-source "#F0F020")
             )
       :view 'two-weeks)
      ))
)
(defun cfw ()
  (interactive)
  (select-frame (make-frame))
  (delete-other-windows)
  (let ((buf (get-buffer "*cfw-calendar*")))
    (if buf
        (pop-to-buffer buf nil)
      (cfw:open-calendar-buffer
       :contents-sources
       (list
        (cfw:org-create-source "#F0F020")
             )
       :view 'two-weeks)
      ))
)

      ;; (cfw:org-create-file-source "Success" my-success-cal "#baffc9")
      ;; (cfw:org-create-file-source "Success Atom" my-success-atom-cal "#E3FFE9")
      ;; (cfw:org-create-file-source "Moment" my-moment-cal "#bae1ff")
      ;; (cfw:org-create-file-source "Target" my-target-cal "#40e0d0")
      ;; (cfw:org-create-file-source "Hevent" my-hevent-cal "#ffb3ba"))))


;(use-package calfw-gcal
;:ensure t
;:config
;(require 'calfw-gcal))

;; (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.
;;  '(cfw:face-annotation ((t :foreground "RosyBrown" :inherit cfw:face-day-title)))
;;  '(cfw:face-day-title ((t :background "grey10")))
;;  '(cfw:face-default-content ((t :foreground "#bfebbf")))
;;  '(cfw:face-default-day ((t :weight bold :inherit cfw:face-day-title)))
;;  '(cfw:face-disable ((t :foreground "DarkGray" :inherit cfw:face-day-title)))
;;  '(cfw:face-grid ((t :foreground "DarkGrey")))
;;  '(cfw:face-header ((t (:foreground "#d0bf8f" :weight bold))))
;;  '(cfw:face-holiday ((t :background "grey10" :foreground "#8c5353" :weight bold)))
;;  '(cfw:face-periods ((t :foreground "cyan")))
;;  '(cfw:face-saturday ((t :foreground "#8cd0d3" :background "grey10" :weight bold)))
;;  '(cfw:face-select ((t :background "yellow" :foreground "black")))
;;  '(cfw:face-sunday ((t :foreground "#cc9393" :background "grey10" :weight bold)))
;;  '(cfw:face-title ((t (:foreground "#f0dfaf" :weight bold :height 2.0 :inherit variable-pitch))))
;;  '(cfw:face-today ((t :background: "Gray" :weight bold)))
;;  '(cfw:face-today-title ((t :background "#7f9f7f" :weight bold)))
;;  '(cfw:face-toolbar ((t :foreground "Steelblue4" :background "Steelblue4")))
;;  '(cfw:face-toolbar-button-off ((t :foreground "White" :weight bold)))
;;  '(cfw:face-toolbar-button-on ((t :foreground "Gray" :weight bold)))
;;  )

;;(defun use-cfw-font ()
;;  (interactive)
;;  "Switch the current buffer to a monospace font."
;;  (face-remap-add-relative 'default '(:family "Ubuntu Mono" :height 80))
;;  (add-hook 'cfw:calendar-mode-hook 'use-cfw-font))

;;fix to avoid multiple ranges
(defun cfw:org-get-timerange (text)
  "Return a range object (begin end text).
If TEXT does not have a range, return nil."
  (let* ((dotime (cfw:org-tp text 'dotime)))
    (and (stringp dotime) (string-match org-ts-regexp dotime)
     (let* ((matches  (s-match-strings-all org-ts-regexp dotime))
           (start-date (nth 1 (car matches)))
           (end-date (nth 1 (nth 1 matches)))
           (extra (cfw:org-tp text 'extra)))
       (if (string-match "(\\([0-9]+\\)/\\([0-9]+\\)): " extra)
       ( list( calendar-gregorian-from-absolute
       (time-to-days
       (org-read-date nil t start-date))
       )
       (calendar-gregorian-from-absolute
       (time-to-days
       (org-read-date nil t end-date))) text)
       )))))

;(defun my--cfw:open-calendar-buffer-view (orig-func &rest args &allow-other-keys)
;  (apply orig-func :view 'two-weeks :allow-other-keys t args)
;  )
;(advice-add 'cfw:open-calendar-buffer :around #'my--cfw:open-calendar-buffer-view)

(defun show-cfw-help ()
    (interactive)
    (message-box "
CALFW
-----

g:         goto date
r:         refresh
k:         capture
x:         close all
t:         today
D,T,W,M:   day, 2-weeks, week, month view
<SPACE>  : popup detail buffer
"))

3.14 Mail

3.14.1 mu4e

  1. Comments

    Now when I check my emails, I do one of the following

    • delete if it is rubbish
    • read and delete if it is not something I’ll need to revisit
    • read and archive if it is something I might need to look up again
    • reply and archive if it is something that will take less than a couple of minutes to reply to and I have the time
    • add to todo list and archive if it is something that requires an action or just needs a longer reply than I have time to write

    New install:

    • install from git (https://github.com/djcb/mu)
    • ./configure and make
    • mu init –maildir ~/.mail –my-address=x@y –my-address=x2@y2 mu info
    • mu index

    Troubleshooting:

    • mu index –maildir=~/.mail
    • This message might appear “database needs update; try ‘mu index –rebuild and mu index’
    • mu4e error in process sentinel: Database is locked by another process: killall mu

    manual sync

    • mbsync xxx

    Watch out: mbsync must use the IMAP folder names in Xxx and the latter are regionalized! Use US names… When comparing counts in mbsync and Xxx, remember that Xxx can be setup to count conversations or messages

    gpg password in tmp file make sure .gnupg is not owned by root gpg2 –output .mbsyncpass.gpg –symmetric pass use in .mbsynrc: PassCmd "gpg2 -q –for-your-eyes-only –no-tty -d ~/.mbsyncpass.gpg" \rm tmp file!

    even better: create .authinfo.gpg: first create tmp file with: machine imap.xxx.com login xxx@xxx.com password MYPASSWORD machine smtp.xxx.com login xxx@xxx.com password MYPASSWORD then gpg2 –output ~/.authinfo.gpg –symmetric ~/.authinfo in .mbsynrc PassCmd "gpg2 -q –for-your-eyes-only –no-tty -d ~/.authinfo.gpg | awk 'machine imap.xxx.com login xxx@xxx.com {print $NF}'"

  2. General configuration
    ;; first view: just unread inboxes
    (defun init-mu4e-headers ()
      "Like `mu4e' but show the header view.
    Default to unread messages if the header buffer does not already exist."
      (interactive)
      (mu4e~start)
      (mu4e-update-mail-and-index 0) ;;t is to run in background
      (if (get-buffer "*mu4e-headers*" )
          (switch-to-buffer "*mu4e-headers*")
        (mu4e-headers-search "(maildir:/xxx/Inbox or maildir:/xxx/Inbox or maildir:/cnrs/Inbox) AND flag:unread")))
    
    
    (setq mu4e-mu-binary "~/.emacs.d/mu/mu/mu")
    
    ;; MU4E
    ;;(add-to-list 'load-path "~/.emacs.d/mu/mu4e") ;; already done for org-mu4e
    (use-package mu4e
      :defer t
      :config
    
      ;; emacs allows you to select an e-mail program as the default program it uses when you press C-x m (compose-mail), call report-emacs-bug and so on. If you want to use mu4e for this, you do so by adding the following to your configuration:
      (setq mail-user-agent 'mu4e-user-agent)
    
      ;; don't keep message buffers around
      (setq message-kill-buffer-on-exit t)
    
      ;; no need to confirm
      (setq mu4e-confirm-quit nil)
    
      ;; single window mode
                                            ;(setq mu4e-split-view 'single-window) 
    
      ;;mu4e buffers have a leading space...
      ;;" *mu4e-main"
      )
    
  3. Addresses
    (use-package mu4e
      :defer t
      :config
      ;; general emacs mail settings; used when composing e-mail
      ;; the non-mu4e-* stuff is inherited from emacs/message-mode
      ;; later redefined in contexts
      (setq user-mail-address "xxx.xxx@xxx.fr" ;;cannot be nil for export to HTML (org)
            user-full-name "xxx xxx") ;;cannot be nil for export to HTML (org)
    
      ;; To determine whether a message was sent by you, mu4e uses the variable mu4e-user-mail-address-list, a list of your e-mail addresses.
      ;;not used in mu4e 1.4, need to set mu init --maildir=~/.mail --my-address=ad1 --my-address=ad2 ...
      ;;(setq mu4e-user-mail-address-list '("xxx.xxx@xxx.fr" "xxx@xxx.com" "xxx.xxx@xxx.com" "xxx.xxx@xxx.fr"))
    
      ;;mail aliases for lists (address lists)
      (setq mail-personal-alias-file (expand-file-name "~/ownCloud/org/mailing-lists"))
      )
    
  4. Getting mail
    (use-package mu4e
      :defer t
      :config
      ;; get mail
      (setq mu4e-get-mail-command "/usr/bin/mbsync -aV" ;-a ~/.mbsyncrc" ;;-c ~/.mbsyncrc xxx" ;;use U in main view to update
            ;;(setq mu4e-get-mail-command "/usr/bin/offlineimap -o" ;-a ~/.mbsyncrc" ;;-c ~/.mbsyncrc xxx" ;;use U in main view to update
            ;;w3m -dump -T text/html -cols 72 -o display_link_number=true -o auto_image=false -o display_image=false -o ignore_null_img_alt=true"
            ;;w3m-command "/usr/bin/w3m"
            mu4e-update-interval 300 ;;every xxx sec
            mu4e-headers-auto-update t
            mu4e-view-prefer-html t
            )
    
      ;;You can then get your e-mail using M-x mu4e-update-mail-and-index, or C-S-u in all mu4e-views; alternatively, you can use C-c C-u, which may be more convenient if you use emacs in a terminal.
      ;;You can kill the (foreground) update process with q.
    
      ;; faster indexing
                                            ;(setq
                                            ;  mu4e-index-cleanup nil      ;; don't do a full cleanup check
                                            ;  mu4e-index-lazy-check t)    ;; don't consider up-to-date dirs
      )
    
    
  5. Folders
    (use-package mu4e
      :defer t
      :config
      ;; defaults
      (setq mu4e-attachment-dir "~/Downloads") ;;no slash
      ;;mu4e-maildir (expand-file-name "~/.mail") obsolete, set by mu init
      ;;(setq mu4e-maildir (expand-file-name "/media/DATA/Mail"))
      ;; /!!!\ ln -s "/media/DATA/Mail" .mail
    
    
      ;; these are modified in the contexts
      (setq mu4e-trash-folder nil ;; must be configured later by context
            mu4e-drafts-folder nil ;; must be configured later by context
            mu4e-sent-folder nil ;; must be configured later by context
            mu4e-compose-reply-to-address nil ;; must be configured later by context
            mu4e-compose-signature nil ;; must be configured later by context
            )
                                            ;(setq mu4e-sent-folder   "/xxx/[Xxx].SentMail")
                                            ;(setq mu4e-drafts-folder "/xxx/[Xxx].Drafts")
                                            ;(setq mu4e-trash-folder  "/xxx/[Xxx].Trash")
    
      ;;rename files when moving
      ;;NEEDED FOR MBSYNC
      (setq mu4e-change-filenames-when-moving t)
    
      )
    
  6. Attachments
    (setq mu4e-save-multiple-attachments-without-asking t)
    
    ;; attach files fom dired
    ;; need a special version of the gnus-dired-mail-buffers function so it understands mu4e buffers as well
    (require 'gnus-dired)
    ;; make the `gnus-dired-mail-buffers' function also work on
    ;; message-mode derived modes, such as mu4e-compose-mode
    (defun gnus-dired-mail-buffers ()
      "Return a list of active message buffers."
      (let (buffers)
        (save-current-buffer
          (dolist (buffer (buffer-list t))
            (set-buffer buffer)
            (when (and (derived-mode-p 'message-mode)
                       (null message-sent-message-via))
              (push (buffer-name buffer) buffers))))
        (nreverse buffers)))
    
    (setq gnus-dired-mail-mode 'mu4e-user-agent)
    (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
    ;; in dired: C-c RET C-a
    
  7. Bookmarks, shortcuts
    (use-package mu4e
      :defer t
      :config
    
      ;; shortcuts
      ;; you can quickly switch to your Inbox -- press ``ji''
      ;; then, when you want archive some messages, move them to
      ;; the 'All Mail' folder by pressing ``ma''.
      ;; (setq mu4e-maildir-shortcuts
      ;;       '( ("/xxx/Inbox"                    . ?I)
      ;;          ;;("/xxx/XxxOnly"                . ?G)
      ;;          ("/xxx/[Xxx].SentMail"  . ?S)
      ;;          ("/xxx/[Xxx].Trash"      . ?T)
      ;;          ("/xxx/[Xxx].Drafts"     . ?D)
      ;;          ("/xxx/Inbox"                    . ?i)
      ;;          ("/xxx/[Xxx].SentMail"  . ?s)
      ;;          ("/xxx/[Xxx].Trash"      . ?t)
      ;;          ("/xxx/[Xxx].Drafts"     . ?d)
      ;;          ))
    
    (setq mu4e-maildir-shortcuts
        '((:maildir "/xxx/Inbox" :key ?I)
          (:maildir "/xxx/[Xxx].SentMail"   :key ?S)
          (:maildir "/xxx/[Xxx].Trash"   :key ?T)
          (:maildir "/xxx/[Xxx].Drafts"   :key ?D)
          (:maildir "/xxx/Inbox" :key ?i)
          (:maildir "/xxx/[Xxx].SentMail"   :key ?s)
          (:maildir "/xxx/[Xxx].Trash"   :key ?t)
          (:maildir "/xxx/[Xxx].Drafts"   :key ?d)
    ))
    
    
      ;;j-i 	jump to `inbox’
      ;;j-s 	jump to `sent’
      ;;? mark as unread
      ;;! mark as read
      ;;D delete, d trash
      ;;u remove mark, U remove all marks
      ;;x execute
      ;;R reply
      ;;C-c C-c send / C-c C-k abort
    
      )
    
  8. Search
    (use-package mu4e
      :defer t
      :config
    
      ;;redefine header search
      (defun mu4e-headers-search (&optional expr prompt edit
                                            ignore-history msgid show)
        "Search in the mu database for EXPR, and switch to the output
    buffer for the results. This is an interactive function which ask
    user for EXPR. PROMPT, if non-nil, is the prompt used by this
    function (default is \"Search for:\"). If EDIT is non-nil,
    instead of executing the query for EXPR, let the user edit the
    query before executing it. If IGNORE-HISTORY is true, do *not*
    update the query history stack. If MSGID is non-nil, attempt to
    move point to the first message with that message-id after
    searching. If SHOW is non-nil, show the message with MSGID."
        ;; note: we don't want to update the history if this query comes from
        ;; `mu4e~headers-query-next' or `mu4e~headers-query-prev'."
        (interactive)
        (let* ((prompt (mu4e-format (or prompt "Search for: ")))
               (expr
                (if edit
                    (read-string prompt expr)
                  (or expr
                      (read-string prompt nil 'mu4e~headers-search-hist)))))
          (mu4e-mark-handle-when-leaving)
    
          ;; change dest:
          (setq regex1 "\\(dest:\\([^\s]+\\)\\)")
          (setq expr (replace-regexp-in-string regex1 "(to:\\2 OR cc:\\2)" expr nil nil 1))
          ;;(message-box expr)
    
          (mu4e~headers-search-execute expr ignore-history)
          (setq mu4e~headers-msgid-target msgid
                mu4e~headers-view-target show)))
                                            ;))
      ;; (tocc:([^\s]+))
      ;; \(tocc:\([^\s]+\)\)
      ;; \1\,(caca)
    
      ;; unbind default bookmarks
      (makunbound 'mu4e-bookmarks)
                                            ;(fmakunbound 'mu4e-bookmarks)
      (defvar mu4e-bookmarks
        `( ,(make-mu4e-bookmark
             :name  "Unread @Work (CEA, CNRS)"
             :query "(maildir:/xxx/Inbox OR maildir:/cnrs/Inbox) AND flag:unread"
             :key ?u)))
    
      ;; CEA bookmarks
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Today @Work (CEA, CNRS)"
                    :query "(maildir:/xxx/Inbox OR maildir:/cnrs/Inbox) AND date:today..now"
                    :key ?t)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Last 7 days @Work (CEA, CNRS)"
                    :query "(maildir:/xxx/Inbox OR maildir:/cnrs/Inbox) AND date:7d..now"
                    :key ?w)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Inbox @Work (CEA, CNRS)"
                    :query "(maildir:/xxx/Inbox OR maildir:/cnrs/Inbox)"
                    :key ?i)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "w/ attachment @Work (CEA, CNRS)"
                    :query "(maildir:/xxx/Inbox OR maildir:/cnrs/Inbox) AND flag:attach"
                    :key ?a)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Big messages @Work (CEA, CNRS)"
                    :query "(maildir:/xxx/Inbox OR maildir:/cnrs/Inbox) AND size:5M..500M"
                    :key ?b)  )
    
      ;; Xxx
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Unread @Xxx"
                    :query "maildir:/xxx/Inbox AND flag:unread"
                    :key ?U)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Today @Xxx"
                    :query "maildir:/xxx/Inbox AND date:today..now"
                    :key ?T)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Last 7 days @Xxx"
                    :query "maildir:/xxx/Inbox AND date:7d..now"
                    :key ?W)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Inbox @Xxx"
                    :query "maildir:/xxx/Inbox"
                    :key ?I)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "w/ attachment @Xxx"
                    :query "maildir:/xxx/Inbox AND flag:attach"
                    :key ?A)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Big messages @Xxx"
                    :query "maildir:/xxx/Inbox AND size:5M..500M"
                    :key ?B)  )
    
      ;; potential spams
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "SPAM? recent with unsubscribe"
                    :query "NOT cc:(xxx* OR xxx OR xxx) AND NOT to:(xxx* OR xxx) AND NOT from:(xxx* OR xxx OR xxx) AND NOT (astro OR cnrs) AND NOT body:(xxx OR xxx) AND date:1y..now AND body:unsubscribe"
                    :key ?s)  )
      (add-to-list 'mu4e-bookmarks
                   (make-mu4e-bookmark
                    :name  "Remove attachments from old sent mail?"
                    :query "date:20000101..31d AND flag:attach AND from:(xxx OR xxx) AND size:1M..500M"
                    :key ?R)  )
    
    
      ;; Get all messages regarding bananas:
      ;;          bananas
    
      ;; Get all messages regarding bananas from John with an attachment:
      ;;          from:john and flag:attach and bananas
    
      ;; Get all messages with subject wombat in June 2017
      ;;          subject:wombat and date:20170601..20170630
    
      ;; Get all messages with PDF attachments in the /projects folder
      ;;          maildir:/projects and mime:application/pdf
    
      ;; Get all messages about Rupert in the /Sent Items folder. Note that maildirs with spaces must be quoted.
      ;;          "maildir:/Sent Items" and rupert
    
      ;; Get all important messages which are signed:
      ;;          flag:signed and prio:high
    
      ;; Get all messages from Jim without an attachment:
      ;;          from:jim and not flag:attach
    
      ;; Get all messages with Alice in one of the contacts-fields (to, from, cc, bcc):
      ;;          contact:alice
    
      ;; Get all unread messages where the subject mentions Ångström: (search is case-insensitive and accent-insensitive, so this matches Ångström, angstrom, aNGstrøM, ...)
      ;;          subject:Ångström and flag:unread
    
      ;; Get all unread messages between Mar-2012 and Aug-2013 about some bird:
      ;;          date:20120301..20130831 and nightingale and flag:unread
    
      ;; Get today’s messages:
      ;;          date:today..now
    
      ;; Get all messages we got in the last two weeks regarding emacs:
      ;;          date:2w.. and emacs
    
      ;; Get messages from the Mu mailing list:
      ;;          list:mu-discuss.googlegroups.com
      ;; Note — in the Headers view you may see the ‘friendly name’ for a list; however, when searching you need the real name. You can see the real name for a mailing list from the friendly name’s tool-tip.
    
      ;; Get messages with a subject soccer, Socrates, society, ...; note that the ‘*’-wildcard can only appear as a term’s rightmost character:
      ;;          subject:soc*
    
      ;; Get all messages not sent to a mailing-list:
      ;;          NOT flag:list
    
      ;; Get all mails with attachments with filenames starting with pic; note that the ‘*’ wildcard can only appear as the term’s rightmost character:
      ;;          file:pic*
    
      ;; Get all messages with PDF-attachments:
      ;;          mime:application/pdf
    
      ;; Get all messages with image attachments, and note that the ‘*’ wildcard can only appear as the term’s rightmost character:
      ;;          mime:image/*
    
    
      )
    
  9. Compose
    (use-package mu4e
      :defer t
      :config
      ;; list of contacts
      ;;in shell: mu cfind
    
      ;; allows reading other emails while composing
      (setq mu4e-compose-in-new-frame t)
    
      ;; please don't ever include me when I reply...
      (setq mu4e-compose-dont-reply-to-self t)
    
      ;; signature
      (setq message-signature-file "~/ownCloud/org/signature.txt") ; put your signature in this file
    
      ;;mu4e-compose-signature-auto-include nil
    
      ;; don't save message to Sent Messages, IMAP takes care of this
      (setq mu4e-sent-messages-behavior 'delete) ;set in contexts
    
      ;; citation
      (setq message-citation-line-format "%a %d %b %Y à %R, %n a écrit:\n"
            message-citation-line-function 'message-insert-formatted-citation-line)
    
      ;; spell check
      (add-hook 'mu4e-compose-mode-hook
                (defun my-do-compose-stuff ()
                  "My settings for message composition."
                  (set-fill-column 72)
                  (flyspell-mode)))
    
      ;; when set to t, only consider addresses that were seen in personal messages — that is, messages in which one of my e-mail addresses (mu4e-user-mail-address-list) was seen in one of the address fields. This is to exclude mailing list posts.
      ;;(setq mu4e-compose-complete-only-personal t) ;;somehow removes everything... maybe wait till full sync is done?
    
      ;; warn if no attachments
      (defun message-attachment-present-p ()
        "Return t if an attachment is found in the current message."
        (save-excursion
          (save-restriction
            (widen)
            (goto-char (point-min))
            (when (search-forward "<#part" nil t) t))))
      (defcustom message-attachment-intent-re
        (regexp-opt '("attach"
                      "attached"
                      "joint"
                      "joins"
                      "PDF"
                      "attachment"))
        "A regex which - if found in the message, and if there is no
    attachment - should launch the no-attachment warning.")
      (defcustom message-attachment-reminder
        "Are you sure you want to send this message without any attachment? "
        "The default question asked when trying to send a message
    containing `message-attachment-intent-re' without an
    actual attachment.")
      (defun message-warn-if-no-attachments ()
        "Ask the user if s?he wants to send the message even though
    there are no attachments."
        (when (and (save-excursion
                     (save-restriction
                       (widen)
                       (goto-char (point-min))
                       (re-search-forward message-attachment-intent-re nil t)))
                   (not (message-attachment-present-p)))
          (unless (y-or-n-p message-attachment-reminder)
            (keyboard-quit))))
      ;; add hook to message-send-hook (so also works with gnus)
      (add-hook 'message-send-hook #'message-warn-if-no-attachments)
    
    
      ;; It is possible to attach files to mu4e messages (using dired in the same frame process...)
      ;; mark the file(s) in dired you would like to attach and press C-c RET C-a, and you’ll be asked whether to attach them to an existing message, or create a new one.
      (require 'gnus-dired)
      ;; make the `gnus-dired-mail-buffers' function also work on
      ;; message-mode derived modes, such as mu4e-compose-mode
      (defun gnus-dired-mail-buffers ()
        "Return a list of active message buffers."
        (let (buffers)
          (save-current-buffer
            (dolist (buffer (buffer-list t))
              (set-buffer buffer)
              (when (and (derived-mode-p 'message-mode)
                         (null message-sent-message-via))
                (push (buffer-name buffer) buffers))))
          (nreverse buffers)))
      (setq gnus-dired-mail-mode 'mu4e-user-agent)
      (add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
    
      ;; highlight some words
      ;; http://emacs-fu.blogspot.co.uk/2008/12/highlighting-todo-fixme-and-friends.html
      (set-face-attribute 'font-lock-warning-face nil :foreground "red" :weight 'bold :background "yellow")
      (add-hook 'mu4e-compose-mode-hook
                (defun mu4e-highlight-words ()
                  "Flag attachment keywords"
                  (font-lock-add-keywords nil
                                          '(("\\(urgent\\|xxx\\|attach\\)" 1 font-lock-warning-face t)))))
    
      ;; remove automatic wrapping of lines
      (add-hook 'mu4e-compose-mode-hook 'turn-off-auto-fill)
      )
    
  10. Faces/appearance
    (use-package mu4e
      :defer t
      :config
    
      ;; display is definitely nicer with these
      (setq mu4e-use-fancy-chars t)
    
      ;;line spacing, especially for header view
      (defun set-bigger-spacing ()
        (setq-local default-text-properties '(line-spacing 0.25 line-height 1.25)))
      (defun set-big-spacing ()
        (setq-local default-text-properties '(line-spacing 0.2 line-height 1.1)))
      (add-hook 'mu4e-default-hook 'set-bigger-spacing)
      (add-hook 'mu4e-mode-hook 'set-bigger-spacing)
      (add-hook 'mu4e-view-mode-hook 'set-big-spacing)
      (add-hook 'mu4e-compose-mode-hook 'set-big-spacing)
      (add-hook 'mu4e-headers-mode-hook 'set-bigger-spacing)
    
      ;; default faces (may be overridden with header filter, see below)
      (set-face-attribute 'mu4e-header-face nil :height 100)
      (set-face-attribute 'mu4e-draft-face nil :height 100)
      (set-face-attribute 'mu4e-flagged-face nil :height 100)
      (set-face-attribute 'mu4e-forwarded-face nil :height 100)
      (set-face-attribute 'mu4e-moved-face nil :height 100)
      (set-face-attribute 'mu4e-trashed-face nil :height 100)
    
      (set-face-attribute 'mu4e-unread-face nil :height 100 :background "#000" :underline t :foreground "#FFF")
    
      (set-face-attribute 'mu4e-replied-face nil :height 100 :background "#444" :foreground "#FFF") ;;:slant 'italic 
    
      (set-face-attribute 'mu4e-forwarded-face nil :height 100 :foreground "#222" :foreground "#FFF") ;;:slant 'italic 
    
      (set-face-attribute 'mu4e-flagged-face nil :height 100 :foreground "#888" :foreground "#FFF")
    
                                            ;(set-face-attribute 'mu4e-cited-1-face nil :slant 'italic)
                                            ;(set-face-attribute 'mu4e-cited-2-face nil :slant 'italic)
                                            ;(set-face-attribute 'mu4e-cited-3-face nil :slant 'italic)
                                            ;(set-face-attribute 'mu4e-cited-4-face nil :slant 'italic)
                                            ;(set-face-attribute 'mu4e-cited-5-face nil :slant 'italic)
                                            ;(set-face-attribute 'mu4e-cited-6-face nil :slant 'italic)
                                            ;(set-face-attribute 'mu4e-cited-7-face nil :slant 'italic)
    
                                            ;+mu4e-basic-face           ;;Face defining the starting point for the rest of mu4e
                                            ;MESSAGE LIST         ;; (inherits from mu4e-basic-face)
                                            ;mu4e-unread-face        ;;Face for an unread message header.
                                            ;+mu4e-read-face            ;;Face for an read message header (it is not specified, or the basic face?)
                                            ;mu4e-draft-face                ;;Face for a draft message header, i.e. a message with the draft flag set.
                                            ;mu4e-flagged-face        ;;Face for a flagged message header.
                                            ;mu4e-forwarded-face        ;;Face for a passed (forwarded) message header.
                                            ;mu4e-moved-face                ;;Face for a message header that has been moved to some folder.
                                            ;mu4e-replied-face        ;;Face for a replied message header.
                                            ;mu4e-trashed-face        ;;Face for an message header in the trash folder.
    
    
                                            ;READ/WRITE         ;; (inherits from mu4e-basic-face)
                                            ;mu4e-contact-face        ;;Face for showing URLs and attachments in the message view.
                                            ;mu4e-compose-header-face    ;;Face for the separator between headers / message in mu4e-compose-mode.
                                            ;mu4e-compose-separator-face    ;;Face for the separator between headers / message in mu4e-compose-mode.
                                            ;mu4e-link-face                ;;Face for showing URLs and attachments in the message view.
                                            ;mu4e-url-number-face        ;;Face for the number tags for URLs.
                                            ;mu4e-attach-number-face        ;;Face for the number tags for attachments.
                                            ;mu4e-cited-1-face        ;;Face for cited message parts (level 1).
                                            ; mu4e-cited-2-face        ;;Face for cited message parts (level 2).
                                            ;  mu4e-cited-3-face        ;;Face for cited message parts (level 3).
                                            ;   mu4e-cited-4-face        ;;Face for cited message parts (level 4).
                                            ;    mu4e-cited-5-face        ;;Face for cited message parts (level 5).
                                            ;     mu4e-cited-6-face        ;;Face for cited message parts (level 6).
                                            ;      mu4e-cited-7-face    ;;Face for cited message parts (level 7).
    
                                            ;mu4e-header-face        ;;Face for a header without any special flags.
                                            ;mu4e-header-highlight-face    ;;Face for the header at point.
                                            ;mu4e-header-key-face        ;;Face for a header key (such as \"Foo\" in \"Subject:\ Foo\").
                                            ;mu4e-header-marks-face        ;;Face for the mark in the headers list.
                                            ;mu4e-header-title-face        ;;Face for a header title in the headers view.
                                            ;mu4e-header-value-face        ;;Face for a header value (such as \
                                            ;mu4e-footer-face        ;;Face for message footers (signatures).
    
                                            ;VARIOUS
                                            ;mu4e-highlight-face        ;;Face for highlighting things.
                                            ;mu4e-region-code        ;;Face for highlighting marked region in mu4e-view buffer.
                                            ;mu4e-special-header-value-face    ;;Face for special header values.
                                            ;mu4e-system-face        ;;Face for system message (such as the footers for message headers).
                                            ;mu4e-title-face                ;;Face for a header title in the headers view.
                                            ;mu4e-ok-face                ;;Face for things that are okay.
                                            ;mu4e-warning-face        ;;Face for warnings / error.
      )
    
  11. Headers
    (use-package mu4e
      :defer t
      :config
      ;; default sorting
      ;; (setq mu4e-headers-sort-direction 'ascending)
    
      ;; the headers to show in the headers list -- a pair of a field
      ;; and its width, with `nil' meaning 'unlimited'
      ;; (better only use that for the last field.
      ;; These are the defaults:
      (setq mu4e-headers-fields
            '( (:human-date          .  15)    ;; date, human-date, more-human-date
               (:flags         .   4)
               (:size         .   8)
               ;;(:sizen         .   9)
               (:from          .  25) ;; from , to, from-or-to
               (:recipnum            .  5)
               (:to            .  25)
                                            ;(:mailing-list . 10)
               (:thread-subject       .  nil))) ;; subject, thread-subject
    
      ;;colors
      (defvar mu4e-list-colors
        '(
          ;;work
          ("xxx" . "#AFA")
          ))
      (setq list (alist-keys mu4e-list-colors))
      (defun mu4e~headers-line-apply-list-face (msg line)
        "Adjust LINE's face property based on the color list."
        (let* ((ml (downcase (cdar (mu4e-message-field msg :from))))
               ;;(face (if (assoc ml mu4e-list-colors)
               ;;          (let ((color (assoc-default ml mu4e-list-colors)))
               (res (xah-string-match-in-list-p ml list "no" 1))
               (face (if res
                         (let ((color (assoc-default res mu4e-list-colors)))
                           ;;`(:foreground ,color :background ,color))
                           `(:foreground ,color))
                       ;;`(:foreground ,(face-attribute 'highlight :background))
                       `(:foreground ,(face-attribute 'mu4e-flagged-face :background))
                       ;;`(:foreground "black" :background "black")
                       )))
          (when (fboundp 'add-face-text-property)
            (add-face-text-property 0 (length line) face t line))
          ;;(add-face-text-property 28 29 face t line))
          line))
      (add-to-list 'mu4e~headers-line-handler-functions
                   'mu4e~headers-line-apply-list-face)
    
    
      (setq mu4e-headers-show-threads nil)
    
      ;; The letters in the ‘Flags’ field correspond to the following: D=draft, F=flagged (i.e., ‘starred’), N=new, P=passed (i.e., forwarded), R=replied, S=seen, T=trashed, a=has-attachment, x=encrypted, s=signed, u=unread. The tooltip for this field also contains this information.
    
      ;; date format
      (setq mu4e-headers-date-format "%d-%m-%Y %a")
      (setq mu4e-headers-time-format "[%H:%M]")
    
      ;;thread options
      (setq
       ;; thread prefix marks
       mu4e-headers-has-child-prefix '("."  . "◼ ")
       mu4e-headers-default-prefix '(" "  . "│ ")
       )
    
      ;; show full addresses in view message (instead of just names)
      ;; toggle per name with M-RET
      ;; (setq mu4e-view-show-addresses 't)
    
      ;; mark all visible messages as read
      ;;('mu4e-headers-flag-all-read)
    
      ;;When in the headers view, which displays your email messages, you can easily navigate through different messages using n and p and hitting return will open a message, allowing you to read it. In addition, mu4e includes some very useful marking capabilities: d marks a message for deletion, r for refiling/archiving, and m for moving (after a target directory is specified). Simply press x to "execute" the marks. In addition, with * you can "bulk mark" emails; pressing x after some messages have been marked with x will allow you to perform an action to all of them. See the mu4e user manual for more details.
      )
    
  12. View
    (use-package mu4e
      :defer t
      :config
      ;; show images
      (setq mu4e-view-show-images t
            mu4e-show-images t
            mu4e-view-image-max-width 800
            mu4e-image-max-width 800)
      ;; use imagemagick, if available
      (when (fboundp 'imagemagick-register-types)
        (imagemagick-register-types))
    
      ;; show addresses
      (setq mu4e-view-show-addresses t) 
    
      ;;(setq mu4e-msg2pdf "/path/to/msg2pdf")
    
      ;; view HTML messages
      ;;mu4e-html2text-command "w3m -dump -T text/html" ;;"w3m -dump -T text/html"
      ;;mu4e-html2text-command "html2text -utf8 -width 72" ;;seems to be doing a better job than w3m
      (require 'mu4e-contrib)
      ;;(setq mu4e-html2text-command 'mu4e-shr2text)
      (setq shr-color-visible-luminance-min 50)
      (setq shr-color-visible-distance-min 5)
      (setq mu4e-html2text-command-orig "html2text -utf8 -width 72")
      (setq mu4e-html2text-command mu4e-html2text-command-orig)
    
      ;; <tab> to navigate to links, <RET> to open them in browser
                                            ;(add-hook 'mu4e-view-mode-hook
                                            ;  (lambda()
    ;;; try to emulate some of the eww key-bindings
                                            ;(local-set-key (kbd "<RET>") 'mu4e~view-browse-url-from-binding)
                                            ;(local-set-key (kbd "<tab>") 'shr-next-link) ;;doesn work
                                            ;(local-set-key (kbd "<backtab>") 'shr-previous-link)))
    
      ;; toggle between html2text and mu4e-shr2text
      (defun mu4e-view-toggle-html2 ()
        "Toggle html-display of the message body (if any)."
        (interactive)
        (setq mu4e-html2text-command (if (string= mu4e-html2text-command mu4e-html2text-command-orig) 'mu4e-shr2text mu4e-html2text-command-orig))
        (setq mu4e~view-html-text 'html)
        (mu4e-view-refresh)
        )
      (define-key mu4e-view-mode-map    (kbd "C-c h") 'mu4e-view-toggle-html2)
    
    
                                            ;(setq mu4e-view-fields '(:from :to  :cc :subject :flags :date :maildir
                                            ;                         :mailing-list :tags :useragent :attachments
                                            ;                         :openpgp :signature :decryption))
    
                                            ;(defun mu4e-view-toggle-html ()
                                            ;  "Toggle html-display of the message body (if any)."
                                            ;  (interactive)
                                            ;  (setq mu4e~view-html-text
                                            ;    (if mu4e~message-body-html 'text 'html))
                                            ;(mu4e-view-refresh))
    
      ;; open mail links in new frame
      ;;(defun mu4e-link-in-new-frame (MSGID) (select-frame (make-frame)))
      ;;(advice-add 'mu4e-view-message-with-message-id :before 'mu4e-link-in-new-frame)
      )
    
  13. Actions
    (use-package mu4e
      :defer t
      :config
    
      ;; add view in browser for html messages
      (add-to-list 'mu4e-view-actions
                   '("gViewInBrowser" . mu4e-action-view-in-browser) t)
    
                                            ;(defun mu4e-action-view-in-external-browser (msg)
                                            ; (let ((browse-url-browser-function 'browse-url-generic))
                                            ; ;; (let ((browse-url-generic-program "xdg-open"))
                                            ;  (mu4e-action-view-in-browser msg))
                                            ;)
    ;;; add view in browser for html messages
                                            ;(add-to-list 'mu4e-view-actions
                                            ;	     '("GViewInBrowser" . mu4e-action-view-in-external-browser) t)
    
      ;; search for sender
      (defun search-for-sender (msg)
        "Search for messages sent by the sender of the message at point."
        (mu4e-headers-search
         (concat "from:" (cdar (mu4e-message-field msg :from)))))
      ;; define 'x' as the shortcut
      (add-to-list 'mu4e-view-actions
                   '("xsearch for sender" . search-for-sender) t)
    
    
      ;; overwrite save attachment to propose making non-existing directories first
      ;; also allows using directory as input
      (defun mu4e-view-save-attachment-single (&optional msg attnum)
        "Save attachment number ATTNUM from MSG.
    If MSG is nil use the message returned by `message-at-point'.
    If ATTNUM is nil ask for the attachment number."
        (interactive)
        (let* ((msg (or msg (mu4e-message-at-point)))
               (attnum (or attnum
                           (mu4e~view-get-attach-num "Attachment to save" msg)))
               (att (mu4e~view-get-attach msg attnum))
               (fname  (plist-get att :name))
               (mtype  (plist-get att :mime-type))
               (path (concat
                      (mu4e~get-attachment-dir fname mtype) "/"))
               (index (plist-get att :index))
               (retry t) (fpath))
          ;;path is attachment dir (~)
          (while retry
            (setq fpath (mu4e~view-request-attachment-path fname path))
            (setq path2 (file-name-directory fpath))
            (setq retry
                  (and (not (file-exists-p path2))
                       (not (y-or-n-p (mu4e-format "Create directory '%s'?" path2))))))
          (make-directory path2 t)
          ;;if input is a directory, append fname
          (if (file-directory-p (substitute-in-file-name fpath))
              (setq fpath (concat fpath "/" fname)))
          ;;should we overwrite?
          (while retry
            (setq retry
                  (and (file-exists-p fpath)
                       (not (y-or-n-p (mu4e-format "Overwrite '%s'?" fpath))))))
          (mu4e~proc-extract
           'save (mu4e-message-field msg :docid)
           index mu4e-decryption-policy fpath)))
    
      ;; overwrite to save all attachments with no confirmation
      (defun mu4e-view-save-attachment-multi2 (&optional msg)
        "Offer to save multiple email attachments from the current message.
    Default is to save all messages, [1..n], where n is the number of
    attachments.  You can type multiple values separated by space, e.g.
      1 3-6 8
    will save attachments 1,3,4,5,6 and 8.
    Furthermore, there is a shortcut \"a\" which so means all
    attachments, but as this is the default, you may not need it."
        (interactive)
        (let* ((msg (or msg (mu4e-message-at-point)))
               (count (hash-table-count mu4e~view-attach-map))
               (attachnums (mu4e-split-ranges-to-numbers "a" count)))
          (let* ((path (concat (mu4e~get-attachment-dir) "/"))
                 (attachdir (mu4e~view-request-attachments-dir path)))
            (dolist (num attachnums)
              (let* ((att (mu4e~view-get-attach msg num))
                     (fname  (plist-get att :name))
                     (index (plist-get att :index))
                     (retry t)
                     fpath)
                (while retry
                  (setq fpath (expand-file-name (concat attachdir fname) path))
                  (setq retry
                        (and (file-exists-p fpath)
                             (not (y-or-n-p
                                   (mu4e-format "Overwrite '%s'?" fpath))))))
                (mu4e~proc-extract
                 'save (mu4e-message-field msg :docid)
                 index mu4e-decryption-policy fpath))))
          ))
      (define-key mu4e-view-mode-map (kbd "s") 'mu4e-view-save-attachment-multi2)
    
    
    
      ;; overwrite fetch URL to propose making non-existing directories first and choosing the filename
      (defun mu4e-view-fetch-url (&optional multi)
        "Offer to fetch (download) urls(s). If MULTI (prefix-argument) is nil,
    download a single one, otherwise, offer to fetch a range of
    URLs. The urls are fetched to `mu4e-attachment-dir'."
        (interactive "P")
        (mu4e~view-handle-urls "URL to fetch" multi
                               (lambda (url)
                                 (setq retry t)
                                 (while retry
                                   (setq fname (file-name-nondirectory url))
                                   (setq path (concat
                                               (mu4e~get-attachment-dir fname) "/"))
                                   (setq fpath (mu4e~view-request-attachment-path fname path))
                                   (setq path2 (file-name-directory fpath))
                                   (setq retry
                                         (and (not (file-exists-p path2))
                                              (not (y-or-n-p (mu4e-format "Create directory '%s'?" path2))))))
                                 (make-directory path2 t)
                                 (while retry
                                   (setq retry
                                         (and (file-exists-p fpath)
                                              (not (y-or-n-p (mu4e-format "Overwrite '%s'?" fpath))))))
                                 (url-copy-file url fpath)
                                 (mu4e-message "Fetched %s -> %s" url fpath))
                               ))
    
    
                                            ;(defun try-move ()
                                            ;  (interactive)
                                            ;  (mu4e~proc-move (mu4e-message-field-at-point :message-id) "/xxx/[Xxx].Drafts" nil)
                                            ;  )
                                            ;(add-to-list 'mu4e-headers-actions
                                            ;             '("dd" . try-move))
      ;;(defun try-move (msg)
      ;;  (mu4e~proc-move (mu4e-message-field msg :message-id) "/xxx/[Xxx].Drafts")
      ;;  )
      ;;(add-to-list 'mu4e-headers-actions
      ;;             '("dd" . try-move))
    
      ;; add action to show the local filename of the message
      (defun my-show-filename (msg)
        (kill-new (mu4e-message-field msg :path))
        )
      (add-to-list 'mu4e-view-actions
                   '("filename in kill-ring" . my-show-filename))
      (add-to-list 'mu4e-headers-actions
                   '("filename in kill-ring" . my-show-filename))
    
      ;; remove attachment?
      ;;https://emacs.stackexchange.com/questions/23812/remove-attachments-from-emails
      ;; This adds a new "attachment action" in Mu4e. When viewing an email, press A, then r to select the action defined above, then enter the number of the attachment. The action will ask you for confirmation before deleting the attachment. The header listing the attachments is not updates but when you leave the email and reopen it, the attachment is gone.
                                            ;(defun my-remove-attachment2 (msg num) 
                                            ;  "Remove attachment." 
                                            ;  (let* ((attach (mu4e~view-get-attach msg num))
                                            ;         (path (mu4e-msg-field msg :path))
                                            ;         (filename (and attach (plist-get attach :name)))
                                            ;         (cmd (format "altermime --input=%s --remove='%s'"  path filename)))
                                            ;    (when (and filename
                                            ;               (yes-or-no-p
                                            ;                (format "Are you sure you want to remove '%s'?" filename)))
                                            ;      (shell-command cmd)
                                            ;      (message cmd))))
                                            ;(add-to-list 'mu4e-view-attachment-actions
                                            ;             '("remove-attachment2" . my-remove-attachment2))
    
    
                                            ;(defun my-remove-attachment (msg num) 
                                            ;  "Remove attachment." 
                                            ;  (let* ((path (mu4e-msg-field msg :path))
                                            ;	 ;; Create the disclaimer files
                                            ;	 (disc-txt "Removed attachments")
                                            ;	 (disc-txt-fpath "/tmp/disclaimer.txt")
                                            ;        (cmd (format "altermime --input=%s --removeall --disclaimer='%s'" path disc-txt-fpath)))
                                            ;   (with-temp-file disc-txt-fpath (insert disc-txt))
                                            ;   (shell-command cmd)
                                            ;   (message cmd))
                                            ; (let* ((oldmaildir (mu4e-message-field msg :maildir)))
                                            ;     (mu4e~proc-move (mu4e-message-field msg :message-id) "/xxx/[Xxx].Drafts")
                                            ;     (mu4e~proc-move (mu4e-message-field msg :message-id) oldmaildir))
                                            ; )
                                            ;(add-to-list 'mu4e-view-attachment-actions
                                            ;             '("remove-attachments" . my-remove-attachment))
                                            ;(add-to-list 'mu4e-headers-actions
                                            ;             '("remove-attachments" . my-remove-attachment))
    
    
      ;; remove all attachments from email. This works also for Xxx, with the tweak that the message is moved around so as to force an update on the IMAP server
      ;; This adds a new "attachment action" in Mu4e. When viewing an email, press A, then R to select the action defined above, then enter the number of the attachment. The action will ask you for confirmation before deleting the attachment. The header listing the attachments is not updates but when you leave the email and reopen it, the attachment is gone.
      ;;also check mu4e-detach
      (defun my-remove-attachment (msg) 
        "Remove attachment."
        (let* ((x (mu4e~view-construct-attachments-header msg));; Populate attachment map
               (count (hash-table-count mu4e~view-attach-map));; Count the attachments
               (attachnums (mu4e-split-ranges-to-numbers "a" count));; A list of numbers for all attachments
               (num 1)
               )
          (let (fnamelist '())
            ;; Save all attachments
            (dolist (num attachnums)
              (let* ((att (mu4e~view-get-attach msg num))
                     (fname (plist-get att :name)))
                (add-to-list 'fnamelist fname)))
    
            (let* ((path (mu4e-msg-field msg :path))
                   (disc-txt (format "Removed attachments:\n- %s\n"
                                     (s-join "\n- " fnamelist)))
                   (disc-txt-fpath "/tmp/disclaimer.txt")
                   (cmd (format "altermime --input=%s --removeall --disclaimer='%s'" path disc-txt-fpath)))
              (with-temp-file disc-txt-fpath (insert disc-txt))
              (shell-command cmd)
              (message cmd))
    
            ))
                                            ;move mail around so it gets updated in IMAP
        (let* ((oldmaildir (mu4e-message-field msg :maildir)))
          (mu4e~proc-move (mu4e-message-field msg :message-id) "/xxx/[Xxx].Drafts")
          (mu4e~proc-move (mu4e-message-field msg :message-id) oldmaildir))
                                            ;(mu4e-headers-rerun-search) ;update header view
        )
      (add-to-list 'mu4e-headers-actions
                   '("remove-attachments" . my-remove-attachment))
    
      (defun my-remove-attachment2 (msg num) 
        "Remove attachment."
        (let* ((x (mu4e~view-construct-attachments-header msg));; Populate attachment map
               (count (hash-table-count mu4e~view-attach-map));; Count the attachments
               (attachnums (mu4e-split-ranges-to-numbers "a" count));; A list of numbers for all attachments
               )
          (let (fnamelist '())
            ;; Save all attachments
            (dolist (num attachnums)
              (let* ((att (mu4e~view-get-attach msg num))
                     (fname (plist-get att :name)))
                (add-to-list 'fnamelist fname)))
    
            (let* ((path (mu4e-msg-field msg :path))
                   (disc-txt (format "Removed attachments:\n- %s\n"
                                     (s-join "\n- " fnamelist)))
                   (disc-txt-fpath "/tmp/disclaimer.txt")
                   (cmd (format "altermime --input=%s --removeall --disclaimer='%s'" path disc-txt-fpath)))
              (with-temp-file disc-txt-fpath (insert disc-txt))
              (shell-command cmd)
              (message cmd))
    
            ))
                                            ;move mail around so it gets updated in IMAP
        (let* ((oldmaildir (mu4e-message-field msg :maildir)))
          (mu4e~proc-move (mu4e-message-field msg :message-id) "/xxx/[Xxx].Drafts")
          (mu4e~proc-move (mu4e-message-field msg :message-id) oldmaildir))
        (mu4e-headers-rerun-search) ;update header view
        )
      (add-to-list 'mu4e-view-attachment-actions
                   '("remove-attachments" . my-remove-attachment2))
    
    
    
    
    
                                            ;(defun speak-message (msg)
                                            ;  (mu4e-action-message-to-speech msg))
    ;;; define 's' as the shortcut
                                            ;(add-to-list 'mu4e-view-actions
                                            ;	     '("sspeech" . speak-message) t)
      )
    
  14. Flags, marking
    (use-package mu4e
      :defer t
      :config
    
      (setq mu4e-headers-flagged-mark   `("F" . "!"))
      (setq mu4e-headers-trashed-mark   `("T" . "♻"))
      (setq mu4e-headers-attach-mark    `("a" . "#"))
      (setq mu4e-headers-encrypted-mark `("x" . "X"))
      (setq mu4e-headers-signed-mark    '("s" . "☡"))
      (setq mu4e-headers-unread-mark    `("u" . "⚑"))
      (setq mu4e-headers-new-mark       '("N" . "⚐"))
      (setq mu4e-headers-draft-mark     '("D" . "⚒"))
      (setq mu4e-headers-passed-mark    '("P" . "F"))
      (setq mu4e-headers-replied-mark   '("R" . "R"))
      (setq mu4e-headers-seen-mark      '("S" . ""))
    
    
      ;;somehow trash flag don't seem to work for xxx, it keeps showing
      ;;in all-mail. Just move them to Trash, xxx seems to take care of the
      ;;trashed flag just fine
      (add-to-list 'mu4e-marks
                   '(archive
                     :char       ("D" . "❌❌")
                     :prompt     "Delete"
                                            ;:show-target (lambda (target) "trash!")
                     :dyn-target (lambda (target msg) (mu4e-get-trash-folder msg))
                     :action      (lambda (docid msg target)
                                    ;; must come before proc-move since retag runs
                                    ;; 'sed' on the file
                                    (mu4e~proc-move docid nil "+S-u-N") ;; mark as read first
                                    (mu4e~proc-move docid (mu4e~mark-check-target target)))))
      (mu4e~headers-defun-mark-for archive)
      (define-key mu4e-headers-mode-map (kbd "D") 'mu4e-headers-mark-for-archive)
      ;;also overwrite other existing marks
      (add-to-list 'mu4e-marks
                   '(archive
                     :char       ("d" . "❌❌")
                     :prompt     "delete"
                                            ;:show-target (lambda (target) "trash!")
                     :dyn-target (lambda (target msg) (mu4e-get-trash-folder msg))
                     :action      (lambda (docid msg target)
                                    ;; must come before proc-move since retag runs
                                    ;; 'sed' on the file
                                    ;;(mu4e~proc-move docid nil "+S-u-N") ;; mark as read first
                                    (mu4e~proc-move docid (mu4e~mark-check-target target))
                                    (mu4e~proc-move docid nil "+S-u-N") ;; mark as read 
                                    )))
      (mu4e~headers-defun-mark-for archive)
      (define-key mu4e-headers-mode-map (kbd "d") 'mu4e-headers-mark-for-archive)
      )
    
  15. Accounts, contexts
    (use-package mu4e
      :defer t
      :config
      ;; Multiple accounts: https://www.djcbsoftware.nl/code/mu/mu4e/Multiple-accounts.html
      ;; You can put any variable you want in the account lists, just make sure that you put in all the variables that differ for each account. Variables that do not differ need not be included. For example, if you use the same SMTP server for both accounts, you don’t need to include the SMTP-related variables in my-mu4e-account-alist.
    
      ;; in the following, leave-func is because when switching contexts with errors, autocompletion of addresses doesn't work anymore... https://github.com/djcb/mu/issues/1016
    
                                            ;add?
                                            ;(setq mu4e-sent-folder   "/xxx/[Xxx].SentMail")
                                            ;(setq mu4e-drafts-folder "/xxx/[Xxx].Drafts")
                                            ;(setq mu4e-trash-folder  "/xxx/[Xxx].Trash")
    
      ;;context policies
      (setq mu4e-context-policy 'pick-first) ;;useful to pick first automatically because context is chosen automatically afterwards anyway
      ;;     mu4e-compose-context-policy 'ask)
    
                                            ;(setq message-send-mail-function 'smtpmail-send-it
                                            ;      starttls-use-gnutls t
                                            ;      smtpmail-debug-info t
                                            ;      )
    
      (defun checkk (&optional msg attnum)
        (interactive)
        (setq msg (mu4e-message-at-point))
        (message-box (format "%s" (string= (mu4e-message-field msg :maildir) "/xxx/Inbox")))
        (message-box (format "%s" (string-match "xxx/" (mu4e-message-field msg :maildir))))
        )
    
    
      ;; SMTP
      ;; https://dataswamp.org/~solene/2018-05-22-mu4esmtp.html
      (setq message-send-mail-function 'smtpmail-send-it
            smtpmail-debug-info t)
      ;; shows errors in *messages*
      (setq auth-source-debug t)
      (setq auth-source-do-cache nil)
    
      ;; smtpmail-auth-credentials obsolete in emacs 25
      ;; (setq auth-sources '("~/.authinfo.gpg" "~/.authinfovl.gpg"))
      (setq auth-sources '("~/.authinfo.gpg"))
    
      ;; 
      (if at-cea
          (setq mu4e-contexts `( ,(make-mu4e-context
                                   :name "xxx"
                                   :enter-func (lambda () (mu4e-message "xxx context")
                                                 (setq mu4e-sent-messages-behavior 'sent)) ;; make a copy in sent-folder defined below, which is different than the CEA SMTP/IMAP sent folder
                                   :match-func (lambda (msg) (and at-cea (when msg (string-match "xxx/" (mu4e-message-field msg :maildir)))))
                                   :leave-func (lambda () (setq mu4e-maildir-list nil))
                                   :vars '((user-mail-address . "xxx.xxx@xxx.fr")
                                           (user-full-name . "xxx xxx")
                                           (mu4e-reply-to-address . "xxx.xxx@xxx.fr")
                                           (mu4e-compose-reply-to-address . "xxx.xxx@xxx.fr")
                                           (mu4e-compose-signature . t)
                                           ;;(mu4e-sent-messages-behavior . (quote sent))
                                           (mu4e-sent-folder .  "/xxx/[Xxx].SentMail")
                                           (mu4e-drafts-folder . "/xxx/[Xxx].Drafts")
                                           (mu4e-trash-folder . "/xxx/[Xxx].Trash")
                                           ;;mu4e-refile-folder "/archive")   ;; saved messages
                                           (smtpmail-default-smtp-server . "xxx.fr"); needs to be specified before the (require)
                                           (smtpmail-local-domain . "xxx.fr")
                                           (smtpmail-smtp-user . "xxx")
                                           (smtpmail-smtp-server . "xxx.fr")
                                           (smtpmail-stream-type . plain)
                                           (smtpmail-smtp-service . 25))
                                   )
                                 )
                )
        ;; else
        (setq mu4e-contexts `( ,(make-mu4e-context
                                 :name "homework"
                                 :enter-func (lambda () (mu4e-message "Homework context (CNRS + CEA)")
                                            ;(setq mu4e-sent-messages-behavior 'delete)) ;; xxx IMAP takes care of placing a copy in sent
                                               (setq mu4e-sent-messages-behavior 'sent)) ;; xxx IMAP takes care of placing a copy in sent
                                 ;;:match-func (lambda (msg) (and (not 'check-if-at-CEA) (or (when msg (mu4e-message-contact-field-matches msg :to "[[:ascii:]]+@xxx.fr")) (when msg (mu4e-message-contact-field-matches msg :to "xxx.xxx@xxx.com")) )))
                                 :match-func (lambda (msg) (and (not at-cea) (when msg (string-match "xxx/" (mu4e-message-field msg :maildir)))))
                                 :leave-func (lambda () (setq mu4e-maildir-list nil))
                                 :vars '(;(user-mail-address . "xxx@xxx.com")
                                         (user-mail-address . "xxx.xxx@xxx.fr")
                                         (user-full-name . "xxx xxx")
                                         (mu4e-reply-to-address . "xxx.xxx@xxx.fr")
                                         (mu4e-compose-reply-to-address . "xxx.xxx@xxx.fr")
                                         (mu4e-compose-signature . t)
                                         ;;(mu4e-sent-messages-behavior . (quote delete))
                                            ;(mu4e-sent-folder .  "/xxx/[Xxx].SentMail")
                                            ;(mu4e-drafts-folder . "/xxx/[Xxx].Drafts")
                                            ;(mu4e-trash-folder . "/xxx/[Xxx].Trash")
                                         (mu4e-sent-folder .  "/cnrs/SentMail")
                                         (mu4e-drafts-folder . "/cnrs/Drafts")
                                         (mu4e-trash-folder . "/cnrs/Trash")
                                         ;;mu4e-refile-folder "/archive")   ;; saved messages
                                         ;;(smtpmail-starttls-credentials . '(("smtp.googlemail.com" 587 nil nil)))
                                            ;(smtpmail-default-smtp-server . "smtp.xxx.com"); needs to be specified before the (require)
                                            ;(smtpmail-local-domain . "xxx.com")
                                            ;(smtpmail-smtp-user . "xxx.xxx@xxx.com")
                                            ;(smtpmail-smtp-server . "smtp.xxx.com")
                                         (smtpmail-default-smtp-server . "smtp.xxx.fr"); needs to be specified before the (require)
                                         (smtpmail-local-domain . "xxx.fr")
                                         ;;(smtpmail-smtp-user . "xxx xxx")
                                         (smtpmail-smtp-user . "xxx.xxx@xxx.fr") ;;reseda
                                         (smtpmail-smtp-server . "smtp.xxx.fr")
                                         (smtpmail-stream-type . starttls)
                                         ;;(smtpmail-auth-credentials . (("hostname" "port" "username" "password")))
                                         (smtpmail-smtp-service . 587)))
                               ))
        )
    
      (require 'smtpmail)
    
         ;;;smtp.xxx.com port 587/TLS 465/SSL Normal password
      ;;,(make-mu4e-context ;;emails from this context should come from CEA identity
      ;;  :name "VL"
      ;;  :enter-func (lambda () (mu4e-message "xxx(VL) context"))
      ;; ;;:match-func (lambda (msg) (when msg (mu4e-message-contact-field-matches msg :to "work-email@xxx.com")))
      ;;  :leave-func (lambda () (setq mu4e-maildir-list nil))
      ;;  :vars '((user-mail-address . "xxx.xxx@xxx.com")
      ;;	   (mu4e-reply-to-address . "xxx.xxx@xxx.com")
      ;;	   (mu4e-compose-reply-to-address . "xxx.xxx@xxx.com")
      ;;	   (mu4e-sent-folder .  "/xxx/[Xxx].SentMail")
      ;;	   (mu4e-drafts-folder . "/xxx/[Xxx].Drafts")
      ;;	   (mu4e-trash-folder  . "/xxx/[Xxx].Trash")
      ;;	   (smtpmail-default-smtp-server . "smtp.googlemail.com")
      ;;	   (smtpmail-local-domain . "googlemail.com")
      ;;	   (smtpmail-smtp-user . "xxx.xxx")
      ;;	   (smtpmail-smtp-server . "smtp.googlemail.com")
      ;;	   (smtpmail-stream-type . starttls)
      ;;	   (smtpmail-smtp-service . 587)) 
      ;; )
         ;;;smtp.xxx.com port 587/TLS 465/SSL Normal password
      ;; compose with the current context if no context matches;
      (setq mu4e-compose-context-policy nil)
    
                                            ;(defun mu4e-auto-context (at-cea)
                                            ;(if at-cea
                                            ;    (mu4e-context-switch nil "CEA")
                                            ;    (mu4e-context-switch nil "homework")
                                            ;    )
                                            ;)
    
      )
    
  16. mu4e-alert
    ;;https://devhub.io/repos/iqbalansari-mu4e-alert
    ;;(mu4e-alert-set-default-style 'libnotify) ;; notifications or libnotify
    ;;(add-hook 'after-init-hook #'mu4e-alert-enable-notifications)
                                            ;(add-hook 'after-init-hook #'mu4e-alert-enable-mode-line-display)
                                            ;(setq mu4e-alert-interesting-mail-query
                                            ;        (concat
                                            ;         "flag:unread"
                                            ;         " AND NOT flag:trashed"
                                            ;         " AND NOT maildir:\"/xxx/[Xxx].Spam\""
                                            ;         " AND NOT maildir:\"/xxx/[Xxx].Spam\""
                                            ;	 ))
    
    
  17. Conversation
    ;(with-eval-after-load 'mu4e (require 'mu4e-conversation))
    ;(global-mu4e-conversation-mode)
    
    ;(setq mu4e-view-func 'mu4e-conversation)
    ;(defun conv()
    ;(interactive)
    ;(make-frame)
    ;(mu4e-conversation--turn-on)
    ;(mu4e-conversation)
    ;(mu4e-conversation--turn-on)
    ;)
    
  18. Web links
                                            ;(use-package mu4e
                                            ;:defer t
                                            ;:config
                                            ;(defun mu4e-view-go-to-url-gui ()
                                            ;  "Wrapper for mu4e-view-go-to-url to use gui browser instead of eww"
                                            ;  (interactive)
                                            ; (let ((browse-url-browser-function 'browse-url-generic))
    ;;;  (let ((browse-url-generic-program "xdg-open"))
                                            ;    (mu4e-view-go-to-url)))
    ;;; bind it
                                            ;(define-key mu4e-view-mode-map (kbd "G") 'mu4e-view-go-to-url-gui)
                                            ;)
    
  19. Help
    
    
    (use-package mu4e
      :defer t
      :init
    
    
    
    
      ;;------------------ help
    
      ;;help
      (defun show-mu4e-main-help ()
        (interactive)
        (message-box "
    MU4E
    ----
    ?           : update (+elfeed)
    M-x speedbar: speedbar!
    "))
    
      (defun show-mu4e-view-help ()
        (interactive)
        (message-box "
    MU4E-view
    ---------
    
    R,F,C: reply, forward, compose
    a: message actions
    A: attachment actions
    V: conversation toggle
    W: show/hide related messages
    
    g: visit URLs 
    f: fetch URLs
    e: save (extract) attachment
    s: save all attachments
    
    C-cr: capture reply to/to-do mail
    h   : toggle html
    C-ch: toggle html2text method
    "))
    
      (defun show-mu4e-headers-help ()
        (interactive)
        (message-box "
    MU4E-headers
    ------------
    
    P    : threading on/off
    R,F,C: reply, forward, compose
    E    : edit (drafts)
    W    : show/hide related messages
    
    d/=  :  trash/untrash
    DEL,D: deletion
    m    : move
    r    : refile
    u/U  : unmark (all) message(s)
    t,T  : mark (sub)thread
    Flags: +/- importance
           ?,!: unread/read
    x    : execute actions
    
    /,M-arrows: narrow-down and navigate queries
    
    C-cr: capture reply to/to-do mail
    "))
    
      (defun show-mu4e-compose-help ()
        (interactive)
        (message-box "
    MU4E-compose
    ------------
    C-c C-a: attach
    C-c C-c: send
    C-c C-k: cancel
    C-x C-s: save in drafts
    V:       conversation toggle
    
    TAB: cycle through email addresses suggestions
    "))
    
      ;;shortcut
      ;;(global-set-key (read-kbd-macro "<C-f2>") 'mu4e)
    
      (defun mu4e-elfeed-update ()
        (interactive)
        (mu4e-update-mail-and-index t) ;;t is to run in background
        (elfeed-update)
        )
    
      (defun mu4e-new-frame ()
        (interactive)
        (select-frame (make-frame))
        (delete-other-windows)
        (mu4e)
        )
      ;;
      (global-set-key "\C-c2" 'mu4e-new-frame)
    
    
      (defun mu4e-elfeed ()
        (interactive)
        (delete-other-windows)
        ;;(select-frame (make-frame))
        (split-window-vertically)
        (other-window 1)
        (elfeed-load)
        (other-window 1)
        (select-window (mu4e)) ;;mu4e takes a long time to load...
        )
      ;;
      (global-set-key "\C-c3" 'mu4e-elfeed)
    
    
      ;; specific shortcuts 
      (progn
        ;; keyboard shortcuts
        (require 'mu4e)
        (define-key mu4e-main-mode-map (kbd "?") 'mu4e-elfeed-update)
        (define-key mu4e-main-mode-map (kbd "<C-f1>") 'show-mu4e-main-help)
        (define-key mu4e-view-mode-map (kbd "<C-f1>") 'show-mu4e-view-help)
        (define-key mu4e-headers-mode-map (kbd "<C-f1>") 'show-mu4e-headers-help)
        (define-key mu4e-compose-mode-map (kbd "<C-f1>") 'show-mu4e-compose-help)
        (define-key mu4e-view-mode-map (kbd "\C-cr") 'org-capture-todomail)
        (define-key mu4e-headers-mode-map (kbd "\C-cr") 'org-capture-todomail)
        (define-key mu4e-compose-mode-map (kbd "\C-cr") 'org-capture-todomail)
                                            ;(define-key mu4e-view-mode-map (kbd "\C-ct") 'org-capture-todomail)
                                            ;(define-key mu4e-headers-mode-map (kbd "\C-ct") 'org-capture-todomail)
                                            ;(define-key mu4e-compose-mode-map (kbd "\C-ct") 'org-capture-todomail)
        )
      )
    

3.15 Browsers

3.15.1 Browser choice

;; default browser function
(setq browse-url-browser-function 'eww-browse-url)
                                        ;(setq browse-url-browser-function 'browse-url-firefox)
                                        ;(setq browse-url-browser-function 'browse-url-chromium)

;; default browser program
(setq browse-url-generic-program "brave-browser")
;;(setq browse-url-generic-program "vivaldi")

;; example
                                        ;(setq browse-url-browser-function 'browse-url-generic
                                        ;      browse-url-generic-program "brave-browser")

;; default
(setq current-browser "external")
(setq browse-url-browser-function 'browse-url-generic)

;; toggle between eww and external browser
(defun toggle-browser ()
  "Toggle between browsers"
  (interactive)
  (setq current-browser (if (string= current-browser "internal") "external" "internal"))
  (message current-browser)
  (if (string= current-browser "internal")
      (setq browse-url-browser-function 'eww-browse-url)
    (setq browse-url-browser-function 'browse-url-generic)
    )
  )

3.15.2 eww

(defhydra hydra-eww ()
  "eww"
  ("b" eww-back-url "Back")
  ("f" eww-forward-url "Forward")
  ("g" eww-browse-with-external-browser "External")
  ("h" eww-list-histories "History")
  )

(defun vl-eww-hook ()
  (define-key eww-mode-map "?" 'hydra-eww/body))
(add-hook 'eww-mode-hook 'vl-eww-hook)

3.15.3 edit with emacs

(add-to-list 'load-path "~/.emacs.d/edit-server")
(require 'edit-server)
(edit-server-start)

3.16 System


;; System monitor in bar
(use-package symon
  :defer 3
  :ensure t
  :config
  (setq symon-sparkline-type 'bounded)
  (define-symon-monitor symon-current-date-time-monitor
    :interval 5
    :display (propertize
              (format-time-string "%k:%M %a %d %b %Y ")
              'face 'font-lock-type-face))
  (setq symon-monitors
        (cond ((memq system-type '(gnu/linux cygwin))
               '(symon-current-date-time-monitor
                 symon-linux-memory-monitor
                 symon-linux-cpu-monitor
                 symon-linux-network-rx-monitor
                 symon-linux-network-tx-monitor
                 symon-linux-battery-monitor))
              ((memq system-type '(darwin))
               '(symon-current-date-time-monitor
                 symon-darwin-memory-monitor
                 symon-darwin-cpu-monitor
                 symon-darwin-network-rx-monitor
                 symon-darwin-network-tx-monitor
                 symon-darwin-battery-monitor))
              ((memq system-type '(windows-nt))
               '(symon-current-date-time-monitor
                 symon-windows-memory-monitor
                 symon-windows-cpu-monitor
                 symon-windows-network-rx-monitor
                 symon-windows-network-tx-monitor
                 symon-windows-battery-monitor))))
  ;; (symon-mode) ; dont launch at start
  )

3.17 Terminal


;; System monitor in bar
                                        ;(use-package terminal-here
                                        ;:init
                                        ;(setq terminal-here-terminal-command (list "tilix")) ;; (list "my-terminal" "--foo")
                                        ;)
                                        ;(global-set-key (kbd "\C-xt") #'terminal-here-launch)
;; (global-set-key (kbd "C-<f6>") #'terminal-here-project-launch)

(use-package multi-term
  :defer t
  :bind (("C-?"  . hydra-term/body) ("M-<up>"  . multi-term) ("M-<left>"  . multi-term-prev) ("M-<right>"  . multi-term-next))
  :init
  (setq multi-term-program "/bin/bash")
  (setq multi-term-default-dir "~") ;; This is only used when the current buffer is not in a real directory.
  (setq multi-term-dedicated-select-after-open-p t)
  )
(global-set-key (kbd "\C-xT") 'multi-term)
(global-set-key (kbd "\C-xt") 'multi-term-dedicated-open)


                                        ;(multi-term)
                                        ;ask for name
                                        ;(rename-buffer "redshift")
(defun rename-term (name)
  (interactive "s")
  (rename-buffer (concat "*T* " name)))

(defun multi-term-new (name)
  (interactive "s")
  (multi-term)
  (rename-buffer (concat "*T* " name))
  )


;; hydra for PDF actions (type ? in PDF)
(defhydra hydra-term ()
  "term"
  ;;("+" multi-term "new")
  ("+" multi-term-new "new")
  ("p" multi-term-prev "previous")
  ("n" multi-term-next "next")
  ("o" multi-term-dedicated-open "open")
  ("c" multi-term-dedicated-close "close")
  ("t" multi-term-dedicated-toggle "toggle")
  ("s" multi-term-dedicated-select "select")
  ("r" rename-term "rename")
  ("q" nil "cancel" :color blue)) 
                                        ;(use-package term
                                        ;  :bind (:map term-mode-map ("C-<f1>" . show-term-help))
                                        ;  :config 
                                        ;  (defun show-term-help ()
                                        ;  (interactive)
                                        ;  (message-box "
                                        ;  Terminal
                                        ;  --------
                                        ;  
                                        ;  C-c C-j: line mode
                                        ;  C-c C-k: char mode
                                        ;  "))
                                        ;)

3.18 snippets

;;tab was removed from auto complete (see ac)

(use-package yasnippet
  :ensure t
  :init

  ;;git clone https://github.com/gabrielelanaro/emacs-for-python.git
  (setq yas-snippet-dirs
        '("~/.emacs.d/snippets"                 ;; personal snippets
          ))

  (yas-global-mode 1)

  ;;(global-set-key (kbd "\t") 'ac-complete-yasnippet)    ;; \t : tab
  (global-set-key (read-kbd-macro "<C-f7>") 'yas-expand)
  )

3.19 Bug fixes

;; capture error JSON
                                        ;(when (memq window-system '(mac ns x)) ;(exec-path-from-shell-initialize))
;;install path exec-path-from-shell

;;disable eldoc (messages in echo area for fct args etc...)
;;(global-eldoc-mode -1)
;;Disable documentation for object at point in the echo area. It conflicts with Flycheck.
(use-package eldoc
  :ensure nil
  :config (global-eldoc-mode -1))



3.20 Try

3.20.1 Line spacing/height

;(setq line-spacing 0.2)

3.20.2 Misc

(when (memq window-system '(mac ns x)) (exec-path-from-shell-initialize))

                                        ;(setq inverse-video t)
                                        ;(setq mode-line-inverse-video t)



(require 'multiple-cursors)
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
                                        ;(global-set-key (kbd "C->") 'mc/mark-next-like-this)
                                        ;(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
                                        ;(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
(global-set-key (kbd "C-S-<mouse-1>") 'mc/add-cursor-on-click)

                                        ;transparent background ;;active/inactive
                                        ;(set-frame-parameter (selected-frame) 'alpha '(98 . 70))
                                        ;(add-to-list 'default-frame-alist '(alpha . (98 . 70)))

(add-hook 'org-mode-hook 'toc-org-mode)

;; Garbage-collect on focus-out, Emacs should feel snappier.
(add-hook 'focus-out-hook #'garbage-collect)

(org-reload)

3.20.3 literate-calc

;;lets you write something like = uconv(33 mi, km)
(with-eval-after-load 'calc
    (defalias 'calcFunc-uconv 'math-convert-units)
    )

(defun lcalc ()
  (interactive)
  (let ((buffer (get-buffer-create (format "*calc.in"))))
    (switch-to-buffer buffer)
    (literate-calc-mode)
    (insert "LITERATE-CALC-MODE
Cheat sheet
-----------
- uconv(33 mi, km)
- round(pi, 2)
- evalv(pi), uconv(c, m/s), uconv(c, 1) to eval default with unit
- tab = [1 2 3]
- log/ln, log10, e, exp, 
-----------

")
    ))

3.20.4 popup-kill-ring

                                        ;(add-to-list 'load-path "~/.emacs.d/popup-kill-ring")
                                        ;(use-package popup-kill-ring
                                        ;  :bind ("C-y" . popup-kill-ring)
                                        ;  )
(defun view-kill ()
  (interactive)
  (save-excursion
    (save-window-excursion
      (let ((working-buffer (current-buffer))
            (new-buffer (get-buffer-create "kill-ring-view"))
            (count 0)
            (custom-map (copy-keymap minibuffer-local-map))
            (selection nil)
            )      
        (unwind-protect
            (progn
              (define-key custom-map " " 'scroll-other-window)

              (switch-to-buffer new-buffer t)
              (delete-other-windows)

              (dolist (x kill-ring)
                (insert (concat "----- " 
                                (number-to-string count) 
                                " -----"))
                (newline)
                (insert x)
                (newline)
                (newline)
                (setq count (+ count 1))
                )
              (goto-char (point-min))

              (let ((choice (read-from-minibuffer "choose: " nil custom-map t nil)))
                (and (numberp choice)
                     (< choice count)
                     (progn
                       (set-buffer working-buffer)
                       (insert (nth choice kill-ring))
                       (setq selection choice)
                       ))
                ))
          (kill-buffer new-buffer) ; unwind-protect clean-up form
          )
        selection
        ))))
(global-set-key (read-kbd-macro "M-y") 'view-kill)

4 Mails with Emacs + mbsync + gpg2

4.1 Migration process

  • I've been using Thunderbird to manage my emails for quite many years. It was for me the best "mainstream" Linux alternative among many other applications I've pretty much all tried…
  • I was never fully satisfied though, mostly because of the excruciatingly slow and tedious search, lack of integration with a nice agenda/to-do organizer, and lack of integration with the filesystem. I wanted my emails, filesystem, and agenda to communicate altogether in order to manage projects.
  • I was also never fully satisfied with the way my emails were organized (i.e., in folders). I kept creating new folders for sub/sub/sub projects, making searches even more complicated.
  • After migrating most of my workflow to EMACS (agenda with org-mode, calendar, text editing, programming, file manager…), it was clear that a good solution would be emails within EMACS.
  • There are several possibilities for this and the setup can be quite intimidating and overwhelming, so I took a few days just browsing feedback, checking pros and cons before making a final choice. Alternatives I considered were offlineimap for synchronizing and gnus, wanderlust, and notmuch for the email management.
  • Final setup chosen:
    • mbsync to synchronize (push/pull).
    • mu to index emails.
    • mu4e as the EMACS layer to mu and as an email manager.

4.2 What is an email (or why I stopped caring about folders)?

  • Emails are indeed not a to-do list, they shouldn't be kept visible/important/flagged/etc… as long as an action is not taken on them. The action must be decided when reading the email, and if there is an associated task, it belongs in the organizer! Therefore, either we remove, just read, read and reply, or read and associate a task (which can be "don't forget to reply to" or a work task).
  • Emails are just a way to communicate, and can be used to build an external, relatively independent, to-do list. They are also a (bad) way to share files, but that doesn't have to be this way (download the file & remove the attachment!).
  • Although mbsync and mu4e can deal with folders and labels (à la Xxx) very well (you just need to include them or the entire mailbox in the mbsync settings), mu4e is so good at searching (either live or with preset filters, aka "bookmarks") that folders are not that useful anymore, at least not for folders as a way to organize emails and find them quickly. Accounts/folders/labels, in my opinion, should be used as a way to manage very different scopes (e.g., work/private), and mu4e is definitely well adapted for this.
  • The point of no return is to remove all labels, thereby flattening out the mailbox. After a few weeks I realized it's really ok to have all the emails in a single inbox (actually I kept one label because I forward my work emails to Xxx and also keep this Xxx account for personal emails….). The point is that if you define an action for each email you receive, then you can forget about them. If you do need to look for specific emails, mu is more than capable. The workflow is within the organizer file (e.g., org-mode), not in the mailbox.

4.3 What this setup enables

  • Fast search queries.
  • Multiple contexts with various addresses and servers that can be switched instantly, e.g.:
    • @work: use IMAP and SMTP servers from work
    • @homework: use home SMTP, set reply-to to work address etc…
    • @xxx: use xxx IMAP and SMTP, reply-to at xxx etc…
  • mu4e is well integrated within EMACS and can communicate, for instance, with org-mode. It's possible to capture to-do items from an email and get a link, then click the link to open the email again.
  • mu4e does auto-completion of email addresses by default. It can write and read rich emails or HTML emails. Can also view emails in browser if email is really filled with images and HTML, remove attachment, and plenty of other things (see mu4e section)…

4.4 mbsync

4.4.1 Steps

  • Install mbsync (Ubuntu: sudo apt-get install isync).
  • setup password with gpg2.
  • edit .mbsyncrc file (other file names can be chose but that's the default one).

4.4.2 Configuration file .mbsynrc

IMAPAccount xxx
# Address to connect to
Host imap.xxx.com
User myname@xxx.com
# Pass passwordinclearsobadidea
# To store the password in an encrypted file use PassCmd instead of Pass
PassCmd "gpg2 -q --for-your-eyes-only --no-tty -d ~/.authinfo.gpg | awk '/machine imap.xxx.com login myname@xxx.com/ {print $NF}'"

# Port 993
# Use SSL
AuthMechs Login
SSLType IMAPS
#SSLVersions SSLv3
# Try one of the following
CertificateFile /etc/ssl/certs/ca-certificates.crt
#CertificateFile /opt/local/share/curl/curl-ca-bundle.crt
#CertificateFile ~/.cert/imap.xxx.com.pem
#CertificateFile ~/.cert/Equifax_Secure_CA.pem
#CertificateFile /etc/ssl/certs/ca-bundle.crt

#------------------------------------------------------------------

IMAPStore xxx-remote
Account xxx

MaildirStore xxx-local
# The trailing "/" is important
Path ~/.mail/xxx/
Inbox ~/.mail/xxx/Inbox

#------------------------------------------------------------------

Channel xxx-inbox
Master :xxx-remote:
Slave :xxx-local:
Patterns "INBOX"
Create Both
Expunge Both
SyncState *

#can choose a different name for local
Channel xxx-mylabel1
Master :xxx-remote:"label1"
Slave :xxx-local:"Local_label1"
Create Both
Expunge Both
SyncState *

#better to remove space in local name
Channel xxx-drafts
Master :xxx-remote:"[Xxx]/Sent Mail"
Slave :xxx-local:"[Xxx].SentMail"
Create Both
Expunge Both
SyncState *

Channel xxx-drafts
Master :xxx-remote:"[Xxx]/Drafts"
Slave :xxx-local:"[Xxx].Drafts"
Create Both
Expunge Both
SyncState *

#...

Group xxx
Channel xxx-mylabel2
Channel xxx-drafts
Channel xxx-inbox

# can repeat IMAPAccount
  • Quick remarks pertaining to Xxx:
    • IMAP must be enabled (through the Xxx web interface)
    • IMAP folder names are "regionalized" (i.e., they have different names depending on which language you choose, again through the web interface).
    • It seems that spaces in local (slave) folders can create some problems, e.g., with commands ran through mu4e (particularly relevant for "Sent Mail").
  • It is useful to do a manual synchronization in verbose mode in the terminal first (i.e., not in mu4e) to make sure everything is in order (when comparing number of messages sync'ed, remember that your mailbox, e.g., Xxx, may return conversations and not individual messages). Synchronization may be done in the following ways:
    • sync one channel: mbsync -V xxx-inbox
    • sync one group: mbsync -V xxx
    • sync all: mbsync -aV
    • sync, specifying the file: mbsync -c ~.mbsyncrc/
  • If no password is provided (no Pass or PassCmd), it will be prompted in the terminal. This makes initial tests easy to make sure mbsync is working fine. The password cannot be prompted in the mu4e interface, so it will have to be provided through an encrypted file (see following).
  • Mail index can also be tested manually with mu:
mu index --maildir=~/.mail

If a message appears that the database needs update, do mu index -rebuild.

  • If moving cur/new/tmp folders around between maildirs, and error message "Maildir error: UID 2 is beyond highest assigned UID 1", use "rename 's/,U=[1-9][0-9]*.*//' /" in the maildir where the files have been moved (this will rename all files in cur and new to remove everything after ,U=)

4.4.3 Troubleshooting

  • If a timeout occurs (Socket error on imap.xxx.com: timeout), try removing hidden files in corresponding maildir/folder (e.g., Inbox), and synchronize again manually with, e.g., mbsync -V xxx-inbox. Also try removing entire channel and resychronize

4.5 gpg2 password management

4.5.1 Solution 1

  • First, create a temporary file (e.g., ~/tmp) with your password inside.
  • Make sure ~.gnupg/ is not owned by root.
  • Then:
gpg2 --output .mbsyncpass.gpg --symmetric tmp

and provide passphrase.

  • Remove temporary file!
  • Use in .mbsynrc the following:
PassCmd "gpg2 -q --for-your-eyes-only --no-tty -d .mbsyncpass.gpg"

4.5.2 Solution 2 (preferred)

  • First create a temporary file (e.g., ~/tmp) with:
machine imap.xxx.com login myname@xxx.com password MYPASSWORD
machine smtp.xxx.com login myname@xxx.com password MYPASSWORD
machine imap.xxx.com login myname2@xxx.com password2 MYPASSWORD
machine smtp.xxx.com login myname2@xxx.com password2 MYPASSWORD
  • Then:
gpg2 --output .authinfo.gpg --symmetric tmp
  • Remove temporary file!
  • Use in .mbsynrc the following:
PassCmd "gpg2 -q --for-your-eyes-only --no-tty -d .authinfo.gpg | awk '/machine imap.xxx.com login myname@xxx.com/ {print $NF}'"
  • Normally the SMTP line can be used within emacs to provide the SMTP settings and password.

4.5.3 Troubleshooting

  • If mail retrieval hangs for other reasons than mailbox connection issues, make sure that gpg-agent is not stuck (e.g., by trying to view the authinfo file manually) and if necessary, kill the corresponding job.
  • make sure to use the same smtp address (e.g., gmail.com or googlemail.com but not a combination) for mbsync, authinfo, and mu4e!
  • emacs will look for the authinfo file automatically, so put all the authentication info there.

4.6 mu4e

4.6.1 Installation

  • Now we want to install mu4e (Ubuntu: sudo apt-get install mu4e).
  • Put all the necessary customization in .emacs, including SMTP server (see configuration file below).
  • Quick note: mu4e buffers have a leading space (e.g., " mu4e-main") and they don't appear in the buffer list.
  • It is useful to install w3 or html2text to convert HTML to text and altermime to remove attachment from emails. You need EMACS with ImageMagick support to display images.

4.6.2 Features

  • Here are some cool settings that are not enabled by default:
    • Don't include myself when replying to all.
    • Alerts to know when emails comes (which I don't use; I like to check messages when I decide).
  • Here are some useful additional capabilities enabled in the configuration file:
    • Compose in new frame (window).
    • Warn if there should be an attachment.
    • Always highlight some particular words in messages.
    • Quick search for all messages from sender.
    • Ask for location of URL fetched files.
    • Automatically create non-existing directories (incl. parent) when saving attachment or URL fetched file.
    • Use either filename or directory as input to save attachment.
    • Save all attachments to any directory with no confirmation.
    • Remove attachments from message.
  • The following .emacs configuration is a patchwork of many posts I found online. My apologies to people who found the solutions and whose names I didn't keep…

4.7 Screenshot

mail.png

Author: Vianney Lebouteiller

Created: 2021-01-05 Tue 11:36

Validate