anonimno

My Emacs Config

This is my Emacs config for home and work. Feel free to borrow, copy and hack … I did it myself from different sources!

init.el

To get this initialization to work place this snippet in init.el.

(require 'org)
  (org-babel-load-file
  (expand-file-name "config.org"
		    "~/org/"))

Add this to your init.el to get some nice colors and fonts.

(custom-set-faces
  '(default ((t (:inherit nil :stipple nil :background "seashell" :foreground "SystemWindowText" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 120 :width normal :foundry "outline" :family "Consolas"))))
  '(org-level-1 ((t (:inherit outline-1 :height 1.1))))
  '(region ((t (:background "#ddffdd")))))

Defaults

What system are we running on?

At work I use Windows and at home GNU/Linux.

(defvar my/work (eq system-type 'windows-nt))
(defvar my/home (eq system-type 'gnu/linux))

Interface

(setq inhibit-startup-screen t)
(setq inhibit-startup-echo-area-message t)
(setq inhibit-startup-message t)   
(tool-bar-mode 0)
(tooltip-mode  0)
(scroll-bar-mode 0)
(defalias 'yes-or-no-p 'y-or-n-p)
(global-visual-line-mode 1)

Get backups out of the way and remove littering in auto-save-list

(setq auto-save-list-file-prefix nil)

(if my/work
    (setq temporary-file-directory "C:/Users/khajvaz/AppData/Local/Temp"))

(setq backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))

Bindings

Open important files

(global-set-key (kbd "<f1>") (lambda() (interactive)(find-file "~/org/config.org")))
(global-set-key (kbd "<f2>") (lambda() (interactive)(find-file "~/org/work.org")))
(global-set-key (kbd "<f3>") (lambda() (interactive)(find-file "~/org/notes.org")))

Bind functions

Text Zoom

(global-set-key (kbd "C-c C-+") 'text-scale-increase)
(global-set-key (kbd "C-c C--") 'text-scale-decrease)
(global-set-key (kbd "C-c C-0") (lambda () (interactive)(text-scale-adjust 0)))

Revert Buffer, if not changed.

Interactive call to revert-buffer. Ignoring the auto-save file and not requesting for confirmation. When the current buffer is modified, the command refuses to revert it, unless you specify the optional argument: force-reverting to true.

(global-set-key
 (kbd "<f5>")
 (lambda (&optional force-reverting)
   (interactive "P")
   ;;(message "force-reverting value is %s" force-reverting)
   (if (or force-reverting (not (buffer-modified-p)))
       (revert-buffer :ignore-auto :noconfirm)
     (error "The buffer has been modified."))))

Packages

Setup repos

Debian Buster needs this variable to work.

(if my/home
    (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3"))

Now let's setup repos.

(require 'package)
(add-to-list 'package-archives
	     '("melpa" . "https://melpa.org/packages/"))
(package-initialize)

Use-Package

Install Use-Package, then use it for other packages.

(unless (package-installed-p 'use-package)
  (package-install 'use-package))
(eval-when-compile
      (require 'use-package))

Quelpa

Install Quelpa and Quelpa-Use-Package.

(use-package quelpa
  :ensure t
  :config
  (setq quelpa-checkout-melpa-p nil))
(quelpa
 '(quelpa-use-package
   :fetcher git
   :url "https://framagit.org/steckerhalter/quelpa-use-package.git"))
(require 'quelpa-use-package)

Spelling

(global-set-key (kbd "<f12>") 'flyspell-buffer)
(global-set-key (kbd "<f11>") 'fd-switch-dictionary)

(setq ispell-curent-dictionary "deutsch")
(setq ispell-local-dictionary "deutsch")

(if my/work
    (setq ispell-program-name "~/tools/hunspell/bin/hunspell.exe"))

(defun fd-switch-dictionary()
      (interactive)
      (let* ((dic ispell-current-dictionary)
	 (change (if (string= dic "deutsch") "english" "deutsch")))
	(ispell-change-dictionary change)
	(message "Dictionary switched from %s to %s" dic change)))

Org Mode

Basics

(setq org-startup-indented t)
(setq org-hide-emphasis-markers t)
(setq org-startup-folded t)
(setq org-log-into-drawer t)
(setq org-todo-keywords
      '((sequence "TODO(t)" "INPROGRESS(i@/!)" "WAIT(w@/!)" "|" "DONE(d@)" "CANCELED(c@)")))

Linking

Classic linking

(require 'org-id)
(setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
(define-key global-map "\C-cl" 'org-store-link)

Backlinks

(use-package org-super-links
  :quelpa (org-super-links :repo "toshism/org-super-links" :fetcher github :commit "develop")
  :bind
  (("C-c s s" . org-super-links-link)
   ("C-c s l" . org-super-links-store-link)
   ("C-c s C-l" . org-super-links-insert-link))
  :config
  (setq org-super-links-related-into-drawer t))

Capture

Basic templates.

(define-key global-map (kbd "C-c c") 'org-capture)
(setq org-capture-templates
      '(("t" "Todo" entry (file "~/org/work.org")
	 "* TODO %?\nSCHEDULED: %t\n")
	("n" "Note" entry (file "~/org/notes.org")
	 "* %U %?\n\n")
	))

At work I also need a meeting template.

(if my/work
    (add-to-list 'org-capture-templates '("m" "Meeting" entry (file "~/org/notes.org")
				      "* %U %?\n\n** Teilnehmer: \n- ?\n\n** Agenda Punkt 1\n- ?\n\n** Aufgaben:\n*** TODO ")))

Agenda

Basic stuff

(define-key global-map "\C-ca" 'org-agenda)
(setq org-agenda-window-setup (quote current-window))
(setq org-agenda-files (list "~/org/work.org" "~/org/notes.org"))
(setq org-agenda-start-day nil)
(setq org-agenda-span 7)
(setq org-agenda-start-on-weekday nil)
(setq org-agenda-skip-deadline-prewarning-if-scheduled t)
(setq org-agenda-todo-ignore-deadlines (quote all))
(setq org-agenda-todo-ignore-scheduled (quote all))
(setq org-agenda-skip-scheduled-if-done t)
(setq org-agenda-skip-deadline-if-done t)

Custom agenda views

Priority-based agenda taken from https://blog.aaronbieber.com/2016/09/24/an-agenda-for-life-with-org-mode.html Use Eisenhower for priority:

  • A = Urgent AND Important (DO NOW)
  • B = NOT Urgent and Important (DO)
  • C = Urgent and NOT Important (DELEGATE)
  • D = NOT Urgent AND NOT Important (DON'T DO)

At work I also need some custom tagging and views.

(setq org-highest-priority ?A)
(setq org-lowerst-priority ?C) 
(setq org-default-priority ?C)
(defun air-org-skip-subtree-if-priority (priority)
  (let ((subtree-end (save-excursion (org-end-of-subtree t)))
	(pri-value (* 1000 (- org-lowest-priority priority)))
	(pri-current (org-get-priority (thing-at-point 'line t))))
    (if (<= pri-value pri-current)
	subtree-end
      nil)))
(setq org-agenda-custom-commands
      '(
	("k" "Agenda for KEMAL"
	 ((tags "PRIORITY<=\"B\"" 
		((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
		 (org-agenda-overriding-header "High Priority Tasks:")))
	  (agenda "")
	  (alltodo ""
		   ((org-agenda-skip-function
		     '(or (air-org-skip-subtree-if-priority ?B)
			  (org-agenda-skip-if nil '(scheduled deadline))))))))
	("t" "Speak with the TEAM"
	 ((tags "team"
		((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
		 (org-agenda-overriding-header "Let's talk about:")))))
	("b" "Speak with the BOSS"
	 ((tags "boss"
		((org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done))
		 (org-agenda-overriding-header "Let's talk about:")))))))

Refile

(setq org-refile-targets
      '((org-agenda-files :maxlevel . 1)))
(setq org-refile-use-outline-path 'file)
(setq org-outline-path-complete-in-steps nil)

Screenshots

To use this make a screenshot with a tool that saves the picture to the clipboard. We then grab this photo, save it and insert a link to this file. For GNU/Linux I use org-download package to get this done. For Windows 10 I use a custom function from https://stackoverflow.com/questions/17435995/paste-an-image-on-clipboard-to-emacs-org-mode-file-without-saving-it, because org-download doesn't work.

(if my/home
    (define-key global-map "\C-ci" 'org-download-clipboard)
  (define-key global-map "\C-ci" 'my-org-insert-screenshot))

(when my/home
  (use-package org-download
  :ensure t
  :config
  (setq org-download-method 'attach)))

(defun my-org-insert-screenshot ()
  (interactive)
  (setq filename
	(concat
	 (make-temp-name
	  (concat "data/imgs/" (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (unless (file-exists-p (file-name-directory filename))
    (make-directory (file-name-directory filename)))
  (shell-command (concat "powershell -command \"Add-Type -AssemblyName System.Windows.Forms;if ($([System.Windows.Forms.Clipboard]::ContainsImage())) {$image = [System.Windows.Forms.Clipboard]::GetImage();[System.Drawing.Bitmap]$image.Save('" filename "',[System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'clipboard content saved as file'} else {Write-Output 'clipboard does not contain image data'}\""))
  (if (file-exists-p filename)
      (insert (concat "[[file:" filename "]]"))))

Helm

(use-package helm
  :ensure t
  :bind
  (("M-x" . 'helm-M-x)
   ("C-x C-f" . 'helm-find-files)
   ("C-s" . 'helm-occur)
   ("C-x C-b" . 'helm-buffers-list)
   ("M-y" . 'helm-show-kill-ring)
   ("C-x C-p" . 'helm-list-elisp-packages)
   ([tab] . 'helm-execute-persistent-action))
  :config
  (setq helm-mode 1)
  (setq helm-autoresize-mode 0)
  (setq helm-split-window-in-side-p 1)
  (setq helm-move-to-line-cycle-in-source 1))

Which Key

(use-package which-key
  :ensure t
  :config
  (which-key-mode))

Blog

Get needed packages.

(require 'ox-html)
(require 'ox-publish)
(use-package webfeeder
  :ensure t)

Helper stuff

Some stuff from https://pavpanchekha.com/blog/org-mode-publish.html to clear up HTML.

(setq org-html-home/up-format "")
(setq org-html-link-up "")
(setq org-html-link-home "")
(setq org-html-scripts "")

Add a post template to Org Capture.

(add-to-list 'org-capture-templates
	     '("p" "Post" plain (file create-blog-post)
	       (file "~/Nextcloud/Documents/blog/src/posts/template.draft.org")))
(defun create-blog-post ()
	"Create an org file in ~/source/myblog/posts."
	(interactive)
	(let ((name (read-string "Filename: ")))
	  (expand-file-name (format "%s.org" name) "~/Nextcloud/Documents/blog/src/posts/")))

Get stuff for the sitemap, generate RSS, publish.

(defun my-sitemap-format-entry (entry style project)
  (format "%s - [[file:%s][%s]] (%s)"
	  (format-time-string "%Y-%m-%d" (org-publish-find-date entry project))
	  entry
	  (org-publish-find-title entry project)
	  (org-find-category
	   (expand-file-name entry (plist-get (cdr project) :base-directory)))))

(defun org-find-category (file)
  (with-temp-buffer
    (message file)
    (insert-file-contents file)
    (goto-char (point-min))
    (let ((beg (+ 1 (re-search-forward "^#\\+CATEGORY\:")))
	  (end (progn (forward-word) (point))))
      (buffer-substring beg end))))

(defun rss-gen()
  (interactive)
  (webfeeder-build
   "rss.xml"
   "~/Nextcloud/Documents/blog/pages/"
   "https://anonimno.codeberg.page/"
   (delete '"index.html" (directory-files "~/Nextcloud/Documents/blog/pages/" nil
					  "\.html"))
   :title "anonimno's blog"
   :description "My blog in RSS"
   :builder 'webfeeder-make-rss))

(defun my-blog-publish()
  (interactive)
  (progn
    (org-publish-all)
    (rss-gen)
    ;;(let ((msg (read-string "Commit msg: "))))
    (let ((msg (read-string "Commit msg: ")))
      (shell-command (format "%s %s" "~/Nextcloud/Documents/blog/pages/git_publish.sh" msg)))
    ))

Project setup.

(setq org-publish-project-alist
      '(("blog"
	 :base-directory "~/Nextcloud/Documents/blog/src/posts/"
	 :base-extension "org"
	 :publishing-directory "~/Nextcloud/Documents/blog/pages/"
	 :publishing-function org-html-publish-to-html
	 :recursive t
	 :exclude "level-.*\\|.*\.draft\.org"
	 :section-numbers nil
	 :with-toc nil
	 :with-sub-superscript nil
	 :with-author nil
	 :with-date t
	 :with-drawers t
	 :auto-sitemap t
	 :sitemap-filename "index.org"
	 :sitemap-title "anonimno's blog"
	 :sitemap-sort-files anti-chronologically
	 :sitemap-style list
	 :sitemap-format-entry my-sitemap-format-entry
	 :html-head-include-default-style nil
	 :html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"/assets/site.css\" />"
	 :html-preamble "<a href=\"/about.html\"> <img alt=\"anonimno\" class=\"avatar--circle\" src=\"/assets/avatar.png\" width=\"100\" height=\"100\"></a> <p class=\"pubdate\" style=\"visibility:hidden;\"> %d </p>"
	 :html-postamble "<p><span style=\"float: left;\"><a href= \"/rss.xml\">RSS</a></span> <span style=\"float: right;\"><a href= \"/index.html\">Home</a></span></p> <br> <p><span class=\"date\" style=\"float: left;\">Updated: %C</span> <span class=\"licence\" style=\"float: right;\">License: <a href= \"https://creativecommons.org/licenses/by-sa/4.0/\">CC BY-SA 4.0</a></span></p>")

	("assets"
	 :base-directory "~/Nextcloud/Documents/blog/src/assets/"
	 :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
	 :publishing-directory "~/Nextcloud/Documents/blog/pages/assets/"
	 :recursive t
	 :publishing-function org-publish-attachment)

	("all" :components ("blog" "assets"))))

RSS Home


Updated: 2021-07-28 Wed 18:56 License: CC BY-SA 4.0