nixos/home-manager/software/emacs/emacs.d/loader.org

3079 lines
92 KiB
Org Mode

#+title: Emacs Configuration
:preamble:
#+setupfile: ~/git_repos/dot_files/docs/html_themes/theme-readtheorg.setup
#+latex_header: \input{/home/andreas/nextcloud/10_documents/99_archive/0000/settings/latex/style}
#+author: Andreas Zweili
#+options: todo:t toc:nil
:end:
* Enable Options
This example code can be used to wrap a code section to dis-/enable it with a
variable.
#+begin_example
(when (boundp 'enable-ox-pandoc)
)
#+end_example
This file contains all the variables. It gets ignored by git so that the user
can modify it's content. However it's default state is commited.
#+begin_src emacs-lisp
(load-file "~/.emacs.d/variables.el")
#+end_src
* Detect Environment
With these functions its possible to create configuration sections
which only run on a specific system. The can be used like this:
#+begin_example
(when (is-mac-p)
(set-face-attribute 'default nil :height 165))
(add-hook 'after-make-frame-functions
(lambda ()
(if window-system
)))
#+end_example
Taken from this configuration:
- https://github.com/mwfogleman/.emacs.d/blob/master/michael.org
#+begin_src emacs-lisp
(defun is-mac-p ()
(eq system-type 'darwin))
(defun is-linux-p ()
(eq system-type 'gnu/linux))
(defun is-windows-p ()
(or (eq system-type 'ms-dos)
(eq system-type 'windows-nt)
(eq system-type 'cygwin)))
(defun is-bsd-p ()
(eq system-type 'gnu/kfreebsd))
#+end_src
* Packages
** Repositories
*** MELPA
Melpa is an alternative repository for Emacs packages. Usually they
are comming directly from a git repository. This can make them
sometimes a bit unstable.
- https://melpa.org/#/
#+begin_src emacs-lisp
;; MELPA
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/"))
#+end_src
*** Org-mode
Even though org-mode comes with Emacs by default I would like to use
the newever version from it's repository.
#+begin_src emacs-lisp
;; org-mode
;(add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t)
#+end_src
** use-package
Use-package is a very handy package which can automatically download
specified packages. This helps with reinstalling Emacs. In addition it
allows you to load the packages and their configuration only when they
are needed. This helps with Emacs' startup time.
#+begin_src emacs-lisp
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(require 'use-package)
(use-package use-package-ensure-system-package
:ensure t)
#+end_src
** evil-mode
Evil-mode is a package which emulates Vim in Emacs.
#+begin_src emacs-lisp
;; evil-mode allows to use vim keybindings
(use-package evil
:ensure t
:config
;; Start these modes in emacs mode
(add-to-list 'evil-emacs-state-modes 'deft-mode)
(add-to-list 'evil-emacs-state-modes 'neotree-mode)
(add-to-list 'evil-emacs-state-modes 'helpful-mode)
(setq global-evil-search-highlight-persist t)
;; Start these modes in insert mode
(evil-set-initial-state 'mu4e-compose-mode 'insert)
;; Add vim keybindings to the bookmark menu
(evil-add-hjkl-bindings bookmark-bmenu-mode-map 'emacs
;; (kbd "/") 'evil-search-forward
(kbd "n") 'evil-search-next
(kbd "N") 'evil-search-previous
(kbd "C-d") 'evil-scroll-down
(kbd "C-u") 'evil-scroll-up
(kbd "C-w C-w") 'other-window)
;; Add vim keybindings to the ibuffer
(evil-add-hjkl-bindings ibuffer-mode-map 'emacs
;; (kbd "/") 'evil-search-forward
(kbd "n") 'evil-search-next
(kbd "N") 'evil-search-previous
(kbd "C-d") 'evil-scroll-down
(kbd "C-u") 'evil-scroll-up
(kbd "C-w C-w") 'other-window)
;; Add vim keybindings to the package mode
(evil-add-hjkl-bindings package-menu-mode-map 'emacs
;; (kbd "/") 'evil-search-forward
(kbd "n") 'evil-search-next
(kbd "N") 'evil-search-previous
(kbd "C-d") 'evil-scroll-down
(kbd "C-u") 'evil-scroll-up
(kbd "C-w C-w") 'other-window)
(evil-add-hjkl-bindings helpful-mode-map 'emacs
;; (kbd "/") 'evil-search-forward
(kbd "n") 'evil-search-next
(kbd "N") 'evil-search-previous
(kbd "C-d") 'evil-scroll-down
(kbd "C-u") 'evil-scroll-up
(kbd "C-w C-w") 'other-window)
;; vim keybindings for mu4e
(evil-add-hjkl-bindings mu4e-headers-mode-map 'emacs
(kbd "/") 'evil-search-forward
(kbd "n") 'evil-search-next
(kbd "N") 'evil-search-previous
(kbd "C-d") 'evil-scroll-down
(kbd "C-u") 'evil-scroll-up
(kbd "C-w C-w") 'other-window)
(evil-add-hjkl-bindings mu4e-view-mode-map 'emacs
(kbd "C-d") 'evil-scroll-down
(kbd "C-u") 'evil-scroll-up
(kbd "C-w C-w") 'other-window)
;; evilificate calendar in org-mode
(define-key org-read-date-minibuffer-local-map (kbd "M-h")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-backward-day 1))))
(define-key org-read-date-minibuffer-local-map (kbd "M-l")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-forward-day 1))))
(define-key org-read-date-minibuffer-local-map (kbd "M-k")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-backward-week 1))))
(define-key org-read-date-minibuffer-local-map (kbd "M-j")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-forward-week 1))))
(define-key org-read-date-minibuffer-local-map (kbd "M-H")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-backward-month 1))))
(define-key org-read-date-minibuffer-local-map (kbd "M-L")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-forward-month 1))))
(define-key org-read-date-minibuffer-local-map (kbd "M-K")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-backward-year 1))))
(define-key org-read-date-minibuffer-local-map (kbd "M-J")
(lambda ()
(interactive) (org-eval-in-calendar '(calendar-forward-year 1))))
(defun az-dired-up-directory ()
"Take dired up one directory, but behave like dired-find-alternate-file"
(interactive)
(let ((old (current-buffer)))
(dired-up-directory)
(kill-buffer old)))
;; evil keybindings for dired
(with-eval-after-load 'dired
(evil-define-key 'normal dired-mode-map "h" 'az-dired-up-directory)
(evil-define-key 'normal dired-mode-map "l" 'dired-find-alternate-file)
(evil-define-key 'normal dired-mode-map "o" 'dired-sort-toggle-or-edit)
(evil-define-key 'normal dired-mode-map "v" 'dired-toggle-marks)
(evil-define-key 'normal dired-mode-map "m" 'dired-mark)
(evil-define-key 'normal dired-mode-map "u" 'dired-unmark)
(evil-define-key 'normal dired-mode-map "U" 'dired-unmark-all-marks)
(evil-define-key 'normal dired-mode-map "c" 'dired-create-directory)
(evil-define-key 'normal dired-mode-map "n" 'evil-search-next)
(evil-define-key 'normal dired-mode-map "N" 'evil-search-previous))
;; evil keybindings for window movement
(global-set-key (kbd "M-h") 'windmove-left)
(global-set-key (kbd "M-l") 'windmove-right)
(global-set-key (kbd "M-k") 'windmove-up)
(global-set-key (kbd "M-j") 'windmove-down)
(evil-mode 1))
#+end_src
*** esc quits everything
Comming from Vim it's a bit annoying to not be able to use ESC to quit
basically everything. This code fixes this.
#+begin_src emacs-lisp
;;; esc quits
(defun minibuffer-keyboard-quit ()
"Abort recursive edit.
In Delete Selection mode, if the mark is active, just deactivate it;
then it takes a second \\[keyboard-quit] to abort the minibuffer."
(interactive)
(if (and delete-selection-mode transient-mark-mode mark-active)
(setq deactivate-mark t)
(when (get-buffer "*Completions*")
(delete-windows-on "*Completions*"))
(abort-recursive-edit)))
(define-key evil-normal-state-map [escape] 'keyboard-quit)
(define-key evil-visual-state-map [escape] 'keyboard-quit)
(define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit)
(define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit)
#+end_src
*** evil-surround
evil-surround emulates the vim-surround plugin for vim. Both plugins
allow you to surround objects with an input of your choice. E.g.
surround a word with ~"~. Which would be: ~ysiw"~
- https://github.com/emacs-evil/evil-surround/blob/master/readme.org
#+begin_src emacs-lisp
(use-package evil-surround
:ensure t
:after evil
:config
(global-evil-surround-mode 1))
#+end_src
** UI
Various packages related to UI changes.
*** color-theme
This settings provides the color-theme package and sets a color-theme
which I store in my sourec directory as the current theme.
#+begin_src emacs-lisp
;; Color theme
;; disable background in terminal
(defun on-after-init ()
(unless (display-graphic-p (selected-frame))
(set-face-background 'default "unspecified-bg" (selected-frame))))
(add-hook 'window-setup-hook 'on-after-init)
(when (boundp 'enable-color-theme)
;; load solarized color theme
(use-package solarized-theme
:ensure t
:config
(setq solarized-use-variable-pitch nil)
(setq solarized-scale-org-headlines nil)
(setq solarized-high-contrast-mode-line t)
(set-face-inverse-video 'region nil)
(load-theme 'solarized-light t)))
#+end_src
** smooth-scrolling
I can't recall what this package does exactly, however it has to do
with scrolling in comparison to Vim.
#+begin_src emacs-lisp
;; smooth scrolling
(use-package smooth-scrolling
:ensure t
:config
(setq scroll-margin 1
scroll-conservatively 9999
scroll-step 1))
#+end_src
** Various Tools
*** deft
Deft is a mode which lets you quickly search and create notes. It
works similarly to Notational Velocity. I configured it to use org
files and open org-mode to edit. In addition it should search in all
my org files. I search through all my org files and open deft with
~F5~.
- https://github.com/jrblevin/deft
#+begin_src emacs-lisp
(use-package deft
:ensure t
:bind ("<f5>" . deft)
:commands (deft)
:config
(setq deft-extensions '("md")
deft-default-extension "md"
deft-auto-save-interval 300.0
deft-use-filename-as-title nil
deft-use-filter-string-for-filename t
deft-recursive t)
(setq deft-file-naming-rules
'((noslash . "-")
(nospace . "_")
(case-fn . downcase)))
(setq deft-directory "~/nextcloud/10_documents/"))
#+end_src
*** dash
Is required by many packages. I've added it specifically because it's
required by the org-insert-image function.
#+begin_src emacs-lisp
(use-package dash
:defer t
:ensure t)
#+end_src
*** swiper
Another dependency for the org-insert-image function.
#+begin_src emacs-lisp
(use-package swiper
:defer t
:ensure t)
#+end_src
*** s
The last depency for the org-insert-image function.
#+begin_src emacs-lisp
(use-package s
:defer t
:ensure t)
#+end_src
*** pdf-tools
pdf-tools is an alternativ for doc-view which works very nicely with
AUCTex.
https://github.com/politza/pdf-tools/blob/master/README.org
The config line is required so that a AUCTex compiled PDF gets updated
after each compilation.
#+begin_src emacs-lisp
(when (boundp 'enable-pdf-tools)
(use-package pdf-tools
:ensure t
:mode ("\\.pdf\\'" . pdf-view-mode)
:config
(pdf-tools-install)
(setq-default pdf-view-display-size 'fit-page)
;; turn off cua so copy works
(add-hook 'pdf-view-mode-hook (lambda () (cua-mode 0)))
;; keyboard shortcuts
(define-key pdf-view-mode-map (kbd "C-w C-w") 'other-window)
(define-key pdf-view-mode-map (kbd "j") 'pdf-view-next-page-command)
(define-key pdf-view-mode-map (kbd "k") 'pdf-view-previous-page-command)
(define-key pdf-view-mode-map (kbd "h") 'pdf-annot-add-highlight-markup-annotation)
(define-key pdf-view-mode-map (kbd "t") 'pdf-annot-add-text-annotation)
(define-key pdf-view-mode-map (kbd "D") 'pdf-annot-delete)
(add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer)))
#+end_src
*** treemacs
Treemacs is a tool which display a file explorer in a little buffer on
the side of your main buffer. This is very useful if you're working on
a project which consists of multiple files. It even understands some
files and can display their sections (org-mode), or classes (python).
- https://github.com/Alexander-Miller/treemacs
#+begin_src emacs-lisp
(use-package treemacs
:ensure t
:bind ("<f12>" . treemacs)
:config
(progn
(use-package treemacs-evil
:ensure t
:demand t)))
#+end_src
*** yasnippet
Yasnippet is a package with which you can insert code or text snippets
based on templates. It already comes with a wide variety of snippets
and you can easily define your own.
- https://github.com/joaotavora/yasnippet
#+begin_src emacs-lisp
;; enable yasnippet
(use-package yasnippet
:ensure t
:config
(yas-global-mode 1))
#+end_src
**** yasnippet-snippets
The default snippets got moved into their seperate package. I'm
loading it after the main yasnippet package.
#+begin_src emacs-lisp
;; enable yasnippet
(use-package yasnippet-snippets
:ensure t
:after yasnippet
:config
(yas-global-mode 1))
#+end_src
**** org-mode snippets
| key | function |
|-----------+-----------------------------------------|
| img_ | insert an html snippet for images |
|-----------+-----------------------------------------|
| pic_ | inserts a snippet for latex images |
|-----------+-----------------------------------------|
| orgtemp | inserts a template for org files |
|-----------+-----------------------------------------|
| orgrev | template for org-reveal |
|-----------+-----------------------------------------|
| orgbeamer | template for beamer presentations |
|-----------+-----------------------------------------|
| clk | template for a clock report |
|-----------+-----------------------------------------|
| orgconf | template for config files writen in org |
|-----------+-----------------------------------------|
| _project | inserts a section for a new project |
|-----------+-----------------------------------------|
*** which-key
Displays a small buffer which shows all the possible key combinations
you can press at the current moment.
- https://github.com/justbur/emacs-which-key
#+begin_src emacs-lisp
;; which key is a package to show which keys can be pressed
(use-package which-key
:ensure t
:diminish which-key-mode
:config
(which-key-mode))
#+end_src
*** discover-my-major
discover-my-major is a package which shows you all the keybindings
related to the current major mode. While you can get this information
with the ~C-h m~ keybindings it's a bit easier to view in this mode.
- https://github.com/steckerhalter/discover-my-major
#+begin_src emacs-lisp
(use-package discover-my-major
:ensure t
:bind ("C-h C-m" . discover-my-major))
#+end_src
*** langtool
#+BEGIN_SRC emacs-lisp
(when (boundp 'enable-langtool)
(use-package langtool
:ensure t
:defer t
:config
(setq langtool-language-tool-jar "~/.emacs.d/languagetool/languagetool-commandline.jar")))
#+END_SRC
*** hydra
This code has been taken from this post:
https://sam217pa.github.io/2016/09/23/keybindings-strategies-in-emacs/
I should read it again to get a better understanding of hydra and general.
#+begin_src emacs-lisp
(use-package hydra
:ensure t)
(defhydra hydra-buffer (:color red :columns 3)
"
Buffers :
"
("n" next-buffer "next")
("b" ivy-switch-buffer "switch")
("B" ibuffer "ibuffer")
("p" previous-buffer "prev")
("C-b" buffer-menu "buffer menu")
("N" evil-buffer-new "new")
("d" kill-this-buffer "delete")
;; don't come back to previous buffer after delete
("D" (progn (kill-this-buffer) (next-buffer)) "Delete")
("s" save-buffer "save"))
(defhydra hydra-window-operations (:color red :columns 3)
"
Windows :
"
("h" windmove-left "left")
("l" windmove-right "right")
("j" windmove-down "down")
("k" windmove-up "up")
("w" (lambda () (interactive) (other-window 1)) "Unkown")
("h" split-window-vertically "horizontal split")
("v" split-window-horizontally "vertical split")
("o" delete-other-windows "Delete all other")
("X" delete-window "Delete this")
("x" (lambda ()
(interactive)
(ace-window 16)
(add-hook 'ace-window-end-once-hook
'hydra-window/body)) "Unknown")
("z" (lambda ()
(interactive)
(ace-window 4)
(add-hook 'ace-window-end-once-hook
'hydra-window/body)) "Swap")
("=" balance-windows "Balance")
("K" kill-this-buffer "Kill Buffer")
("D" kill-all-dired-buffers "Kill all dired")
("a" ace-window "Ace")
("S" toggle-window-split "Toggle Split"))
;https://www.reddit.com/r/emacs/comments/931la6/tip_how_to_adopt_flycheck_as_your_new_best_friend/
(defhydra hydra-flycheck (:color blue)
"
^
^Flycheck^ ^Errors^ ^Checker^
^────────^──────────^──────^────────────^───────^─────
_q_ quit _<_ previous _?_ describe
_M_ manual _>_ next _d_ disable
_v_ verify setup _f_ check _m_ mode
^^ _l_ list _s_ select
^^ ^^ ^^
"
("q" nil)
("<" flycheck-previous-error :color pink)
(">" flycheck-next-error :color pink)
("?" flycheck-describe-checker)
("M" flycheck-manual)
("d" flycheck-disable-checker)
("f" flycheck-buffer)
("l" flycheck-list-errors)
("m" flycheck-mode)
("s" flycheck-select-checker)
("v" flycheck-verify-setup))
(defhydra hydra-ediff (:color blue :columns 3)
"
Ediff :
"
("b" ediff-buffers "buffers")
("B" ediff-buffers3 "buffers 3-way")
("f" ediff-files "files")
("F" ediff-files3 "files 3-way")
("c" ediff-current-file "current file")
("r" ediff-revision "revision")
("l" ediff-regions-linewise "linewise")
("w" ediff-regions-wordwise "wordwise"))
(defhydra hydra-yasnippet (:color blue :columns 3)
"
Yasnippet:
"
("d" yas-load-directory "directory")
("e" yas-activate-extra-mode "extra")
("i" yas-insert-snippet "insert")
("f" yas-visit-snippet-file "file")
("n" yas-new-snippet "new")
("t" yas-tryout-snippet "tryout")
("l" yas-describe-tables "list")
("a" yas-reload-all "reload"))
(defhydra hydra-apropos (:color blue :columns 3)
"Apropos"
("a" apropos "apropos")
("c" apropos-command "cmd")
("d" apropos-documentation "doc")
("e" apropos-value "val")
("l" apropos-library "lib")
("o" apropos-user-option "option")
("v" apropos-variable "var")
("i" info-apropos "info")
("t" tags-apropos "tags")
("z" hydra-customize-apropos/body "customize"))
(defhydra hydra-customize-apropos (:color blue :columns 3)
"Apropos (customize)"
("a" customize-apropos "apropos")
("f" customize-apropos-faces "faces")
("g" customize-apropos-groups "groups")
("o" customize-apropos-options "options"))
(define-key Info-mode-map (kbd "?") #'hydra-info/body)
(defhydra hydra-info (:color blue
:hint nil)
"
Info-mode:
^^_]_ forward (next logical node) ^^_l_ast (←) _u_p (↑) _f_ollow reference _T_OC
^^_[_ backward (prev logical node) ^^_r_eturn (→) _m_enu (↓) (C-u for new window) _i_ndex _d_irectory
^^_n_ext (same level only) ^^_H_istory _g_oto (C-u for new window) _,_ next index item _c_opy node name
^^_p_rev (same level only) _<_/_t_op _b_eginning of buffer virtual _I_ndex _C_lone buffer
regex _s_earch (_S_ case sensitive) ^^_>_ final _e_nd of buffer ^^ _a_propos
_1_ .. _9_ Pick first .. ninth item in the node's menu.
"
("]" Info-forward-node)
("[" Info-backward-node)
("n" Info-next)
("p" Info-prev)
("s" Info-search)
("S" Info-search-case-sensitively)
("l" Info-history-back)
("r" Info-history-forward)
("H" Info-history)
("t" Info-top-node)
("<" Info-top-node)
(">" Info-final-node)
("u" Info-up)
("^" Info-up)
("m" Info-menu)
("g" Info-goto-node)
("b" beginning-of-buffer)
("e" end-of-buffer)
("f" Info-follow-reference)
("i" Info-index)
("," Info-index-next)
("I" Info-virtual-index)
("T" Info-toc)
("d" Info-directory)
("c" Info-copy-current-node-name)
("C" clone-buffer)
("a" info-apropos)
("1" Info-nth-menu-item)
("2" Info-nth-menu-item)
("3" Info-nth-menu-item)
("4" Info-nth-menu-item)
("5" Info-nth-menu-item)
("6" Info-nth-menu-item)
("7" Info-nth-menu-item)
("8" Info-nth-menu-item)
("9" Info-nth-menu-item)
("?" Info-summary "Info summary")
("h" Info-help "Info help"))
(defhydra hydra-spellchecking (:color blue :columns 3)
"
Spell Checking
"
("g" langtool-check "Check grammar")
("q" langtool-check-done "Finish grammar check")
("l" langtool-switch-default-language "Switch grammar language")
("m" langtool-show-message-at-point "unkown")
("b" langtool-correct-buffer "Correct grammar in buffer")
("s" ispell "Correct Spelling")
("d" ispell-change-dictionary "Change dictionary"))
;(define-key dired-mode-map (kbd "'") #'hydra-dired/body)
;https://github.com/abo-abo/hydra/wiki/Dired
(defhydra hydra-dired (:hint nil :color pink)
"
_+_ mkdir _v_iew _m_ark _(_ details _i_nsert-subdir wdired
_C_opy _O_ view other _U_nmark all _)_ omit-mode _$_ hide-subdir C-x C-q : edit
_D_elete _o_pen other _u_nmark _l_ redisplay _w_ kill-subdir C-c C-c : commit
_R_ename _M_ chmod _t_oggle _g_ revert buf _e_ ediff C-c ESC : abort
_Y_ rel symlink _G_ chgrp _E_xtension mark _s_ort _=_ pdiff
_S_ymlink ^ ^ _F_ind marked _._ toggle hydra \\ flyspell
_r_sync ^ ^ ^ ^ ^ ^ _?_ summary
_z_ compress-file _A_ find regexp
_Z_ compress _Q_ repl regexp
T - tag prefix
"
("\\" dired-do-ispell)
("(" dired-hide-details-mode)
(")" dired-omit-mode)
("+" dired-create-directory)
("=" diredp-ediff) ;; smart diff
("?" dired-summary)
("$" diredp-hide-subdir-nomove)
("A" dired-do-find-regexp)
("C" dired-do-copy) ;; Copy all marked files
("D" dired-do-delete)
("E" dired-mark-extension)
("e" dired-ediff-files)
("F" dired-do-find-marked-files)
("G" dired-do-chgrp)
("g" revert-buffer) ;; read all directories again (refresh)
("i" dired-maybe-insert-subdir)
("l" dired-do-redisplay) ;; relist the marked or singel directory
("M" dired-do-chmod)
("m" dired-mark)
("O" dired-display-file)
("o" dired-find-file-other-window)
("Q" dired-do-find-regexp-and-replace)
("R" dired-do-rename)
("r" dired-do-rsynch)
("S" dired-do-symlink)
("s" dired-sort-toggle-or-edit)
("t" dired-toggle-marks)
("U" dired-unmark-all-marks)
("u" dired-unmark)
("v" dired-view-file) ;; q to exit, s to search, = gets line #
("w" dired-kill-subdir)
("Y" dired-do-relsymlink)
("z" diredp-compress-this-file)
("Z" dired-do-compress)
("q" nil)
("." nil :color blue))
;https://github.com/abo-abo/hydra/wiki/PDF-Tools
(defhydra hydra-pdftools (:color blue :hint nil)
"
╭───────────┐
Move History Scale/Fit Annotations Search/Link Do │ PDF Tools │
╭──────────────────────────────────────────────────────────────────┴───────────╯
^^_g_^^ _B_ ^↧^ _+_ ^ ^ [_al_] list [_s_] search [_u_] revert buffer
^^^↑^^^ ^↑^ _H_ ^↑^ ↦ _W_ ↤ [_am_] markup [_o_] outline [_i_] info
^^_p_^^ ^ ^ ^↥^ _0_ ^ ^ [_at_] text [_F_] link [_d_] dark mode
^^^↑^^^ ^↓^ ╭─^─^─┐ ^↓^ ╭─^ ^─┐ [_ad_] delete [_f_] search link
_h_ ←pag_e_→ _l_ _N_ │ _P_ │ _-_ _b_ [_aa_] dired
^^^↓^^^ ^ ^ ╰─^─^─╯ ^ ^ ╰─^ ^─╯ [_y_] yank
^^_n_^^ ^ ^ _r_eset slice box
^^^↓^^^
^^_G_^^
--------------------------------------------------------------------------------
"
("\\" hydra-master/body "back")
("<ESC>" nil "quit")
("al" pdf-annot-list-annotations)
("ad" pdf-annot-delete)
("aa" pdf-annot-attachment-dired)
("am" pdf-annot-add-markup-annotation)
("at" pdf-annot-add-text-annotation)
("y" pdf-view-kill-ring-save)
("+" pdf-view-enlarge :color red)
("-" pdf-view-shrink :color red)
("0" pdf-view-scale-reset)
("H" pdf-view-fit-height-to-window)
("W" pdf-view-fit-width-to-window)
("P" pdf-view-fit-page-to-window)
("n" pdf-view-next-page-command :color red)
("p" pdf-view-previous-page-command :color red)
("d" pdf-view-dark-minor-mode)
("b" pdf-view-set-slice-from-bounding-box)
("r" pdf-view-reset-slice)
("g" pdf-view-first-page)
("G" pdf-view-last-page)
("e" pdf-view-goto-page)
("o" pdf-outline)
("s" pdf-occur)
("i" pdf-misc-display-metadata)
("u" pdf-view-revert-buffer)
("F" pdf-links-action-perfom)
("f" pdf-links-isearch-link)
("B" pdf-history-backward :color red)
("N" pdf-history-forward :color red)
("l" image-forward-hscroll :color red)
("h" image-backward-hscroll :color red))
(defhydra hydra-elpy (:color red)
"
Navigate errors
"
("n" next-error "next error")
("p" previous-error "previous error")
("d" (progn (call-interactively 'elpy-test-django-runner) (elpy-nav-errors/body)) "current test, Django runner" :color blue)
("t" (progn (call-interactively 'elpy-test-pytest-runner) (elpy-nav-errors/body)) "current test, pytest runner" :color blue)
("s" (progn
(switch-to-buffer-other-window "*compilation*")
(goto-char (point-max))) "switch to compilation buffer" :color blue)
("w" (venv-workon) "Workon venv…")
("q" nil "quit")
("Q" (kill-buffer "*compilation*") "quit and kill compilation buffer" :color blue)
)
#+end_src
*** NEXT general-define-key
#+begin_src emacs-lisp
(use-package general
:ensure t
:config
(general-def
:states '(normal visual insert emacs)
:prefix "SPC"
:non-normal-prefix "M-SPC"
"b" '(hydra-buffer/body t :which-key "Buffer")
"w" '(hydra-window-operations/body t :which-key "Windows")
"r" '(hydra-restclient/body t :which-key "Restclient")
"f" '(hydra-flycheck/body t :which-key "Flycheck")
"s" '(hydra-spellchecking/body t :which-key "Spell Checking")
"e" '(hydra-ediff/body t :which-key "Diffing")
"i" '(hydra-yasnippet/body t :which-key "Yasnippets")
"p" '(hydra-pdftools/body t :which-key "PDF Tools")
"y" '(hydra-elpy/body t :which-key "Elpy")
"a" '(hydra-apropos/body t :which-key "Apropos Commands")))
#+end_src
*** helpful
#+BEGIN_SRC emacs-lisp
(use-package helpful
:ensure t
:bind (("C-h f" . helpful-function)
("C-h v" . helpful-variable)
("C-h s" . helpful-symbol)
("C-h k" . helpful-key)
("C-c h f" . helpful-function)
("C-c h v" . helpful-variable)
("C-c h c" . helpful-command)
("C-c h m" . helpful-macro)
("<C-tab>" . backward-button)
:map helpful-mode-map
("M-?" . helpful-at-point)
:map emacs-lisp-mode-map
("M-?" . helpful-at-point)
:map lisp-interaction-mode-map ; Scratch buffer
("M-?" . helpful-at-point)))
#+END_SRC
*** ivy/swiper/counsel
This packages provide a much better experience in the minibuffer.
http://oremacs.com/swiper/
#+BEGIN_SRC emacs-lisp
(use-package amx
:ensure t
:config
(amx-mode t))
(use-package counsel
:ensure t
:config
(ivy-mode 1)
(counsel-mode 1)
(setq ivy-use-virtual-buffers t)
(setq ivy-count-format "(%d/%d) ")
(setq ivy-initial-inputs-alist nil)
(with-eval-after-load 'org
(define-key org-mode-map (kbd "C-c C-q") #'counsel-org-tag))
(global-set-key (kbd "C-c v") 'ivy-push-view)
(global-set-key (kbd "C-c V") 'ivy-pop-view)
;; (global-set-key (kbd "C-s") 'swiper-isearch)
(evil-define-key 'normal 'global "/" 'swiper-isearch)
(global-set-key (kbd "C-c g") 'counsel-git)
(global-set-key (kbd "C-c j") 'counsel-git-grep)
(global-set-key (kbd "C-c k") 'counsel-ag)
(define-key ivy-minibuffer-map (kbd "S-SPC") (lambda () (interactive) (insert " ")))
(global-set-key (kbd "C-c C-r") 'ivy-resume))
#+END_SRC
*** eyebrowse
The eyebrowse package is a very helpful package which gives you workspaces in
Emacs. The work very similar to the desktops in i3wm.
https://github.com/wasamasa/eyebrowse
#+BEGIN_SRC emacs-lisp
(use-package eyebrowse
:ensure t
:init
(setq eyebrowse-keymap-prefix (kbd "C-c M-e"))
(global-unset-key (kbd "C-c C-w"))
(define-key evil-normal-state-map "gt" 'eyebrowse-next-window-config)
(define-key evil-normal-state-map "gT" 'eyebrowse-prev-window-config)
(define-key evil-normal-state-map "gr" 'eyebrowse-rename-window-config)
(define-key evil-normal-state-map "gc" 'eyebrowse-close-window-config)
:config
(setq eyebrowse-new-workspace t)
(setq eyebrowse-switch-back-and-forth t)
(setq eyebrowse-wrap-around t)
(eyebrowse-setup-opinionated-keys)
(eyebrowse-mode 1))
#+END_SRC
*** move-text
https://github.com/emacsfodder/move-text
#+begin_src emacs-lisp
(use-package move-text
:ensure t
:config
(move-text-default-bindings))
#+end_src
*** gnu-elpa-keyring-update
#+begin_src emacs-lisp
(use-package gnu-elpa-keyring-update
:ensure t)
#+end_src
** Language Support
The following package provide an improved support for their
corresponding language.
*** web-mode
#+begin_src emacs-lisp
;; web-mode for general web development
(use-package web-mode
:ensure t
:mode
(("\\.phtml\\'" . web-mode)
("\\.tpl\\'" . web-mode)
("\\.[agj]sp\\'" . web-mode)
("\\.as[cp]x\\'" . web-mode)
("\\.erb\\'" . web-mode)
("\\.mustache\\'" . web-mode)
("\\.djhtml\\'" . web-mode)
("\\.html?\\'" . web-mode))
:config
(add-to-list 'auto-mode-alist '("\\.php$" . my/php-setup))
(add-to-list 'auto-mode-alist '("\\.phpi$" . my/php-setup)))
#+end_src
*** markdown-mode
Provides syntax highlighting and other functions for markdown.
#+begin_src emacs-lisp
;; add markdown-mode to edit markdown files
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "multimarkdown"))
#+end_src
*** powershell
Provides syntax highlighting and other functions for powershell
scripts.
#+begin_src emacs-lisp
;; enable powershell-mode
(use-package powershell
:ensure t
:mode
(("\\.ps1\\'" . powershell-mode)
("\\.psm1\\'" . powershell-mode)))
#+end_src
*** auctex
Auctex is a great package which helps you a lot when you're writing
LaTeX documents.
#+begin_src emacs-lisp
(when (boundp 'enable-auctex)
;; auctex a greate plugin for latex writing
(use-package latex
:if (is-linux-p)
:ensure auctex
:mode ("\\.tex\\'" . latex-mode)
:ensure-system-package
(pdflatex . texlive-full)
:config
(setq-default TeX-master nil)
(setq TeX-auto-save t)
(setq TeX-parse-self t)
(setq TeX-electric-math (quote ("\\(" . "\\)")))
(setq LaTeX-electric-left-right-brace t)
(setq TeX-view-program-selection
(quote
(((output-dvi has-no-display-manager)
"dvi2tty")
((output-dvi style-pstricks)
"dvips and gv")
(output-dvi "xdvi")
(output-pdf "PDF Tools")
(output-html "xdg-open"))))))
#+end_src
*** yaml-mode
A mode to work with yaml files.
#+begin_src emacs-lisp
(use-package yaml-mode
:defer t
:mode
(("\\.yml\\'" . yaml-mode)
("\\.yaml\\'" . yaml-mode))
:interpreter ("yml" . yml-mode)
:ensure t)
#+end_src
*** python-mode
While Emacs comes by default with python-mode installed. I want to use
the updated version from Melpa.
#+begin_src emacs-lisp
(use-package python-mode
:ensure t
:defer t
:config
(setq python-shell-interpreter "python3"))
#+end_src
*** elpy
elpy is a package which helps you greatly with writing Python code. It
provides all the things you would wish from an IDE.
- https://github.com/jorgenschaefer/elpy
#+begin_src emacs-lisp
(use-package elpy
:ensure t
:config
(setq elpy-rpc-python-command "python3")
(setq elpy-test-runner 'elpy-test-pytest-runner)
(setq eldoc-idle-delay 1)
(add-hook 'python-mode-hook (lambda () (highlight-indentation-mode -1)))
(elpy-enable))
#+end_src
** Coding Tools
*** company-mode
company-mode is a package to provide auto-complete functionality.
- https://company-mode.github.io/
#+begin_src emacs-lisp
(use-package company
:ensure t
:bind
("C-<tab>" . company-complete)
:config
(setq company-idle-delay 0)
(define-key company-active-map (kbd "TAB") 'company-complete-common-or-cycle)
(define-key company-active-map (kbd "<tab>") 'company-complete-common-or-cycle)
(setq company-dabbrev-downcase nil)
(add-hook 'after-init-hook 'global-company-mode)
;; Add yasnippet support for all company backends
(defvar company-mode/enable-yas t
"Enable yasnippet for all backends.")
(defun company-mode/backend-with-yas (backend)
(if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend)))
backend
(append (if (consp backend) backend (list backend))
'(:with company-yasnippet))))
(setq company-backends (mapcar #'company-mode/backend-with-yas company-backends)))
#+end_src
**** company-auctex
Auctex support for company-mode.
- https://github.com/alexeyr/company-auctex/
#+begin_src emacs-lisp
(when (boundp 'enable-auctex)
(use-package company-auctex
:if (is-linux-p)
:ensure t
:after auctex
:defer t
:init
(add-hook 'LaTeX-mode-hook 'company-auctex-init)))
#+end_src
**** company-web
https://github.com/dakra/dmacs/blob/master/init.org
#+BEGIN_SRC emacs-lisp
(use-package company-web
:ensure t
:after web-mode
:commands company-web-html
:config
(require 'company-web-html)
;; Tide completion support in web-mode with company-mode
(defun my-web-mode-hook ()
"Hook for `web-mode'."
(set (make-local-variable 'company-backends)
'(company-tide company-web-html company-yasnippet company-files)))
(add-hook 'web-mode-hook 'my-web-mode-hook)
;; Enable JavaScript completion between <script>...</script> etc.
(defadvice company-tide (before web-mode-set-up-ac-sources activate)
"Set `tide-mode' based on current language before running company-tide."
(if (equal major-mode 'web-mode)
(let ((web-mode-cur-language
(web-mode-language-at-pos)))
(if (or (string= web-mode-cur-language "javascript")
(string= web-mode-cur-language "jsx"))
(unless tide-mode (tide-mode))
(if tide-mode (tide-mode -1)))))))
#+END_SRC
**** company-restclient
https://github.com/dakra/dmacs/blob/master/init.org
#+BEGIN_SRC emacs-lisp
(use-package company-restclient
:ensure t
:after (restclient company)
:config (add-to-list 'company-backends 'company-restclient))
#+END_SRC
*** magit
Magit is a package which allows you to control git from within Emacs.
It's really great and makes using git so much easier. Thanks to Magit
alone I think I became a much better git user.
- https://magit.vc/
#+begin_src emacs-lisp
;; enable magit a great git porcelain.
(use-package magit
:ensure t
:commands magit-status
:bind
("<f10>" . magit-status))
#+end_src
*** rainbow-delimiters
Each level of parantheses has it's own colour to differentiate them
more easily.
#+begin_src emacs-lisp
;; change the colours of parenthesis the further out they are
(use-package rainbow-delimiters
:ensure t
:config
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode))
#+end_src
*** elisp-bug-hunter
This package let's you debug your Emacs config which makes it easier
to find bugs before you restart Emacs.
https://github.com/Malabarba/elisp-bug-hunter/blob/master/README.org
#+begin_src emacs-lisp
(use-package bug-hunter
:defer t
:ensure t)
#+end_src
*** flycheck
flycheck is a handy tool to provide syntax checking on the fly.
- http://www.flycheck.org/en/latest/
#+begin_src emacs-lisp
(use-package flycheck
:ensure t)
#+end_src
*** highlight-indent-guides
This mode shows lines to display the current level of indentation. I've enabled
it in text- and prog-modes.
https://github.com/DarthFennec/highlight-indent-guides
#+BEGIN_SRC emacs-lisp
(use-package highlight-indent-guides
:ensure t
:config
(setq highlight-indent-guides-method 'character
hightlight-indentation-mode nil
highlight-indent-guides-auto-enabled nil)
(set-face-background 'highlight-indent-guides-odd-face "darkgray")
(set-face-background 'highlight-indent-guides-even-face "gray")
(set-face-foreground 'highlight-indent-guides-character-face "gray")
(add-hook 'text-mode-hook 'highlight-indent-guides-mode)
(add-hook 'prog-mode-hook 'highlight-indent-guides-mode))
#+END_SRC
*** direnv
Enable direnv support.
#+begin_src emacs-lisp
(use-package direnv
:config
(direnv-mode))
#+end_src
*** format-all
#+begin_src emacs-lisp
(use-package format-all
:ensure t
:hook
((prog-mode . format-all-ensure-formatter)
(yaml-mode . format-all-ensure-formatter)
(prog-mode . format-all-mode))
:preface
(defun nebucatnetzer/format-code ()
"format buffer."
(interactive)
(format-all-buffer))
:config
(global-set-key (kbd "C-c C-f") #'nebucatnetzer/format-code)
(setq format-all-show-errors 'errors))
#+end_src
* Email
Requires the following packages to be installed:
#+BEGIN_EXAMPLE
offlineimap mu4e w3m
#+END_EXAMPLE
After a fresh installation you have to first sync your emails with ~offlineimap
-o~. Afterwards run ~mu index --maildir=~/Maildir~.
#+BEGIN_SRC emacs-lisp
(when (boundp 'enable-email)
(use-package mu4e
:if (is-linux-p)
:config
(require 'smtpmail)
;; use msmtp
(setq message-send-mail-function 'message-send-mail-with-sendmail)
(setq sendmail-program "msmtp")
(require 'mu4e)
(require 'org-mu4e)
(setq mu4e-completing-read-function (quote ivy-completing-read))
(setq mail-user-agent 'mu4e-user-agent)
(setq mu4e-drafts-folder "/personal/Drafts")
(setq mu4e-sent-folder "/personal/Sent")
(setq mu4e-trash-folder "/personal/Trash")
(setq mu4e-refile-folder "/personal/Archive")
(setq browse-url-browser-function 'browse-url-generic
browse-url-generic-program "firefox")
(require 'mu4e-contrib)
(setq mu4e-html2text-command 'mu4e-shr2text)
(add-to-list 'mu4e-view-actions
'("ViewInBrowser" . mu4e-action-view-in-browser) t)
(setq mu4e-headers-fields
'((:date . 10) ;; alternatively, use :human-date
(:flags . 5)
(:from . 22)
(:subject . nil))) ;; alternatively, use :thread-subject
(setq mu4e-get-mail-command "offlineimap -qo"
mu4e-update-interval 120
mu4e-headers-auto-update t
mu4e-compose-format-flowed t
mu4e-index-update-in-background t
mu4e-compose-dont-reply-to-self t
mu4e-attachment-dir "~/nextcloud/10_documents/01_inbox"
mu4e-compose-signature-auto-include nil)
(add-hook 'mu4e-view-mode-hook 'visual-line-mode)
(setq mu4e-maildir-shortcuts
'(("/personal/INBOX" . ?i)
("/personal/Sent" . ?s)
("/personal/Trash" . ?t)
("/personal/Archive" . ?a)
("/personal/Drafts" . ?d)))
;; show images
(setq mu4e-show-images t)
;; general emacs mail settings; used when composing e-mail
;; the non-mu4e-* stuff is inherited from emacs/message-mode
(setq mu4e-reply-to-address "andreas@zweili.ch")
(setq message-kill-buffer-on-exit t)
;; Don't ask for a 'context' upon opening mu4e
(setq mu4e-context-policy 'pick-first)
;; Don't ask to quit
(setq mu4e-confirm-quit nil)
;; spell check
(add-hook 'mu4e-compose-mode-hook
(defun my-do-compose-stuff ()
"My settings for message composition."
(setq mu4e-compose-format-flowed t)
(use-hard-newlines -1)
(turn-off-auto-fill)
(flyspell-mode)))))
#+END_SRC
* UI Changes
** Hide the menu and toolbar
I like to work in a distraction free editor that's why I hide all the
menues, toolbars and scrollbars.
#+begin_src emacs-lisp
;; disable menu and toolbar
(tool-bar-mode -1)
(menu-bar-mode -99)
(when (boundp 'enable-scroll-bar)
(scroll-bar-mode -1))
#+end_src
** Line wrapping
By default Emacs doesn't do line wrapping. Instead it shows you on the
edge of the buffer a marker to indicate that the line continues
further. I'm not really a fan of this behaviour, that's why I disable
it and enable proper line wrapping.
*** enable line wrapping
#+begin_src emacs-lisp
; Proper line wrapping
(global-visual-line-mode 1)
#+end_src
*** disable fringe mode
fringe-mode are the little markers on the side of the buffer which
show when a line continues over the edge. Since I use visual-line-mode
this settings isn't required anymore.
#+begin_src emacs-lisp
(when (boundp 'disable-fringe)
; Disable fringe because I use visual-line-mode
(set-fringe-mode '(0 . 0)))
#+end_src
** Disable the splash screen
Emacs usually displays a splash screen with some helpful information
for beginners. I don't really need that anymore.
#+begin_src emacs-lisp
; Disable splash screen
(setq inhibit-splash-screen t)
#+end_src
** Disable tooltips
Can't remember how they look like but I've disabled them
probably for a reason :).
#+begin_src emacs-lisp
(tooltip-mode -1)
(setq tooltip-use-echo-area t)
#+end_src
** Prompts
*** Y and N are enough
I don't want to type the whole word. The starting characters should be
enough.
#+begin_src emacs-lisp
;; disable or reconfigure prompts
(fset 'yes-or-no-p 'y-or-n-p) ;; remap yes or no to y or n
#+end_src
*** Don't prompt on buffer creation
"Yes I'm sure that I want to create a new buffer.", options.
#+begin_src emacs-lisp
(setq confirm-nonexistent-file-or-buffer nil);; just create buffers don't ask
(setq ido-create-new-buffer 'always)
#+end_src
** Hightlight whitespace
This options shows you where you accidentally left some bad
whitespace.
#+begin_src emacs-lisp
;; highlight bad whitespace
(use-package whitespace
:ensure t
:config
(setq whitespace-style '(face lines-tail tabs trailing))
(set-face-attribute 'whitespace-line nil :foreground "#af005f")
(global-whitespace-mode t))
#+end_src
** Font
Set the font to the nice Source Code Pro. I think it works quite well for coding
as well as writing text.
#+begin_src emacs-lisp
(when (boundp 'enable-font)
(set-face-attribute 'default nil
:family "Source Code Pro"
:height 120
:weight 'normal
:width 'normal))
#+end_src
** Doc-view resolution
By default the doc-view looks a bit fuzzy. With a resolution of 200
it's much more comfortable to read a PDF.
#+begin_src emacs-lisp
(when (boundp 'enable-pdf-tools)
;; improve the resolution of doc-view
(setq doc-view-resolution 200))
#+end_src
** Start Emacs maximized
I always want to run Emacs maximized. The easiest solution to this problem
is the following code. The downside of this is, that if Emacs is already
maximized it will switch to windowed mode.
#+begin_src emacs-lisp
(toggle-frame-maximized)
#+end_src
** mode-line settings
#+begin_src emacs-lisp
(setq-default mode-line-format
'("%e"
mode-line-front-space
;; mode-line-mule-info
mode-line-client
mode-line-modified
mode-line-remote
mode-line-frame-identification
mode-line-buffer-identification
" "
mode-line-position
(vc-mode vc-mode)
;; " "
;; mode-line-modes
" "
mode-line-misc-info
;; battery-mode-line-string
;; mode-line-end-spaces
))
#+end_src
** display line numbers
Since I'm an evil user I would like to display the line numbers relativ to the
cursor position and only show the line numbers for the visible content.
#+BEGIN_SRC emacs-lisp
(setq display-line-numbers-type 'visual)
(add-hook 'prog-mode-hook (lambda ()
(when (version<= "26.0.50" emacs-version )
(display-line-numbers-mode))))
#+END_SRC
** inhibit-compacting-font-caches
Should improve performance a bit when working with org-mode and in general
#+begin_src elisp
(setq inhibit-compacting-font-caches t)
#+end_src
* Org-mode
*Please be aware that the whole org-mode configuration is one code block.*
*While I've splitted it here for a better understanding it needs to be used*
*in it's entirety or it won't work.*
** Additional Packages
*** org-superstar
Provides prettier bullets for org-mode headings.
https://github.com/integral-dw/org-superstar-mode
#+begin_src emacs-lisp
(when (boundp 'enable-org-bullets)
;; Enable pretty bullets in org mode
(use-package org-superstar
:ensure t
:config
(add-hook 'org-mode-hook (lambda ()
(org-superstar-mode 1)))))
#+end_src
*** htmlize
This package is needed to export the current agenda view to a HTML file.
The command to do so is ~C-x C-w~.
#+begin_src emacs-lisp
;; add a package to convert the agenda view to HTML
(use-package htmlize
:ensure t
:after org)
#+end_src
*** org-man
Allows to link to man pages in an org-mode file. This can be quite
useful for taking notes about a Unix system. The code is taken from here:
https://orgmode.org/manual/Adding-hyperlink-types.html
#+BEGIN_SRC emacs-lisp
(when (is-linux-p)
;;; org-man.el - Support for links to manpages in Org
(org-add-link-type "man" 'org-man-open)
(add-hook 'org-store-link-functions 'org-man-store-link)
(defcustom org-man-command 'man
"The Emacs command to be used to display a man page."
:group 'org-link
:type '(choice (const man) (const woman)))
(defun org-man-open (path)
"Visit the manpage on PATH.
PATH should be a topic that can be thrown at the man command."
(funcall org-man-command path))
(defun org-man-store-link ()
"Store a link to a manpage."
(when (memq major-mode '(Man-mode woman-mode))
;; This is a man page, we do make this link
(let* ((page (org-man-get-page-name))
(link (concat "man:" page))
(description (format "Manpage for %s" page)))
(org-store-link-props
:type "man"
:link link
:description description))))
(defun org-man-get-page-name ()
"Extract the page name from the buffer name."
;; This works for both `Man-mode' and `woman-mode'.
(if (string-match " \\(\\S-+\\)\\*" (buffer-name))
(match-string 1 (buffer-name))
(error "Cannot create link to this man page")))
(provide 'org-man)
;;; org-man.el ends here
(require 'org-man))
#+END_SRC
*** org-ref
#+BEGIN_SRC emacs-lisp
(use-package org-ref
:ensure t
:after org
:init
(setq org-ref-completion-library 'org-ref-ivy-cite)
:config
(setq org-ref-default-citation-link "footcite")
(setq reftex-default-bibliography '("~/nextcloud/03_documents/org/notes/_resources/references.bib"))
(setq org-ref-bibliography-notes "~/nextcloud/03_documents/org/notes/bibliography_notes.org"
org-ref-default-bibliography '("~/nextcloud/03_documents/org/notes/_resources/references.bib")
org-ref-pdf-directory "~/nextcloud/03_documents/org/notes/_resources/"))
#+END_SRC
*** org-pandoc
Provides pandoc support for org-mode.
https://github.com/kawabata/ox-pandoc
#+begin_src emacs-lisp
(when (boundp 'enable-ox-pandoc)
(use-package ox-pandoc
:ensure t
:after org))
#+end_src
** General config
*** Enable org-mode
This settings make sure the org-mode is downloaded from the org
repository.
#+begin_src emacs-lisp
(use-package org
:ensure t
:pin gnu
:config
#+end_src
*** Main keybindings
This defines org-modes main keybindings which are:
- Open the agenda ~C-c a~
- Capture a task ~C-c c~
- Switch org buffer ~C-c b~
#+begin_src emacs-lisp
;; enable org-mode keys
(when (or (boundp 'enable-personal-agenda)
(boundp 'enable-work-agenda))
(define-key global-map "\C-ca" 'org-agenda))
(global-set-key "\C-cl" 'org-store-link)
(global-set-key "\C-cc" 'org-capture)
(global-set-key "\C-cb" 'org-iswitchb)
;; evil keybindings for the org-agenda
(evil-add-hjkl-bindings org-agenda-mode-map 'emacs
;;(kbd "/") 'evil-search-forward
(kbd "n") 'evil-search-next
(kbd "N") 'evil-search-previous
(kbd "C-d") 'evil-scroll-down
(kbd "C-u") 'evil-scroll-up
(kbd "c") 'org-capture
(kbd "C-w C-w") 'other-window)
#+end_src
*** Disable line split
By default the command ~M-RET~ enters a new heading which
splits the current line at the cursor position.
This can get very annoying at times that's why I disable
this behaviour.
#+begin_src emacs-lisp
;; disable line split with M-RET
(setq org-M-RET-may-split-line (quote ((default))))
#+end_src
*** Correct indentation in code blocks
Indentation in source code blocks should match the
corresponding language in the code block.
#+begin_src emacs-lisp
;; enable the correct intdentation for source code blocks
(setq org-edit-src-content-indentation 0)
(setq org-src-tab-acts-natively t)
(setq org-src-preserve-indentation t)
#+end_src
*** Archive location
I've configured the archive function so that when I archive a tasks it
gets archived into an archive folder and put into a monthly file.
#+begin_src emacs-lisp
;; archive files to a monthly file
(when (boundp 'enable-personal-agenda)
(when (is-linux-p)
(setq org-archive-location
(concat "~/nextcloud/10_documents/99_archive/2022/projects/"
(format-time-string "%Y-%m" (current-time)) "-%s::datetree/"))))
(when (boundp 'enable-work-agenda)
(when (is-windows-p)
(setq org-archive-location
(concat "~/nextcloud/03_documents/org/archive/work/"
(format-time-string "%Y-%m" (current-time)) "-%s::datetree/"))))
#+end_src
*** Todo depencies
This settings only lets you close a parent task if you closed all it's
parents.
#+begin_src emacs-lisp
;; enable todo and checkbox depencies
(setq org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
#+end_src
*** Workflow states
This configuration defines the TODO and DONE keywords one can use for headings.
*TODO keywords*
- TODO
- NEXT
- WAITING
*DONE keywords*
- DONE
- CANCELLED
If you want to change the TODO states of a heading you have to toggle
through all of them which can be quite annoying if you want to use a
state which is somewhere at the end of the list. With this setting
Emacs shows you the complete list and you can select the corresponding
key to apply your desired TODO state.
#+begin_src emacs-lisp
;; quick access for todo states
(setq org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "WAITING(w!)" "PROJECT(p)" "|" "DONE(d)")
(sequence "|" "CANCELLED(c)")))
#+end_src
*** Log workflow states
In order to keep track when I finished a tasks I would like to have a
timestamp which records this information for me.
#+begin_src emacs-lisp
(setq org-log-done 'time)
#+end_src
In addition I would like to record when I set a WAITING state for a task. This
way I know when I started waiting. This allows me for example to get back to a
person if I haven't back from them for two weeks.
#+BEGIN_SRC emacs-lisp
(setq org-log-into-drawer t)
#+END_SRC
*** Cleaner outline view
This option replaces the heading stars with indents.
Which makes the outline more readable and gives a better overview.
#+begin_src emacs-lisp
;; enable org-indent
(setq org-startup-indented t)
#+end_src
*** Capture templates
Capture templates are templates with which you can predefine tasks/projects.
Each template gets it's own keybinding which you can call from ~C-c c~.
Since I'm required to report my working hours at my job I've added
some clocking functionality to my work related capture templates. The
one I like the most ist the daily clock. This adds an entry with the
current date as a heading and starts a clock on it. This makes it very
easy to start the clock at the beginning of the day.
#+begin_src emacs-lisp
;; capture templates
(defun my/org-capture-read-file-name ()
(concat (expand-file-name (read-file-name "PROMPT: " "~/nextcloud/12_tasks/")) ".org"))
(when (boundp 'enable-personal-agenda)
(when (is-linux-p)
(setq org-capture-templates
(quote
(("t" "Adds a Next entry" entry
(file+headline "~/nextcloud/12_tasks/personal.org" "Capture")
(file "~/nextcloud/10_documents/99_archive/0000/settings/templates/temp_personal_todo.txt")
:empty-lines 1)
("n" "Add note" plain (file my/org-capture-read-file-name)
(file "~/nextcloud/10_documents/99_archive/0000/settings/templates/temp_note.txt"))
)))))
(when (boundp 'enable-work-agenda)
(when (is-windows-p)
(setq org-capture-templates
(quote
(("j" "Journal Entry" entry
(file+headline "~/nextcloud/03_documents/org/agenda/work/work.org" "Clock")
(file "~/nextcloud/10_documents/99_archive/0000/settings/templates/temp_clock_note.txt")
:empty-lines 1)
("c" "Phone call" entry (file+headline "~/nextcloud/03_documents/org/agenda/work/work.org" "Clock")
"* %U PHONE %?" :clock-in t :clock-resume t)
("t" "Adds a Next entry" entry
(file+headline "~/nextcloud/03_documents/org/agenda/work/work.org" "Capture")
(file "~/nextcloud/10_documents/99_archive/0000/settings/templates/temp_work_todo.txt")
:clock-in t :clock-resume t)
("p" "Small Project" entry
(file+headline "~/nextcloud/03_documents/org/agenda/work/work.org" "Capture")
(file "~/nextcloud/10_documents/99_archive/0000/settings/templates/temp_work_small_project.txt"))
("m" "Meeting" entry (file+headline "~/nextcloud/03_documents/org/agenda/work/work.org" "Capture")
"* %U MEETING: with %?\n" :clock-in t :clock-resume t :empty-lines 1)
("n" "Add note" plain (file my/org-capture-read-file-name)
(file "~/nextcloud/10_documents/99_archive/0000/settings/templates/temp_note.txt"))
)))))
#+end_src
*** Columns format
Adjust the format of the org-columns.
#+begin_src emacs-lisp
;; org-columns format
(setq org-columns-default-format
"%40ITEM(Task) %8Effort(Estimated Effort){:} %8CLOCKSUM %10TAGS")
#+end_src
*** Efforts
Configuration of the available effort times.
You can set efforts with ~C-c C-x e~.
#+begin_src emacs-lisp
;; available effort times
(setq org-global-properties
(quote
(("Effort_ALL" . "0 0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00"))))
#+end_src
*** Refile options
The refile option lets you move headings to other headings or into
different files. I configured org-mode so that it allows to create
parent headings and looks 6 levels deep for headings to file under.
In addition I changed the way the refile menu works. It's a bit slower
this way but gives in my opinion a better overview.
The implementation of ~nebucatnetzer-org-files-list~ has been found here:
https://emacs.stackexchange.com/questions/22128/how-to-org-refile-to-a-target-within-the-current-file
#+begin_src emacs-lisp
;; org-refile options
(setq org-refile-allow-creating-parent-nodes (quote confirm))
(setq org-refile-use-outline-path 'file
org-outline-path-complete-in-steps nil)
(defun nebucatnetzer-org-files-list ()
(delq nil
(mapcar (lambda (buffer)
(buffer-file-name buffer))
(org-buffer-list 'files t))))
(setq org-refile-targets '((nebucatnetzer-org-files-list :maxlevel . 6)))
#+end_src
*** Syntax highlighting in code blocks
By default syntax highlighting is not enabled for code blocks however
it's very nice to have that's why I enabled it.
#+begin_src emacs-lisp
(setq org-src-fontify-natively t)
#+end_src
*** Syntax highlighting for latex code
To make latex code in org-mode stand out a bit more we can enable
syntax highlighting for it.
#+begin_src emacs-lisp
(setq org-highlight-latex-and-related '(latex))
#+end_src
*** Show inline images
I want to display images in org-mode.
#+begin_src emacs-lisp
(setq org-image-actual-width (quote (500)))
(setq org-startup-with-inline-images t)
#+end_src
*** create custom id for links
When creating an internal org link this code creates a unique ID to
the heading. This allows the links to continue working even when the
file is in a new location.
#+begin_src emacs-lisp
(setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id
org-clone-delete-id t)
#+end_src
*** separate headings by an empty line
Headings should be separated by their content by an empty line. This
way the files are easier to read.
#+BEGIN_SRC emacs-lisp
(setq org-blank-before-new-entry
(quote ((heading . t)
(plain-list-item . auto))))
#+END_SRC
*** Footnotes heading
I wan't to use footnotes as references. Therefore I want the footnotes to get
stored under a heading called ressources.
#+BEGIN_SRC emacs-lisp
(setq org-footnote-section "Resources")
#+END_SRC
*** update footnotes
After a change to the footnotes in a document org-mode should update the labels.
#+BEGIN_SRC emacs-lips
(setq org-footnote-auto-adjust t)
#+END_SRC
*** org-attach-directory
Since all my org-files live in a git directory and I don't want to polute the
repository with a ton of binary files I save the attachements into a directory
synchronised by Nextcloud.
#+BEGIN_SRC emacs-lisp
(setq org-attach-directory "~/nextcloud/10_documents/99_archive/2022/resources/")
#+END_SRC
*** Faces
This section defines how org-mode looks like.
#+BEGIN_SRC emacs-lisp
(setq org-todo-keyword-faces
`(("WAITING" :foreground "#0087ff" :weight bold)
("TODO" :foreground "#d75f00" :weight bold)
("PROJECT" :foreground "#626262" :weight bold)
("NEXT" :foreground "#d70000" :weight bold)))
(set-face-attribute 'org-agenda-structure nil :inherit 'default :height 1.00)
(set-face-attribute 'org-agenda-date-weekend nil :height 1.00 :weight 'medium)
(set-face-attribute 'org-agenda-calendar-event nil :weight 'medium)
(set-face-attribute 'org-agenda-date nil :inherit 'default :height 1.00 :weight 'bold)
(set-face-attribute 'org-agenda-date-today nil :slant 'normal :weight 'bold :height 1.00)
(set-face-attribute 'org-done nil :foreground "#5f8700" :weight 'bold)
(set-face-attribute 'org-link nil :foreground "#0087ff" :underline t)
(set-face-attribute 'org-scheduled nil :foreground "#5f8700" :slant 'italic :weight 'normal)
(set-face-attribute 'org-scheduled-previously nil :foreground "#d70000" :weight 'normal)
(set-face-attribute 'org-scheduled-today nil :foreground "#5f8700" :slant 'italic :weight 'normal)
(set-face-attribute 'org-todo nil :background "nil" :foreground "#d70000" :weight 'bold)
(set-face-attribute 'org-upcoming-deadline nil :foreground "#d70000" :weight 'normal)
(set-face-attribute 'org-warning nil :foreground "#d70000" :weight 'normal)
#+END_SRC
*** org-startup-shrink-all-tables
Org-mode should display all tables in shrinked mode if the table contains a
width cookie.
#+begin_src emacs-lisp
(setq org-startup-shrink-all-tables t)
#+end_src
** Exports
*** TODO Export formats
This is currently not working correctly that's why I customized
it through org-customize.
Configures the available export formats.
#+begin_src emacs-lisp
;; org-export formats
;;(setq org-export-backends (quote (beamer html latex md odt reveal)))
#+end_src
*** html export doctype
Since we live in the 21st century org-mode should use HTML5.
#+begin_src emacs-lisp
(setq org-html-html5-fancy t
org-html-doctype "html5")
#+end_src
*** Disable TODO keywords
Usually I don't want the TODO states being dispayed in the exported files.
If i still want to have them displayed I can add the option:
#+begin_example
#+options: todo:t
#+end_example
To the beginning of the file.
#+begin_src emacs-lisp
;; disable the Todo keywords in the export
(setq org-export-with-todo-keywords nil)
#+end_src
*** Disable Tags
As with the TODO states I want to disable the tags as well.
The per file option for this setting is:
#+begin_example
#+options: tags:t
#+end_example
#+begin_src emacs-lisp
;; disable the tags in the export
(setq org-export-with-tags nil)
#+end_src
*** Place captions under tables
I want captions to appear below tables and not above.
#+begin_src emacs-lisp
(setq org-latex-caption-above nil)
#+end_src
*** Disable susb superscript
The default settings export text like ~10^2~ or ~this_file~ as 10^{2}
and this_{file}. Since I often use underline in filenames and
variables it's easiert for me to use ~10^{2}~ and ~this_{file}~ to
achieve this.
#+begin_src emacs-lisp
(setq org-export-with-sub-superscripts nil)
#+end_src
*** Smart quotes
Different languages use different types of quotes. With this option
org-mode tries to be smart about it and export the correct quotes.
#+begin_src emacs-lisp
(setq org-export-with-smart-quotes t)
#+end_src
*** Headline levels
By default org-mode exports headings down to level 3 as headings and
the rest as lists. I want it to export headings down to level 5.
#+begin_src emacs-lisp
(setq org-export-headline-levels 5)
#+end_src
*** Beamer settings
This specifies my options for Beamer exports. Level 1 headings
generate title pages, the table of contents should be called "Inhalt"
and the theme I'm using is metropolis.
#+begin_src emacs-lisp
;; options for beamer exports
(setq org-beamer-frame-level 2)
(setq org-beamer-outline-frame-options "")
(setq org-beamer-outline-frame-title "Inhalt")
(setq org-beamer-theme "metropolis")
#+end_src
*** LaTeX settings
Various LaTeX export settings. The most important one ist that I use
my own class and customize the look of the title page.
#+begin_src emacs-lisp
;; options for latex exports
(setq org-latex-classes
(quote
(("beamer" "\\documentclass{beamer}"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
("article" "\\documentclass{article}"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
("report" "\\documentclass[11pt]{report}"
("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
("book" "\\documentclass[11pt]{book}"
("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")))))
(setq org-latex-default-packages-alist nil)
(setq org-latex-listings 'listings)
(setq org-latex-title-command "\\maketitle\\newpage")
(setq org-latex-toc-command "\\tableofcontents
\\newpage
")
#+end_src
** Agenda
*** Keybinding
To have easy access to my agenda view I've bound the
F9 key to that function. Now I can access it with just
one simple key press.
#+BEGIN_SRC emacs-lisp
;; Set the agenda separator to a space character.
(setq org-agenda-block-separator " ")
;; a function to call the custom agenda view.
(defun az/custom-agenda (&optional arg)
(interactive "P")
(org-agenda arg "A"))
#+END_SRC
#+begin_src emacs-lisp
(global-set-key [f9] 'az/custom-agenda)
#+end_src
*** Hide tasks with a DONE state
Tasks which are scheduled, have a deadline or have a timestamp but are
marked DONE shouldn't get displayed in the Agenda. I usually clean
them out at the end of the week.
#+begin_src emacs-lisp
;; hide done tasks in the agenda
(setq org-agenda-skip-deadline-if-done t)
(setq org-agenda-skip-scheduled-if-done t)
(setq org-agenda-skip-timestamp-if-done t)
#+end_src
*** Custom agenda commands
When you open the agenda command selection with ~C-c a~ you can choose
these settings. They allow you to filter the current file for the TODO
state corresponding to their keybinding. This is very useful for my
weekly review.
*Sorting Strategy*
By default org-mode sorts the agenda by the category. While this is
great it mixes the NEXT actions with the WAITING actions which have a
far lower priority than the NEXT actions. With this code the WAITING
actions get sorted to the bottom.
#+begin_src emacs-lisp
;; Custom agenda command to list the stuck projects in the normal
;; agenda view.
(setq org-stuck-projects '("/PROJECT" ("NEXT") nil ""))
(setq org-agenda-custom-commands
(quote (("A" "Custom Agenda"
((agenda "" nil)
(stuck ""
((org-agenda-overriding-header "Stuck Projects")
(org-agenda-sorting-strategy
'(category-up))))
(tags-todo "TODO=\"PROJECT\" "
((org-agenda-overriding-header "Projects")
(org-agenda-sorting-strategy
'(category-up))))
nil))
;; Show all headings with the corresponding TODO state
("N" occur-tree "NEXT")
("O" occur-tree "TODO")
("W" occur-tree "WAITING"))))
#+end_src
*** Hide deadline prewarnings for scheduled tasks
By default the agenda shows you prewarnings for tasks which have a deadline.
However those don't make much sense when I already have scheduled that item
for this reason I disable the warnings for scheduled tasks.
#+begin_src emacs-lisp
;; don't show the warnings for deadlines if the item is scheduled
(setq org-agenda-skip-deadline-prewarning-if-scheduled t)
#+end_src
*** Default agenda settings
My default agenda view starts on the current day and shows the next 14
days. This gives me a good overview of whats comming and helps greatly
with scheduling tasks. In addition I added an option to better display
the tags in the agenda. With the new default settings they always get
wrapped on a new line which is quite annoying.
#+begin_src emacs-lisp
;; start the agenda on the current day and show the next 13 days
(setq org-agenda-span 14
org-agenda-start-on-weekday nil)
(setq org-agenda-tags-column -80)
(setq org-agenda-show-future-repeats (quote next))
(setq org-agenda-sorting-strategy
(quote
((agenda todo-state-up priority-down category-up))))
#+end_src
*** Dim blocked tasks
Blocked tasks are apparently dimmed by default however I still have
this setting enabled.
#+begin_src emacs-lisp
;; dimm open tasks
(setq org-agenda-dim-blocked-tasks t)
#+end_src
*** Refresh agenda after capturing a task
This function updates the agenda after you've captured a new task.
Otherwise this would be a two step process.
#+begin_src emacs-lisp
;; automatically refresh the agenda after adding a task
(add-hook 'org-capture-after-finalize-hook 'nebucatnetzer:org-agenda-redo)
(defun nebucatnetzer:org-agenda-redo ()
(interactive)
(when (get-buffer "*Org Agenda*")
(with-current-buffer "*Org Agenda*"
(org-agenda-redo t)
(message "[org agenda] refreshed!"))))
#+end_src
** Clocking
*** Remove clocks with a duration of 0
#+begin_src emacs-lisp
(setq org-clock-out-remove-zero-time-clocks t)
#+end_src
*** define clocking heading
#+BEGIN_SRC emacs-lisp
(when (boundp 'enable-clocking)
(defun start-heading-clock (id file)
"Start clock programmatically for heading with ID in FILE."
(require 'org-id)
(if-let (marker (org-id-find-id-in-file id file t))
(save-current-buffer
(save-excursion
(set-buffer (marker-buffer marker))
(goto-char (marker-position marker))
(org-clock-in)))
(warn "Clock not started (Could not find ID '%s' in file '%s')" id file)))
(defun start-main-clock ()
"This functions always clocks in to the * Clock heading"
(interactive)
(start-heading-clock "e9f71012-4370-4dd2-af8e-9ae14d86508a" "~/nextcloud/03_documents/org/agenda/work/work.org"))
(global-set-key (kbd "<f6>") 'start-main-clock))
#+END_SRC
*** Resume a running clock when emacs restarts
#+begin_src emacs-lisp
(org-clock-persistence-insinuate)
#+end_src
*** Clock out when moving task to a done state
#+begin_src emacs-lisp
(setq org-clock-out-when-done t)
#+end_src
*** Save the running clock when exiting Emacs
#+begin_src emacs-lisp
(setq org-clock-persist t)
;; Do not prompt to resume an active clock
(setq org-clock-persist-query-resume nil)
#+end_src
*** Clocking Keybindings
Clock in with ~C-x C-i~ and out with ~C-x C-o~ and ~C-x C-d~ to mark a
task as the default task.
#+begin_src emacs-lisp
(global-set-key (kbd "<f7>") 'org-clock-in)
(global-set-key (kbd "<f8>") 'org-clock-out)
(global-set-key (kbd "C-x C-d") 'org-clock-mark-default-task)
#+end_src
*** Clock table time format
At my job we have to report the times in decimal format. Therefore
it's a bit difficult when org-mode displays the time in the normal
format. This code snippets let's you display the time in decimal
format in the clock table.
#+BEGIN_SRC emacs-lisp
(setq org-duration-format (quote (("h") (special . 2))))
#+END_SRC
*** org agenda clock report
For quite some time I've used a clock table in my main org file. However I
noticed that on Windows Emacs got very slow with complicated org files.
Therefore I've looked for a way to replicate the clock table in the agenda
because it pulls from multiple files.
This way I can split the tasks over many files.
#+BEGIN_SRC emacs-lisp
(setq org-agenda-clockreport-parameter-plist
(quote (:link t :maxlevel 4 :tcolumns 3)))
#+END_SRC
** org-insert-image
This function allows to quickly insert a picture into the current org
file. The file will get renamed and moved to the file location.
I found this code on this blog post:
http://pragmaticemacs.com/emacs/a-workflow-to-quickly-add-photos-to-org-mode-notes/
#+begin_src emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; add image from conference phone upload ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; use case is taking a photo of a slide in a conference and uploading
;; it to google drive or dropbox or whatever to get it on your
;; computer. You then want to embed it in an org-mode document by
;; moving it to the same folder and renaming according to the current
;; section of the org file, avoiding name clashes
;; required libraries
(require 'dash)
(require 'swiper)
(require 's)
(global-set-key (kbd "C-c i") 'org-insert-image)
;; start directory
(defvar bjm/conference-image-dir (expand-file-name "~/Downloads/"))
(defun org-insert-image ()
"Insert image from conference directory, rename and add link in current file.
The file is taken from a start directory set by
`bjm/conference-image-dir' and moved to the current directory, renamed
and embedded at the point as an org-mode link. The user is presented
with a list of files in the start directory, from which to select the
file to move, sorted by most recent first."
(interactive)
(let (file-list target-dir file-list-sorted start-file start-file-full file-ext end-file end-file-base end-file-full file-number)
;; clean directories from list but keep times
(setq file-list
(-remove (lambda (x) (nth 1 x))
(directory-files-and-attributes bjm/conference-image-dir)))
;; get target directory
(setq target-dir (concat (file-name-directory buffer-file-name) "_resources/"))
(unless (file-exists-p target-dir)
(make-directory target-dir))
;; sort list by most recent
;; http://stackoverflow.com/questions/26514437/emacs-sort-list-of-directories-files-by-modification-date
(setq file-list-sorted
(mapcar #'car
(sort file-list
#'(lambda (x y) (time-less-p (nth 6 y) (nth 6 x))))))
;; use ivy to select start-file
(setq start-file (ivy-read
(concat "Move selected file to " target-dir ":")
file-list-sorted
:re-builder #'ivy--regex
:sort nil
:initial-input nil))
;; add full path to start file and end-file
(setq start-file-full
(expand-file-name start-file bjm/conference-image-dir))
;; generate target file name from current org section
(setq file-ext
(file-name-extension start-file t))
;; get section heading and clean it up
(setq end-file-base (s-downcase (s-dashed-words (nth 4 (org-heading-components)))))
;; shorten to first 40 chars to avoid long file names
(setq end-file-base (s-left 40 end-file-base))
;; number to append to ensure unique name
(setq file-number 1)
(setq end-file (concat
end-file-base
(format "-%s" file-number)
file-ext))
;; increment number at end of name if file exists
(while (file-exists-p (concat "_resources/" end-file))
;; increment
(setq file-number (+ file-number 1))
(setq end-file (concat
end-file-base
(format "-%s" file-number)
file-ext)))
;; final file name including path
(setq end-file-full
(expand-file-name end-file target-dir))
;; rename file
(rename-file start-file-full end-file-full)
(message "moved %s to _resources/%s" start-file-full end-file)
;; insert link
(insert (org-make-link-string (format "file:_resources/%s" end-file)))
;; display image
(org-display-inline-images t t)))
#+end_src
** Agenda file
This settings tells Emacs where to look for agenda files.
All the files in this directories and its sub directories count as
agenda files.
#+begin_src emacs-lisp
(load-library "find-lisp")
(when (boundp 'enable-personal-agenda)
(when (is-linux-p)
(setq org-agenda-files
(find-lisp-find-files "~/nextcloud/12_tasks" "\.org$"))))
(when (boundp 'enable-work-agenda)
(when (is-windows-p)
(setq org-agenda-files
(find-lisp-find-files "~/nextcloud/03_documents/org/agenda/work" "\.org$"))))
#+end_src
** org-update-cookies-after-save
It can happen that statistic cookies in an org-mode buffer don't get
updated. This function updates all the statistic cookies before the
buffer gets saved.
#+begin_src emacs-lisp
(defun org-update-cookies-after-save()
(interactive)
(let ((current-prefix-arg '(4)))
(org-update-statistics-cookies "ALL")))
(add-hook 'org-mode-hook
(lambda ()
(add-hook 'before-save-hook 'org-update-cookies-after-save nil 'make-it-local)))
#+end_src
** mark-task-as-done
This function sets a parent to the DONE state when the last of it's
children gets changed to DONE. This is especially usefull in
combination with org-edna.
- https://orgmode.org/manual/Breaking-down-tasks.html
#+begin_src emacs-lisp
(defun org-summary-todo (n-done n-not-done)
"Switch entry to DONE when all subentries are done, to TODO otherwise."
(let (org-log-done org-log-states) ; turn off logging
(org-todo (if (= n-not-done 0) "DONE" "TODO"))))
(add-hook 'org-after-todo-statistics-hook 'org-summary-todo))
#+end_src
** Personal org file
I defined ~C-c p~ to quickly jump to my personal org file.
#+begin_src emacs-lisp
;; keymap for my personal.org file
(when (boundp 'enable-personal-agenda)
(when (is-linux-p)
(global-set-key (kbd "C-c p")
(lambda () (interactive) (find-file "~/nextcloud/12_tasks/personal.org")))))
(when (boundp 'enable-work-agenda)
(when (is-windows-p)
(global-set-key (kbd "C-c p")
(lambda () (interactive) (find-file "~/nextcloud/03_documents/org/agenda/work/work.org")))))
#+end_src
* General
** User data
#+begin_src emacs-lisp
;; My details
(setq user-full-name "Andreas Zweili")
(setq user-mail-address "andreas@zweili.ch")
#+end_src
** Toggle window splits
Sometimes when emacs opens a buffer it's in a wrong orientation. With
the keybinding ~C-x 4~ I can toggle between horizontal and vertical
split.
#+begin_src emacs-lisp
;; a function to toggle the splits
(defun toggle-window-split ()
(interactive)
(if (= (count-windows) 2)
(let* ((this-win-buffer (window-buffer))
(next-win-buffer (window-buffer (next-window)))
(this-win-edges (window-edges (selected-window)))
(next-win-edges (window-edges (next-window)))
(this-win-2nd (not (and (<= (car this-win-edges)
(car next-win-edges))
(<= (cadr this-win-edges)
(cadr next-win-edges)))))
(splitter
(if (= (car this-win-edges)
(car (window-edges (next-window))))
'split-window-horizontally
'split-window-vertically)))
(delete-other-windows)
(let ((first-win (selected-window)))
(funcall splitter)
(if this-win-2nd (other-window 1))
(set-window-buffer (selected-window) this-win-buffer)
(set-window-buffer (next-window) next-win-buffer)
(select-window first-win)
(if this-win-2nd (other-window 1))))))
(define-key ctl-x-map "4" 'toggle-window-split)
#+end_src
** Split Windows and move cursor into it
Usually when I want to split the window I want the cursor to be place
into the new window because I need to manipulate that window. Emacs
doesn't do this by default but we can add that functionality.
#+begin_src emacs-lisp
(defun nebucatnetzer:split-window-below-and-move-cursor ()
(interactive)
(split-window-below)
(other-window 1))
(defun nebucatnetzer:split-window-right-and-move-cursor ()
(interactive)
(split-window-right)
(other-window 1))
(global-set-key (kbd "C-x 2") 'nebucatnetzer:split-window-below-and-move-cursor)
(global-set-key (kbd "C-x 3") 'nebucatnetzer:split-window-right-and-move-cursor)
#+end_src
** Use spaces instead of tabs
#+begin_src emacs-lisp
;; Spaces instead of TABs
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(setq indent-line-function 'insert-tab)
#+end_src
** Key bindings
*** buffer switching
ibuffer is a much better way to give an overview than the standard buffer
view in emacs. Interestingly it's already built in but not configured.
You can open it with ~C-x C-b~. Ivy is a nice tool for completions I configured
~C-x b~ to open Ivy for switching buffers.
#+begin_src emacs-lisp
;; keymap for buffer switching
(global-set-key (kbd "C-x C-b") 'ibuffer)
(global-set-key (kbd "C-x b") 'ivy-switch-buffer)
#+end_src
*** kill current buffer
Don't ask which buffer to kill, kill the current buffer with ~C-x C-k~.
#+begin_src emacs-lisp
;; kill THIS buffer
(global-set-key (kbd "C-x C-k") 'kill-this-buffer)
#+end_src
*** Copy buffer to clipboard
Sometimes it's handy to be able the complete buffer into the clipboard.
E.g. when you write an email in Emacs an want to copy it into Outlook.
This function is bound to ~C-S-c~.
#+begin_src emacs-lisp
;; copy the complete buffer to the clipboard
(defun copy-all ()
"Copy entire buffer to clipboard"
(interactive)
(clipboard-kill-ring-save (point-min) (point-max)))
(global-set-key (kbd "C-S-c") 'copy-all)
#+end_src
*** Frame Controls
This keybindings allow to create and navigate frames.
Frames are in a desktop environment usually called windows.
However because Emacs is so old it has it's own terminology.
- New frame :: ~C-x N~
- Switch to the other frame :: ~C-x O~
- Kill frame :: ~C-x K~
#+begin_src emacs-lisp
;; keybinding for new frame
(global-set-key (kbd "C-x N") 'make-frame)
;; switch to frame
(global-set-key (kbd "C-x O") 'other-frame)
;; kill frame
(global-set-key (kbd "C-x K") 'delete-frame)
#+end_src
*** Hippie Expand
This option enables hippie expand which allows for path complition and
more. You can execute it with ~M-Space~.
#+begin_src emacs-lisp
;; enable hippie expand on M-Space
(global-set-key "\M- " 'hippie-expand)
#+end_src
*** jump to minibuffer
#+begin_src emacs-lisp
(defun switch-to-minibuffer () "Switch to minibuffer window."
(interactive) (if (active-minibuffer-window)
(select-window
(active-minibuffer-window)) (error "Minibuffer is not active")))
(bind-key "M-m" 'switch-to-minibuffer)
#+end_src
** File encoding
*** Prefer Unix encoding.
#+begin_src emacs-lisp
;; file encodings
(prefer-coding-system 'utf-8-unix)
#+end_src
** Move backup files to the temp folder
With this configuration Emacs saves the backup files into the temp
directory. Otherwise they get created in the current directory which
IMO is unneeded clutter.
#+begin_src emacs-lisp
(setq backup-directory-alist
`((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
`((".*" ,temporary-file-directory t)))
#+end_src
** ibuffer, buffer groups
This function groups buffers depending on their mode which gives an
even better overview. In addition it hides temporary buffers from the
ibuffer view.
#+begin_src emacs-lisp
;; hide temporary buffers
(add-hook 'ibuffer-mode-hook
(lambda ()
(ibuffer-filter-by-name "^[^*]")))
(setq ibuffer-saved-filter-groups
(quote (("default"
("Org" ;; all org-related buffers
(mode . org-mode))
("Programming" ;; prog stuff not already in MyProjectX
(or
(mode . python-mode)
(mode . web-mode)
(mode . php-mode)
(mode . csharp-mode)
(mode . javascript-mode)
(mode . sql-mode)
(mode . powershell-mode)
(mode . emacs-lisp-mode)))
;; etc
("Dired"
(mode . dired-mode))))))
(add-hook 'ibuffer-mode-hook
(lambda ()
(ibuffer-switch-to-saved-filter-groups "default")))
#+end_src
** Initial buffer mode
When I create a new buffer it should start in text-mode.
By default Emacs uses elisp-mode.
#+begin_src emacs-lisp
;; initial buffers should use text-mode
(setq-default major-mode 'text-mode)
#+end_src
** Localization
*** First day of the week
In Switzerland weeks start on Monday not Sunday.
#+begin_src emacs-lisp
; Calender should start on Monday
(setq calendar-week-start-day 1)
#+end_src
*** Spell checking
Since I write both in English and in German I need two dictionaries.
This code configures Emacs to use the Linux dictionaries en_US and
de_CH. If you want to switch languages you need the function:
~ispell-change-dictionary~
#+begin_src emacs-lisp
;; ispell settings
(setenv "DICTIONARY" "en_US")
(setq ispell-program-name "hunspell")
(setq ispell-local-dictionary "en_US")
(setq ispell-local-dictionary-alist
'(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US") nil utf-8)
("de_CH" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "de_CH") nil utf-8)))
#+end_src
*** Spaces after periods.
#+begin_src emacs-lisp
;; insert only one space after a period
(setq sentence-end-double-space nil)
#+end_src
** Parantheses
*** Math parantheses
This setting shows matching parantheses and hightlights the ones which
don't have a counter part.
#+begin_src emacs-lisp
; Matches parentheses and such in every mode
(show-paren-mode 1)
#+end_src
*** Electric parantheses
When you insert a parenthesis it's counter pair gets inserted automatically.
#+begin_src emacs-lisp
;; pair parentheses
(electric-pair-mode 1)
#+end_src
** Auto-fill
This enables auto-fill which is basically line wrapping.
#+begin_src emacs-lisp
(add-hook 'text-mode-hook 'turn-on-auto-fill)
#+end_src
** Suppressing ad-handle-definition Warnings
This settings surpresses the following warning which shows up when
Emacs starts:
#+begin_example
ad-handle-definition: `tramp-read-passwd' got redefined
#+end_example
#+begin_src emacs-lisp
(setq ad-redefinition-action 'accept)
#+end_src
** remove bad whitespace when saving
#+begin_src emacs-lisp
(add-hook 'before-save-hook 'whitespace-cleanup)
#+end_src
** Autorefresh buffers if the file changes on disk
#+BEGIN_SRC emacs-lisp
(global-auto-revert-mode t)
#+END_SRC
** 80 characters line width
#+BEGIN_SRC emacs-lisp
(setq-default fill-column 79)
#+END_SRC
** show column number
#+BEGIN_SRC emacs-lisp
(setq column-number-mode 1)
#+END_SRC
** display emojis
Display Emoji requires the ~fonts-symbola~ Debian package.
#+BEGIN_SRC emacs-lisp
(when (boundp 'enable-emojis)
(when (is-linux-p)
(set-fontset-font t nil "Symbola" nil 'prepend)))
#+END_SRC
** kill all buffers
This function is helpful to "clean up" emacs without having to restart it.
#+BEGIN_SRC emacs-lisp
(defun kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer
(delq
(current-buffer)
(buffer-list))))
#+END_SRC
** insert date
#+begin_src emacs-lisp
(defun insert-date ()
"Insert the current date."
(interactive)
(let ((format "%d.%m.%Y")
(system-time-locale "de_CH"))
(insert (format-time-string format))))
(defun insert-iso-date ()
"Insert the current date in the ISO format."
(interactive)
(let ((format "%Y-%m-%d")
(system-time-locale "de_CH"))
(insert (format-time-string format))))
(defun insert-full-date ()
"Insert the current date, write out the day and month name."
(interactive)
(let ((format "%A, %d. %B %Y")
(system-time-locale "de_CH"))
(insert (format-time-string format))))
#+end_src
** handling large files
Taken from here:
https://github.com/jhallen/joes-sandbox/issues/29
#+begin_src emacs-lisp
(defun buffer-too-big-p ()
(or (> (buffer-size) (* 5000 64))
(> (line-number-at-pos (point-max)) 5000)))
(defun generic-setup ()
;; turn off `linum-mode' when there are more than 5000 lines
(if (buffer-too-big-p) (display-line-numbers-mode -1)))
(add-hook 'prog-mode-hook 'generic-setup)
(add-hook 'text-mode-hook 'generic-setup)
#+end_src
** remove duplicates from history
#+begin_src emacs-lisp
(setq history-delete-duplicates t)
#+end_src
** enable mouse support in terminal
#+begin_src emacs-lisp
(xterm-mouse-mode 1)
#+end_src
* Eshell
** General
Make the tab completion behave like in Bash.
#+begin_src emacs-lisp
(add-hook 'eshell-mode-hook
(lambda ()
(setq pcomplete-cycle-completions nil)))
#+end_src
* Tramp
** default-tramp-method
To improve the perfomance of tramp I use SSH instead of scp.
#+begin_src emacs-lisp
(setq tramp-default-method "ssh")
#+end_src
* LaTex
** Align Tables
This is a nice function to work with LaTeX tables. I've got it from
here: https://thenybble.de/projects/inhibit-auto-fill.html
#+begin_src emacs-lisp
(when (boundp 'enable-auctex)
(defun LaTeX-collapse-table ()
(interactive)
(save-excursion
(LaTeX-mark-environment)
(while (re-search-forward "[[:space:]]+\\(&\\|\\\\\\\\\\)" (region-end) t)
(replace-match " \\1"))))
(defun LaTeX-align-environment (arg)
(interactive "P")
(if arg
(LaTeX-collapse-table)
(save-excursion
(LaTeX-mark-environment)
(align (region-beginning) (region-end))))))
#+end_src
** Inhibiting auto-fill
"Auto-fill is nice. Filling to 80 columns (as god intended) makes code
or any other text easier to read.
However, it's not so nice for large latex tables that you want to
align properly (perhaps using align). This is why I hacked together
some elisp to inhibit auto-fill when the cursor is in a table (or any
other environment that doesn't need to be auto-filled, according to
your whims."
Taken from here:
https://thenybble.de/projects/inhibit-auto-fill.html
#+begin_src emacs-lisp
(when (boundp 'enable-auctex)
(defcustom LaTeX-inhibited-auto-fill-environments
'("tabular" "tikzpicture") "For which LaTeX environments not to run auto-fill.")
(defun LaTeX-limited-auto-fill ()
(let ((environment (LaTeX-current-environment)))
(when (not (member environment LaTeX-inhibited-auto-fill-environments))
(do-auto-fill)))))
#+end_src
** Enable the LaTeX tweaks
#+begin_src emacs-lisp
(when (boundp 'enable-auctex)
(global-set-key (kbd "C-c f") 'LaTeX-align-environment)
(setq auto-fill-function 'LaTeX-limited-auto-fill))
#+end_src
* Dired
** open a folder in the same buffer
By default dired obens a buffer for every folder one opens. With this setting
it's possible open a folder in the current buffer when pressing ~a~ on it.
#+BEGIN_SRC emacs-lisp
(put 'dired-find-alternate-file 'disabled nil)
#+END_SRC
** use human readable formats
#+BEGIN_SRC emacs-lisp
(setq-default dired-listing-switches "-alh")
#+END_SRC
** Keybindings
*** open
You can open dired with ~C-c d~
#+begin_src emacs-lisp
;; keymap for dired
(global-set-key (kbd "C-c d") 'dired-jump)
#+end_src
*** kill
By default ~q~ in dired just hides the dired buffer. However I prefer
the buffer to get killed completely.
#+begin_src emacs-lisp
(bind-keys :map dired-mode-map ("q" . az-kill-dired-buffers))
#+end_src
** Kill all dired buffers
Dired opens a lot of buffers when you use it. This functions helps to
clean up afterwards.
#+begin_src emacs-lisp
;;a function to kill all dired buffers
(defun az-kill-dired-buffers ()
(interactive)
(mapc (lambda (buffer)
(when (eq 'dired-mode (buffer-local-value 'major-mode buffer))
(kill-buffer buffer)))
(buffer-list)))
#+end_src
** dired hide dot folders
#+BEGIN_SRC emacs-lisp
(use-package dired-hide-dotfiles
:ensure t
:init
(defun my-dired-mode-hook ()
"My `dired' mode hook."
;; To hide dot-files by default
(dired-hide-dotfiles-mode)
;; To toggle hiding
(add-hook 'dired-mode-hook #'my-dired-mode-hook))
:bind
(:map dired-mode-map
("." . dired-hide-dotfiles-mode)))
#+END_SRC