This config file is still in its early stages of development, Everything is unstable! To play around with my config files, clone this repo anywhere you like on your system.
git clone --depth=1 https://github.com/A7R7/EmaxBound.git
Then, simply execute these make rules inside the repo directory.
make bootstrap-borg # bootstrap borg itself
make bootstrap # bootstrap collective or new drones
Last, run emacs --init-directory=<path-of-the-repo>
(replace the path).
The whole config structure is built upon emacscollective/emacs.g. It is a starter-kit using borg as the package manager, which utilizes git submodules to maintain all its packages. Check Bootstrapping-using-a-seed from Borg’s manual to see how to build the config structure.
- First, I generated the structure from the seed.
- Then, I copied and pasted all the original code from init.el and early-init.el to this org file.
- Last, most further config does not go beyond the following 3 steps:
- Run M-x borg-assimilate and input the name of the package to install this package.
- Write config codes into this org file, then run M-x org-babel-tangle so that emacs writes the codes into the corresponding file. (the org-auto-tangle package that I installed enables auto tangling on saving org file)
- For some packages, specify its load path or build method in
.borgconfig
for them to be load or built as expected. This is auto tangled as well.
The name “EmaxBound” is inspired by “Starbound”, a game I used to play and I love it. Why it is “EmaxBound” but not “EmacsBound” ?
- “Emax” has the same number of characters of “Star”
- So that the logo I drawed (mimicing the style of starbound) looks balanced
- “Emaxbound” means “Explore the maxium bound of emacs”
- Doom emacs, spacemacs and other emacs “distros”, are pretty good. They did a good job in “working out of the box”. However, their complexities is blocking me from gaining a further understanding of emacs and elisp.
- Meanwhile, it’s much harder to do customizations on those complex systems, especially when you do not know what it already have. However, self-configured emacs does not have this problem.
- Those distros get updates from time to time. What if one update breaks your workflow?
Using literate configuration in org-mode has many benefits.
- You know what you code does, because there’re descriptions in various styles around the code. Code comments cannot achieve 100% of this.
- Easy jumping to the target code block among those foldable outlines.
- Hot reload code blocks: after editing a src block,
C-c C-c
to apply changes on the fly. - The org file can be used as readme in github/gitlab, which shows all your codes. It can be published as blogs. For example, I use ox-hugo to generate markdown files, and later hugo renders it to html files. This is where this blog comes from.
Credits goes to the authors of those emacs configs that I referenced during the build-up of my emacs config file.
- Luca’s vanilla-emacs (2023) detailed org config file.
- DistroTube’s Configuring Emacs (2023) easy to follow.
- seagle0128’s Centaur Emacs (2023) be morden.
- Daviwell’s Emacs from scratch (2021) intuitive.
- Doom Emacs (2023) Some best practices.
- Dakra’s Dmacs (2023) Another Emacs Literate configuration with borg
- DogLooksGood’s Meomacs (2023) Meow modal editing, emacs native friendly
NOTE: the year number after link equals to min (last time the config get’s updated, last time I refered to the config)
TransparencyNOTE: elisp codes under this headline are tangled to early-init.el.
Emacs load early-init.el before the initalization of GUI, which is before init.el.
Enable lexical-binding. Disable byte-compile for early-init.el.
According to the emacs manual, byte-compiling the init does not startup very much, and often leads to problems when you forget to recompile the file. Also, from my experience, it may lead to bugs that do not happen when not using byte-compile.
;;; -*- lexical-binding: t; no-byte-compile: t -*-
Defer garbage collection in the startup process.
(setq gc-cons-threshold most-positive-fixnum)
;; copied from lazycat
(setq gc-cons-percentage 0.6)
Prevent unwanted runtime compilation for native-comp.
(setq native-comp-deferred-compilation nil ;; obsolete since 29.1
native-comp-jit-compilation nil)
Disable tool-bar, menu-bar and scroll-bar before they’re loaded.
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)
;; Prevent flashing of unstyled modeline at startup
(setq-default mode-line-format nil)
Smooth window on startup
(setq frame-inhibit-implied-resize t)
Config use-package before loading use-package.
When start emacs with --debug-init
, the init-file-debug
condition is meet, and use-package will print out more info.
;; (if init-file-debug
(setq use-package-verbose t
use-package-expand-minimally nil
use-package-compute-statistics t
use-package-minimum-reported-time 0.001
;;debug-on-error t
)
;; (setq use-package-verbose nil
;; use-package-expand-minimally t))
Make emacs startup with background Transparency.
(set-frame-parameter nil 'alpha-background 85)
(add-to-list 'default-frame-alist '(alpha-background . 85))
(add-to-list 'default-frame-alist '(background-color . "#11142c"))
Disable fcitx5 on linux, because I use emacs rime, an internal input method of emacs, which is setuped here,
(setq pgtk-use-im-context-on-new-connection nil)
Below codes belongs to the original Borg seed.
(setq load-prefer-newer t)
(let ((dir (file-name-directory (or load-file-name buffer-file-name))))
(add-to-list 'load-path (expand-file-name "lib/compat" dir))
(add-to-list 'load-path (expand-file-name "lib/packed" dir))
(add-to-list 'load-path (expand-file-name "lib/auto-compile" dir))
(add-to-list 'load-path (expand-file-name "lib/org" dir))
)
(require 'auto-compile)
(auto-compile-on-load-mode)
(auto-compile-on-save-mode)
(setq package-enable-at-startup nil)
(with-eval-after-load 'package
(add-to-list 'package-archives (cons "melpa" "https://melpa.org/packages/") t))
NOTE: Starting from here, elisp codes are tangled to init.el
After loading early-init.el, emacs begin to load init.el.
Disable byte compile for init.el, same reason of early-init.el.
;;; -*- lexical-binding: t; no-byte-compile: t -*-
Calculating time used loading emacs excutable, as well as setting some variables.
(progn ; startup
(defvar before-user-init-time (current-time)
"Value of `current-time' when Emacs begins loading `user-init-file'.")
;; (switch-to-buffer "*Messages*")
(message "Loading Emacs...done (%fs)"
(float-time (time-subtract before-user-init-time
before-init-time)))
(setq user-init-file (or load-file-name buffer-file-name))
(setq user-emacs-directory (file-name-directory user-init-file))
(message "Loading %s..." user-init-file)
)
Set some defaults of emacs
(progn
(setq inhibit-startup-buffer-menu t)
(setq inhibit-startup-screen t)
(setq inhibit-startup-echo-area-message "locutus")
(setq initial-buffer-choice t)
;; (setq initial-scratch-message "")
;; This improves performance for some fonts
(setq inhibit-compacting-font-cache t)
;; emacs.stackexchange/how-to-disable-emacs-bidi
(setq-default bidi-paragraph-direction 'left-to-right)
(setq bidi-inhibit-bpa t
long-line-threshold 1000
large-hscroll-threshold 1000
syntax-wholeline-max 1000)
(setq use-dialog-box nil)
(setq confirm-kill-emacs 'y-or-n-p)
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
)
(global-auto-revert-mode)
drones
” in borg’s specific.
Borg clones all drones into borg-drones-directory
(by default user-emacs-directory/lib
).
The drones are not added to the load path until borg-initialize
is called. In a nut shell borg-initialize
is a loop of borg-activate
on all assimilated (and not disabled) drones, which adds the drone to the load path and eval its autoloads.
Here we add lib/borg
to the load-path before borg is loaded, and then call borg-initialize
to add all packages to the load path and eval their autoloads.
And then we switch to the message buffer in an attempt to make the loading process not that boring.
(use-package borg
:init
(add-to-list 'load-path
(expand-file-name "lib/borg" user-emacs-directory))
:config
(borg-initialize)
(switch-to-buffer "*Messages*")
)
(use-package auto-compile
:config
(setq auto-compile-display-buffer nil
auto-compile-mode-line-counter t
auto-compile-source-recreate-deletes-dest t
auto-compile-toggle-deletes-nonlib-dest t
auto-compile-update-autoloads t
warning-suppress-log-types '((comp))
)
)
epkg-describe-package
that looks nicer than the built-in describe-package.
(use-package epkg
:defer t
:bind
([remap describe-package] . epkg-describe-package)
:init
(setq epkg-repository
(expand-file-name "var/epkgs/" user-emacs-directory))
(setq epkg-database-connector 'sqlite-builtin ) ; requires emacs >=29
)
It’s not a good idea to put too many customizations in the custom file, especially for a declarative configuration
. If one wants to make something permanent, he should write them down in the user configuration file (like here).
On the other hand, some unimportant customizations that change over time based on user’s likes are better suited to be placed in the custom file, a good example is the theme
.
(use-package custom
:no-require t
:config
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(setf custom-safe-themes t) ;Treat all themes as safe
(when (file-exists-p custom-file)
(load custom-file))
)
(use-package server
:commands (server-running-p)
:config (or (server-running-p) (server-mode)))
The Garbage Collector Magic Hack enforce a sneaky Garbage Collection strategy to minimize GC interference with user activity.
(use-package gcmh
:init
(setq gcmh-high-cons-threshold 536870912) ;; 512mb
:config
(gcmh-mode 1)
)
(use-package no-littering)
Dash-Fontify mode
is a buffer-local minor mode intended for Emacs Lisp buffers. Enabling it causes the special variables bound in anaphoric Dash macros to be fontified. These anaphoras include ‘it’, ‘it-index’, ‘acc’, and ‘other’. In older Emacs versions which do not dynamically detect macros, Dash-Fontify mode additionally fontifies Dash macro calls.
(use-package dash
:config (global-dash-fontify-mode))
Dash needs some tweaks to be built
[submodule "dash"]
no-byte-compile = dash-functional.el
no-makeinfo = dash-template.texi
EIEIO is a series of Lisp routines which implements a subset of CLOS, the Common Lisp Object System
. In addition, EIEIO also adds a few new features which help it integrate more strongly with the Emacs running environment.
(use-package eieio)
[submodule "sqlite3"]
build-step = make
tweaks to buiild emacsql
[submodule "emacsql"]
no-byte-compile = emacsql-pg.el
(use-package diff-mode
:defer t
:config
(when (>= emacs-major-version 27)
(set-face-attribute 'diff-refine-changed nil :extend t)
(set-face-attribute 'diff-refine-removed nil :extend t)
(set-face-attribute 'diff-refine-added nil :extend t)))
(use-package dired
:defer t
:config (setq dired-listing-switches "-alh"))
(use-package eldoc
:when (version< "25" emacs-version)
:config (global-eldoc-mode))
(use-package help
:defer t
:config (temp-buffer-resize-mode))
Helpful adds a lot of very helpful information to Emacs’ describe-
command buffers.
For example, if you use describe-function
, you will not only get the documentation about the function,
you will also see the source code of the function and where it gets used in other places in the Emacs configuration.
It is very useful for figuring out how things work in Emacs.
It’s not a built in package. I put it here simply because it’s near help.
(use-package helpful
:bind
([remap describe-key] . helpful-key)
([remap describe-command] . helpful-command)
([remap describe-variable] . helpful-variable)
([remap describe-function] . helpful-callable)
("C-h F" . describe-face)
("C-h K" . describe-keymap)
:config
;; (defun my/helpful--syntax-highlight (string)
;; (propertize string 'family 'fixed-pitch))
;; (advice-add 'helpful--syntax-highlight :filter-return #'my/helpful--syntax-highlight)
)
(use-package info+
:defer t
:config
)
(use-package info-colors
:config
(add-hook 'Info-selection-hook 'info-colors-fontify-node)
(add-hook 'Info-mode-hook 'olivetti-mode)
(add-hook 'Info-mode-hook 'mixed-pitch-mode)
)
(progn ; `isearch'
(setq isearch-allow-scroll t))
(use-package lisp-mode
:config
(add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
(add-hook 'emacs-lisp-mode-hook 'reveal-mode)
(defun indent-spaces-mode ()
(setq indent-tabs-mode nil))
(add-hook 'lisp-interaction-mode-hook 'indent-spaces-mode))
(use-package man
:defer t
:config (setq Man-width 80))
(use-package prog-mode
:config
(global-prettify-symbols-mode)
(defun indicate-buffer-boundaries-left ()
(setq indicate-buffer-boundaries 'left))
(add-hook 'prog-mode-hook 'indicate-buffer-boundaries-left)
)
(use-package recentf
:demand t
:config (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?x?:"))
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init
(savehist-mode))
;; A few more useful configurations...
(use-package emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
(defun crm-indicator (args)
(cons (format "[CRM%s] %s"
(replace-regexp-in-string
"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
crm-separator)
(car args))
(cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; Emacs 28: Hide commands in M-x which do not work in the current mode.
;; Vertico commands are hidden in normal buffers.
;; (setq read-extended-command-predicate
;; #'command-completion-default-include-p)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t))
(use-package simple
:config (column-number-mode))
(use-package smerge-mode
:defer t
:config
(when (>= emacs-major-version 27)
(set-face-attribute 'smerge-refined-removed nil :extend t)
(set-face-attribute 'smerge-refined-added nil :extend t)))
(progn ; `text-mode'
(add-hook 'text-mode-hook 'indicate-buffer-boundaries-left))
(use-package tramp
:config
(add-to-list 'tramp-default-proxies-alist '(nil "\\`root\\'" "/ssh:%h:"))
(add-to-list 'tramp-default-proxies-alist '("localhost" nil nil))
(add-to-list 'tramp-default-proxies-alist
(list (regexp-quote (system-name)) nil nil))
(setq vc-ignore-dir-regexp
(format "\\(%s\\)\\|\\(%s\\)"
vc-ignore-dir-regexp
tramp-file-name-regexp)))
(use-package tramp-sh
:config (cl-pushnew 'tramp-own-remote-path tramp-remote-path))
(use-package pixel-scroll
:config
(setq scroll-conservatively 97)
(setq scroll-preserve-screen-position 1)
(setq mouse-wheel-progressive-speed nil)
;; The following piece of code is stolen from
;; https://emacs-china.org/t/topic/25114/5
(pixel-scroll-precision-mode 1)
(setq pixel-scroll-precision-interpolate-page t)
(defun +pixel-scroll-interpolate-down (&optional lines)
(interactive)
(if lines
(pixel-scroll-precision-interpolate (* -1 lines (pixel-line-height)))
(pixel-scroll-interpolate-down)))
(defun +pixel-scroll-interpolate-up (&optional lines)
(interactive)
(if lines
(pixel-scroll-precision-interpolate (* lines
(pixel-line-height))))
(pixel-scroll-interpolate-up))
(defalias 'scroll-up-command '+pixel-scroll-interpolate-down)
(defalias 'scroll-down-command '+pixel-scroll-interpolate-up)
)
(progn ; startup
(message "Loading core units...done (%fs)"
(float-time (time-subtract (current-time) before-user-init-time))))
<<debug-init>>
An overview of this outline:
In General.el
and Meow.el
, we setup the keybinding framework.
Then in Keybindings
, define keybindings.
Note: byte compile init.el will lead to function created by general-create-definer failed to work.
;; Make ESC quit prompts
;; (global-set-key ([kbd] "<escape>") 'keyboard-escape-quit)
(use-package general)
(use-package meow
:custom-face
(meow-cheatsheet-command ((t (:height 180 :inherit fixed-pitch))))
:config
;cate the behavior of vi's
(defun my-meow-append ()
"Move to the end of selection, switch to INSERT state."
(interactive)
(if meow--temp-normal
(progn
(message "Quit temporary normal mode")
(meow--switch-state 'motion))
(if (not (region-active-p))
(when (and (not (use-region-p))
(< (point) (point-max)))
(forward-char 1))
(meow--direction-forward)
(meow--cancel-selection))
(meow--switch-state 'insert)))
(advice-add 'meow-append :override #'my-meow-append)
(defun my-meow-open-below ()
"Open a newline below and switch to INSERT state."
(interactive)
(if meow--temp-normal
(progn
(message "Quit temporary normal mode")
(meow--switch-state 'motion))
(meow--switch-state 'insert)
;(goto-char (line-end-position))
(move-end-of-line 1)
(meow--execute-kbd-macro "RET")))
(advice-add 'meow-open-below :override #'my-meow-open-below)
(setq meow-keypad-self-insert-undefined nil)
(setq meow-selection-command-fallback '(
(meow-grab . meow-right-expand)
(meow-change . meow-change-char)
(meow-kill . meow-delete)
(meow-cancel-selection . keyboard-quit)
(meow-pop-selection . meow-pop-grab)
(meow-beacon-change . meow-beacon-change-char)
(meow-replace . meow-yank)
(meow-reverse . negative-argument)
))
(setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
(meow-global-mode)
)
- Let
C-<escape>
be the local leader. The convention is to useC-c
, but I makeC-c
save to system clipboard;)
- I do not directly press
C-<escape>
. Instead, I translate\
toC-<escape>
in meow’s normal mode. - The keybindings are bind to those major mode maps.
(defvar my/mode-leader "C-<escape>")
(defmacro my/key (&optional key)
`(general-key
(if ,key
(concat ,my/mode-leader " " ,key)
,my/mode-leader)))
(general-create-definer my/mode-leader-def
:prefix my/mode-leader
:wk-full-keys nil
)
(meow-normal-define-key
'("<escape>" . meow-cancel-selection)
'("SPC" . my/leader-prefix-cmd) ;; defined latter
'("1" . meow-expand-1) '("2" . meow-expand-2)
'("3" . meow-expand-3) '("4" . meow-expand-4)
'("5" . meow-expand-5) '("6" . meow-expand-6)
'("7" . meow-expand-7) '("8" . meow-expand-8)
'("9" . meow-expand-9) '("0" . meow-expand-0)
'("*" . tempel-insert) '("+" . tempel-expand)
'("q" . meow-quit) '("Q" . meow-quit)
;'("w" . meow-window) '("W" . meow-window)
'("e" . embark-dwim) '("E" . embark-act)
;'("r" . meow-) '("R" . meow-e)
'("t" . meow-till) '("T" . meow-till-expand)
'("a" . begin-of-line) '("a" . meow-beginning-of-thing)
'("s" . meow) '("s" . meow-bounds-of-thing)
'("d" . meow) '("d" . meow-inner-of-thing)
'("f" . end-of-line) '("f" . meow-end-of-thing)
'("g" . meow-right-expand) '("G" . meow-grab)
'("z" . meow-undo) '("Z" . meow-undo-in-selection)
'("x" . meow-kill) '("X" . meow-clipboard-kill)
'("c" . meow-clipboard-save)
'("v" . meow-replace) '("V" . meow-yank-pop)
'("C-v" . meow-clipboard-yank)
'("b". meow-block) '("B" . meow-to-block)
'("y" . meow-visit)
'("u" . meow-change) '("U" . meow-reverse)
'("i" . meow-insert) '("I" . meow-open-above)
'("o" . meow-append) '("O" . meow-open-below)
'("p" . meow-pop-selection)
'("[" . meow-beginning-of-thing) '("]" . meow-end-of-thing)
'("h" . meow-join) '("H" . meow-join)
'("j" . meow-left) '("J" . meow-left-expand)
'("k" . meow-prev) '("K" . meow-prev-expand)
'("l" . meow-next) '("L" . meow-next-expand)
'(";" . meow-right) '(":" . meow-right-expand)
'("'" . meow-line) '("\"" . meow-line)
'("C-j" . "C-<escape> C-j")
'("C-k" . "C-<escape> C-k")
'("C-l" . "C-<escape> C-l")
'("C-;" . "C-<escape> C-;")
'("n" . meow-search) '("N" . meow-pop-search)
'("m" . meow-mark-word) '("M" . meow-mark-symbol)
'("," . meow-back-word) '("<" . meow-back-symbol)
'("." . meow-next-word) '(">" . meow-next-symbol)
'("/" . meow-reverse)
'("\"" . fingertip-wrap-double-quote)
'("(" . fingertip-wrap-round)
'("[" . fingertip-wrap-bracket)
'("{" . fingertip-wrap-curly)
)
(meow-motion-overwrite-define-key
'("j" . meow-left)
'("k" . meow-prev)
'("l" . meow-next)
'(";" . meow-right)
'("SPC" . my/leader-prefix-cmd) ;; defined latter
'("<escape>" . ignore)
)
(meow-leader-define-key
;; Use SPC (0-9) for digit arguments.
'("1" . meow-digit-argument) '("2" . meow-digit-argument)
'("3" . meow-digit-argument) '("4" . meow-digit-argument)
'("5" . meow-digit-argument) '("6" . meow-digit-argument)
'("7" . meow-digit-argument) '("8" . meow-digit-argument)
'("9" . meow-digit-argument) '("0" . meow-digit-argument)
'("/" . meow-keypad-describe-key) '("?" . meow-cheatsheet)
;;'("SPC" . config/leader-prefix-cmd)
)
(general-def
:keymaps '(global-map)
"C-v" '(clipboard-yank :wk "paste")
"C-SPC" '(toggle-input-method :wk "input method")
"<f12>" 'org-capture
"C-j" (my/key "C-j")
"C-;" (my/key "C-;")
"C-k" (my/key "C-k")
"C-l" (my/key "C-l")
;"C-/" '(yank :wk "comment-dwim")
)
(general-def
:keymaps '(meow-normal-state-keymap meow-motion-state-keymap)
"\\" (my/key)
"M-j" '(windmove-left :wk " Win")
"M-k" '(windmove-up :wk " Win")
"M-l" '(windmove-down :wk " Win")
"M-;" '(windmove-right :wk " Win")
"M-\'" '(delete-window :wk " Win")
"M-," '(sort-tab-select-prev-tab :wk " Tab")
"M-." '(sort-tab-select-next-tab :wk " Tab")
"M-/" '(sort-tab-close-current-tab :wk " Tab")
)
(general-create-definer my/leader
:prefix-command 'my/leader-prefix-cmd
:prefix-map 'my/leader-prefix-map
:wk-full-keys nil
"DEL" '(which-key-undo :wk "undo-key")
)
(my/leader
"SPC" (my/key)
"/" '(comment-dwim :wk "comment")
"c" '(nil :wk "consult")
"d" '(dirvish-side :wk "dirvish-side ")
"D" '(dirvish :wk "dirvish")
"r" '(nil :wk "run")
"s" '(save-buffer :wk "save")
"t" '(nil :wk "toggle")
"w" '(nil :wk "workspace")
"x" '(consult-mode-command :wk "execute")
"z" '(vundo :wk "visual undo")
)
(my/leader :infix "r"
"b" '(nil :wk "borg")
"e" '(elfeed :wk " elfeed")
"t" '(telega :wk " telega")
"p" '(profiler-start :wk " profiler")
"P" '(profiler-stop :wk " profiler stop")
)
;; Borg
(my/leader :infix "rb"
"a" '(borg-assimilate :wk " assimilate ")
"b" '(borg-build :wk " build")
"c" '(borg-clone :wk " clone")
"d" '(borg-remove :wk " delete")
"r" '(borg-activate :wk " run")
)
(my/leader :infix "c"
"l" '(consult-line :wk "line")
"L" '(consult-line-multi :wk "line multi")
"o" '(consult-outline :wk "outline")
"i" '(consult-imenu :wk "imenu")
"I" '(consult-imenu-multi :wk "imenu multi")
"r" '(consult-ripgrep :wk "ripgrep")
"m" '(consult-mark :wk "mark")
"x" '(consult-mode-command :wk "execute")
)
(my/leader :infix "w" ;; workspaces
"\\" '(tab-new :wk "tab ")
"|" '(tab-close :wk "tab ")
"[" '(tab-previous :wk "tab ")
"]" '(tab-next :wk "tab ")
"/" '(consult-buffer :wk "buffer ")
"f" '(find-file :wk "file ")
"r" '(revert-buffer-quick :wk "revert")
"J" '(split-window-right :wk "split ")
"K" '(split-window-below :wk "split ")
"L" '(split-window-above :wk "split ")
":" '(split-window-left :wk "split ")
)
;; toggle
(my/leader :infix "t"
"o" '(olivetti-mode :wk " olivetti")
"l" '(nil :wk " line Number ")
)
(my/leader :infix "tl"
"DEL" '(which-key-undo :wk " Undo key ")
"n" '(config/toggle-line-number-nil :wk " Nil ")
"a" '(config/toggle-line-number-absolute :wk " Absolute ")
"r" '(config/toggle-line-number-relative :wk " Relative ")
"v" '(config/toggle-line-number-visual :wk " Visual ")
"h" '(hl-line-mode :wk " Hl-line")
)
;; Git
(my/leader :infix "g"
"" '(nil :wk "git")
"g" '(magit :wk " magit")
)
;; windows, buffers and tabs(workspaces)
;; these are copied from emacs source code
(defun split-window-left (&optional size window-to-split)
(interactive `(,(when current-prefix-arg
(prefix-numeric-value current-prefix-arg))
,(selected-window)))
(let (new-window)
(when (and size (< size 0) (< (- size) window-min-width))
;; `split-window' would not signal an error here.
(error "Size of new window too small"))
(setq new-window (split-window window-to-split size 'left))
;; Always copy quit-restore parameter in interactive use.
(let ((quit-restore (window-parameter window-to-split 'quit-restore)))
(when quit-restore
(set-window-parameter new-window 'quit-restore quit-restore)))
new-window))
(defun split-window-above (&optional size window-to-split)
(interactive `(,(when current-prefix-arg
(prefix-numeric-value current-prefix-arg))
,(selected-window)))
(let ((old-point (window-point))
moved-by-window-height moved new-window bottom)
(when (and size (< size 0) (< (- size) window-min-height))
;; `split-window' would not signal an error here.
(error "Size of new window too small"))
(setq new-window (split-window window-to-split size 'above))
(when (and (null split-window-keep-point)
(or (null window-to-split)
(eq window-to-split (selected-window))))
(with-current-buffer (window-buffer window-to-split)
(save-excursion
(goto-char (window-start))
(setq moved (vertical-motion (window-height)))
(set-window-start new-window (point))
(when (> (point) (window-point new-window))
(set-window-point new-window (point)))
(when (= moved (window-height))
(setq moved-by-window-height t)
(vertical-motion -1))
(setq bottom (point)))
(and moved-by-window-height
(<= bottom (point))
(set-window-point window-to-split (1- bottom)))
(and moved-by-window-height
(<= (window-start new-window) old-point)
(set-window-point new-window old-point)
(select-window new-window))))
;; Always copy quit-restore parameter in interactive use.
(let ((quit-restore (window-parameter window-to-split 'quit-restore)))
(when quit-restore
(set-window-parameter new-window 'quit-restore quit-restore)))
new-window))
(use-package transient-posframe
:config
(setq transient-posframe-min-height 1)
(setq transient-posframe-poshandler
'posframe-poshandler-frame-bottom-right-corner)
(transient-posframe-mode)
)
Magit and meow all use transient maps, therefore we let which-key show transient maps.
(use-package which-key
:init
;; contents
(setq which-key-sort-order 'which-key-key-order)
(setq which-key-sort-uppercase-first nil)
;; delays
(setq which-key-idle-delay 0.01) ; the first idle
(setq which-key-idle-secondary-delay 0.01) ; set to 0 will cause some problems
(setq which-key-show-early-on-C-h t)
;; arrangements
(setq which-key-max-display-columns nil)
(setq which-key-max-description-length 25) ;
(setq which-key-allow-imprecise-window-fit t) ; reduce delay
(setq which-key-show-transient-maps t)
(setq which-key-frame-max-height 60)
;; window
(setq which-key-popup-type 'side-window)
(setq which-key-side-window-location 'right)
;; characters
(setq which-key-prefix-prefix " ")
(setq which-key-separator " ") ; yeah I don't like the arrow
;; (dolist (replace
;; '((("SPC" . nil) . ("" . nil))
;; (("TAB" . nil) . ("" . nil))
;; (("RET" . nil) . ("" . nil))
;; (("DEL" . nil) . ("" . nil))
;; ))
;; (add-to-list 'which-key-replacement-alist replace))
:config
(set-face-attribute 'which-key-key-face nil :inherit 'fixed-pitch)
(which-key-mode 1)
)
Which-key-posframe use posframe to show which-key popup.
Here I tried to make which-key act like the one in helix editor. It pops up instantly at the right bottom of the editor, and displays one column vertically.
(use-package which-key-posframe
:after which-key
:config
(setq which-key-posframe-poshandler
'posframe-poshandler-frame-bottom-right-corner)
(setq which-key-max-display-columns 1)
(setq which-key-min-display-lines 1)
(which-key-posframe-mode)
)
(use-package rime
:custom
(rime-emacs-module-header-root "~/.nix-profile/include")
(rime-librime-root "~/.nix-profile")
(rime-share-data-dir "~/.config/fcitx/rime")
:config
(setq default-input-method "rime"
rime-show-candidate 'posframe)
(setq rime-disable-predicates
'(meow-normal-mode-p
meow-motion-mode-p
rime-predicate-after-alphabet-char-p
rime-predicate-prog-in-code-p))
(setq pgtk-use-im-context-on-new-connection nil)
)
We try to decide what emacs would look like beneath this outline. However, many packages affect how emacs looks. To make it simplier, we’ll just define things that only changes how emacs looks, but do not provides extra functionalities or stuffs, meanning that deleting them will not affect how emacs works (hopefully).
Fonts in emacs is really a complex system. If you don’t treat it with care, you’ll definitedly encounter some bugs.One essential thing about font is pitch. In general, pitch control’s whether a font is fixed-widthed or non-fixed-widthed. Currently there’re 2 helpful packages that controls font pitch: mixed-pitch-mode
and fixed-pitch-mode
.
I recommend stick to only one of these modes and does all the font settings based on that mode.
(use-package mixed-pitch
:custom
'(mixed-pitch-fixed-pitch-faces
'(diff-added diff-context diff-file-header diff-function diff-header diff-hunk-header diff-removed
font-latex-math-face font-latex-sedate-face font-latex-warning-face font-latex-sectioning-5-face font-lock-builtin-face font-lock-comment-delimiter-face font-lock-constant-face font-lock-doc-face font-lock-function-name-face font-lock-keyword-face font-lock-negation-char-face font-lock-preprocessor-face font-lock-regexp-grouping-backslash font-lock-regexp-grouping-construct font-lock-string-face font-lock-type-face font-lock-variable-name-face line-number line-number-current-line line-number-major-tick line-number-minor-tick markdown-code-face markdown-gfm-checkbox-face markdown-inline-code-face markdown-language-info-face markdown-language-keyword-face markdown-math-face message-header-name message-header-to message-header-cc message-header-newsgroups message-header-xheader message-header-subject message-header-other mu4e-header-key-face mu4e-header-value-face mu4e-link-face mu4e-contact-face mu4e-compose-separator-face mu4e-compose-header-face
org-document-info-keyword org-code org-indent org-latex-and-related org-checkbox org-formula org-special-keyword org-table org-verbatim widget-field org-modern-label))
'(mixed-pitch-set-height nil)
:config
(setq mixed-pitch-set-height nil)
(set-face-attribute
'default nil
:family "IBM Plex Mono Text"
;; :family "Sarasa Gothic SC Nerd Font"
;; :family "IBM Plex Serif"
:height 150)
(set-face-attribute
'fixed-pitch nil
:family "IBM Plex Mono Text"
;; :family "RobotoMono Nerd Font Mono"
;; :family "CommitMono Nerd Font Mono"
;; :family "Sarasa Fixed SC"
;; :family "Monaspace Neon"
:height 1.0)
(set-face-attribute 'fixed-pitch-serif nil
;; :family "Sarasa Gothic SC Nerd Font"
:family "IBM Plex Mono Text"
;; :family "IBM Plex Serif"
:height 1.0)
(set-face-attribute 'variable-pitch nil
;; :family "Sarasa Gothic SC Nerd Font"
:family "IBM Plex Serif"
:height 1.0)
(set-face-attribute 'link nil :underline t :bold nil)
;; patches nerd font
(set-fontset-font t 'han "Source Han Serif SC")
(set-fontset-font t 'symbol "Noto Sans Symbols")
(set-fontset-font t 'nil "Noto Emoji")
(set-fontset-font t 'nil "Weather Icons")
(set-fontset-font t 'nil "Material Icons")
(set-fontset-font t 'nil "github-octicons")
(set-fontset-font t 'nil "file-icons")
(set-fontset-font t 'nil "FontAwesome")
(set-fontset-font t 'nil "Symbols Nerd Font Mono")
)
You can use the bindings CTRL plus =/- for zooming in/out. You can also use CTRL plus the mouse wheel for zooming in/out.
(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "<C-wheel-down>") 'text-scale-decrease)
(global-set-key (kbd "<C-wheel-up>") 'text-scale-increase)
(defun my/toggle-line-spacing ()
"Toggle line spacing between no extra space to extra half line height.
URL `http://xahlee.info/emacs/emacs/emacs_toggle_line_spacing.html'
Version 2017-06-02"
(interactive)
(if line-spacing
(setq line-spacing nil)
(setq line-spacing 0.5))
(redraw-frame (selected-frame)))
All-the-icons is an icon set that can be used with dashboard, dired, ibuffer and other Emacs programs.
(use-package all-the-icons
:if (display-graphic-p))
;(use-package all-the-icons-dired
; :hook (dired-mode . (lambda () (all-the-icons-dired-mode t))))
NOTE: In order for the icons to work it is very important that you install the Resource Fonts included in this package. Run M-x all-the-icons-install-fonts to install necessary icons.
All-the-icons-completion makes icons appear in the minibuffer. Cool.(use-package all-the-icons-completion
:after (marginalia all-the-icons)
:hook (marginalia-mode . all-the-icons-completion-marginalia-setup)
:init
(all-the-icons-completion-mode))
Symbols Nerd Fonts Mono
for you.
(use-package nerd-icons
;; :custom
;; The Nerd Font you want to use in GUI
;; "Symbols Nerd Font Mono" is the default and is recommended
;; but you can use any other Nerd Font if you want
;; (nerd-icons-font-family "Symbols Nerd Font Mono")
)
M-x counsel-load-theme
to choose between them easily.
Solaire-mode makes certain buffers grossly incandescent. Useful to distinguish the main buffers from others.
(use-package solaire-mode
:defer t
:init (solaire-global-mode)
:config
(add-hook 'org-src-mode-hook 'turn-off-solaire-mode)
)
Note that a ‘frame’ is a window on the desktop, a ‘window’ is a subwindow of emacs.
(use-package posframe
:config
(defun posframe-poshandler-frame-upper-center! (info)
"Posframe's position handler.
This poshandler function let center of posframe align to
vertically upper 1/6, horizontally center
of frame."
(cons (/ (max 0 (- (plist-get info :parent-frame-width)
(plist-get info :posframe-width))) 2)
(/ (plist-get info :parent-frame-height) 6)))
(defun posframe-poshandler-window-upper-center! (info)
"Posframe's position handler.
This poshandler function let center of posframe align to
vertically upper 1/6, horizontally center
of window."
(let* ((window-left (plist-get info :parent-window-left))
(window-top (plist-get info :parent-window-top))
(window-width (plist-get info :parent-window-width))
(window-height (plist-get info :parent-window-height))
(posframe-width (plist-get info :posframe-width)))
(cons (max 0 (+ window-left (/ (- window-width posframe-width) 2)))
(+ window-top (/ window-height 6))))
)
)
(defun my/set-transparency (value)
"Sets the transparency of the frame window. 0=transparent/100=opaque"
(interactive "nTransparency Value 0 - 100 opaque:")
(set-frame-parameter nil 'alpha-background value))
Olibetti is a simple Emacs minor mode for a nice writing environment. Set olivetti-style to both margins and fringes for a fancy “page” look.
Note that for pages with variable-pitch fonts,
olivetti-body-width
should be set smaller for it to look good.
(use-package olivetti
:defer nil
:hook (org-mode . olivetti-mode)
(Custom-mode . olivetti-mode)
(help-mode . olivetti-mode)
;(dashboard-mode . olivetti-mode)
(dashboard-mode . variable-pitch-mode)
(olivetti-mode . visual-line-mode)
:init
(setq-default fill-column 100)
:config
;If nil (the default), use the value of fill-column + 2.
(setq olivetti-body-width nil olivetti-style 'fancy)
;; (set-face-attribute 'olivetti-fringe nil :background "#171B24")
(defun config/window-center (width)
(interactive)
(setq fill-column width)
(olivetti-mode)
)
;; (config/leader
;; "tc" '(olivetti-mode :wk " Center")
;; )
)
(setq-default visual-fill-column-center-text t)
anywhere, anytime
in emacs.
Therefore I grouped them together.
Mode mapVertico provides a performant and minimalistic vertical completion UI based on the default completion system.
(use-package vertico
:init
;; Different scroll margin
(setq vertico-scroll-margin 1)
;; Show more candidates
(setq vertico-count 20)
;; Grow the Vertico minibuffer
;; (setq vertico-resize 'grow-only)
;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
(setq vertico-cycle t)
;; use Vertico as an in-buffer completion UI
(setq completion-in-region-function 'consult-completion-in-region)
(vertico-mode 1)
:config
(general-def
:keymaps '(vertico-map)
"C-l" 'vertico-next
"C-k" 'vertico-previous
"C-j" 'vertico-directory-delete-word
"C-;" 'vertico-directory-enter
"C-," 'vertico-previous-group
"C-." 'vertico-next-group
"A-l" 'vertico-next
"A-k" 'vertico-previous
"A-j" 'vertico-directory-delete-word
"A-;" 'vertico-directory-enter
"A-," 'vertico-previous-group
"A-." 'vertico-next-group
"RET" 'vertico-directory-enter
"DEL" 'vertico-directory-delete-char
"M-DEL" 'vertico-directory-delete-word
)
)
tweaks to build vertico
[submodule "vertico"]
load-path = .
load-path = extensions
(use-package vertico-directory
:after vertico
;; More convenient directory navigation commands
:bind (:map vertico-map
)
;; Tidy shadowed file names
:hook (rfn-eshadow-update-overlay . vertico-directory-tidy))
Vertico-multiform configures Vertico modes per command or completion category.
(use-package vertico-multiform
:after vertico
:config (vertico-multiform-mode)
)
Vertico-posframe is an vertico extension, which lets vertico use posframe to show its candidate menu. See Posframe for function defintion.
(use-package vertico-posframe
;:disabled
:after vertico-multiform
:init
(setq vertico-posframe-poshandler
'posframe-poshandler-frame-top-center)
(setq vertico-count 15
vertico-posframe-border-width 3
vertico-posframe-width 140
)
(setq vertico-posframe-parameters
'((left-fringe . 20)
(right-fringe . 20)))
(setq vertico-multiform-commands
'(
(execute-extended-command ; M-x
(vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
(vertico-posframe-width . 120))
(meow-visit
(vertico-posframe-poshandler . posframe-poshandler-window-top-right-corner)
(vertico-posframe-width . 50))
(meow-yank-pop; M-x
(vertico-posframe-poshandler . posframe-poshandler-point-window-center)
(vertico-posframe-width . 50))
(find-file
(vertico-count . 25)
(vertico-posframe-width . 100)
(vertico-posframe-poshandler . posframe-poshandler-window-upper-center!))
(consult-buffer
(vertico-count . 25)
(vertico-posframe-width . 100)
(vertico-posframe-poshandler . posframe-poshandler-window-upper-center!))
(switch-to-buffer
(vertico-count . 25)
(vertico-posframe-width . 100)
(vertico-posframe-poshandler . posframe-poshandler-window-upper-center!))
(org-insert-link; C-c C-l
(vertico-posframe-poshandler . posframe-poshandler-point-top-left-corner)
(vertico-posframe-width . 70))
(tempel-insert
(vertico-posframe-poshandler . posframe-poshandler-point-top-left-corner)
(vertico-posframe-width . 70))
(consult-imenu
(vertico-count . 40)
(vertico-posframe-poshandler . posframe-poshandler-window-top-right-corner)
(vertico-posframe-width . 80))
(consult-outline
(vertico-count . 30)
(vertico-posframe-poshandler . posframe-poshandler-window-top-right-corner)
(vertico-posframe-width . 40))
(consult-line
(vertico-count . 30)
(vertico-posframe-poshandler . posframe-poshandler-frame-top-right-corner)
(vertico-posframe-width . 60))
(t
(vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
(vertico-posframe-width . 120))
))
:config
(vertico-multiform-mode 1)
(vertico-posframe-mode 1)
)
(use-package orderless
:init
(setq completion-styles '(orderless))
(setq orderless-component-separator
#'orderless-escapable-split-on-space)
(setq orderless-matching-styles
'(orderless-initialism orderless-prefixes orderless-regexp))
)
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init
(savehist-mode))
;; A few more useful configurations...
(use-package emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
(defun crm-indicator (args)
(cons (format "[CRM%s] %s"
(replace-regexp-in-string
"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
crm-separator)
(car args))
(cdr args)))
(advice-add #'completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; Emacs 28: Hide commands in M-x which do not work in the current mode.
;; Vertico commands are hidden in normal buffers.
;; (setq read-extended-command-predicate
;; #'command-completion-default-include-p)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t))
Consult provides search and navigation commands based on the Emacs completion function completing-read.
(use-package consult
;; Replace bindings. Lazily loaded due by `use-package'.
:bind (;; C-c bindings in `mode-specific-map'
("C-c M-x" . consult-mode-command)
("C-c h" . consult-history)
;("C-c k" . consult-kmacro)
("C-c m" . consult-man)
;("C-c i" . consult-info)
([remap Info-search] . consult-info)
;; C-x bindings in `ctl-x-map'
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
([remap list-buffers] . consult-buffer) ;; orig. switch-to-buffer
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
;; Custom M-# bindings for fast register access
("M-#" . consult-register-load)
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
("C-M-#" . consult-register)
;; Other custom bindings
("M-y" . consult-yank-pop) ;; orig. yank-pop
;; M-g bindings in `goto-map'
("M-g e" . consult-compile-error)
("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-g o" . consult-outline) ;; Alternative: consult-org-heading
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-g i" . consult-imenu)
("M-g I" . consult-imenu-multi)
;; M-s bindings in `search-map'
("M-s d" . consult-find)
("M-s D" . consult-locate)
("M-s g" . consult-grep)
("M-s G" . consult-git-grep)
("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-s k" . consult-keep-lines)
("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map isearch-mode-map
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
;; Minibuffer history
:map minibuffer-local-map
("M-s" . consult-history) ;; orig. next-matching-history-element
("M-r" . consult-history)) ;; orig. previous-matching-history-element
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI.
:hook (completion-list-mode . consult-preview-at-point-mode)
:init
;; Optionally configure the register formatting.
;; This improves the register preview for
;; `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
(setq register-preview-delay 0.5
register-preview-function #'consult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
:config
;; Optionally configure preview.
;; The default value is 'any, such that any key triggers the preview.
;; (setq consult-preview-key 'any)
;; (setq consult-preview-key "M-.")
;; (setq consult-preview-key '("S-<down>" "S-<up>"))
;; For some commands and buffer sources it is useful to configure the
;; :preview-key on a per-command basis using the `consult-customize' macro.
(consult-customize
consult-theme
:preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-file-register
consult--source-recent-file consult--source-project-recent-file
;; :preview-key "M-."
:preview-key '(:debounce 0.4 any)
)
;; Optionally configure the narrowing key.
(setq consult-narrow-key "<") ;; "C-+"
(setq consult-buffer-filter "\\*")
;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)
)
(use-package marginalia
:general
(:keymaps 'minibuffer-local-map
"M-A" 'marginalia-cycle)
:custom
(marginalia-max-relative-age 0)
(marginalia-align 'right)
:init
(marginalia-mode)
)
(use-package sort-tab
:if (not (daemonp))
:init (sort-tab-mode)
:config
(defun my/sort-tab-filter (buffer)
"a filter functioni for sort-tab. return t hides the buffer"
(let ((major-mode (buffer-local-value 'major-mode buffer)))
(cond ((eq major-mode 'dired-mode) t)
(t nil)))
)
(setq sort-tab-hide-function 'my/sort-tab-filter)
)
toggle-one-window
, to toggle between one window to multiple window. When you have a multiple windows, it remembers the window layout and deletes all other windows. The next call restores them.
(use-package toggle-one-window)
(use-package doom-modeline
:init
(setq
;; doom-modeline-height 37
doom-modeline-enable-word-count t
doom-modeline-modal nil
)
(doom-modeline-mode 1)
:config
(set-face-attribute 'doom-modeline t
:inherit 'variable-pitch)
;; let modeline show on the header, not bottom
(defun move-up-modeline ()
(interactive)
(progn
(setq-default header-line-format mode-line-format)
(setq-default mode-line-format nil)
))
(move-up-modeline)
)
NOTE1: Nerd-icons are necessary. Run M-x nerd-icons-install-fonts to install the resource fonts.
NOTE2: All-the-icons hasn’t been supported since 4.0.0. If prefer all-the-icons, use release 3.4.0, then run M-x all-the-icons-install-fonts to install necessary icons.
This package implements hiding or abbreviation of the modeline displays (lighters) of minor-modes. With this package installed, you can add ‘:diminish’ to any use-package block to hide that particular mode in the modeline.(use-package diminish)
(use-package awesome-tray
:defer t
:init
;(awesome-tray-mode)
:config
(setq awesome-tray-hide-mode-line nil)
)
Dashboard is an extensible startup screen showing you recent files, bookmarks, agenda items and an Emacs banner.
Emacs currently cannot display correpng or svg with alpha channels, when emacs’s background is transparent. A workaround is to use xpm or webp format image.
(use-package dashboard
:if (not (daemonp))
:init
(setq initial-buffer-choice 'dashboard-open
dashboard-image-banner-max-width 1100
dashboard-set-heading-icons t
dashboard-center-content t ;; set to 't' for centered content
dashboard-set-file-icons t
initial-buffer-choice (lambda () (get-buffer-create "*scratch*"))
dashboard-startup-banner ;; use custom image as banner
(concat user-emacs-directory "assets/EmaxBound.xpm")
dashboard-items
'((recents . 5)
(agenda . 5 )
(bookmarks . 3)
(projects . 3)
(registers . 3)
)
)
:config
(dashboard-setup-startup-hook)
(setq-default header-line-format mode-line-format)
(setq-default mode-line-format nil)
(set-face-attribute 'dashboard-items-face nil)
:bind (:map dashboard-mode-map
("k" . 'dashboard-previous-line)
("l" . 'dashboard-next-line)
(";" . 'dashboard-next-section)
("j" . 'dashboard-previous-section)
)
)
(use-package vundo
:config
(general-def vundo-mode-map
"j" 'vundo-backward
";" 'vundo-forward
"k" 'vundo-previous
"l" 'vundo-next
"q" 'vundo-quit
"s" 'vundo-save
)
)
(use-package magit
:defer t
:commands (magit-add-section-hook)
;; :hook (magit-mode . olivetti-mode)
:config
(magit-add-section-hook 'magit-status-sections-hook
'magit-insert-modules
'magit-insert-stashes
'append
)
(setq magit-show-long-lines-warning nil)
(set-face-attribute 'magit-hash nil :inherit 'fixed-pitch)
(set-face-attribute 'magit-diff-removed-highlight nil :inherit 'fixed-pitch)
(set-face-attribute 'magit-diff-context-highlight nil :inherit 'fixed-pitch)
(set-face-attribute 'magit-diff-added-highlight nil :inherit 'fixed-pitch)
(general-def
:keymaps '(magit-mode-map)
"n" 'magit-gitignore
"p" 'magit-push
"P" 'magit-pull
"DEL" 'magit-discard
)
)
- tweaks to build magit
[submodule "magit"]
no-byte-compile = lisp/magit-libgit.el
Diff highlight highlights the fringe of lines that have been edited.
(use-package diff-hl
:custom-face
(diff-hl-change ((t (:background "#2c5f72" :foreground "#77a8d9"))))
(diff-hl-delete ((t (:background "#844953" :foreground "#f27983"))))
(diff-hl-insert ((t (:background "#5E734A" :foreground "#a6cc70"))))
:init
(setq diff-hl-draw-borders nil)
:config
;(global-diff-hl-mode)
(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh t)
(add-hook 'prog-mode-hook #'diff-hl-mode)
(add-hook 'conf-mode-hook #'diff-hl-mode)
(add-hook 'dired-mode-hook #'diff-hl-dired-mode)
(add-hook 'magit-pre-refresh-hook #'diff-hl-magit-pre-refresh)
(add-hook 'magit-post-refresh-hook #'diff-hl-magit-post-refresh)
;; Highlight on-the-fly
(diff-hl-flydiff-mode 1)
(unless (display-graphic-p)
;; Fall back to the display margin since the fringe is unavailable in tty
(diff-hl-margin-mode 1)
;; Avoid restoring `diff-hl-margin-mode'
(with-eval-after-load 'desktop
(add-to-list 'desktop-minor-mode-table
'(diff-hl-margin-mode nil))))
)
(use-package diredfl
:after dired
:hook
((dired-mode . diredfl-mode)
;; highlight parent and directory preview as well
(dirvish-directory-view-mode . diredfl-mode))
:config
(set-face-attribute 'diredfl-dir-name nil :bold t)
)
Tweaks to build dirvish. Load dirvish and its extensions.
[submodule "dirvish"]
load-path = .
load-path = extensions
Dirvish is a dropin replacement for dired. It looks and feels like ranger.
(use-package dirvish
:after dired
:custom
(dirvish-quick-access-entries ;`setq' won't work for custom
'(("h" "~/" "Home")
("d" "~/Downloads/" "Downloads")
("m" "/mnt/" "Drives")
("t" "~/.local/share/Trash/files/" "TrashCan"))
)
:config
(dirvish-define-preview exa (file)
"Use `exa' to generate directory preview."
:require ("exa") ; tell Dirvish to check if we have the executable
(when (file-directory-p file) ; we only interest in directories here
`(shell . ("exa" "-al" "--color=always" "--icons"
"--group-directories-first" ,file))))
(add-to-list 'dirvish-preview-dispatchers 'exa)
;; (dirvish-peek-mode) ; Preview files in minibuffer
;; (dirvish-side-follow-mode) ; similar to `treemacs-follow-mode'
(setq dirvish-path-separators (list " " " " " "))
(setq dirvish-mode-line-format
'(:left (sort symlink) :right (omit yank index)))
(setq dirvish-attributes
'(all-the-icons file-time file-size collapse subtree-state vc-state git-msg))
(setq delete-by-moving-to-trash t)
(setq dired-listing-switches
"-l --almost-all --human-readable --group-directories-first --no-group")
(general-def dirvish-mode-map
"q" '(dirvish-quit :wk "quit")
"TAB" '(dirvish-toggle-subtree :wk "subtree toggle")
"j" '(dired-up-directory :wk "up-dir")
";" '(dired-find-file :wk "open/toggle")
"C-b" '(dired-up-directory :wk "up-dir")
"C-f" '(dired-find-file :wk "open/toggle")
"a" '(dirvish-quick-access :wk "access")
"c" '(dired-do-copy :wk "copy")
"u" '(dired-do-rename :wk "rename")
)
;; (nmap dirvish-mode-map
;; "?" '(dirvish-dispatch :wk "Dispatch")
;; "TAB" '(dirvish-subtree-toggle :wk "Subtre-toggle")
;; "q" '(dirvish-quit :wk "Quit")
;; "h" '(dired-up-directory :wk "Up-dir")
;; "l" '(dired-find-file :wk "Open/Toggle")
;; "a" '(dirvish-quick-access :wk "Access")
;; "f" '(dirvish-file-info-menu :wk "File Info Menu")
;; "y" '(dirvish-yank-menu :wk "Yank Menu")
;; "N" '(dirvish-narrow :wk "Narrow")
;; ; `dired-view-file'
;; "v" '(dirvish-vc-menu :wk "View-file")
;; ; `dired-sort-toggle-or-edit'
;; "s" '(dirvish-quicksort :wk "Quick-sort")
;; "M-f" '(dirvish-history-go-forward :wk "History-forward")
;; "M-b" '(dirvish-history-go-backward :wk "History-back")
;; "M-l" '(dirvish-ls-switches-menu :wk "ls Switch Menu")
;; "M-m" '(dirvish-mark-menu :wk "Mark Menu")
;; "M-t" '(dirvish-layout-toggle :wk "Layout-toggle")
;; "M-s" '(dirvish-setup-menu :wk "Setup-Menu")
;; "M-e" '(dirvish-emerge-menu :wk "Emerge-Menu")
;; "M-j" '(dirvish-fd-jump :wk "fd-jump")
;; )
(dirvish-override-dired-mode)
)
(use-package embark
;; :bind
;; (("C-." . embark-act) ;; pick some comfortable binding
;; ("C-;" . embark-dwim) ;; good alternative: M-.
;; ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
:init
;; Optionally replace the key help with a completing-read interface
(setq prefix-help-command #'embark-prefix-help-command)
;; Show the Embark target at point via Eldoc. You may adjust the Eldoc
;; strategy, if you want to see the documentation from multiple providers.
(add-hook 'eldoc-documentation-functions #'embark-eldoc-first-target)
;; (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)
:config
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none)))))
(use-package embark-consult
:hook
(embark-collect-mode . consult-preview-at-point-mode))
Blink-search is the fastest multi-source search framework for Emacs.
(use-package blink-search
:defer t
:config
(setq blink-search-enable-posframe t)
)
Color-rg is a search and refactoring tool based on ripgrep.
(use-package color-rg
:config
(general-def isearch-mode-map
"M-s M-s" 'isearch-toggle-color-rg
)
)
Voyager is an Emacs debugging plugin based on the DAP protocol.
(use-package voyager)
(use-package holo-layer
:commands holo-layer-enable
:if (memq window-system '(pgtk mac ns))
:config
(setq holo-layer-enable-cursor-animation 1
holo-layer-enable-window-border 1
holo-layer-sort-tab-ui 1
;;holo-layer-cursor-animation-type "arrow easing"
)
(holo-layer-enable)
)
(general-def
:keymaps '(prog-mode-map)
:wk-full-keys nil
"C-<escape>" '(my/prog-cmd :wk "Prog")
)
(general-def
:prefix-command 'my/prog-cmd
:prefix-map 'my/prog-map
:wk-full-keys nil
"C-j" '()
"C-k" '(backward-paragraph :wk " para")
"C-l" '(forward-paragraph :wk " para")
"C-;" '()
)
(use-package beacon
:defer t
:config
(beacon-mode)
)
Be careful that it’s possible to consume a horrible amount of memory with pulsing-cursor-blinks
set to 0 (means infinite blinks) and without proper gc configuration (can be done with GCMH).
(use-package pulsing-cursor
:config
(setq pulse-delay 0.02
pulse-iterations 10)
(setq pulsing-cursor-interval 0.7)
(setq pulsing-cursor-blinks 20)
(set-face-attribute 'pulsing-cursor-overlay-face1 nil
:background (face-background 'cursor))
;; (setq blink-cursor-alist '((box . hollow)))
(advice-add 'describe-face :around
(lambda (func FACE &optional FRAME)
(pulsing-cursor-mode -1)
(unwind-protect
(funcall-interactively func FACE FRAME)
(pulsing-cursor-mode 1))))
(pulsing-cursor-mode)
)
(use-package goggles
:hook ((prog-mode text-mode org-mode) . goggles-mode)
:config
(setq-default goggles-pulse t)) ;; set to nil to disable pulsing
Highlights the line that the cursor locates.
(use-package hl-line
:config
(defun my/read-face-advice (orig-fun &rest args)
"Advice function to turn off hl-line-mode before calling describe-face."
(if hl-line-mode
(progn
(hl-line-mode -1)
(apply orig-fun args)
(hl-line-mode 1)
)
(apply orig-fun args)))
;; (advice-add 'read-face-name :around #'my/read-face-advice)
;; (global-hl-line-mode)
)
Whitespace mode is a built in mode of emacs that visualizes whitespaces, tab symbols, indentations and related stuffs.
(use-package whitespace
:config
(setq whitespace-line-column 1000) ;; do not want line to be highlighted
)
;; (config/leader :infix "t"
;; "SPC" '(whitespace-mode :wk " Show Space")
;; )
(use-package emacs
:hook (prog-mode . config/toggle-line-number-absolute)
:init (setq display-line-numbers-width 4)
:config
(defun config/toggle-line-number-nil ()
(interactive)
(setq display-line-numbers nil)
)
(defun config/toggle-line-number-absolute ()
(interactive)
(setq display-line-numbers t)
)
(defun config/toggle-line-number-relative ()
(interactive)
(setq display-line-numbers 'relative)
)
(defun config/toggle-line-number-visual ()
(interactive)
(setq display-line-numbers 'visual)
)
)
This minor mode sets background color to strings that match color names, useful for UI and theme design.
(use-package simple-call-tree :defer t)
(use-package electric
:config
(setq-default indent-tabs-mode nil) ;; always indent with spaces
(setq electric-pair-mode t) ;; global-minor mode
)
(use-package aggressive-indent
:disabled
:config
(global-aggressive-indent-mode 1)
)
(use-package highlight-indent-guides
:hook (prog-mode . highlight-indent-guides-mode)
:config
(setq highlight-indent-guides-method 'character
highlight-indent-guides-character 9474
highlight-indent-guides-auto-enabled nil
highlight-indent-guides-responsive nil
)
(set-face-attribute 'highlight-indent-guides-character-face nil
:foreground "#3b445f")
(set-face-attribute 'highlight-indent-guides-top-character-face nil
:foreground "#ffcc66")
)
Dtrt-indent is a minor mode that guesses the indentation offset originally used for creating source code files and transparently adjusts the corresponding settings in Emacs, making it more convenient to edit foreign files.
(use-package dtrt-indent
:config
(dtrt-indent-global-mode)
)
(use-package smartparens
:config
(smartparens-global-mode)
)
(use-package highlight-parentheses
:init
(show-paren-mode 0)
:config
(setq highlight-parentheses-highlight-adjacent 1
highlight-parentheses-attributes '((:box (:line-width (-1 . -1))))
highlight-parentheses-colors nil
highlight-parentheses-delay 0.03)
(global-highlight-parentheses-mode)
)
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode)
)
(use-package tempel
;; Require trigger prefix before template name when completing.
;; :custom
;; (tempel-trigger-prefix "<")
:bind (("M-+" . tempel-complete) ;; Alternative tempel-expand
("M-*" . tempel-insert))
:init
;; Setup completion at point
(defun tempel-setup-capf ()
;; Add the Tempel Capf to `completion-at-point-functions'.
;; `tempel-expand' only triggers on exact matches. Alternatively use
;; `tempel-complete' if you want to see all matches, but then you
;; should also configure `tempel-trigger-prefix', such that Tempel
;; does not trigger too often when you don't expect it. NOTE: We add
;; `tempel-expand' *before* the main programming mode Capf, such
;; that it will be tried first.
(setq-local completion-at-point-functions
(cons #'tempel-expand
completion-at-point-functions)))
(add-hook 'conf-mode-hook 'tempel-setup-capf)
(add-hook 'prog-mode-hook 'tempel-setup-capf)
(add-hook 'text-mode-hook 'tempel-setup-capf)
;; Optionally make the Tempel templates available to Abbrev,
;; either locally or globally. `expand-abbrev' is bound to C-x '.
;; (add-hook 'prog-mode-hook #'tempel-abbrev-mode)
(global-tempel-abbrev-mode)
(my/mode-leader-def
:keymaps '(tempel-map)
"C-j" 'tempel-previous
"C-;" 'tempel-next
"TAB" 'tempel-next
)
)
;; Optional: Add tempel-collection.
;; The package is young and doesn't have comprehensive coverage.
(use-package tempel-collection
:after tempel
)
(use-package lsp-bridge
:config
(setq lsp-bridge-java-lsp-server "jdt-language-server")
(setq lsp-bridge-nix-lsp-server "nil")
(global-lsp-bridge-mode)
;(set-face-attributes 'lsp-bridge-alive-mode-line nil
; :inherit 'variable-pitch
;)
)
tweaks to build lsp-bridge
[submodule "lsp-bridge"]
load-path = .
load-path = acm
Treesit-auto
fingertip.el is a plugin that provides grammatical edit base on treesit
(use-package fingertip
:config
(dolist (hook (list
'c-mode-common-hook 'c-mode-hook 'c++-mode-hook
'c-ts-mode-hook 'c++-ts-mode-hook
'cmake-ts-mode-hook
'java-mode-hook
'haskell-mode-hook
'emacs-lisp-mode-hook
'lisp-interaction-mode-hook 'lisp-mode-hook
'maxima-mode-hook
'ielm-mode-hook
'bash-ts-mode-hook 'sh-mode-hook
'makefile-gmake-mode-hook
'php-mode-hook
'python-mode-hook 'python-ts-mode-hook
'js-mode-hook
'go-mode-hook
'qml-mode-hook
'jade-mode-hook
'css-mode-hook 'css-ts-mode-hook
'ruby-mode-hook
'coffee-mode-hook
'rust-mode-hook 'rust-ts-mode-hook
'qmake-mode-hook
'lua-mode-hook
'swift-mode-hook
'web-mode-hook
'markdown-mode-hook
'llvm-mode-hook
'conf-conf-mode-hook 'conf-ts-mode-hook
'nim-mode-hook
'typescript-mode-hook 'typescript-ts-mode-hook
'js-ts-mode-hook 'json-ts-mode-hook
))
(add-hook hook #'(lambda () (fingertip-mode 1))))
;; (general-def
;; :keymaps 'fingertip-mode-map
;; "(" 'fingertip-open-round
;; "[" 'fingertip-open-bracket
;; "{" 'fingertip-open-curly
;; ")" 'fingertip-close-round
;; "]" 'fingertip-close-bracket
;; "}" 'fingertip-close-curly
;; "=" 'fingertip-equal
;; "%" 'fingertip-match-paren
;; "\"" 'fingertip-double-quote
;; "'" 'fingertip-single-quote
;; "SPC" 'fingertip-space
;; "RET" 'fingertip-newline
;; "M-o" 'fingertip-backward-delete
;; "C-d" 'fingertip-forward-delete
;; "C-k" 'fingertip-kill
;; "M-\"" 'fingertip-wrap-double-quote
;; "M-'" 'fingertip-wrap-single-quote
;; "M-[" 'fingertip-wrap-bracket
;; "M-{" 'fingertip-wrap-curly
;; "M-(" 'fingertip-wrap-round
;; "M-)" 'fingertip-unwrap
;; "M-p" 'fingertip-jump-right
;; "M-n" 'fingertip-jump-left
;; ;"M-:" 'fingertip-jump-out-pair-and-newline
;; "C-j" 'fingertip-jump-up )
)
Treesitter-context utilize emacs built-in treesit to show code context.
(use-package treesitter-context
:config
(add-hook 'python-ts-mode-hook #'treesitter-context-mode)
)
M-x treesit-install-language-grammar
and select the language. This will clone the language’s tree-sitter repo and build it (requires system cc
).
(use-package treesit
:commands (treesit-install-language-grammar
config/treesit-install-all-languages)
:init
(setq treesit-language-source-alist
'((bash . ("https://github.com/tree-sitter/tree-sitter-bash"))
(c . ("https://github.com/tree-sitter/tree-sitter-c"))
(cpp . ("https://github.com/tree-sitter/tree-sitter-cpp"))
(css . ("https://github.com/tree-sitter/tree-sitter-css"))
(cmake . ("https://github.com/uyha/tree-sitter-cmake"))
(common-lisp . ("https://github.com/theHamsta/tree-sitter-commonlisp"))
(csharp . ("https://github.com/tree-sitter/tree-sitter-c-sharp.git"))
(dockerfile . ("https://github.com/camdencheek/tree-sitter-dockerfile"))
(elisp . ("https://github.com/Wilfred/tree-sitter-elisp"))
(go . ("https://github.com/tree-sitter/tree-sitter-go"))
(gomod . ("https://github.com/camdencheek/tree-sitter-go-mod.git"))
(html . ("https://github.com/tree-sitter/tree-sitter-html"))
(java . ("https://github.com/tree-sitter/tree-sitter-java.git"))
(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript"))
(json . ("https://github.com/tree-sitter/tree-sitter-json"))
(lua . ("https://github.com/Azganoth/tree-sitter-lua"))
(make . ("https://github.com/alemuller/tree-sitter-make"))
(markdown . ("https://github.com/MDeiml/tree-sitter-markdown" nil
"tree-sitter-markdown/src"))
(nix . ("https://github.com/nix-community/tree-sitter-nix.git"))
(ocaml . ("https://github.com/tree-sitter/tree-sitter-ocaml" nil "ocaml/src"))
(org . ("https://github.com/milisims/tree-sitter-org"))
(python . ("https://github.com/tree-sitter/tree-sitter-python"))
(php . ("https://github.com/tree-sitter/tree-sitter-php"))
(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" nil
"typescript/src"))
(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" nil
"tsx/src"))
(ruby . ("https://github.com/tree-sitter/tree-sitter-ruby"))
(rust . ("https://github.com/tree-sitter/tree-sitter-rust"))
(sql . ("https://github.com/m-novikov/tree-sitter-sql"))
(vue . ("https://github.com/merico-dev/tree-sitter-vue"))
(yaml . ("https://github.com/ikatyang/tree-sitter-yaml"))
(toml . ("https://github.com/tree-sitter/tree-sitter-toml"))
(zig . ("https://github.com/GrayJack/tree-sitter-zig"))))
:config
(defun config/treesit-install-all-languages ()
"Install all languages specified by `treesit-language-source-alist'."
(interactive)
(let ((languages (mapcar 'car treesit-language-source-alist)))
(dolist (lang languages)
(treesit-install-language-grammar lang)
(message "`%s' parser was installed." lang)
(sit-for 0.75)))))
;; stolen from lazycat
(setq major-mode-remap-alist
'((c-mode . c-ts-mode)
(c++-mode . c++-ts-mode)
(cmake-mode . cmake-ts-mode)
(conf-toml-mode . toml-ts-mode)
(css-mode . css-ts-mode)
(js-mode . js-ts-mode)
(js-json-mode . json-ts-mode)
(nix-mode . nix-ts-mode)
(python-mode . python-ts-mode)
(sh-mode . bash-ts-mode)
(typescript-mode . typescript-ts-mode)
(rust-mode . rust-ts-mode)
))
;; (advice-add 'org-src-get-lang-mode :filter-return #'my/remap-mode)
(add-hook 'markdown-mode-hook #'(lambda ()
(treesit-parser-create 'markdown)))
(add-hook 'web-mode-hook #'(lambda ()
(let ((file-name (buffer-file-name)))
(when file-name
(treesit-parser-create
(pcase (file-name-extension file-name)
("vue" 'vue)
("html" 'html)
("php" 'php))))
)))
(add-hook 'emacs-lisp-mode-hook #'(lambda () (treesit-parser-create 'elisp)))
(add-hook 'ielm-mode-hook #'(lambda () (treesit-parser-create 'elisp)))
(add-hook 'json-mode-hook #'(lambda () (treesit-parser-create 'json)))
(add-hook 'go-mode-hook #'(lambda () (treesit-parser-create 'go)))
(add-hook 'java-mode-hook #'(lambda () (treesit-parser-create 'java)))
(add-hook 'java-ts-mode-hook #'(lambda () (treesit-parser-create 'java)))
(add-hook 'php-mode-hook #'(lambda () (treesit-parser-create 'php)))
(add-hook 'php-ts-mode-hook #'(lambda () (treesit-parser-create 'php)))
(use-package auto-save
:after lsp-bridge
:config
(auto-save-enable)
(setq auto-save-silent t) ; quietly save
(setq auto-save-delete-trailing-whitespace t)
)
(use-package vlf-setup
:config
(setq-default vlf-application 'dont-ask)
)
(use-package outli
:hook ((prog-mode text-mode) . outli-mode))
Envrc provides support for direnv that is buffer-local.
(use-package envrc
:config
(envrc-global-mode)
)
- buttercup
- elisp-def
- elisp-demos
- highlight-quoted
- macrostep
- oversee
(setq-default lexical-binding t)
(use-package highlight-quoted)
(use-package lisp-mode
:mode "\\.yuck\\'"
)
(use-package auctex)
AucTex needs some tweaks to be built.
To build auctex, autoconf
should be avaliable on your system.
[submodule "auctex"]
load-path = .
build-step = ./autogen.sh
build-step = ./configure --with-lispdir="$HOME"/.emacs.d/lib/auctex --with-texmf-dir="$HOME"/texmf
build-step = make
build-step = make doc
build-step = borg-maketexi
build-step = borg-makeinfo
build-step = borg-update-autoloads
(use-package cdlatex)
LASS (LaTeX Auto Activating Snippets) is a chunky set of LaTeX snippets for the auto-activating-snippets engine.
(use-package laas
:after ass
:hook (LaTeX-mode . laas-mode))
(use-package markdown-mode
:config
(dotimes (i 6)
(set-face-attribute (intern (format "markdown-header-face-%d" (1+ i)))
nil
:inherit
(intern (format "outline-%d" (1+ i)))))
)
(use-package nix-mode
:mode "\\.nix\\'"
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((nix . t))
)
)
(use-package nix-ts-mode
:mode "\\.nix\\'"
)
(use-package plantuml-mode
:mode "\\.plantuml\\'"
)
(use-package jupyter
;; :defer t
:config
(org-babel-do-load-languages
'org-babel-load-languages
(append org-babel-load-languages
'((jupyter . t)))))
(use-package rust-ts-mode
:mode "\\.rs\\'"
)
Rusty object notation mode
(use-package ron-mode
:mode "\\.ron\\'"
)
(use-package verilog-mode
:mode "\\.v\\'"
)
(use-package yaml-mode
:mode "\\.yaml\\'"
)
(use-package org
:after emacs
:init
(setq org-element-cache-persistent nil)
(setq org-element-use-cache nil)
(setq org-latex-preview-numbered t)
:config
(add-hook 'org-mode-hook #'olivetti-mode)
;(add-hook 'org-mode-hook #'org-visual-indent-mode)
(add-hook 'org-mode-hook #'turn-on-org-cdlatex)
)
All the .el files are placed in the ./lisp/ folder. According to the installation manual of org, we need to make autoloads before compile.
[submodule "org"]
load-path = lisp
build-step = make autoloads
build-step = borg-update-autoloads
build-step = borg-compile
build-step = borg-maketexi
build-step = borg-makeinfo
Change the font size of different org-levels.
(use-package org
:custom-face
;; (org-latex-and-related ((t (:foreground "LightSteelBlue4" :weight bold))))
;; (org-meta-line ((t (:foreground "LightSteelBlue4"))))
;; (org-special-keyword ((t (:foreground "LightSteelBlue4"))))
;; (org-tag ((t (:foreground "LightSteelBlue4" :weight normal))))
:hook (org-mode . (lambda () (face-remap-add-relative 'default 'variable-pitch)))
:config
(set-face-attribute 'outline-1 nil :height 1.8 )
(set-face-attribute 'outline-2 nil :height 1.6 )
(set-face-attribute 'outline-3 nil :height 1.4 )
(set-face-attribute 'outline-4 nil :height 1.3 )
(set-face-attribute 'outline-5 nil :height 1.2 )
(set-face-attribute 'outline-6 nil :height 1.1 )
(set-face-attribute 'org-document-title nil :height 2.5 :bold t)
(set-face-attribute 'org-document-info nil :height 1.8 :bold t)
(set-face-attribute 'org-document-info-keyword nil
:inherit 'org-document-info)
(set-face-attribute 'org-block nil
:extend t :inherit 'fixed-pitch)
(set-face-attribute 'org-block-begin-line nil
:background (face-background 'default) :height 0.9 :inherit nil)
)
Org-modern implements a modern style for Org buffers using font locking and text properties. The package styles headlines
, keywords
, tables
and source blocks
.
(use-package org-modern
;;:hook (org-mode . org-modern-mode)
:config
(setq org-modern-keyword
'(("author" . "◇")
("title" . "◈")
("subtitle" . "◉")
("html" . " ")
("results" . "results")
(t . t)))
(setq org-modern-star
nil
;; '("" "" "" "" "" "")
;; '("" "" "" "" "" "")
)
;; (set-face-attribute 'org-modern-symbol nil :family "Noto Sans Symbols 2")
(setq org-modern-list ;; for '+' '-' '*' respectively
'((43 . "◆") (45 . "▶ ") (42 . "★")))
(setq org-modern-block-fringe nil)
(setq org-modern-todo nil)
(setq org-modern-timestamp nil)
(setq org-modern-priority nil)
;; (setq org-modern-block-name )
(setq org-modern-block-name
'("" . "")
;; '(" " . " ")
;; '("" . "")
;; '("" . "")
;; '(" " . " ") ; nf-md-square
)
(set-face-attribute 'org-modern-block-name nil
:inherit 'variable-pitch)
(set-face-attribute 'org-meta-line nil
:height 0.9)
(set-face-attribute 'org-modern-horizontal-rule nil
:strike-through (face-foreground 'org-meta-line) :inherit 'org-hide)
(setq org-modern-table nil)
(global-org-modern-mode)
)
Org-superstar replaces the asterisk before every org-level with ascii symbols. Disabled because org-morden is a drop-in replacement.
(use-package org-superstar
:defer t
;:hook (org-mode . org-superstar-mode)
:init
(setq
;;org-superstar-headline-bullets-list '("" "" "" "" "" "")
org-superstar-special-todo-items t
;;org-ellipsis " "
)
)
global svg tag mode will not work will dashboard image banner.
(use-package svg-tag-mode
;; :hook (org-mode . svg-tag-mode)
:config
(setq svg-tag-tags
(append svg-tag-tags
'(;; (":\\([A-Za-z0-9]+\\)" .
;; ((lambda (tag)
;; (if (not (or (org-at-table-p) (org-in-src-block-p)))
;; (svg-tag-make tag)))))
("\\[#A\\]" .
((lambda (tag)
(svg-tag-make tag
:face '(:foreground "IndianRed" :weight bold)
:inverse t))))
("\\[#B\\]" .
((lambda (tag)
(svg-tag-make tag
:face '(:foreground "DarkOrange" :weight bold)
:inverse t))))
("\\[#C\\]" .
((lambda (tag)
(svg-tag-make tag
:face '(:foreground "Grey" :weight bold)
:inverse t)))))))
)
- Org-dynamic-bullets
- handles the dynamic bullets.
- Org-visual-indent
- adds vertical lines to org-indent.
Does better than Org-bars-mode
, as it do not need to set bar’s height.
(use-package org-visual-outline
;; :custom-face
;; (org-visual-indent-blank-pipe-face ((t
;; (:background "#1f2430" :foreground "#1f2430"
;; :height 0.1 :width extra-expanded))))
;; (org-visual-indent-pipe-face ((t
;; (:background "#454d6d" :foreground "#454d6d"
;; :height 0.1 :width extra-expanded))))
:hook (org-mode . org-visual-indent-mode)
(org-mode . org-dynamic-bullets-mode)
:after org
)
This package provides visual alignment for Org Mode, Markdown and table.el tables on GUI Emacs. It can properly align tables containing variable-pitch font, CJK characters and images. Meanwhile, the text-based alignment generated by Org mode (or Markdown mode) is left untouched.
(use-package valign
:hook (org-mode . valign-mode)
:config
(setq valign-fancy-bar t)
)
(use-package hl-todo
:init
(hl-todo-mode)
)
(use-package org-appear
:hook (org-mode . org-appear-mode)
:init
(setq org-appear-autoemphasis t
;; org-appear-autolinks t
org-appear-autosubmarkers t
org-appear-autoentities t
org-appear-autokeywords t
;; org-appear-inside-latex t
org-hide-emphasis-markers t
)
)
(use-package org-popup-posframe
:config
(setq org-popup-posframe-border-width 3)
(setq org-popup-posframe-font "IBM Plex Mono-15")
(setq org-popup-posframe-parameters
'((left-fringe . 20)
(right-fringe . 20)))
(setq org-popup-posframe-org-todo-poshandler
'posframe-poshandler-point-1)
(org-popup-posframe-mode)
)
(setq org-return-follows-link t)
(my/mode-leader-def
:prefix-command 'my/org-cmd
:prefix-map 'my/org-map
:keymaps '(org-mode-map)
"" '(nil :wk "org-mode")
"a" '(org-attach :wk "attach")
"b" '(nil :wk "Babel")
"c" '(org-ctrl-c-ctrl-c :wk "execute")
"d" '(org-deadline :wk "deadline")
"e" '(org-edit-special :wk "edit")
"f" '(org-fold-reveal :wk "reveal")
"g" '(org-goto :wk "goto")
;; "h" '( :wk "")
;; "i" '( :wk "")
"i" '(org-insert-structure-template :wk "structure")
;; "j" '( :wk "")
;; "k" '( :wk "")
"l" '(org-insert-link :wk "link")
"m" '(org-toggle-inline-images :wk "toggle image")
;; "n" '( :wk "")
"o" '(org-export-dispatch :wk "export")
"p" '(org-priority :wk "priority")
;; "q" '( :wk "")
"r" '(org-refile :wk "refile")
"s" '(org-schedule :wk "schedule")
"t" '(org-todo :wk "todo")
;; "u" '(nil :wk "")
"v" '(org-download-clipboard :wk "paste image")
"w" '(org-refile :wk "refile")
"x" '(nil :wk "latex")
"y" '(org-evaluate-time-range :wk "time range")
;; "z" '(nil :wk "")
"C-j" '(my/outline-left :wk "dwim ")
"C-k" '(my/outline-up :wk "dwim ")
"C-l" '(my/outline-down :wk "dwim ")
"C-;" '(my/outline-right :wk "dwim ")
)
(my/mode-leader-def
:keymaps '(org-mode-map)
:infix "b"
"t" '(org-babel-tangle :wk "tangle")
"d" '(org-babel-demarcate-block :wk "demarcate")
)
(my/mode-leader-def
:keymaps '(org-mode-map)
:infix "x"
"c" '(org-latex-preview-clear-cache :wk "clear")
"p" '(org-latex-preview :wk "preview")
"a" '(org-latex-preview-auto-mode :wk "auto")
"r" '(my/org-latex-preview-reload :wk "reload")
)
(my/mode-leader-def
:keymaps '(org-src-mode-map)
"e" 'org-edit-src-exit
"k" 'org-edit-src-abort
)
(my/mode-leader-def
:keymaps '(org-capture-mode-map)
"c" 'org-capture-finalize
"w" 'org-capture-refile
"k" 'org-capture-kill
)
(defvar my/recenter 6)
(defun my/outline-left ()
(interactive)
(cond ((outline-on-heading-p)
(hide-subtree)
(outline-up-heading 1)
(hide-subtree)
(outline-show-children)
(outline-show-entry))
(t
(outline-back-to-heading)
))
(recenter my/recenter)
)
(defun my/outline-up ()
(interactive)
(cond ((outline-on-heading-p)
(hide-subtree)
(outline-backward-same-level 1)
(outline-show-children)
(outline-show-entry)
)
(t
(org-previous-block 1)))
(recenter my/recenter)
)
(defun my/outline-down ()
(interactive)
(cond ((outline-on-heading-p)
(hide-subtree)
(outline-forward-same-level 1)
(outline-show-children)
(outline-show-entry)
)
(t
(org-next-block 1)))
(recenter my/recenter))
(defun my/outline-right ()
(interactive)
(outline-show-children)
(outline-show-entry)
(if (outline-has-subheading-p)
(progn (outline-next-heading)
(outline-show-children)
(outline-show-entry)))
(recenter my/recenter))
(use-package org
:init
(setq org-babel-load-languages
'((awk . t)
(shell . t)
(eshell . t)
(emacs-lisp . t)
(lisp . t)
(haskell . t)
(clojure . t)
(scheme . t)
(org . t)
(C . t)
(sql . t)
;; (jupyter . t)
(java . t)
(lua . t)
(js . t)
(dot . t)
(plantuml . t)
(R . t)
(python . t)
(octave . t)
(matlab . t)
(julia . t)))
:config
(setq org-edit-src-content-indentation 0
org-src-tab-acts-natively t
org-src-preserve-indentation nil
org-src-ask-before-returning-to-edit-buffer nil
org-confirm-babel-evaluate nil
org-confirm-elisp-link-function nil
org-link-elisp-confirm-function nil
)
(general-define-key :keymap 'org-src-mode-map
"C-c C-c" 'eval-buffer)
)
Org-auto-tangle Automatically and Asynchronously tangles org files on save.
Adding the option #+auto_tangle: t
in an org file to auto-tangle.
Or setting org-auto-tangle-default
to t to configure auto-tangle as the default behavior for all org buffers. In this case, it can be disabled for some buffers by adding #+auto_tangle: nil
.
(use-package org-auto-tangle
:hook (org-mode . org-auto-tangle-mode)
)
Ob-async enables asynchronous execution of org-babel src blocks. Simply add the keyword :async
to the header-args of any org-babel src block and invoke ob-async-org-babel-execute-src-block
.
(use-package ob-async
:after org
:config
;; below languages may have independent implementation of async
(setq ob-async-no-async-languages-alist '("jupyter-python" "jupyter-julia"))
)
Orgtbl-aggregate can creat a new table by computing sums, averages, and so on, out of material from the first table.
Disable hiding of{}
, _
and ^
, from this post in emacs china.
(use-package org
:config
(defconst org-match-substring-regexp
(concat
"\\(\\S-\\)\\([_^]\\)\\("
"\\(?:" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
"\\|"
"\\(?:" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
"\\|"
"\\(?:.\\)"
"\\|"
"\\(?:\\\\[[:alnum:].,\\]*[[:alnum:]]\\)"
"\\)")
"The regular expression matching a sub- or superscript.")
(defun +org-raise-scripts (limit)
"Add raise properties to sub/superscripts."
(when (and org-pretty-entities org-pretty-entities-include-sub-superscripts
(re-search-forward org-match-substring-regexp limit t))
(let* ((pos (point)) table-p comment-p
(mpos (match-beginning 3))
(emph-p (get-text-property mpos 'org-emphasis))
(link-p (get-text-property mpos 'mouse-face))
(keyw-p (eq 'org-special-keyword (get-text-property mpos 'face)))
(tex-p (eq 'org-latex-and-related (get-text-property mpos 'face))))
(goto-char (line-beginning-position))
(setq table-p (looking-at-p org-table-dataline-regexp)
comment-p (looking-at-p "^[ \t]*#[ +]"))
(goto-char pos)
;; Handle a_b^c
(when (member (char-after) '(?_ ?^)) (goto-char (1- pos)))
(if (not (or comment-p emph-p link-p keyw-p))
(put-text-property (match-beginning 3) (match-end 0)
'display
(if (equal (char-after (match-beginning 2)) ?^)
(nth (if table-p 3 1) org-script-display)
(nth (if table-p 2 0) org-script-display)))
(put-text-property (match-beginning 2) (match-end 3) 'org-emphasis t))
t)))
(advice-add #'org-raise-scripts :override #'+org-raise-scripts)
)
Prettify symbols mode
(use-package org
:hook
(org-mode . (lambda ()
(push '("\\operatorname{\\mathrm{" . (? (Bc . Bl) ?{ (Bc . Br) ?{)) prettify-symbols-alist)
(push '("\\mathcal{" . (? (Bc . Bl) ?{ (Bc . Br) ?𝒞)) prettify-symbols-alist)
(push '("\\mathbb{" . (? (Bc . Bl) ?{ (Bc . Br) ?𝔹)) prettify-symbols-alist)
(push '("\\\\{" . ?{) prettify-symbols-alist)
(push '("\\\\}" . ?}) prettify-symbols-alist)
(push '("\\(" . ?⟨) prettify-symbols-alist)
(push '("\\)" . ?⟩) prettify-symbols-alist)
(push '("\\)," . (? (Bc . Bl) ?, (Bc . Br) ?⟩)) prettify-symbols-alist)
(push '("\\)。" . (? (Bc . Bl) ?。 (Bc . Br) ?⟩)) prettify-symbols-alist)
(push '("\\);" . (? (Bc . Bl) ?; (Bc . Br) ?⟩)) prettify-symbols-alist)
))
)
Org-entities-user
(use-package org
:config
(setq org-entities-user '(
("frac" "\\frac" t "÷" "÷" "÷" "÷")
("sqrt" "\\sqrt" t "√" "√" "√" "√")
("vdash" "\\vdash" t "⊢" "⊢" "⊢" "⊢")
("vDash" "\\vDash" t "⊨" "⊨" "⊨" "⊨")
("Vdash" "\\Vdash" t "⊩" "⊩" "⊩" "⊩")
("Vvdash" "\\Vvdash" t "⊪" "⊪" "⊪" "⊪")
("nvdash" "\\nvdash" t "⊬" "⊬" "⊬" "⊬")
("nvDash" "\\nvDash" t "⊭" "⊭" "⊭" "⊭")
("nVdash" "\\nVdash" t "⊮" "⊮" "⊮" "⊮")
("nVDash" "\\nVDash" t "⊯" "⊯" "⊯" "⊯")
("subseteq" "\\subseteq" t "⊆" "⊆" "⊆" "⊆")
("supseteq" "\\supseteq" t "⊇" "⊇" "⊇" "⊇")
("subsetneq" "\\subsetneq" t "⊊" "⊊" "⊊" "⊊")
("supsetneq" "\\supsetneq" t "⊋" "⊋" "⊋" "⊋")
("nsubseteq" "\\nsubseteq" t "⊈" "⊈" "⊈" "⊈")
("nsupseteq" "\\nsupseteq" t "⊉" "⊉" "⊉" "⊉")
("nsubseteqq" "\\nsubseteqq" t "⊈" "⊈" "⊈" "⊈")
("nsupseteqq" "\\nsupseteqq" t "⊉" "⊉" "⊉" "⊉")
("subsetneqq" "\\subsetneqq" t "⊊" "⊊" "⊊" "⊊")
("supsetneqq" "\\supsetneqq" t "⊋" "⊋" "⊋" "⊋")
("nsubset" "\\nsubset" t "⊄" "⊄" "⊄" "⊄")
("nsupset" "\\nsupset" t "⊅" "⊅" "⊅" "⊅")
("nsubseteq" "\\nsubseteq" t "⊈" "⊈" "⊈" "⊈")
("nsupseteq" "\\nsupseteq" t "⊉" "⊉" "⊉" "⊉")
))
)
Org Latex Preview configs. This makes the preview looks nicer.
(use-package org
:config
(setq org-latex-preview-numbered t)
(plist-put org-latex-preview-options :zoom 1.25)
(let ((pos (assoc 'dvisvgm org-latex-preview-process-alist)))
(plist-put (cdr pos) :image-converter '("dvisvgm --page=1- --optimize --clipjoin --relative --no-fonts --bbox=preview -o %B-%%9p.svg %f")))
(defun my/org-latex-preview-reload ()
(interactive)
(call-interactively 'org-latex-preview-clear-cache)
(org-latex-preview)
)
)
(use-package org-download
:after org
)
(use-package plantuml-mode
:defer t
:mode ("\\.plantuml\\'" . plantuml-mode)
:init
;; enable plantuml babel support
(add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
(org-babel-do-load-languages 'org-babel-load-languages
(append org-babel-load-languages
'((plantuml . t))))
:config
(setq org-plantuml-exec-mode 'plantuml)
(setq org-plantuml-executable-path "plantuml")
(setq plantuml-executable-path "plantuml")
(setq plantuml-default-exec-mode 'executable)
;; set default babel header arguments
(setq org-babel-default-header-args:plantuml
'((:exports . "results")
(:results . "file")
))
)
(use-package org-capture
:after org
:init
(setq org-directory "~/org")
:config
;; if file path is not absolute
;; it is treated as relative path to org-directory
(defun org-hugo-new-subtree-post-capture-template ()
"Returns `org-capture' template string for new Hugo post.
See `org-capture-templates' for more information."
(let* ((title (read-from-minibuffer "Post Title: "))
(fname (org-hugo-slug title)))
(mapconcat #'identity
`(,(concat "* TODO " title) ":PROPERTIES:"
,(concat ":EXPORT_FILE_NAME: " fname) ":END:" "%?\n")
;Place the cursor here finally
"\n")))
(setq org-capture-templates
(append org-capture-templates
'(("i" "Inbox" entry (file+olp "gtd.org" "Inbox")
"* TODO %?\n:ENTERED: %U\n")
("j" "Journal" entry (file+olp+datetree "journal.org")
"* [%<%R>] %?\n")
("l" "Link" entry (file+olp "org-linkz/Linkz.org" "INBOX")
"* %a %U"
:immediate-finish t)
("h" "Hugo post" entry (file+olp "capture.org" "Notes")
(function org-hugo-new-subtree-post-capture-template)))))
(require 'org-protocol)
(setq org-protocol-default-template-key "l")
)
I’m using two plugins that handles backlink. Org-super-links
handles inserting backlinks in current buffer. Org-roam
inserts links and backlinks between different org files.
(use-package org
:config
(defun my/org-add-custom-id ()
"Add CUSTOM_ID property to current heading, skip if already have"
(interactive)
(let ((custom-id (org-entry-get nil "CUSTOM_ID")))
(unless custom-id
(org-set-property "CUSTOM_ID" (org-id-new))))
)
(defun my/org-add-custom-id-to-all-headings ()
"Add CUSTOM_ID properties to headings without a CUSTOM_ID property in current Org buffer."
(interactive)
(org-map-entries
(lambda ()
(let ((custom-id (org-entry-get nil "CUSTOM_ID")))
(unless custom-id
(org-set-property "CUSTOM_ID" (org-id-new)))))
nil 'file)
)
)
org-super-links-link
, it automatically inserts a backlink at the target.
I think this is what makes Org’s tree-style structure more complete. A tree style structure is efficient in dividing a big object into many smaller ones. But it’s possible that two children share something in common, but do not belong to the same parent. In this case backlinks does the job.
(use-package org-super-links
:after org
:config
(defun my/org-insert-backlink ()
"insert backlink using consult-org-heading in current org file"
(interactive)
(let ((target-position
(save-excursion (consult-org-heading) (point) )))
(org-super-links--insert-link
(set-marker (make-marker) target-position)))
(recenter)
)
(setq org-super-links-search-function 'my/org-insert-backlink)
(setq org-super-links-backlink-prefix nil)
)
(use-package org-roam
:after org
:init
(setq org-roam-directory (file-truename "~/roam"))
(org-roam-db-autosync-mode)
(setq org-roam-v2-ack t)
(setq org-roam-capture-templates '(
("d" "default" plain "%?"
:target (file+head
"%<%Y%m%d%H>-${slug}.org"
"#+title: ${title}\n#+filetags: \n")
:unnarrowed t)
("b" "book notes" plain "%?"
:target (file+head
"book/book%<%Y%m%d%H>-${slug}.org"
"#+title: ${title}\n#+filetags: :bookreading: \n\n")
:unnarrowed t)
("c" "coMpany" plain "%?"
:target (file+head
"company/company%<%Y%m%d%H>-${slug}.org"
"#+title: ${title}\n#filetags: :compnay: \n\n")
:unnarrowed t)
("i" "industry" plain "%?"
:target (file+head
"industry/industry%<%Y%m%d%H>-${slug}.org"
"#+title:${slug}\n#+filetags: :industry: \n\n")
:unnarrowed t)
("m" "marketing" plain "%?"
:target (file+head
"marketing/marketing%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n#+filetags: :marketing: \n\n")
:unnarrowed t)
("p" "project" plain "%?"
:target (file+head
"project/project%<%Y%m%d%H>-${slug}.org"
"#+title: ${title}\n#+filetags: :project: \n\n - tag ::")
:unnarrowed t)
("r" "reference" plain "%?"
:target (file+head
"<%Y%m%d%H>-${slug}.org"
"#+title: {$title}\n%filetags: reference \n\n -tag ::")
:unarrowed t)))
)
(use-package org
:config
(setq org-todo-keywords '(
(sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)")
(sequence "WAIT(w@/!)" "HOLD(h@/!)" "|" "CNCL(c@/!)")
(sequence "SOMEDAY")
))
(setq org-todo-state-tags-triggers
'(("CNCL" ("CNCL" . t))
("WAIT" ("WAIT" . t))
("HOLD" ("WAIT") ("HOLD" . t))
(done ("WAIT") ("HOLD"))
("TODO" ("WAIT") ("CNCL") ("HOLD"))
("NEXT" ("WAIT") ("CNCL") ("HOLD"))
("DONE" ("WAIT") ("CNCL") ("HOLD"))))
)
;;selecting keys from the fast todo selection key menu
(setq org-use-fast-todo-selection t
org-enforce-todo-dependencies t
org-log-done 'time
)
(use-package org-agenda
:after org
:hook
(org-agenda-mode . solaire-mode)
(org-agenda-mode . olivetti-mode)
:bind
("<f12>" . org-agenda)
:config
(setq org-agenda-span 'day)
(setq org-agenda-files '("~/Org"))
(let ((org-agenda-custom-commands '(
("u" "Super view" (
(agenda "" (
(org-agenda-span 1)
(org-super-agenda-groups '(
(:name "Today"
:tag ("bday" "ann" "hols" "cal" "today")
:time-grid t
:todo ("WIP")
:deadline today)
(:name "Perso"
:tag "perso")
(:name "Overdue"
:deadline past)
(:name "Reschedule"
:scheduled past)
(:name "Due Soon"
:deadline future)
)))
)
(tags (concat "w" (format-time-string "%V"))
( (org-agenda-overriding-header
(concat "ToDos Week " (format-time-string "%V")))
(org-super-agenda-groups '(
(:discard (:deadline t))
(:name "Perso" :tag "perso")
(:name "Loka" :tag "loka")
(:name "Ping" :tag "ping")
))
)
)
)))))
(org-agenda nil "u"))
)
(use-package org-super-agenda
:after org-agenda
:config
(org-super-agenda-mode)
(setq org-super-agenda-groups '(
(:name "Today"
:time-grid t
:scheduled today)
(:name "Due today"
:deadline today)
(:name "Important"
:priority "A")
(:name "Overdue"
:deadline past)
(:name "Due soon"
:deadline future)
(:name "Waiting"
:todo "WAIT")
(:name "Someday"
:todo "SOMEDAY")
))
)
(use-package calendar
:hook
(calendar-mode . olivetti-mode)
(calendar-mode . solaire-mode)
:config
(setq calendar-date-style 'iso)
)
Copied from https://lists.gnu.org/archive/html/emacs-orgmode/2020-11/msg00361.html
(use-package org
:config
(defun my/org-archive-without-delete ()
"Archive item at point, but do not actually delete it."
(cl-letf (((symbol-function 'org-cut-subtree) (lambda () nil)))
(org-archive-subtree)))
(defun org-archive-repeated-task (arg)
"Add a copy of the recurring task marked DONE to archive."
(when (and (eq (plist-get arg :type) 'todo-state-change)
(string= (plist-get arg :to) "DONE")) ;; The state is changed to DONE
(let* ((pos (plist-get arg :position))
(repeater (org-with-point-at pos (org-get-repeat))))
(when repeater ;; Only consider tasks with repeater timestamp anywhere in the task body
(my/org-archive-without-delete)))))
(add-hook 'org-trigger-hook #'org-archive-repeated-task)
)
(use-package ox
:after org
:defer t
:config
(setq
org-export-with-toc t
org-export-with-tags 'not-in-toc
org-export-with-drawers nil
org-export-with-priority t
org-export-with-footnotes t
org-export-with-smart-quotes t
org-export-with-section-numbers t
org-export-with-sub-superscripts '{}
org-export-use-babel t
org-export-headline-levels 9
org-export-coding-system 'utf-8
org-export-with-broken-links 'mark
)
)
(use-package ox-html
:defer t
:after ox
:config
(setq org-html-doctype "html5"
org-html-html5-fancy t
org-html-checkbox-type 'unicode
org-html-validation-link nil))
(use-package htmlize
:defer t
:config
(setq htmlize-pre-style t
htmlize-output-type 'inline-css))
(use-package grip-mode
:after org
)
- ox-html, then export to pdf via browser.
- ox-latex
- ox-pandoc
(use-package ox-latex
:defer t
:after ox
:config
;; use xelatex
(setq org-latex-pdf-process '("xelatex -file-line-error -interaction nonstopmode %f"
"bibtex %b"
"xelatex -file-line-error -interaction nonstopmode %f"
"xelatex -file-line-error -interaction nonstopmode %f"))
;; clear files after generating PDF
;; https://answer-id.com/53623039
(setq org-latex-logfiles-extensions
(quote ("lof" "lot" "tex~" "tex" "aux"
"idx" "log" "out" "toc" "nav"
"snm" "vrb" "dvi" "fdb_latexmk"
"blg" "brf" "fls" "entoc" "ps"
"spl" "bbl" "xdv")))
(setq org-image-actual-width nil)
(setq org-export-with-sub-superscripts nil)
;;
(setq make-backup-files nil)
(setq org-latex-listings t)
(add-to-list
'org-latex-classes
'("elegantpaper"
"\\documentclass[lang=cn]{elegantpaper}
[NO-DEFAULT-PACKAGES]
[PACKAGES]
[EXTRA]"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
)
(use-package ox-ipynb
:defer t
:after ox
)
git clone https://github.com/hakimel/reveal.js.git
cd reveal.js && npm install
(use-package ox-reveal
:defer t
:after ox
:config
(setq org-reveal-hlevel 1
org-reveal-theme "moon"
org-reveal-mathjax t
org-reveal-ignore-speaker-notes t
org-reveal-title-slide "<h1><font size=\"8\">%t</font></h1><h2><font size=\"6\">%s</font></h2><p><font size=\"5\">%a</font><br/><font size=\"5\">%d</font></p>"
org-reveal-plugins '(markdown zoom notes search)
org-reveal-klipsify-src 'on))
(use-package ox-gfm
:defer t
:after ox
)
(use-package ox-pandoc
:defer t
:after ox
:config
(setq org-pandoc-format-extensions
'(markdown_github+pipe_tables+raw_html)
)
)
(use-package ox-publish
:defer t
)
- create a org mode heading
- write your blog
- use ox-hugo to export to a markdown file (Because hugo doesn’t support org very well)
- use easy-hugo to preview
- publish
ox-hugo is an Org exporter backend that exports Org to Hugo-compatible Markdown and also generates the front-matter (in TOML or YAML format).
(use-package ox-hugo
:after ox
:commands (org-hugo-export-as-md org-hugo-export-to-md)
:init
(setq org-hugo-base-dir "~/Blog"
org-hugo-front-matter-format "yaml"
)
)
Easy-hugo
(use-package easy-hugo
:defer t
)
(use-package telega
:defer t
:hook (telega-chat-mode .
(lambda ()
(visual-fill-column-mode 0)
(config/window-center 102)
(solaire-mode -1)
))
:init
(setq telega-server-libs-prefix "~/.nix-profile")
(setq telega-avatar-workaround-gaps-for '(return t)) ;; solves broken avatar
(setq telega-emoji-use-images nil) ;; or emoji will look monochrome and broken
(setq ;; telega-root
;; telega-root-default-view-function 'telega-view-folders
telega-root-keep-cursor 'track
telega-root-buffer-name "*Telega Root*"
telega-root-fill-column 70 ; fill-column
telega-symbol-folder " ")
(setq telega-symbol-forum (nerd-icons-mdicon "nf-md-format_list_text"))
(setq telega-brackets
`(((chat (type private))
,(concat " "
(nerd-icons-mdicon "nf-md-account"
:face '(:foreground "#86dffd" :height 0.7))
" ") " ")
((chat (type bot))
,(concat " "
(nerd-icons-mdicon "nf-md-robot"
:face '(:foreground "#86dffd" :height 0.7))
" ") " ")
((chat (type basicgroup))
,(concat " "
(nerd-icons-mdicon "nf-md-account_multiple"
:face '(:foreground "#70bcff" :height 0.7))
" ") " ")
((chat (type supergroup))
,(concat " "
(nerd-icons-mdicon "nf-md-account_multiple"
:face '(:foreground "#70bcff" :height 0.7))
" ") " ")
((chat (type channel))
,(concat " "
(nerd-icons-faicon "nf-fa-feed"
:face '(:foreground "#ffa95f" :height 0.7))
" ") " ")
((user (return t))
,(concat " "
(nerd-icons-mdicon "nf-md-account"
:face '(:foreground "#86dffd" :height 0.7))
" ") " ")
((return t)
,(concat " "
(nerd-icons-faicon "nf-fa-question_circle"
:face '(:foreground "#ff0000" :height 0.7))
" ") " "))
)
(general-def
:keymaps '(telega-msg-button-map)
"SPC" nil
"l" nil
"C" 'telega-msg-copy-link
)
)
[submodule "telega"]
;; build-nix-shell-packages = tdlib
build-step = make server
build-step = make autoloads
build-step = borg-update-autoloads
build-step = borg-compile
build-step = borg-maketexi
build-step = borg-makeinfo
Elfeed is emacs’s built-in rss reader.
The following config adds nerd icons, copied from Emacs China.
(use-package elfeed
:defer t
:hook
(elfeed-search-mode .
(lambda () (config/window-center 110) (solaire-mode -1)))
(elfeed-show-mode .
(lambda () (config/window-center 114) (solaire-mode -1)))
:config
(defun nerd-icon-for-tags (tags)
"Generate Nerd Font icon based on tags.
Returns default if no match."
(cond
((member "youtube" tags)
(nerd-icons-faicon "nf-fa-youtube_play" :face '(:foreground "#FF0200")))
((member "instagram" tags)
(nerd-icons-faicon "nf-fa-instagram" :face '(:foreground "#FF00B9")))
((member "emacs" tags)
(nerd-icons-sucicon "nf-custom-emacs" :face '(:foreground "#9A5BBE")))
((member "github" tags)
(nerd-icons-faicon "nf-fa-github"))
((member "zhihu" tags)
(nerd-icons-mdicon "nf-md-alpha_z_box" :face '(:foreground "#1772F6")))
((member "bilibili" tags)
(nerd-icons-mdicon "nf-md-alpha_b_box" :face '(:foreground "#FB7299")))
(t
(nerd-icons-faicon "nf-fae-feedly" :face '(:foreground "#2AB24C")))))
(defun my/elfeed-search-print-entry--better-default (entry)
"Print ENTRY to the buffer."
(let* ((date (elfeed-search-format-date (elfeed-entry-date entry)))
(date-width (car (cdr elfeed-search-date-format)))
(title (concat (or (elfeed-meta entry :title)
(elfeed-entry-title entry) "")
;; NOTE: insert " " for overlay to swallow
" "))
(title-faces (elfeed-search--faces (elfeed-entry-tags entry)))
(feed (elfeed-entry-feed entry))
(feed-title (when feed (or (elfeed-meta feed :title) (elfeed-feed-title feed))))
(tags (mapcar #'symbol-name (delq 'unread (elfeed-entry-tags entry))))
(tags-str (mapconcat (lambda (s) (propertize s 'face 'elfeed-search-tag-face)) tags ","))
(title-width (- (frame-width)
;; (window-width (get-buffer-window (elfeed-search-buffer) t))
date-width elfeed-search-trailing-width))
(title-column (elfeed-format-column
title (elfeed-clamp
elfeed-search-title-min-width
title-width
elfeed-search-title-max-width) :left))
;; Title/Feed ALIGNMENT
(align-to-feed-pixel (+ 2 date-width
(max elfeed-search-title-min-width
(min title-width elfeed-search-title-max-width)))))
(insert (propertize date 'face 'elfeed-search-date-face) " ")
(insert (propertize title-column 'face title-faces 'kbd-help title))
(put-text-property (1- (point)) (point) 'display `(space :align-to ,align-to-feed-pixel))
;; (when feed-title (insert " " (propertize feed-title 'face 'elfeed-search-feed-face) " "))
(when feed-title
(insert " " (concat (nerd-icon-for-tags tags) " ")
(propertize feed-title 'face 'elfeed-search-feed-face) " "))
(when tags (insert "(" tags-str ")"))))
(setq elfeed-search-print-entry-function
#'my/elfeed-search-print-entry--better-default)
)
(use-package elfeed-org
:after elfeed
:init
(setq rmh-elfeed-org-files (list "~/.emacs.d/elfeed.org"))
(elfeed-org)
)
M-x pdf-tools-install
to install libraries needed.
pdf-view-midnight-colors
are set by doom-themes
(use-package pdf-tools
;; manually update
;; after each update we have to call:
;; Install pdf-tools but don't ask or raise error (otherwise daemon mode will wait for input)
;; (pdf-tools-install t t t)
:magic ("%PDF" . pdf-view-mode)
:mode (("\\.pdf\\'" . pdf-view-mode))
:hook ((pdf-view-mode . pdf-view-init))
:bind (:map pdf-view-mode-map
("C-s" . isearch-forward)
("M-w" . pdf-view-kill-ring-save)
("M-p" . print-pdf))
:config
(defun pdf-view-init ()
"Initialize pdf-tools view like enabline TOC functions or use dark theme at night."
;; Use dark theme when opening PDFs at night time
(let ((hour (string-to-number (format-time-string "%H"))))
(when (or (< hour 5) (< 20 hour))
(pdf-view-midnight-minor-mode)))
;; Enable pdf-tools minor mode to have features like TOC extraction by pressing `o'.
(pdf-tools-enable-minor-modes)
;; Disable while-line-or-region to free keybindings.
(whole-line-or-region-local-mode -1))
;; Use `gtklp' or `hp-print' to print as it has better cups support
(setq print-pdf-command "hp-print")
(defun print-pdf (&optional pdf)
"Print PDF using external program defined in `print-pdf-command'."
(interactive "P")
(start-process-shell-command
print-pdf-command nil (concat print-pdf-command " " (shell-quote-argument (or pdf (buffer-file-name))))))
;; more fine-grained zooming; +/- 10% instead of default 25%
(setq pdf-view-resize-factor 1.1)
)
nov.el provides a major mode for reading EPUB documents.
(use-package nov
:defer t)
[submodule "mu4e"]
build-step = ./autogen.sh
build-step = make -C mu4e > /dev/null
build-step = borg-update-autoloads
load-path = build/mu4e
EAF is an extensible framework that revolutionizes the graphical capabilities of Emacs.
(use-package eaf
:disabled
:custom
; See https://github.com/emacs-eaf/emacs-application-framework/wiki/Customization
(eaf-browser-continue-where-left-off t)
(eaf-browser-enable-adblocker t)
(browse-url-browser-function 'eaf-open-browser)
:config
(defalias 'browse-web #'eaf-open-browser)
;; (eaf-bind-key scroll_up "C-n" eaf-pdf-viewer-keybinding)
;; (eaf-bind-key scroll_down "C-p" eaf-pdf-viewer-keybinding)
;; (eaf-bind-key take_photo "p" eaf-camera-keybinding)
;; (eaf-bind-key nil "M-q" eaf-browser-keybinding)
(setq confirm-kill-processes nil)
) ;; unbind, see more in the Wiki
;(use-package eaf-browser)
;(use-package eaf-pdf-viewer)
tweaks to build eaf
[submodule "eaf"]
load-path = .
load-path = core
load-path = extension
(add-hook 'tetris-mode-hook (lambda () (config/window-center 76)))
(add-hook '2048-mode-hook (lambda () (config/window-center 35)))
(progn ; startup
(message "Loading %s...done (%fs)" user-init-file
(float-time (time-subtract (current-time)
before-user-init-time)))
(add-hook 'after-init-hook
(lambda ()
(message
"Loading %s...done (%fs) [after-init]" user-init-file
(float-time (time-subtract (current-time)
before-user-init-time))))
t))
(progn ; personalize
(let ((file (expand-file-name (concat (user-real-login-name) ".el")
user-emacs-directory)))
(when (file-exists-p file)
(load file))))
;; Local Variables:
;; indent-tabs-mode: nil
;; End:
;;; init.el ends here
*