Emacs configuration, contained in an org file
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

682 lines
20 KiB

;;; init.el --- Initialization file for Emacs
;;; Commentary: Emacs Startup File --- initialization for Emacs
;;; Code:
;; Make startup faster by reducing the frequency of garbage
;; collection. The default is 800 kilobytes. Measured in bytes.
(setq gc-cons-threshold (* 50 1000 1000))
;; only use straight.el as a package source
(setq package-enable-at-startup nil)
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
'silent 'inhibit-cookies)
(goto-char (point-max))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'use-package)
(setq straight-use-package-by-default t
straight-check-for-modifications nil)
(setq custom-file "~/.emacs.d/elisp/custom.el")
(put 'dired-find-alternate-file 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(defun play-with-mpv (url)
(start-process "Run: " nil "mpv" url))
(defun rename-this-buffer-and-file ()
"Renames current buffer and file it is visiting."
(let ((name (buffer-name))
(filename (buffer-file-name))
(read-file-name-function 'read-file-name-default))
(if (not (and filename (file-exists-p filename)))
(error "Buffer '%s' is not visiting a file!" name)
(let ((new-name (read-file-name "New name: " filename)))
(cond ((get-buffer new-name)
(error "A buffer named '%s' already exists!" new-name))
(rename-file filename new-name 1)
(rename-buffer new-name)
(set-visited-file-name new-name)
(set-buffer-modified-p nil)
(message "File '%s' successfully renamed to '%s'" name (file-name-nondirectory new-name))))))))
(defun delete-this-buffer-and-file (force)
"Delete the file connected to this buffer and kill it, FORCE is universal argument."
(interactive "P")
(let ((filename (buffer-file-name))
(buffer (current-buffer))
(name (buffer-name)))
(if (not (and filename (file-exists-p filename)))
(error "'%s' is not a file buffer" name)
(when (or force (yes-or-no-p (format "Delete '%s', Are you sure? " filename)))
(delete-file filename)
(kill-buffer buffer)
(message "Deleted '%s'" filename)))))
(defun save-all-and-quit ()
(save-some-buffers t)
(defun delete-word (arg)
"Delete characters forward until encountering the end of a word.
With argument, do this that many times."
(interactive "p")
(if (use-region-p)
(delete-region (region-beginning) (region-end))
(delete-region (point) (progn (forward-word arg) (point)))))
(defun backward-delete-word (arg)
"Delete characters backward until encountering the end of a word.
With argument, do this that many times."
(interactive "p")
(delete-word (- arg)))
(defun load-agenda-month-view () (interactive) (org-agenda nil "c"))
(defun emacs-load-configuration ()
(org-babel-tangle-file "~/.emacs.d/init.org")
(org-babel-load-file "~/.emacs.d/init.org"))
(global-set-key (kbd "C-c R") 'emacs-load-configuration)
(defun emacs-edit-configuration ()
(find-file "~/.emacs.d/init.org"))
(global-set-key (kbd "C-c E") 'emacs-edit-configuration)
(defun org-open-orgfile-from-dir ()
(ido-find-file-in-dir "~/Documents/orgfiles/"))
(global-set-key (kbd "C-x F") 'org-open-orgfile-from-dir)
;; I'm not a sharp typer
(global-set-key (kbd "C-x f") 'ido-find-file)
(global-set-key (kbd "C-x C-f") 'ido-find-file)
(global-set-key (kbd "C-x b") 'ido-switch-buffer)
(global-set-key (kbd "C-x C-b") 'ido-switch-buffer)
(global-set-key (kbd "C-x k") 'ido-kill-buffer)
(global-set-key (kbd "C-x C-k") 'ido-kill-buffer)
(global-set-key (kbd "C-c #") 'comment-or-uncomment-region)
(global-set-key (kbd "C-c C-D") 'delete-this-buffer-and-file)
(use-package ido
:defer 1
:straight nil
ido-enable-flex-matching t
ido-everywhere t
;; for recently visited files
ido-virtual-buffers t)
(ido-mode 1)
;; for throwaway buffers
(setq ido-create-new-buffer 'always)
;; to display results vertically
(use-package ido-vertical-mode
(setq ido-vertical-show-count t)
(setq ido-vertical-define-keys 'C-n-C-p-up-and-down)
(ido-vertical-mode 1)))
(setq auto-revert-use-notify nil)
(global-auto-revert-mode t)
(setq show-trailing-whitespace t)
(global-set-key (kbd "<C-backspace>") 'backward-delete-word)
(global-set-key (kbd "<M-backspace>") 'backward-delete-word)
(setq x-select-enable-primary t)
(defalias 'yes-or-no-p 'y-or-n-p)
(setq show-paren-delay 0)
(toggle-truncate-lines -1)
(toggle-word-wrap t)
;; (use-package which-key
;; :init
;; (which-key-mode)
;; :config
;; (which-key-setup-side-window-bottom)
;; (setq which-key-idle-delay 0.2)
;; (setq which-key-sort-order 'which-key-key-order-alpha))
(setq make-backup-files nil)
(setq auto-save-default nil)
;; (setq backup-directory-alist `(("." . "~/.saves")))
(use-package auto-complete
(ac-set-trigger-key "TAB")
(setq ac-auto-start nil)
(add-to-list 'ac-modes 'org-mode)
(global-subword-mode t)
(setq pop-up-windows nil)
(setq tramp-default-method "ssh")
;; Enable richer annotations using the Marginalia package
(use-package marginalia
;; Either bind `marginalia-cycle` globally or only in the minibuffer
:bind (("M-A" . marginalia-cycle)
:map minibuffer-local-map
("M-A" . marginalia-cycle))
;; The :init configuration is always executed (Not lazy!)
;; Must be in the :init section of use-package such that the mode gets
;; enabled right away. Note that this forces loading the package.
(use-package custom
:straight nil
(load-theme 'wombat)
;; Menu, toolbar and scrollbar
(menu-bar-mode -1)
(when window-system
(tool-bar-mode -1)
(scroll-bar-mode -1))
;; Left and right margins
(setq-default left-margin-width 5 right-margin-width 5)
;; Bigger fonts for mole eyes
(set-face-attribute 'default nil :height 160)
;; just a scratch buffer at startup
(setq inhibit-startup-screen t)
;; (add-hook 'after-init-hook #'load-agenda-month-view)
(setq inhibit-startup-echo-area-message t)
;; A cosmetic bug is making org blocks header and footer "leak" through section header when folded
;; (let ((bg (face-attribute 'default :background)))
;; (set-face-attribute 'org-block-end-line nil :background bg)
;; (set-face-attribute 'org-block-begin-line nil :background bg))
(use-package diminish
(diminish 'ivy-mode)
(diminish 'flycheck-mode)
(diminish 'auto-complete-mode)
(diminish 'subword-mode)
(diminish 'autopair-mode)
(diminish 'which-key-mode))
(add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
(add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
(setq org-startup-folded t)
(use-package org-superstar
(org-mode . org-superstar-mode))
(setq org-startup-indented t)
(setq org-startup-truncated nil)
;; (setq-default org-display-custom-times t)
;; (setq org-time-stamp-custom-formats '("<%d/%m/%y>" . "<%d/%m/%y - %R>"))
(use-package org-agenda
:after org
:straight nil
(setq org-agenda-window-setup 'current-window ;; Open org-agenda in current window
org-agenda-span 'month
org-agenda-skip-scheduled-if-done nil
org-agenda-start-on-weekday 1
org-agenda-files (list "~/Documents/orgfiles/todo.org")
'((sequence "TODO(t)" "STARTED(s)" "|" "DONE(d)" "DELAYED(D)"))
(setq org-agenda-custom-commands
'(("c" "Simple agenda view"
((agenda "")
(alltodo "")))))
(setq org-support-shift-select 'always)
(add-hook 'org-shiftup-final-hook 'windmove-up)
(add-hook 'org-shiftleft-final-hook 'windmove-left)
(add-hook 'org-shiftdown-final-hook 'windmove-down)
(add-hook 'org-shiftright-final-hook 'windmove-right)
(setq org-edit-src-content-indentation 0
org-src-tab-acts-natively t
org-src-preserve-indentation t)
(setq org-src-window-setup 'current-window)
(setq org-default-notes-file "~/Documents/orgfiles/queue.org")
(setq org-capture-templates
("b" "Bookmarks" entry (file "~/Documents/orgfiles/bookmarks.org")
(file "~/Documents/orgtemplates/bookmarks_template.org") :prepend t)
("d" "Dream" entry (file "~/Documents/orgfiles/djournal.org")
(file "~/Documents/orgtemplates/dream_template.org") :prepend t)
("m" "Music" entry (file "~/Documents/orgfiles/music.org")
(file "~/Documents/orgtemplates/music_template.org") :prepend t)
("n" "Note" entry (file "~/Documents/orgfiles/queue.org")
(file "~/Documents/orgtemplates/note_template.org") :prepend t)
("r" "RSS" entry (file "~/Documents/orgfiles/rss.org")
(file "~/Documents/orgtemplates/rss_template.org") :prepend t)
("t" "Todo" entry (file "~/Documents/orgfiles/todo.org")
(file "~/Documents/orgtemplates/todo_template.org") :prepend t)))
(defun org-export-output-file-name-modified
(orig-fun extension &optional subtreep pub-dir)
(unless pub-dir
(setq pub-dir "./exports")
(unless (file-directory-p pub-dir)
(make-directory pub-dir)))
(apply orig-fun extension subtreep pub-dir nil))
(advice-add 'org-export-output-file-name
:around #'org-export-output-file-name-modified)
(setq org-latex-with-hyperref nil)
(with-eval-after-load 'ox-latex
;; (add-to-list 'org-latex-packages-alist '("" "minted"))
(setq org-latex-listings 'minted)
;; (setq org-latex-listings 'listings)
(setq org-src-fontify-natively t)
(setq org-latex-pdf-process
'("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
"pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f")))
(setq org-latex-listings 'minted)
(setq org-latex-minted-options '(("breaklines" "true")
("breakanywhere" "true")
("breaksymbolleft" "{}")))
(with-eval-after-load 'ox-latex
'(add-to-list 'org-latex-classes
,(concat "\\documentclass[presentation]{beamer}\n"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))
(use-package dired
:straight nil
(:map dired-mode-map
("<return>" . dired-find-alternate-file)
("^" . dired-single-up-directory))
(use-package dired-filter
:defer t
(dired-mode . (lambda () (dired-filter-group-mode)
(setq dired-filter-show-filters nil))
(use-package dired-single
:defer t)
(dired-filter-mode 1)
(setq image-dired-external-viewer "feh")
(setq dired-listing-switches "-alh --group-directories-first"))
(use-package elfeed
:defer t
(:map elfeed-search-mode-map
("A" . elfeed-show-all)
("E" . elfeed-show-emacs)
("D" . elfeed-show-daily)
("q" . elfeed-save-db-and-bury)
("C" . elfeed-mark-all-as-read)
("R" . elfeed-update)
("p" . elfeed-play-in-external-player))
;; :general
(use-package elfeed-org
(setq-default elfeed-search-filter "@2-week-ago +unread")
(setq elfeed-db-directory "~/Documents/elfeeddb")
;; (setq rmh-elfeed-org-auto-ignore-invalid-feeds t)
(setq rssfile "~/Documents/orgfiles/rss.org")
(setq rmh-elfeed-org-files (list rssfile)))
(defun elfeed-play-in-external-player ()
(play-with-mpv (substring-no-properties (car kill-ring))))
(defun elfeed-show-all ()
(elfeed-search-set-filter "@2-months-ago"))
(defun elfeed-mark-all-as-read ()
;;functions to support syncing .elfeed between machines
;;makes sure elfeed reads index from disk before launching
(defun elfeed-load-db-and-open ()
"Wrapper to load the elfeed db from disk before opening"
;;write to disk when quiting
(defun elfeed-save-db-and-bury ()
"Wrapper to save the elfeed db to disk before burying buffer"
(use-package nov
:defer t
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
(use-package magit
:defer t
(setq magit-display-buffer-function (quote magit-display-buffer-fullframe-status-topleft-v1)))
(global-set-key (kbd "C-c G") 'magit)
(use-package mu4e
:defer t
:straight nil
;; disable scroll-down-command binding
(lambda ()
(local-unset-key (kbd "S-SPC"))))
;; required for mbsync
(setq mu4e-change-filenames-when-moving t)
;; command to index mails
(setq mu4e-mu-binary "/usr/bin/mu")
;; command to retrieve mails from box
(setq mu4e-get-mail-command "mbsync -a")
;; Configure SMTP
(setq message-send-mail-function 'message-send-mail-with-sendmail)
(setq send-mail-function 'smtpmail-send-it)
(setq message-sendmail-f-is-evil t)
(setq message-sendmail-extra-arguments '("--read-envelope-from"))
(setq sendmail-program "/usr/bin/msmtp")
(setq mail-user-agent 'mu4e-user-agent)
;; disable automatic checking of the mailbox at start
(setq mu4e-update-interval nil)
(setq mu4e-confirm-quit nil)
(setq mu4e-view-show-images t)
(setq mu4e-use-fancy-chars t)
(setq mu4e-headers-include-related t)
(setq mu4e-attachment-dir "~/Downloads")
(setq message-kill-buffer-on-exit t)
(when (fboundp 'imagemagick-register-types)
'("View in browser" . mu4e-action-view-in-browser) t)
;; (add-hook 'mu4e-compose-mode-hook 'flyspell-mode)
(load (expand-file-name "~/Config/private/mail.el")))
(use-package pdf-tools
:defer t
:bind (:map pdf-view-mode-map ("C-s" . isearch-forward))
;; initialise
;; open pdfs scaled to fit page
(setq-default pdf-view-display-size 'fit-page)
;; automatically annotate highlights
(setq pdf-annot-activate-created-annotations t))
(add-to-list 'auto-mode-alist '("\\.pdf\\'" . pdf-tools-enable-minor-modes))
(use-package doc-view
;; :ensure
(set-terminal-coding-system 'utf-8)
(use-package jabber
:defer t
(leader-def "aj" '(:ignore t :which-key "Jabber")
"ajc" '(jabber-connect :which-key "Jabber Connect")
"ajd" '(jabber-disconnect :which-key "Jabber Disconnect"))
'(defun jabber-sasl-read-passphrase-closure (jc remember)
"Return a lambda function suitable for `sasl-read-passphrase' for JC.
Call REMEMBER with the password. REMEMBER is expected to return it as well."
(lexical-let ((password (plist-get (fsm-get-state-data jc) :password))
(bare-jid (jabber-connection-bare-jid jc))
(remember remember))
(if password
(lambda (prompt)
(funcall remember
(cond ((stringp password) password)
((listp password) (eval password)))
(lambda (prompt) (funcall remember (jabber-read-password bare-jid))))))
(org-babel-load-file (expand-file-name "~/Config/private/xmpp.org"))
(add-hook 'prog-mode-hook 'linum-mode)
;;(use-package rainbow-mode
;; :init
;; (add-hook 'prog-mode-hook 'rainbow-mode)
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
(use-package lsp-mode
;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
(setq lsp-keymap-prefix "C-c l")
:hook (
(lsp-mode . lsp-enable-which-key-integration)
(javascript-mode . #'lsp-deferred)
(elixir-mode . lsp)
(go-mode . #'lsp-deferred)
(typescript-mode . #'lsp-deferred)
(vue-mode . #'lsp-deferred))
:commands lsp-deferred
(use-package lsp-ivy :commands lsp-ivy-workspace-symbol)
(add-to-list 'exec-path (expand-file-name "~/SRC/thirdparty/elixir-ls/release"))
(use-package dockerfile-mode
:defer t)
(use-package elixir-mode
(setq home (getenv "HOME"))
(setenv "PATH" (concat (getenv "PATH") ":/usr/local/go/bin"))
(setenv "GOPATH" (concat home "/Applications/go"))
(use-package go-mode
:defer t
:mode ("\\.go\\'" . go-mode)
(setq compile-command "echo Building... && go build -v && echo Testing... && go test -v && echo Linter... && golint")
(setq compilation-read-command nil)
;; folding code blocks
(add-hook 'go-mode 'hs-minor-mode)
(("M-," . compile)
("M-." . godef-jump))
(setq compilation-window-height 14)
(defun my-compilation-hook ()
(when (not (get-buffer-window "*compilation*"))
(let* ((w (split-window-vertically))
(h (window-height w)))
(select-window w)
(switch-to-buffer "*compilation*")
(shrink-window (- h compilation-window-height)))))))
(add-hook 'compilation-mode-hook 'my-compilation-hook)
(setq compilation-scroll-output t)
;;Set up before-save hooks to format buffer and add/delete imports.
;;Make sure you don't have other gofmt/goimports hooks enabled.
(defun lsp-go-install-save-hooks ()
(add-hook 'before-save-hook #'lsp-format-buffer t t)
(add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
;; faster than using `org-babel-do-load-languages'
(use-package ob-haskell
:defer t
:straight nil
;; :ensure org-plus-contrib
:commands (org-babel-execute:haskell)
(use-package haskell-mode
:defer t
(setq haskell-process-type 'stack-ghci))
(add-to-list 'auto-mode-alist '("\\.hs\\'" . haskell-mode))
(setq js-indent-level 2)
(use-package jinja2-mode
:defer t)
(use-package markdown-mode
:defer t)
(use-package powershell
:defer t)
;; faster than using `org-babel-do-load-languages'
(use-package ob-python
:defer t
:straight nil
;; :ensure org-plus-contrib
:commands (org-babel-execute:python)
(add-to-list 'auto-mode-alist '("\\.scm\\'" . scheme-mode))
(use-package rainbow-delimiters
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
(use-package geiser
:defer t
(setq geiser-active-implementations '(chicken)
geiser-default-implementation '(chicken))
(add-hook 'scheme-mode-hook 'geiser-mode)
(use-package geiser-chicken
:defer t)
(use-package ac-geiser
:defer t
(add-hook 'geiser-mode-hook 'ac-geiser-setup)
(add-hook 'geiser-repl-mode-hook 'ac-geiser-setup)
(eval-after-load "auto-complete"
'(add-to-list 'ac-modes 'geiser-repl-mode)))
;; faster than using `org-babel-do-load-languages'
(use-package ob-shell
:defer t
:straight nil
;; :ensure org-plus-contrib
(use-package typescript-mode
:defer t
(setq typescript-indent-level 2))
(use-package vue-mode
:defer t
(setq vue-html-extra-indent 2)
(use-package yaml-mode
:defer t)
(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))
;; Make gc pauses faster by decreasing the threshold.
(setq gc-cons-threshold (* 2 1000 1000))
(provide 'init)
;;; init ends here