(setq user-full-name "Borislav Atanasov"
user-mail-address "natomanofglory@gmail.com")
Set the customize file to a separate file.
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(load custom-file)
(defun get-active-file-repo ()
"Return the repository of the active file if any."
(when buffer-file-name
(s-wrap
(s-chop-prefix "/"
(second
(s-split ":"
(repo-origin
(projectile-project-root
(f-dirname
(buffer-file-name)))))))
"[" "]")))
;(setq frame-title-format
; '("" "emacs - %b " (:eval (get-repo-for-title))))
Allow installations from packages from github
(quelpa
'(quelpa-use-package
:fetcher git
:url "https://github.com/quelpa/quelpa-use-package.git"))
(require 'quelpa-use-package)
Set up Language Server Protocol.
This (or an equivalent, see eglot) is a must for any serious development.
You could theoretically go without it (considering it is a big performance hit) but it is hard for me to justify it.
(use-package lsp-mode
:commands lsp
:hook ((c++-mode scala-mode) . (lambda ()
(lsp))))
(use-package lsp-ui
:commands lsp-ui-mode
:after lsp)
(use-package consult-lsp)
(use-package company-lsp
:commands company-lsp
:after (lsp company))
Kill. Whole. Lines. This should be the default. I really don’t understand why it isn’t.
Not really necessary if you use crux-kill-whole-line
like you are supposed to.
(setq kill-whole-line t)
I don’t actually know what this does but the EmacsWiki told me to put it in.
(autoload 'wl "wl" "Wanderlust" t)
Watch my emacs activity with ActivityWatch
(when (executable-find "aw-server")
(use-package activity-watch-mode
:defer 5
:config (global-activity-watch-mode)
:diminish activity-watch-mode))
Set zathura as the default pdf viewer
sudo pacman -S zathura zathura-pdf-mupdf
(with-eval-after-load 'tex
(require 'tex)
(add-to-list 'TeX-view-program-selection
'(output-pdf "Zathura")))
More convenient *scratch*
buffers
(use-package scratch
:commands scratch)
undo-tree
is absolutely necessary.
You really shouldn’t do anything without it (or an equivalent).
(setq use-package-ensure-function 'use-package-ensure-elpa)
(use-package undo-tree
; :quelpa (undo-tree :fetcher url
; :url "http://git.savannah.gnu.org/cgit/emacs/elpa.git/plain/packages/undo-tree/undo-tree.el")
:diminish undo-tree-mode
:config (global-undo-tree-mode))
(setq use-package-ensure-function 'quelpa)
Crux.
(use-package crux)
Auto rename pair tag in html/xml
(use-package auto-rename-tag
:defer t)
Revert buffer automatically when underlying file is changed outside of Emacs.
(global-auto-revert-mode t)
Smarter tab.
(setq tab-always-indent 'complete)
Switch between visible buffers / frames with shift + arrow keys
This requires framemove.el
from EmacsWiki.
(use-package windmove
:bind (("S-<up>" . windmove-up)
("S-<left>" . windmove-left)
("S-<right>" . windmove-right)
("S-<down>" . windmove-down)))
;(add-to-list 'load-path "~/.config/emacs/elpa/framemove/")
;(require 'framemove)
(use-package framemove
:quelpa (framemove
:fetcher url
:url "https://raw.githubusercontent.com/emacsmirror/emacswiki.org/master/framemove.el")
:after windmove
:config
(setq framemove-hook-into-windmove t)
(windmove-default-keybindings))
Save buffers on buffer switch
(use-package super-save
:diminish super-save-mode
:config (super-save-mode +1))
;; add integration with ace-window
(add-to-list 'super-save-triggers 'ace-window)
Highlighting
(global-hl-line-mode +1)
(diminish 'hl-line-mode)
Add the ability to kill the current line without marking it
;(use-package rect )
(require 'rect)
(crux-with-region-or-line kill-region)
(crux-with-region-or-line kill-ring-save)
Automatically clean up unused buffers.
(use-package midnight
:defer 30)
Do not activate mark if there is no active region when
exchange-point-and-mark
(C-x C-x by default) is called.
(defadvice exchange-point-and-mark (before deactivate-mark activate compile)
"When called with no active region, do not activate mark."
(interactive "P")
(list (not (region-active-p))))
Create macro for calling functions on region or buffer
(defmacro with-region-or-buffer (func)
"When called with no active region, call FUNC on current buffer."
`(defadvice ,func (before with-region-or-buffer activate compile)
(interactive
(if mark-active
(list (region-beginning) (region-end))
(list (point-min) (point-max))))))
(with-region-or-buffer indent-region)
Show available keybindings after you start typing
;; show available keybindings after you start typing
(use-package which-key
:config
(which-key-mode +1)
(which-key-enable-god-mode-support nil)
:diminish which-key-mode)
Following config mostly taken from bbatsov’s Prelude.
;; Copyright © 2011-2020 Bozhidar Batsov
;;
;; Author: Bozhidar Batsov <bozhidar@batsov.com>
;; URL: https://github.com/bbatsov/prelude
;; Version: 1.0.0
;; Keywords: convenience
(use-package smartparens
:config ;; smart curly braces
(sp-pair "{" nil :post-handlers
'(((lambda (&rest _ignored)
(crux-smart-open-line-above)) "RET"))))
(defun prelude-local-comment-auto-fill ()
(set (make-local-variable 'comment-auto-fill-only-comments) t))
;; show the name of the current function definition in the modeline
(use-package which-func
:config (which-function-mode 1))
;; font-lock annotations like TODO in source code
(use-package hl-todo
:config (global-hl-todo-mode 1))
;; in Emacs 24 programming major modes generally derive from a common
;; mode named prog-mode; for others, we'll arrange for our mode
;; defaults function to run prelude-prog-mode-hook directly. To
;; augment and/or counteract these defaults your own function
;; to prelude-prog-mode-hook, using:
;;
;; (add-hook 'prelude-prog-mode-hook 'my-prog-mode-defaults t)
;;
;; (the final optional t sets the *append* argument)
(defun prelude-prog-mode-defaults ()
"Default coding hook, useful with any programming language."
(flycheck-mode)
(flyspell-prog-mode)
(smartparens-mode +1)
(prelude-local-comment-auto-fill))
(setq prelude-prog-mode-hook 'prelude-prog-mode-defaults)
(add-hook 'prog-mode-hook (lambda ()
(run-hooks 'prelude-prog-mode-hook)))
;; enable on-the-fly syntax checking
I have recently (READ: for a few months) been skimping on installing new
packages the proper way, since it is way easier to just run
(package-list-packages)
that to write stuff in the config.
I wanted to rectify that so I wrote a couple of helper functions.
(defun get-packages-installed-by-config ()
"Return a list of all packages installed with `use-package' by the config."
(--map
(s-replace ")" "" (second (s-split " " it)))
(--filter
(s-prefix? "(use-package" it)
(--map
(s-trim it)
(--filter
(s-contains? "use-package" it)
(-flatten
(--map
(s-lines (f-read it))
(f-glob "*.el" user-emacs-directory))))))))
(defun get-selected-packages-not-in-config ()
"Return a list of all packages that are in `package-selected-packages' but
aren't explicitly installed by config."
(-map
#'symbol-name
(-difference
(package--find-non-dependencies)
(-map
#'intern
(get-packages-installed-by-config)))))
(defun show-populated-buffer (populate-function buffer-name)
"Open a buffer called BUFFER_NAME and fill it using POPULATE_FUNCTION"
(with-current-buffer (get-buffer-create buffer-name)
(insert (s-join "\n" (funcall populate-function))))
(view-buffer buffer-name #'kill-buffer))
(defun show-packages-installed-by-config ()
"Open a buffer containing all packages explicitly installed by config."
(interactive)
(show-populated-buffer #'get-packages-installed-by-config
"*Installed Packages*"))
(defun show-selected-packages-not-in-config ()
"Open a buffer containing all (not-dependency) packages not explicitly installed by config."
(interactive)
(show-populated-buffer #'get-selected-packages-not-in-config
"*Missing Packages*"))
Some are sourced from Daniel Mai’s config.
For some reason these functions are disabled.
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)
Yes is two letters too long for me.
(defalias 'yes-or-no-p 'y-or-n-p)
Clean up back-ups / autosaves.
(setq backup-directory-alist `(("." . ,(concat user-emacs-directory "backups"))))
(setq auto-save-file-name-transforms `((".*" ,(concat user-emacs-directory "auto-save-list/") t)))
UTF-8.
(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
Don’t indent with TABS please.
(setq-default indent-tabs-mode nil)
Indicate empty lines.
(setq-default indicate-empty-lines t)
Don’t count two spaces after a period as the end of a sentence. Just one space is needed.
(setq sentence-end-double-space nil)
Delete the region when typing.
(delete-selection-mode t)
Logical buffer names.
(setq uniquify-buffer-name-style 'forward)
Load aliases from .bash_profile
(setq shell-command-switch "-ic")
Silence!
(setq visible-bell t)
(setq ring-bell-function 'ignore)
(use-package flycheck
:diminish flycheck-mode
:commands (global-flycheck-mode flycheck-mode)
:config
(setq flycheck-html-tidy-executable "tidy5"))
Enable flyspell
(use-package flyspell
:when (executable-find "aspell")
:defer 5
:diminish flyspell-mode
:bind ("C->" . flyspell-correct-word-before-point)
:config (setq ispell-program-name "aspell"
ispell-extra-args (listp "--sug-mode=ultra"))
(flyspell-mode +1))
Don’t ask for confirmation when evaluating code blocks. It’s annoying.
(setq org-confirm-babel-evaluate nil)
Enable some languages for evaluation in Org code blocks.
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)
(C . t)
(shell . t)
(lisp . t)))
I mainly export to \LaTeX but that comes installed by default.
(setq org-export-backends
(quote
(html latex)))
(defun org-export-as-pdf (filename)
"Export org-file FILENAME as pdf."
(with-current-buffer (find-file-noselect filename)
(org-mode)
(org-latex-export-to-pdf)))
(defun org-export-as-epub (filename)
"Export org-file FILENAME as epub."
(with-current-buffer (find-file-noselect filename)
(org-mode)
(org-epub-export-to-epub)))
Enable linting of source code blocks when exported to \LaTeX This requires minted.
On Archlinux:
sudo pacman -S minted
You also might need to install some of the (La)TeX libraries included by your distribution.
(use-package ox-latex
:after org
:config
(add-to-list 'org-latex-packages-alist '("" "minted"))
(add-to-list 'org-latex-packages-alist '("" "color"))
(add-to-list 'org-latex-packages-alist '("" "xcolor"))
(add-to-list 'org-latex-packages-alist '("" "mathtools"))
(add-to-list 'org-latex-packages-alist '("" "amsmath"))
(setq org-latex-listings 'minted)
(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")))
Enable Org Tempo mode for template expansion
(use-package org-tempo)
Source blocks
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("ll" . "src lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("sh" . "src sh"))
(add-to-list 'org-structure-template-alist '("bh" . "src bash"))
(add-to-list 'org-structure-template-alist '("sc" . "src scala"))
Set up emphasis symbols
(setq org-emphasis-alist
(quote
(("*" bold)
("/" italic)
("_" underline)
("=" org-verbatim verbatim)
("~" org-code verbatim)
("+"
(:strike-through t)))))
Set up better link previews using org-link-beautify.
It is not available in MELPA.
So we have to install it manually.
(use-package org-link-beautify
:quelpa (org-link-beautify
:fetcher github
:repo "stardiviner/org-link-beautify")
:disabled t)
Or so I would like. But it’s way too laggy and the icons show up wrong for me.
Enable some good minor modes for working with org-mode when in org-mode.
(use-package org-superstar)
;(use-package org-sticky-header )
(setq use-package-ensure-function 'use-package-ensure-elpa)
(use-package tex-site :ensure auctex)
(setq use-package-ensure-function 'quelpa)
(use-package cdlatex
:after tex-site)
(defun org-mode-enable-minor-modes-hook ()
"Enable some good minor-modes for fancier 'org-mode' experience."
(org-superstar-mode 1)
(diminish 'org-superstar-mode)
;;(org-sticky-header-mode 1)
(org-indent-mode 1)
(diminish 'org-indent-mode)
;;(org-cdlatex-mode 1)
(diminish 'org-cdlatex-mode)
(yas-minor-mode 1)
(diminish 'yas-minor-mode)
(fira-code-mode 1)
(diminish 'fira-code-mode)
;;(org-link-beautify-mode 1)
)
(add-hook 'org-mode-hook 'org-mode-enable-minor-modes-hook)
Let TAB behave as expected when inside code block.
(setq org-src-tab-acts-natively t)
Set the default notes file.
(setq org-default-notes-file "~/Documents/notes.org")
Enable speed commands.
(setq org-use-speed-commands t)
(setq org-tags-column 45)
Enable windmove/framemove in org-mode.
;(setq org-support-shift-select nil)
(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)
Make latex previews in org-mode twice as big.
(setq org-format-latex-options (append '(:scale 2.0) org-format-latex-options ))
Add custom TODO keywords
(setq org-todo-keywords
'((sequence "INACTIVE(i!)" "SCHEDULED(s!)" "NEXT(n!)" "ACTIVE(a!)" "|" "DONE(d!)" "CANCELLED(c!)")
(sequence "SUSPENDED(p!)")
(sequence "EXPORT(e)" "|" "EXPORTED")))
Set custom faces for TODO keywords.
(setq org-todo-keyword-faces
'(("INACTIVE" . "#004488" )
("SCHEDULED" . "#aa6600")
("NEXT" . "#006622")
("ACTIVE" . (:background "#004400" :foreground "white" :weight bold ))
("SUSPENDED" . (:background "#440000" :foreground "white" :weight bold ))
("DONE" . (:foreground "#204420" :weight bold))
("CANCELLED" . "#616161" )
("EXPORT" . (:background "#443322" :foreground "#ffaa00" ))
("EXPORTED" . "#414141" )))
Obviously you can’t really work on two tasks at the same time. So let’s enforce a single ACTIVE task at all times.
(when (file-exists-p "~/Code/Projects/kaltask")
(use-package kaltask
:quelpa (kaltask :fetcher file
:path "~/Code/Projects/kaltask")))
Enforce todo dependencies.
(setq org-enforce-todo-dependencies t)
Enable org-drill.
(use-package org-drill)
(setq org-drill-hide-item-headings-p t)
Show live-preview of latex fragements.
(use-package org-elp)
Add a company backend for math.
(use-package company-math
:after company)
Register the agenda files.
(defvar org-agenda-files-root
"~/Documents/" "Store the root of all org-agenda files")
;(setq org-agenda-files nil)
(defvar org-agenda-files-assoc
'(( "agenda" . ( "* INACTIVE %?\nAdded on %U\n%i" org-ask-location))
( "notes" . "* INACTIVE %?\nAdded on %U\n%i")
( "tickler" . "* INACTIVE %?\nDEADLINE: %^{Deadline}T\nAdded on %U\n%a\n%i"))
"A agenda name associated with the format for org-capture entries."
)
(defun expand-to-agenda-file (file)
"Expand FILE to a path to an .org file located at `org-agenda-files-root'."
(concat (concat org-agenda-files-root file) ".org"))
(defun org-register-agenda-file (file)
"Register an agenda FILE."
(add-to-list 'org-agenda-files
(expand-to-agenda-file file)))
(seq-do 'org-register-agenda-file
(mapcar (lambda (elem) (car elem))
org-agenda-files-assoc))
(defvar org-agenda-shortcuts-prefix-key "H-z"
"Prefix key for accessing org-agenda-shortcuts")
(bind-key
(concat org-agenda-shortcuts-prefix-key
(concat " " org-agenda-shortcuts-prefix-key))
'previous-buffer)
(defun generate-shortcuts-to-agenda-file (agenda-file)
(let* ((key (char-to-string (string-to-char agenda-file)))
(key-chords (concat org-agenda-shortcuts-prefix-key (concat " " key))))
(bind-key key-chords `(lambda () (interactive) (find-file (expand-to-agenda-file ,agenda-file))))
(which-key-add-key-based-replacements key-chords agenda-file)
))
(seq-do 'generate-shortcuts-to-agenda-file
(mapcar (lambda (elem) (car elem))
org-agenda-files-assoc))
Create capture templates for quick writes to different agenda files.
(defun org-ask-location ()
(setq org-refile-use-outline-path nil)
(let* ((org-refile-targets '((nil :maxlevel . 1)))
(hd (condition-case nil
(car (org-refile-get-location "Headline" nil t))
(error (car org-refile-history)))))
(goto-char (point-min))
(outline-next-heading)
(if (re-search-forward
(format org-complex-heading-regexp-format (regexp-quote hd))
nil t)
(goto-char (point-at-bol))
(goto-char (point-max))
(or (bolp) (insert "\n"))
(insert "* " hd "\n")))
(setq org-refile-use-outline-path 'file)
(end-of-line))
(setq org-capture-templates nil)
(defun build-capture-template-definition
(capture-key capture-description agenda-file template)
"Generate a capture template.
The capture template can be accessed with CAPTURE-KEY.
It is described by CAPTURE-DESCRIPTION.
It points to AGENDA-FILE.
And it uses TEMPLATE to generate the entry.
TEMPLATE is either a string with which to format the entry,
or a cons cell of a string with which to format the entry and a function which
tells where exactly in the file to add the new entry."
(append (list capture-key capture-description)
'(entry)
(if (char-or-string-p template)
(list (append '(file)
(list agenda-file)))
(list (append '(file+function)
(list agenda-file) (cdr template))))
(if (char-or-string-p template)
(list template)
(list (car template)))))
(defun org-generate-agenda-capture-template-definition (agenda-file)
(let* ((agenda-name (file-name-base agenda-file))
(capture-key (char-to-string (string-to-char agenda-name)))
(capture-description (concat (concat "Add entry to " agenda-name) "."))
(template (cdr (assoc agenda-name org-agenda-files-assoc))))
(build-capture-template-definition
capture-key capture-description agenda-file template)))
(defun register-agenda-capture-template-from-agenda-file (agenda-file)
(add-to-list 'org-capture-templates
(org-generate-agenda-capture-template-definition agenda-file)))
(defun register-agenda-capture-templates-from-agenda-files ()
(seq-do 'register-agenda-capture-template-from-agenda-file
org-agenda-files))
(register-agenda-capture-templates-from-agenda-files)
(add-to-list 'org-capture-templates
(build-capture-template-definition "e" "Export entry"
(expand-to-agenda-file "notes")
"* EXPORT %?\nAdded on %U\n%i" ))
Add state changes to a drawer.
(setq org-log-into-drawer t)
Set up archivation.
(setq org-archive-location (concat (expand-to-agenda-file "archive") "::"))
;;Requires Org >= 9.4
;(setq org-archive-subtree-save-file-p t)
;;Org < 9.4
(defun save-notes-archive-file ()
(interactive)
(save-some-buffers
'no-confirm (lambda ()
(equal buffer-file-name
(expand-file-name (expand-to-agenda-file "archive"))))))
(advice-add 'org-archive-subtree :after #'save-notes-archive-file)
Set up refiling
(setq org-refile-use-outline-path 'file)
(setq org-refile-targets '((org-agenda-files . (:level . 0))))
(defvar org-files-refile-internally
(list (expand-file-name (expand-to-agenda-file "agenda")))
"List of files which should be offered a list of internal headlines
instead of other files")
(defun dynamic-org-refile-get-targets (func &rest args)
"Extend `org-refile-get-targets' in various contexts.
If the file visited in current buffer is inside
`org-files-refile-internally' then show a list of top-level headings to
refile to instead of the default `org-refile-targets'.
If the file visited in current buffer is a member of
`org-agenda-files', remove it from the list so it doesn't clutter the
target list. All changes to variables are restored at the end of the
function."
(setq org-refile-history nil)
(let ((current-file (buffer-file-name (current-buffer))))
(if (member current-file org-files-refile-internally)
(let ((org-refile-use-outline-path nil)
(org-refile-targets nil))
(apply func args))
(let ((org-agenda-files (remove-if
(lambda (file)
(equal current-file (expand-file-name file)))
org-agenda-files)))
(apply func args)))))
(advice-add 'org-refile-get-targets :around #'dynamic-org-refile-get-targets)
Set up alerts for agenda items.
(use-package org-wild-notifier
:after org
:config
(setq alert-default-style 'libnotify)
(setq org-wild-notifier-keyword-whitelist nil)
(org-wild-notifier-mode 1))
(use-package org-roam
:config
(unless (f-dir? "~/Documents/Knowledge/src/org")
(make-directory "~/Documents/Knowledge/src/org"))
(setq org-roam-directory "~/Documents/Knowledge/src/org")
(setq org-roam-db-location "~/Documents/Knowledge/src/org/org-roam.db")
(setq org-roam-link-auto-replace t)
(add-hook 'after-init-hook 'org-roam-mode)
(setq org-roam-title-sources '((title headline) alias))
(setq org-roam-tag-sources '(prop vanilla all-directories))
(setq org-roam-index-file "index.org")
(setq org-roam-completion-everywhere t)
(setq org-id-track-globally t)
(org-id-update-id-locations (f-glob "*.org" org-roam-directory)))
(use-package lister
:after org-roam
:quelpa (lister :fetcher git
:url "https://github.com/publicimageltd/lister"))
(use-package delve
:after lister
:quelpa (delve :fetcher git
:url "https://github.com/publicimageltd/delve")
:config
(use-package delve-minor-mode
:config
(add-hook 'org-mode-hook #'delve-minor-mode-maybe-activate)
(setq delve-use-icons-in-completions t))
:bind
(("<f12>" . delve-open-or-select)))
(defun find-roam-notes-with-tag (tag)
(let ((search (delve-db-query-pages-with-tag tag)))
(when search
(delve search (format "of tag %s" tag)))))
(defun org-roam-open-file-by-title (title)
(org-roam--find-file
(first
(-flatten
(org-roam-db-query [:select [file]
:from titles
:where (= title $s1)]
title)))))
(defun org-roam-protocol-find-tag (info)
(when-let ((tag (plist-get info :tag)))
(raise-frame)
(find-roam-notes-with-tag tag))
nil)
(defun org-roam-protocol-find-by-title (info)
(when-let ((title (plist-get info :title)))
(raise-frame)
(org-roam-open-file-by-title title)))
(require 'org-protocol)
(push '("org-roam-tag" :protocol "roam-tag"
:function org-roam-protocol-find-tag)
org-protocol-protocol-alist)
(push '("org-roam-file-by-title" :protocol "roam-by-title"
:function org-roam-protocol-find-by-title)
org-protocol-protocol-alist)
(setq org-roam-graph-exclude-matcher "recentchanges.org")
(setq org-roam-graph-node-extra-config '(("shape" . "rectangle")
("style" . "rounded,filled")
("fillcolor" . "#273434")
("fontname" . "sans")
("fontsize" . "12px")
("labelfontname" . "sans")
("color" . "#b75867")
("fontcolor" . "#c4c7c7")))
(setq org-roam-graph-edge-extra-config
'(("dir" . "back")
("color" . "#b75867")))
(setq org-roam-graph-extra-config
'(("rankdir" . "BT")
("bgcolor" . "\"#132020\"")))
(use-package org-roam-server
:commands org-roam-server-mode
:config
(setq org-roam-server-host "127.0.0.1"
org-roam-server-port 7000
org-roam-server-authenticate nil
org-roam-server-export-inline-images t
org-roam-server-serve-files t
org-roam-server-served-file-extensions '("pdf" "mp4" "ogv")
org-roam-server-network-poll t
org-roam-server-network-arrows "from"
org-roam-server-network-label-truncate t
org-roam-server-network-label-truncate-length 60
org-roam-server-network-label-wrap-length 20))
(defvar roam-subjects '("Numeric Methods"
"Linear Algebra"
"Logic Programming"
"Computer Architectures"
"Design and Analysis of Algorithms"
"Discrete Structures"
"Geometry of Movement")
"Subjects used as auto-complete for `make-roam-template'")
(defun make-roam-template (name)
"Create roam template with NAME."
(let ((key (char-to-string (downcase (string-to-char name))))
(completion (string-join roam-subjects "|")))
`(,key ,name entry #'org-roam--capture-get-point
"* ${title}\n %?"
:file-name "${slug}"
:head ,(concat "#+title: ${title}\n#+roam_alias: \"${title}\"\n#+roam_tags: \"%^{prompt|General|"
completion
"}\" \""
name
"\"\n")
:unnarrowed t)))
(defvar roam-template-types '("Theorem" "Definition" "Lecture"))
(setq org-roam-capture-templates nil)
(dolist (template (mapcar #'make-roam-template roam-template-types))
(add-to-list 'org-roam-capture-templates template))
Set LSP for C/C++ using ccls.
sudo pacman -S ccls
We also need the emacs package.
(use-package ccls
:disabled t
:hook ((c-mode c++-mode objc-mode cuda-mode) .
(lambda ()
(ccls-code-lens-mode))))
(setq ccls-executable "/usr/bin/ccls")
(use-package lsp-clangd
:after lsp)
(setq lsp-disabled-clients '(ccls))
Enable some refactoring with srefactor.
(use-package srefactor
:after ccls)
(use-package clang-format
:hook
(((c-mode c++-mode) . #'clang-format-buffer)
((after-save) . (lambda ()
(when c-buffer-is-cc-mode
(clang-format-buffer))))))
This package displays function signatures in the mode line.
(use-package c-eldoc
:commands c-turn-on-eldoc-mode
:init (add-hook 'c-mode-hook 'c-turn-on-eldoc-mode))
(use-package novel-mode
:quelpa (novel-mode
:fetcher github
:repo "TLINDEN/novel-mode"))
Enable editing of browser text fields in Emacs. Just because it’s possible.
(use-package edit-server
:commands edit-server-start
:init (if after-init-time
(edit-server-start)
(add-hook 'after-init-hook
#'(lambda() (edit-server-start))))
:config (setq edit-server-new-frame-alist
'((name . "Edit with Emacs")
(minibuffer . t)
(menu-bar-lines . t)
(window-system . x))))
(use-package emms
:config
(emms-all)
(emms-default-players))
Make reading stuff in Emacs easier.
(defun reading-mode ()
"Enable a major mode and some minor modes useful for reading."
(interactive)
(fundamental-mode)
(text-scale-set 1)
(visual-line-mode 1)
(set-frame-font "Roboto")
(set-fill-column 65)
(set-justification-full (point-min) (point-max))
(set-left-margin (point-min) (point-max) 7)
(split-window-horizontally)
(follow-mode 1)
(read-only-mode 1))
(use-package ido
:disabled t
:init
(setq ido-enable-flex-matching t)
(setq ido-everywhere t)
(ido-mode t)
(use-package ido-vertical-mode
:defer t
:init (ido-vertical-mode 1)
(setq ido-vertical-define-keys 'C-n-and-C-p-only)))
(use-package whitespace)
(setq whitespace-line-column 80) ;; limit line length
(setq whitespace-style '(face tabs empty trailing lines-tail))
(global-whitespace-mode)
(diminish 'global-whitespace-mode)
(defun cleanup-on-save ()
"Call `whitespace-cleanup' on save"
(whitespace-cleanup))
(add-hook 'before-save-hook 'cleanup-on-save)
(use-package helm
:diminish helm-mode
:disabled t
:init
(require 'helm-config)
:config
;;(helm-mode 1)
(setq helm-locate-command "mdfind -interpret -name %s %s"
helm-ff-newfile-prompt-p nil
helm-M-x-fuzzy-match t)
:bind ("C-c h i" . helm-imenu))
(use-package helm-projectile
:after (helm projectile)
:commands helm-projectile
:bind ("C-c p h" . helm-projectile))
(use-package helm-ag
:after helm)
(use-package helm-swoop
:after helm
:disabled t
:bind ("C-S" . helm-swoop)
:config
(setq helm-swoop-fontify-buffer-size-limit 'always
helm-swoop-use-line-number-face t
helm-swoop-speed-or-color t))
(use-package ivy
:diminish (ivy-mode . "")
:bind
(:map ivy-mode-map
("C-'" . ivy-avy))
:config
(ivy-mode 1)
;; add ‘recentf-mode’ and bookmarks to ‘ivy-switch-buffer’.
(setq ivy-use-virtual-buffers t)
;; number of result lines to display
(setq ivy-height 10)
;; Show candidate index and total count
(setq ivy-count-format "(%d/%d) ")
;; no regexp by default
(setq ivy-initial-inputs-alist nil)
;; configure regexp engine.
(setq ivy-re-builders-alist
;; allow input not in order
'((t . ivy--regex-ignore-order))))
(use-package avy)
(use-package counsel
:bind (("M-x" . counsel-M-x)
("C-x C-r" . counsel-recentf)
("C-c h i" . counsel-imenu)
("C-h v" . counsel-describe-variable)
("C-h f" . counsel-describe-function)
("C-x C-f" . counsel-find-file)
("C-x b" . counsel-switch-buffer)
("M-y" . counsel-yank-pop)))
(use-package counsel-projectile
:after (counsel projectile)
:bind (("C-x f" . counsel-projectile-find-file))
:config
; (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(counsel-projectile-mode)
(setq counsel-projectile-switch-project-action 'dired))
(use-package swiper
:after counsel
:bind (("C-s" . swiper)))
(use-package ivy-yasnippet
:after (ivy yasnippet))
(use-package ivy-rich
:diminish (ivy-rich-mode . "")
:after (ivy)
:config (ivy-rich-mode 1))
(use-package htmlize)
(use-package typescript-mode
:commands typescript-mode)
(use-package tss
:after typescript-mode)
(setq js-indent-level 2)
(setq css-indent-offset 2)
(use-package scss-mode)
(use-package postcss-sorting
:after css-mode
:quelpa (postcss-sorting
:fetcher git
:url "https://github.com/P233/postcss-sorting.el.git")
:config
(add-hook 'css-mode-hook
(lambda ()
(add-hook 'before-save-hook 'postcss-sorting-buffer t t))))
Show parent’s chain on header for web-releated files
(use-package cakecrumbs
:config
(setq cakecrumbs-html-major-modes '(mhtml-mode html-mode web-mode nxml-mode sgml-mode))
(setq cakecrumbs-jade-major-modes '(yajade-mode jade-mode pug-mode))
(setq cakecrumbs-scss-major-modes '(scss-mode less-css-mode css-mode))
(setq cakecrumbs-stylus-major-modes '(stylus-mode sass-mode))
(cakecrumbs-auto-setup)
(setq cakecrumbs-separator ">"))
Use emacs as a calibre client.
(use-package calibredb
:defer t
:commands (calibredb calibredb-find-counsel)
:config
(setq calibredb-root-dir "~/Documents/Library")
(setq calibredb-db-dir (f-join calibredb-root-dir "metadata.db"))
(setq calibredb-ref-default-bibliography (f-join calibredb-root-dir "catalog.bib"))
(setq calibredb-library-alist '(("~/Documents/Library")))
(setq calibredb-format-all-the-icons t)
(setq calibredb-virtual-library-alist
'(("Default" . "^\\(epub\\|mobi\\|pdf\\|docx\\)")))
(setq calibredb-virtual-library-default-name "Default")
)
(use-package vue-mode
:commands vue-mode)
A great interface for git projects. It’s much more pleasant to use than the git interface on the command line. Use an easy keybinding to access magit.
(use-package magit
:demand
:bind (("C-c g" . magit-status)
("C-c G" . magit-dispatch)
("C-c m l" . magit-log-buffer-file)
("C-c m b" . magit-blame)
("C-c m m" . magit-list-repositories))
:config
(setq magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
(setq magit-diff-refine-hunk t)
(add-hook 'magit-process-find-password-functions
#'magit-process-password-auth-source)
(setq magit-repository-directories '(("~/" . 0)
("~/.config/" . 3)
("~/Code" . 2)
("~/.local/src" . 4)
("~/Documents/Knowledge" . 1))))
The following code makes magit-status run alone in the frame, and then restores the old window configuration when you quit out of magit.
No more juggling windows after commiting. It’s magit bliss.
From: Magnar Sveen
;; full screen magit-status
(defadvice magit-status (around magit-fullscreen activate)
"Make Magit full screen and restore windows when done."
(window-configuration-to-register :magit-fullscreen)
ad-do-it
(delete-other-windows))
(defun magit-quit-session ()
"Restore the previous window configuration and kill the magit buffer."
(interactive)
(kill-buffer)
(jump-to-register :magit-fullscreen))
Magit extension for GitHub/GitLab
(use-package forge
:after magit)
Enable Yasnippets.
(use-package yasnippet
:diminish yas-minor-mode
:defer 15
:config
(setq yas-indent-line 'fixed)
(yas-global-mode))
We do however still need some snippets.
(use-package common-lisp-snippets
:commands lisp-mode
:after (yasnippet common-lisp))
(use-package yasnippet-snippets
:after yasnippet)
Search through files really fast
(use-package ripgrep)
Install the Superior Lisp Interaction Mode for Emacs.
(use-package slime
:config (setq inferior-lisp-program "sbcl"))
Set up company for SLIME
(use-package slime-company
:after (slime company)
:config (slime-setup '(slime-company)))
Following lisp config mostly taken from bbatsov’s Prelude.
(use-package rainbow-delimiters)
(define-key read-expression-map (kbd "TAB") 'completion-at-point)
(defun prelude-lisp-coding-defaults ()
(smartparens-strict-mode +1)
(rainbow-delimiters-mode +1))
(setq prelude-lisp-coding-hook 'prelude-lisp-coding-defaults)
;; interactive modes don't need whitespace checks
(defun prelude-interactive-lisp-coding-defaults ()
(smartparens-strict-mode +1)
(rainbow-delimiters-mode +1)
(whitespace-mode -1))
(setq prelude-interactive-lisp-coding-hook
'prelude-interactive-lisp-coding-defaults)
(add-hook 'lisp-mode-hook (lambda ()
(run-hooks 'prelude-lisp-coding-hook)))
(use-package macrostep
:bind (("H-`" . macrostep-expand)
("H-C-`" . macrostep-collapse)))
Following emacs-lisp config mostly taken from bbatsov’s Prelude.
(setq use-package-ensure-function 'use-package-ensure-elpa)
(use-package rainbow-mode)
(setq use-package-ensure-function 'quelpa)
(use-package crux)
;(use-package elisp-slime-nav )
(defun prelude-recompile-elc-on-save ()
"Recompile your elc when saving an elisp file."
(add-hook 'after-save-hook
(lambda ()
(when
(file-exists-p (byte-compile-dest-file buffer-file-name))
(emacs-lisp-byte-compile)))
nil
t))
(define-key emacs-lisp-mode-map (kbd "C-c C-c") 'eval-defun)
(define-key emacs-lisp-mode-map (kbd "C-c C-b") 'eval-buffer)
(defun prelude-conditional-emacs-lisp-checker ()
"Don't check doc style in Emacs Lisp test files."
(let ((file-name (buffer-file-name)))
(when (and file-name (string-match-p ".*-tests?\\.el\\'" file-name))
(setq-local flycheck-checkers '(emacs-lisp)))))
(defun prelude-emacs-lisp-mode-defaults ()
"Sensible defaults for `emacs-lisp-mode'."
(run-hooks 'prelude-lisp-coding-hook)
(eldoc-mode +1)
(prelude-recompile-elc-on-save)
(rainbow-mode +1)
(setq mode-name "EL")
(prelude-conditional-emacs-lisp-checker))
(setq prelude-emacs-lisp-mode-hook 'prelude-emacs-lisp-mode-defaults)
(add-hook 'emacs-lisp-mode-hook (lambda ()
(run-hooks 'prelude-emacs-lisp-mode-hook)))
;(with-eval-after-load "elisp-slime-nav"
; (diminish 'elisp-slime-nav-mode))
(with-eval-after-load "rainbow-mode"
(diminish 'rainbow-mode))
(with-eval-after-load "eldoc"
(diminish 'eldoc-mode))
;(add-hook 'emacs-lisp-mode-hook (lambda () (elisp-slime-nav-move 1)))
(defun conditionally-enable-smartparens-mode ()
"Enable `smartparens-mode' in the minibuffer, during `eval-expression'."
(if (eq this-command 'eval-expression)
(smartparens-mode 1)))
(add-hook 'minibuffer-setup-hook 'conditionally-enable-smartparens-mode)
Project management and navigation.
(use-package projectile
:diminish projectile-mode
:demand
:bind (("C-c p p" . projectile-switch-project)
("C-c p s s" . projectile-ag)
("C-c p s r" . projectile-ripgrep))
:config (define-key projectile-mode-map
(kbd "C-c p") 'projectile-command-map)
(projectile-mode 1)
(setq projectile-enable-caching t)
(setq projectile-switch-project-action 'projectile-dired))
(use-package python-mode
:defer t)
Auto completion
(use-package company
:bind (("C-n" . company-select-next)
("C-p" . company-select-previous))
:config
(setq company-tooltip-limit 20)
(setq company-idle-delay .15)
(setq company-echo-delay 0)
(setq company-begin-commands '(self-insert-command))
(global-company-mode))
(use-package stumpwm-mode)
Add a quick way for connecting to the Swank server started by StumpWM.
(defvar stumpwm-swank-host "localhost" "Swank host as set in your StumpWM config")
(defvar stumpwm-swank-port 4004 "Swank port as set in your StumpWM config")
(defun stumpwm-connect ()
(interactive)
(slime-connect stumpwm-swank-host stumpwm-swank-port))
Install nov so I can read epub files in Emacs.
(setq use-package-ensure-function 'use-package-ensure-elpa)
(use-package nov
:commands nov-mode)
(setq use-package-ensure-function 'quelpa)
Enable nov-mode for epub files.
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
Properly justify text. This requires justify-kp which is unfortunately not in MELPA, since it hasn’t been updated since <2019-11-19>. It is still up on github though so we can do a quick clone.
cd "$HOME/.emacs.d/elpa/"
git clone "https://github.com/Fuco1/justify-kp"
It should also be available as a git submodule of my .emacs.d repo
(use-package justify-kp
:quelpa (justify-kp :fetcher github :repo "Fuco1/justify-kp")
:after nov
:config
(setq nov-text-width t)
(defun nov-justify-hook ()
"Justify nov buffer."
(if (get-buffer-window)
(
let ((max-width (pj-line-width))
buffer-read-only)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(when (not (looking-at "^[[:space:]]*$"))
(goto-char (line-end-position))
(when (> (shr-pixel-column) max-width)
(goto-char (line-beginning-position))
(pj-justify)))
(forward-line 1)))
(toggle-word-wrap 1)
)
(add-hook 'window-configuration-change-hook
'my-nov-window-configuration-change-hook
nil t))
(defun my-nov-window-configuration-change-hook ()
"Justify on nov window change."
(nov-justify-hook)
(remove-hook 'window-configuration-change-hook
'my-nov-window-configuration-change-hook
t))
(add-hook 'nov-post-html-render-hook 'nov-justify-hook)))
(defun prepare-nov-mode-hook ()
"Disable `whitespace-mode' in `nov-mode' since it makes reading hard."
(whitespace-mode 1)
(whitespace-mode 0))
(add-hook 'nov-post-html-render-hook 'prepare-nov-mode-hook)
(use-package cmake-mode
:commands cmake-mode)
(defun maybe-cmake-project-mode ()
(if (or (file-exists-p "CMakeLists.txt")
(file-exists-p (expand-file-name "CMakeLists.txt" (car (project-roots (project-current))))))
(cmake-project-mode)))
(use-package cmake-project
:after cmake-mode
:config
(add-hook 'c-mode-hook 'maybe-cmake-project-mode)
(add-hook 'c++-mode-hook 'maybe-cmake-project-mode))
(use-package tramp
:config (setq tramp-default-method "ssh"))
(use-package json-mode)
(use-package kotlin-mode)
(use-package flycheck-kotlin)
(use-package flymake-ktlint)
;(use-package centered-window-mode)
(defvar cwm-whitelist '(nov-mode)
"Whitelist `centered-window-mode' in the given major modes")
(defun buffer-mode (&optional buffer-or-name)
"Returns the major mode associated with a buffer.
If buffer-or-name is nil return current buffer's mode."
(buffer-local-value 'major-mode
(if buffer-or-name (get-buffer buffer-or-name) (current-buffer))))
;(defun centered-window-mode-on-buffer-switch-hook ())
; (if (member (buffer-mode) cwm-whitelist)
; (centered-window-mode 1)
; (centered-window-mode 0)))
;(setq cwm-centered-window-width 80)
;(setq cwm-incremental-padding t)
;(setq cwm-incremental-padding-% 20)
;(add-hook 'buffer-list-update-hook 'centered-window-mode-on-buffer-switch-hook)
(use-package web-server)
(use-package god-mode)
;(god-mode)
(global-set-key (kbd "<escape>") #'god-local-mode)
(defun my-god-mode-update-cursor ()
(setq cursor-type (if (or overwrite-mode (or god-local-mode buffer-read-only))
'box
'bar)))
(add-hook 'god-mode-enabled-hook #'my-god-mode-update-cursor)
(add-hook 'overwrite-mode-hook #'my-god-mode-update-cursor)
(add-hook 'buffer-list-update-hook #'my-god-mode-update-cursor)
(add-hook 'god-mode-disabled-hook #'my-god-mode-update-cursor)
(define-key god-local-mode-map (kbd ".") #'repeat)
(global-set-key (kbd "C-x C-1") #'delete-other-windows)
(global-set-key (kbd "C-x C-2") #'split-window-below)
(global-set-key (kbd "C-x C-3") #'split-window-right)
(global-set-key (kbd "C-x C-0") #'delete-window)
Change color of mode line when in god-mode
(use-package ewal-doom-themes)
(defun my-god-mode-update-modeline ()
"Update the mode line colors when in god-mode"
(let ((mode-line-fg-default (ewal-doom-themes-get-color 'background -3))
(mode-line-fg-god (ewal-doom-themes-get-color 'background -3))
(red (ewal-doom-themes-get-color 'red 5))
(blue (ewal-doom-themes-get-color 'blue 0)))
(cond
(god-local-mode
(progn
(set-face-background
'mode-line
(car (doom-lighten mode-line-fg-god 0.15)))
(set-face-background
'mode-line-inactive
(car (doom-darken mode-line-fg-default 0.1)))
(set-face-background
'cursor
(car red))))
(t (progn
(set-face-background
'mode-line
(car (doom-darken mode-line-fg-default 0.15)))
(set-face-background
'mode-line-inactive
(car (doom-darken mode-line-fg-default 0.1)))
(set-face-background
'cursor
(car blue)))))))
(add-hook 'god-mode-enabled-hook #'my-god-mode-update-modeline)
(add-hook 'buffer-list-update-hook #'my-god-mode-update-modeline)
(add-hook 'god-mode-disabled-hook #'my-god-mode-update-modeline)
(defun org-agenda-sync ()
"Sync notes between emacs and android"
(interactive)
(async-shell-command "agendaSync"))
(define-key org-mode-map (kbd "H-s") 'org-agenda-sync)
(define-key c-mode-map (kbd "C-c r") 'srefactor-refactor-at-point)
(define-key c++-mode-map (kbd "C-c r") 'srefactor-refactor-at-point)
(global-set-key (kbd "C-d") 'crux-duplicate-current-line-or-region)
(global-set-key (kbd "<delete>") 'delete-char)
(global-set-key (kbd "C-x x") 'replace-regexp)
(global-set-key (kbd "C-x c C-c") 'replace-string)
(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "C-x O") (lambda ()
(interactive)
(other-window -1))) ;; back one
(bind-key "C-k" 'crux-kill-whole-line)
(bind-key "C-M-x" 'kmacro-call-macro)
(bind-key "C-c c" 'org-capture)
(bind-key "C-c a" 'org-agenda)
(bind-key "C-." 'hippie-expand)
(defcustom after-save-interactively-hook nil
"Normal hook that is run after a buffer is saved interactively to its file.
See `run-hooks'."
:group 'files
:type 'hook)
(defun save-buffer-and-call-interactive-hooks (&optional arg)
"Save the buffer and call hooks if called interactively.
ARG is passed to 'save-buffer'"
(interactive "p")
(save-buffer arg)
(when (called-interactively-p 'all) ;; run post-hooks only if called interactively
(run-hooks 'after-save-interactively-hook)))
(global-set-key (kbd "C-x s") 'save-buffer-and-call-interactive-hooks)
(use-package expand-region
:bind ("C-=" . er/expand-region))
(defvar global-roam-map (make-keymap "Org-Roam")
"Global keymap for org-roam commands")
(bind-key "C-j" global-roam-map)
(bind-key "C-j" global-roam-map org-mode-map)
(bind-key "C-j J" #'org-roam-capture)
(bind-key "C-j j" #'org-roam-find-file)
(bind-key "C-j C-j" #'org-roam-insert)
(defun org-roam-grep-content (regexp)
"Use REGEXP to search `org-roam-directory' contents."
(interactive "sSearch: ")
(ripgrep-regexp regexp org-roam-directory '("-g \"*.org\"")))
(bind-key "C-j g" #'org-roam-grep-content)
(bind-key "C-j b" #'org-roam)
I do enjoy myself a good looking user interface. In fact customization of graphical elements is one of the reason I use Emacs.
Enable unicode fonts using the suprisingly named package unicode-fonts
This does require that some Unicode fonts exists.
yay -S ttf-symbola quivira ttf-dejavu noto-fonts noto-fonts-emoji noto-fonts-extra
Setting up this package for the first time may take upwards of 5 minutes the first time you start Emacs. There is a lot of unicode characters.
(use-package unicode-fonts
:config (unicode-fonts-setup))
Currently I use pywal to dynamically generate a colour scheme on the fly from my current background, which I change automatically every 5 minutes
Ideally I would apply that colour scheme to my Emacs theme as well.
(when (executable-find "wal")
(use-package ewal
:config (setq ewal-use-built-in-always-p nil
ewal-use-built-in-on-failure-p t
ewal-json-file "~/.cache/wal/colors.json"
ewal-built-in-palette "sexy-material")))
Thankfully ewal exist so I can just use that.
Now we need a theme that knows how to apply the scheme colours. ewal-doom-themes looks pretty nice.
(use-package ewal-doom-themes
:config
(if (executable-find "wal")
(progn
(load-theme 'ewal-doom-one t)
(enable-theme 'ewal-doom-one))
(progn (load-theme 'doom-molokai t)
(enable-theme 'doom-molokai))))
We do need to configure some things so that the ewal theme is reapplied every time the background changes, since apparently that is not a common circumstance.
(when (executable-find "wal")
(defun refresh-theme ()
"Reload the theme."
(load-theme 'ewal-doom-one t)
(run-hooks 'buffer-list-update-hook))
(defun theme-callback (event)
"Callback for refreshing the theme. Parameter EVENT is ignored."
(refresh-theme))
(use-package filenotify)
(file-notify-add-watch
"~/.cache/wal/colors.json" '(change) 'theme-callback)
(enable-theme 'ewal-doom-one))
Mark all themes as safe for simplicity.
(setq custom-safe-themes t)
Org mode is something I use quite often (case in point) so I would prefer it would look fairly decent.
(setq org-fontify-done-headline t
org-fontify-whole-heading-line t
org-src-fontify-natively t
org-src-window-setup 'current-window
org-src-strip-leading-and-trailing-blank-lines t
org-src-preserve-indentation t)
I set headlines to fontify the whole line as well as change the face when marked DONE. Also fontify code blocks.
Obviously we want to display
emphasis markers as what they do
rather than some random characters.
(setq org-hide-emphasis-markers t)
And we want some fancy UTF8 characters for entries
(setq org-pretty-entities t)
Since I write in \LaTeX a lot I would prefer if \LaTeX things were being highlighted.
(setq org-highlight-latex-and-related (quote (native script entities)))
Finally replace the default … when a heading is collapsed with a fancy unicode arrow ↘
(setq org-ellipsis "↘")
Enable icons in various buffers with all-the-icons.
(use-package all-the-icons)
(use-package all-the-icons-ibuffer
:after (all-the-icons ibuffer)
:commands ibuffer
:config (all-the-icons-ibuffer-mode 1))
(use-package all-the-icons-gnus
:after (all-the-icons gnus)
:config (all-the-icons-gnus-setup))
(use-package all-the-icons-dired
:after (all-the-icons ibuffer)
:config (add-hook 'dired-mode-hook 'all-the-icons-dired-mode))
(use-package all-the-icons-ivy
:after (all-the-icons ivy)
:config (all-the-icons-ivy-setup))
(use-package all-the-icons-ivy-rich
:after (all-the-icons-ivy)
:config (all-the-icons-ivy-rich-mode))
Display tags everywere as fancy svg icons.
(use-package svg-tag-mode
:quelpa (svg-tag-mode :repo "rougier/svg-tag-mode"
:fetcher github
:files ("svg-tag-mode.el")))
(define-globalized-minor-mode global-svg-tag-mode svg-tag-mode
(lambda () (svg-tag-mode 1)))
(defun svg-tag-round (text)
(svg-tag-make (substring text 1 -1) nil 2 2 12))
(setq svg-tag-tags '(("@[a-zA-Z0-9]+?@" . svg-tag-round)))
Font ligatures sure are nice.
I happen to know that the Fira Code ones are doubly so.
First we need to set the default font to Fire Code.
That requires that it is installed on the system of course.
Thankfully I happen to know that a nice Fira Code package exists in the AUR.
yay -S "otf-fira-code-symbol" "ttf-fira-code"
We also need to set the Fira Code as the actual font for emacs.
(add-to-list 'default-frame-alist
(cond
((string-equal system-type "gnu/linux") '(font . "Fira Code-12"))))
(use-package fira-code-mode
:config (define-globalized-minor-mode global-fira-code-mode fira-code-mode
(lambda () (fira-code-mode 1))))
Make a global minor mode for Fira code font ligatures.
Enable doom-modeline.
(use-package doom-modeline
:config (doom-modeline-mode 1))
Enable icons in the modeline
(setq doom-modeline-icon t)
Don’t show time in the Emacs modeline. I have the Stumpwm modeline for that.
(display-time-mode 0)
Diplay the column number in the modeline
(line-number-mode t)
(column-number-mode t)
(size-indication-mode t)
The following function for occur-dwim is taken from Oleh Krehel from his blog post at (or emacs. It takes the current region or the symbol at point as the default value for occur.
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(thing-at-point 'symbol))
regexp-history)
(call-interactively 'occur))
(bind-key "M-s o" 'occur-dwim)
Make page breaks pretty instead of ^L
.
See also this article.
(use-package page-break-lines)
Use Ibuffer by default.
(defalias 'list-buffers 'ibuffer)
(add-hook 'dired-mode-hook 'auto-revert-mode)
;; Also auto refresh dired, but be quiet about it
(setq global-auto-revert-non-file-buffers t)
(setq auto-revert-verbose nil)
Save recent files.
(use-package recentf
:config
(recentf-mode t)
(setq recentf-max-saved-items 500))
Lately I’ve felt like opening *scratch*
when I start Emacs
is sort of a waste.
I use *scratch*
sparingly so having some kind of hub thingy instead
could be more useful.
So I want to implement one.
I don’t have any idea what might be useful there so let’s just wing it.
Having some recently visited files might be nice.
So firstly let’s write a function to get the last N visited files.
I use recentf
to keep track of that usually so we can probably get the
information from there.
(defun last-visited (&optional count)
"Find last COUNT visited items."
(cl-loop for n
from 0
below (or count 10)
collect (nth n recentf-list)))
There has to be an emacs lisp function to get the first N elements of a list that I can’t find. This will do until I figure it out.
Maybe being able to see my last active repos could be fine.
I don’t think magit
stores your last active repos so we can just approximate
with the function above
(defun last-repos-dir (&optional count)
"Find last active repositories, checking the last COUNT files visited."
(remove-duplicates
(flatten-list
(remove-if #'null
(mapcar #'magit-toplevel
(last-visited (or count 30)))))
:test #'string=))
This however returns the local (or remote really) path where the repo is cloned.
(defmacro magit-with-repository (repo &rest body)
"Evaluate BODY as if REPO was the currently active directory."
`(let ((default-directory ,repo))
,@body
))
(defun repo-origin (repo)
"Return the origin remote of REPO."
(magit-with-repository repo
(magit-get "remote.origin.url")))
(defun last-repos (&optional count)
(mapcar #'repo-origin (last-repos-dir count)))
Let’s see if it gets it right.
(mapcar #'(lambda (repo) (concat repo "\n"))
(last-repos 1))
\*looks up to address bar\*
Seems right to me.
What else… What else…
Latest commits?
Sure let’s go with that.
(defun latest-commits ()
)
Disable fringes.
(fringe-mode 0)
Disable the blinking cursor.
(blink-cursor-mode -1)
Show matching parenthesis.
(show-paren-mode t)
Wrap lines properly
(global-visual-line-mode)
(diminish 'visual-line-mode)
Smooth scrolling
(use-package smooth-scrolling)
(smooth-scrolling-mode)
Use bar cursor
(use-package bar-cursor)
(bar-cursor-mode 1)
(diminish 'bar-cursor-mode)
(message "Loaded config")
(provide 'config)
;;; config.el ends here