Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/A7R7/EmaxBound

Let's explore the bound of emacs :D
https://github.com/A7R7/EmaxBound

Last synced: 7 days ago
JSON representation

Let's explore the bound of emacs :D

Awesome Lists containing this project

README

        

:DOC-CONFIG:

# for all elisp codes, if not explicitly set rules, they're tangled to init.el, with comments style noweb (in order to do org-babel-detangle), and when C-c C-c, they're evaled without output.
#+PROPERTY: header-args:elisp :tangle init.el :comments link :results silent
#+PROPERTY: header-args:emacs-lisp :tangle init.el :comments link :results silent

# for all conf codes, they're tangled to .borgconfig
#+PROPERTY: header-args:conf :tangle .borgconfig :language conf

#+STARTUP: fold

# this org file tangle on save
#+AUTO_TANGLE: t

# Hugo stuffs
#+HUGO_BUNDLE: emaxbound-configuration
#+EXPORT_FILE_NAME: index.en
#+HUGO_PUBLISHDATE: 2023-07-24
#+HUGO_FRONT_MATTER_KEY_REPLACE: author>authors
#+HUGO_CUSTOM_FRONT_MATTER: :featuredImage Emacsbound.png
#+FILETAGS: :Emacs:Org-mode:

:END:

#+TITLE: EmaxBound Configuration
#+AUTHOR: A7R7

#+DESCRIPTION: My GNU Emacs's literate config
#+HTML:
-----
#+HTML:GNU Emacs
#+HTML:Package Manager
#+HTML:Linux

[[file:assets/dashboard.png]]

* Introduction
:PROPERTIES:
:CUSTOM_ID: f3aacf74-1f96-4b4f-932c-60805a632437
:END:

** How to deploy this config
:PROPERTIES:
:CUSTOM_ID: 5e6cc345-e6c5-4652-9041-7ba1d6eb58b8
:END:
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.
#+begin_src bash
git clone --depth=1 https://github.com/A7R7/EmaxBound.git
#+end_src

Then, simply execute these make rules inside the repo directory.
#+begin_src bash
make bootstrap-borg # bootstrap borg itself
make bootstrap # bootstrap collective or new drones
#+end_src

Last, run ~emacs --init-directory=~ (replace the path).

** How I built this config from the seed
:PROPERTIES:
:CUSTOM_ID: f2cf02e1-4051-403d-8b43-9465c0ffc346
:END:

The whole config structure is built upon [[https://github.com/emacscollective/emacs.g][emacscollective/emacs.g]].
It is a starter-kit using borg as the package manager, which utilizes git submodules to maintain all its packages.
Check [[https://emacsmirror.net/manual/borg/Bootstrapping-using-a-seed.html][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 [[elisp: borg-assimilate][M-x borg-assimilate]] and input the name of the package to install this package.
- Write config codes into this org file, then run [[elisp:org-babel-tangle][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.

** Why it's called EmaxBound
:PROPERTIES:
:CUSTOM_ID: 57396c12-74f2-41c4-9b65-2bc866a305d6
:END:

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"

** Why not other popular emacs distros
:PROPERTIES:
:CUSTOM_ID: d4ab13f2-c03e-4da6-904c-26e9111e11a4
:END:

+ 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?

** Why a literate config
:PROPERTIES:
:CUSTOM_ID: 00a4f4b9-289a-4a01-b5f8-fffdefb5bebe
:END:

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.

** References
:PROPERTIES:
:CUSTOM_ID: f7569389-72f0-4580-b532-f330a9f511df
:END:

Credits goes to the authors of those emacs configs that I referenced during the build-up of my emacs config file.

- [[https://github.com/lccambiaghi/vanilla-emacs][Luca's vanilla-emacs]] (2023) detailed org config file.
- [[https://gitlab.com/dwt1/configuring-emacs][DistroTube's Configuring Emacs]] (2023) easy to follow.
- [[https://github.com/seagle0128/.emacs.d][seagle0128's Centaur Emacs]] (2023) be morden.
- [[https://github.com/daviwil/emacs-from-scratch][Daviwell's Emacs from scratch]] (2021) intuitive.
- [[https://github.com/doomemacs/doomemacs][Doom Emacs]] (2023) Some best practices.
- [[https://github.com/dakra/dmacs][Dakra's Dmacs]] (2023) Another Emacs Literate configuration with borg
- [[https://github.com/DogLooksGood/meomacs][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)

* Early Init
:PROPERTIES:
:header-args:elisp: :tangle early-init.el :language elisp :comments link
:CUSTOM_ID: b343e4f2-36db-4558-8e69-3bb52bcb5190
:END:
:BACKLINKS:
[[*Transparency][Transparency]]
:END:

*NOTE*: 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 [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html][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.
#+begin_src elisp
;;; -*- lexical-binding: t; no-byte-compile: t -*-
#+end_src

Defer garbage collection in the startup process.
#+begin_src elisp
(setq gc-cons-threshold most-positive-fixnum)
;; copied from lazycat
(setq gc-cons-percentage 0.6)
#+end_src

Prevent unwanted runtime compilation for native-comp.
#+begin_src elisp
(setq native-comp-deferred-compilation nil ;; obsolete since 29.1
native-comp-jit-compilation nil)
#+end_src

Disable tool-bar, menu-bar and scroll-bar before they're loaded.
#+begin_src elisp
(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)
#+end_src

Smooth window on startup
#+begin_src elisp
(setq frame-inhibit-implied-resize t)
#+end_src

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.
#+begin_src elisp
;; (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))
#+end_src

Make emacs startup with background Transparency.
#+begin_src elisp
(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"))
#+end_src

Disable fcitx5 on linux, because I use emacs rime, an internal input method of emacs, which is setuped [[#c418f945-d240-4dcb-bd38-c656bb9253b8][here]],
#+begin_src elisp
(setq pgtk-use-im-context-on-new-connection nil)
#+end_src

Below codes belongs to the original Borg seed.
#+begin_src elisp
(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))
#+end_src

* Init
:PROPERTIES:
:header-args:elisp: :noweb-ref debug-init :tangle init.el
:CUSTOM_ID: fb6f20e1-1c32-44ef-ae11-1e78e6ae3cef
:END:

*NOTE*: Starting from here, elisp codes are tangled to init.el

** Begin of init
:PROPERTIES:
:CUSTOM_ID: 34e4f990-1bd5-45a7-a3f9-8b7ea719c0d6
:END:

After loading early-init.el, emacs begin to load init.el.

Disable byte compile for init.el, same reason of early-init.el.
#+begin_src elisp
;;; -*- lexical-binding: t; no-byte-compile: t -*-
#+end_src

Calculating time used loading emacs excutable, as well as setting some variables.
#+begin_src elisp
(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)
)
#+end_src

Set some defaults of emacs
#+begin_src elisp
(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)
#+end_src
** Borg
:PROPERTIES:
:CUSTOM_ID: c420faba-8328-4d7d-a379-c22f29d828d6
:END:
[[https://github.com/emacscollective/borg][Borg]] is the package manager that I use for my configuration. It assimilate Emacs packages as git submodules, which are called "=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.
#+begin_src elisp
(use-package borg
:init
(add-to-list 'load-path
(expand-file-name "lib/borg" user-emacs-directory))
:config
(borg-initialize)
(switch-to-buffer "*Messages*")
)
#+end_src

#+begin_src elisp

#+end_src
** COMMENT Borg-nix-shell
This is copied from [[https://github.com/thblt/borg-nix-shell][borg-nix-shell]]
#+begin_src elisp
(defvar borg-nix-shell-build-use-pure-shell
t
"Determine if nix-shells should be pure.")

(defun borg-nix-shell-borg-get
(drone key &optional all)
"A reimplementation of `borg-get' for consistency.

This function has consistent behavior regardless of the way Borg behaves"
(let ((ret (borg-get drone key all)))
(if all
ret
(if (listp ret)
ret
(list ret)))))

(defun borg-nix-shell-build-command (drone)
"Return a format string for wrapping a build-step in a nix-shell.

The nix-shell is started with the file at
submodules.DRONE.build-nix-shell-file or the packages at
submodules.DRONE.build-nix-shell-packages. If none of this is
provided, and the package has no default.nix, it is run with the
-p argument. If there's a default.nix or shell.nix, no extra
arguments are added."
(if (borg-nix-shell-borg-get drone "build-nix-shell-disable")
nil
(concat "nix-shell "
(when borg-nix-shell-build-use-pure-shell "--pure ")
"--run %S "
(if (car (borg-nix-shell-borg-get drone "build-nix-shell-file"))
(car (borg-nix-shell-borg-get drone "build-nix-shell-file"))
(unless (or (file-exists-p
(expand-file-name "shell.nix" (borg-worktree drone)))
(file-exists-p
(expand-file-name "default.nix" (borg-worktree drone))))
(concat "-p " (car
(borg-nix-shell-borg-get drone
"build-nix-shell-packages"))))))))

(setq borg-build-shell-command 'borg-nix-shell-build-command)
#+end_src

** Auto-Compile
:PROPERTIES:
:CUSTOM_ID: 7ae05ee5-af80-48d3-90d3-ce206daee4da
:END:
[[https://github.com/emacscollective/auto-compile][Auto-Compile]] automatically compile Emacs Lisp libraries.
But comp warnings are always boring. Suppress comp warnings.
#+begin_src elisp
(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))
)
)
#+end_src

** Epkg
:PROPERTIES:
:CUSTOM_ID: c2d5ac28-75b7-4914-956a-ddd1d003585a
:END:
[[https://github.com/emacscollective/epkg][Epkg]] allows you browse the Emacsmirror package database. It also provides a command ~epkg-describe-package~ that looks nicer than the built-in describe-package.
#+begin_src elisp
(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
)
#+end_src
** Custom
:PROPERTIES:
:CUSTOM_ID: 2d77e7c8-32a4-44bc-b48c-cac9e26e60cb
:END:
[[https://www.emacswiki.org/emacs/CustomizingAndSaving#Customize][Custom]] is a built-in package, provides the customize system of emacs.
We set the custom-file to custom.el and then load it.

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=.
#+begin_src elisp
(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))
)
#+end_src

** Server
:PROPERTIES:
:CUSTOM_ID: fa0a264a-cc5d-476f-9ce5-44c0002dbec1
:END:
Server allows Emacs to operate as a server for other processes. Built in.
#+begin_src elisp
(use-package server
:commands (server-running-p)
:config (or (server-running-p) (server-mode)))
#+end_src
** GCMH
:PROPERTIES:
:CUSTOM_ID: 3aeaad54-3694-4ad4-a887-ac1d06ccc9c4
:END:
:BACKLINKS:
[[#bdf3a8f0-d259-491b-99cd-16e72cc3f605][Pulse-Cursor]]
:END:

The [[https://github.com/emacsmirror/gcmh][Garbage Collector Magic Hack]] enforce a sneaky Garbage Collection strategy to minimize GC interference with user activity.
#+begin_src elisp
(use-package gcmh
:init
(setq gcmh-high-cons-threshold 536870912) ;; 512mb
:config
(gcmh-mode 1)
)
#+end_src
** No-littering
#+begin_src elisp
(use-package no-littering)
#+end_src
** Libraries
:PROPERTIES:
:CUSTOM_ID: 47db424a-224f-4ff7-b29d-86ff149fbda6
:END:
*** S
:PROPERTIES:
:CUSTOM_ID: 9ee8fcaa-3b39-496a-afc3-c295eda309c4
:END:
[[https://github.com/magnars/s.el][S]] is the long lost Emacs string manipulation library.

*** F
:PROPERTIES:
:CUSTOM_ID: c47d9db7-47e0-4b53-ad56-971574886bbc
:END:
[[https://github.com/rejeep/f.el][F]] is a modern API for working with files and directories in Emacs.
*** Dash
:PROPERTIES:
:CUSTOM_ID: d34df8ba-bb6d-410e-bc33-2425d668b24d
:END:
[[https://github.com/magnars/dash.el][Dash]] is a modern list library for Emacs. See its overview at [[https://github.com/magnars/dash.el#functions][dash.el - functions]].
=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.

#+begin_src elisp
(use-package dash
:config (global-dash-fontify-mode))
#+end_src

Dash needs some tweaks to be built
#+begin_src conf
[submodule "dash"]
no-byte-compile = dash-functional.el
no-makeinfo = dash-template.texi
#+end_src

*** EIEIO
:PROPERTIES:
:CUSTOM_ID: 154d69e1-e292-4fe3-9650-a420f37aceac
:END:
[[https://www.gnu.org/software/emacs][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.
#+begin_src elisp
(use-package eieio)
#+end_src

*** Annalist
:PROPERTIES:
:CUSTOM_ID: 864c3d87-4e35-41e5-8b5a-15a200164207
:END:
[[https://github.com/noctuid/annalist.el][annalist.el]] is a library that can be used to record information and later print that information using org-mode headings and tables. It allows defining different types of things that can be recorded (e.g. keybindings, settings, hooks, and advice) and supports custom filtering, sorting, and formatting. annalist is primarily intended for use in other packages like general and evil-collection, but it can also be used directly in a user’s configuration.

*** COMMENT Shrink path
:PROPERTIES:
:CUSTOM_ID: 03bb7e45-a788-4a19-8296-4dc5b5aa3e35
:END:
[[https://github.com/zbelial/shrink-path.el][Shrink path]] is a small utility functions that allow for fish-style trunctated directories in eshell and for example modeline.
#+begin_src elisp
(use-package shrink-path :demand t)
#+end_src

*** Sqlite3
:PROPERTIES:
:CUSTOM_ID: b312e319-00e3-4c04-a855-8d6b8c71e9ba
:END:
#+begin_src conf
[submodule "sqlite3"]
build-step = make
#+end_src

*** Emacsql
:PROPERTIES:
:CUSTOM_ID: 16777f9e-a96f-467a-ba65-f86746e23d45
:END:
tweaks to buiild emacsql
#+begin_src conf
[submodule "emacsql"]
no-byte-compile = emacsql-pg.el
#+end_src

*** Emacs Async
:PROPERTIES:
:CUSTOM_ID: e73c946b-a803-44e9-89a0-8c4a421edd14
:END:
** Builtins
:PROPERTIES:
:CUSTOM_ID: 3811cabb-2894-4b06-9234-42e26b54d24a
:END:
*** DIff mode
:PROPERTIES:
:CUSTOM_ID: 7742d6fb-5f74-40ac-9dc6-24df18e3a8e2
:END:
#+begin_src elisp
(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)))
#+end_src
*** Dired
:PROPERTIES:
:CUSTOM_ID: 48d4fd1d-c1f0-410d-96d1-d5221c8bcaeb
:END:
#+begin_src elisp
(use-package dired
:defer t
:config (setq dired-listing-switches "-alh"))
#+end_src

*** ELdoc
:PROPERTIES:
:CUSTOM_ID: 40fc2f2b-5d78-4eea-bbe6-10239d6b1c0e
:END:
a MinorMode which shows you, in the echo area, the argument list of the function call you are currently writing.
#+begin_src elisp
(use-package eldoc
:when (version< "25" emacs-version)
:config (global-eldoc-mode))
#+end_src
*** Help
:PROPERTIES:
:CUSTOM_ID: d3472f01-1cdc-47b4-8505-7dda94ee4864
:END:
#+begin_src elisp
(use-package help
:defer t
:config (temp-buffer-resize-mode))
#+end_src
*** Helpful
:PROPERTIES:
:CUSTOM_ID: 14bddefb-9db5-485e-91d6-d47ed73b6775
:END:

[[https://github.com/Wilfred/helpful][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.
#+begin_src elisp
(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)
)
#+end_src

*** Info+
:PROPERTIES:
:CUSTOM_ID: af99c97f-1ac8-4ab2-b322-ae66c78cc960
:END:
#+begin_src elisp
(use-package info+
:defer t
:config
)
#+end_src
#+begin_src elisp
(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)
)
#+end_src
*** Isearch
:PROPERTIES:
:CUSTOM_ID: 95631f66-29f3-46aa-9088-d18bf0b925d8
:END:
#+begin_src elisp
(progn ; `isearch'
(setq isearch-allow-scroll t))
#+end_src
*** Lisp-mode
:PROPERTIES:
:CUSTOM_ID: 499297a3-67cd-46ab-bda6-2587b64c4cc0
:END:
#+begin_src elisp
(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))
#+end_src
*** Man
:PROPERTIES:
:CUSTOM_ID: 5e9fb076-8f0f-496a-8860-bce104072a19
:END:
#+begin_src elisp
(use-package man
:defer t
:config (setq Man-width 80))
#+end_src

*** Prog-mode
:PROPERTIES:
:CUSTOM_ID: 26d1c604-e1c0-42d0-8e07-539614dfd757
:END:
#+begin_src elisp
(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)
)
#+end_src

*** Recentf
:PROPERTIES:
:CUSTOM_ID: 723104c7-10be-4782-84fd-451b8bf0e4bf
:END:
#+begin_src elisp
(use-package recentf
:demand t
:config (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?x?:"))
#+end_src
*** Savehist
:PROPERTIES:
:CUSTOM_ID: 202d5f4c-fca3-4a81-87c5-390798ca293e
:END:
#+begin_src elisp
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init
(savehist-mode))
#+end_src
*** Saveplace
:PROPERTIES:
:CUSTOM_ID: 5113ee1e-df60-4452-a21e-6386cc6913ca
:END:
#+begin_src elisp
;; A few more useful configurations...
(use-package emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; We display [CRM], 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))
#+end_src
*** Simple
:PROPERTIES:
:CUSTOM_ID: 4e860888-be36-4c64-b8f3-be05dc030d31
:END:
#+begin_src elisp
(use-package simple
:config (column-number-mode))
#+end_src
*** Smerge
:PROPERTIES:
:CUSTOM_ID: 57fe9b41-0e6f-443a-a0b3-742f0c005543
:END:
#+begin_src elisp
(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)))
#+end_src
*** Text
:PROPERTIES:
:CUSTOM_ID: 950b2287-ffed-4baa-a3e1-fb47798612c2
:END:
#+begin_src elisp
(progn ; `text-mode'
(add-hook 'text-mode-hook 'indicate-buffer-boundaries-left))
#+end_src

*** Tramp
:PROPERTIES:
:CUSTOM_ID: 07612efe-a2a9-4164-90e5-164f00637886
:END:
#+begin_src elisp
(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))
#+end_src

*** Pixel-scroll
:PROPERTIES:
:CUSTOM_ID: b783d068-76ae-483c-8eee-5adcedc2cc94
:END:
#+begin_src elisp
(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)
)
#+end_src
** End of core units
:PROPERTIES:
:CUSTOM_ID: a95c065e-97dd-4229-aa32-ed64ead673c4
:END:
Calculate loading time of core units.
#+begin_src elisp
(progn ; startup
(message "Loading core units...done (%fs)"
(float-time (time-subtract (current-time) before-user-init-time))))
#+end_src
* Debug init
:PROPERTIES:
:CUSTOM_ID: abe84653-207a-4b06-af06-5156ac556d83
:END:
#+begin_src elisp :tangle debug-init.el :noweb no-export
<>
#+end_src
* Keybindings
:PROPERTIES:
:CUSTOM_ID: 793ddb0b-2cad-49d0-8b2f-3886744f748a
:TOC: headlines 1
:END:

An overview of this outline:
In =General.el= and =Meow.el=, we setup the keybinding framework.
Then in =Keybindings=, define keybindings.

** General.el
:PROPERTIES:
:CUSTOM_ID: 6377b946-b638-4773-93e6-21abada88d59
:END:
[[https://github.com/noctuid/general.el][General]] provides a more convenient method for binding keys in emacs
(for both evil and non-evil users).

*Note*: byte compile init.el will lead to function created by general-create-definer failed to work.
#+begin_src elisp :noweb no-export
;; Make ESC quit prompts
;; (global-set-key ([kbd] "") 'keyboard-escape-quit)

(use-package general)
#+end_src
** Meow.el
:PROPERTIES:
:CUSTOM_ID: bac687ce-13c4-413c-b92d-7f7df81fa6ff
:END:
[[https://github.com/meow-edit/meow][Meow]] is yet another modal editing.

#+begin_src elisp :noweb no-export
(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)
)
#+end_src
** Mode-map
:PROPERTIES:
:CUSTOM_ID: 20dbcac9-a7cb-4447-8b96-a490d1637b75
:END:
Keybindings defined somewhere else...
+ [[#36fd11bc-3a4e-4f96-ad85-5c1d6991e7c4][Vertico]]
+ [[#4e4b8f79-8616-4cc0-bcc8-2b1a2ca03de2][Org mode]]
+ [[#85c28b3b-dcb0-4dce-9fdf-0fdaee9d66d2][Tempel]]
*** Mode leader
:PROPERTIES:
:CUSTOM_ID: 19d9abad-e3e5-426d-81c5-e281020c3daf
:END:
Generally, I define my local leader as follows:
- Let ~C-~ be the local leader. The convention is to use ~C-c~, but I make ~C-c~ save to system clipboard ~;)~
- I do not directly press ~C-~. Instead, I translate ~\~ to ~C-~ in meow's normal mode.
- The keybindings are bind to those major mode maps.
#+begin_src elisp
(defvar my/mode-leader "C-")

(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
)
#+end_src
** Global-map
*** Meow-normal
:PROPERTIES:
:CUSTOM_ID: 0bb7f8a0-4c80-4139-bf84-c9944308c64a
:END:

#+begin_src elisp
(meow-normal-define-key
'("" . 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- C-j")
'("C-k" . "C- C-k")
'("C-l" . "C- C-l")
'("C-;" . "C- 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)
)
#+end_src

#+RESULTS:

*** Meow-motion
:PROPERTIES:
:CUSTOM_ID: 108e1a69-3e19-4a36-9547-86e7370974af
:END:

#+begin_src elisp
(meow-motion-overwrite-define-key
'("j" . meow-left)
'("k" . meow-prev)
'("l" . meow-next)
'(";" . meow-right)
'("SPC" . my/leader-prefix-cmd) ;; defined latter
'("" . ignore)
)
#+end_src

*** Meow-keypad
:PROPERTIES:
:CUSTOM_ID: c276b705-4a1d-4da3-aac2-96848e79eb9a
:END:
I generally do not use meow's keypad, because meow's keypad highly relies on vanilla emacs's keybindings, which is what I do not prefer.
#+begin_src elisp
(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)
)

#+end_src

#+RESULTS:

*** Meow-insert
:PROPERTIES:
:CUSTOM_ID: f764a901-b07e-4d34-97e0-158cbfc8d519
:END:

#+begin_src elisp
(general-def
:keymaps '(global-map)
"C-v" '(clipboard-yank :wk "paste")
"C-SPC" '(toggle-input-method :wk "input method")
"" '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")
)

#+end_src

#+RESULTS:

*** Global leader
:PROPERTIES:
:CUSTOM_ID: 2ebc323d-4318-4f0d-9f85-924861dab4db
:END:

#+begin_src elisp
(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")
)
#+end_src

#+begin_src elisp
(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")
)
#+end_src

#+begin_src elisp
(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")
)
#+end_src

#+begin_src elisp
;; 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")
)
#+end_src

#+begin_src elisp
(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")
)
#+end_src

#+begin_src elisp
(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 ")
)
#+end_src

#+begin_src elisp
;; 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")
)

#+end_src

#+begin_src elisp
;; Git
(my/leader :infix "g"
"" '(nil :wk "git")
"g" '(magit :wk " magit")
)
#+end_src

#+begin_src elisp
;; 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))
#+end_src

** Transient
:PROPERTIES:
:CUSTOM_ID: b7838793-3629-4d7d-88d3-19c1cbefe997
:END:
[[https://github.com/yanghaoxie/transient-posframe][Transient-posframe]] display transient popups using a posframe.
#+begin_src elisp
(use-package transient-posframe
:config
(setq transient-posframe-min-height 1)
(setq transient-posframe-poshandler
'posframe-poshandler-frame-bottom-right-corner)
(transient-posframe-mode)
)
#+end_src
** Which-key.el
:PROPERTIES:
:CUSTOM_ID: 1b5d6414-c2e4-41a8-b04d-f150f6883d8e
:END:
[[https://github.com/justbur/emacs-which-key][Which-key]] is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup.

Magit and meow all use transient maps, therefore we let which-key show transient maps.
#+begin_src elisp
(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)
)
#+end_src

[[https://github.com/yanghaoxie/which-key-posframe][Which-key-posframe]] use posframe to show which-key popup.
# Currently which key still have problems showing things correctly. I may fix them someday :(
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.
#+begin_src elisp
(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)
)
#+end_src
** Rime.el
:PROPERTIES:
:CUSTOM_ID: c418f945-d240-4dcb-bd38-c656bb9253b8
:END:
:BACKLINKS:
[[#b343e4f2-36db-4558-8e69-3bb52bcb5190][Early Init]]
:END:

#+begin_src elisp
(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)
)
#+end_src

** COMMENT Evil
:PROPERTIES:
:CUSTOM_ID: bd479272-28ec-4552-bd41-9178ae7af148
:END:
I guess evil surround and evil nerd commentor should be better to put under Coding.
I do not use evil mode anymore because of Meow Edit.
*** Evil mode
:PROPERTIES:
:CUSTOM_ID: 9e2741ae-3fba-4db2-afc2-1100a454a70b
:END:
[[https://github.com/emacs-evil/evil][Evil mode]] that turns you into an evil.

#+begin_src elisp
(use-package evil
:disabled
:init
(setq evil-want-integration t) ;; t by default
(setq evil-want-keybinding nil)
(setq evil-vsplit-window-right t)
(setq evil-split-window-below t)
(setq evil-want-C-u-scroll t)

:config
(evil-mode 1)
;; Use visual line motions even outside of visual-line-mode buffers
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dashboard-mode 'normal)
(evil-set-undo-system 'undo-redo)
(evil-define-key 'normal 'foo-mode "e" 'baz)
)
#+end_src
#+begin_src conf
[submodule "evil"]
info-path = doc/build/texinfo
#+end_src
*** Evil collection
:PROPERTIES:
:CUSTOM_ID: 69599a36-31aa-4ebd-acd1-e798f84e9b8f
:END:
[[https://github.com/emacs-evil/evil-collection][Evil-collection]] automatically configures various Emacs modes with Vi-like keybindings.

#+begin_src elisp
(use-package evil-collection
;; :demand t
:disabled
:after evil
:custom (evil-collection-setup-minibuffer t)
:config
;(setq evil-collection-mode-list '(dashboard dired ibuffer))
(evil-collection-init))

(use-package evil-tutor
:demand t)

(use-package emacs
:config (setq ring-bell-function #'ignore)
)
#+end_src

*** Evil Surround
:PROPERTIES:
:CUSTOM_ID: 951d378a-487a-4113-945b-df3c01b87610
:END:
#+begin_src elisp
(use-package evil-surround
:after evil
:disabled
:config
(global-evil-surround-mode 1))
#+end_src
*** Evil Nerd commenter
:PROPERTIES:
:CUSTOM_ID: 6b17c871-86e5-4746-b8f5-00a899f1051c
:END:
[[https://github.com/redguardtoo/evil-nerd-commenter][Evi Nerd Commenter]] helps you comment code efficiently!
#+begin_src elisp
(use-package evil-nerd-commenter
:after evil
:disabled
:config
)
#+end_src
** COMMENT Key-echo
:PROPERTIES:
:CUSTOM_ID: ed65190a-9a2b-43ce-83d9-5d73bec899f5
:END:
[[https://github.com/manateelazycat/key-echo][Key-Echo]] is an Emacs plugin that uses XRecord technology to listen to system key events.
#+begin_src elisp
(use-package key-echo
:disabled
:config
(key-echo-enable)
)
#+end_src

* Displays
:PROPERTIES:
:CUSTOM_ID: cb45a662-f7d3-4afa-a9c4-f2795b01c9d0
:END:

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
:PROPERTIES:
:CUSTOM_ID: 94ead78c-1e1b-4f6f-b78f-5d805c08519b
:END:
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.

*** COMMENT Face-remap.el
Face-remap is a builtin library, where ~face-remap-add-relative~ is defined.

note: ~set-face-attribute~ can receive both ~:family~ and ~:font~, they function almost the same, except that ~:font~ doesn't work in emacsclient.
#+begin_src elisp
(use-package face-remap
:config
(set-face-attribute 'default nil
;; :family "Sarasa Gothic SC Nerd Font"
:family "IBM Plex Sans"
;; :family "IBM Plex Serif"
:height 150)
(set-face-attribute 'fixed-pitch nil
;: :family "Sarasa Fixed SC"
;; :family "RobotoMono Nerd Font Mono"
;; :family "CommitMono Nerd Font Mono"
:family "IBM Plex Mono Text"
;; :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)

;; 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")

(set-face-attribute 'link nil :underline t :bold nil)

(defun my/use-fixed-pitch ()
(interactive)
(face-remap-add-relative 'default 'fixed-pitch)
(turn-off-solaire-mode)
)
(defun my/use-variable-pitch ()
(interactive)
(face-remap-add-relative 'default 'variable-pitch)
)
(dolist (hook '(
dired-mode-hook
comint-mode-hook
magit-mode-hook
prog-mode-hook
profiler-report-mode-hook
conf-mode-hook conf-ts-mode-hook
toml-mode-hook toml-ts-mode-hook
))
(add-hook hook 'my/use-fixed-pitch))

)

#+end_src
*** COMMENT Fixed-pitch-mode
:PROPERTIES:
:CUSTOM_ID: f46177cf-c0b0-4525-8f5b-2e891568e788
:END:
[[https://github.com/cstby/fixed-pitch-mode][Fixed-pitch-mode]] make certain buffers (especially prog mode buffers) to have fixed-pitch fonts, and left all the other fonts to the default font (which can be set to some non-fixed-pitch fonts). It has a simplier implementation than mixed-pitch-mode.

However, I found out that many UI designs in emacs assumes that you use a fixed pitch font. If you instead use a variable pitch font, it could look much unaligned and messy. Redesign those UIs is not a small amount of work, so for the time being, I simply gave it up.
#+begin_src elisp
(use-package fixed-pitch
:config
;; This cause some bugs
;; (add-to-list 'default-frame-alist '(font . "Sarasa Gothic SC-16" ))
(set-face-attribute 'default nil
:font "Sarasa Gothic SC Nerd Font"
:height 150)
(set-face-attribute 'fixed-pitch nil
;:font "Sarasa Fixed SC"
:font "RobotoMono Nerd Font Mono"
:height 1.0)
(set-face-attribute 'variable-pitch nil
:font "Sarasa Gothic SC Nerd Font"
:height 1.0)
; (set-fontset-font t 'symbol "Noto Sans Symbols 2")
(set-face-attribute 'link nil
:foreground "#ffcc66" :underline t :bold nil)
;; This is a temporary fix for solaire mode
;; (set-face-attribute 'solaire-default-face nil
;; :inherit 'fixed-pitch)
(setq fixed-pitch-use-extended-default t)
(dolist (hook '(
conf-mode-hook
conf-ts-mode-hook
toml-mode-hook
toml-ts-mode-hook
))
(add-to-list 'fixed-pitch-whitelist-hooks hook))
(fixed-pitch-enable)
)
#+end_src

*** Mixed-pitch-mode
:PROPERTIES:
:CUSTOM_ID: 692c7608-bd4e-4acb-affd-b9e639cd7d28
:END:
#+begin_src elisp
(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")

)
#+end_src

*** Zooming In/Out
:PROPERTIES:
:CUSTOM_ID: 0b75f580-be0a-4932-a88f-e8e6c29257c2
:END:

You can use the bindings CTRL plus =/- for zooming in/out. You can also use CTRL plus the mouse wheel for zooming in/out.
#+begin_src elisp
(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "") 'text-scale-decrease)
(global-set-key (kbd "") 'text-scale-increase)
#+end_src

*** Line Space
#+begin_src elisp
(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)))
#+end_src
*** Icons
:PROPERTIES:
:CUSTOM_ID: 2debde78-476a-4961-a003-b37166d772c7
:END:
**** All-the-icons
:PROPERTIES:
:CUSTOM_ID: 97c26c8f-dfbc-47ae-83ae-f40b44379ac6
:END:

[[https://github.com/domtronn/all-the-icons.el][All-the-icons]] is an icon set that can be used with dashboard, dired, ibuffer and other Emacs programs.

#+begin_src elisp
(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))))
#+end_src

*NOTE*: In order for the icons to work it is very important that you install the Resource Fonts included in this package. Run [[elisp:all-the-icons-install-fonts][M-x all-the-icons-install-fonts]] to install necessary icons.

**** All-the-icons-completion
:PROPERTIES:
:CUSTOM_ID: 701c4747-737c-43c3-b63d-f133c36cffb2
:END:
All-the-icons-completion makes icons appear in the minibuffer. Cool.
#+begin_src elisp
(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))
#+end_src
**** Nerd-icons
:PROPERTIES:
:CUSTOM_ID: c9b35d34-1c55-45fa-a648-6669cf6ed8ac
:END:
[[https://github.com/rainstormstudio/nerd-icons.el][Nerd-icons]] is a library for easily using Nerd Font icons inside Emacs, an alternative to all-the-icons.
Run [[elisp:nerd-icons-install-fonts][M-x nerd-icons-install-fonts]] to install =Symbols Nerd Fonts Mono= for you.
#+begin_src elisp
(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")
)
#+end_src

** Themes
:PROPERTIES:
:CUSTOM_ID: 440ed820-dd6b-4c79-8859-3e039c268121
:END:
*** Doom-themes
:PROPERTIES:
:CUSTOM_ID: 96b9a835-6606-478b-98f8-4792101b6e81
:END:
[[https://github.com/hlissner/emacs-doom-themes][Doom-themes]] is a great set of themes with a lot of variety and support for many different Emacs modes. Taking a look at the [[https://github.com/hlissner/emacs-doom-themes/tree/screenshots][screenshots]] might help you decide which one you like best. Run =M-x counsel-load-theme= to choose between them easily.

*** Solaire mode
:PROPERTIES:
:CUSTOM_ID: 549aabd9-a7a3-4f40-adc0-20c029630a4e
:END:
[[https://github.com/hlissner/emacs-solaire-mode][Solaire-mode]] makes certain buffers grossly incandescent. Useful to distinguish the main buffers from others.
#+begin_src elisp
(use-package solaire-mode
:defer t
:init (solaire-global-mode)
:config
(add-hook 'org-src-mode-hook 'turn-off-solaire-mode)
)
#+end_src

** Frames
:PROPERTIES:
:CUSTOM_ID: 6774a05e-f776-46b8-b7c8-40e9b7699c11
:END:
*** Posframe
:PROPERTIES:
:CUSTOM_ID: e5eedb77-9815-49c1-8742-f3a26bc1747c
:END:
[[https://github.com/tumashu/posframe][Posframe]] can pop up a frame at point, this *posframe* is a child-frame connected to its root window's buffer, in which some texts are showed. It's more pretty and tidy than showing everything in the minibuffer.
Posframe can be used by many useful and important package, such as vertico, consult, emacs-rime, lsp-bridge.

Note that a 'frame' is a window on the desktop, a 'window' is a subwindow of emacs.
#+begin_src elisp
(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))))
)
)
#+end_src
*** COMMENT Mini-frame
:PROPERTIES:
:CUSTOM_ID: b80c7c3e-4002-4e2a-a3d2-c6c60f300e8c
:END:
[[https://github.com/muffinmad/emacs-mini-frame][Mini-Frame]], similar to posframe, shows minibuffer in child frame on read-from-minibuffer.
#+begin_src elisp
(use-package mini-frame
:config
(setq mini-frame-detach-on-hide nil)
;(setq mini-frame-standalone 't)
;(setq mini-frame-resize-min-height 10)

)
#+end_src

*** Transparency
:PROPERTIES:
:CUSTOM_ID: ace4738e-27d7-44c7-b7c8-c18c82acf961
:END:
We have already set transparency in [[#b343e4f2-36db-4558-8e69-3bb52bcb5190][Early Init]]
Here lets define a function to interactively set transparency value.
#+begin_src elisp
(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))
#+end_src
** Margin
:PROPERTIES:
:CUSTOM_ID: 8e96278e-1713-4186-b967-6064a6a8f67f
:END:
*** Horizontal
:PROPERTIES:
:CUSTOM_ID: 8f648737-5ac5-4187-8d2f-13344efd4a59
:END:
We have 3 modes that can help centering text in a window.
But currently we only use olivetti mode.

**** Olivetti
:PROPERTIES:
:CUSTOM_ID: 4a391819-9c4f-4394-bef2-83036c1ca8f0
:END:

[[https://github.com/rnkn/olivetti][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.
#+begin_src elisp
(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")
;; )
)
#+end_src

**** Visual-fill-column
:PROPERTIES:
:CUSTOM_ID: 9c1ae6c1-0ace-460f-a92d-dd922c0a0f22
:END:
[[https://github.com/joostkremers/visual-fill-column][visual-fill-column]]
#+begin_src elisp
(setq-default visual-fill-column-center-text t)
#+end_src

**** Writeroom-mode
:PROPERTIES:
:CUSTOM_ID: 7ab32bc9-054e-495f-b946-aa235cfe3357
:END:

*** COMMENT Vertical
:PROPERTIES:
:CUSTOM_ID: deee099a-b78e-4c82-a662-4a796f2736d5
:END:

[[https://github.com/trevorpogue/topspace][Topspace]] recenter line 1 with scrollable upper margin/padding.
#+begin_src elisp
(use-package topspace
:init (global-topspace-mode)
:config
;; Zen mode, the hack is from
;; https://github.com/trevorpogue/topspace/issues/17#issuecomment-1637004205
(defun zen-mode-bodge ()
(let ((ov (make-overlay 1 1 nil t t)))
(overlay-put ov 'priority 9999999)
(overlay-put ov 'before-string (propertize " 1 " 'face 'line-number))
(overlay-put ov 'zen--remove-from-buffer-tag t))
(let ((ov (make-overlay 1 2)))
(overlay-put ov 'display-line-numbers-disable t)
(overlay-put ov 'zen--remove-from-buffer-tag t)))

(defun zen-mode-clear ()
(remove-overlays 1 2 'zen--remove-from-buffer-tag t))

;; install hooks
;; (advice-add 'topspace--enable :after #'zen-mode-bodge)
;; (advice-add 'topspace--disable :after #'zen-mode-clear)
)
#+end_src

* The Four
:PROPERTIES:
:CUSTOM_ID: 5d02391b-fb05-43ae-abb3-d6d7a4052b6e
:END:
These four things are basically what you're gonna to see =anywhere, anytime= in emacs.
Therefore I grouped them together.

** Minibuffer
:PROPERTIES:
:CUSTOM_ID: 0f18c662-2e67-43ce-b083-aa38cf1bb77e
:END:
*** Vertico
:PROPERTIES:
:CUSTOM_ID: 36fd11bc-3a4e-4f96-ad85-5c1d6991e7c4
:END:
:BACKLINKS:
[[#20dbcac9-a7cb-4447-8b96-a490d1637b75][Mode map]]
:END:
[[https://github.com/minad/vertico#extensions][Vertico]] provides a performant and minimalistic vertical completion UI based on the default completion system.

#+begin_src elisp
(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
)
)
#+end_src
tweaks to build vertico
#+begin_src conf
[submodule "vertico"]
load-path = .
load-path = extensions
#+end_src
**** Vertico-directory
:PROPERTIES:
:CUSTOM_ID: 798614c1-afb2-4609-9860-2e35cd563813
:END:

#+begin_src elisp
(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))
#+end_src
**** Vertico-multiform
:PROPERTIES:
:CUSTOM_ID: f094f952-1386-46ce-9af2-12a31a585221
:END:

Vertico-multiform configures Vertico modes per command or completion category.

#+begin_src elisp
(use-package vertico-multiform
:after vertico
:config (vertico-multiform-mode)
)
#+end_src

**** Vertico-posframe
:PROPERTIES:
:CUSTOM_ID: fe331f40-1788-4453-9c14-cace67fdf620
:END:

[[https://github.com/tumashu/vertico-posframe][Vertico-posframe]] is an vertico extension, which lets vertico use posframe to show its candidate menu.
See [[* Posframe][Posframe]] for function defintion.

#+begin_src elisp
(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)
)
#+end_src

*** Completion
**** Orderless
:PROPERTIES:
:CUSTOM_ID: e49ba787-90af-48c5-8153-1a4ed60cf094
:END:
[[https://github.com/oantolin/orderless][Orderless]] provides a completion style that divides the pattern into space-separated components, and matches candidates that match all of the components in any order.
Each component can match in any one of several ways: literally, as a regexp, as an initialism, in the flex style, or as multiple word prefixes. By default, regexp and literal matches are enabled.

#+begin_src elisp
(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))
)
#+end_src

**** COMMENT flx-rs + fussy
#+begin_src elisp
(use-package flx-rs
:config
(advice-add 'flx-score :override #'flx-rs-score))
#+end_src
**** COMMENT Hotfuzz
#+begin_src elisp
(use-package hotfuzz
:init
(setq completion-styles '(hotfuzz)))
#+end_src
*** Savehist
:PROPERTIES:
:CUSTOM_ID: 949e27b3-decf-49fa-828d-dab2be046ec8
:END:

#+begin_src elisp
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
:init
(savehist-mode))
#+end_src

#+begin_src elisp
;; A few more useful configurations...
(use-package emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; We display [CRM], 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))
#+end_src

*** Consult
:PROPERTIES:
:CUSTOM_ID: 67e08b1c-6c75-40e0-b279-e32e86660a63
:END:

[[https://github.com/minad/consult][Consult]] provides search and navigation commands based on the Emacs completion function completing-read.

#+begin_src elisp
(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-" "S-"))

;; 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)
)
#+end_src

*** Marginalia
:PROPERTIES:
:CUSTOM_ID: 1e4c6fa2-a8de-41d7-9a73-2ec0612761a5
:END:
[[https://github.com/minad/marginalia][Marginalia]] enriches existing commands with completion annotations
#+begin_src elisp
(use-package marginalia
:general
(:keymaps 'minibuffer-local-map
"M-A" 'marginalia-cycle)
:custom
(marginalia-max-relative-age 0)
(marginalia-align 'right)
:init
(marginalia-mode)
)
#+end_src

** Tabs
:PROPERTIES:
:CUSTOM_ID: 7ed80fba-c7b3-4fb8-9bfd-20557b4d2e2c
:END:
*** Tab-bar-mode
:PROPERTIES:
:CUSTOM_ID: c1a1309e-1e38-4149-aa3f-f8c0ae968367
:END:
*** Sort-tab
:PROPERTIES:
:CUSTOM_ID: ba49602c-1d1a-43bd-99c8-50ef27584561
:END:

#+begin_src elisp
(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)
)
#+end_src
*** COMMENT Tab-line-mode
:PROPERTIES:
:CUSTOM_ID: 30ab2a21-2272-4965-b721-4af3a31fa51a
:END:
Code stolen from [[https://emacs-china.org/t/27-1-tab-line-mode/20514][Emacs China]]
#+begin_src elisp
;; from tabbar-ruler
(defcustom config/included-buffers '("*scratch*")
"* Included buffers in tabbar."
:type '(repeat (string :tag "Buffer Name"))
:group 'EmacsPortable)

(defcustom config/excluded-buffers '("*Messages*" "*Completions*" "*ESS*")
"* Excluded buffers in tabbar."
:type '(repeat (string :tag "Buffer Name"))
:group 'EmacsPortable)

(setq config/excluded-buffers '(
"*Messages*" "*Completions*" "*ESS*"
"*Compile-Log*" "*Ibuffer*" "*SPEEDBAR*"
"*etags tmp*" "*reg group-leader*" "*Pymacs*" "*grep*")
)
(setq config/included-buffers '("*scratch*" "*shell*"))
(defun ep-tabbar-buffer-list ()
"Return the list of buffers to show in tabs.
Exclude buffers whose name starts with a space or *, when they are not
visiting a file. The current buffer is always included."
(delq nil
(mapcar #'(lambda (b)
(cond
;; Always include the current buffer.
((eq (current-buffer) b) b)
((string-match "^TAGS\\(<[0-9]+>\\)?$" (format "%s" (buffer-name b))) nil)
;; ((string= "TAGS" (format "%s" (buffer-name b))) nil)
((buffer-file-name b) b)
((member (buffer-name b) EmacsPortable-included-buffers) b)
((member (buffer-name b) EmacsPortable-excluded-buffers) nil)
((char-equal ?\ (aref (buffer-name b) 0)) nil)
((char-equal ?* (aref (buffer-name b) 0)) nil)
((buffer-live-p b) b)))
(buffer-list))))
(when (functionp 'global-tab-line-mode)
(use-package tab-line
:defer 0.5
:init
(setq tab-line-tabs-function 'ep-tabbar-buffer-list)
:config
(global-tab-line-mode 1)
)
#+end_src
*** COMMENT Centaur-tabs
:PROPERTIES:
:CUSTOM_ID: 0d6f7e8e-7cf3-4137-8d10-f000168193e5
:END:

#+begin_src elisp :tangle init.el
(use-package centaur-tabs
:disabled
:hook
(emacs-startup . centaur-tabs-mode)
(dired-mode . centaur-tabs-local-mode)
(dirvish-directory-view-mode . centaur-tabs-local-mode)
(dashboard-mode . centaur-tabs-local-mode)
(calendar-mode . centaur-tabs-local-mode)
:init
:config
(setq
centaur-tabs-set-icons t
centaur-tabs-set-modified-marker t
centaur-tabs-modified-marker "M"
centaur-tabs-cycle-scope 'tabs
centaur-tabs-set-bar 'over
centaur-tabs-enable-ido-completion nil
)
(centaur-tabs-change-fonts "Sarasa Gothic SC" 160)
(defun centaur-tabs-buffer-groups ()
(list (cond
((or (string-equal "*" (substring (buffer-name) 0 1))
(memq major-mode '(
magit-process-mode
magit-status-mode
magit-diff-mode
magit-log-mode
magit-file-mode
magit-blob-mode
magit-blame-mode)))
"Emacs")
((derived-mode-p '(prog-mode org-mode) "Editing"))
((derived-mode-p 'dired-mode) "Dired")
((memq major-mode '(helpful-mode help-mode)) "Help")
((memq major-mode '(
org-agenda-clockreport-mode
org-src-mode
org-agenda-mode
org-beamer-mode
org-indent-mode
org-bullets-mode
org-cdlatex-mode
org-agenda-log-mode
diary-mode))
"OrgMode")
(t
(centaur-tabs-get-group-name (current-buffer))))))
(centaur-tabs-mode t)
;; (centaur-tabs-headline-match)
;; (centaur-tabs-group-by-projectile-project)

)
#+end_src
** Windows
:PROPERTIES:
:CUSTOM_ID: e2e5d1ce-cb29-4bcd-8642-8c041fe8a5c5
:END:
*** Popper
:PROPERTIES:
:CUSTOM_ID: 678e275f-7e0c-4380-aa83-92f625f980c7
:END:

#+begin_src elisp

#+end_src

*** Toggle-one-window
:PROPERTIES:
:CUSTOM_ID: 4783e0a7-5258-4127-aef9-9a8e0efdf8dc
:END:
[[https://github.com/manateelazycat/toggle-one-window][Toggle-one-window]] provides only one function, ~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.
#+begin_src elisp
(use-package toggle-one-window)
#+end_src
** Modeline
:PROPERTIES:
:CUSTOM_ID: 0ab7afcf-8449-465e-99b8-bbe18870171f
:END:
*** Doom-modeline
:PROPERTIES:
:CUSTOM_ID: da367cb2-cf54-4e86-9c3e-83e07a7b89f2
:END:
[[https://github.com/seagle0128/doom-modeline][Doom-modeline]] is a very attractive and rich (yet still minimal) mode line configuration for Emacs. The default configuration is quite good but you can check out the [[https://github.com/seagle0128/doom-modeline#customize][configuration options]] for more things you can enable or disable.

#+begin_src elisp
(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)
)
#+end_src

*NOTE1*: [[Nerd-icons]] are necessary. Run [[elisp:nerd-icons-install-fonts][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 [[elisp:all-the-icons-install-fonts][M-x all-the-icons-install-fonts]] to install necessary icons.

*** COMMENT Nano-modline
:PROPERTIES:
:CUSTOM_ID: 699f2b2b-289d-4151-b870-3145646e1404
:END:
#+begin_src elisp
(use-package nano-modeline
:defer t
:config
(add-hook 'prog-mode-hook #'nano-modeline-prog-mode)
(add-hook 'text-mode-hook #'nano-modeline-text-mode)
(add-hook 'org-mode-hook #'nano-modeline-org-mode)
(add-hook 'pdf-view-mode-hook #'nano-modeline-pdf-mode)
(add-hook 'mu4e-headers-mode-hook #'nano-modeline-mu4e-headers-mode)
(add-hook 'mu4e-view-mode-hook #'nano-modeline-mu4e-message-mode)
(add-hook 'elfeed-show-mode-hook #'nano-modeline-elfeed-entry-mode)
(add-hook 'elfeed-search-mode-hook #'nano-modeline-elfeed-search-mode)
(add-hook 'term-mode-hook #'nano-modeline-term-mode)
(add-hook 'xwidget-webkit-mode-hook #'nano-modeline-xwidget-mode)
(add-hook 'messages-buffer-mode-hook #'nano-modeline-message-mode)
(add-hook 'org-capture-mode-hook #'nano-modeline-org-capture-mode)
(add-hook 'org-agenda-mode-hook #'nano-modeline-org-agenda-mode)
)
#+end_src
*** Diminish
:PROPERTIES:
:CUSTOM_ID: 5f5bbdb2-3644-40a3-8bf9-9226e6063a65
:END:
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.
#+begin_src elisp
(use-package diminish)
#+end_src

*** Awesome-tray
:PROPERTIES:
:CUSTOM_ID: 2d50c10f-6c78-40b0-8944-6dbbc0070eb0
:END:
#+begin_src elisp
(use-package awesome-tray
:defer t
:init
;(awesome-tray-mode)
:config
(setq awesome-tray-hide-mode-line nil)
)

#+end_src

* Interface
:PROPERTIES:
:CUSTOM_ID: cb12123c-aeb2-46ed-8bc4-dec0c9e5324c
:END:
Packages beneath this outline implements some functionalities by creating new buffers or windows.
Packages that serves for a specific mode is not configured here.

** Dashboard
:PROPERTIES:
:CUSTOM_ID: ada74755-5de2-4552-802e-5d3c71945b3a
:END:
*** Emacs Dashboard
:PROPERTIES:
:CUSTOM_ID: ad0fd7bc-d40c-4bc7-a556-4a128dd293ae
:END:

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.

#+begin_src elisp
(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)
)
)
#+end_src

*** COMMENT Doom Dashboard
:PROPERTIES:
:CUSTOM_ID: f0f8c236-f5ab-485c-8cd1-2647e0877b0a
:END:
#+begin_src elisp
(use-package doom-dashboard
:init
(setq doom-dashboard-banner-file "assets/EmaxBound-1400.xpm")
:config
(doom-dashboard-init-h)
(doom-dashboard-load)
)
#+end_src

** Visual Undo
:PROPERTIES:
:CUSTOM_ID: 6529ab53-c72d-451e-a9b9-acea32b79987
:END:
[[https://github.com/casouri/vundo][Vundo]] (visual undo) displays the undo history as a tree and lets you move in the tree to go back to previous buffer states.
#+begin_src elisp
(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
)
)
#+end_src

** Version Control
:PROPERTIES:
:CUSTOM_ID: 298a7b94-ac37-4f39-a15e-d68bc4fba61d
:END:
*** Magit
:PROPERTIES:
:CUSTOM_ID: fb0d621a-2819-4171-bb76-17314d4d027f
:END:
[[https://github.com/magit/magit][Magit]] is a VERY powerful git client.
#+begin_src elisp
(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
)
)
#+end_src

- tweaks to build magit
#+begin_src conf
[submodule "magit"]
no-byte-compile = lisp/magit-libgit.el
#+end_src
*** Diff-hl
:PROPERTIES:
:CUSTOM_ID: a7e7f5b2-64ce-4430-95a4-9ee10af93f9b
:END:

Diff highlight highlights the fringe of lines that have been edited.
#+begin_src elisp
(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))))
)
#+end_src

** Dired
:PROPERTIES:
:CUSTOM_ID: 206f2252-10b8-49ed-bba3-f70dc0eb3b8d
:END:
*** Dired
*** Diredfl
:PROPERTIES:
:CUSTOM_ID: af5fc17a-95de-4c3f-a1af-85b005311873
:END:
[[https://github.com/purcell/diredfl][Diredfl]] defines extra font lock rules to make dired more colorful.
#+begin_src elisp
(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)
)
#+end_src

Tweaks to build dirvish. Load dirvish and its extensions.
#+begin_src conf
[submodule "dirvish"]
load-path = .
load-path = extensions
#+end_src
*** COMMENT Dired-all-the-icons

#+begin_src elisp
(use-package all-the-icons-dired
:hook (dired-mode . all-the-icons-dired-mode)
)
#+end_src

*** Dirvish
:PROPERTIES:
:CUSTOM_ID: 4a83db9a-d850-49a5-9d00-84010319e6f6
:END:
Dirvish is a dropin replacement for dired. It looks and feels like ranger.

#+begin_src elisp
(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)
)
#+end_src

*** COMMENT Treemacs
:PROPERTIES:
:CUSTOM_ID: 5c283b5d-4f73-4cae-8745-9c85512a6002
:END:
#+begin_src elisp
(use-package treemacs
:disabled
:init
(with-eval-after-load 'winum
(define-key winum-keymap (kbd "M-0") #'treemacs-select-window))
:config
(progn
(setq treemacs-collapse-dirs
(if treemacs-python-executable 3 0)
treemacs-deferred-git-apply-delay 0.5
treemacs-directory-name-transformer #'identity
treemacs-display-in-side-window t
treemacs-eldoc-display 'simple
treemacs-file-event-delay 2000
treemacs-file-extension-regex
treemacs-last-period-regex-value
treemacs-file-follow-delay 0.2
treemacs-file-name-transformer #'identity
treemacs-follow-after-init t
treemacs-expand-after-init t
treemacs-find-workspace-method
'find-for-file-or-pick-first
treemacs-git-command-pipe ""
treemacs-goto-tag-strategy 'refetch-index
treemacs-header-scroll-indicators '(nil . "^^^^^^")
treemacs-hide-dot-git-directory t
treemacs-indentation 2
treemacs-indentation-string " "
treemacs-is-never-other-window nil
treemacs-max-git-entries 5000
treemacs-missing-project-action 'ask
treemacs-move-forward-on-expand nil
treemacs-no-png-images nil
treemacs-no-delete-other-windows t
treemacs-project-follow-cleanup nil
treemacs-persist-file
(expand-file-name ".cache/treemacs-persist"
user-emacs-directory)
treemacs-position 'left
treemacs-read-string-input 'from-child-frame
treemacs-recenter-distance 0.1
treemacs-recenter-after-file-follow nil
treemacs-recenter-after-tag-follow nil
treemacs-recenter-after-project-jump 'always
treemacs-recenter-after-project-expand 'on-distance
treemacs-litter-directories
'("/node_modules" "/.venv" "/.cask")
treemacs-project-follow-into-home nil
treemacs-show-cursor nil
treemacs-show-hidden-files t
treemacs-silent-filewatch nil
treemacs-silent-refresh nil
treemacs-sorting 'alphabetic-asc
treemacs-select-when-already-in-treemacs 'move-back
treemacs-space-between-root-nodes t
treemacs-tag-follow-cleanup t
treemacs-tag-follow-delay 1.5
treemacs-text-scale nil
treemacs-user-mode-line-format nil
treemacs-user-header-line-format nil
treemacs-wide-toggle-width 70
treemacs-width 35
treemacs-width-increment 1
treemacs-width-is-initially-locked t
treemacs-workspace-switch-cleanup nil)

;; The default width and height of the icons is 22 pixels. If you are
;; using a Hi-DPI display, uncomment this to double the icon size.
;;(treemacs-resize-icons 44)

(treemacs-follow-mode t)
(treemacs-filewatch-mode t)
(treemacs-fringe-indicator-mode 'always)
(when treemacs-python-executable
(treemacs-git-commit-diff-mode t))

(pcase (cons (not (null (executable-find "git")))
(not (null treemacs-python-executable)))
(`(t . t)
(treemacs-git-mode 'deferred))
(`(t . _)
(treemacs-git-mode 'simple)))

(treemacs-hide-gitignored-files-mode nil))
:bind
(:map global-map
("M-0" . treemacs-select-window)
("C-x t 1" . treemacs-delete-other-windows)
("C-x t t" . treemacs)
("C-x t d" . treemacs-select-directory)
("C-x t B" . treemacs-bookmark)
("C-x t C-t" . treemacs-find-file)
("C-x t M-t" . treemacs-find-tag)))

(use-package treemacs-evil
:after (treemacs evil)
)

(use-package treemacs-projectile
:after (treemacs projectile)
)

(use-package treemacs-icons-dired
:hook (dired-mode . treemacs-icons-dired-enable-once)
)

(use-package treemacs-magit
:after (treemacs magit)
)

(use-package treemacs-persp ;;treemacs-perspective if you use perspective.el vs. persp-mode
:after (treemacs persp-mode) ;;or perspective vs. persp-mode
:config (treemacs-set-scope-type 'Perspectives))

(use-package treemacs-tab-bar ;;treemacs-tab-bar if you use tab-bar-mode
:after (treemacs)
:config (treemacs-set-scope-type 'Tabs))
#+end_src

All the el files in treemacs are in =src/elisp= and =src/extra=
#+begin_src conf
[submodule "treemacs"]
load-path = src/elisp
load-path = src/extra
#+end_src
** Embark
:PROPERTIES:
:CUSTOM_ID: 6e9e24f1-5d7c-4e11-a8a0-fe7a3307a8d4
:END:
#+begin_src elisp
(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)))))
#+end_src

#+begin_src elisp
(use-package embark-consult
:hook
(embark-collect-mode . consult-preview-at-point-mode))
#+end_src
** Blink search
:PROPERTIES:
:CUSTOM_ID: 97f63833-c362-4a67-886b-2268ff8216d1
:END:

[[https://github.com/manateelazycat/blink-search][Blink-search]] is the fastest multi-source search framework for Emacs.

#+begin_src elisp
(use-package blink-search
:defer t
:config
(setq blink-search-enable-posframe t)
)
#+end_src

** Color-rg
:PROPERTIES:
:CUSTOM_ID: ed606051-7138-40c1-ad70-c851115c9fa7
:END:

[[https://github.com/manateelazycat/color-rg][Color-rg]] is a search and refactoring tool based on ripgrep.
#+begin_src elisp
(use-package color-rg
:config
(general-def isearch-mode-map
"M-s M-s" 'isearch-toggle-color-rg
)
)
#+end_src
** Voyager
:PROPERTIES:
:CUSTOM_ID: 9f6cd50b-6766-4f7e-ba85-393b35c8502a
:END:

[[https://github.com/manateelazycat/voyager][Voyager]] is an Emacs debugging plugin based on the DAP protocol.
#+begin_src elisp
(use-package voyager)
#+end_src

** Holo-layer
:PROPERTIES:
:CUSTOM_ID: d2ccade1-d85f-4dff-a67f-e508b1fa6f46
:END:
[[https://github.com/manateelazycat/holo-layer][Holo-layer]] is developed based on PyQt, aiming to significantly enhance the visual experience of Emacs.
#+begin_src elisp
(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)
)
#+end_src

* Coding
:PROPERTIES:
:CUSTOM_ID: da3e4dda-4fd1-4f9a-8c50-b71203fe58bd
:END:
** Keybindings
#+begin_src elisp
(general-def
:keymaps '(prog-mode-map)
:wk-full-keys nil
"C-" '(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-;" '()
)
#+end_src
** Displays
:PROPERTIES:
:CUSTOM_ID: e6d01f82-1e1f-4f68-bd34-2ab7d6ab3b2e
:END:
*** Pulse
:PROPERTIES:
:CUSTOM_ID: 6777738a-7c6e-45bd-95c2-759d714ee9da
:END:

**** Beacon
:PROPERTIES:
:CUSTOM_ID: 8c20fc21-c98e-4ca2-bb4e-728d66b76ad2
:END:
Beacon makes the cursor shine when scrolling window or jumping. Somewhat buggy.
#+begin_src elisp
(use-package beacon
:defer t
:config
(beacon-mode)
)
#+end_src

**** Pulse-Cursor
:PROPERTIES:
:CUSTOM_ID: bdf3a8f0-d259-491b-99cd-16e72cc3f605
:END:
Makes the cursor to blink with fade out animation when idle. Cool.

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 [[#3aeaad54-3694-4ad4-a887-ac1d06ccc9c4][GCMH]]).
#+begin_src elisp
(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)
)
#+end_src
**** Goggles
:PROPERTIES:
:CUSTOM_ID: 1adcfc39-e4d0-4559-acaa-43355f608c4f
:END:
Goggles highlights the modified region using pulse. Currently the commands undo, yank, kill and delete are supported.

#+begin_src elisp
(use-package goggles
:hook ((prog-mode text-mode org-mode) . goggles-mode)
:config
(setq-default goggles-pulse t)) ;; set to nil to disable pulsing
#+end_src
*** Hl-line
:PROPERTIES:
:CUSTOM_ID: 6000d6d5-dec0-4bbf-8496-cfddc6fba15d
:END:

Highlights the line that the cursor locates.
#+begin_src elisp
(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)
)
#+end_src

*** Whitespace mode
:PROPERTIES:
:CUSTOM_ID: 60025927-e86d-4ea4-94f1-097e91ac871b
:END:

[[https://www.emacswiki.org/emacs/WhiteSpace][Whitespace mode]] is a built in mode of emacs that visualizes whitespaces, tab symbols, indentations and related stuffs.
#+begin_src elisp
(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")
;; )
#+end_src
*** Line Number
:PROPERTIES:
:CUSTOM_ID: 438334d9-53c1-4a75-bd5a-90ee0fd26cc9
:END:
#+begin_src elisp
(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)
)
)
#+end_src

*** Rainbow-mode
:PROPERTIES:
:CUSTOM_ID: eac5adc2-9a8d-4bba-a890-a37465f20eb9
:END:

This minor mode sets background color to strings that match color names, useful for UI and theme design.
#+begin_src elisp

#+end_src
*** COMMENT Ts-fold
:PROPERTIES:
:CUSTOM_ID: a0b69753-a991-49d7-8625-a93082f06ca6
:END:
#+begin_src elisp
(use-package ts-fold)
#+end_src
*** Simple-call-tree
#+begin_src elisp
(use-package simple-call-tree :defer t)
#+end_src
** Indent
*** Electric-Indent
:PROPERTIES:
:CUSTOM_ID: e9971fa5-52b4-4f85-93a5-28b0dab46b80
:END:
#+begin_src elisp
(use-package electric
:config
(setq-default indent-tabs-mode nil) ;; always indent with spaces
(setq electric-pair-mode t) ;; global-minor mode
)
#+end_src
*** Aggressive-Indent
:PROPERTIES:
:CUSTOM_ID: 4532c3c9-2f73-4ccc-acb4-250156b08309
:END:
[[https://github.com/Malabarba/aggressive-indent-mode][Aggressive-indent-mode]] is a minor mode that keeps your code always
indented. It reindents after every change, making it more reliable
than `electric-indent-mode'.
#+begin_src elisp
(use-package aggressive-indent
:disabled
:config
(global-aggressive-indent-mode 1)
)
#+end_src
*** Highlight-Indent-Guides
:PROPERTIES:
:CUSTOM_ID: 1e3c6c09-61e5-42fa-87d2-5f0d0496d8f0
:END:
[[https://github.com/DarthFennec/highlight-indent-guides][Highlight-Indent-Guides]] is a minor mode that highlights indentation levels via font-lock.
#+begin_src elisp
(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")

)
#+end_src
*** COMMENT Indent-bars
#+begin_src elisp
(use-package indent-bars
:custom
(indent-bars-no-descend-string t)
;; (indent-bars-color-by-depth '(:palette ("LightSteelBlue4")))
(indent-bars-pattern ".")
(indent-bars-width-frac 0.1)
:hook ((progn-mode) . indent-bars-mode)
)
#+end_src
*** Dtrt-indent
[[https://github.com/jscheid/dtrt-indent][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.
#+begin_src elisp
(use-package dtrt-indent
:config
(dtrt-indent-global-mode)
)
#+end_src
** Parens
*** Smartparens
:PROPERTIES:
:CUSTOM_ID: c5380826-f396-48b3-8983-40cd1317425c
:END:
[[https://github.com/Fuco1/smartparens][Smartparens]] is minor mode for Emacs that deals with parens pairs and tries to be smart about it. It insert pair of parens.
#+begin_src elisp
(use-package smartparens
:config
(smartparens-global-mode)
)
#+end_src
*** Highlight-parentheses
:PROPERTIES:
:CUSTOM_ID: 9deea56d-45cc-4bcc-8ada-c1cd311412cc
:END:
#+begin_src elisp
(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)
)
#+end_src
*** Rainbow-Delimiters
:PROPERTIES:
:CUSTOM_ID: bf6c1d8c-ac59-4334-a837-1f1fe7a87375
:END:
[[https://github.com/Fanael/rainbow-delimiters][Rainbow-delimiters]] is a "rainbow parentheses"-like mode which highlights
parentheses, brackets, and braces according to their depth.
#+begin_src elisp
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode)
)
#+end_src
** Snippets
*** COMMENT YASnippet
:PROPERTIES:
:CUSTOM_ID: 628a09cf-6583-401d-97cf-654928938cde
:END:
[[https://github.com/joaotavora/yasnippet][YASnippet]] is a template system for Emacs. It allows you to type an abbreviation and automatically expand it into function templates.
#+begin_src elisp
(use-package yasnippet
:init
(yas-global-mode 1)
)
#+end_src

*** COMMENT AAS
:PROPERTIES:
:CUSTOM_ID: aeb49330-f1b3-428a-b6a3-3bbea03913f9
:END:
[[https://github.com/ymarco/auto-activating-snippets][AAS (Auto Activating Snippets)]] implements an engine for auto-expanding snippets. It is done by tracking your inputted chars along a tree until you complete a registered key sequence.
#+begin_src elisp
(use-package aas
:hook (LaTeX-mode . aas-activate-for-major-mode)
:hook (org-mode . aas-activate-for-major-mode)
:config
(aas-set-snippets 'text-mode
;; expand unconditionally
";o-" "ō"
";i-" "ī"
";a-" "ā"
";u-" "ū"
";e-" "ē")
(aas-set-snippets 'latex-mode
;; set condition!
:cond #'texmathp ; expand only while in math
"supp" "\\supp"
"On" "O(n)"
"O1" "O(1)"
"Olog" "O(\\log n)"
"Olon" "O(n \\log n)"
;; Use YAS/Tempel snippets with ease!
"amin" '(yas "\\argmin_{$1}") ; YASnippet snippet shorthand form
"amax" '(tempel "\\argmax_{" p "}") ; Tempel snippet shorthand form
;; bind to functions!
";ig" #'insert-register
";call-sin"
(lambda (angle) ; Get as fancy as you like
(interactive "sAngle: ")
(insert (format "%s" (sin (string-to-number angle))))))
;; disable snippets by redefining them with a nil expansion
(aas-set-snippets 'latex-mode
"supp" nil))
#+end_src

*** Tempel
:PROPERTIES:
:CUSTOM_ID: 85c28b3b-dcb0-4dce-9fdf-0fdaee9d66d2
:END:
:BACKLINKS:
[[#20dbcac9-a7cb-4447-8b96-a490d1637b75][Mode map]]
:END:
#+begin_src elisp
(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
)
)
#+end_src

#+begin_src elisp
;; Optional: Add tempel-collection.
;; The package is young and doesn't have comprehensive coverage.
(use-package tempel-collection
:after tempel
)
#+end_src
** LSP-bridge
:PROPERTIES:
:CUSTOM_ID: ade7813c-6a0a-4c9b-a47b-7b3ee5df0fc2
:END:
[[https://github.com/manateelazycat/lsp-bridge][lsp-bridge]] builds a high-speed cache between Emacs and the LSP server.
#+begin_src elisp
(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
;)
)
#+end_src
tweaks to build lsp-bridge
#+begin_src conf
[submodule "lsp-bridge"]
load-path = .
load-path = acm
#+end_src

** Fingertip
:PROPERTIES:
:CUSTOM_ID: e58e3846-e182-414e-b006-77690c4f6e61
:END:
:BACKLINKS:
[[#e59e6985-9ec3-4bea-8bf0-552741c5029d][Treesit-auto]]
:END:

fingertip.el is a plugin that provides grammatical edit base on treesit
#+begin_src elisp
(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 )
)
#+end_src

** Treesit
:PROPERTIES:
:CUSTOM_ID: b631d5dd-1e0a-4499-b2b1-7275666b5f1f
:END:
*** COMMENT Treesit-auto
:PROPERTIES:
:CUSTOM_ID: e59e6985-9ec3-4bea-8bf0-552741c5029d
:END:
[[https://github.com/renzmann/treesit-auto][Treesit-auto]] automatically installs and uses tree-sitter major modes in Emacs 29+. If the tree-sitter version can't be used, fall back to the original major mode.

When configuring treesit the following things are worth considering:
+ [[#b8ff6dfc-3a9c-46e4-be9e-b95c496d4697][Org src block]] which by default do not use ts-mode
+ [[#e58e3846-e182-414e-b006-77690c4f6e61][Fingertip]] which relies on treesit to work
#+begin_src elisp
(use-package treesit-auto
:config

(defun my/remap-mode (mode)
"make org-src-get-lang-mode respect major-mode-remap-alist"
(treesit-auto--set-major-remap)
(alist-get mode major-mode-remap-alist mode)
)
(advice-add 'org-src-get-lang-mode :filter-return #'my/remap-mode)

;; a workaround for lack of lang-ts-mode
(add-hook 'emacs-lisp-mode-hook #'(lambda () (treesit-parser-create 'elisp)))
(add-hook 'markdown-mode-hook #'(lambda () (treesit-parser-create 'markdown)))
(global-treesit-auto-mode))
#+end_src
*** Treesitter-context
[[https://github.com/zbelial/treesitter-context.el][Treesitter-context]] utilize emacs built-in treesit to show code context.
#+begin_src elisp
(use-package treesitter-context
:config
(add-hook 'python-ts-mode-hook #'treesitter-context-mode)
)
#+end_src
*** Lazycat's method
:PROPERTIES:
:CUSTOM_ID: ad854d70-6c48-4e35-8fb6-0591ba5e5c20
:END:
You can find the addresses of language parsers at [[https://tree-sitter.github.io/tree-sitter/][treesitter's official doc]].
To enable treesit support for a language, you need to run =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=).
#+begin_src elisp
(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)))
#+end_src
** Copilot
:PROPERTIES:
:CUSTOM_ID: 34c3222e-9339-4393-9006-96177fb5ea94
:END:
https://github.com/zerolfx/copilot.el

** Auto-save
:PROPERTIES:
:CUSTOM_ID: 1c6aa069-acd3-4f3c-94dd-0890bc30efb4
:END:
Auto save saves your buffer after entering idle state.
#+begin_src elisp
(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)
)
#+end_src

** Vlf
#+begin_src elisp
(use-package vlf-setup
:config
(setq-default vlf-application 'dont-ask)
)
#+end_src
** Outli
#+begin_src elisp
(use-package outli
:hook ((prog-mode text-mode) . outli-mode))
#+end_src
** Direnv
[[https://github.com/purcell/envrc][Envrc]] provides support for direnv that is buffer-local.
#+begin_src elisp
(use-package envrc
:config
(envrc-global-mode)
)
#+end_src

* Languages
:PROPERTIES:
:CUSTOM_ID: 0d2cb490-c0f4-4e42-acfe-55e0ee789fb7
:END:
** Elisp
:PROPERTIES:
:CUSTOM_ID: f998e88f-3234-4f94-a86f-683caaab3483
:END:
- buttercup
- elisp-def
- elisp-demos
- highlight-quoted
- macrostep
- oversee
#+begin_src elisp
(setq-default lexical-binding t)
#+end_src

#+begin_src elisp
(use-package highlight-quoted)
#+end_src
** Lisp
#+begin_src elisp
(use-package lisp-mode
:mode "\\.yuck\\'"
)
#+end_src
** LaTeX
:PROPERTIES:
:CUSTOM_ID: 76c817ec-2dac-425e-b8a3-a04d6946892f
:END:
*** AUCTeX
:PROPERTIES:
:CUSTOM_ID: 9543c01b-f1dc-4d85-9056-ce73e2019dbb
:END:
#+begin_src elisp
(use-package auctex)
#+end_src

AucTex needs some tweaks to be built.
To build auctex, =autoconf= should be avaliable on your system.
#+begin_src conf :tangle .borgconfig
[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
#+end_src
*** CDTeX
:PROPERTIES:
:CUSTOM_ID: e4c612e7-07a4-47b7-95dd-01a881a715cc
:END:
#+begin_src elisp
(use-package cdlatex)
#+end_src
*** LAAS
:PROPERTIES:
:CUSTOM_ID: 94ce08e7-d4dd-4804-985d-b154934f9442
:END:

[[https://github.com/tecosaur/LaTeX-auto-activating-snippets][LASS (LaTeX Auto Activating Snippets)]] is a chunky set of LaTeX snippets for the auto-activating-snippets engine.

#+begin_src elisp
(use-package laas
:after ass
:hook (LaTeX-mode . laas-mode))
#+end_src
** Markdown
#+begin_src elisp
(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)))))
)
#+end_src
** Nix
:PROPERTIES:
:CUSTOM_ID: 58e308df-8796-4406-b89b-136adc972ddb
:END:
#+begin_src elisp
(use-package nix-mode
:mode "\\.nix\\'"
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((nix . t))
)
)
#+end_src

#+begin_src elisp
(use-package nix-ts-mode
:mode "\\.nix\\'"
)
#+end_src
** PlantUML
:PROPERTIES:
:CUSTOM_ID: 060fbe09-da11-47fa-83c1-1492fc4a5295
:END:
#+begin_src elisp
(use-package plantuml-mode
:mode "\\.plantuml\\'"
)
#+end_src
** Python
:PROPERTIES:
:CUSTOM_ID: c0695b7a-e139-4c5c-bcd5-d5be5d3fae89
:END:
*** Jupyter
:PROPERTIES:
:CUSTOM_ID: d67b0864-7efe-4341-baad-cf2a9f2c6345
:END:
#+begin_src elisp
(use-package jupyter
;; :defer t
:config
(org-babel-do-load-languages
'org-babel-load-languages
(append org-babel-load-languages
'((jupyter . t)))))
#+end_src
** Rust

#+begin_src elisp
(use-package rust-ts-mode
:mode "\\.rs\\'"
)
#+end_src

Rusty object notation mode
#+begin_src elisp
(use-package ron-mode
:mode "\\.ron\\'"
)
#+end_src
** Verilog
:PROPERTIES:
:CUSTOM_ID: 0f43d38a-0d54-441d-ac37-c2c8b4abc1a9
:END:
#+begin_src elisp
(use-package verilog-mode
:mode "\\.v\\'"
)
#+end_src
** YAML
:PROPERTIES:
:CUSTOM_ID: f38fbcdd-6212-442d-9b43-64bf9823ac6f
:END:
#+begin_src elisp
(use-package yaml-mode
:mode "\\.yaml\\'"
)
#+end_src
* Org
:PROPERTIES:
:CUSTOM_ID: 9b0a5dda-16ef-4e5d-a408-26a4d0ce3e75
:END:
Org mode is a reason to use emacs.
** Init
:PROPERTIES:
:CUSTOM_ID: 99ce76ad-c694-486e-8e3e-3fd72508b0f8
:END:
[[https://git.tecosaur.net/tec/org-mode][Org-9.7]] did some overhaul to org-latex-preview in org mode. Load External org before the built in org is loaded.
#+begin_src elisp
(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)
)
#+end_src

All the .el files are placed in the ./lisp/ folder.
According to the installation manual of org, we need to make autoloads before compile.
#+begin_src conf
[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
#+end_src

** UI
:PROPERTIES:
:CUSTOM_ID: 0ee8b7f7-a645-4d98-932f-9810297d0d3f
:END:
*** Fonts
:PROPERTIES:
:CUSTOM_ID: 2f66cc35-6cbf-4f92-8868-d9bb88856421
:END:

Change the font size of different org-levels.
#+begin_src elisp
(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)
)
#+end_src

*** Org-modern
:PROPERTIES:
:CUSTOM_ID: 02508b8f-6b97-44ed-975a-1ff170f3b1fc
:END:

[[https://github.com/minad/org-modern][Org-modern]] implements a modern style for Org buffers using font locking and text properties. The package styles =headlines=, =keywords=, =tables= and =source blocks=.

#+begin_src elisp
(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)
)
#+end_src

[[https://github.com/integral-dw/org-superstar-mode][Org-superstar]] replaces the asterisk before every org-level with ascii symbols.
Disabled because org-morden is a drop-in replacement.

#+begin_src elisp
(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 " "
)
)
#+end_src
*** Svg-tag-mode
global svg tag mode will not work will dashboard image banner.
#+begin_src elisp
(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)))))))
)
#+end_src
*** COMMENT Org-modern-indent
#+begin_src elisp
(use-package org-modern-indent
:init
;; override defconst
(defconst org-modern-indent-begin (propertize " " 'face 'org-modern-bracket-line))
(defconst org-modern-indent-guide (propertize " " 'face 'org-modern-bracket-line))
(defconst org-modern-indent-end (propertize " " 'face 'org-modern-bracket-line))
)
#+end_src
*** Org-visual-outline
:PROPERTIES:
:CUSTOM_ID: 49dc8626-3dcf-462b-a153-d0c2ace43dd2
:END:
[[https://github.com/legalnonsense/org-visual-outline][Org-visual-outline]] does the same as Org-bars-mode. It has two independent packages:
- 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.

#+begin_src elisp
(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
)
#+end_src

*** valign
:PROPERTIES:
:CUSTOM_ID: aeeeeb33-5896-41d2-9142-f6d06d79b5a2
:END:

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.
#+begin_src elisp
(use-package valign
:hook (org-mode . valign-mode)
:config
(setq valign-fancy-bar t)
)
#+end_src

*** Highlight TODO
:PROPERTIES:
:CUSTOM_ID: 9b02ee39-8831-40a1-b8fd-48f446b00b9c
:END:

#+begin_src elisp
(use-package hl-todo
:init
(hl-todo-mode)
)
#+end_src

*** Org-appear
:PROPERTIES:
:CUSTOM_ID: c7c438bf-de33-4c06-9a78-a9e2c05f6e43
:END:
[[https://github.com/awth13/org-appearAutomatically][Org-appear]] disaply emphasis markers and links when the cursor is on them.
#+begin_src elisp
(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
)

)
#+end_src
*** Org-popup-posframe
#+begin_src elisp
(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)
)
#+end_src

** Keybindings
:PROPERTIES:
:CUSTOM_ID: 4e4b8f79-8616-4cc0-bcc8-2b1a2ca03de2
:END:
:BACKLINKS:
[[#20dbcac9-a7cb-4447-8b96-a490d1637b75][Local Keybindings]]
:END:
#+begin_src elisp
(setq org-return-follows-link t)
#+end_src
#+begin_src elisp
(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 ")
)
#+end_src

#+begin_src elisp
(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")
)
#+end_src

#+begin_src elisp
(my/mode-leader-def
:keymaps '(org-src-mode-map)
"e" 'org-edit-src-exit
"k" 'org-edit-src-abort
)
#+end_src
#+begin_src elisp
(my/mode-leader-def
:keymaps '(org-capture-mode-map)
"c" 'org-capture-finalize
"w" 'org-capture-refile
"k" 'org-capture-kill
)
#+end_src

*** outline functions
:PROPERTIES:
:CUSTOM_ID: 9129a8b6-26af-4a5f-b54e-927c84888031
:END:
#+begin_src elisp

(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))
#+end_src

** Objects
:PROPERTIES:
:CUSTOM_ID: 538ca1a1-0f04-418d-932e-a69a165c2923
:END:
*** Src block
:PROPERTIES:
:CUSTOM_ID: b8ff6dfc-3a9c-46e4-be9e-b95c496d4697
:END:
:BACKLINKS:
[[#e59e6985-9ec3-4bea-8bf0-552741c5029d][Treesit-auto]]
:END:
#+begin_src elisp
(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)
)
#+end_src

[[https://github.com/yilkalargaw/org-auto-tangle][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=.
#+begin_src elisp
(use-package org-auto-tangle
:hook (org-mode . org-auto-tangle-mode)
)
#+end_src

[[https://github.com/astahlman/ob-async][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~.
#+begin_src elisp
(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"))
)
#+end_src
*** Table
:PROPERTIES:
:CUSTOM_ID: 8c93381a-2a6e-43e5-af2b-6dafcdcf0c23
:END:
[[https://github.com/casouri/valign][Valign]] 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.

[[https://github.com/tbanel/orgaggregate][Orgtbl-aggregate]] can creat a new table by computing sums, averages, and so on, out of material from the first table.
*** LaTeX
:PROPERTIES:
:CUSTOM_ID: 7859c5cb-3f1c-4a2b-a569-6786c82b3eb8
:END:
Disable hiding of ~{}~, ~_~ and ~^~, from [[https://emacs-china.org/t/org/26045][this post in emacs china]].
#+begin_src elisp
(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)
)
#+end_src

Prettify symbols mode
#+begin_src elisp
(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)
))
)
#+end_src

Org-entities-user
#+begin_src elisp
(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 "⊉" "⊉" "⊉" "⊉")
))
)

#+end_src

Org Latex Preview configs. This makes the preview looks nicer.
#+begin_src elisp
(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)
)
)
#+end_src
** Images
:PROPERTIES:
:CUSTOM_ID: 906466ea-995a-4934-af23-1ce6538a44bd
:END:
*** Org-download
:PROPERTIES:
:CUSTOM_ID: b138609f-c760-4068-8e5b-b794d75f45dd
:END:
#+begin_src elisp
(use-package org-download
:after org
)
#+end_src
*** PlantUML
:PROPERTIES:
:CUSTOM_ID: 0bc4e2a7-406a-478e-9ffa-baa7639968f9
:END:

#+begin_src elisp
(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")
))
)
#+end_src
** Org-capture
:PROPERTIES:
:CUSTOM_ID: 836fc7e8-d50b-4e42-b4f3-f77de9c5da44
:END:
Check [[https://orgmode.org/manual/Capture-templates.html][capture-templates]] for more info.
#+begin_src elisp
(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")
)
#+end_src
** Links
:PROPERTIES:
:CUSTOM_ID: 739bfe4d-8702-40f3-9a45-54a25cb4460e
:END:
What is a backlink? If there's a link at A pointing to B, and in the same time if there's also a link at B pointing to A, then the link at B can be called the backlink of the link at A.

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.

*** Custom-ID
:PROPERTIES:
:CUSTOM_ID: 4bc8824b-c721-4ad5-a3c3-995d3539929e
:END:
#+begin_src elisp
(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)
)
)
#+end_src
*** Org-super-links
:PROPERTIES:
:CUSTOM_ID: 2a97fa47-7911-46f4-9666-9f75832baec3
:END:
Org super links handles backlink inside the current file. When inserting link to a target using ~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.

#+begin_src elisp
(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)
)
#+end_src

*** Org-roam
:PROPERTIES:
:CUSTOM_ID: 7838a97c-8f2d-4cff-aade-54943c58d820
:END:
#+begin_src elisp
(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)))
)
#+end_src

** Scheduling
:PROPERTIES:
:CUSTOM_ID: 8d5ceac8-06cf-4cda-a653-c9a6fcb29cb6
:END:
*** TODOs
:PROPERTIES:
:CUSTOM_ID: b1789eb6-0fc0-4c1b-aa1c-c88d219383ec
:END:
#+begin_src elisp
(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
)
#+end_src
*** Org-agenda
:PROPERTIES:
:CUSTOM_ID: 15adfec6-d92c-44db-b3cd-717f54af5a84
:END:
#+begin_src elisp :tangle no
(use-package org-agenda
:after org
:hook
(org-agenda-mode . solaire-mode)
(org-agenda-mode . olivetti-mode)
:bind
("" . 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"))

)
#+end_src
*** Org-super-agenda
:PROPERTIES:
:CUSTOM_ID: 4e9b6e7a-a7fd-4f03-8450-47ce16ff8316
:END:
#+begin_src elisp
(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")
))
)
#+end_src
*** Calendar
:PROPERTIES:
:CUSTOM_ID: 78815b7d-8cfa-4c16-a31b-a66c93ed753f
:END:

#+begin_src elisp
(use-package calendar
:hook
(calendar-mode . olivetti-mode)
(calendar-mode . solaire-mode)
:config
(setq calendar-date-style 'iso)
)
#+end_src

*** Archive repeated task
Copied from https://lists.gnu.org/archive/html/emacs-orgmode/2020-11/msg00361.html
#+begin_src elisp
(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)
)
#+end_src
*** COMMENT GTD
:PROPERTIES:
:CUSTOM_ID: a5273f17-b61f-40de-afde-898a739c0673
:END:
#+begin_src elisp
(use-package org-gtd
:after org
:init
(setq org-gtd-update-ack "3.0.0")
:config
;; where org-gtd will put its files.
(setq org-gtd-directory "~/gtd/")
;; package: https://github.com/Malabarba/org-agenda-property
;; this is so you can see who an item was delegated to in the agenda
(setq org-agenda-property-list '("DELEGATED_TO"))
;; I think this makes the agenda easier to read
(setq org-agenda-property-position 'next-line)
;; package: https://www.nongnu.org/org-edna-el/
;; org-edna is used to make sure that when a project task gets DONE,
;; the next TODO is automatically changed to NEXT.
(setq org-edna-use-inheritance t)
(org-edna-load)
:bind
(("C-c d c" . org-gtd-capture) ;; add item to inbox
("C-c d a" . org-agenda-list) ;; see what's on your plate today
("C-c d p" . org-gtd-process-inbox) ;; process entire inbox
("C-c d n" . org-gtd-show-all-next) ;; see all NEXT items
;; see projects that don't have a NEXT item
("C-c d s" . org-gtd-show-stuck-projects)
;; the keybinding to hit when you're done editing an item in the
;; processing phase
("C-c d f" . org-gtd-clarify-finalize)))
#+end_src

** Export
:PROPERTIES:
:CUSTOM_ID: 124ad25a-1f0e-4fa8-ab58-b8a1abf0c69f
:END:
*** Ox
:PROPERTIES:
:CUSTOM_ID: bded0258-b949-405e-a9b8-cdf3a0962244
:END:
#+begin_src elisp
(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
)
)
#+end_src
*** HTML
:PROPERTIES:
:CUSTOM_ID: b16239e6-c6bf-432d-b567-bbe54372cc6b
:END:

#+begin_src elisp
(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))
#+end_src

#+begin_src elisp
(use-package htmlize
:defer t
:config
(setq htmlize-pre-style t
htmlize-output-type 'inline-css))
#+end_src
**** grip-mode
:PROPERTIES:
:CUSTOM_ID: 13feb49e-8ea5-4a09-8179-9ccc0b8f4bb4
:END:
#+begin_src elisp
(use-package grip-mode
:after org
)
#+end_src

*** PDF
:PROPERTIES:
:CUSTOM_ID: 420b1286-023a-4491-bf0f-e617f2239e5b
:END:
There're 3 common ways to export org into PDF.
- ox-html, then export to pdf via browser.
- ox-latex
- ox-pandoc
*** LaTeX
:PROPERTIES:
:CUSTOM_ID: 1762c60b-bc06-4d1f-8bcc-9394e0191f99
:END:
#+begin_src elisp
(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}")))
)
#+end_src
*** Ipynb
:PROPERTIES:
:CUSTOM_ID: ba439797-96a3-4563-8de2-3a3b02e6493b
:END:
#+begin_src elisp
(use-package ox-ipynb
:defer t
:after ox
)
#+end_src
*** Slides
:PROPERTIES:
:CUSTOM_ID: d86cd158-7813-42b3-8566-6240e6dc50f9
:END:
Use [[revealjs.com][reveal.js]] to generate beautiful presentations.
This requires reveal.js installed on your machine.

#+begin_src bash
git clone https://github.com/hakimel/reveal.js.git
cd reveal.js && npm install
#+end_src

#+begin_src elisp
(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 "

%t

%s

%a
%d

"
org-reveal-plugins '(markdown zoom notes search)
org-reveal-klipsify-src 'on))
#+end_src
*** Markdown
:PROPERTIES:
:CUSTOM_ID: 427d0384-085c-4157-9faa-6864b1755348
:END:
Use [[https://github.com/larstvei/ox-gfm][ox-gfm]] to generate github-style markdown file.
#+begin_src elisp
(use-package ox-gfm
:defer t
:after ox
)
#+end_src
*** MS-Office
:PROPERTIES:
:CUSTOM_ID: 72b1ab0a-fc11-46c7-a53e-a79c576170f3
:END:
Use ox-pandoc to generate MS-Office files like word and ppt.
#+begin_src elisp
(use-package ox-pandoc
:defer t
:after ox
:config
(setq org-pandoc-format-extensions
'(markdown_github+pipe_tables+raw_html)
)
)
#+end_src

*** Static HTML
:PROPERTIES:
:CUSTOM_ID: 176c8d06-3d2f-4a27-8861-44967b922b3c
:END:
#+begin_src elisp
(use-package ox-publish
:defer t
)
#+end_src
*** Hugo
:PROPERTIES:
:CUSTOM_ID: a878bf6d-de0c-4c74-b03a-f224f43a0045
:END:
General steps to publish a blog using hugo in emacs includes:
- 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

[[https://github.com/kaushalmodi/ox-hugo][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).
#+begin_src elisp
(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"
)
)
#+end_src

Easy-hugo

#+begin_src elisp
(use-package easy-hugo
:defer t
)
#+end_src

** Org-transclusion
:PROPERTIES:
:CUSTOM_ID: 5d96a326-52cd-4d0f-975c-a5f6b8163752
:END:
* Emacs OS
:PROPERTIES:
:CUSTOM_ID: 87a84d95-742b-4f3b-a9a8-917dfe2d8e3a
:END:
** Telega
:PROPERTIES:
:CUSTOM_ID: 763733ef-e1a9-4b5e-a30f-f5bb468b11ba
:END:
Telegram inside emacs!
#+begin_src elisp
(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
)

)
#+end_src

#+begin_src conf
[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
#+end_src
** Elfeed
:PROPERTIES:
:CUSTOM_ID: eac8de6e-d1e9-45d9-a516-67b98f113c4b
:END:
Elfeed is emacs's built-in rss reader.

The following config adds nerd icons, copied from [[https://emacs-china.org/t/elfeed-nerd-icons/26125][Emacs China]].
#+begin_src elisp
(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)
)
#+end_src
*** COMMENT Elfeed-goodies
#+begin_src elisp
(use-package elfeed-goodies
:hook (after-init . elfeed-goodies/setup)
:config
;; set elfeed show entry switch function
(setq elfeed-show-entry-switch #'elfeed-goodies/switch-pane) ; switch-to-buffer, pop-to-buffer
)
#+end_src
*** Elfeed-org
#+begin_src elisp
(use-package elfeed-org
:after elfeed
:init
(setq rmh-elfeed-org-files (list "~/.emacs.d/elfeed.org"))
(elfeed-org)
)
#+end_src
*** COMMENT Elfeed-autotag
#+begin_src elisp
(use-package elfeed-autotag
:after elfeed
:config
(setq elfeed-autotag-files '("~/.emacs.d/elfeed.org"))
(elfeed-autotag)
)
#+end_src
** TODO Calc
#+begin_src elisp
#+end_src
** PDF-Tools
:PROPERTIES:
:CUSTOM_ID: 510896cb-a9d1-4ee9-8ed3-d22c19229103
:END:
PDF-tools is a replacement for DocView for PDF files.
The rendering is performed by poppler.
Run =M-x pdf-tools-install= to install libraries needed.

~pdf-view-midnight-colors~ are set by doom-themes
#+begin_src elisp
(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)
)

#+end_src
** Nov
nov.el provides a major mode for reading EPUB documents.
#+begin_src elisp
(use-package nov
:defer t)
#+end_src
** Mu4e
:PROPERTIES:
:CUSTOM_ID: ddda3958-7467-41d3-91b4-516eef5fbd18
:END:
#+begin_src conf
[submodule "mu4e"]
build-step = ./autogen.sh
build-step = make -C mu4e > /dev/null
build-step = borg-update-autoloads
load-path = build/mu4e
#+end_src
** Eaf
:PROPERTIES:
:CUSTOM_ID: fd9de43f-6849-4c0f-9227-a121a7f1af98
:END:

[[https://github.com/emacs-eaf/emacs-application-framework][EAF]] is an extensible framework that revolutionizes the graphical capabilities of Emacs.
#+begin_src elisp
(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)
#+end_src
tweaks to build eaf
#+begin_src conf
[submodule "eaf"]
load-path = .
load-path = core
load-path = extension
#+end_src
** Games
:PROPERTIES:
:CUSTOM_ID: 298954d6-4ae6-475b-9ef6-64237ad99030
:END:
*** Tetris
:PROPERTIES:
:CUSTOM_ID: 5964883d-f883-4ec2-b064-87501622ab3a
:END:
#+begin_src elisp
(add-hook 'tetris-mode-hook (lambda () (config/window-center 76)))
#+end_src

*** 2048
:PROPERTIES:
:CUSTOM_ID: 781bdb48-691a-4d65-a575-ab1f236620c7
:END:
#+begin_src elisp
(add-hook '2048-mode-hook (lambda () (config/window-center 35)))
#+end_src

** Emacs-Everywhere
:PROPERTIES:
:CUSTOM_ID: e207c4f5-5a78-4db7-afa0-3f2761f0536d
:END:
Takes emacs-everywhere with you, all over your system
#+begin_src elisp

#+end_src
* End
:PROPERTIES:
:CUSTOM_ID: c3fad58e-8bd1-4896-973b-615c5fb3107c
:END:
#+begin_src elisp
(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
#+end_src

*
* COMMENT Tests
:PROPERTIES:
:CUSTOM_ID: 89a426af-df86-4d55-aac2-160919674c22
:END:
This subtree is used to execute some elisps to test.
#+begin_src elisp :results value

#+end_src
* TODO COMMENT
** Org-denote
** Completion
*** flx-rs + fussy
*** hotfuzz
** Align variable pitch
*** Transient maps
*** Dired
** Elfeed add filter group
** Dired guess shell alist user
** Svg libs/tabs
** copy from nano emacs
** Try setup.el
** Memacs
https://github.com/novoid/Memacs